From c7c2801ca5a1ca0fee5f6b74f78de3a5a8c03b04 Mon Sep 17 00:00:00 2001 From: "Per G. da Silva" Date: Mon, 19 Oct 2026 16:42:40 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=8C=B1=20add=20ClusterObjectSet=20pre-app?= =?UTF-8?q?ly=20dry-run=20validation=20e2e=20scenarios?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a cos_preflight.feature suite covering the phase-level pre-apply checks that surface on the ClusterObjectSet as Ready=False/ PreconditionsNotMet: - an object targeting a non-existent namespace, - an object with an invalid spec (a Pod with no containers), and - recovery: the revision returns to Ready=True/AllObjectsReady once the missing target namespace is created. Assertions match on "check rejected phase ..." so they hold regardless of the exact leading wording of the controller message. Co-Authored-By: Claude Opus 4.8 Signed-off-by: Per G. da Silva --- test/e2e/features/cos_preflight.feature | 108 ++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 test/e2e/features/cos_preflight.feature diff --git a/test/e2e/features/cos_preflight.feature b/test/e2e/features/cos_preflight.feature new file mode 100644 index 0000000000..064f85f857 --- /dev/null +++ b/test/e2e/features/cos_preflight.feature @@ -0,0 +1,108 @@ +@BoxcutterRuntime +Feature: ClusterObjectSet preflight dry-run validation + + As an OLM user applying a ClusterObjectSet directly, I want the revision to be + rejected with an actionable PreconditionsNotMet condition when one of its + objects would be rejected by the API server, and to recover automatically once + the underlying problem is resolved, so that transient or fixable issues do not + require re-creating the revision. + + Background: + Given OLM is available + + Scenario: ClusterObjectSet reports PreconditionsNotMet when an object targets a non-existent namespace + When ClusterObjectSet is applied + """ + apiVersion: olm.operatorframework.io/v1 + kind: ClusterObjectSet + metadata: + name: ${COS_NAME} + spec: + lifecycleState: Active + collisionProtection: Prevent + group: ${NAME} + phases: + - name: resources + objects: + - object: + apiVersion: v1 + kind: ConfigMap + metadata: + name: cm-x + namespace: ${COS_NAME}-absent + data: + k: v + revision: 1 + """ + Then ClusterObjectSet "${COS_NAME}" reports Ready as False with Reason PreconditionsNotMet and Message includes: + """ + check rejected phase "resources": phase "resources": /v1, Kind=ConfigMap ${COS_NAME}-absent/cm-x: namespaces "${COS_NAME}-absent" not found. + """ + + Scenario: ClusterObjectSet reports PreconditionsNotMet when an object has an invalid spec + Given namespace "${TEST_NAMESPACE}" is available + When ClusterObjectSet is applied + """ + apiVersion: olm.operatorframework.io/v1 + kind: ClusterObjectSet + metadata: + name: ${COS_NAME} + spec: + lifecycleState: Active + collisionProtection: Prevent + group: ${NAME} + phases: + - name: resources + objects: + - object: + apiVersion: v1 + kind: Pod + metadata: + name: bad-pod + namespace: ${TEST_NAMESPACE} + spec: + containers: [] + revision: 1 + """ + Then ClusterObjectSet "${COS_NAME}" reports Ready as False with Reason PreconditionsNotMet and Message includes: + """ + check rejected phase "resources": phase "resources": /v1, Kind=Pod ${TEST_NAMESPACE}/bad-pod: Pod "bad-pod" is invalid: spec.containers: Required value. + """ + + Scenario: ClusterObjectSet recovers once a missing target namespace is created + When ClusterObjectSet is applied + """ + apiVersion: olm.operatorframework.io/v1 + kind: ClusterObjectSet + metadata: + name: ${COS_NAME} + spec: + lifecycleState: Active + collisionProtection: Prevent + group: ${NAME} + phases: + - name: resources + objects: + - object: + apiVersion: v1 + kind: ConfigMap + metadata: + name: cm-x + namespace: ${COS_NAME}-recover + data: + k: v + revision: 1 + """ + Then ClusterObjectSet "${COS_NAME}" reports Ready as False with Reason PreconditionsNotMet and Message includes: + """ + check rejected phase "resources": phase "resources": /v1, Kind=ConfigMap ${COS_NAME}-recover/cm-x: namespaces "${COS_NAME}-recover" not found. + """ + When resource is applied + """ + apiVersion: v1 + kind: Namespace + metadata: + name: ${COS_NAME}-recover + """ + And ClusterObjectSet "${COS_NAME}" reconciliation is triggered + Then ClusterObjectSet "${COS_NAME}" reports Ready as True with Reason AllObjectsReady