Skip to content

Commit eb20885

Browse files
Merge pull request #707 from openshift-bot/synchronize-upstream
NO-ISSUE: Synchronize From Upstream Repositories
2 parents 9b9eb03 + 6362918 commit eb20885

992 files changed

Lines changed: 32296 additions & 300224 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Makefile

Lines changed: 12 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -254,26 +254,20 @@ $(eval $(call install-sh,standard,operator-controller-standard.yaml))
254254
.PHONY: test
255255
test: manifests generate fmt lint test-unit test-e2e test-regression #HELP Run all tests.
256256

257-
E2E_TIMEOUT ?= 10m
257+
E2E_TIMEOUT ?= 15m
258+
GODOG_ARGS ?=
258259
.PHONY: e2e
259260
e2e: #EXHELP Run the e2e tests.
260-
go test -count=1 -v ./test/e2e/features_test.go -timeout=$(E2E_TIMEOUT)
261+
go test -count=1 -v ./test/e2e/features_test.go -timeout=$(E2E_TIMEOUT) $(if $(GODOG_ARGS),-args $(GODOG_ARGS))
261262

262-
E2E_REGISTRY_NAME := docker-registry
263-
E2E_REGISTRY_NAMESPACE := operator-controller-e2e
264-
265-
export REG_PKG_NAME := registry-operator
266-
export CLUSTER_REGISTRY_HOST := $(E2E_REGISTRY_NAME).$(E2E_REGISTRY_NAMESPACE).svc:5000
267-
export LOCAL_REGISTRY_HOST := localhost:30000
268-
export E2E_TEST_CATALOG_V1 := e2e/test-catalog:v1
269-
export E2E_TEST_CATALOG_V2 := e2e/test-catalog:v2
270-
export CATALOG_IMG := $(CLUSTER_REGISTRY_HOST)/$(E2E_TEST_CATALOG_V1)
263+
export CLUSTER_REGISTRY_HOST := docker-registry.operator-controller-e2e.svc:5000
271264
.PHONY: extension-developer-e2e
272-
extension-developer-e2e: $(OPERATOR_SDK) $(KUSTOMIZE) #EXHELP Run extension create, upgrade and delete tests.
273-
test/extension-developer-e2e/setup.sh $(OPERATOR_SDK) $(CONTAINER_RUNTIME) $(KUSTOMIZE) ${LOCAL_REGISTRY_HOST} ${CLUSTER_REGISTRY_HOST}
265+
extension-developer-e2e: export OPERATOR_SDK := $(OPERATOR_SDK)
266+
extension-developer-e2e: export CONTAINER_RUNTIME := $(CONTAINER_RUNTIME)
267+
extension-developer-e2e: $(OPERATOR_SDK) #EXHELP Run extension create, upgrade and delete tests.
274268
go test -count=1 -v ./test/extension-developer-e2e/...
275269

276-
UNIT_TEST_DIRS := $(shell go list ./... | grep -vE "/test/|/testutils")
270+
UNIT_TEST_DIRS := $(shell go list ./... | grep -vE "/test/|/testutils") $(shell go list ./test/internal/...)
277271
COVERAGE_UNIT_DIR := $(ROOT_DIR)/coverage/unit
278272

279273
.PHONY: envtest-k8s-bins #HELP Uses setup-envtest to download and install the binaries required to run ENVTEST-test based locally at the project/bin directory.
@@ -298,18 +292,6 @@ test-regression: #HELP Run regression test
298292
rm -rf $(COVERAGE_REGRESSION_DIR) && mkdir -p $(COVERAGE_REGRESSION_DIR)
299293
go test -count=1 -v ./test/regression/... -cover -coverprofile ${ROOT_DIR}/coverage/regression.out -test.gocoverdir=$(COVERAGE_REGRESSION_DIR)
300294

