This is an automated email from the ASF dual-hosted git repository.
davsclaus 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 19e52982123f CAMEL-26934: camel-jbang-plugin-kubernetes - env, mounts,
labels and annotations apply to a CronJob and a Knative Service (#29932)
19e52982123f is described below
commit 19e52982123fbc04219a7b8bdfbec10f3df7b4b5
Author: Claus Ibsen <[email protected]>
AuthorDate: Sat Nov 14 19:28:01 2026 +0100
CAMEL-26934: camel-jbang-plugin-kubernetes - env, mounts, labels and
annotations apply to a CronJob and a Knative Service (#29932)
A kubernetes export with the CronJob trait dropped --env, --config,
--volume and
--annotation, and a Knative Service lost the env and the labels: EnvTrait
was not used
without a Deployment and, like MountTrait, applied to the Deployment only;
LabelTrait
skipped the Knative Service and AnnotationTrait the CronJob. Each applies
to the
workload there is now.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
.../kubernetes/traits/AnnotationTrait.java | 5 ++
.../core/commands/kubernetes/traits/EnvTrait.java | 56 ++++++++++++++++------
.../commands/kubernetes/traits/LabelTrait.java | 6 +++
.../commands/kubernetes/traits/MountTrait.java | 28 +++++++++++
.../kubernetes/KubernetesExportKnativeTest.java | 26 +++++++++-
.../commands/kubernetes/KubernetesExportTest.java | 23 +++++++++
6 files changed, 128 insertions(+), 16 deletions(-)
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/AnnotationTrait.java
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/AnnotationTrait.java
index be6d7fd367af..c9827410bffb 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/AnnotationTrait.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/AnnotationTrait.java
@@ -44,5 +44,10 @@ public class AnnotationTrait extends BaseTrait {
s -> s.editOrNewMetadata()
.addToAnnotations(context.getAnnotations())
.endMetadata());
+ // a CronJob had none (CAMEL-26934)
+ context.doWithCronJobs(
+ j -> j.editOrNewMetadata()
+ .addToAnnotations(context.getAnnotations())
+ .endMetadata());
}
}
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/EnvTrait.java
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/EnvTrait.java
index f7556cc88b68..4d03c0567fde 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/EnvTrait.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/EnvTrait.java
@@ -17,11 +17,12 @@
package org.apache.camel.dsl.jbang.core.commands.kubernetes.traits;
+import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
+import io.fabric8.kubernetes.api.model.EnvVar;
import io.fabric8.kubernetes.api.model.EnvVarBuilder;
-import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder;
import org.apache.camel.RuntimeCamelException;
import
org.apache.camel.dsl.jbang.core.commands.kubernetes.traits.model.Environment;
import org.apache.camel.dsl.jbang.core.commands.kubernetes.traits.model.Traits;
@@ -35,8 +36,8 @@ public class EnvTrait extends BaseTrait {
@Override
public boolean configure(Traits traitConfig, TraitContext context) {
- Optional<DeploymentBuilder> deployment = context.getDeployment();
- if (deployment.isEmpty()) {
+ // a workload: a Deployment, a CronJob or a Knative Service
(CAMEL-26934: only a Deployment had the variables)
+ if (context.getDeployment().isEmpty() &&
context.getCronJob().isEmpty() && context.getKnativeService().isEmpty()) {
return false;
}
@@ -49,23 +50,48 @@ public class EnvTrait extends BaseTrait {
Environment envTrait = traitConfig.getEnvironment();
if (ObjectHelper.isNotEmpty(envTrait.getVars())) {
+ List<EnvVar> vars = envTrait.getVars().stream().map(envvar -> {
+ String[] parts = envvar.split("=", 2);
+ if (parts.length != 2) {
+ throw new RuntimeCamelException(
+ "Invalid environment variable '%s', must be in
NAME=value format".formatted(envvar));
+ }
+ return new EnvVarBuilder()
+ .withName(parts[0])
+ .withValue(parts[1])
+ .build();
+ }).collect(Collectors.toList());
context.doWithDeployments(
d -> d.editSpec()
.editTemplate()
.editSpec()
.editFirstContainer()
-
.addAllToEnv(envTrait.getVars().stream().map(envvar -> {
- String[] parts = envvar.split("=", 2);
- if (parts.length != 2) {
- throw new RuntimeCamelException(
- "Invalid environment variable
'%s', must be in NAME=value format"
- .formatted(envvar));
- }
- return new EnvVarBuilder()
- .withName(parts[0])
- .withValue(parts[1])
- .build();
- }).collect(Collectors.toList()))
+ .addAllToEnv(vars)
+ .endContainer()
+ .endSpec()
+ .endTemplate()
+ .endSpec());
+ // and the other workloads: a CronJob and a Knative Service had no
variables (CAMEL-26934)
+ context.doWithCronJobs(
+ j -> j.editOrNewSpec()
+ .editOrNewJobTemplate()
+ .editOrNewSpec()
+ .editOrNewTemplate()
+ .editOrNewSpec()
+ .editFirstContainer()
+ .addAllToEnv(vars)
+ .endContainer()
+ .endSpec()
+ .endTemplate()
+ .endSpec()
+ .endJobTemplate()
+ .endSpec());
+ context.doWithKnativeServices(
+ k -> k.editOrNewSpec()
+ .editOrNewTemplate()
+ .editOrNewSpec()
+ .editFirstContainer()
+ .addAllToEnv(vars)
.endContainer()
.endSpec()
.endTemplate()
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/LabelTrait.java
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/LabelTrait.java
index 590b14d0d50a..22143f6d054a 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/LabelTrait.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/LabelTrait.java
@@ -55,5 +55,11 @@ public class LabelTrait extends BaseTrait {
.endMetadata()
.endJobTemplate()
.endSpec());
+ // a Knative Service had none, also not app.kubernetes.io/runtime
(CAMEL-26934)
+ context.doWithKnativeServices(
+ k -> k.editOrNewMetadata()
+ .addToLabels(KUBERNETES_LABEL_NAME, context.getName())
+ .addToLabels(context.getLabels())
+ .endMetadata());
}
}
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/MountTrait.java
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/MountTrait.java
index 7738a1e649b5..f76b8cacfdc9 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/MountTrait.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/MountTrait.java
@@ -102,6 +102,34 @@ public class MountTrait extends BaseTrait {
.endSpec()
.endTemplate()
.endSpec());
+ if (volumes.isEmpty()) {
+ return;
+ }
+ // and the other workloads: a CronJob and a Knative Service had no
volumes (CAMEL-26934)
+ context.doWithCronJobs(j -> j.editOrNewSpec()
+ .editOrNewJobTemplate()
+ .editOrNewSpec()
+ .editOrNewTemplate()
+ .editOrNewSpec()
+ .addAllToVolumes(volumes)
+ .editFirstContainer()
+ .addAllToVolumeMounts(volumeMounts)
+ .endContainer()
+ .endSpec()
+ .endTemplate()
+ .endSpec()
+ .endJobTemplate()
+ .endSpec());
+ context.doWithKnativeServices(k -> k.editOrNewSpec()
+ .editOrNewTemplate()
+ .editOrNewSpec()
+ .addAllToVolumes(volumes)
+ .editFirstContainer()
+ .addAllToVolumeMounts(volumeMounts)
+ .endContainer()
+ .endSpec()
+ .endTemplate()
+ .endSpec());
}
private void configureVolumesAndMounts(Mount mountTrait, List<Volume>
volumes, List<VolumeMount> volumeMounts) {
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExportKnativeTest.java
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExportKnativeTest.java
index 2e7557595429..0db69b22519b 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExportKnativeTest.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExportKnativeTest.java
@@ -76,7 +76,9 @@ public class KubernetesExportKnativeTest extends
KubernetesExportBaseTestSupport
var labelsB =
service.getSpec().getTemplate().getMetadata().getLabels();
Map<String, String> annotations =
service.getSpec().getTemplate().getMetadata().getAnnotations();
Assertions.assertEquals("route-service",
service.getMetadata().getName());
- Assertions.assertEquals(8, labelsA.size());
+ // and app.kubernetes.io/runtime, which the Knative Service did not
have (CAMEL-26934)
+ Assertions.assertEquals(9, labelsA.size());
+ Assertions.assertEquals("camel",
labelsA.get("app.kubernetes.io/runtime"));
Assertions.assertEquals("route-service",
labelsA.get(BaseTrait.KUBERNETES_LABEL_NAME));
Assertions.assertEquals("true",
labelsA.get("bindings.knative.dev/include"));
Assertions.assertEquals("cluster-local",
labelsA.get("networking.knative.dev/visibility"));
@@ -93,6 +95,28 @@ public class KubernetesExportKnativeTest extends
KubernetesExportBaseTestSupport
Assertions.assertEquals(300,
service.getSpec().getTemplate().getSpec().getTimeoutSeconds());
}
+ @ParameterizedTest
+ @MethodSource("runtimeProvider")
+ public void theOptionsOfTheWorkloadApplyToAKnativeService(RuntimeType rt)
throws Exception {
+ // the env, the volumes and the labels were not in the Knative Service
(CAMEL-26934)
+ KubernetesExport command = createCommand(new String[] {
"classpath:route-service.yaml" },
+ "--image-group=camel-test", "--runtime=" + rt.runtime(),
"--env=MY_VAR=hello",
+ "--config=configmap:my-cm", "--label=tier=web");
+ command.traits = new String[] { "knative-service.enabled=true" };
+ Assertions.assertEquals(0, command.doCall());
+
+ Service service = getResource(rt, Service.class)
+ .orElseThrow(() -> new RuntimeCamelException("Missing Knative
service in Kubernetes manifest"));
+ var pod = service.getSpec().getTemplate().getSpec();
+ var container = pod.getContainers().get(0);
+ Assertions.assertTrue(container.getEnv().stream()
+ .anyMatch(e -> "MY_VAR".equals(e.getName()) &&
"hello".equals(e.getValue())), container.getEnv().toString());
+ Assertions.assertTrue(pod.getVolumes().stream()
+ .anyMatch(v -> v.getConfigMap() != null &&
"my-cm".equals(v.getConfigMap().getName())),
+ pod.getVolumes().toString());
+ Assertions.assertEquals("web",
service.getMetadata().getLabels().get("tier"));
+ }
+
@ParameterizedTest
@MethodSource("runtimeProvider")
public void shouldAddKnativeTrigger(RuntimeType rt) throws Exception {
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 fefb0123af96..332561c3eb4b 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
@@ -224,6 +224,29 @@ class KubernetesExportTest extends
KubernetesExportBaseTestSupport {
Assertions.assertFalse(hasKnativeService(rt));
}
+ @ParameterizedTest
+ @MethodSource("runtimeProvider")
+ public void theOptionsOfTheWorkloadApplyToACronjob(RuntimeType rt) throws
Exception {
+ // --env, --config and --annotation were not in cronjob.yml
(CAMEL-26934)
+ KubernetesExport command = createCommand(new String[] {
"classpath:route.yaml" },
+ "--image-group=camel-test", "--runtime=" + rt.runtime(),
"--env=MY_VAR=hello",
+ "--config=configmap:my-cm", "--annotation=team=ops");
+ command.traits = new String[] { "cronjob.enabled=true",
"cronjob.schedule=\"0 22 * * 1-5\"" };
+ Assertions.assertEquals(0, command.doCall());
+
+ CronJob cronjob = getResource(rt, CronJob.class)
+ .orElseThrow(() -> new RuntimeCamelException("Cannot find
cronjob for: %s".formatted(rt.runtime())));
+ var pod =
cronjob.getSpec().getJobTemplate().getSpec().getTemplate().getSpec();
+ var container = pod.getContainers().get(0);
+ Assertions.assertTrue(container.getEnv().stream()
+ .anyMatch(e -> "MY_VAR".equals(e.getName()) &&
"hello".equals(e.getValue())), container.getEnv().toString());
+ Assertions.assertTrue(pod.getVolumes().stream()
+ .anyMatch(v -> v.getConfigMap() != null &&
"my-cm".equals(v.getConfigMap().getName())),
+ pod.getVolumes().toString());
+ Assertions.assertFalse(container.getVolumeMounts().isEmpty());
+ Assertions.assertEquals("ops",
cronjob.getMetadata().getAnnotations().get("team"));
+ }
+
@ParameterizedTest
@MethodSource("runtimeProvider")
public void shouldGenerateCronjobKubernetesManifest(RuntimeType rt) throws
Exception {