Skill v1.0.0
currentLLM-judged scan90/100version: "1.0.0" name: migration-v0.1.45-control-plane-secrets description: Upgrade v0.1.45 environments from optional or hand-provisioned telemetry secrets to declared ControlPlaneSecret delivery. relevance: migration
v0.1.45 — control-plane delivered secrets
Use when an env declares a control plane (control_plane = forge.ControlPlane {}) that mints and renews a Secret your workloads read, and that Secret is modelled today as an env var with secret_optional = True (to dodge the first-deploy block), as a required_secrets ExternalSecret you then provision by hand, or as a Secret someone mints on a calendar.
What changed
- New primitive
forge.ControlPlaneSecretonBundle.control_plane_secrets. It declares a Secret whose value the control plane supplies and renews. It is recorded in the env shape (shape.control_plane_secrets: name, namespace, cluster, connected cluster, kind, keys; never a value), never blocks a first deploy, and is refused without a connected-cluster binding (and withoutcontrol_plane). There is no k3d exemption: delivery is the control plane dialing the cluster. - A cluster workload in the same cluster and namespace as a
telemetry_tokengets, automatically, an optional Secret volumeforge-otlp-authat/var/run/secrets/forge/otlpandOTEL_EXPORTER_OTLP_HEADERS_FILE=/var/run/secrets/forge/otlp/headers.pkg/observere-reads that file, so a renewal needs no restart. forge.ObservabilityDestinationgainedtoken_from_control_plane = True: for a destination that is the control plane's OTLP ingest, forge declares the node agent'sControlPlaneSecret(forge-otlp-tokeninagent.namespace, keytoken) on every cluster that runs the agent. Exclusive withheaders_secret/token_secret.- The Secret volume source gained
optional(an author can set it on a volume of their own).output.control_plane_secrets[]is a new render-contract key (empty when none); everyrender_contractgolden gained"control_plane_secrets": [].
Steps
- Delete the workaround. Remove
secret_optional = Truefrom theSecretRefthat read the delivered token, and remove therequired_secretsExternalSecretfor it if there is one. Declaring the same Secret as both is refused ("one Secret has one provider"). - Declare the Secret, on a cluster that names its connected cluster:
``python control_plane_secrets = [ forge.ControlPlaneSecret {name = "reliant-otel-auth", cluster = _prod} ] ``
_prod needs connected_cluster = "<name>" (or connected_clusters = {"<context>": "<name>"} on the Bundle); register the cluster once with forge cluster connect <name> --context <ctx> --env <env>.
- Drop the env var that carried the headers (
OTEL_EXPORTER_OTLP_HEADERSfrom aSecretRef). A workload that still sets it, orOTEL_EXPORTER_OTLP_HEADERS_FILE, is left alone and gets no volume. - For a node agent that exports to the control plane's ingest, replace
headers_secret/token_secretplus therequired_secretsentry withtoken_from_control_plane = Trueon the destination. forge env render <env>, thenforge env deploy <env> --dry-run: the preflight no longer asks for the Secret, and the pod spec gains theforge-otlp-authvolume (one rolling restart).
Verify
forge env shape <env> --json | jq .shape.control_plane_secrets lists the Secret; a first forge env deploy where it does not exist yet passes the preflight.