Skip to content

Commit 72ad150

Browse files
Per G. da Silvaclaude
andcommitted
🌱 Address review: move collision e2e test to update.feature, assert original CE stays installed
- Move the higher-revision collision test from install.feature to update.feature where it fits better alongside the existing collision scenario. - Add assertions that the original ClusterExtension remains Installed=True after both collision points. - Add NamedClusterExtensionReportsCondition and ClusterExtensionHasClusterObjectSets step definitions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent a3d8bce commit 72ad150

2 files changed

Lines changed: 103 additions & 0 deletions

File tree

test/e2e/features/update.feature

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,3 +338,97 @@ Feature: Update ClusterExtension
338338
Then ClusterExtension reports "${NAME}-1, ${NAME}-2" as active revisions
339339
And ClusterObjectSet "${NAME}-2" reports Progressing as True with Reason RollingOut
340340
And ClusterObjectSet "${NAME}-2" reports Available as False with Reason ProbeFailure
341+
342+
@BoxcutterRuntime
343+
@DeploymentConfig
344+
Scenario: A conflicting ClusterExtension with a higher revision does not take over resources from the original owner
345+
Given ClusterExtension is applied
346+
"""
347+
apiVersion: olm.operatorframework.io/v1
348+
kind: ClusterExtension
349+
metadata:
350+
name: ${NAME}
351+
spec:
352+
namespace: ${TEST_NAMESPACE}
353+
serviceAccount:
354+
name: olm-sa
355+
source:
356+
sourceType: Catalog
357+
catalog:
358+
packageName: ${PACKAGE:test}
359+
version: 1.0.0
360+
selector:
361+
matchLabels:
362+
"olm.operatorframework.io/metadata.name": ${CATALOG:test}
363+
"""
364+
And ClusterExtension is rolled out
365+
And ClusterExtension is available
366+
And ClusterExtension "${NAME}" has 1 ClusterObjectSet
367+
And the current ClusterExtension is tracked for cleanup
368+
# Apply a second ClusterExtension pointing to the same package and version
369+
When ClusterExtension is applied
370+
"""
371+
apiVersion: olm.operatorframework.io/v1
372+
kind: ClusterExtension
373+
metadata:
374+
name: ${NAME}-dup
375+
spec:
376+
namespace: ${TEST_NAMESPACE}
377+
serviceAccount:
378+
name: olm-sa
379+
source:
380+
sourceType: Catalog
381+
catalog:
382+
packageName: ${PACKAGE:test}
383+
version: 1.0.0
384+
selector:
385+
matchLabels:
386+
"olm.operatorframework.io/metadata.name": ${CATALOG:test}
387+
"""
388+
Then ClusterExtension reports Progressing as True with Reason Retrying and Message includes:
389+
"""
390+
revision object collisions
391+
"""
392+
# Verify the original ClusterExtension remains installed and unaffected
393+
And ClusterExtension "ce-${SCENARIO_ID}" reports Installed as True
394+
# Update the conflicting ClusterExtension with a deployment config env var. At the time
395+
# of writing, there is no other way to get the operator controller to generate another
396+
# ClusterObjectSet by simply targeting another bundle version in the ClusterExtension.
397+
# Since nothing has been installed yet for this CE, the resolver returns the currently
398+
# installed bundle. Injecting an environment variable via DeploymentConfig changes the
399+
# desired state, which causes the controller to create a second ClusterObjectSet
400+
# (revision 2) after the first one collides.
401+
When ClusterExtension is updated
402+
"""
403+
apiVersion: olm.operatorframework.io/v1
404+
kind: ClusterExtension
405+
metadata:
406+
name: ${NAME}
407+
spec:
408+
namespace: ${TEST_NAMESPACE}
409+
serviceAccount:
410+
name: olm-sa
411+
config:
412+
configType: Inline
413+
inline:
414+
deploymentConfig:
415+
env:
416+
- name: MY_VAR
417+
value: "my-value"
418+
source:
419+
sourceType: Catalog
420+
catalog:
421+
packageName: ${PACKAGE:test}
422+
version: 1.0.0
423+
selector:
424+
matchLabels:
425+
"olm.operatorframework.io/metadata.name": ${CATALOG:test}
426+
"""
427+
Then ClusterExtension "${NAME}" has 2 ClusterObjectSets
428+
# The higher-revision COS (revision 2) should also collide, not take over resources
429+
And ClusterExtension reports Progressing as True with Reason Retrying and Message includes:
430+
"""
431+
revision object collisions
432+
"""
433+
# Verify the original ClusterExtension is still installed after the higher-revision collision
434+
And ClusterExtension "ce-${SCENARIO_ID}" reports Installed as True

test/e2e/steps/steps.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ func RegisterSteps(sc *godog.ScenarioContext) {
124124
sc.Step(`^(?i)ClusterExtension reports ([[:alnum:]]+) as ([[:alnum:]]+) with Reason ([[:alnum:]]+) and Message includes:$`, ClusterExtensionReportsConditionWithMessageFragment)
125125
sc.Step(`^(?i)ClusterExtension reports ([[:alnum:]]+) as ([[:alnum:]]+) with Reason ([[:alnum:]]+)$`, ClusterExtensionReportsConditionWithoutMsg)
126126
sc.Step(`^(?i)ClusterExtension reports ([[:alnum:]]+) as ([[:alnum:]]+)$`, ClusterExtensionReportsConditionWithoutReason)
127+
sc.Step(`^(?i)ClusterExtension "([^"]+)" reports ([[:alnum:]]+) as ([[:alnum:]]+)$`, NamedClusterExtensionReportsCondition)
127128
sc.Step(`^(?i)ClusterObjectSet "([^"]+)" reports ([[:alnum:]]+) as ([[:alnum:]]+) with Reason ([[:alnum:]]+)$`, ClusterObjectSetReportsConditionWithoutMsg)
128129
sc.Step(`^(?i)ClusterObjectSet "([^"]+)" reports ([[:alnum:]]+) as ([[:alnum:]]+) with Reason ([[:alnum:]]+) and Message:$`, ClusterObjectSetReportsConditionWithMsg)
129130
sc.Step(`^(?i)ClusterObjectSet "([^"]+)" reports ([[:alnum:]]+) as ([[:alnum:]]+) with Reason ([[:alnum:]]+) and Message includes:$`, ClusterObjectSetReportsConditionWithMessageFragment)
@@ -688,6 +689,14 @@ func ClusterExtensionReportsConditionWithoutReason(ctx context.Context, conditio
688689
return waitForExtensionCondition(ctx, conditionType, conditionStatus, nil, nil)
689690
}
690691

692+
// NamedClusterExtensionReportsCondition waits for a specific ClusterExtension (by name) to have a condition
693+
// matching type and status. Polls with timeout.
694+
func NamedClusterExtensionReportsCondition(ctx context.Context, extName, conditionType, conditionStatus string) error {
695+
sc := scenarioCtx(ctx)
696+
extName = substituteScenarioVars(extName, sc)
697+
return waitForCondition(ctx, "clusterextension", extName, conditionType, conditionStatus, nil, nil)
698+
}
699+
691700
// ClusterExtensionReportsConditionTransitionTime asserts that a condition's lastTransitionTime falls within
692701
// the specified minute range since the ClusterExtension's creation.
693702
func ClusterExtensionReportsConditionTransitionTime(ctx context.Context, conditionType string, minMinutes, maxMinutes int) error {

0 commit comments

Comments
 (0)