301-
.PHONY: image-registry
302-
E2E_REGISTRY_IMAGE=localhost/e2e-test-registry:devel
303-
image-registry: export GOOS=linux
304-
image-registry: export GOARCH=amd64
305-
image-registry: ## Build the testdata catalog used for e2e tests and push it to the image registry
306-
# Use double quotes (not single quotes) for build flags like -ldflags, -tags, etc.
307-
# Single quotes are passed literally and not stripped by `go build`, which can cause errors
308-
# or inject unintended characters into the binary (e.g., version metadata).
309-
go build $(GO_BUILD_FLAGS) $(GO_BUILD_EXTRA_FLAGS) -tags '$(GO_BUILD_TAGS)' -ldflags "$(GO_BUILD_LDFLAGS)" -gcflags '$(GO_BUILD_GCFLAGS)' -asmflags '$(GO_BUILD_ASMFLAGS)' -o ./testdata/push/bin/push ./testdata/push/push.go
310-
$(CONTAINER_RUNTIME) build -f ./testdata/Dockerfile -t $(E2E_REGISTRY_IMAGE) ./testdata
311-
$(KIND) load docker-image $(E2E_REGISTRY_IMAGE) --name $(KIND_CLUSTER_NAME)
312-
./testdata/build-test-registry.sh $(E2E_REGISTRY_NAMESPACE) $(E2E_REGISTRY_NAME) $(E2E_REGISTRY_IMAGE)
313295

314296
# When running the e2e suite, you can set the ARTIFACT_PATH variable to the absolute path
315297
# of the directory for the operator-controller e2e tests to store the artifacts, which
@@ -323,7 +305,7 @@ test-e2e: GO_BUILD_EXTRA_FLAGS := -cover
323305
test-e2e: COVERAGE_NAME := e2e
324306
test-e2e: export MANIFEST := $(STANDARD_RELEASE_MANIFEST)
325307
test-e2e: export INSTALL_DEFAULT_CATALOGS := false
326-
test-e2e: run-internal image-registry prometheus e2e e2e-coverage kind-clean #HELP Run e2e test suite on local kind cluster
308+
test-e2e: run-internal prometheus e2e e2e-coverage kind-clean #HELP Run e2e test suite on local kind cluster
327309

328310
.PHONY: test-experimental-e2e
329311
test-experimental-e2e: SOURCE_MANIFEST := $(EXPERIMENTAL_E2E_MANIFEST)
@@ -334,8 +316,8 @@ test-experimental-e2e: COVERAGE_NAME := experimental-e2e
334316
test-experimental-e2e: export MANIFEST := $(EXPERIMENTAL_RELEASE_MANIFEST)
335317
test-experimental-e2e: export INSTALL_DEFAULT_CATALOGS := false
336318
test-experimental-e2e: PROMETHEUS_VALUES := helm/prom_experimental.yaml
337-
test-experimental-e2e: E2E_TIMEOUT := 15m
338-
test-experimental-e2e: run-internal image-registry prometheus e2e e2e-coverage kind-clean #HELP Run experimental e2e test suite on local kind cluster
319+
test-experimental-e2e: E2E_TIMEOUT := 20m
320+
test-experimental-e2e: run-internal prometheus e2e e2e-coverage kind-clean #HELP Run experimental e2e test suite on local kind cluster
339321

340322
.PHONY: prometheus
341323
prometheus: PROMETHEUS_NAMESPACE := olmv1-system
@@ -352,7 +334,7 @@ test-extension-developer-e2e: SOURCE_MANIFEST := $(STANDARD_E2E_MANIFEST)
352334
test-extension-developer-e2e: KIND_CLUSTER_NAME := operator-controller-ext-dev-e2e
353335
test-extension-developer-e2e: export INSTALL_DEFAULT_CATALOGS := false
354336
test-extension-developer-e2e: export MANIFEST := $(STANDARD_RELEASE_MANIFEST)
355-
test-extension-developer-e2e: run-internal image-registry extension-developer-e2e kind-clean #HELP Run extension-developer e2e on local kind cluster
337+
test-extension-developer-e2e: run-internal extension-developer-e2e kind-clean #HELP Run extension-developer e2e on local kind cluster
356338

