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

86 lines
3.5 KiB
Go

package kea
// Filesystem and binary paths inside the kea container image, plus the
// operator's label/annotation vocabulary.
const (
// ContainerDHCP4 is the kea-dhcp4 container name.
ContainerDHCP4 = "kea-dhcp4"
// ContainerCtrlAgent is the kea-ctrl-agent container name.
ContainerCtrlAgent = "kea-ctrl-agent"
// ContainerInit is the initContainer that finalises config and waits for
// HA peer DNS before the main containers start.
ContainerInit = "kea-init"
// ConfigDir is where projected config is mounted read-only.
ConfigDir = "/etc/kea-operator"
// RunDir is a shared emptyDir for the config copy and control socket. Kea
// 2.6+ restricts unix socket paths to its compiled runstatedir and rejects
// anything else by exact string ("supported path is '/var/run/kea'"), even
// though /var/run symlinks to /run, so this must be the literal /var/run/kea.
RunDir = "/var/run/kea"
// DHCP4ConfPath is the runtime kea-dhcp4 config.
DHCP4ConfPath = RunDir + "/kea-dhcp4.conf"
// CtrlAgentConfPath is the runtime kea-ctrl-agent config.
CtrlAgentConfPath = RunDir + "/kea-ctrl-agent.conf"
// CtrlSocketPath is the unix control socket between ctrl-agent and dhcp4.
CtrlSocketPath = RunDir + "/kea4-ctrl-socket"
// InitScriptPath is where the initContainer entrypoint is projected from the
// ConfigMap.
InitScriptPath = ConfigDir + "/init.sh"
// DHCP4Bin is the kea-dhcp4 server binary.
DHCP4Bin = "/usr/sbin/kea-dhcp4"
// CtrlAgentBin is the kea-ctrl-agent binary.
CtrlAgentBin = "/usr/sbin/kea-ctrl-agent"
// HooksDir holds the Kea hook libraries.
HooksDir = "/usr/lib64/kea/hooks"
// HALibrary is the High Availability hook.
HALibrary = HooksDir + "/libdhcp_ha.so"
// LeaseCmdsLibrary is the lease commands hook (required by HA lease sync).
LeaseCmdsLibrary = HooksDir + "/libdhcp_lease_cmds.so"
// CtrlAgentPort is the REST control channel port.
CtrlAgentPort = 8000
// DHCP4Port is the DHCPv4 server port.
DHCP4Port = 67
// DefaultImage is the kea workload image built by this repo.
DefaultImage = "git.unkin.net/unkin/kea:latest"
// ClientArchOption is the DHCP option code carrying PXE client arch.
ClientArchOption = 93
// WaitAttempts caps the initContainer's bounded wait for the HA peer DNS to
// resolve (i.e. for the rendered config to pass "kea-dhcp4 -t").
WaitAttempts = 60
// WaitSleepSeconds is the delay between bounded-wait attempts.
WaitSleepSeconds = 2
)
// Environment variable names the operator sets on the initContainer. The
// embedded init.sh reads only these; keeping the names here means the script
// stays free of any Go string interpolation.
const (
// EnvPodName carries the pod name (downward API metadata.name); its ordinal
// suffix selects this pod's HA peer name.
EnvPodName = "POD_NAME"
// EnvRunDir is the shared run/socket dir path.
EnvRunDir = "RUN_DIR"
// EnvConfigDir is the read-only projected config dir path.
EnvConfigDir = "CONFIG_DIR"
// EnvThisServerPlaceholder is the token replaced with this pod's HA peer name.
EnvThisServerPlaceholder = "THIS_SERVER_PLACEHOLDER"
// EnvDHCP4Bin is the kea-dhcp4 binary path (used for the -t config check).
EnvDHCP4Bin = "DHCP4_BIN"
// EnvDHCP4Conf is the finalized kea-dhcp4 config path in the shared run dir.
EnvDHCP4Conf = "DHCP4_CONF"
// EnvCtrlAgentConf is the staged kea-ctrl-agent config path in the run dir.
EnvCtrlAgentConf = "CTRL_AGENT_CONF"
// EnvWaitAttempts is the bounded-wait attempt cap.
EnvWaitAttempts = "WAIT_ATTEMPTS"
// EnvWaitSleep is the per-attempt sleep in seconds.
EnvWaitSleep = "WAIT_SLEEP"
)