Skip to content

Commit 56dddb8

Browse files
pedjakclaude
andcommitted
Migrate operator upgrade e2e tests to Godog/Cucumber BDD framework
Replace testify-based upgrade tests with a Godog test runner and Gherkin feature file. Add step definitions for OLM install/upgrade, component readiness via leader election leases, and reconciliation verification. Simplify Makefile upgrade targets using a reusable install script macro and fix template path resolution so tests work from any directory. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent f19c8c9 commit 56dddb8

12 files changed

Lines changed: 579 additions & 632 deletions

Makefile

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,17 @@ verify-crd-compatibility: $(CRD_DIFF) manifests
240240

241241
#SECTION Test
242242

243+
define install-sh
244+
.PHONY: $(1)/install.sh
245+
$(1)/install.sh: manifests
246+
@echo -e "\n\U1F4D8 Using $(1).yaml as source manifest\n"
247+
sed "s/cert-git-version/cert-$$(VERSION)/g" manifests/$(1).yaml > $(2)
248+
MANIFEST=$(2) INSTALL_DEFAULT_CATALOGS=false DEFAULT_CATALOG=$$(RELEASE_CATALOGS) envsubst '$$$$DEFAULT_CATALOG,$$$$CERT_MGR_VERSION,$$$$INSTALL_DEFAULT_CATALOGS,$$$$MANIFEST' < scripts/install.tpl.sh > $(1)-install.sh
249+
endef
250+
251+
$(eval $(call install-sh,experimental,operator-controller-experimental.yaml))
252+
$(eval $(call install-sh,standard,operator-controller-standard.yaml))
253+
243254
.PHONY: test
244255
test: manifests generate fmt lint test-unit test-e2e test-regression #HELP Run all tests.
245256

@@ -343,52 +354,43 @@ run-latest-release:
343354
@echo -e "\n\U23EC Using $(RELEASE_INSTALL) as release installer\n"
344355
curl -L -s https://github.com/operator-framework/operator-controller/releases/latest/download/$(notdir $(RELEASE_INSTALL)) | bash -s
345356

346-
.PHONY: pre-upgrade-setup
347-
pre-upgrade-setup:
348-
./hack/test/pre-upgrade-setup.sh $(CATALOG_IMG) $(TEST_CLUSTER_CATALOG_NAME) $(TEST_CLUSTER_EXTENSION_NAME)
349-
350-
.PHONY: post-upgrade-checks
351-
post-upgrade-checks:
352-
go test -count=1 -v ./test/upgrade-e2e/...
357+
.PHONY: test-upgrade-e2e
358+
test-upgrade-e2e:
359+
RELEASE_INSTALL=$(RELEASE_INSTALL) \
360+
RELEASE_UPGRADE=$(RELEASE_UPGRADE) \
361+
KIND_CLUSTER_NAME=$(KIND_CLUSTER_NAME) \
362+
ROOT_DIR=$(ROOT_DIR) \
363+
go test -count=1 -v ./test/upgrade-e2e/upgrade_test.go
353364

354365

355-
TEST_UPGRADE_E2E_TASKS := kind-cluster run-latest-release image-registry pre-upgrade-setup docker-build kind-load kind-deploy post-upgrade-checks kind-clean
366+
TEST_UPGRADE_E2E_TASKS := kind-cluster docker-build kind-load test-upgrade-e2e kind-clean
356367

357368
.PHONY: test-upgrade-st2st-e2e
358-
test-upgrade-st2st-e2e: SOURCE_MANIFEST := $(STANDARD_MANIFEST)
359-
test-upgrade-st2st-e2e: RELEASE_INSTALL := $(STANDARD_RELEASE_INSTALL)
369+
test-upgrade-st2st-e2e: RELEASE_INSTALL := https://github.com/operator-framework/operator-controller/releases/latest/download/install.sh
370+
test-upgrade-st2st-e2e: RELEASE_UPGRADE := $(ROOT_DIR)/standard-install.sh
360371
test-upgrade-st2st-e2e: KIND_CLUSTER_NAME := operator-controller-upgrade-st2st-e2e
361-
test-upgrade-st2st-e2e: export MANIFEST := $(STANDARD_RELEASE_MANIFEST)
362-
test-upgrade-st2st-e2e: export TEST_CLUSTER_CATALOG_NAME := test-catalog
363-
test-upgrade-st2st-e2e: export TEST_CLUSTER_EXTENSION_NAME := test-package
364-
test-upgrade-st2st-e2e: $(TEST_UPGRADE_E2E_TASKS) #HELP Run upgrade (standard -> standard) e2e tests on a local kind cluster
372+
test-upgrade-st2st-e2e: standard/install.sh $(TEST_UPGRADE_E2E_TASKS) #HELP Run upgrade (standard -> standard) e2e tests on a local kind cluster
365373

