Bake the conformance harness toolchain into infra/devcontainer so `make -C ci gate` runs identically here and in CI: - Containerfile: install kyverno CLI (1.13.4), kyverno-json, chainsaw (0.2.12), yamllint (1.35.1), check-jsonschema (0.29.4), yq (4.44.6) via new pinned RUN block; add diffutils + python3-pip; drop stale LIBVIRT_DEFAULT_URI; refresh header for the Proxmox(bpg)+conformance toolbox; extend /etc/dev-toolchain-versions provenance. - versions.env: add KYVERNO/KYVERNO_JSON/CHAINSAW/YAMLLINT/YQ/CHECK_JSONSCHEMA; align KUBECTL 1.32.0 -> 1.31.4. dev.sh build(): pass the new --build-args. - ci/versions.env: pin CHECK_JSONSCHEMA_VERSION=0.29.4 (single source of truth). Fix harness seams so the gate can run: - dev.sh run(): mount the sibling spec repo (home-network-k3s) read-only at /home-network-k3s for ci/spec-immutability.sh (R-TEST-06); conditional so the container still runs without it. - conformance/lib/common.sh conf_dirs_for_layer(): accept a comma/space list of layers and union the dirs, so ci/conformance.sh `run.sh --layer l2,l3` selects both layers in one pass (backward compatible for single layers). NOTE: ci/versions.env pins KYVERNO_JSON_VERSION=0.0.5, which has no upstream release (max tag is v0.0.3; platform/kyverno/scripts/run-l0.sh already defaults to v0.0.3). Baked v0.0.3 and flagged for PM to correct ci/versions.env. kyverno-json is not used by any static gate stage. Co-Authored-By: Claude Opus 4.8 <[email protected]>
92 lines
5.1 KiB
Bash
Executable File
92 lines
5.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# infra/devcontainer/dev.sh — build & enter the pinned dev toolbox.
|
|
#
|
|
# Mounts the repo so OpenTofu (bpg/proxmox) and Ansible drive the Proxmox-hosted k3s cluster
|
|
# from inside the container. Rootless podman by default (ENGINE=docker to switch); SELinux
|
|
# label is disabled for the run. On each run it also opens a best-effort SSH tunnel to the
|
|
# cluster's kube-API over the pfSense SSH NAT, so kubectl/flux/helm reach the Proxmox cluster
|
|
# transparently (the API port itself is not NAT-forwarded). Set DEV_NO_TUNNEL=1 to skip it.
|
|
#
|
|
# ./dev.sh build # build the image only
|
|
# ./dev.sh # build (if needed) + open a shell (kube tunnel up)
|
|
# ./dev.sh run tofu -version # run one command in the toolbox
|
|
# ./dev.sh run kubectl get nodes # talks to the Proxmox k3s cluster via the tunnel
|
|
set -euo pipefail
|
|
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "${HERE}/../.." && pwd)"
|
|
IMAGE="${IMAGE:-home-k3s-dev:local}"
|
|
ENGINE="${ENGINE:-podman}"
|
|
# shellcheck disable=SC1091
|
|
source "${HERE}/versions.env"
|
|
|
|
# k3s API access: the dev cluster runs on Proxmox (nodes on 192.168.1.0/24), whose kube-API
|
|
# port is NOT directly routable from here — dev.sh opens an SSH tunnel over the pfSense SSH NAT
|
|
# (local :${K3S_API_LOCAL_PORT} -> primary node 127.0.0.1:6443) so kubectl/flux/helm work
|
|
# transparently. infra/ansible/.cache/dev.kubeconfig targets https://127.0.0.1:${K3S_API_LOCAL_PORT}.
|
|
K3S_SSH_HOST="${K3S_SSH_HOST:-192.168.2.102}" # pfSense NAT front for the primary node SSH
|
|
K3S_SSH_PORT="${K3S_SSH_PORT:-2250}" # forwards to k3s-dev-1 (192.168.1.50):22
|
|
K3S_SSH_USER="${K3S_SSH_USER:-k3s}"
|
|
K3S_API_LOCAL_PORT="${K3S_API_LOCAL_PORT:-16443}"
|
|
|
|
build() {
|
|
"$ENGINE" build \
|
|
--build-arg FEDORA_VERSION="$FEDORA_VERSION" \
|
|
--build-arg OPENTOFU_VERSION="$OPENTOFU_VERSION" \
|
|
--build-arg AGE_VERSION="$AGE_VERSION" \
|
|
--build-arg SOPS_VERSION="$SOPS_VERSION" \
|
|
--build-arg FLUX_VERSION="$FLUX_VERSION" \
|
|
--build-arg KUBECTL_VERSION="$KUBECTL_VERSION" \
|
|
--build-arg HELM_VERSION="$HELM_VERSION" \
|
|
--build-arg KYVERNO_VERSION="$KYVERNO_VERSION" \
|
|
--build-arg KYVERNO_JSON_VERSION="$KYVERNO_JSON_VERSION" \
|
|
--build-arg CHAINSAW_VERSION="$CHAINSAW_VERSION" \
|
|
--build-arg YAMLLINT_VERSION="$YAMLLINT_VERSION" \
|
|
--build-arg YQ_VERSION="$YQ_VERSION" \
|
|
--build-arg CHECK_JSONSCHEMA_VERSION="$CHECK_JSONSCHEMA_VERSION" \
|
|
-t "$IMAGE" -f "${HERE}/Containerfile" "${HERE}"
|
|
}
|
|
|
|
run() {
|
|
# Persist the SOPS age keyring on the HOST so the age PRIVATE key generated by
|
|
# bootstrap/sops/age-keygen.sh survives this --rm container (otherwise it lives only
|
|
# in the ephemeral container fs and is lost on exit — you'd be locked out of every
|
|
# SOPS-encrypted secret). SOPS_AGE_KEY_FILE defaults to ~/.config/sops/age/keys.txt,
|
|
# which is this mount. Create it first so the bind source exists.
|
|
mkdir -p "${HOME}/.config/sops/age"
|
|
# In-container prelude (runs before your command): bring up the kube-API SSH tunnel so
|
|
# kubectl/flux/helm reach the Proxmox cluster. Best-effort — if the cluster is unreachable
|
|
# it warns and continues (tofu/ansible don't need it). Skip with DEV_NO_TUNNEL=1.
|
|
local prelude=":"
|
|
if [ "${DEV_NO_TUNNEL:-0}" != "1" ]; then
|
|
prelude="if [ -f /root/.ssh/home_network ]; then ssh -fN -L ${K3S_API_LOCAL_PORT}:127.0.0.1:6443 -p ${K3S_SSH_PORT} -i /root/.ssh/home_network -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ExitOnForwardFailure=yes -o ConnectTimeout=5 -o ServerAliveInterval=30 ${K3S_SSH_USER}@${K3S_SSH_HOST} 2>/dev/null || echo '[dev.sh] k3s API tunnel not up (cluster down or NAT changed?) — kubectl/flux/helm will not reach the cluster' >&2; fi"
|
|
fi
|
|
# Spec repo (home-network-k3s) mount, read-only, for ci/spec-immutability.sh (R-TEST-06).
|
|
# That script reads SPEC_REPO (default ${REPO_ROOT}/../home-network-k3s); inside the
|
|
# container REPO_ROOT is /work, so the default resolves to /home-network-k3s. Mount the
|
|
# sibling spec repo there RO when it exists; skip the mount otherwise so the container
|
|
# still runs (the gate then honestly SKIPS immutability — exit 3, never faked green).
|
|
local -a spec_mount=()
|
|
local spec_host
|
|
spec_host="$(cd "${REPO_ROOT}/../home-network-k3s" 2>/dev/null && pwd || true)"
|
|
if [ -n "${spec_host}" ] && [ -d "${spec_host}/.git" ]; then
|
|
spec_mount=(-v "${spec_host}:/home-network-k3s:ro" -e SPEC_REPO=/home-network-k3s)
|
|
fi
|
|
"$ENGINE" run --rm -it \
|
|
--network host \
|
|
--security-opt label=disable \
|
|
-v "${REPO_ROOT}:/work" -w /work \
|
|
"${spec_mount[@]}" \
|
|
-v "${HOME}/.ssh:/root/.ssh:ro" \
|
|
-v "${HOME}/.config/sops:/root/.config/sops" \
|
|
-v "${HOME}/.config/home-k3s/ansible-vault-pass:/root/.config/home-k3s/ansible-vault-pass:ro" \
|
|
-e KUBECONFIG="${DEV_KUBECONFIG:-/work/infra/ansible/.cache/dev.kubeconfig}" \
|
|
"$IMAGE" bash -lc "${prelude}"'; if [ "$#" -gt 0 ]; then exec "$@"; else exec bash -l; fi' dev.sh "$@"
|
|
}
|
|
|
|
case "${1:-shell}" in
|
|
build) build ;;
|
|
run) shift; run "$@" ;;
|
|
shell) build; shift 2>/dev/null || true; run ;;
|
|
*) build; run "$@" ;;
|
|
esac
|