From 8d0e821b0157676bc35120a1750ea6594875e8db Mon Sep 17 00:00:00 2001 From: Pujitha Paladugu <10557236+pujitha24@users.noreply.github.com> Date: Tue, 4 Aug 2026 12:21:52 -0700 Subject: [PATCH] fix(common): apply registry override to image args Motivation: TEKTON_REGISTRY_OVERRIDE is documented as a way to rewrite the registry for every image the operator deploys, but only container.Image, Task step images, and StepAction images had a fallback that applies it when no per-image env var is set. Images passed as container CLI args (e.g. "-workingdirinit-image ", "-el-image ", "-shell-image-win ") were skipped by that fallback, so in an air-gapped install those container args still pointed at the public upstream registries (gcr.io, mcr.microsoft.com) even with TEKTON_REGISTRY_OVERRIDE set, unless the user also set every documented per-image env var individually. This matches the images the reporter listed as not being rewritten. No crash or outage results; the effect is ImagePullBackOff for those specific images in registry-restricted clusters, and it did already have a documented per-image env var workaround. Approach: replaceContainersArgsImage (pkg/reconciler/common/transformers.go) only rewrote an arg's image when a matching per-image env var existed. Add the same registry-override fallback already used by replaceContainerImages/replaceStepsImages/replaceStepActionImages: when no per-image override matches an arg whose flag name looks like an image flag (contains "_image" once normalized, covering both "-foo-image" and "-foo-image-win" style flags), rewrite just its registry domain via TEKTON_REGISTRY_OVERRIDE. Validation: Added TestDeploymentContainerArgsImagesRegistryOverrideFallback to pkg/reconciler/common/transformers_test.go, covering both a plain "-bash-image" arg and the real "-shell-image-win" flag shipped in the Tekton Pipeline controller manifest. Confirmed (by temporarily reverting the transformers.go change) that this test fails without the fix and passes with it. go build ./... go vet ./pkg/reconciler/common/... gofmt -l pkg/reconciler/common/transformers.go pkg/reconciler/common/transformers_test.go go test ./pkg/reconciler/common/... ./pkg/reconciler/kubernetes/tektonpipeline/... \ ./pkg/reconciler/kubernetes/tektontrigger/... ./pkg/reconciler/openshift/tektontrigger/... \ ./pkg/reconciler/openshift/common/... All of the above pass. golangci-lint could not be downloaded in this sandbox (checksum mismatch fetching the pinned release binary, unrelated to this change); go vet and gofmt are clean. Report: https://github.com/tektoncd/operator/issues/3270 ```release-note Fix `TEKTON_REGISTRY_OVERRIDE` not being applied to image references passed as container args (e.g. entrypoint, nop, workingdirinit, shell-image-win, and triggers' event-listener sink images). ``` Signed-off-by: Pujitha Paladugu <10557236+pujitha24@users.noreply.github.com> --- .../common/testdata/test-replace-image.yaml | 3 ++- pkg/reconciler/common/transformers.go | 13 ++++++++++-- pkg/reconciler/common/transformers_test.go | 21 +++++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/pkg/reconciler/common/testdata/test-replace-image.yaml b/pkg/reconciler/common/testdata/test-replace-image.yaml index 602f740a7a..432410fe7e 100644 --- a/pkg/reconciler/common/testdata/test-replace-image.yaml +++ b/pkg/reconciler/common/testdata/test-replace-image.yaml @@ -17,7 +17,8 @@ spec: name: controller-deployment args: [ "-bash-image", "busybox", - "-nop=nop" + "-nop=nop", + "-shell-image-win", "mcr.microsoft.com/powershell:nanoserver" ] - image: busybox name: sidecar diff --git a/pkg/reconciler/common/transformers.go b/pkg/reconciler/common/transformers.go index bf0d53b195..b8188ede85 100644 --- a/pkg/reconciler/common/transformers.go +++ b/pkg/reconciler/common/transformers.go @@ -321,16 +321,23 @@ func replaceContainerImages(containers []corev1.Container, images map[string]str containers[i].Image = overrideImageRegistry(registry, containers[i].Image) } - replaceContainersArgsImage(&container, images) + replaceContainersArgsImage(&container, images, registry) } } -func replaceContainersArgsImage(container *corev1.Container, images map[string]string) { +// replaceContainersArgsImage replaces image references passed as container +// args (e.g. "-workingdirinit-image", "gcr.io/..."). If no per-image env var +// matches a given "*-image*" flag (e.g. "-shell-image-win"), it falls back +// to rewriting just the registry domain, so TEKTON_REGISTRY_OVERRIDE alone +// also applies to arg-based images and not only to container.Image. +func replaceContainersArgsImage(container *corev1.Container, images map[string]string, registry string) { for a, arg := range container.Args { if argVal, hasArg := SplitsByEqual(arg); hasArg { argument := formKey(ArgPrefix, argVal[0]) if url, exist := images[argument]; exist { container.Args[a] = argVal[0] + "=" + url + } else if strings.Contains(argument, "_image") { + container.Args[a] = argVal[0] + "=" + overrideImageRegistry(registry, argVal[1]) } continue } @@ -338,6 +345,8 @@ func replaceContainersArgsImage(container *corev1.Container, images map[string]s argument := formKey(ArgPrefix, arg) if url, exist := images[argument]; exist { container.Args[a+1] = url + } else if strings.Contains(argument, "_image") { + container.Args[a+1] = overrideImageRegistry(registry, container.Args[a+1]) } } } diff --git a/pkg/reconciler/common/transformers_test.go b/pkg/reconciler/common/transformers_test.go index 8713d540e4..e75e1aad87 100644 --- a/pkg/reconciler/common/transformers_test.go +++ b/pkg/reconciler/common/transformers_test.go @@ -277,6 +277,27 @@ func TestDeploymentImagesRegistryOverrideFallback(t *testing.T) { assertDeployContainersHasImage(t, newManifest.Resources(), "sidecar", "custom-registry.io/custom-path/busybox") } +func TestDeploymentContainerArgsImagesRegistryOverrideFallback(t *testing.T) { + t.Setenv("TEKTON_REGISTRY_OVERRIDE", "custom-registry.io/custom-path") + // no per-image env var matches any arg in the manifest + images := map[string]string{ + "some_other_image": "foo.bar/unrelated", + } + testData := path.Join("testdata", "test-replace-image.yaml") + + manifest, err := mf.ManifestFrom(mf.Recursive(testData)) + assertNoError(t, err) + newManifest, err := manifest.Transform(DeploymentImages(images)) + assertNoError(t, err) + // "-bash-image" ends in "-image", so the registry override fallback applies. + assertDeployContainerArgsHasImage(t, newManifest.Resources(), "-bash-image", "custom-registry.io/custom-path/busybox") + // "-shell-image-win" contains "-image" but doesn't end with it (real example + // from the Tekton Pipeline controller manifest); the fallback must still apply. + assertDeployContainerArgsHasImage(t, newManifest.Resources(), "-shell-image-win", "custom-registry.io/custom-path/powershell:nanoserver") + // "-git" does not look like an image flag and must be left untouched. + assertDeployContainerArgsHasImage(t, newManifest.Resources(), "-git", "git") +} + func TestTaskImagesRegistryOverrideFallback(t *testing.T) { t.Setenv("TEKTON_REGISTRY_OVERRIDE", "custom-registry.io/custom-path") images := map[string]string{}