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 <[email protected]>
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;
[email protected](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;
[email protected](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();
}
}