This is an automated email from the ASF dual-hosted git repository.

claudio4j pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new e5885b85167 camel-jbang-plugin-kubernetes: make the delete op to 
delete from the k8s resources (#17335)
e5885b85167 is described below

commit e5885b851672e4231c7ff35367c8be9d114b2d2c
Author: Claudio Miranda <clau...@claudius.com.br>
AuthorDate: Sun Mar 9 09:35:35 2025 -0300

    camel-jbang-plugin-kubernetes: make the delete op to delete from the k8s 
resources (#17335)
    
    Do not use the camel-jbang temporary directory
    The "run" op sets labels used in the "del" op
    Use a single KubernetesClient instance in the KubernetesHelper
---
 .../camel-jbang-plugin-kubernetes/pom.xml          |  11 +-
 .../commands/kubernetes/KubernetesBaseCommand.java |  14 +-
 .../core/commands/kubernetes/KubernetesDelete.java | 111 ++++------
 .../core/commands/kubernetes/KubernetesHelper.java |  22 +-
 .../core/commands/kubernetes/KubernetesRun.java    |  12 +-
 .../commands/kubernetes/KubernetesCommandTest.java |   2 +-
 .../commands/kubernetes/KubernetesDeleteTest.java  | 232 +++++++++++++++------
 7 files changed, 245 insertions(+), 159 deletions(-)

diff --git a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/pom.xml 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/pom.xml
index 5ade3566b5c..eb4ff51fdac 100644
--- a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/pom.xml
+++ b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/pom.xml
@@ -65,6 +65,11 @@
             <artifactId>openshift-model</artifactId>
             <version>${kubernetes-client-version}</version>
         </dependency>
+        <dependency>
+            <groupId>io.fabric8</groupId>
+            <artifactId>openshift-client</artifactId>
+            <version>${kubernetes-client-version}</version>
+        </dependency>
 
         <!-- Knative model -->
         <dependency>
@@ -99,12 +104,6 @@
             <version>${kubernetes-client-version}</version>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>io.fabric8</groupId>
-            <artifactId>openshift-client</artifactId>
-            <version>${kubernetes-client-version}</version>
-            <scope>test</scope>
-        </dependency>
     </dependencies>
 
     <build>
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesBaseCommand.java
 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesBaseCommand.java
index c77146be48c..43eebadccc5 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesBaseCommand.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesBaseCommand.java
@@ -60,8 +60,6 @@ public abstract class KubernetesBaseCommand extends 
CamelCommand {
 
     List<Supplier<String>> projectNameSuppliers = new ArrayList<>();
 
-    private KubernetesClient kubernetesClient;
-
     public KubernetesBaseCommand(CamelJBangMain main) {
         super(main);
         projectNameSuppliers.add(() -> name);
@@ -130,22 +128,14 @@ public abstract class KubernetesBaseCommand extends 
CamelCommand {
      * uses default client.
      */
     protected KubernetesClient client() {
-        if (kubernetesClient == null) {
-            if (kubeConfig != null) {
-                kubernetesClient = 
KubernetesHelper.getKubernetesClient(kubeConfig);
-            } else {
-                kubernetesClient = KubernetesHelper.getKubernetesClient();
-            }
-        }
-
-        return kubernetesClient;
+        return KubernetesHelper.getKubernetesClient();
     }
 
     /**
      * Sets the Kubernetes client.
      */
     public KubernetesBaseCommand withClient(KubernetesClient kubernetesClient) 
{
-        this.kubernetesClient = kubernetesClient;
+        KubernetesHelper.setKubernetesClient(kubernetesClient);
         return this;
     }
 }
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesDelete.java
 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesDelete.java
index 7a73fe6f221..f60790bc02f 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesDelete.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesDelete.java
@@ -17,93 +17,68 @@
 
 package org.apache.camel.dsl.jbang.core.commands.kubernetes;
 
-import java.io.File;
-import java.io.FileInputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import io.fabric8.kubernetes.api.model.StatusDetails;
+import io.fabric8.openshift.client.OpenShiftClient;
 import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
-import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.dsl.jbang.core.commands.kubernetes.traits.BaseTrait;
 import org.apache.camel.util.StringHelper;
+import org.codehaus.plexus.util.ExceptionUtils;
 import picocli.CommandLine;
 
-@CommandLine.Command(name = "delete", description = "Delete Camel application 
from Kubernetes", sortOptions = false)
-public class KubernetesDelete extends KubernetesBaseCommand {
-
-    @CommandLine.Parameters(description = "The Camel file to delete. 
Integration name is derived from the file name.",
-                            arity = "0..1", paramLabel = "<file>")
-    String filePath;
+import static 
org.apache.camel.dsl.jbang.core.commands.kubernetes.KubernetesHelper.getKubernetesClient;
 
-    @CommandLine.Option(names = { "--working-dir" },
-                        description = "The working directory where to find 
exported project sources.")
-    String workingDir;
+@CommandLine.Command(name = "delete",
+                     description = "Delete Camel application from Kubernetes. 
This operation will delete all resources associated to this app, such as: 
Deployment, Routes, Services, etc. filtering by labels 
\"app.kubernetes.io/managed-by=camel-jbang\" and \"app=<app name>\".",
+                     sortOptions = false)
+public class KubernetesDelete extends KubernetesBaseCommand {
 
-    @CommandLine.Option(names = { "--cluster-type" },
-                        description = "The target cluster type. Special 
configurations may be applied to different cluster types such as Kind or 
Minikube or Openshift."
-                                      +
-                                      " If a target cluster type was set to 
create the project (run/export command), it needs to be set.")
-    protected String clusterType;
+    @CommandLine.Parameters(description = "The deployed application name", 
arity = "1", paramLabel = "<app name>")
+    String appName;
 
     public KubernetesDelete(CamelJBangMain main) {
         super(main);
-        projectNameSuppliers.add(() -> projectNameFromFilePath(() -> 
filePath));
     }
 
     public Integer doCall() throws Exception {
-
-        // First, try the explicit workingDir
-        File resolvedManifestDir = null;
-        if (workingDir != null) {
-            File resolvedWorkingDir = new File(workingDir);
-            File candidateDir = new File(resolvedWorkingDir, 
"target/kubernetes");
-            if (candidateDir.isDirectory()) {
-                resolvedManifestDir = candidateDir;
-            }
-        }
-
-        String projectName = getProjectName();
-
-        // Next, try the project name in the run dir
-        if (resolvedManifestDir == null) {
-            File resolvedWorkingDir = new File(RUN_PLATFORM_DIR + "/" + 
projectName);
-            File candidateDir = new File(resolvedWorkingDir, 
"target/kubernetes");
-            if (candidateDir.isDirectory()) {
-                resolvedManifestDir = candidateDir;
+        printer().printf("Deleting all resources from app: %s%n", appName);
+        Map<String, String> labels = new HashMap<>();
+        // this label is set in KubernetesRun command
+        labels.put(BaseTrait.KUBERNETES_LABEL_MANAGED_BY, "camel-jbang");
+        labels.put("app", appName);
+        List<StatusDetails> deleteStatuses = new ArrayList<>();
+        try {
+            // delete the most common resources
+            // delete Deployment cascades to pod
+            
deleteStatuses.addAll(getKubernetesClient().apps().deployments().withLabels(labels).delete());
+            // delete service
+            
deleteStatuses.addAll(getKubernetesClient().services().withLabels(labels).delete());
+            ClusterType clusterType = KubernetesHelper.discoverClusterType();
+            if (ClusterType.OPENSHIFT == clusterType) {
+                // openshift specific: BuildConfig, ImageStreams, Route - 
BuildConfig casacade delete to Build and ConfigMap
+                OpenShiftClient ocpClient = 
getKubernetesClient().adapt(OpenShiftClient.class);
+                // BuildConfig
+                
deleteStatuses.addAll(ocpClient.buildConfigs().withLabels(labels).delete());
+                // ImageStreams
+                
deleteStatuses.addAll(ocpClient.imageStreams().withLabels(labels).delete());
+                // Route
+                
deleteStatuses.addAll(ocpClient.routes().withLabels(labels).delete());
             }
-        }
-
-        // Next, try the project name in the current dir
-        if (resolvedManifestDir == null) {
-            File candidateDir = new File("./target/kubernetes");
-            if (candidateDir.isDirectory()) {
-                resolvedManifestDir = candidateDir;
-            }
-        }
-
-        if (resolvedManifestDir == null) {
-            printer().printErr("Failed to resolve exported project: 
%s".formatted(projectName));
-            return 1;
-        }
-
-        File manifest = 
KubernetesHelper.resolveKubernetesManifest(clusterType, resolvedManifestDir);
-        printer().printf("Deleting resources from manifest: %s%n", manifest);
-
-        try (FileInputStream fis = new FileInputStream(manifest)) {
-            List<StatusDetails> status;
-            var loadedResources = client().load(fis);
-            if (!ObjectHelper.isEmpty(namespace)) {
-                status = loadedResources.inNamespace(namespace).delete();
+            if (deleteStatuses.size() > 0) {
+                deleteStatuses.forEach(
+                        s -> printer().printf("Deleted: %s '%s'%n", 
StringHelper.capitalize(s.getKind()), s.getName()));
             } else {
-                // First, let the client choose the default namespace
-                status = loadedResources.delete();
-                // Next, explicitly name the default namespace
-                if (status.isEmpty()) {
-                    status = loadedResources.inNamespace("default").delete();
-                }
+                printer().println("No deployment found with name: " + appName);
             }
-            status.forEach(s -> printer().printf("Deleted: %s '%s'%n", 
StringHelper.capitalize(s.getKind()), s.getName()));
+        } catch (Exception ex) {
+            // there could be various chained exceptions, so we want to get 
the root cause
+            printer().println("Error trying to delete the app: " + 
ExceptionUtils.getRootCause(ex));
+            return 1;
         }
-
         return 0;
     }
 }
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesHelper.java
 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesHelper.java
index caaee6e85f6..71fbf2349a5 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesHelper.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesHelper.java
@@ -80,7 +80,7 @@ public final class KubernetesHelper {
         if (kubernetesClient == null) {
             kubernetesClient = new KubernetesClientBuilder().build();
         }
-
+        setKubernetesClientProperties();
         return kubernetesClient;
     }
 
@@ -91,11 +91,25 @@ public final class KubernetesHelper {
         if (clients.containsKey(config)) {
             return clients.get(config);
         }
-
+        setKubernetesClientProperties();
         var client = new KubernetesClientBuilder().withConfig(config).build();
         return clients.put(config, client);
     }
 
+    // set short timeouts to fail fast in case it's not connected to a cluster 
and don't waste time
+    // the user can override these values by setting the property in the cli
+    private static void setKubernetesClientProperties() {
+        if (System.getProperty("kubernetes.connection.timeout") == null) {
+            System.setProperty("kubernetes.connection.timeout", "2000");
+        }
+        if (System.getProperty("kubernetes.request.timeout") == null) {
+            System.setProperty("kubernetes.request.timeout", "2000");
+        }
+        if (System.getProperty("kubernetes.request.retry.backoffLimit") == 
null) {
+            System.setProperty("kubernetes.request.retry.backoffLimit", "1");
+        }
+    }
+
     /**
      * Creates new Yaml instance. The implementation provided by Snakeyaml is 
not thread-safe. It is better to create a
      * fresh instance for every YAML stream.
@@ -125,10 +139,6 @@ public final class KubernetesHelper {
      */
     static ClusterType discoverClusterType() {
         ClusterType cluster = ClusterType.KUBERNETES;
-        // in case it's not connected to a cluster, don't waste time waiting 
for a response.
-        System.setProperty("kubernetes.connection.timeout", "2000");
-        System.setProperty("kubernetes.request.timeout", "2000");
-        System.setProperty("kubernetes.request.retry.backoffLimit", "1");
         if (isConnectedToOpenshift()) {
             cluster = ClusterType.OPENSHIFT;
         } else if (isConnectedToMinikube()) {
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRun.java
 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRun.java
index c5246b6a723..0fa05b85375 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRun.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRun.java
@@ -354,6 +354,9 @@ public class KubernetesRun extends KubernetesBaseCommand {
 
     private KubernetesExport configureExport(String workingDir) {
         detectCluster();
+        // jkube automatically sets the "app.kubernetes.io/managed-by: jkube" 
label
+        // given this is a deployment managed by this plugin, we will replace 
the value for "camel-jbang"
+        
buildProperties.add("jkube.enricher.jkube-well-known-labels.managedBy=camel-jbang");
         KubernetesExport.ExportConfigurer configurer = new 
KubernetesExport.ExportConfigurer(
                 runtime,
                 quarkusVersion,
@@ -438,7 +441,6 @@ public class KubernetesRun extends KubernetesBaseCommand {
 
                 printer().printf("Reloading project due to file change: %s%n", 
FileUtil.stripPath(name));
 
-                String currentWorkingDir = getIndexedWorkingDir(projectName);
                 devModeReloadCount += 1;
 
                 String reloadWorkingDir = getIndexedWorkingDir(projectName);
@@ -459,8 +461,6 @@ public class KubernetesRun extends KubernetesBaseCommand {
                     // Undeploy/Delete current project
                     //
                     KubernetesDelete deleteCommand = new 
KubernetesDelete(getMain());
-                    deleteCommand.workingDir = currentWorkingDir;
-                    deleteCommand.clusterType = clusterType;
                     deleteCommand.name = projectName;
                     deleteCommand.doCall();
 
@@ -530,13 +530,11 @@ public class KubernetesRun extends KubernetesBaseCommand {
     private void installShutdownHook(String projectName, String workingDir) {
         devModeShutdownTask = new Thread(() -> {
             KubernetesDelete deleteCommand = new KubernetesDelete(getMain());
-            deleteCommand.clusterType = clusterType;
-            deleteCommand.workingDir = workingDir;
             deleteCommand.name = projectName;
             try (var client = createKubernetesClientForShutdownHook()) {
                 KubernetesHelper.setKubernetesClient(client);
                 deleteCommand.doCall();
-                CommandHelper.cleanExportDir(deleteCommand.workingDir, false);
+                CommandHelper.cleanExportDir(workingDir, false);
             } catch (Exception e) {
                 throw new RuntimeException(e);
             }
@@ -585,6 +583,8 @@ public class KubernetesRun extends KubernetesBaseCommand {
         // skip image build and push because we only want to build the 
Kubernetes manifest
         args.add("-Djkube.skip.build=true");
         args.add("-Djkube.skip.push=true");
+        // suppress maven transfer progress
+        args.add("-ntp");
 
         args.add("package");
 
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesCommandTest.java
 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesCommandTest.java
index d20df61591f..c76ecad1a4a 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesCommandTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesCommandTest.java
@@ -64,7 +64,7 @@ class KubernetesCommandTest extends KubernetesBaseTest {
         Assertions.assertEquals("route", 
deployment.getMetadata().getLabels().get(BaseTrait.KUBERNETES_LABEL_NAME));
         Assertions.assertEquals("route", 
deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getName());
         Assertions.assertEquals("route", 
matchLabels.get(BaseTrait.KUBERNETES_LABEL_NAME));
-        Assertions.assertEquals("jkube", 
matchLabels.get(BaseTrait.KUBERNETES_LABEL_MANAGED_BY));
+        Assertions.assertEquals("camel-jbang", 
matchLabels.get(BaseTrait.KUBERNETES_LABEL_MANAGED_BY));
         Assertions.assertEquals("camel-test/route:1.0-SNAPSHOT",
                 
deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage());
         Assertions.assertEquals("IfNotPresent",
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesDeleteTest.java
 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesDeleteTest.java
index c4717e4cf96..159ee6307e9 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesDeleteTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesDeleteTest.java
@@ -17,86 +17,198 @@
 
 package org.apache.camel.dsl.jbang.core.commands.kubernetes;
 
-import io.fabric8.kubernetes.api.model.ContainerBuilder;
-import io.fabric8.kubernetes.api.model.IntOrString;
-import io.fabric8.kubernetes.api.model.ServiceBuilder;
-import io.fabric8.kubernetes.api.model.ServicePortBuilder;
-import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder;
+import java.net.HttpURLConnection;
+import java.util.Collections;
+
+import io.fabric8.kubernetes.api.model.Node;
+import io.fabric8.kubernetes.api.model.NodeBuilder;
+import io.fabric8.kubernetes.api.model.NodeList;
+import io.fabric8.kubernetes.api.model.NodeListBuilder;
+import io.fabric8.kubernetes.client.KubernetesClient;
+import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient;
+import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer;
+import io.fabric8.openshift.api.model.config.v1.ClusterVersion;
+import io.fabric8.openshift.api.model.config.v1.ClusterVersionBuilder;
+import io.fabric8.openshift.client.OpenShiftClient;
 import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
-import org.apache.camel.dsl.jbang.core.commands.kubernetes.traits.BaseTrait;
+import org.apache.camel.dsl.jbang.core.common.StringPrinter;
+import org.apache.camel.dsl.jbang.core.common.VersionHelper;
 import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
-import org.junit.jupiter.api.condition.EnabledIf;
+import org.junitpioneer.jupiter.SetEnvironmentVariable;
 
 @DisabledIfSystemProperty(named = "ci.env.name", matches = ".*",
                           disabledReason = "Requires too much network 
resources")
-@EnabledIf("isDockerAvailable")
-class KubernetesDeleteTest extends KubernetesBaseTest {
+@EnableKubernetesMockClient
+class KubernetesDeleteTest {
+
+    protected KubernetesMockServer server;
+    protected KubernetesClient client;
+    protected StringPrinter printer;
+
+    @BeforeEach
+    public void setup() {
+        // Set Camel version with system property value, usually set via Maven 
surefire plugin
+        // In case you run this test via local Java IDE you need to provide 
the system property or a default value here
+        VersionHelper.setCamelVersion(System.getProperty("camel.version", ""));
+        printer = new StringPrinter();
+    }
 
     @Test
-    public void shouldDeleteKubernetesResources() throws Exception {
-        kubernetesClient.apps().deployments().resource(new DeploymentBuilder()
-                .withNewMetadata()
-                .withName("route")
-                .addToLabels(BaseTrait.KUBERNETES_LABEL_NAME, "route")
-                .endMetadata()
-                .withNewSpec()
-                .withNewTemplate()
-                .withNewSpec()
-                .addToContainers(new ContainerBuilder()
-                        .withName("route")
-                        .withImage("quay.io/camel-test/route:1.0-SNAPSHOT")
-                        .build())
-                .endSpec()
-                .endTemplate()
-                .endSpec()
-                .build()).create();
-
-        kubernetesClient.services().resource(new ServiceBuilder()
+    public void shouldDeleteNonExistentApp() throws Exception {
+        KubernetesDelete command = new KubernetesDelete(new 
CamelJBangMain().withPrinter(printer));
+        command.withClient(client);
+        command.appName = "does-not-exist";
+        int exit = command.doCall();
+        boolean errorOutput = printer.getOutput().contains("Error trying to 
delete the app");
+        if (errorOutput) {
+            Assertions.assertEquals(1, exit, printer.getOutput());
+        } else {
+            Assertions.assertEquals(0, exit, printer.getOutput());
+            Assertions.assertTrue(printer.getOutput().contains("No deployment 
found with name"), printer.getOutput());
+        }
+    }
+
+    @Test
+    @SetEnvironmentVariable(key = "MINIKUBE_ACTIVE_DOCKERD", value = "foo")
+    @SetEnvironmentVariable(key = "DOCKER_TLS_VERIFY", value = "foo")
+    public void shouldDeleteNonExistentAppInMinikube() throws Exception {
+        Node nodeCR = new NodeBuilder()
                 .withNewMetadata()
-                .withName("route")
+                .withName("minikube")
+                .withLabels(Collections.singletonMap("minikube.k8s.io/name", 
"minikube"))
                 .endMetadata()
-                .withNewSpec()
-                .withPorts(new ServicePortBuilder()
-                        .withPort(80)
-                        .withProtocol("TCP")
-                        .withName("http")
-                        .withTargetPort(new IntOrString(8080))
-                        .build())
-                .endSpec()
-                .build()).create();
-
-        KubernetesRun run = new KubernetesRun(new 
CamelJBangMain().withPrinter(printer));
-        run.withClient(kubernetesClient);
-        run.imageGroup = "camel-test";
-        run.imageBuild = false;
-        run.imagePush = false;
-        run.filePaths = new String[] { "classpath:route.yaml" };
-        run.output = "yaml";
-        int exit = run.doCall();
-        Assertions.assertEquals(0, exit);
+                .build();
+        NodeList nodeList = new NodeListBuilder().addToItems(nodeCR)
+                .build();
+
+        serverExpect("/api/v1/nodes?labelSelector=minikube.k8s.io%2Fname", 
nodeList);
+
+        KubernetesDelete command = new KubernetesDelete(new 
CamelJBangMain().withPrinter(printer));
+        command.withClient(client);
+        command.appName = "does-not-exist";
+        int exit = command.doCall();
+        boolean errorOutput = printer.getOutput().contains("Error trying to 
delete the app");
+        if (errorOutput) {
+            Assertions.assertEquals(1, exit, printer.getOutput());
+        } else {
+            Assertions.assertEquals(0, exit, printer.getOutput());
+            Assertions.assertTrue(printer.getOutput().contains("No deployment 
found with name"), printer.getOutput());
+        }
+    }
+
+    @Test
+    public void shouldDeleteNonExistentAppInOpenshift() throws Exception {
+        ClusterVersion versionCR = new ClusterVersionBuilder()
+                .withNewMetadata().withName("version").endMetadata()
+                .withNewStatus()
+                .withNewDesired()
+                .withVersion("4.14.5")
+                .endDesired()
+                .endStatus()
+                .build();
+
+        serverExpect("/apis/config.openshift.io/v1/clusterversions/version", 
versionCR);
 
         KubernetesDelete command = new KubernetesDelete(new 
CamelJBangMain().withPrinter(printer));
-        command.withClient(kubernetesClient);
-        command.name = "route";
-        exit = command.doCall();
+        command.withClient(client);
+        command.appName = "does-not-exist";
+        int exit = command.doCall();
+        boolean errorOutput = printer.getOutput().contains("Error trying to 
delete the app");
+        if (errorOutput) {
+            Assertions.assertEquals(1, exit, printer.getOutput());
+        } else {
+            Assertions.assertEquals(0, exit, printer.getOutput());
+            Assertions.assertTrue(printer.getOutput().contains("No deployment 
found with name"), printer.getOutput());
+        }
+    }
+
+    @Test
+    public void shouldDeleteOnKubernetes() throws Exception {
+        String appName = "my-route";
+
+        // Mock the delete request expectation
+        serverDeleteExpect(
+                
"/apis/apps/v1/namespaces/test/deployments?labelSelector=app%3Dmy-route%2Capp.kubernetes.io%2Fmanaged-by%3Dcamel-jbang");
+        serverDeleteExpect(
+                
"/api/v1/namespaces/test/services?labelSelector=app%3Dmy-route%2Capp.kubernetes.io%2Fmanaged-by%3Dcamel-jbang");
 
-        Assertions.assertEquals(0, exit);
-        
Assertions.assertNull(kubernetesClient.apps().deployments().withName("route").get());
-        
Assertions.assertNull(kubernetesClient.services().withName("route").get());
+        // Execute delete command
+        KubernetesDelete command = new KubernetesDelete(new 
CamelJBangMain().withPrinter(printer));
+        command.withClient(client);
+        command.namespace = "test";
+        command.appName = appName;
+        int exit = command.doCall();
+
+        // Verify command execution
+        Assertions.assertEquals(0, exit, printer.getOutput());
+
+        // Verify deployment was deleted
+        
Assertions.assertNull(client.apps().deployments().withName(appName).get());
+        Assertions.assertNull(client.services().withName(appName).get());
     }
 
     @Test
-    public void shouldHandleNoExportFound() throws Exception {
+    public void shouldDeleteOnOpenShift() throws Exception {
+        ClusterVersion versionCR = new ClusterVersionBuilder()
+                .withNewMetadata().withName("version").endMetadata()
+                .withNewStatus()
+                .withNewDesired()
+                .withVersion("4.14.5")
+                .endDesired()
+                .endStatus()
+                .build();
+
+        serverExpect("/apis/config.openshift.io/v1/clusterversions/version", 
versionCR);
+
+        String appName = "my-route";
+
+        // Mock the delete request expectations for openshift resources
+        serverDeleteExpect(
+                
"/apis/apps/v1/namespaces/test/deployments?labelSelector=app%3Dmy-route%2Capp.kubernetes.io%2Fmanaged-by%3Dcamel-jbang");
+        serverDeleteExpect(
+                
"/api/v1/namespaces/test/services?labelSelector=app%3Dmy-route%2Capp.kubernetes.io%2Fmanaged-by%3Dcamel-jbang");
+        serverDeleteExpect(
+                
"/apis/build.openshift.io/v1/namespaces/test/buildconfigs?labelSelector=app%3Dmy-route%2Capp.kubernetes.io%2Fmanaged-by%3Dcamel-jbang");
+        serverDeleteExpect(
+                
"/apis/image.openshift.io/v1/namespaces/test/imagestreams?labelSelector=app%3Dmy-route%2Capp.kubernetes.io%2Fmanaged-by%3Dcamel-jbang");
+        serverDeleteExpect(
+                
"/apis/route.openshift.io/v1/namespaces/test/routes?labelSelector=app%3Dmy-route%2Capp.kubernetes.io%2Fmanaged-by%3Dcamel-jbang");
+
+        // Execute delete command
         KubernetesDelete command = new KubernetesDelete(new 
CamelJBangMain().withPrinter(printer));
-        command.withClient(kubernetesClient);
-        command.name = "does-not-exist";
+        command.withClient(client);
+        command.namespace = "test";
+        command.appName = appName;
         int exit = command.doCall();
 
-        Assertions.assertEquals(1, exit);
-        Assertions.assertEquals("ERROR: Failed to resolve exported project: 
does-not-exist",
-                printer.getOutput());
+        // Verify command execution
+        Assertions.assertEquals(0, exit, printer.getOutput());
+
+        OpenShiftClient ocpClient = client.adapt(OpenShiftClient.class);
+
+        // Verify deployment was deleted
+        
Assertions.assertNull(client.apps().deployments().withName(appName).get());
+        Assertions.assertNull(client.services().withName(appName).get());
+        
Assertions.assertNull(ocpClient.buildConfigs().withName(appName).get());
+        
Assertions.assertNull(ocpClient.imageStreams().withName(appName).get());
+        Assertions.assertNull(ocpClient.routes().withName(appName).get());
+    }
+
+    private void serverDeleteExpect(String path) {
+        server.expect().delete()
+                .withPath(path)
+                .andReturn(HttpURLConnection.HTTP_OK, null)
+                .once();
+    }
+
+    private void serverExpect(String path, Object response) {
+        server.expect().get()
+                .withPath(path)
+                .andReturn(HttpURLConnection.HTTP_OK, response)
+                .once();
     }
 
 }

Reply via email to