Snapshot ConfigMap resourceVersions before and after kubectl apply.
For any ConfigMap whose resourceVersion changed, find all Deployments
in the same namespace that mount it as a volume and issue a rollout
restart. Eliminates the need to manually restart pods after editing
ConfigMaps (e.g. services.json, nginx configs).
Builds the integration-service Docker image from the sunbeam/ root
context (needs both integration/packages/ for the widget source and
integration-service/ for nginx config and logos), pushes to Gitea,
pre-seeds into k3s containerd, and rolls the deployment.
images.py: extend AMD64_ONLY_IMAGES with the three impress (La Suite Docs)
images — impress-backend, impress-frontend, impress-y-provider. Always pull
the amd64 manifest + layers by digest unconditionally before the blob check;
the prior guard skipped the pull when the index blob was present but layers
were missing, causing the OCI import to fail on arm64 hosts.
secrets.py: add docs KV path (django-secret-key, collaboration-secret) to
_seed_openbao so a fresh sunbeam seed generates all required credentials for
the impress deployment.
kube.py: kube_exec now accepts an optional container= kwarg so callers
can target a specific container in Linkerd-injected pods (where exec
would otherwise land in the linkerd-proxy sidecar instead of the app).
Used by check_valkey (container="valkey") and check_openbao
(container="openbao").
kube.py + cli.py: new cmd_k8s / sunbeam k8s verb — transparent
kubectl --context=sunbeam passthrough for one-off cluster operations.
Returns kubectl's exit code directly.
manifests.py: fix REPO_ROOT parents index (was 3, needed 2) which
caused kustomize overlay lookup to resolve against the wrong directory.
tools.py: call ensure_tool("helm") before running kustomize so the
bundled helm v3.17.1 is on PATH; system helm v4 dropped the -c flag
that kustomize 5.6.0 uses for version detection.
gitea.py: pass --must-change-password=false to gitea admin user
change-password, removing the separate Postgres UPDATE workaround that
was fragile and required a second exec into the CNPG pod.
Replaced the unauthenticated SeaweedFS probe (which accepted any HTTP
< 500 as passing) with a signed S3 ListBuckets request using AWS
Signature V4. Credentials are read from the seaweedfs-s3-credentials
K8s secret; a 200 response confirms authentication is working.
Updated tests to cover missing creds, 403 bad-creds, 502 gateway error,
and URLError cases.
All checks now run concurrently via ThreadPoolExecutor so total time
is bounded by the slowest single check, not their sum.
Timeout reduced from 10s to 5s per check. SeaweedFS check switched
from kubectl exec (wget not reliably available in container) to an
HTTP probe against the external S3 endpoint (https://s3.DOMAIN/) —
consistent with the "use external URLs for publicly facing services"
requirement. 403 is treated as healthy (unauthenticated S3 response).
Output now mirrors sunbeam status (namespace headers, checks indented
below). Any uncaught exception from a check is caught in cmd_check
and displayed as a failed check instead of crashing.
Also fix _http_get: TimeoutError and other raw OSError/SSL errors that
Python 3.13 doesn't always wrap in URLError are now normalized to
URLError before re-raising, so each check function's URLError handler
reliably catches all network failures.