357339
.PHONY: run-latest-release
358340
run-latest-release:
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# E2E Test Isolation: Per-Scenario Catalogs via Dynamic OCI Image Building
2+
3+
## Problem
4+
5+
E2E test scenarios previously shared cluster-scoped resources (ClusterCatalogs, CRDs, packages),
6+
causing cascading failures when one scenario left state behind. Parallelism was impossible because
7+
scenarios conflicted on shared resource names.
8+
9+
## Solution
10+
11+
Each scenario dynamically builds and pushes its own bundle and catalog OCI images at test time,
12+
parameterized by scenario ID. All cluster-scoped resource names include the scenario ID, making
13+
conflicts structurally impossible.
14+
15+
```
16+
Scenario starts
17+
-> Generate parameterized bundle manifests (CRD names, deployments, etc. include scenario ID)
18+
-> Build + push bundle OCI images to e2e registry via go-containerregistry
19+
-> Generate FBC catalog config referencing those bundle image refs
20+
-> Build + push catalog OCI image to e2e registry
21+
-> Create ClusterCatalog pointing at the catalog image
22+
-> Run scenario steps
23+
-> Cleanup all resources (including catalog)
24+
```
25+
26+
### Key Properties
27+
28+
- Every cluster-scoped resource name includes the scenario ID -- no conflicts by construction.
29+
- Failed scenario state is preserved for debugging without affecting other scenarios.
30+
- Parallelism (`Concurrency > 1`) is safe without further changes.
31+
- Adding new scenarios requires zero coordination with existing ones.
32+
33+
## Builder API (`test/internal/catalog/`)
34+
35+
Bundles are defined as components of a catalog. A single `Build()` call builds and pushes
36+
all bundle images, generates the FBC, and pushes the catalog image:
37+
38+
```go
39+
cat := catalog.NewCatalog("test", scenarioID,
40+
catalog.WithPackage("test",
41+
catalog.Bundle("1.0.0", catalog.WithCRD(), catalog.WithDeployment(), catalog.WithConfigMap()),
42+
catalog.Bundle("1.2.0", catalog.WithCRD(), catalog.WithDeployment()),
43+
catalog.Channel("beta", catalog.Entry("1.0.0"), catalog.Entry("1.2.0")),
44+
),
45+
)
46+
result, err := cat.Build(ctx, "v1", localRegistry, clusterRegistry)
47+
// result.CatalogName = "test-catalog-{scenarioID}"
48+
// result.CatalogImageRef = "{clusterRegistry}/e2e/test-catalog-{scenarioID}:v1"
49+
// result.PackageNames = {"test": "test-{scenarioID}"}
50+
```
51+
52+
### Bundle Options
53+
54+
- `WithCRD()` -- CRD with group `e2e-{id}.e2e.operatorframework.io`
55+
- `WithDeployment()` -- Deployment named `test-operator-{id}` (includes CSV, script ConfigMap, NetworkPolicy)
56+
- `WithConfigMap()` -- additional test ConfigMap
57+
- `WithInstallMode(modes...)` -- sets supported install modes on the CSV
58+
- `WithLargeCRD(fieldCount)` -- CRD with many fields for large bundle testing
59+
- `WithClusterRegistry(host)` -- overrides the cluster-side registry host (for mirror testing)
60+
- `StaticBundleDir(dir)` -- reads pre-built bundle manifests without parameterization (e.g. webhook-operator)
61+
- `BadImage()` -- uses an invalid container image to trigger ImagePullBackOff
62+
- `WithBundleProperty(type, value)` -- adds a property to bundle metadata
63+
64+
## Feature File Conventions
65+
66+
Feature files define catalogs inline via data tables:
67+
68+
```gherkin
69+
Background:
70+
Given OLM is available
71+
And an image registry is available
72+
And a catalog "test" with packages:
73+
| package | version | channel | replaces | contents |
74+
| test | 1.0.0 | alpha | | CRD, Deployment, ConfigMap |
75+
| test | 1.0.1 | alpha | 1.0.0 | CRD, Deployment, ConfigMap |
76+
| test | 1.2.0 | beta | | CRD, Deployment |
77+
```
78+
79+
### Variable Substitution
80+
81+
Templates in feature file YAML use these variables:
82+
83+
| Variable | Expansion | Example |
84+
|----------|-----------|---------|
85+
| `${NAME}` | ClusterExtension name | `ce-abc123` |
86+
| `${TEST_NAMESPACE}` | Scenario namespace | `ns-abc123` |
87+
| `${SCENARIO_ID}` | Unique scenario identifier | `abc123` |
88+
| `${PACKAGE:<name>}` | Parameterized package name | `test-abc123` |
89+
| `${CATALOG:<name>}` | ClusterCatalog resource name | `test-catalog-abc123` |
90+
| `${COS_NAME}` | ClusterObjectSet name | `cos-abc123` |
91+
92+
### Naming Conventions
93+
94+
| Resource | Pattern |
95+
|----------|---------|
96+
| CRD group | `e2e-{id}.e2e.operatorframework.io` |
97+
| Deployment | `test-operator-{id}` |
98+
| Package name (FBC) | `{package}-{id}` |
99+
| Bundle image | `{registry}/bundles/{package}-{id}:v{version}` |
100+
| Catalog image | `{registry}/e2e/{name}-catalog-{id}:{tag}` |
101+
| ClusterCatalog | `{name}-catalog-{id}` |
102+
| Namespace | `ns-{id}` |
103+
| ClusterExtension | `ce-{id}` |
104+
105+
## Registry Access
106+
107+
An in-cluster OCI registry (`test/internal/registry/`) stores bundle and catalog images.
108+
The registry runs as a ClusterIP Service; there is no NodePort or kind `extraPortMappings`.
109+
110+
The test runner reaches the registry via **Kubernetes port-forward** (SPDY through the API
111+
server), which works regardless of the cluster's network topology. A `sync.OnceValues` in the
112+
step definitions starts the port-forward once and returns the dynamically assigned
113+
`localhost:<port>` address used for all `crane.Push` / `crane.Tag` calls.
114+
115+
In-cluster components (e.g. the catalog unpacker) pull images using the Service DNS name
116+
(`docker-registry.operator-controller-e2e.svc.cluster.local:5000`), resolved by CoreDNS.
117+
Containerd on the node is never involved because the registry only holds OCI artifacts
118+
consumed by Go code, not container images for pods.