366374
.PHONY: test-upgrade-ex2ex-e2e
367-
test-upgrade-ex2ex-e2e: SOURCE_MANIFEST := $(EXPERIMENTAL_MANIFEST)
368-
test-upgrade-ex2ex-e2e: RELEASE_INSTALL := $(EXPERIMENTAL_RELEASE_INSTALL)
375+
test-upgrade-ex2ex-e2e: RELEASE_INSTALL := https://github.com/operator-framework/operator-controller/releases/latest/download/install-experimental.sh
369376
test-upgrade-ex2ex-e2e: KIND_CLUSTER_NAME := operator-controller-upgrade-ex2ex-e2e
370-
test-upgrade-ex2ex-e2e: export MANIFEST := $(EXPERIMENTAL_RELEASE_MANIFEST)
371-
test-upgrade-ex2ex-e2e: export TEST_CLUSTER_CATALOG_NAME := test-catalog
372-
test-upgrade-ex2ex-e2e: export TEST_CLUSTER_EXTENSION_NAME := test-package
373-
test-upgrade-ex2ex-e2e: $(TEST_UPGRADE_E2E_TASKS) #HELP Run upgrade (experimental -> experimental) e2e tests on a local kind cluster
377+
test-upgrade-ex2ex-e2e: RELEASE_UPGRADE := $(ROOT_DIR)/experimental-install.sh
378+
test-upgrade-ex2ex-e2e: experimental/install.sh $(TEST_UPGRADE_E2E_TASKS) #HELP Run upgrade (experimental -> experimental) e2e tests on a local kind cluster
374379

375380
.PHONY: test-upgrade-st2ex-e2e
376-
test-upgrade-st2ex-e2e: SOURCE_MANIFEST := $(EXPERIMENTAL_MANIFEST)
377-
test-upgrade-st2ex-e2e: RELEASE_INSTALL := $(STANDARD_RELEASE_INSTALL)
381+
test-upgrade-st2ex-e2e: RELEASE_INSTALL := https://github.com/operator-framework/operator-controller/releases/latest/download/install.sh
382+
test-upgrade-st2ex-e2e: RELEASE_UPGRADE := $(ROOT_DIR)/experimental-install.sh
378383
test-upgrade-st2ex-e2e: KIND_CLUSTER_NAME := operator-controller-upgrade-st2ex-e2e
379-
test-upgrade-st2ex-e2e: export MANIFEST := $(EXPERIMENTAL_RELEASE_MANIFEST)
380-
test-upgrade-st2ex-e2e: export TEST_CLUSTER_CATALOG_NAME := test-catalog
381-
test-upgrade-st2ex-e2e: export TEST_CLUSTER_EXTENSION_NAME := test-package
382-
test-upgrade-st2ex-e2e: $(TEST_UPGRADE_E2E_TASKS) #HELP Run upgrade (standard -> experimental) e2e tests on a local kind cluster
384+
test-upgrade-st2ex-e2e: experimental/install.sh $(TEST_UPGRADE_E2E_TASKS) #HELP Run upgrade (standard -> experimental) e2e tests on a local kind cluster
383385

384386
.PHONY: test-st2ex-e2e
385-
test-st2ex-e2e: SOURCE_MANIFEST := $(STANDARD_MANIFEST)
386-
test-st2ex-e2e: RELEASE_INSTALL := $(STANDARD_RELEASE_INSTALL)
387+
test-st2ex-e2e: RELEASE_INSTALL := $(ROOT_DIR)/standard-install.sh
388+
test-st2ex-e2e: RELEASE_UPGRADE := $(ROOT_DIR)/experimental-install.sh
387389
test-st2ex-e2e: KIND_CLUSTER_NAME := operator-controller-st2ex-e2e
388390
test-st2ex-e2e: export MANIFEST := $(STANDARD_RELEASE_MANIFEST)
389391
test-st2ex-e2e: export TEST_CLUSTER_CATALOG_NAME := test-catalog
390392
test-st2ex-e2e: export TEST_CLUSTER_EXTENSION_NAME := test-package
391-
test-st2ex-e2e: run-internal image-registry pre-upgrade-setup kind-deploy-experimental post-upgrade-checks kind-clean #HELP Run swichover (standard -> experimental) e2e tests on a local kind cluster
393+
test-st2ex-e2e: experimental/install.sh standard/install.sh $(TEST_UPGRADE_E2E_TASKS) #HELP Run swichover (standard -> experimental) e2e tests on a local kind cluster
392394

393395
.PHONY: e2e-coverage
394396
e2e-coverage:

hack/test/pre-upgrade-setup.sh

Lines changed: 0 additions & 172 deletions
This file was deleted.

test/e2e/README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,14 @@ test/e2e/
3333
├── steps.go # Step definition implementations
3434
├── hooks.go # Test hooks and scenario context
3535
└── testdata/ # Test data (RBAC templates, catalogs)
36-
├── rbac-template.yaml
36+
├── serviceaccount-template.yaml
37+
├── olm-sa-helm-rbac-template.yaml
38+
├── olm-sa-boxcutter-rbac-template.yaml
39+
├── pvc-probe-sa-boxcutter-rbac-template.yaml
3740
├── cluster-admin-rbac-template.yaml
3841
├── metrics-reader-rbac-template.yaml
3942
├── test-catalog-template.yaml
40-
├── extra-catalog-template.yaml
41-
└── ...
43+
└── extra-catalog-template.yaml
4244
```
4345

4446
## Architecture

test/e2e/steps/hooks.go

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,12 @@ type scenarioContext struct {
3131
namespace string
3232
clusterExtensionName string
3333
clusterExtensionRevisionName string
34+
clusterCatalogName string
35+
addedResources []resource
3436
removedResources []unstructured.Unstructured
3537
backGroundCmds []*exec.Cmd
3638
metricsResponse map[string]string
39+
leaderPods map[string]string // component name -> leader pod name
3740

3841
extensionObjects []client.Object
3942
}
@@ -89,30 +92,37 @@ func RegisterHooks(sc *godog.ScenarioContext) {
8992
sc.After(ScenarioCleanup)
9093
}
9194

92-
func BeforeSuite() {
93-
if devMode {
94-
logger = textlogger.NewLogger(textlogger.NewConfig(textlogger.Verbosity(1)))
95-
} else {
96-
logger = textlogger.NewLogger(textlogger.NewConfig())
97-
}
98-
95+
func detectOLMDeployment() (*appsv1.Deployment, error) {
9996
raw, err := k8sClient("get", "deployments", "-A", "-l", "app.kubernetes.io/part-of=olm", "-o", "jsonpath={.items}")
10097
if err != nil {
101-
panic(fmt.Errorf("failed to get OLM deployments: %v", err))
98+
return nil, err
10299
}
103100
dl := []appsv1.Deployment{}
104101
if err := json.Unmarshal([]byte(raw), &dl); err != nil {
105-
panic(fmt.Errorf("failed to unmarshal OLM deployments: %v", err))
102+
return nil, fmt.Errorf("failed to unmarshal OLM deployments: %v", err)
106103
}
107-
var olm *appsv1.Deployment
108104

109105
for _, d := range dl {
110106
if d.Name == olmDeploymentName {
111-
olm = &d
112-
olmNamespace = d.Namespace
113-
break
107+
return &d, nil
114108
}
115109
}
110+
return nil, fmt.Errorf("failed to detect OLM Deployment")
111+
}
112+
113+
func BeforeSuite() {
114+
if devMode {
115+
logger = textlogger.NewLogger(textlogger.NewConfig(textlogger.Verbosity(1)))
116+
} else {
117+
logger = textlogger.NewLogger(textlogger.NewConfig())
118+
}
119+
120+
olm, err := detectOLMDeployment()
121+
if err != nil {
122+
logger.Info("OLM deployments not found; skipping feature gate detection (upgrade scenarios will install OLM in Background)")
123+
return
124+
}
125+
olmNamespace = olm.Namespace
116126

117127
featureGatePattern := regexp.MustCompile(`--feature-gates=([[:alnum:]]+)=(true|false)`)
118128
for _, c := range olm.Spec.Template.Spec.Containers {
@@ -147,6 +157,7 @@ func CreateScenarioContext(ctx context.Context, sc *godog.Scenario) (context.Con
147157
namespace: fmt.Sprintf("ns-%s", sc.Id),
148158
clusterExtensionName: fmt.Sprintf("ce-%s", sc.Id),
149159
clusterExtensionRevisionName: fmt.Sprintf("cer-%s", sc.Id),
160+
leaderPods: make(map[string]string),
150161
}
151162
return context.WithValue(ctx, scenarioContextKey, scCtx), nil
152163
}
@@ -174,7 +185,7 @@ func ScenarioCleanup(ctx context.Context, _ *godog.Scenario, err error) (context
174185
return ctx, err
175186
}
176187

177-
forDeletion := []resource{}
188+
forDeletion := sc.addedResources
178189
if sc.clusterExtensionName != "" {
179190
forDeletion = append(forDeletion, resource{name: sc.clusterExtensionName, kind: "clusterextension"})
180191
}

0 commit comments

Comments
 (0)