This is an automated email from the ASF dual-hosted git repository. cdeppisch 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 089356d392b CAMEL-21903: Adjustable container image name on Kubernetes export 089356d392b is described below commit 089356d392b5a09ea9dc9beabc39155d37bfdfde Author: Christoph Deppisch <cdeppi...@redhat.com> AuthorDate: Thu Mar 27 15:41:08 2025 +0100 CAMEL-21903: Adjustable container image name on Kubernetes export - Do not set container image name on Kubernetes deployment - Use `jkube.container-image.name` setting in the generated Maven project instead - Allows users to overwrite the container image name in Maven builds (e.g. when using a CI/CD pipeline) --- .../core/commands/kubernetes/KubernetesExport.java | 11 +-- .../commands/kubernetes/traits/ContainerTrait.java | 8 +- .../commands/kubernetes/traits/TraitHelper.java | 37 +++++---- .../commands/kubernetes/KubernetesExportTest.java | 92 +++++++++++++++++++--- 4 files changed, 112 insertions(+), 36 deletions(-) diff --git a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java index 3b9c8f7a695..44263c016a0 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java +++ b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java @@ -278,24 +278,15 @@ public class KubernetesExport extends Export { openapi = null; } TraitHelper.configureContainerImage(traitsSpec, image, - resolvedImageRegistry, resolvedImageGroup, projectName, getVersion()); + resolvedImageRegistry, resolvedImageGroup, projectName, getVersion(), buildProperties); TraitHelper.configureEnvVars(traitsSpec, envVars); TraitHelper.configureConnects(traitsSpec, connects); Container container = traitsSpec.getContainer(); - - buildProperties.add("jkube.image.name=%s".formatted(container.getImage())); - buildProperties.add("jkube.container-image.name=%s".formatted(container.getImage())); - if (container.getName() != null && !container.getName().equals(projectName)) { printer().printf("Custom container name '%s' not supported%n".formatted(container.getName())); } - if (container.getImagePullPolicy() != null) { - var imagePullPolicy = container.getImagePullPolicy().getValue(); - buildProperties.add("jkube.container-image.imagePullPolicy=%s".formatted(imagePullPolicy)); - } - buildProperties.add("jkube.skip.push=%b".formatted(!imagePush)); if (ClusterType.OPENSHIFT.isEqualTo(clusterType)) { diff --git a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/ContainerTrait.java b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/ContainerTrait.java index 549f7f58241..03dfe897268 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/ContainerTrait.java +++ b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/ContainerTrait.java @@ -25,6 +25,7 @@ import io.fabric8.kubernetes.api.model.Quantity; import io.fabric8.kubernetes.api.model.ResourceRequirementsBuilder; import org.apache.camel.dsl.jbang.core.commands.kubernetes.traits.model.Container; import org.apache.camel.dsl.jbang.core.commands.kubernetes.traits.model.Traits; +import org.apache.camel.util.ObjectHelper; public class ContainerTrait extends BaseTrait { @@ -48,8 +49,11 @@ public class ContainerTrait extends BaseTrait { Container containerTrait = Optional.ofNullable(traitConfig.getContainer()).orElseGet(Container::new); ContainerBuilder container = new ContainerBuilder() - .withName(Optional.ofNullable(containerTrait.getName()).orElse(context.getName())) - .withImage(containerTrait.getImage()); + .withName(Optional.ofNullable(containerTrait.getName()).orElse(context.getName())); + + if (ObjectHelper.isNotEmpty(containerTrait.getImage())) { + container.withImage(containerTrait.getImage()); + } if (containerTrait.getImagePullPolicy() != null) { container.withImagePullPolicy(containerTrait.getImagePullPolicy().getValue()); diff --git a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/TraitHelper.java b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/TraitHelper.java index f8d3461f5c5..9a326228375 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/TraitHelper.java +++ b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/TraitHelper.java @@ -275,12 +275,12 @@ public final class TraitHelper { } public static void configureContainerImage( - Traits traitsSpec, String image, String imageRegistry, String imageGroup, String imageName, String version) { - Container containerTrait = Optional.ofNullable(traitsSpec.getContainer()).orElseGet(Container::new); + Traits traitsSpec, String image, String imageRegistry, String imageGroup, + String imageName, String version, List<String> buildProperties) { + String imageToUse; if (image != null) { - containerTrait.setImage(image); - traitsSpec.setContainer(containerTrait); - } else if (containerTrait.getImage() == null) { + imageToUse = image; + } else { String registryPrefix = ""; if ("minikube".equals(imageRegistry) || "minikube-registry".equals(imageRegistry)) { registryPrefix = "localhost:5000/"; @@ -290,18 +290,27 @@ public final class TraitHelper { registryPrefix = imageRegistry + "/"; } - var resolvedImageName = getResolvedImageName(imageGroup, imageName, version); - containerTrait.setImage("%s%s".formatted(registryPrefix, resolvedImageName)); + imageToUse = "%s%s".formatted(registryPrefix, getResolvedImageName(imageGroup, imageName, version)); + } - // Plain export command always exposes a health endpoint on 8080. - // Skip this, when we decide that the health endpoint can be disabled. - if (containerTrait.getPort() == null) { - containerTrait.setPortName(ContainerTrait.DEFAULT_CONTAINER_PORT_NAME); - containerTrait.setPort((long) ContainerTrait.DEFAULT_CONTAINER_PORT); - } + buildProperties.add("jkube.image.name=%s".formatted(imageToUse)); + buildProperties.add("jkube.container-image.name=%s".formatted(imageToUse)); - traitsSpec.setContainer(containerTrait); + Container containerTrait = Optional.ofNullable(traitsSpec.getContainer()).orElseGet(Container::new); + + if (containerTrait.getImagePullPolicy() != null) { + var imagePullPolicy = containerTrait.getImagePullPolicy().getValue(); + buildProperties.add("jkube.container-image.imagePullPolicy=%s".formatted(imagePullPolicy)); + } + + // Plain export command always exposes a health endpoint on 8080. + // Skip this, when we decide that the health endpoint can be disabled. + if (containerTrait.getPort() == null) { + containerTrait.setPortName(ContainerTrait.DEFAULT_CONTAINER_PORT_NAME); + containerTrait.setPort((long) ContainerTrait.DEFAULT_CONTAINER_PORT); } + + traitsSpec.setContainer(containerTrait); } public static String getResolvedImageName(String imageGroup, String imageName, String version) { diff --git a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExportTest.java b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExportTest.java index 2385e78d268..97db5fa3106 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExportTest.java +++ b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExportTest.java @@ -64,6 +64,7 @@ class KubernetesExportTest extends KubernetesExportBaseTest { Properties props = model.getProperties(); Assertions.assertEquals("examples/route:1.0.0", props.get("jkube.image.name")); + Assertions.assertEquals("examples/route:1.0.0", props.get("jkube.container-image.name")); Assertions.assertEquals("eclipse-temurin:17", props.get("jkube.container-image.from")); Assertions.assertEquals("jib", props.get("jkube.build.strategy")); Assertions.assertNull(props.get("jkube.docker.push.registry")); @@ -106,6 +107,7 @@ class KubernetesExportTest extends KubernetesExportBaseTest { Properties props = model.getProperties(); Assertions.assertEquals("quay.io/camel-riders/route:1.0-SNAPSHOT", props.get("jkube.image.name")); + Assertions.assertEquals("quay.io/camel-riders/route:1.0-SNAPSHOT", props.get("jkube.container-image.name")); Assertions.assertEquals("mirror.gcr.io/my-base-image:latest", props.get("jkube.container-image.from")); Assertions.assertEquals("docker", props.get("jkube.build.strategy")); Assertions.assertEquals("quay.io", props.get("jkube.docker.push.registry")); @@ -130,7 +132,16 @@ class KubernetesExportTest extends KubernetesExportBaseTest { Assertions.assertEquals("route", labels.get(BaseTrait.KUBERNETES_LABEL_NAME)); Assertions.assertEquals("route", containers.get(0).getName()); Assertions.assertEquals("route", matchLabels.get(BaseTrait.KUBERNETES_LABEL_NAME)); - Assertions.assertEquals("quay.io/camel-test/route:1.0-SNAPSHOT", containers.get(0).getImage()); + Assertions.assertNull(containers.get(0).getImage()); + + Model model = readMavenModel(); + Assertions.assertEquals("org.example.project", model.getGroupId()); + Assertions.assertEquals("route", model.getArtifactId()); + Assertions.assertEquals("1.0-SNAPSHOT", model.getVersion()); + + Properties props = model.getProperties(); + Assertions.assertEquals("quay.io/camel-test/route:1.0-SNAPSHOT", props.get("jkube.image.name")); + Assertions.assertEquals("quay.io/camel-test/route:1.0-SNAPSHOT", props.get("jkube.container-image.name")); Assertions.assertTrue(hasService(rt)); Assertions.assertFalse(hasKnativeService(rt)); @@ -155,7 +166,16 @@ class KubernetesExportTest extends KubernetesExportBaseTest { Assertions.assertEquals("route", labels.get(BaseTrait.KUBERNETES_LABEL_NAME)); Assertions.assertEquals("route", containers.get(0).getName()); Assertions.assertEquals("route", matchLabels.get(BaseTrait.KUBERNETES_LABEL_NAME)); - Assertions.assertEquals("camel-test/route:1.0-SNAPSHOT", containers.get(0).getImage()); + Assertions.assertNull(containers.get(0).getImage()); + + Model model = readMavenModel(); + Assertions.assertEquals("org.example.project", model.getGroupId()); + Assertions.assertEquals("route", model.getArtifactId()); + Assertions.assertEquals("1.0-SNAPSHOT", model.getVersion()); + + Properties props = model.getProperties(); + Assertions.assertEquals("camel-test/route:1.0-SNAPSHOT", props.get("jkube.image.name")); + Assertions.assertEquals("camel-test/route:1.0-SNAPSHOT", props.get("jkube.container-image.name")); Assertions.assertTrue(hasService(rt)); Assertions.assertFalse(hasKnativeService(rt)); @@ -187,11 +207,20 @@ class KubernetesExportTest extends KubernetesExportBaseTest { Container container = deployment.getSpec().getTemplate().getSpec().getContainers().get(0); Assertions.assertEquals("route", deployment.getMetadata().getName()); Assertions.assertEquals(1, deployment.getSpec().getTemplate().getSpec().getContainers().size()); - Assertions.assertEquals("route:1.0-SNAPSHOT", container.getImage()); + Assertions.assertNull(container.getImage()); Assertions.assertEquals(1, container.getPorts().size()); Assertions.assertEquals("http", container.getPorts().get(0).getName()); Assertions.assertEquals(8080, container.getPorts().get(0).getContainerPort()); + Model model = readMavenModel(); + Assertions.assertEquals("org.example.project", model.getGroupId()); + Assertions.assertEquals("route", model.getArtifactId()); + Assertions.assertEquals("1.0-SNAPSHOT", model.getVersion()); + + Properties props = model.getProperties(); + Assertions.assertEquals("route:1.0-SNAPSHOT", props.get("jkube.image.name")); + Assertions.assertEquals("route:1.0-SNAPSHOT", props.get("jkube.container-image.name")); + Service service = getService(rt); List<ServicePort> ports = service.getSpec().getPorts(); Assertions.assertEquals("route", service.getMetadata().getName()); @@ -218,11 +247,20 @@ class KubernetesExportTest extends KubernetesExportBaseTest { Container container = deployment.getSpec().getTemplate().getSpec().getContainers().get(0); Assertions.assertEquals("route-service", deployment.getMetadata().getName()); Assertions.assertEquals(1, deployment.getSpec().getTemplate().getSpec().getContainers().size()); - Assertions.assertEquals("route-service:1.0-SNAPSHOT", container.getImage()); + Assertions.assertNull(container.getImage()); Assertions.assertEquals(1, container.getPorts().size()); Assertions.assertEquals("http", container.getPorts().get(0).getName()); Assertions.assertEquals(8080, container.getPorts().get(0).getContainerPort()); + Model model = readMavenModel(); + Assertions.assertEquals("org.example.project", model.getGroupId()); + Assertions.assertEquals("route-service", model.getArtifactId()); + Assertions.assertEquals("1.0-SNAPSHOT", model.getVersion()); + + Properties props = model.getProperties(); + Assertions.assertEquals("route-service:1.0-SNAPSHOT", props.get("jkube.image.name")); + Assertions.assertEquals("route-service:1.0-SNAPSHOT", props.get("jkube.container-image.name")); + Service service = getService(rt); List<ServicePort> ports = service.getSpec().getPorts(); Assertions.assertEquals("route-service", service.getMetadata().getName()); @@ -258,11 +296,20 @@ class KubernetesExportTest extends KubernetesExportBaseTest { Container container = deployment.getSpec().getTemplate().getSpec().getContainers().get(0); Assertions.assertEquals("route-service", deployment.getMetadata().getName()); Assertions.assertEquals(1, deployment.getSpec().getTemplate().getSpec().getContainers().size()); - Assertions.assertEquals("route-service:1.0-SNAPSHOT", container.getImage()); + Assertions.assertNull(container.getImage()); Assertions.assertEquals(1, container.getPorts().size()); Assertions.assertEquals("http", container.getPorts().get(0).getName()); Assertions.assertEquals(8080, container.getPorts().get(0).getContainerPort()); + Model model = readMavenModel(); + Assertions.assertEquals("org.example.project", model.getGroupId()); + Assertions.assertEquals("route-service", model.getArtifactId()); + Assertions.assertEquals("1.0-SNAPSHOT", model.getVersion()); + + Properties props = model.getProperties(); + Assertions.assertEquals("route-service:1.0-SNAPSHOT", props.get("jkube.image.name")); + Assertions.assertEquals("route-service:1.0-SNAPSHOT", props.get("jkube.container-image.name")); + Ingress ingress = getIngress(rt); Assertions.assertEquals("route-service", ingress.getMetadata().getName()); Assertions.assertEquals("example.com", ingress.getSpec().getRules().get(0).getHost()); @@ -307,11 +354,20 @@ class KubernetesExportTest extends KubernetesExportBaseTest { Container container = deployment.getSpec().getTemplate().getSpec().getContainers().get(0); Assertions.assertEquals("route-service", deployment.getMetadata().getName()); Assertions.assertEquals(1, deployment.getSpec().getTemplate().getSpec().getContainers().size()); - Assertions.assertEquals("route-service:1.0-SNAPSHOT", container.getImage()); + Assertions.assertNull(container.getImage()); Assertions.assertEquals(1, container.getPorts().size()); Assertions.assertEquals("http", container.getPorts().get(0).getName()); Assertions.assertEquals(8080, container.getPorts().get(0).getContainerPort()); + Model model = readMavenModel(); + Assertions.assertEquals("org.example.project", model.getGroupId()); + Assertions.assertEquals("route-service", model.getArtifactId()); + Assertions.assertEquals("1.0-SNAPSHOT", model.getVersion()); + + Properties props = model.getProperties(); + Assertions.assertEquals("route-service:1.0-SNAPSHOT", props.get("jkube.image.name")); + Assertions.assertEquals("route-service:1.0-SNAPSHOT", props.get("jkube.container-image.name")); + Route route = getRoute(rt); Assertions.assertEquals("route-service", route.getMetadata().getName()); Assertions.assertEquals("example.com", route.getSpec().getHost()); @@ -359,8 +415,7 @@ class KubernetesExportTest extends KubernetesExportBaseTest { Deployment deployment = getDeployment(rt); Assertions.assertEquals("route-service", deployment.getMetadata().getName()); Assertions.assertEquals(1, deployment.getSpec().getTemplate().getSpec().getContainers().size()); - Assertions.assertEquals("camel-test/route-service:1.0.0", - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage()); + Assertions.assertNull(deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage()); Assertions.assertEquals("IfNotPresent", deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImagePullPolicy()); Assertions.assertEquals(1, deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getPorts().size()); @@ -381,6 +436,15 @@ class KubernetesExportTest extends KubernetesExportBaseTest { deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getResources().getLimits().get("memory") .toString()); + Model model = readMavenModel(); + Assertions.assertEquals("camel-test", model.getGroupId()); + Assertions.assertEquals("route-service", model.getArtifactId()); + Assertions.assertEquals("1.0.0", model.getVersion()); + + Properties props = model.getProperties(); + Assertions.assertEquals("camel-test/route-service:1.0.0", props.get("jkube.image.name")); + Assertions.assertEquals("camel-test/route-service:1.0.0", props.get("jkube.container-image.name")); + Service service = getService(rt); Assertions.assertEquals("route-service", service.getMetadata().getName()); Assertions.assertEquals(1, service.getSpec().getPorts().size()); @@ -553,7 +617,15 @@ class KubernetesExportTest extends KubernetesExportBaseTest { Deployment deployment = getDeployment(rt); Assertions.assertEquals("demo-app", deployment.getMetadata().getName()); Assertions.assertEquals(1, deployment.getSpec().getTemplate().getSpec().getContainers().size()); - Assertions.assertEquals("quay.io/camel/demo-app:1.0", - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage()); + Assertions.assertNull(deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage()); + + Model model = readMavenModel(); + Assertions.assertEquals("org.example.project", model.getGroupId()); + Assertions.assertEquals("demo-app", model.getArtifactId()); + Assertions.assertEquals("1.0", model.getVersion()); + + Properties props = model.getProperties(); + Assertions.assertEquals("quay.io/camel/demo-app:1.0", props.get("jkube.image.name")); + Assertions.assertEquals("quay.io/camel/demo-app:1.0", props.get("jkube.container-image.name")); } }