go.mod

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ require (
3131
github.com/stretchr/testify v1.11.1
3232
go.podman.io/image/v5 v5.39.2
3333
golang.org/x/exp v0.0.0-20260209203927-2842357ff358
34-
golang.org/x/mod v0.34.0
34+
golang.org/x/mod v0.35.0
3535
golang.org/x/sync v0.20.0
36-
golang.org/x/tools v0.43.0
36+
golang.org/x/tools v0.44.0
3737
helm.sh/helm/v3 v3.20.2
3838
k8s.io/api v0.35.3
3939
k8s.io/apiextensions-apiserver v0.35.3
@@ -90,6 +90,7 @@ require (
9090
github.com/containerd/typeurl/v2 v2.2.3 // indirect
9191
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect
9292
github.com/containers/ocicrypt v1.2.1 // indirect
93+
github.com/creack/pty v1.1.24 // indirect
9394
github.com/cucumber/gherkin/go/v26 v26.2.0 // indirect
9495
github.com/cucumber/messages/go/v21 v21.0.1 // indirect
9596
github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 // indirect
@@ -141,6 +142,7 @@ require (
141142
github.com/google/gnostic-models v0.7.1 // indirect
142143
github.com/google/uuid v1.6.0 // indirect
143144
github.com/gorilla/mux v1.8.1 // indirect
145+
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
144146
github.com/gosuri/uitable v0.0.4 // indirect
145147
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
146148
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 // indirect
@@ -172,6 +174,7 @@ require (
172174
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
173175
github.com/mitchellh/reflectwalk v1.0.2 // indirect
174176
github.com/moby/locker v1.0.1 // indirect
177+
github.com/moby/spdystream v0.5.1 // indirect
175178
github.com/moby/sys/capability v0.4.0 // indirect
176179
github.com/moby/sys/mountinfo v0.7.2 // indirect
177180
github.com/moby/sys/sequential v0.6.0 // indirect
@@ -182,6 +185,7 @@ require (
182185
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
183186
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
184187
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
188+
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
185189
github.com/nxadm/tail v1.4.11 // indirect
186190
github.com/onsi/gomega v1.39.1 // indirect
187191
github.com/opencontainers/runtime-spec v1.3.0 // indirect
@@ -226,12 +230,12 @@ require (
226230
go.podman.io/storage v1.62.0 // indirect
227231
go.yaml.in/yaml/v2 v2.4.4 // indirect
228232
go.yaml.in/yaml/v3 v3.0.4 // indirect
229-
golang.org/x/crypto v0.49.0 // indirect
230-
golang.org/x/net v0.52.0 // indirect
233+
golang.org/x/crypto v0.50.0 // indirect
234+
golang.org/x/net v0.53.0 // indirect
231235
golang.org/x/oauth2 v0.36.0 // indirect
232-
golang.org/x/sys v0.42.0 // indirect
233-
golang.org/x/term v0.41.0 // indirect
234-
golang.org/x/text v0.35.0 // indirect
236+
golang.org/x/sys v0.43.0 // indirect
237+
golang.org/x/term v0.42.0 // indirect
238+
golang.org/x/text v0.36.0 // indirect
235239
golang.org/x/time v0.15.0 // indirect
236240
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
237241
google.golang.org/genproto v0.0.0-20260209200024-4cfbd4190f57 // indirect

0 commit comments

Comments
 (0)