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 22e73302fa7 CAMEL-21087: Add jolokia trait to Camel Jbang Kubernetes 
plugin (#18159)
22e73302fa7 is described below

commit 22e73302fa7cb4cf99955eaaad3b09a6c99234ef
Author: Gaƫlle Fournier <gaelle.fournier.w...@gmail.com>
AuthorDate: Fri May 23 08:15:50 2025 +0200

    CAMEL-21087: Add jolokia trait to Camel Jbang Kubernetes plugin (#18159)
---
 .../modules/ROOT/pages/camel-jbang-kubernetes.adoc | 104 +++++++++++++++++++
 .../commands/kubernetes/traits/JolokiaTrait.java   |  93 +++++++++++++++++
 .../commands/kubernetes/traits/TraitCatalog.java   |   1 +
 .../commands/kubernetes/traits/model/Jolokia.java  | 110 +++++++++++++++++++++
 .../kubernetes/traits/model/JolokiaBuilder.java    |  74 ++++++++++++++
 .../commands/kubernetes/traits/model/Traits.java   |  16 ++-
 .../commands/kubernetes/KubernetesExportTest.java  |  45 +++++++++
 7 files changed, 442 insertions(+), 1 deletion(-)

diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-kubernetes.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-jbang-kubernetes.adoc
index 58aec45a7f7..974d61425bc 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang-kubernetes.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-kubernetes.adoc
@@ -1222,6 +1222,110 @@ spec:
 <6> Service Resource reference
 
 
+=== Jolokia trait options
+
+The Jolokia trait enhances the Kubernetes manifest enabling JMX access to 
Camel application. This requires jolokia being configured in the Camel 
Application.
+
+The Jolokia trait provides the following configuration options:
+
+[cols="2m,1m,5a"]
+|===
+|Property | Type | Description
+
+| jolokia.enabled
+| bool
+| Can be used to enable or disable a trait. All traits share this common 
property. (default `false`).
+
+| jolokia.container-port
+| int
+| To configure a different jolokia port exposed by the container (default 
`8778`).
+
+| jolokia.container-port-name
+| string
+| To configure a different port name for the port exposed by the container 
(default `jolokia`).
+
+| jolokia.expose
+| bool
+| Can be used to enable/disable exposure of jolokia via kubernetes Service. 
(default `false`).
+
+| jolokia.service-port
+| int
+| To configure a different jolokia port exposed by the service (default 
`8778`). It is applied only when the expose parameter is true.
+
+| jolokia.service-port-name
+| string
+| To configure a different port name for the port exposed by the service 
(default `jolokia`). It is applied only when the expose parameter is true.
+
+
+|===
+
+The syntax to specify jolokia trait options is as follows:
+
+[source,bash]
+----
+camel kubernetes export Sample.java --trait jolokia.[key]=[value]
+----
+
+You may specify these options with the export command to customize the 
Container and Service Resource specification for Jolokia.
+
+[source,bash]
+----
+camel kubernetes export Sample.java --trait jolokia.enabled=true --trait 
jolokia.container-port=8779 --trait jolokia.container-port-name=jolokia-port 
--trait jolokia.expose=true --trait jolokia.service-port=8779 --trait 
jolokia.service-port-name=port-jolokia
+----
+
+This results in the following specifications in the Deployment and Service 
resources.
+
+[source,yaml]
+----
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  ...
+  name: sample
+spec:
+  selector:
+  ...
+  template:
+  ...
+    spec:
+      containers:
+      - name: sample
+        ports:
+        - containerPort: 8080
+          name: http
+          protocol: TCP
+        - containerPort: 8779 #<1>
+          name: jolokia-port #<2>
+          protocol: TCP
+...
+----
+
+[source,yaml]
+----
+apiVersion: v1
+kind: Service
+metadata:
+...
+  name: sample
+spec:
+  ports:
+  - name: http
+    port: 80
+    protocol: TCP
+    targetPort: http
+  - name: jolokia-port #<3>
+    port: 8779 #<4>
+    protocol: TCP
+    targetPort: jolokia-port #<2>
+...
+----
+
+<1> Custom Jolokia container port
+<2> Custom Jolokia container port name
+<3> Custom Jolokia service port name
+<4> Custom Jolokia service port
+
+
 === OpenApi specifications
 
 You can mount OpenAPI specifications to the application container with this 
trait.
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/JolokiaTrait.java
 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/JolokiaTrait.java
new file mode 100644
index 00000000000..aeaa97ded51
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/JolokiaTrait.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.jbang.core.commands.kubernetes.traits;
+
+import java.util.Optional;
+
+import io.fabric8.kubernetes.api.model.IntOrString;
+import 
org.apache.camel.dsl.jbang.core.commands.kubernetes.traits.model.Jolokia;
+import org.apache.camel.dsl.jbang.core.commands.kubernetes.traits.model.Traits;
+
+public class JolokiaTrait extends BaseTrait {
+    public static final int JolokiaTrait = 1800;
+
+    public static final int DEFAULT_JOLOKIA_PORT = 8778;
+    public static final String DEFAULT_JOLOKIA_PORT_NAME = "jolokia";
+    public static final String DEFAULT_JOLOKIA_PORT_PROTOCOL = "TCP";
+
+    public JolokiaTrait() {
+        super("jolokia", JolokiaTrait);
+    }
+
+    @Override
+    public boolean configure(Traits traitConfig, TraitContext context) {
+        // must be explicitly enabled
+        if (traitConfig.getJolokia() == null) {
+            return false;
+        } else {
+            return 
Optional.ofNullable(traitConfig.getJolokia().getEnabled()).orElse(false);
+        }
+    }
+
+    @Override
+    public void apply(Traits traitConfig, TraitContext context) {
+        Jolokia jolokiaTrait = 
Optional.ofNullable(traitConfig.getJolokia()).orElseGet(Jolokia::new);
+
+        context.doWithDeployments(
+                d -> d.editSpec()
+                        .editTemplate()
+                        .editSpec()
+                        .editFirstContainer()
+                        .addNewPort()
+                        
.withName(Optional.ofNullable(jolokiaTrait.getContainerPortName()).orElse(DEFAULT_JOLOKIA_PORT_NAME))
+                        
.withContainerPort(Optional.ofNullable(jolokiaTrait.getContainerPort()).map(Long::intValue)
+                                .orElse(DEFAULT_JOLOKIA_PORT))
+                        .withProtocol(DEFAULT_JOLOKIA_PORT_PROTOCOL)
+                        .endPort()
+                        .endContainer()
+                        .endSpec()
+                        .endTemplate()
+                        .endSpec());
+        context.doWithKnativeServices(
+                s -> s.editSpec()
+                        .editTemplate()
+                        .editSpec()
+                        .editFirstContainer()
+                        .addNewPort()
+                        
.withName(Optional.ofNullable(jolokiaTrait.getContainerPortName()).orElse(DEFAULT_JOLOKIA_PORT_NAME))
+                        
.withContainerPort(Optional.ofNullable(jolokiaTrait.getContainerPort()).map(Long::intValue)
+                                .orElse(DEFAULT_JOLOKIA_PORT))
+                        .withProtocol(DEFAULT_JOLOKIA_PORT_PROTOCOL)
+                        .endPort()
+                        .endContainer()
+                        .endSpec()
+                        .endTemplate()
+                        .endSpec());
+        context.doWithServices(
+                s -> s.editSpec()
+                        .addNewPort()
+                        
.withName(Optional.ofNullable(jolokiaTrait.getServicePortName()).orElse(DEFAULT_JOLOKIA_PORT_NAME))
+                        
.withPort(Optional.ofNullable(jolokiaTrait.getServicePort()).map(Long::intValue)
+                                .orElse(DEFAULT_JOLOKIA_PORT))
+                        .withTargetPort(new IntOrString(
+                                
Optional.ofNullable(jolokiaTrait.getContainerPortName()).orElse(DEFAULT_JOLOKIA_PORT_NAME)))
+                        .endPort()
+                        .endSpec());
+
+    }
+
+}
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/TraitCatalog.java
 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/TraitCatalog.java
index d6205b5686a..0a491f818aa 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/TraitCatalog.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/TraitCatalog.java
@@ -51,6 +51,7 @@ public class TraitCatalog {
         register(new LabelTrait());
         register(new AnnotationTrait());
         register(new CamelTrait());
+        register(new JolokiaTrait());
     }
 
     public List<Trait> allTraits() {
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/model/Jolokia.java
 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/model/Jolokia.java
new file mode 100644
index 00000000000..8927bb95451
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/model/Jolokia.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.jbang.core.commands.kubernetes.traits.model;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyDescription;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.annotation.JsonSetter;
+import com.fasterxml.jackson.annotation.Nulls;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({
+        "enabled", "containerPort", "containerPortName", "expose", 
"servicePort", "servicePortName" })
+public class Jolokia {
+    @JsonProperty("enabled")
+    @JsonPropertyDescription("Can be used to enable or disable a trait.")
+    @JsonSetter(nulls = Nulls.SKIP)
+    private Boolean enabled;
+    @JsonProperty("containerPort")
+    @JsonPropertyDescription("To configure a different jolokia port exposed by 
the container (default `8778`).")
+    @JsonSetter(
+                nulls = Nulls.SKIP)
+    private Long containerPort;
+    @JsonProperty("containerPortName")
+    @JsonPropertyDescription("To configure a different jolokia port name for 
the port exposed by the container. It defaults to `jolokia`.")
+    @JsonSetter(
+                nulls = Nulls.SKIP)
+    private String containerPortName;
+    @JsonProperty("expose")
+    @JsonPropertyDescription("Can be used to enable/disable jolokia exposure 
via kubernetes Service. Requires Service to be enabled to be applicable.")
+    @JsonSetter(
+                nulls = Nulls.SKIP)
+    private Boolean expose;
+    @JsonProperty("servicePort")
+    @JsonPropertyDescription("To configure a different jolokia port exposed by 
the service (default `8778`).")
+    @JsonSetter(
+                nulls = Nulls.SKIP)
+    private Long servicePort;
+    @JsonProperty("servicePortName")
+    @JsonPropertyDescription("To configure a different jolokia port name for 
the port exposed by the service. It defaults to `jolokia`.")
+    @JsonSetter(
+                nulls = Nulls.SKIP)
+    private String servicePortName;
+
+    public Jolokia() {
+    }
+
+    public Boolean getEnabled() {
+        return this.enabled;
+    }
+
+    public void setEnabled(Boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public Long getContainerPort() {
+        return this.containerPort;
+    }
+
+    public void setContainerPort(Long port) {
+        this.containerPort = port;
+    }
+
+    public String getContainerPortName() {
+        return this.containerPortName;
+    }
+
+    public void setContainerPortName(String portName) {
+        this.containerPortName = portName;
+    }
+
+    public Boolean getExpose() {
+        return this.expose;
+    }
+
+    public void setExpose(Boolean expose) {
+        this.expose = expose;
+    }
+
+    public Long getServicePort() {
+        return this.servicePort;
+    }
+
+    public void setServicePort(Long port) {
+        this.servicePort = port;
+    }
+
+    public String getServicePortName() {
+        return this.servicePortName;
+    }
+
+    public void setServicePortName(String portName) {
+        this.servicePortName = portName;
+    }
+}
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/model/JolokiaBuilder.java
 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/model/JolokiaBuilder.java
new file mode 100644
index 00000000000..5b3864875b5
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/model/JolokiaBuilder.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.jbang.core.commands.kubernetes.traits.model;
+
+public final class JolokiaBuilder {
+    private Boolean enabled;
+    private Long containerPort;
+    private String containerPortName;
+    private Boolean expose;
+    private Long servicePort;
+    private String servicePortName;
+
+    private JolokiaBuilder() {
+    }
+
+    public static JolokiaBuilder jolokia() {
+        return new JolokiaBuilder();
+    }
+
+    public JolokiaBuilder withEnabled(Boolean enabled) {
+        this.enabled = enabled;
+        return this;
+    }
+
+    public JolokiaBuilder withContainerPort(Long port) {
+        this.containerPort = port;
+        return this;
+    }
+
+    public JolokiaBuilder withContainerPortName(String portName) {
+        this.containerPortName = portName;
+        return this;
+    }
+
+    public JolokiaBuilder withExpose(Boolean expose) {
+        this.expose = expose;
+        return this;
+    }
+
+    public JolokiaBuilder withServicePort(Long port) {
+        this.servicePort = port;
+        return this;
+    }
+
+    public JolokiaBuilder withServicePortName(String portName) {
+        this.servicePortName = portName;
+        return this;
+    }
+
+    public Jolokia build() {
+        Jolokia jolokia = new Jolokia();
+        jolokia.setEnabled(enabled);
+        jolokia.setContainerPort(containerPort);
+        jolokia.setContainerPortName(containerPortName);
+        jolokia.setExpose(expose);
+        jolokia.setServicePort(servicePort);
+        jolokia.setServicePortName(servicePortName);
+        return jolokia;
+    }
+}
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/model/Traits.java
 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/model/Traits.java
index 88e15c7f51e..512f53fe37b 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/model/Traits.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/model/Traits.java
@@ -29,7 +29,7 @@ import com.fasterxml.jackson.annotation.Nulls;
 @JsonInclude(JsonInclude.Include.NON_NULL)
 @JsonPropertyOrder({
         "camel", "container", "environment", "ingress", "knative", 
"knative-service", "mount", "openapi", "pod", "route",
-        "service", "service-binding" })
+        "service", "service-binding", "jolokia" })
 public class Traits {
 
     @JsonProperty("addons")
@@ -86,11 +86,17 @@ public class Traits {
     @JsonPropertyDescription("The configuration of Service trait")
     @JsonSetter(nulls = Nulls.SKIP)
     private Service service;
+
     @JsonProperty("service-binding")
     @JsonPropertyDescription("The configuration of Service Binding trait")
     @JsonSetter(nulls = Nulls.SKIP)
     private ServiceBinding serviceBinding;
 
+    @JsonProperty("jolokia")
+    @JsonPropertyDescription("The configuration of Jolokia trait")
+    @JsonSetter(nulls = Nulls.SKIP)
+    private Jolokia jolokia;
+
     public Map<String, Addons> getAddons() {
         return this.addons;
     }
@@ -171,6 +177,14 @@ public class Traits {
         this.route = route;
     }
 
+    public Jolokia getJolokia() {
+        return jolokia;
+    }
+
+    public void setJolokia(Jolokia jolokia) {
+        this.jolokia = jolokia;
+    }
+
     public Service getService() {
         return service;
     }
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 97db5fa3106..af3a2083f74 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
@@ -628,4 +628,49 @@ class KubernetesExportTest extends 
KubernetesExportBaseTest {
         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"));
     }
+
+    @ParameterizedTest
+    @MethodSource("runtimeProvider")
+    public void shouldAddJolokiaSpec(RuntimeType rt) throws Exception {
+        KubernetesExport command = createCommand(new String[] { 
"classpath:route-service.yaml" },
+                "--trait", "jolokia.enabled=true",
+                "--trait", "jolokia.expose=true",
+                "--trait", "jolokia.service-port=8779",
+                "--trait", "jolokia.service-port-name=jolokia-port",
+                "--runtime=" + rt.runtime());
+        var exit = command.doCall();
+        Assertions.assertEquals(0, exit);
+
+        Assertions.assertTrue(hasService(rt));
+        Assertions.assertFalse(hasKnativeService(rt));
+
+        Deployment deployment = getDeployment(rt);
+        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.assertNull(container.getImage());
+        Assertions.assertEquals(2, container.getPorts().size());
+        Assertions.assertEquals("jolokia", 
container.getPorts().get(1).getName());
+        Assertions.assertEquals(8778, 
container.getPorts().get(1).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());
+        Assertions.assertEquals(2, ports.size());
+        Assertions.assertEquals("http", ports.get(0).getName());
+        Assertions.assertEquals(80, ports.get(0).getPort());
+        Assertions.assertEquals("http", 
ports.get(0).getTargetPort().getStrVal());
+        Assertions.assertEquals("jolokia-port", ports.get(1).getName());
+        Assertions.assertEquals(8779, ports.get(1).getPort());
+        Assertions.assertEquals("jolokia", 
ports.get(1).getTargetPort().getStrVal());
+    }
 }

Reply via email to