Files
unkinben 9b3fa83dac
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
Move kea entrypoints out of Go fmt.Sprintf into an initContainer
Container entrypoints were rendered as `fmt.Sprintf` shell strings in Go, so
every entrypoint fix needed a full operator release, nothing was shellcheckable,
and the escaping was a hazard.

How:
- Add a `kea-init` initContainer that finalises the per-pod config and
  bounded-waits for HA peer DNS, replacing the in-entrypoint retry. It hardens
  the shared run dir to 0750, substitutes `this-server-name` from the pod
  ordinal (`POD_NAME` via the downward API), stages both configs into the shared
  emptyDir, and gates on `kea-dhcp4 -t` (60x2s) — failing loud after the cap so
  the kubelet restarts it instead of starting a doomed server.
- Run the main kea-dhcp4 / kea-ctrl-agent containers with kea exec'd directly,
  dropping both wrapper shells.
- Replace the two `fmt.Sprintf` entrypoints with a single committed
  `internal/kea/scripts/init.sh` embedded via `go:embed` and parameterised
  entirely by env vars — no Go string interpolation.
- Add a shellcheck step to the pre-commit pipeline.

Test:
- Assert the pod shape: one kea-init initContainer, POD_NAME from the downward
  API, main containers exec kea directly, and the ConfigMap carries init.sh (not
  the old per-container entrypoints).
- Assert init.sh hardens the socket dir, gates on `kea-dhcp4 -t`, fails loud
  after the cap, and is free of fmt verbs.
- shellcheck the embedded script.
2026-08-08 22:52:59 +10:00

42 lines
1.5 KiB
Go

package kea
import _ "embed"
type ctrlAgentRoot struct {
ControlAgent controlAgent `json:"Control-agent"`
}
type controlAgent struct {
HTTPHost string `json:"http-host"`
HTTPPort int `json:"http-port"`
ControlSockets map[string]map[string]any `json:"control-sockets"`
Loggers []logger `json:"loggers"`
}
// RenderCtrlAgent renders the deterministic kea-ctrl-agent.conf JSON. The
// control agent exposes the HA/REST control channel on CtrlAgentPort and
// forwards to kea-dhcp4 over the shared unix socket.
func RenderCtrlAgent() (string, error) {
return marshal(ctrlAgentRoot{ControlAgent: controlAgent{
HTTPHost: "0.0.0.0",
HTTPPort: CtrlAgentPort,
ControlSockets: map[string]map[string]any{
"dhcp4": {"socket-type": "unix", "socket-name": CtrlSocketPath},
},
Loggers: loggers("kea-ctrl-agent"),
}})
}
// initScript is the initContainer entrypoint. It is a committed, shellcheck-clean
// shell file (no fmt.Sprintf interpolation) parameterised entirely by the
// environment variables the operator sets on the initContainer. It prepares the
// shared run dir, finalises this pod's kea-dhcp4 config from the StatefulSet
// ordinal, and bounded-waits for the HA peer DNS to resolve before the main
// kea-dhcp4 / kea-ctrl-agent containers exec kea directly.
//
//go:embed scripts/init.sh
var initScript string
// InitScript returns the initContainer entrypoint shell script.
func InitScript() string { return initScript }