From fce47b628eb2e949dd200881c2dea4d4fa35e4fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Sun, 22 Feb 2026 21:11:04 +0100 Subject: [PATCH 1/4] feat: allow to skip namespace deletion in junit extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is important for tests which are using KubeApiTest from fabric8 client. There is no namespace controller present, so namespaces cannot be deleted. Although waitForNamespaceDeletion already is a workaround, but thought might be nicer to have this more explicit. Signed-off-by: Attila Mészáros --- .../operator/junit/AbstractOperatorExtension.java | 15 +++++++++++++++ .../junit/ClusterDeployedOperatorExtension.java | 3 +++ .../junit/LocallyRunOperatorExtension.java | 3 +++ 3 files changed, 21 insertions(+) diff --git a/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/AbstractOperatorExtension.java b/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/AbstractOperatorExtension.java index eceb6d9d76..86cbcede6e 100644 --- a/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/AbstractOperatorExtension.java +++ b/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/AbstractOperatorExtension.java @@ -58,6 +58,7 @@ public abstract class AbstractOperatorExtension protected Duration infrastructureTimeout; protected final boolean oneNamespacePerClass; protected final boolean preserveNamespaceOnError; + protected final boolean skipNamespaceDeletion; protected final boolean waitForNamespaceDeletion; protected final int namespaceDeleteTimeout = DEFAULT_NAMESPACE_DELETE_TIMEOUT; protected final Function namespaceNameSupplier; @@ -70,6 +71,7 @@ protected AbstractOperatorExtension( Duration infrastructureTimeout, boolean oneNamespacePerClass, boolean preserveNamespaceOnError, + boolean skipNamespaceDeletion, boolean waitForNamespaceDeletion, KubernetesClient kubernetesClient, KubernetesClient infrastructureKubernetesClient, @@ -85,6 +87,7 @@ protected AbstractOperatorExtension( this.infrastructureTimeout = infrastructureTimeout; this.oneNamespacePerClass = oneNamespacePerClass; this.preserveNamespaceOnError = preserveNamespaceOnError; + this.skipNamespaceDeletion = skipNamespaceDeletion; this.waitForNamespaceDeletion = waitForNamespaceDeletion; this.namespaceNameSupplier = namespaceNameSupplier; this.perClassNamespaceNameSupplier = perClassNamespaceNameSupplier; @@ -201,6 +204,9 @@ protected void after(ExtensionContext context) { if (namespace != null) { if (preserveNamespaceOnError && context.getExecutionException().isPresent()) { LOGGER.info("Preserving namespace {}", namespace); + } else if (skipNamespaceDeletion) { + LOGGER.info("Skipping namespace deletion for {}", namespace); + deleteOperator(); } else { infrastructureKubernetesClient.resourceList(infrastructure).delete(); deleteOperator(); @@ -229,6 +235,7 @@ public abstract static class AbstractBuilder> { protected final List infrastructure; protected Duration infrastructureTimeout; protected boolean preserveNamespaceOnError; + protected boolean skipNamespaceDeletion; protected boolean waitForNamespaceDeletion; protected boolean oneNamespacePerClass; protected int namespaceDeleteTimeout; @@ -245,6 +252,9 @@ protected AbstractBuilder() { this.preserveNamespaceOnError = Utils.getSystemPropertyOrEnvVar("josdk.it.preserveNamespaceOnError", false); + this.skipNamespaceDeletion = + Utils.getSystemPropertyOrEnvVar("josdk.it.skipNamespaceDeletion", false); + this.waitForNamespaceDeletion = Utils.getSystemPropertyOrEnvVar("josdk.it.waitForNamespaceDeletion", true); @@ -261,6 +271,11 @@ public T preserveNamespaceOnError(boolean value) { return (T) this; } + public T skipNamespaceDeletion(boolean value) { + this.skipNamespaceDeletion = value; + return (T) this; + } + public T waitForNamespaceDeletion(boolean value) { this.waitForNamespaceDeletion = value; return (T) this; diff --git a/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/ClusterDeployedOperatorExtension.java b/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/ClusterDeployedOperatorExtension.java index 2f134fa5ff..bcca851afe 100644 --- a/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/ClusterDeployedOperatorExtension.java +++ b/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/ClusterDeployedOperatorExtension.java @@ -51,6 +51,7 @@ private ClusterDeployedOperatorExtension( List infrastructure, Duration infrastructureTimeout, boolean preserveNamespaceOnError, + boolean skipNamespaceDeletion, boolean waitForNamespaceDeletion, boolean oneNamespacePerClass, KubernetesClient kubernetesClient, @@ -62,6 +63,7 @@ private ClusterDeployedOperatorExtension( infrastructureTimeout, oneNamespacePerClass, preserveNamespaceOnError, + skipNamespaceDeletion, waitForNamespaceDeletion, kubernetesClient, infrastructureKubernetesClient, @@ -189,6 +191,7 @@ public ClusterDeployedOperatorExtension build() { infrastructure, infrastructureTimeout, preserveNamespaceOnError, + skipNamespaceDeletion, waitForNamespaceDeletion, oneNamespacePerClass, kubernetesClient, diff --git a/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/LocallyRunOperatorExtension.java b/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/LocallyRunOperatorExtension.java index a1cdef8309..c4ed4c9e66 100644 --- a/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/LocallyRunOperatorExtension.java +++ b/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/LocallyRunOperatorExtension.java @@ -80,6 +80,7 @@ private LocallyRunOperatorExtension( List additionalCustomResourceDefinitionInstances, Duration infrastructureTimeout, boolean preserveNamespaceOnError, + boolean skipNamespaceDeletion, boolean waitForNamespaceDeletion, boolean oneNamespacePerClass, KubernetesClient kubernetesClient, @@ -94,6 +95,7 @@ private LocallyRunOperatorExtension( infrastructureTimeout, oneNamespacePerClass, preserveNamespaceOnError, + skipNamespaceDeletion, waitForNamespaceDeletion, kubernetesClient, infrastructureKubernetesClient, @@ -541,6 +543,7 @@ public LocallyRunOperatorExtension build() { additionalCustomResourceDefinitionInstances, infrastructureTimeout, preserveNamespaceOnError, + skipNamespaceDeletion, waitForNamespaceDeletion, oneNamespacePerClass, kubernetesClient, From cfc47a7df1e922e8aa3180789cee02dca14c2035 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Mon, 23 Feb 2026 13:21:10 +0100 Subject: [PATCH 2/4] fix infra resource deletion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- .../junit/AbstractOperatorExtension.java | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/AbstractOperatorExtension.java b/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/AbstractOperatorExtension.java index 86cbcede6e..48c2b33790 100644 --- a/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/AbstractOperatorExtension.java +++ b/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/AbstractOperatorExtension.java @@ -204,23 +204,22 @@ protected void after(ExtensionContext context) { if (namespace != null) { if (preserveNamespaceOnError && context.getExecutionException().isPresent()) { LOGGER.info("Preserving namespace {}", namespace); - } else if (skipNamespaceDeletion) { - LOGGER.info("Skipping namespace deletion for {}", namespace); - deleteOperator(); } else { infrastructureKubernetesClient.resourceList(infrastructure).delete(); deleteOperator(); - LOGGER.info("Deleting namespace {} and stopping operator", namespace); - infrastructureKubernetesClient.namespaces().withName(namespace).delete(); - if (waitForNamespaceDeletion) { - LOGGER.info("Waiting for namespace {} to be deleted", namespace); - Awaitility.await("namespace deleted") - .pollInterval(50, TimeUnit.MILLISECONDS) - .atMost(namespaceDeleteTimeout, TimeUnit.SECONDS) - .until( - () -> - infrastructureKubernetesClient.namespaces().withName(namespace).get() - == null); + if (skipNamespaceDeletion) { + LOGGER.info("Deleting namespace {} and stopping operator", namespace); + infrastructureKubernetesClient.namespaces().withName(namespace).delete(); + if (waitForNamespaceDeletion) { + LOGGER.info("Waiting for namespace {} to be deleted", namespace); + Awaitility.await("namespace deleted") + .pollInterval(50, TimeUnit.MILLISECONDS) + .atMost(namespaceDeleteTimeout, TimeUnit.SECONDS) + .until( + () -> + infrastructureKubernetesClient.namespaces().withName(namespace).get() + == null); + } } } } From 6ce3cab2f25f37e6fa42a457c89938a635f81b9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Mon, 23 Feb 2026 13:57:10 +0100 Subject: [PATCH 3/4] wip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- .../operator/junit/AbstractOperatorExtension.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/AbstractOperatorExtension.java b/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/AbstractOperatorExtension.java index 48c2b33790..d4de325fe0 100644 --- a/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/AbstractOperatorExtension.java +++ b/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/AbstractOperatorExtension.java @@ -207,7 +207,7 @@ protected void after(ExtensionContext context) { } else { infrastructureKubernetesClient.resourceList(infrastructure).delete(); deleteOperator(); - if (skipNamespaceDeletion) { + if (!skipNamespaceDeletion) { LOGGER.info("Deleting namespace {} and stopping operator", namespace); infrastructureKubernetesClient.namespaces().withName(namespace).delete(); if (waitForNamespaceDeletion) { From f252cf30f5367ad1f356d6ffc9e9a3c9078972ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Mon, 23 Feb 2026 13:58:43 +0100 Subject: [PATCH 4/4] logging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- .../operator/junit/AbstractOperatorExtension.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/AbstractOperatorExtension.java b/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/AbstractOperatorExtension.java index d4de325fe0..0609850713 100644 --- a/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/AbstractOperatorExtension.java +++ b/operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/AbstractOperatorExtension.java @@ -205,10 +205,11 @@ protected void after(ExtensionContext context) { if (preserveNamespaceOnError && context.getExecutionException().isPresent()) { LOGGER.info("Preserving namespace {}", namespace); } else { + LOGGER.info("Deleting infrastructure resources and operator in namespace {}", namespace); infrastructureKubernetesClient.resourceList(infrastructure).delete(); deleteOperator(); if (!skipNamespaceDeletion) { - LOGGER.info("Deleting namespace {} and stopping operator", namespace); + LOGGER.info("Deleting namespace {}", namespace); infrastructureKubernetesClient.namespaces().withName(namespace).delete(); if (waitForNamespaceDeletion) { LOGGER.info("Waiting for namespace {} to be deleted", namespace);