Switch from KCL to CUE
Although KCL is unquestionably a more powerful language, and maps more closely to my mental model of how host/environment/application configuration is defined, the fact that it doesn't work on ARM (issue 982]) makes it a non-starter. It's also quite slow (owing to how it compiles a program to evaluate the code) and cumbersome to distribute. Fortunately, `tmpl` doesn't care how the values it uses were computed, so we freely change configuration languages, so long as whatever we use generates JSON/YAML. CUE is probably a lot more popular than KCL, and is quite a bit simpler. It's more restrictive (values cannot be overridden once defined), but still expressive enough for what I am trying to do (so far).master
parent
8f31b0302c
commit
11f9957c11
|
@ -6,6 +6,11 @@ end_of_line = lf
|
|||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[**.cue]
|
||||
max_line_length = 79
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
[**.k]
|
||||
max_line_length = 79
|
||||
indent_style = space
|
||||
|
@ -15,3 +20,7 @@ indent_size = 4
|
|||
max_line_length = 79
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[Containerfile]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
FROM registry.fedoraproject.org/fedora-minimal:39 AS build
|
||||
|
||||
ARG CUE_VERSION=0.7.0
|
||||
|
||||
RUN --mount=type=cache,target=/var/cache \
|
||||
microdnf install -y \
|
||||
--setopt install_weak_deps=0 \
|
||||
|
@ -10,16 +12,12 @@ RUN --mount=type=cache,target=/var/cache \
|
|||
x86_64) ARCH=amd64 ;; \
|
||||
aarch64) ARCH=arm64 ;; \
|
||||
esac \
|
||||
&& url="https://github.com/kcl-lang/lib/raw/v0.7.5/lib/linux-${ARCH}/" \
|
||||
&& curl -fsSL "${url}/kclvm_cli" -o /usr/local/bin/kclvm_cli \
|
||||
&& curl -fsSL "${url}/libkclvm_cli_cdylib.so" \
|
||||
-o /usr/local/bin/libkclvm_cli_cdylib.so \
|
||||
&& chmod +x /usr/local/bin/kclvm_cli \
|
||||
&& url="https://github.com/kcl-lang/cli/releases/download/v0.7.2/kcl-v0.7.2-linux-${ARCH}.tar.gz" \
|
||||
&& url="https://github.com/cue-lang/cue/releases/download/v${CUE_VERSION}/cue_v${CUE_VERSION}_linux_${ARCH}.tar.gz" \
|
||||
&& curl -fsSL "${url}" \
|
||||
| tar -C /usr/local/bin -xz kcl \
|
||||
| tar -C /usr/local/bin -xz cue \
|
||||
&& :
|
||||
|
||||
|
||||
FROM git.pyrocufflink.net/containerimages/tmpl
|
||||
|
||||
RUN --mount=type=cache,target=/var/cache \
|
||||
|
@ -27,11 +25,10 @@ RUN --mount=type=cache,target=/var/cache \
|
|||
microdnf install -y \
|
||||
--setopt install_weak_deps=0 \
|
||||
age \
|
||||
gcc \
|
||||
git \
|
||||
git-core \
|
||||
&& ln -snf /host/etc/passwd /etc/passwd \
|
||||
&& ln -snf /host/etc/group /etc/group \
|
||||
&& cp -a /build/usr/local/bin/. /usr/local/bin \
|
||||
&& cp -a /build/usr/local/bin/cue /usr/local/bin/ \
|
||||
&& for cmd in \
|
||||
systemctl \
|
||||
systemd-sysusers \
|
||||
|
@ -46,9 +43,5 @@ ENTRYPOINT []
|
|||
|
||||
CMD ["/config.sh"]
|
||||
|
||||
ENV KCL_GO_DISABLE_ARTIFACT=on
|
||||
ENV KCL_PKG_PATH=/tmp
|
||||
ENV KCL_CACHE_PATH=/tmp
|
||||
|
||||
LABEL license= \
|
||||
vendor='Dustin C. Hatch' \
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
import pkg.nut
|
||||
|
||||
nut: nut.Nut {
|
||||
users.upsmon = {
|
||||
upsmon = "primary"
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
: "${DESTDIR=/host}"
|
||||
env="$1"
|
||||
|
||||
kcl nut/base nut/"${env}" -o nut.yaml
|
||||
mkdir -p "${DESTDIR}"/etc/ups
|
||||
tera --template nut/templates/ups.conf nut.yaml \
|
||||
> "${DESTDIR}"/etc/ups/ups.conf
|
||||
tera --template nut/templates/upsd.users nut.yaml \
|
||||
> "${DESTDIR}"/etc/ups/upsd.users
|
|
@ -1,24 +0,0 @@
|
|||
import pkg.nut
|
||||
|
||||
nut: nut.Nut {
|
||||
ups = {
|
||||
apc1500 = {
|
||||
driver = "usbhid-ups"
|
||||
port = "auto"
|
||||
desc = "Back-UPS XS 1500G"
|
||||
vendorid = "051d"
|
||||
product = ".*1500M.*"
|
||||
pollonly = "enabled"
|
||||
pollinterval = 1
|
||||
}
|
||||
apc1300 = {
|
||||
driver = "usbhid-ups"
|
||||
port = "auto"
|
||||
desc = "Back-UPS XS 1300G"
|
||||
vendorid = "051d"
|
||||
product = ".*1300G.*"
|
||||
pollonly = "enabled"
|
||||
pollinterval = 1
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
import pkg.nut
|
||||
|
||||
nut: nut.Nut {
|
||||
users.homeassistant.password = """\
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxZUZleGt3emxXdDFtcEtN
|
||||
Wll3K0hrS2c2M1oyMWh2VlBnMER0bkZOb1VVCnU3aTI2eVJoV1dKNWxEd0VnbVNa
|
||||
NlMxVWRuZWpNbTJRVUhWR2w3bUlwaEUKLS0tIGZLcGNQRy9LNUF1Y0JzZEZGdXBn
|
||||
bUJjYlBSSEYwRUpwemlMZ0xCZnpTS2cKUFke27YDeTME9OBgEcQdbJ3jsDZS43km
|
||||
tK61kLMcexq3lXQb30gx4fzMuYa0MXFygawscTnxTrOrXUd36Iga4A==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
"""
|
||||
|
||||
users.upsmon.password = """\
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzdnZMZ1F1d05RRi84ZENT
|
||||
SmdRNkFLWDRPMTBFTkdOdFRBMC8xK0gvUVV3CjRhWVljR3ZiU1hwWEJBN2hCcTM1
|
||||
NWFQWWdmVm1XK1pKUHFnRjJjYXdDNjgKLS0tIERvOU44ellHdGZYVXRDMHN4NkpV
|
||||
QkhtVlVQUS96UStlQWo2QWJISUlGL2cKc8AC3UujJMIafbV31pjAzniqSHBNwYDw
|
||||
zhh094auKibUcg6Tbyc=
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
"""
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
import pkg.nut
|
||||
|
||||
nut: nut.Nut {
|
||||
users.dustin.password = """\
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsdWVBOXZpb3Fxclk4SGJv
|
||||
N0JyeEthbzFOTzQySkw3cWZhSEk2Y1poWm0wCnhEVkJhWWtIdUxnVUFSa2xCSDNU
|
||||
ak1rbzhaUzN1WUxKajdvOTluVGJwaGsKLS0tIG9NL3ZrMDY5Z2prMnNWL003cDRP
|
||||
T3NySlREeXZoaVhGcUdTVmxrYXNyUDQKXFvRM9INd7E334OOYlFgp9pu1w4b3szL
|
||||
yVmqMxpy98iHA6HKvuw=
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
"""
|
||||
|
||||
users.upsmon.password = """\
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzdnZMZ1F1d05RRi84ZENT
|
||||
SmdRNkFLWDRPMTBFTkdOdFRBMC8xK0gvUVV3CjRhWVljR3ZiU1hwWEJBN2hCcTM1
|
||||
NWFQWWdmVm1XK1pKUHFnRjJjYXdDNjgKLS0tIERvOU44ellHdGZYVXRDMHN4NkpV
|
||||
QkhtVlVQUS96UStlQWo2QWJISUlGL2cKc8AC3UujJMIafbV31pjAzniqSHBNwYDw
|
||||
zhh094auKibUcg6Tbyc=
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
"""
|
||||
}
|
|
@ -24,10 +24,10 @@ curl -fsSL \
|
|||
-o keys.age
|
||||
age -d -i "${SSH_KEY}" -o keys.txt keys.age
|
||||
|
||||
if [ -f host/"${HOSTNAME}".k ] && [ -f host/"${HOSTNAME}".yaml ]; then
|
||||
kcl run host/"${HOSTNAME}".k -o instructions.yaml || exit
|
||||
kcl run -Y host/"${HOSTNAME}".yaml -o values.yaml || exit
|
||||
tmpl instructions.yaml values.yaml -d "${DESTDIR}" || exit
|
||||
if [ -f host/"${HOSTNAME}".cue ] && [ -f instructions/"${HOSTNAME}".cue ]; then
|
||||
cue export host/"${HOSTNAME}".cue -o values.json || exit
|
||||
cue export instructions/"${HOSTNAME}".cue -o instructions.json || exit
|
||||
tmpl instructions.json values.json -d "${DESTDIR}" || exit
|
||||
fi
|
||||
|
||||
if [ -f host/"${HOSTNAME}".post.sh ]; then
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
module: "du5t1n.me/cfg"
|
|
@ -0,0 +1,57 @@
|
|||
package prod
|
||||
|
||||
import n "du5t1n.me/cfg/schema/app/nut"
|
||||
|
||||
nut: n.#Nut & {
|
||||
listen: {
|
||||
address: "::"
|
||||
port: 3493
|
||||
}
|
||||
|
||||
ups: {
|
||||
apc1500: {
|
||||
driver: "usbhid-ups"
|
||||
port: "auto"
|
||||
desc: "Back-UPS XS 1500G"
|
||||
vendorid: "051d"
|
||||
product: ".*1500M.*"
|
||||
pollonly: "enabled"
|
||||
pollinterval: 1
|
||||
}
|
||||
apc1300: {
|
||||
driver: "usbhid-ups"
|
||||
port: "auto"
|
||||
desc: "Back-UPS XS 1300G"
|
||||
vendorid: "051d"
|
||||
product: ".*1300G.*"
|
||||
pollonly: "enabled"
|
||||
pollinterval: 1
|
||||
}
|
||||
}
|
||||
|
||||
users: {
|
||||
homeassistant: {
|
||||
password: """
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxZUZleGt3emxXdDFtcEtN
|
||||
Wll3K0hrS2c2M1oyMWh2VlBnMER0bkZOb1VVCnU3aTI2eVJoV1dKNWxEd0VnbVNa
|
||||
NlMxVWRuZWpNbTJRVUhWR2w3bUlwaEUKLS0tIGZLcGNQRy9LNUF1Y0JzZEZGdXBn
|
||||
bUJjYlBSSEYwRUpwemlMZ0xCZnpTS2cKUFke27YDeTME9OBgEcQdbJ3jsDZS43km
|
||||
tK61kLMcexq3lXQb30gx4fzMuYa0MXFygawscTnxTrOrXUd36Iga4A==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
"""
|
||||
}
|
||||
upsmon: {
|
||||
upsmon: "primary"
|
||||
password: """
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzdnZMZ1F1d05RRi84ZENT
|
||||
SmdRNkFLWDRPMTBFTkdOdFRBMC8xK0gvUVV3CjRhWVljR3ZiU1hwWEJBN2hCcTM1
|
||||
NWFQWWdmVm1XK1pKUHFnRjJjYXdDNjgKLS0tIERvOU44ellHdGZYVXRDMHN4NkpV
|
||||
QkhtVlVQUS96UStlQWo2QWJISUlGL2cKc8AC3UujJMIafbV31pjAzniqSHBNwYDw
|
||||
zhh094auKibUcg6Tbyc=
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package test
|
||||
|
||||
import n "du5t1n.me/cfg/schema/app/nut"
|
||||
|
||||
nut: n.#Nut & {
|
||||
listen: {
|
||||
address: "::"
|
||||
port: 3493
|
||||
}
|
||||
|
||||
ups: {
|
||||
nutdev1: {
|
||||
driver: "usbhid-ups"
|
||||
port: "auto"
|
||||
vendorid: "051D"
|
||||
productid: "0002"
|
||||
product: "Back-UPS NS 1100M2 FW:953.e3 .D USB FW:e3"
|
||||
serial: "3B1810X28282"
|
||||
vendor: "American Power Conversion"
|
||||
bus: "001"
|
||||
}
|
||||
}
|
||||
|
||||
users: {
|
||||
dustin: {
|
||||
actions: ["set", "fsd"]
|
||||
instcmds: ["all"]
|
||||
password: """
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnZFN1b095cVk3UnhDdEc2
|
||||
T2RTK0hpSVhGcHhNLzFMZGRvRWRlOERaY3hvCjVvNkxZeXVLcldFRnUwMzdNNU4r
|
||||
eTRYNlFZeGhNWlo5cTdHR2ExNUpBaTgKLS0tIE5DNlp0cVgvMWRXcWd3cFR5akJm
|
||||
a3FnMEhZRHpGMWZicUpqMklQcGtxaEkK82i19a+P++lx2dDJ+SBgNkqOg+7GiSPH
|
||||
gI96Syl48P7V2PP3R6c=
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package nut0
|
||||
|
||||
import (
|
||||
"du5t1n.me/cfg/env/test"
|
||||
)
|
||||
|
||||
nut: test.nut
|
|
@ -1,5 +0,0 @@
|
|||
import pkg
|
||||
import pkg.nut
|
||||
import pkg.common
|
||||
|
||||
render: [pkg.RenderInstruction] = common.templates + nut.templates
|
|
@ -1,4 +0,0 @@
|
|||
kcl_cli_configs:
|
||||
files:
|
||||
- ../app/nut/base
|
||||
- ../app/nut/test
|
|
@ -0,0 +1,7 @@
|
|||
package nut0
|
||||
|
||||
import (
|
||||
"du5t1n.me/cfg/schema/app/nut"
|
||||
)
|
||||
|
||||
render: nut.templates
|
|
@ -1,21 +0,0 @@
|
|||
templates = [
|
||||
{
|
||||
template = "common/reload-udev-rules.path"
|
||||
dest = "/etc/systemd/system/reload-udev-rules.path"
|
||||
hooks = {
|
||||
changed = [
|
||||
{run = "systemctl daemon-reload"}
|
||||
{run = "systemctl try-restart reload-udev-rules.path"}
|
||||
]
|
||||
}
|
||||
}
|
||||
{
|
||||
template = "common/reload-udev-rules.service"
|
||||
dest = "/etc/systemd/system/reload-udev-rules.service"
|
||||
hooks = {
|
||||
changed = [
|
||||
{run = "systemctl daemon-reload"}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
|
@ -1,17 +0,0 @@
|
|||
schema Hook:
|
||||
run: str
|
||||
immediate?: bool
|
||||
|
||||
schema Hooks:
|
||||
changed?: [Hook]
|
||||
|
||||
schema RenderInstruction:
|
||||
template: str
|
||||
dest: str
|
||||
owner?: str
|
||||
group?: str
|
||||
mode?: str
|
||||
hooks?: Hooks
|
||||
|
||||
schema Instructions:
|
||||
render: [RenderInstruction]
|
|
@ -1,35 +0,0 @@
|
|||
schema Ups:
|
||||
"""Schema for ups.conf sections"""
|
||||
|
||||
driver: str
|
||||
port?: str
|
||||
desc?: str
|
||||
vendorid?: str
|
||||
productid?: str
|
||||
product?: str
|
||||
serial?: str
|
||||
vendor?: str
|
||||
bus?: str
|
||||
pollonly?: "enabled" | "disabled"
|
||||
pollinterval?: int
|
||||
|
||||
schema User:
|
||||
"""Schema for upsd.users sections"""
|
||||
|
||||
password: str
|
||||
actions?: [str]
|
||||
instcmds?: [str]
|
||||
upsmon?: "primary" | "secondary"
|
||||
|
||||
schema Listen:
|
||||
"""Schema for listen socket address"""
|
||||
|
||||
address: str = "::"
|
||||
port: int = 3493
|
||||
|
||||
schema Nut:
|
||||
"""Schema for NUT configuration"""
|
||||
|
||||
listen = Listen()
|
||||
ups: {str:Ups} = {}
|
||||
users: {str:User} = {}
|
|
@ -1,49 +0,0 @@
|
|||
templates = [
|
||||
{
|
||||
template = "nut/nut.sysusers"
|
||||
dest = "/etc/sysusers.d/nut.conf"
|
||||
hooks = {
|
||||
changed = [{
|
||||
run = "systemd-sysusers /etc/sysusers.d/nut.conf"
|
||||
immediate = True
|
||||
}]
|
||||
}
|
||||
}
|
||||
{
|
||||
template = "nut/ups.conf"
|
||||
dest = "/etc/ups/ups.conf"
|
||||
hooks = {
|
||||
changed = [{run = "systemctl try-restart nut-server"}]
|
||||
}
|
||||
}
|
||||
{
|
||||
template = "nut/upsd.conf"
|
||||
dest = "/etc/ups/upsd.conf"
|
||||
owner = "root"
|
||||
group = "nut"
|
||||
mode = "u=rw,g=r,o="
|
||||
hooks = {
|
||||
changed = [{run = "systemctl try-reload-or-restart nut-server"}]
|
||||
}
|
||||
}
|
||||
{
|
||||
template = "nut/upsd.users"
|
||||
dest = "/etc/ups/upsd.users"
|
||||
owner = "root"
|
||||
group = "nut"
|
||||
mode = "u=rw,g=r,o="
|
||||
hooks = {
|
||||
changed = [{run = "systemctl try-reload-or-restart nut-server"}]
|
||||
}
|
||||
}
|
||||
{
|
||||
template = "nut/nut-server.container"
|
||||
dest = "/etc/containers/systemd/nut-server.container"
|
||||
hooks = {
|
||||
changed = [
|
||||
{run = "systemctl daemon-reload"}
|
||||
{run = "systemctl restart nut-server"}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
|
@ -0,0 +1,33 @@
|
|||
package nut
|
||||
|
||||
#Ups: {
|
||||
driver: string
|
||||
port?: string
|
||||
desc?: string
|
||||
vendorid?: string
|
||||
productid?: string
|
||||
product?: string
|
||||
serial?: string
|
||||
vendor?: string
|
||||
bus?: string
|
||||
pollonly?: "enabled" | "disabled"
|
||||
pollinterval?: int
|
||||
}
|
||||
|
||||
#User: {
|
||||
password: string
|
||||
actions?: [string, ...]
|
||||
instcmds?: [string, ...]
|
||||
upsmon?: "primary" | "secondary"
|
||||
}
|
||||
|
||||
#Listen: {
|
||||
address: string
|
||||
port: int
|
||||
}
|
||||
|
||||
#Nut: {
|
||||
listen: #Listen
|
||||
ups: [string]: #Ups
|
||||
users: [string]: #User
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package nut
|
||||
|
||||
templates: [
|
||||
{
|
||||
template: "nut/nut.sysusers"
|
||||
dest: "/etc/sysusers.d/nut.conf"
|
||||
hooks: {
|
||||
changed: [{
|
||||
run: "systemd-sysusers /etc/sysusers.d/nut.conf"
|
||||
immediate: true
|
||||
}]
|
||||
}
|
||||
},
|
||||
{
|
||||
template: "nut/ups.conf"
|
||||
dest: "/etc/ups/ups.conf"
|
||||
hooks: {
|
||||
changed: [{run: "systemctl try-restart nut-server"}]
|
||||
}
|
||||
},
|
||||
{
|
||||
template: "nut/upsd.conf"
|
||||
dest: "/etc/ups/upsd.conf"
|
||||
owner: "root"
|
||||
group: "nut"
|
||||
mode: "u=rw,g=r,o="
|
||||
hooks: {
|
||||
changed: [{run: "systemctl try-reload-or-restart nut-server"}]
|
||||
}
|
||||
},
|
||||
{
|
||||
template: "nut/upsd.users"
|
||||
dest: "/etc/ups/upsd.users"
|
||||
owner: "root"
|
||||
group: "nut"
|
||||
mode: "u=rw,g=r,o="
|
||||
hooks: {
|
||||
changed: [{run: "systemctl try-reload-or-restart nut-server"}]
|
||||
}
|
||||
},
|
||||
{
|
||||
template: "nut/nut-server.container"
|
||||
dest: "/etc/containers/systemd/nut-server.container"
|
||||
hooks: {
|
||||
changed: [
|
||||
{run: "systemctl daemon-reload", immediate: true},
|
||||
{run: "systemctl restart nut-server"},
|
||||
]
|
||||
}
|
||||
},
|
||||
]
|
|
@ -0,0 +1,23 @@
|
|||
package instructions
|
||||
|
||||
#Hook: {
|
||||
run: string
|
||||
immediate?: bool
|
||||
}
|
||||
|
||||
#Hooks: {
|
||||
changed?: [#Hook]
|
||||
}
|
||||
|
||||
#RenderInstruction: {
|
||||
template: string
|
||||
dest: string
|
||||
owner?: string
|
||||
group?: string
|
||||
mode?: string
|
||||
hooks?: #Hooks
|
||||
}
|
||||
|
||||
#Instructions: {
|
||||
render: [#RenderInstruction]
|
||||
}
|
Loading…
Reference in New Issue