From a98ac6254ccebee2e3ab396a5711fbee2140fdaa Mon Sep 17 00:00:00 2001 From: Philipp Hossner Date: Wed, 11 Nov 2026 23:47:10 +0100 Subject: [PATCH] charts: allow pinning component images by digest Fixes #173 Signed-off-by: Philipp Hossner --- charts/substrate-atelet/templates/_helpers.tpl | 6 +++++- charts/substrate-atelet/values.yaml | 3 +++ charts/substrate-podcert/README.md | 2 +- charts/substrate-podcert/templates/_helpers.tpl | 11 +++++++---- charts/substrate-podcert/values.yaml | 3 +++ charts/substrate/README.md | 3 ++- charts/substrate/templates/_helpers.tpl | 11 ++++++++--- charts/substrate/tests/control_plane_test.yaml | 17 +++++++++++++++++ charts/substrate/values.yaml | 6 ++++++ 9 files changed, 52 insertions(+), 10 deletions(-) diff --git a/charts/substrate-atelet/templates/_helpers.tpl b/charts/substrate-atelet/templates/_helpers.tpl index f9905c8fda..50dfafeff4 100644 --- a/charts/substrate-atelet/templates/_helpers.tpl +++ b/charts/substrate-atelet/templates/_helpers.tpl @@ -79,7 +79,11 @@ substrate release references. {{- $name := index . 0 -}} {{- $ctx := index . 1 -}} {{- $registry := default $ctx.Values.image.registry (($ctx.Values.global).imageRegistry) -}} -{{- printf "%s/%s/%s:%s" $registry $ctx.Values.image.repository $name ($ctx.Values.image.tag | default $ctx.Chart.AppVersion) -}} +{{- $ref := printf "%s/%s/%s:%s" $registry $ctx.Values.image.repository $name ($ctx.Values.image.tag | default $ctx.Chart.AppVersion) -}} +{{- with index ($ctx.Values.image.digests | default dict) $name -}} +{{- $ref = printf "%s@%s" $ref . -}} +{{- end -}} +{{- $ref -}} {{- end -}} {{/* imagePullSecrets for a pod spec. Copied from the substrate chart. */}} diff --git a/charts/substrate-atelet/values.yaml b/charts/substrate-atelet/values.yaml index b68515745e..34453701d1 100644 --- a/charts/substrate-atelet/values.yaml +++ b/charts/substrate-atelet/values.yaml @@ -114,3 +114,6 @@ image: # Image path prefix under the registry, ahead of each component name. repository: kagent-dev/substrate tag: "" + # Optional digest per component image, keyed by component name (atelet, + # objectstore-plugin), appended to its reference after the tag. + digests: {} diff --git a/charts/substrate-podcert/README.md b/charts/substrate-podcert/README.md index 368142e2f5..65f1bc413d 100644 --- a/charts/substrate-podcert/README.md +++ b/charts/substrate-podcert/README.md @@ -34,7 +34,7 @@ PostgreSQL login identities. Entries use `namespace/service-account=username[,username]` form. Configure the controller image through `image.registry`, `image.repository`, -and `image.tag`. `global.imageRegistry` overrides the registry, and +`image.tag` and, to pin it by digest, `image.digests.podcertcontroller`. `global.imageRegistry` overrides the registry, and `imagePullSecrets` and `global.imagePullSecrets` are merged for the controller pod. For an existing installation, the controller resources must be transferred out diff --git a/charts/substrate-podcert/templates/_helpers.tpl b/charts/substrate-podcert/templates/_helpers.tpl index 7ee405fbf9..73efe175d6 100644 --- a/charts/substrate-podcert/templates/_helpers.tpl +++ b/charts/substrate-podcert/templates/_helpers.tpl @@ -32,11 +32,14 @@ limitations under the License. {{- end -}} {{- $registry := default $ctx.Values.image.registry $ctx.Values.global.imageRegistry -}} {{- $tag := default $ctx.Chart.AppVersion $ctx.Values.image.tag -}} -{{- if eq $tag "" -}} -{{- printf "%s/%s/%s" $registry $ctx.Values.image.repository $name -}} -{{- else -}} -{{- printf "%s/%s/%s:%s" $registry $ctx.Values.image.repository $name $tag -}} +{{- $ref := printf "%s/%s/%s" $registry $ctx.Values.image.repository $name -}} +{{- if ne $tag "" -}} +{{- $ref = printf "%s:%s" $ref $tag -}} +{{- end -}} +{{- with index ($ctx.Values.image.digests | default dict) $name -}} +{{- $ref = printf "%s@%s" $ref . -}} {{- end -}} +{{- $ref -}} {{- end -}} {{- define "podcert.imagePullSecrets" -}} diff --git a/charts/substrate-podcert/values.yaml b/charts/substrate-podcert/values.yaml index d4203c8a04..f6432eb991 100644 --- a/charts/substrate-podcert/values.yaml +++ b/charts/substrate-podcert/values.yaml @@ -43,3 +43,6 @@ image: registry: ghcr.io repository: kagent-dev/substrate tag: "" + # Optional digest per component image, keyed by component name + # (podcertcontroller), appended to its reference after the tag. + digests: {} diff --git a/charts/substrate/README.md b/charts/substrate/README.md index 35d7bc96c8..e87de3d140 100644 --- a/charts/substrate/README.md +++ b/charts/substrate/README.md @@ -46,7 +46,8 @@ atelet before ate-api-server. By default, component images are pulled from `ghcr.io/kagent-dev/substrate` using the chart `appVersion` as the tag. Override `image.registry` and -`image.tag` to install from a different image repository or tag. +`image.tag` to install from a different image repository or tag. Set `image.digests` to pin +component images by digest, keyed by component name. The chart installs the Kubernetes credential provider and enables HTTPS egress interception. Create the `egress-mitm-ca-pool` Secret and configure actor trust diff --git a/charts/substrate/templates/_helpers.tpl b/charts/substrate/templates/_helpers.tpl index 35d435d350..d998e4fe00 100644 --- a/charts/substrate/templates/_helpers.tpl +++ b/charts/substrate/templates/_helpers.tpl @@ -163,6 +163,8 @@ Produces {image.registry}/{name}:{tag} where tag is resolved as: 2. .Chart.AppVersion, if image.tag is empty 3. no tag (no colon) when image.tag is the sentinel "" +followed by @{digest} when image.digests has an entry for {name}. + The "" sentinel is used by hack/render-manifests.sh so that ko:// refs are emitted without a tag, letting `ko resolve` supply the digest at build time. */}} @@ -184,11 +186,14 @@ are emitted without a tag, letting `ko resolve` supply the digest at build time. {{- end -}} {{- $registry := printf "%s/%s" (default $ctx.Values.image.registry (($ctx.Values.global).imageRegistry)) $ctx.Values.image.repository -}} {{- $tag := $ctx.Values.image.tag | default $ctx.Chart.AppVersion -}} +{{- $ref := printf "%s/%s" $registry $name -}} {{- if ne $tag "" -}} -{{- printf "%s/%s:%s" $registry $name $tag -}} -{{- else -}} -{{- printf "%s/%s" $registry $name -}} +{{- $ref = printf "%s:%s" $ref $tag -}} {{- end -}} +{{- with index ($ctx.Values.image.digests | default dict) $name -}} +{{- $ref = printf "%s@%s" $ref . -}} +{{- end -}} +{{- $ref -}} {{- end -}} {{/* diff --git a/charts/substrate/tests/control_plane_test.yaml b/charts/substrate/tests/control_plane_test.yaml index 87646b96fc..005b870353 100644 --- a/charts/substrate/tests/control_plane_test.yaml +++ b/charts/substrate/tests/control_plane_test.yaml @@ -600,3 +600,20 @@ tests: asserts: - failedTemplate: errorMessage: "atenetEgress.extraCredentialProviders: vault.example.com needs an address as host:port" + +- it: pins a component image by digest when image.digests names the component + template: ate-api-server.yaml + documentSelector: + path: kind + value: Deployment + set: + image.tag: v9.9.9 + image.digests: + ateapi: sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef + asserts: + - equal: + path: spec.template.spec.containers[0].image + value: ghcr.io/kagent-dev/substrate/ateapi:v9.9.9@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef + - equal: + path: spec.template.spec.initContainers[0].image + value: ghcr.io/kagent-dev/substrate/objectstore-plugin:v9.9.9 diff --git a/charts/substrate/values.yaml b/charts/substrate/values.yaml index 5d0f7a4dce..62fcb43047 100644 --- a/charts/substrate/values.yaml +++ b/charts/substrate/values.yaml @@ -257,6 +257,12 @@ image: # images under this same path. repository: kagent-dev/substrate tag: "" + # Optional digest per component image, keyed by component name (ateapi, + # atecontroller, ate-idp-server, atelet, objectstore-plugin, + # kubernetes-secrets), appended to that image's reference after the tag: + # digests: + # ateapi: sha256:... + digests: {} images: rustfs: rustfs/rustfs:1.0.3@sha256:9ca9559533b537d10482fe923288b676ad08f92a7069d9a17327fbae3cab688b