Repository navigation
Expand file tree
/
Copy pathmigration.mk
More file actions
318 lines (285 loc) · 23.2 KB
/
Copy pathmigration.mk
File metadata and controls
318 lines (285 loc) · 23.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
# Migration-specific build, test, and E2E targets. This file is included by
# the repository Makefile so callers consistently use `make migration/<target>`.
# Output paths for compiled migration CLI binaries.
MIGRATE_OPERATORS_BIN := $(BIN_DIR)/migrate-operators-v0-to-v1
MIGRATE_CATALOGS_BIN := $(BIN_DIR)/migrate-catalogs-v0-to-v1
COVERAGE_DIR := $(ROOT_DIR)/artifacts/coverage
UNIT_COVERAGE_PROFILE := $(COVERAGE_DIR)/unit.out
UNIT_COVERAGE_REPORT := $(COVERAGE_DIR)/unit.txt
E2E_COVERAGE_PROFILE := $(COVERAGE_DIR)/e2e-cli.out
ALL_COVERAGE_PROFILE := $(COVERAGE_DIR)/all.out
E2E_KUBECONFIG ?= $(ROOT_DIR)/.kubeconfig/library-olm-e2e
E2E_TIMEOUT ?= 30m
E2E_ARTIFACTS ?= $(ROOT_DIR)/artifacts/e2e
E2E_COVERAGE_DIR ?= $(E2E_ARTIFACTS)/coverage
E2E_CLUSTER_NAME ?= library-olm-e2e
E2E_FIXTURE_CLUSTER_NAME ?= library-olm-fixture-e2e
E2E_FIXTURE_KUBECONFIG ?= $(ROOT_DIR)/.kubeconfig/library-olm-fixture-e2e
# Pin controller releases used by the E2E cluster. Override only to test a
# compatibility candidate; do not use "latest" in CI.
OLM_V0_VERSION ?= v0.46.0
OLM_V1_VERSION ?= v1.12.0
OLM_V0_CRDS ?= https://github.com/operator-framework/operator-lifecycle-manager/releases/download/$(OLM_V0_VERSION)/crds.yaml
OLM_V0_MANIFEST ?= https://github.com/operator-framework/operator-lifecycle-manager/releases/download/$(OLM_V0_VERSION)/olm.yaml
OLM_V1_INSTALL ?= https://github.com/operator-framework/operator-controller/releases/download/$(OLM_V1_VERSION)/install-experimental.sh
OLM_V1_INSTALL_SHA256 ?= 5c3c86e6d54b21ae7b0b566145ef703f8230e3f4cf4326541d42015a2a195970
E2E_REAL_OPERATOR_MANIFEST ?= $(ROOT_DIR)/test/e2e/migration/real-operator.yaml
E2E_REAL_OPERATOR_NAMESPACE ?= migration-e2e-real
E2E_REAL_OPERATOR_SUBSCRIPTION ?= ecr-secret-operator
E2E_OPERATOR ?= all
E2E_MIGRATION_IMAGE ?= library-olm-migration-e2e:dev
# Retain migration resources after a focused E2E run for manual inspection.
E2E_KEEP_RESOURCES ?= false
##@ Migration
.PHONY: migration/build
migration/build: migration/build-operators migration/build-catalogs ## Build both migration CLI binaries into bin/
.PHONY: migration/build-operators
migration/build-operators: ## Build migrate-operators-v0-to-v1 into bin/
@mkdir -p $(BIN_DIR)
go build -cover -covermode=count -o $(MIGRATE_OPERATORS_BIN) ./migration/examples/cmd/migrate-operators-v0-to-v1
.PHONY: migration/build-catalogs
migration/build-catalogs: ## Build migrate-catalogs-v0-to-v1 into bin/
@mkdir -p $(BIN_DIR)
go build -cover -covermode=count -o $(MIGRATE_CATALOGS_BIN) ./migration/examples/cmd/migrate-catalogs-v0-to-v1
.PHONY: migration/build-e2e-image
migration/build-e2e-image: $(KIND) ## Build and load an uninstrumented migration CLI image into the fixture kind cluster
@mkdir -p $(BIN_DIR)
CGO_ENABLED=0 go build -o $(MIGRATE_OPERATORS_BIN) ./migration/examples/cmd/migrate-operators-v0-to-v1
CGO_ENABLED=0 go build -o $(MIGRATE_CATALOGS_BIN) ./migration/examples/cmd/migrate-catalogs-v0-to-v1
docker build --tag "$(E2E_MIGRATION_IMAGE)" --file test/e2e/migration/migration-tool.Dockerfile .
$(KIND) load docker-image --name "$(E2E_FIXTURE_CLUSTER_NAME)" "$(E2E_MIGRATION_IMAGE)"
.PHONY: migration/test-unit
migration/test-unit: ## Run migration unit tests and write a coverage profile
@mkdir -p $(COVERAGE_DIR)
go test ./migration/... -count=1 -covermode=count -coverprofile=$(UNIT_COVERAGE_PROFILE)
go tool cover -func=$(UNIT_COVERAGE_PROFILE) | tee $(UNIT_COVERAGE_REPORT)
.PHONY: migration/test-verbose
migration/test-verbose: ## Run migration unit tests with verbose output
go test ./migration/... -v -count=1
.PHONY: migration/e2e-setup
migration/e2e-setup: $(KIND) ## Create kind and install pinned OLMv0 and OLMv1 releases
E2E_KUBECONFIG="$(E2E_KUBECONFIG)" E2E_CLUSTER_NAME="$(E2E_CLUSTER_NAME)" KIND="$(KIND)" OLM_V0_CRDS="$(OLM_V0_CRDS)" OLM_V0_MANIFEST="$(OLM_V0_MANIFEST)" OLM_V1_INSTALL="$(OLM_V1_INSTALL)" OLM_V1_INSTALL_SHA256="$(OLM_V1_INSTALL_SHA256)" ./hack/e2e/migration/setup.sh
.PHONY: migration/e2e-fixture-setup
migration/e2e-fixture-setup: $(KIND) $(CRANE) ## Create fixture kind cluster with OLMv0 APIs but no OLMv0 controllers
E2E_KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" E2E_CLUSTER_NAME="$(E2E_FIXTURE_CLUSTER_NAME)" E2E_INSTALL_OLMV0=false KIND="$(KIND)" OLM_V0_CRDS="$(OLM_V0_CRDS)" OLM_V0_MANIFEST="$(OLM_V0_MANIFEST)" OLM_V1_INSTALL="$(OLM_V1_INSTALL)" OLM_V1_INSTALL_SHA256="$(OLM_V1_INSTALL_SHA256)" ./hack/e2e/migration/setup.sh
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" CRANE="$(CRANE)" ./hack/e2e/migration/build-fixture-catalog.sh
.PHONY: migration/e2e-teardown
migration/e2e-teardown: $(KIND) ## Delete the dedicated migration kind cluster
E2E_CLUSTER_NAME="$(E2E_CLUSTER_NAME)" KIND="$(KIND)" ./hack/e2e/migration/teardown.sh
.PHONY: migration/e2e-install-v0
migration/e2e-install-v0: ## Install one migration E2E operator (E2E_OPERATOR=name) or all via OLMv0
@if [[ "$(E2E_OPERATOR)" != all ]]; then \
E2E_OPERATOR="$(E2E_OPERATOR)" KUBECONFIG="$(E2E_KUBECONFIG)" bash -c 'source "$$1"; operator_fields "$$E2E_OPERATOR"' -- ./hack/e2e/migration/operators.sh; \
fi
@for operator in $$(awk -F '\t' -v wanted="$(E2E_OPERATOR)" 'NF==3 && $$1 !~ /^#/ && (wanted=="all" || $$1==wanted) {print $$1}' test/e2e/migration/operators.tsv); do \
KUBECONFIG="$(E2E_KUBECONFIG)" ./hack/e2e/migration/install-v0.sh "$$operator"; \
done
.PHONY: migration/e2e-snapshot-v0
migration/e2e-snapshot-v0: ## Snapshot OLMv0 installs for one migration E2E operator or all
@for operator in $$(awk -F '\t' -v wanted="$(E2E_OPERATOR)" 'NF==3 && $$1 !~ /^#/ && (wanted=="all" || $$1==wanted) {print $$1}' test/e2e/migration/operators.tsv); do \
KUBECONFIG="$(E2E_KUBECONFIG)" ./hack/e2e/migration/snapshot-v0.sh "$$operator"; \
done
.PHONY: migration/e2e-install-fixture-v0
migration/e2e-install-fixture-v0: ## Replay one OLMv0 install snapshot, or all, as fixtures
@for operator in $$(awk -F '\t' -v wanted="$(E2E_OPERATOR)" 'NF==3 && $$1 !~ /^#/ && (wanted=="all" || $$1==wanted) {print $$1}' test/e2e/migration/operators.tsv); do \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/install-fixture-v0.sh "$$operator"; \
done
.PHONY: migration/test-e2e-live-matrix
migration/test-e2e-live-matrix: migration/build ## Install and migrate all three operators from live OLMv0
@set -euo pipefail; \
while IFS=$$'\t' read -r package channel namespace; do \
[[ -z "$$package" || "$$package" == \#* ]] && continue; \
coverage_dir="$(E2E_COVERAGE_DIR)/live/$$package"; \
artifact_dir="$(E2E_ARTIFACTS)/live/$$package"; \
mkdir -p "$$coverage_dir"; \
KUBECONFIG="$(E2E_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$package"; \
KUBECONFIG="$(E2E_KUBECONFIG)" ./hack/e2e/migration/install-v0.sh "$$package"; \
KUBECONFIG="$(E2E_KUBECONFIG)" GOCOVERDIR="$$coverage_dir" E2E_ARTIFACTS="$$artifact_dir" E2E_SUITE=real-operator E2E_NAMESPACE="$$namespace" E2E_SUBSCRIPTION="$$package" go test -count=1 -tags=e2e ./test/e2e/migration -timeout "$(E2E_TIMEOUT)"; \
KUBECONFIG="$(E2E_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$package"; \
done < test/e2e/migration/operators.tsv
.PHONY: migration/test-e2e-live-namespace-delete
migration/test-e2e-live-namespace-delete: migration/build ## Verify acknowledged source-namespace deletion with live OLMv0
@set -euo pipefail; \
package=ecr-secret-operator; \
namespace=migration-e2e-ecr-secret; \
target="$$namespace-target"; \
coverage_dir="$(E2E_COVERAGE_DIR)/live/cross-namespace-delete"; \
artifact_dir="$(E2E_ARTIFACTS)/live/cross-namespace-delete"; \
mkdir -p "$$coverage_dir"; \
KUBECONFIG="$(E2E_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$package"; \
KUBECONFIG="$(E2E_KUBECONFIG)" kubectl delete namespace "$$target" --ignore-not-found --wait=true; \
KUBECONFIG="$(E2E_KUBECONFIG)" ./hack/e2e/migration/install-v0.sh "$$package"; \
KUBECONFIG="$(E2E_KUBECONFIG)" GOCOVERDIR="$$coverage_dir" E2E_ARTIFACTS="$$artifact_dir" E2E_SUITE=real-operator E2E_LIVE_NAMESPACE_DELETE_TEST=true E2E_NAMESPACE="$$namespace" E2E_SUBSCRIPTION="$$package" go test -count=1 -tags=e2e ./test/e2e/migration -run '^TestLiveCrossNamespaceDeletionMigration$$' -timeout "$(E2E_TIMEOUT)"; \
KUBECONFIG="$(E2E_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$package"; \
KUBECONFIG="$(E2E_KUBECONFIG)" kubectl delete namespace "$$target" --ignore-not-found --wait=true
.PHONY: migration/test-e2e-live-batch
# Earlier live scenarios may restore OLMv0 Subscriptions; isolate --all first.
migration/test-e2e-live-batch: migration/build $(KIND) ## Verify four-state batch selection against a live OLMv0 install
@E2E_CLUSTER_NAME="$(E2E_CLUSTER_NAME)" E2E_KUBECONFIG="$(E2E_KUBECONFIG)" KIND="$(KIND)" ./hack/e2e/migration/require-kind-cluster.sh
@set -euo pipefail; \
while IFS=$$'\t' read -r operator channel namespace; do \
[[ -z "$$operator" || "$$operator" == \#* ]] && continue; \
KUBECONFIG="$(E2E_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$operator"; \
KUBECONFIG="$(E2E_KUBECONFIG)" kubectl delete namespace "$$namespace" --ignore-not-found --wait=true; \
done < test/e2e/migration/operators.tsv; \
coverage_dir="$(E2E_COVERAGE_DIR)/live/batch"; mkdir -p "$$coverage_dir"; \
for operator in ecr-secret-operator redis-operator; do \
KUBECONFIG="$(E2E_KUBECONFIG)" ./hack/e2e/migration/install-v0.sh "$$operator"; \
done; \
KUBECONFIG="$(E2E_KUBECONFIG)" GOCOVERDIR="$$coverage_dir" E2E_ARTIFACTS="$(E2E_ARTIFACTS)/live/batch" E2E_SUITE=real-operator E2E_BATCH_TEST=true E2E_NAMESPACE=migration-e2e-ecr-secret E2E_SUBSCRIPTION=ecr-secret-operator E2E_BATCH_SECOND_OPERATOR=redis-operator E2E_BATCH_SECOND_NAMESPACE=migration-e2e-redis go test -count=1 -tags=e2e ./test/e2e/migration -run '^TestBatchSafety$$' -timeout "$(E2E_TIMEOUT)"; \
for operator in ecr-secret-operator redis-operator; do \
KUBECONFIG="$(E2E_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$operator"; \
done
.PHONY: migration/test-e2e-fixture-matrix
migration/test-e2e-fixture-matrix: migration/build ## Replay and migrate all three OLMv0 install snapshots
@set -euo pipefail; \
while IFS=$$'\t' read -r package channel namespace; do \
[[ -z "$$package" || "$$package" == \#* ]] && continue; \
coverage_dir="$(E2E_COVERAGE_DIR)/fixture/$$package"; \
artifact_dir="$(E2E_ARTIFACTS)/fixture/$$package"; \
mkdir -p "$$coverage_dir"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$package"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/install-fixture-v0.sh "$$package"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" GOCOVERDIR="$$coverage_dir" E2E_ARTIFACTS="$$artifact_dir" E2E_SUITE=fixture E2E_NAMESPACE="$$namespace" E2E_SUBSCRIPTION="$$package" go test -count=1 -tags=e2e ./test/e2e/migration -timeout "$(E2E_TIMEOUT)"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$package"; \
done < test/e2e/migration/operators.tsv
.PHONY: migration/test-e2e-batch
migration/test-e2e-batch: migration/build ## Verify four-state batch selection and non-mutating batch preview
@set -euo pipefail; \
package=ecr-secret-operator; \
coverage_dir="$(E2E_COVERAGE_DIR)/fixture/batch"; \
mkdir -p "$$coverage_dir"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$package"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/install-fixture-v0.sh "$$package"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" GOCOVERDIR="$$coverage_dir" E2E_ARTIFACTS="$(E2E_ARTIFACTS)/fixture/batch" E2E_SUITE=fixture E2E_BATCH_TEST=true E2E_NAMESPACE=migration-e2e-ecr-secret E2E_SUBSCRIPTION="$$package" go test -count=1 -tags=e2e ./test/e2e/migration -run '^TestBatchSafety$$' -timeout "$(E2E_TIMEOUT)"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$package"
.PHONY: migration/test-e2e-acceptance
migration/test-e2e-acceptance: migration/build $(KIND) ## Verify remaining fixture acceptance cases with CLI coverage
@E2E_CLUSTER_NAME="$(E2E_FIXTURE_CLUSTER_NAME)" E2E_KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" KIND="$(KIND)" ./hack/e2e/migration/require-kind-cluster.sh
@set -euo pipefail; \
package=ecr-secret-operator; \
for scenario in non-image-source dependents-warning command-name deployment-config; do \
coverage_dir="$(E2E_COVERAGE_DIR)/fixture/acceptance/$$scenario"; \
mkdir -p "$$coverage_dir"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" kubectl delete clusterextension/check --ignore-not-found --wait=true; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" kubectl delete clusterobjectsets -l 'olm.operatorframework.io/owner-name=check' --ignore-not-found --wait=true; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$package"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/install-fixture-v0.sh "$$package"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" GOCOVERDIR="$$coverage_dir" E2E_ARTIFACTS="$(E2E_ARTIFACTS)/fixture/acceptance/$$scenario" E2E_SUITE=fixture E2E_ACCEPTANCE_CASE="$$scenario" E2E_NAMESPACE=migration-e2e-ecr-secret E2E_SUBSCRIPTION="$$package" go test -count=1 -tags=e2e ./test/e2e/migration -run '^TestFixtureAcceptanceCases$$' -timeout "$(E2E_TIMEOUT)"; \
done; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$package"
.PHONY: migration/test-e2e-acknowledgments
migration/test-e2e-acknowledgments: migration/build ## Verify each soft acknowledgment and non-overridable hard block
@set -euo pipefail; \
package=ecr-secret-operator; \
for scenario in watch-target watch-selector unsupported-all-namespaces \
operator-condition olmv0-api-access scoped-serviceaccount \
subscription-state csv-phase package-dependency gvk-dependency \
apiservice generated-dependency missing-package; do \
coverage_dir="$(E2E_COVERAGE_DIR)/fixture/acknowledgments/$$scenario"; \
mkdir -p "$$coverage_dir"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$package"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/install-fixture-v0.sh "$$package"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" GOCOVERDIR="$$coverage_dir" E2E_ARTIFACTS="$(E2E_ARTIFACTS)/fixture/acknowledgments/$$scenario" E2E_SUITE=fixture E2E_ACKNOWLEDGMENT_CASE="$$scenario" E2E_NAMESPACE=migration-e2e-ecr-secret E2E_SUBSCRIPTION="$$package" go test -count=1 -tags=e2e ./test/e2e/migration -run '^TestFixtureAcknowledgments$$' -timeout "$(E2E_TIMEOUT)"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$package"; \
done
.PHONY: migration/test-e2e-backup
migration/test-e2e-backup: migration/build ## Verify backup contents, before-delete ordering, and non-fatal write failures
@set -euo pipefail; \
package=ecr-secret-operator; \
for scenario in success write-failure delete-denied; do \
coverage_dir="$(E2E_COVERAGE_DIR)/fixture/backup/$$scenario"; \
mkdir -p "$$coverage_dir"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$package"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/install-fixture-v0.sh "$$package"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" GOCOVERDIR="$$coverage_dir" E2E_ARTIFACTS="$(E2E_ARTIFACTS)/fixture/backup/$$scenario" E2E_SUITE=fixture E2E_BACKUP_CASE="$$scenario" E2E_NAMESPACE=migration-e2e-ecr-secret E2E_SUBSCRIPTION="$$package" go test -count=1 -tags=e2e ./test/e2e/migration -run '^TestFixtureBackupDirectory$$' -timeout "$(E2E_TIMEOUT)"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$package"; \
done
.PHONY: migration/test-e2e-cross-namespace
migration/test-e2e-cross-namespace: migration/build ## Verify fixture migration into a different install namespace
@set -euo pipefail; \
package=ecr-secret-operator; \
namespace=migration-e2e-ecr-secret; \
target="$$namespace-target"; \
coverage_dir="$(E2E_COVERAGE_DIR)/fixture/cross-namespace"; \
artifact_dir="$(E2E_ARTIFACTS)/fixture/cross-namespace"; \
mkdir -p "$$coverage_dir"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$package"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" kubectl delete namespace "$$target" --ignore-not-found --wait=true; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/install-fixture-v0.sh "$$package"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" GOCOVERDIR="$$coverage_dir" E2E_ARTIFACTS="$$artifact_dir" E2E_SUITE=fixture E2E_CROSS_NAMESPACE_TEST=true E2E_NAMESPACE="$$namespace" E2E_SUBSCRIPTION="$$package" go test -count=1 -tags=e2e ./test/e2e/migration -run '^TestCrossNamespaceMigration$$' -timeout "$(E2E_TIMEOUT)"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$package"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" kubectl delete namespace "$$target" --ignore-not-found --wait=true; \
: 'The source fixture namespace contains captured OLMv0 finalizers. install-fixture-v0.sh releases them before the next replay; CI tears down the Kind cluster.'
.PHONY: migration/test-e2e-system-managed-namespace
migration/test-e2e-system-managed-namespace: migration/build ## Verify migration into the OLMv1 system-managed namespace
@set -euo pipefail; \
package=ecr-secret-operator; \
namespace=migration-e2e-ecr-secret; \
target="$$package"; \
coverage_dir="$(E2E_COVERAGE_DIR)/fixture/system-managed-namespace"; \
artifact_dir="$(E2E_ARTIFACTS)/fixture/system-managed-namespace"; \
mkdir -p "$$coverage_dir"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$package"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" kubectl delete namespace "$$target" --ignore-not-found --wait=true; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/install-fixture-v0.sh "$$package"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" GOCOVERDIR="$$coverage_dir" E2E_ARTIFACTS="$$artifact_dir" E2E_SUITE=fixture E2E_SYSTEM_MANAGED_NAMESPACE_TEST=true E2E_NAMESPACE="$$namespace" E2E_SUBSCRIPTION="$$package" go test -count=1 -tags=e2e ./test/e2e/migration -run '^TestSystemManagedNamespaceMigration$$' -timeout "$(E2E_TIMEOUT)"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$package"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" kubectl delete namespace "$$target" --ignore-not-found --wait=true
.PHONY: migration/test-e2e-in-cluster-job
migration/test-e2e-in-cluster-job: migration/e2e-fixture-setup migration/build-e2e-image ## Run migration CLIs in a fixture-cluster Job (no coverage collection)
E2E_OPERATOR=ecr-secret-operator E2E_KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" $(MAKE) migration/e2e-delete-v1
E2E_OPERATOR=ecr-secret-operator $(MAKE) migration/e2e-install-fixture-v0
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" E2E_SUITE=in-cluster-job E2E_NAMESPACE=migration-e2e-ecr-secret E2E_SUBSCRIPTION=ecr-secret-operator E2E_MIGRATION_IMAGE="$(E2E_MIGRATION_IMAGE)" E2E_ARTIFACTS="$(E2E_ARTIFACTS)/in-cluster-job" go test -count=1 -tags=e2e ./test/e2e/migration -run '^TestMigrationInClusterJob$$' -timeout "$(E2E_TIMEOUT)"
.PHONY: migration/test-e2e-cos-supersession
migration/test-e2e-cos-supersession: migration/e2e-fixture-setup migration/build ## Verify migration COS is superseded by the catalog revision
@set -euo pipefail; \
package=ecr-secret-operator; \
coverage_profile="$(E2E_COVERAGE_DIR)/cos-supersession/cos-supersession-coverage.out"; \
mkdir -p "$$(dirname "$$coverage_profile")"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$package"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/install-fixture-v0.sh "$$package"; \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" E2E_ARTIFACTS="$(E2E_ARTIFACTS)/cos-supersession" E2E_SUITE=fixture E2E_COS_SUPERSESSION_TEST=true E2E_NAMESPACE=migration-e2e-ecr-secret E2E_SUBSCRIPTION="$$package" go test -count=1 -tags=e2e -covermode=count -coverpkg=./migration/... -coverprofile="$$coverage_profile" ./test/e2e/migration -run '^TestPrecreatedClusterObjectSetSupersession$$' -timeout "$(E2E_TIMEOUT)"; \
if [[ "$(E2E_KEEP_RESOURCES)" != true ]]; then \
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$package"; \
else \
echo "Retaining migration resources for inspection"; \
fi
.PHONY: migration/e2e-delete-v1
migration/e2e-delete-v1: ## Delete one migration E2E operator as OLMv1, or all
@if [[ "$(E2E_OPERATOR)" != all ]]; then \
E2E_OPERATOR="$(E2E_OPERATOR)" KUBECONFIG="$(E2E_KUBECONFIG)" bash -c 'source "$$1"; operator_fields "$$E2E_OPERATOR"' -- ./hack/e2e/migration/operators.sh; \
fi
@for operator in $$(awk -F '\t' -v wanted="$(E2E_OPERATOR)" 'NF==3 && $$1 !~ /^#/ && (wanted=="all" || $$1==wanted) {print $$1}' test/e2e/migration/operators.tsv); do \
KUBECONFIG="$(E2E_KUBECONFIG)" ./hack/e2e/migration/delete-v1.sh "$$operator"; \
done
.PHONY: migration/test-e2e-fixture
migration/test-e2e-fixture: migration/build ## Run deterministic fixture migration tests against the fixture kubeconfig
@test -n "$(E2E_FIXTURE_MANIFEST)" || (echo "E2E_FIXTURE_MANIFEST must install the fixture CatalogSource and Subscription" >&2; exit 2)
@test -n "$(E2E_FIXTURE_NAMESPACE)" || (echo "E2E_FIXTURE_NAMESPACE is required" >&2; exit 2)
@test -n "$(E2E_FIXTURE_SUBSCRIPTION)" || (echo "E2E_FIXTURE_SUBSCRIPTION is required" >&2; exit 2)
@mkdir -p "$(E2E_ARTIFACTS)/fixture"
@mkdir -p "$(E2E_COVERAGE_DIR)/fixture"
KUBECONFIG="$(E2E_FIXTURE_KUBECONFIG)" GOCOVERDIR="$(E2E_COVERAGE_DIR)/fixture" E2E_SUITE=fixture E2E_MANIFEST="$(E2E_FIXTURE_MANIFEST)" E2E_NAMESPACE="$(E2E_FIXTURE_NAMESPACE)" E2E_SUBSCRIPTION="$(E2E_FIXTURE_SUBSCRIPTION)" E2E_ARTIFACTS="$(E2E_ARTIFACTS)/fixture" go test -count=1 -tags=e2e ./test/e2e/migration -timeout "$(E2E_TIMEOUT)"
.PHONY: migration/test-e2e-real-operator
migration/test-e2e-real-operator: migration/build ## Run real-operator migration smoke tests against the live kubeconfig
@mkdir -p "$(E2E_ARTIFACTS)/real-operator"
@mkdir -p "$(E2E_COVERAGE_DIR)/real-operator"
KUBECONFIG="$(E2E_KUBECONFIG)" GOCOVERDIR="$(E2E_COVERAGE_DIR)/real-operator" E2E_SUITE=real-operator E2E_MANIFEST="$(E2E_REAL_OPERATOR_MANIFEST)" E2E_NAMESPACE="$(E2E_REAL_OPERATOR_NAMESPACE)" E2E_SUBSCRIPTION="$(E2E_REAL_OPERATOR_SUBSCRIPTION)" E2E_ARTIFACTS="$(E2E_ARTIFACTS)/real-operator" go test -count=1 -tags=e2e ./test/e2e/migration -timeout "$(E2E_TIMEOUT)"
.PHONY: migration/report-coverage-all
migration/report-coverage-all: ## Display coverage from existing unit, E2E CLI, and E2E package profiles
@mkdir -p $(COVERAGE_DIR)
@test -f "$(UNIT_COVERAGE_PROFILE)" || { echo "unit coverage is missing; run make migration/test-unit first" >&2; exit 2; }
@coverage_dirs="$$(find "$(E2E_COVERAGE_DIR)" -type f -name 'covmeta.*' -printf '%h\n' 2>/dev/null | sort -u | paste -sd, -)"; \
test -n "$$coverage_dirs" || { echo "no E2E CLI coverage found; run both E2E matrices before migration/report-coverage-all" >&2; exit 2; }; \
go tool covdata textfmt -i="$$coverage_dirs" -o="$(E2E_COVERAGE_PROFILE)"; \
profiles=("$(UNIT_COVERAGE_PROFILE)" "$(E2E_COVERAGE_PROFILE)"); \
while IFS= read -r profile; do profiles+=("$$profile"); \
done < <(find "$(E2E_COVERAGE_DIR)" -type f -name '*-coverage.out' -print); \
awk 'FNR == 1 { next } { key = $$1 " " $$2; if (!(key in count)) order[++n] = key; count[key] += $$3 } END { print "mode: count"; for (i = 1; i <= n; i++) print order[i] " " count[order[i]] }' "$${profiles[@]}" > "$(ALL_COVERAGE_PROFILE)"; \
go tool cover -func="$(ALL_COVERAGE_PROFILE)"
.PHONY: migration/test-coverage-all
migration/test-coverage-all: migration/test-unit migration/report-coverage-all ## Run unit tests and display combined unit and collected E2E CLI coverage
.PHONY: migration/clean
migration/clean: ## Remove compiled migration CLI binaries from bin/
rm -f $(MIGRATE_OPERATORS_BIN) $(MIGRATE_CATALOGS_BIN)