From de511982b482462e33dba37b87f32e951aae5143 Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Tue, 20 Oct 2026 08:41:19 +0000 Subject: [PATCH 1/7] e2e: enable upgrade test on EKS with pull secret support Add EKS to the upgrade test provider gate and read E2E_IMAGE_PULL_SECRET to set imagePullSecrets on helm install/upgrade, allowing the test to pull from private registries. Assisted-by: AI Signed-off-by: Alice Frosi --- test/e2e/upgrade_test.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/e2e/upgrade_test.go b/test/e2e/upgrade_test.go index 90172488..b78910bd 100644 --- a/test/e2e/upgrade_test.go +++ b/test/e2e/upgrade_test.go @@ -36,7 +36,7 @@ var operatorCRDNames = []string{ // helm upgrade with the current image and verifies the operator still // works. func TestOperatorUpgrade(t *testing.T) { - e2eutil.Providers(t, "bink") + e2eutil.Providers(t, "bink", "eks") releaseTag := os.Getenv("E2E_OPERATOR_RELEASE_TAG") if releaseTag == "" { @@ -206,6 +206,9 @@ func helmImageArgs(t *testing.T, img string, extraArgs []string) []string { "--set-string", "image.tag=" + tag, "--set-string", "image.pullPolicy=Always", } + if secret := os.Getenv("E2E_IMAGE_PULL_SECRET"); secret != "" { + args = append(args, "--set", "imagePullSecrets[0].name="+secret) + } if len(extraArgs) > 0 { j, err := json.Marshal(extraArgs) if err != nil { From d9ce03ccd52e7c675d5354cf5fbbaad7d2f41619 Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Tue, 20 Oct 2026 08:41:24 +0000 Subject: [PATCH 2/7] e2e: pass upgrade test vars to e2e-eks target Forward RELEASED_OPERATOR_TAG, RELEASED_OPERATOR_IMG, and EKS_IMAGE_PULL_SECRET to the e2e-eks make target so the upgrade test can run against EKS clusters. Assisted-by: AI Signed-off-by: Alice Frosi --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index 09bf7638..d3c4e1fc 100644 --- a/Makefile +++ b/Makefile @@ -129,6 +129,7 @@ EKS_NODE_IMAGE_UPDATE2_REF ?= EKS_REGISTRY_HOST ?= EKS_REGISTRY_USER ?= EKS_REGISTRY_PASSWORD ?= +EKS_IMAGE_PULL_SECRET ?= .PHONY: e2e-eks e2e-eks: ## Run e2e tests against EKS. V=1 for verbose. RUN= to filter. @@ -145,6 +146,9 @@ e2e-eks: ## Run e2e tests against EKS. V=1 for verbose. RUN= to filter. E2E_REGISTRY_HOST="$(EKS_REGISTRY_HOST)" \ E2E_REGISTRY_USER="$(EKS_REGISTRY_USER)" \ E2E_REGISTRY_PASSWORD="$(EKS_REGISTRY_PASSWORD)" \ + $(if $(RELEASED_OPERATOR_TAG),E2E_OPERATOR_RELEASE_TAG=$(RELEASED_OPERATOR_TAG)) \ + $(if $(RELEASED_OPERATOR_IMG),E2E_OPERATOR_RELEASED_IMG=$(RELEASED_OPERATOR_IMG)) \ + $(if $(EKS_IMAGE_PULL_SECRET),E2E_IMAGE_PULL_SECRET=$(EKS_IMAGE_PULL_SECRET)) \ ARTIFACTS="$(ARTIFACTS)" \ go test -timeout 30m -count=1 -parallel 2 $(if $(V),-v) $(if $(RUN),-run '$(RUN)') . From e24d1f50252a721c3fc9888787e515d2b99e536c Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Tue, 20 Oct 2026 10:54:39 +0000 Subject: [PATCH 3/7] helm: set nameOverride to fix OCI chart naming The Konflux build pipeline packages the chart as bootc-operator-chart, causing the Helm fullname template to produce bootc-operator-bootc-operator-chart instead of bootc-operator. Setting nameOverride ensures consistent resource names regardless of the OCI artifact name. Assisted-by: AI Signed-off-by: Alice Frosi --- chart/bootc-operator/values.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/chart/bootc-operator/values.yaml b/chart/bootc-operator/values.yaml index 9aaacc54..383c3705 100644 --- a/chart/bootc-operator/values.yaml +++ b/chart/bootc-operator/values.yaml @@ -1,3 +1,5 @@ +nameOverride: bootc-operator + crds: install: true From 408f020a9e81eb097b8fed9d33f7abc44cfb2754 Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Tue, 20 Oct 2026 11:53:29 +0000 Subject: [PATCH 4/7] e2e: use helm upgrade --install for operator restore The upgrade test cleanup uses helm upgrade to restore the operator after the test. If the test fails during uninstall (e.g. CRD deletion timeout), the Helm release no longer exists and a plain helm upgrade fails, leaving the operator down for subsequent tests. Adding --install allows the cleanup to recover from a fully uninstalled state, preventing cascading failures. Assisted-by: AI Signed-off-by: Alice Frosi --- test/e2e/upgrade_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/upgrade_test.go b/test/e2e/upgrade_test.go index b78910bd..50bf90de 100644 --- a/test/e2e/upgrade_test.go +++ b/test/e2e/upgrade_test.go @@ -190,7 +190,7 @@ func helmInstallOperator(t *testing.T, chartPath, img string, extraArgs []string func helmUpgradeOperator(t *testing.T, chartPath, img string, extraArgs []string) { t.Helper() args := []string{ - "upgrade", helmReleaseName, chartPath, + "upgrade", "--install", helmReleaseName, chartPath, "--namespace", testutil.OperatorNamespaceName, } args = append(args, helmImageArgs(t, img, extraArgs)...) From fcf86856e6249cce1ea919fa9eb5ba1acaa014dd Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Tue, 20 Oct 2026 13:59:13 +0000 Subject: [PATCH 5/7] e2e: build helm chart dependencies before install in upgrade test Run helm dependency build before helm install so the CRDs subchart is available. Update uninstallOperator comment to reflect that CRDs are removed together with the main release. Assisted-by: AI Signed-off-by: Alice Frosi --- test/e2e/upgrade_test.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/e2e/upgrade_test.go b/test/e2e/upgrade_test.go index 50bf90de..80fea605 100644 --- a/test/e2e/upgrade_test.go +++ b/test/e2e/upgrade_test.go @@ -126,10 +126,10 @@ func TestOperatorUpgrade(t *testing.T) { Should(poolAllUpdated(1, env.NodeImageUpdateDigest())) } -// uninstallOperator removes the operator via Helm uninstall, then -// deletes CRDs (which Helm does not manage on uninstall). Custom -// resources are deleted first while the operator is still running so -// it can handle finalizer removal. +// uninstallOperator removes the operator. Custom resources are deleted +// first while the operator is still running so it can handle finalizer +// removal. CRDs are bundled as a subchart dependency so they are +// removed together with the main release. func uninstallOperator( t *testing.T, g Gomega, @@ -152,7 +152,7 @@ func uninstallOperator( }).WithTimeout(2*time.Minute).Should(Succeed(), "expected all custom resources to be deleted") - t.Logf("Uninstalling Helm release...") + t.Logf("Uninstalling Helm releases...") helmRun(t, "uninstall", helmReleaseName, "--namespace", testutil.OperatorNamespaceName) @@ -177,6 +177,7 @@ func uninstallOperator( // helmInstallOperator installs the operator via helm install. func helmInstallOperator(t *testing.T, chartPath, img string, extraArgs []string) { t.Helper() + helmRun(t, "dependency", "build", chartPath) args := []string{ "install", helmReleaseName, chartPath, "--namespace", testutil.OperatorNamespaceName, From c59674cb52596cbfb0310c7b672de699b8d0acf1 Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Tue, 20 Oct 2026 14:50:02 +0000 Subject: [PATCH 6/7] e2e: use imageMatchesDigest in upgrade test On EKS, bootc status reports the platform-specific content digest in ImageDigest and the manifest-list digest in the Image pullspec. The direct ImageDigest check fails when these differ. Use the imageMatchesDigest helper which accepts both, matching what the controller does via InfoMatchesDigest. Assisted-by: AI Signed-off-by: Alice Frosi --- test/e2e/upgrade_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/upgrade_test.go b/test/e2e/upgrade_test.go index 80fea605..77c94a4d 100644 --- a/test/e2e/upgrade_test.go +++ b/test/e2e/upgrade_test.go @@ -117,7 +117,7 @@ func TestOperatorUpgrade(t *testing.T) { t.Logf("Patched pool to update image %s", updateRef) testutil.WaitForNodeIdle(t, g, ctx, env.Client, nodeName, 5*time.Minute, - HaveField("Booted", HaveField("ImageDigest", env.NodeImageUpdateDigest())), + HaveField("Booted", imageMatchesDigest(env.NodeImageUpdateDigest())), ) t.Logf("Node %q completed update with upgraded operator", nodeName) From bfc64934bac3e4ada58c3a30f97085c0b45a690d Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Thu, 22 Oct 2026 09:07:03 +0000 Subject: [PATCH 7/7] e2e: uninstall standalone CRDs release in upgrade test On EKS CI, the Konflux pipeline publishes the operator and CRDs as separate OCI Helm charts. The deploy script (test_deploy.py) installs them as two independent releases: bootc-operator-crds and bootc-operator (with crds.install=false). The upgrade test only ran helm uninstall on the main release, leaving the CRDs behind and timing out waiting for them to be deleted. Check whether a standalone CRDs release exists before uninstalling. On bink (where CRDs are bundled as a subchart in a single release) the check returns false and the extra uninstall is skipped. Assisted-by: AI Signed-off-by: Alice Frosi --- test/e2e/upgrade_test.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/e2e/upgrade_test.go b/test/e2e/upgrade_test.go index 77c94a4d..da7ff675 100644 --- a/test/e2e/upgrade_test.go +++ b/test/e2e/upgrade_test.go @@ -153,8 +153,15 @@ func uninstallOperator( "expected all custom resources to be deleted") t.Logf("Uninstalling Helm releases...") + crdsRelease := helmReleaseName + "-crds" + hasCRDsRelease := helmReleaseExists(t, crdsRelease) helmRun(t, "uninstall", helmReleaseName, "--namespace", testutil.OperatorNamespaceName) + if hasCRDsRelease { + t.Logf("Uninstalling standalone CRDs release...") + helmRun(t, "uninstall", crdsRelease, + "--namespace", testutil.OperatorNamespaceName) + } g.Eventually(func(g Gomega) { var d appsv1.Deployment @@ -220,6 +227,28 @@ func helmImageArgs(t *testing.T, img string, extraArgs []string) []string { return args } +// helmReleaseExists returns true if the named Helm release exists in +// the operator namespace. Any error other than "release: not found" +// fails the test. +func helmReleaseExists(t *testing.T, name string) bool { + t.Helper() + args := []string{"status", name, + "--namespace", testutil.OperatorNamespaceName} + if kc := os.Getenv("KUBECONFIG"); kc != "" { + args = append([]string{"--kubeconfig", kc}, args...) + } + cmd := exec.Command("helm", args...) + out, err := cmd.CombinedOutput() + if err == nil { + return true + } + if strings.Contains(string(out), "release: not found") { + return false + } + t.Fatalf("helm status %s failed: %v\n%s", name, err, out) + return false +} + // helmRun executes a helm command, adding --kubeconfig if set. func helmRun(t *testing.T, args ...string) { t.Helper()