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 b8f912555ea CAMEL-20645: Support trait addons in Camel K JBang plugin 
(#14601)
b8f912555ea is described below

commit b8f912555ea27749ed692abe66340ecfeec1583e
Author: Christoph Deppisch <[email protected]>
AuthorDate: Thu Jun 20 07:10:17 2024 +0200

    CAMEL-20645: Support trait addons in Camel K JBang plugin (#14601)
---
 .../camel/component/knative/KnativeEndpoint.java   |   2 +-
 .../knative/ce/AbstractCloudEventProcessor.java    |   4 +-
 .../camel/dsl/jbang/core/commands/k/Bind.java      |  12 +-
 .../dsl/jbang/core/commands/k/IntegrationRun.java  |  70 +-----
 .../jbang/core/commands/k/KubernetesHelper.java    |  11 +
 .../dsl/jbang/core/commands/k/TraitHelper.java     | 222 ++++++++++++++-----
 .../camel/dsl/jbang/core/commands/k/BindTest.java  |   2 +-
 .../jbang/core/commands/k/IntegrationRunTest.java  | 237 +++++++++++----------
 .../jbang/core/commands/k/KubeCommandMainTest.java |  13 +-
 .../dsl/jbang/core/commands/k/integration.yaml     |  13 +-
 .../src/test/resources/route.yaml                  |   2 +-
 11 files changed, 342 insertions(+), 246 deletions(-)

diff --git 
a/components/camel-knative/camel-knative-component/src/main/java/org/apache/camel/component/knative/KnativeEndpoint.java
 
b/components/camel-knative/camel-knative-component/src/main/java/org/apache/camel/component/knative/KnativeEndpoint.java
index 70f58aa359b..151d3ed8e3a 100644
--- 
a/components/camel-knative/camel-knative-component/src/main/java/org/apache/camel/component/knative/KnativeEndpoint.java
+++ 
b/components/camel-knative/camel-knative-component/src/main/java/org/apache/camel/component/knative/KnativeEndpoint.java
@@ -228,7 +228,7 @@ public class KnativeEndpoint extends DefaultEndpoint {
         }
 
         //
-        // For event type endpoints se need to add a filter to filter out 
events received
+        // For event type endpoints we need to add a filter to filter out 
events received
         // based on the given type.
         //
         if (resource.getType() == Knative.Type.event && 
ObjectHelper.isNotEmpty(configuration.getTypeId())) {
diff --git 
a/components/camel-knative/camel-knative-component/src/main/java/org/apache/camel/component/knative/ce/AbstractCloudEventProcessor.java
 
b/components/camel-knative/camel-knative-component/src/main/java/org/apache/camel/component/knative/ce/AbstractCloudEventProcessor.java
index da0defc29af..16cf27dd3b4 100644
--- 
a/components/camel-knative/camel-knative-component/src/main/java/org/apache/camel/component/knative/ce/AbstractCloudEventProcessor.java
+++ 
b/components/camel-knative/camel-knative-component/src/main/java/org/apache/camel/component/knative/ce/AbstractCloudEventProcessor.java
@@ -92,8 +92,8 @@ abstract class AbstractCloudEventProcessor implements 
CloudEventProcessor {
             }
 
             //
-            // in case of events, if the type of the event is defined as URI 
param so we need
-            // to override it to avoid the event type be overridden by 
Messages's headers
+            // in case of events, if the type of the event is defined as URI 
param we need
+            // to override it to avoid the event type be overridden by 
Message's headers
             //
             if (endpoint.getType() == Knative.Type.event && 
endpoint.getTypeId() != null) {
                 final Object eventType = 
headers.get(CloudEvent.CAMEL_CLOUD_EVENT_TYPE);
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/Bind.java
 
b/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/Bind.java
index a1e05446c04..40a58b5e054 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/Bind.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/Bind.java
@@ -19,7 +19,6 @@ package org.apache.camel.dsl.jbang.core.commands.k;
 import java.io.InputStream;
 import java.nio.file.Path;
 import java.util.Arrays;
-import java.util.List;
 import java.util.Stack;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -29,7 +28,6 @@ import 
org.apache.camel.dsl.jbang.core.commands.bind.TemplateProvider;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.v1.Pipe;
 import org.apache.camel.v1.integrationspec.Traits;
-import org.apache.camel.v1.integrationspec.traits.ServiceBinding;
 import picocli.CommandLine;
 import picocli.CommandLine.Command;
 
@@ -165,18 +163,16 @@ public class Bind extends KubeBaseCommand {
             traitsSpec = TraitHelper.parseTraits(traits);
         }
 
-        if (connects != null && connects.length > 0) {
+        if (connects != null) {
             if (traitsSpec == null) {
                 traitsSpec = new Traits();
             }
-
-            ServiceBinding serviceBindingTrait = new ServiceBinding();
-            serviceBindingTrait.setServices(List.of(connects));
-            traitsSpec.setServiceBinding(serviceBindingTrait);
+            TraitHelper.configureConnects(traitsSpec, connects);
         }
 
         if (traitsSpec != null) {
-            String traitYaml = 
KubernetesHelper.yaml().dumpAsMap(traitsSpec).replaceAll("\n", "\n        ");
+            String traitYaml = KubernetesHelper.dumpYaml(traitsSpec);
+            traitYaml = traitYaml.replaceAll("\n", "\n        ");
             integrationSpec = "  integration:\n    spec:\n      traits:\n      
  %s\n".formatted(traitYaml.trim());
         }
 
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/IntegrationRun.java
 
b/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/IntegrationRun.java
index 4acc18ed8c2..e9cb06b6e86 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/IntegrationRun.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/IntegrationRun.java
@@ -54,13 +54,7 @@ import org.apache.camel.v1.integrationspec.Sources;
 import org.apache.camel.v1.integrationspec.Template;
 import org.apache.camel.v1.integrationspec.Traits;
 import org.apache.camel.v1.integrationspec.template.Spec;
-import org.apache.camel.v1.integrationspec.traits.Builder;
-import org.apache.camel.v1.integrationspec.traits.Camel;
 import org.apache.camel.v1.integrationspec.traits.Container;
-import org.apache.camel.v1.integrationspec.traits.Environment;
-import org.apache.camel.v1.integrationspec.traits.Mount;
-import org.apache.camel.v1.integrationspec.traits.Openapi;
-import org.apache.camel.v1.integrationspec.traits.ServiceBinding;
 import picocli.CommandLine;
 import picocli.CommandLine.Command;
 
@@ -245,7 +239,7 @@ public class IntegrationRun extends KubeBaseCommand {
         }
 
         if (image != null) {
-            Container containerTrait = new Container();
+            Container containerTrait = 
Optional.ofNullable(traitsSpec.getContainer()).orElseGet(Container::new);
             containerTrait.setImage(image);
             traitsSpec.setContainer(containerTrait);
         } else {
@@ -310,7 +304,7 @@ public class IntegrationRun extends KubeBaseCommand {
 
         if (output != null) {
             switch (output) {
-                case "yaml" -> 
printer().println(KubernetesHelper.yaml().dumpAsMap(integration));
+                case "yaml" -> 
printer().println(KubernetesHelper.dumpYaml(integration));
                 case "json" -> printer().println(
                         
JSonHelper.prettyPrint(KubernetesHelper.json().writer().writeValueAsString(integration),
 2));
                 default -> {
@@ -347,60 +341,12 @@ public class IntegrationRun extends KubeBaseCommand {
     }
 
     private void convertOptionsToTraits(Traits traitsSpec) {
-        Mount mountTrait = null;
-
-        if (configs != null && configs.length > 0) {
-            mountTrait = new Mount();
-            mountTrait.setConfigs(List.of(configs));
-        }
-
-        if (resources != null && resources.length > 0) {
-            if (mountTrait == null) {
-                mountTrait = new Mount();
-            }
-            mountTrait.setResources(List.of(resources));
-        }
-
-        if (volumes != null && volumes.length > 0) {
-            if (mountTrait == null) {
-                mountTrait = new Mount();
-            }
-            mountTrait.setVolumes(List.of(volumes));
-        }
-
-        if (mountTrait != null) {
-            traitsSpec.setMount(mountTrait);
-        }
-
-        if (openApis != null && openApis.length > 0) {
-            Openapi openapiTrait = new Openapi();
-            openapiTrait.setConfigmaps(List.of(openApis));
-            traitsSpec.setOpenapi(openapiTrait);
-        }
-
-        if (properties != null && properties.length > 0) {
-            Camel camelTrait = new Camel();
-            camelTrait.setProperties(List.of(properties));
-            traitsSpec.setCamel(camelTrait);
-        }
-
-        if (buildProperties != null && buildProperties.length > 0) {
-            Builder builderTrait = new Builder();
-            builderTrait.setProperties(List.of(buildProperties));
-            traitsSpec.setBuilder(builderTrait);
-        }
-
-        if (envVars != null && envVars.length > 0) {
-            Environment environmentTrait = new Environment();
-            environmentTrait.setVars(List.of(envVars));
-            traitsSpec.setEnvironment(environmentTrait);
-        }
-
-        if (connects != null && connects.length > 0) {
-            ServiceBinding serviceBindingTrait = new ServiceBinding();
-            serviceBindingTrait.setServices(List.of(connects));
-            traitsSpec.setServiceBinding(serviceBindingTrait);
-        }
+        TraitHelper.configureMountTrait(traitsSpec, configs, resources, 
volumes);
+        TraitHelper.configureOpenApiSpec(traitsSpec, openApis);
+        TraitHelper.configureProperties(traitsSpec, properties);
+        TraitHelper.configureBuildProperties(traitsSpec, buildProperties);
+        TraitHelper.configureEnvVars(traitsSpec, envVars);
+        TraitHelper.configureConnects(traitsSpec, connects);
     }
 
     private Source resolveSource(String source) {
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/KubernetesHelper.java
 
b/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/KubernetesHelper.java
index 20b44d7a5fa..d109082ccf8 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/KubernetesHelper.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/KubernetesHelper.java
@@ -129,4 +129,15 @@ public final class KubernetesHelper {
     static void setKubernetesClient(KubernetesClient kubernetesClient) {
         KubernetesHelper.kubernetesClient = kubernetesClient;
     }
+
+    /**
+     * Dump given domain model object as YAML. Uses Json conversion to generic 
map as intermediate step. This makes sure
+     * to properly write Json additional properties.
+     *
+     * @param  model
+     * @return
+     */
+    public static String dumpYaml(Object model) {
+        return yaml().dumpAsMap(json().convertValue(model, Map.class));
+    }
 }
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/TraitHelper.java
 
b/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/TraitHelper.java
index de40760942b..7d7aa8659ba 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/TraitHelper.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/TraitHelper.java
@@ -17,16 +17,23 @@
 
 package org.apache.camel.dsl.jbang.core.commands.k;
 
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
 
-import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.util.StringHelper;
 import org.apache.camel.v1.integrationspec.Traits;
+import org.apache.camel.v1.integrationspec.traits.AddonsBuilder;
+import org.apache.camel.v1.integrationspec.traits.Builder;
+import org.apache.camel.v1.integrationspec.traits.Camel;
+import org.apache.camel.v1.integrationspec.traits.Environment;
+import org.apache.camel.v1.integrationspec.traits.Mount;
+import org.apache.camel.v1.integrationspec.traits.Openapi;
+import org.apache.camel.v1.integrationspec.traits.ServiceBinding;
 
 /**
  * Utility class manages trait expressions and its conversion to proper trait 
model.
@@ -44,45 +51,63 @@ public final class TraitHelper {
      * @return
      */
     public static Traits parseTraits(String[] traits) {
-        try {
-            Map<String, Map<String, Object>> traitJson = new HashMap<>();
-
-            for (String traitExpression : traits) {
-                //traitName.key=value
-                final String[] trait = traitExpression.split("\\.", 2);
-                final String[] traitConfig = trait[1].split("=", 2);
-
-                // the CRD api is in CamelCase, then we have to
-                // convert the kebab-case to CamelCase
-                final String traitKey = 
StringHelper.dashToCamelCase(traitConfig[0]);
-                final Object traitValue = resolveTraitValue(traitKey, 
traitConfig[1].trim());
-                if (traitJson.containsKey(trait[0])) {
-                    Map<String, Object> config = traitJson.get(trait[0]);
-
-                    if (config.containsKey(traitKey)) {
-                        Object existingValue = config.get(traitKey);
-
-                        if (existingValue instanceof List) {
-                            List<String> values = (List<String>) existingValue;
-                            values.add(traitValue.toString());
+        Map<String, Map<String, Object>> traitConfigMap = new HashMap<>();
+
+        for (String traitExpression : traits) {
+            //traitName.key=value
+            final String[] trait = traitExpression.split("\\.", 2);
+            final String[] traitConfig = trait[1].split("=", 2);
+
+            // the CRD api is in CamelCase, then we have to
+            // convert the kebab-case to CamelCase
+            final String traitKey = 
StringHelper.dashToCamelCase(traitConfig[0]);
+            final Object traitValue = resolveTraitValue(traitKey, 
traitConfig[1].trim());
+            if (traitConfigMap.containsKey(trait[0])) {
+                Map<String, Object> config = traitConfigMap.get(trait[0]);
+
+                if (config.containsKey(traitKey)) {
+                    Object existingValue = config.get(traitKey);
+
+                    if (existingValue instanceof List) {
+                        List<String> values = (List<String>) existingValue;
+                        if (traitValue instanceof List) {
+                            List<String> traitValueList = (List<String>) 
traitValue;
+                            values.addAll(traitValueList);
                         } else {
-                            config.put(traitKey, 
Arrays.asList(existingValue.toString(), traitValue));
+                            values.add(traitValue.toString());
                         }
+                    } else if (traitValue instanceof List) {
+                        List<String> traitValueList = (List<String>) 
traitValue;
+                        traitValueList.add(0, existingValue.toString());
+                        config.put(traitKey, traitValueList);
                     } else {
-                        config.put(traitKey, initializeTraitValue(traitValue));
+                        config.put(traitKey, 
Arrays.asList(existingValue.toString(), traitValue));
                     }
                 } else {
-                    Map<String, Object> props = new HashMap<>();
-                    props.put(traitKey, initializeTraitValue(traitValue));
-                    traitJson.put(trait[0], props);
+                    config.put(traitKey, traitValue);
                 }
+            } else {
+                Map<String, Object> config = new HashMap<>();
+                config.put(traitKey, traitValue);
+                traitConfigMap.put(trait[0], config);
             }
+        }
+
+        Traits traitModel = 
KubernetesHelper.json().convertValue(traitConfigMap, Traits.class);
 
-            return KubernetesHelper.json().readerFor(Traits.class).readValue(
-                    KubernetesHelper.json().writeValueAsString(traitJson));
-        } catch (IOException e) {
-            throw new RuntimeCamelException("Failed to parse trait options", 
e);
+        // Handle leftover traits as addons
+        Set<?> knownTraits = KubernetesHelper.json().convertValue(traitModel, 
Map.class).keySet();
+        if (knownTraits.size() < traitConfigMap.size()) {
+            traitModel.setAddons(new HashMap<>());
+            for (Map.Entry<String, Map<String, Object>> traitConfig : 
traitConfigMap.entrySet()) {
+                if (!knownTraits.contains(traitConfig.getKey())) {
+                    traitModel.getAddons().put(traitConfig.getKey(),
+                            new 
AddonsBuilder().addToAdditionalProperties(traitConfig.getValue()).build());
+                }
+            }
         }
+
+        return traitModel;
     }
 
     /**
@@ -94,6 +119,30 @@ public final class TraitHelper {
      * @return
      */
     private static Object resolveTraitValue(String traitKey, String value) {
+        if (traitKey.equalsIgnoreCase("enabled") ||
+                traitKey.equalsIgnoreCase("verbose")) {
+            return Boolean.valueOf(value);
+        }
+
+        if (value.startsWith("[") && value.endsWith("]")) {
+            String valueArrayExpression = value.substring(1, value.length() - 
1);
+            List<String> values = new ArrayList<>();
+            if (valueArrayExpression.contains(",")) {
+                values.addAll(List.of(valueArrayExpression.split(",")));
+            } else {
+                values.add(valueArrayExpression);
+            }
+            return values;
+        }
+
+        if (value.contains(",")) {
+            List<String> values = new ArrayList<>();
+            for (String entry : value.split(",")) {
+                values.add(resolveTraitValue("", entry).toString());
+            }
+            return values;
+        }
+
         if (value.startsWith("\"") && value.endsWith("\"")) {
             return value.substring(1, value.length() - 1);
         }
@@ -102,27 +151,104 @@ public final class TraitHelper {
             return value.substring(1, value.length() - 1);
         }
 
-        if (traitKey.equalsIgnoreCase("enabled") ||
-                traitKey.equalsIgnoreCase("verbose")) {
-            return Boolean.valueOf(value);
+        try {
+            return Integer.parseInt(value);
+        } catch (NumberFormatException e) {
+            return value;
         }
+    }
 
-        return value;
+    public static void configureConnects(Traits traitsSpec, String[] connects) 
{
+        if (connects == null || connects.length == 0) {
+            return;
+        }
+        ServiceBinding serviceBindingTrait = 
Optional.ofNullable(traitsSpec.getServiceBinding()).orElseGet(ServiceBinding::new);
+        if (serviceBindingTrait.getServices() == null) {
+            serviceBindingTrait.setServices(new ArrayList<>());
+        }
+        serviceBindingTrait.getServices().addAll(List.of(connects));
+        traitsSpec.setServiceBinding(serviceBindingTrait);
     }
 
-    /**
-     * Initialize trait value with support for array type values.
-     *
-     * @param  value
-     * @return
-     */
-    private static Object initializeTraitValue(Object value) {
-        if (value instanceof String && value.toString().startsWith("[") && 
value.toString().endsWith("]")) {
-            List<String> values = new ArrayList<>();
-            values.add(resolveTraitValue("", value.toString().substring(1, 
value.toString().length() - 1)).toString());
-            return values;
+    public static void configureEnvVars(Traits traitsSpec, String[] envVars) {
+        if (envVars == null || envVars.length == 0) {
+            return;
+        }
+        Environment environmentTrait = 
Optional.ofNullable(traitsSpec.getEnvironment()).orElseGet(Environment::new);
+        if (environmentTrait.getVars() == null) {
+            environmentTrait.setVars(new ArrayList<>());
+        }
+        environmentTrait.getVars().addAll(List.of(envVars));
+        traitsSpec.setEnvironment(environmentTrait);
+    }
+
+    public static void configureBuildProperties(Traits traitsSpec, String[] 
buildProperties) {
+        if (buildProperties == null || buildProperties.length == 0) {
+            return;
+        }
+
+        Builder builderTrait = 
Optional.ofNullable(traitsSpec.getBuilder()).orElseGet(Builder::new);
+        if (builderTrait.getProperties() == null) {
+            builderTrait.setProperties(new ArrayList<>());
+        }
+        builderTrait.getProperties().addAll(List.of(buildProperties));
+        traitsSpec.setBuilder(builderTrait);
+    }
+
+    public static void configureProperties(Traits traitsSpec, String[] 
properties) {
+        if (properties == null || properties.length == 0) {
+            return;
+        }
+
+        Camel camelTrait = 
Optional.ofNullable(traitsSpec.getCamel()).orElseGet(Camel::new);
+        if (camelTrait.getProperties() == null) {
+            camelTrait.setProperties(new ArrayList<>());
+        }
+        camelTrait.getProperties().addAll(List.of(properties));
+        traitsSpec.setCamel(camelTrait);
+    }
+
+    public static void configureOpenApiSpec(Traits traitsSpec, String[] 
openApis) {
+        if (openApis == null || openApis.length == 0) {
+            return;
+        }
+
+        Openapi openapiTrait = 
Optional.ofNullable(traitsSpec.getOpenapi()).orElseGet(Openapi::new);
+        if (openapiTrait.getConfigmaps() == null) {
+            openapiTrait.setConfigmaps(new ArrayList<>());
+        }
+        openapiTrait.getConfigmaps().addAll(List.of(openApis));
+        traitsSpec.setOpenapi(openapiTrait);
+    }
+
+    public static void configureMountTrait(Traits traitsSpec, String[] 
configs, String[] resources, String[] volumes) {
+        if (configs == null && resources == null && volumes == null) {
+            return;
+        }
+
+        Mount mountTrait = 
Optional.ofNullable(traitsSpec.getMount()).orElseGet(Mount::new);
+
+        if (configs != null && configs.length > 0) {
+            if (mountTrait.getConfigs() == null) {
+                mountTrait.setConfigs(new ArrayList<>());
+            }
+            mountTrait.getConfigs().addAll(List.of(configs));
+        }
+
+        if (resources != null && resources.length > 0) {
+            if (mountTrait.getResources() == null) {
+                mountTrait.setResources(new ArrayList<>());
+            }
+            mountTrait.getResources().addAll(List.of(resources));
+        }
+
+        if (volumes != null && volumes.length > 0) {
+            if (mountTrait.getVolumes() == null) {
+                mountTrait.setVolumes(new ArrayList<>());
+            }
+            mountTrait.getVolumes().addAll(List.of(volumes));
         }
 
-        return value;
+        traitsSpec.setMount(mountTrait);
     }
 }
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/BindTest.java
 
b/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/BindTest.java
index 182251a59da..0701e7a5d10 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/BindTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/BindTest.java
@@ -194,7 +194,7 @@ class BindTest extends KubeBaseTest {
                   integration:
                     spec:
                       traits:
-                        serviceBinding:
+                        service-binding:
                           services:
                           - serving.knative.dev/v1:Service:my-service
                   source:
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/IntegrationRunTest.java
 
b/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/IntegrationRunTest.java
index a6f2443fcfd..3ecce4c0c51 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/IntegrationRunTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/IntegrationRunTest.java
@@ -78,20 +78,53 @@ class IntegrationRunTest extends KubeBaseTest {
                   name: route
                 spec:
                   flows:
-                  - additionalProperties:
-                      from:
-                        uri: timer:tick
-                        steps:
-                        - set-body:
-                            constant: Hello Camel !!!
-                        - to: log:info
+                  - from:
+                      uri: timer:tick
+                      steps:
+                      - setBody:
+                          constant: Hello Camel !!!
+                      - to: log:info
                   traits:
                     container:
-                      imagePullPolicy: ALWAYS
+                      imagePullPolicy: Always
                     logging:
                       level: DEBUG""", printer.getOutput());
     }
 
+    @Test
+    public void shouldAddTraitAddons() throws Exception {
+        IntegrationRun command = createCommand();
+        command.filePaths = new String[] { "classpath:route.yaml" };
+        command.traits = new String[] {
+                "container.port=8080", "telemetry.enabled=true",
+                
"telemetry.endpoint=http://opentelemetrycollector.ns.svc.cluster.local:8080"; };
+        command.output = "yaml";
+        command.doCall();
+
+        Assertions.assertEquals("""
+                apiVersion: camel.apache.org/v1
+                kind: Integration
+                metadata:
+                  annotations:
+                    camel.apache.org/operator.id: camel-k
+                  name: route
+                spec:
+                  flows:
+                  - from:
+                      uri: timer:tick
+                      steps:
+                      - setBody:
+                          constant: Hello Camel !!!
+                      - to: log:info
+                  traits:
+                    addons:
+                      telemetry:
+                        endpoint: 
http://opentelemetrycollector.ns.svc.cluster.local:8080
+                        enabled: true
+                    container:
+                      port: 8080""", printer.getOutput());
+    }
+
     @Test
     public void shouldSpecFromOptions() throws Exception {
         IntegrationRun command = createCommand();
@@ -118,13 +151,12 @@ class IntegrationRunTest extends KubeBaseTest {
                   name: custom
                 spec:
                   flows:
-                  - additionalProperties:
-                      from:
-                        uri: timer:tick
-                        steps:
-                        - set-body:
-                            constant: Hello Camel !!!
-                        - to: log:info
+                  - from:
+                      uri: timer:tick
+                      steps:
+                      - setBody:
+                          constant: Hello Camel !!!
+                      - to: log:info
                   profile: knative
                   repositories:
                   - http://custom-repository
@@ -149,13 +181,12 @@ class IntegrationRunTest extends KubeBaseTest {
                   name: route
                 spec:
                   flows:
-                  - additionalProperties:
-                      from:
-                        uri: timer:tick
-                        steps:
-                        - set-body:
-                            constant: Hello Camel !!!
-                        - to: log:info
+                  - from:
+                      uri: timer:tick
+                      steps:
+                      - setBody:
+                          constant: Hello Camel !!!
+                      - to: log:info
                   traits:
                     mount:
                       volumes:
@@ -184,13 +215,12 @@ class IntegrationRunTest extends KubeBaseTest {
                   - camel:jms
                   - mvn:foo:bar:1.0
                   flows:
-                  - additionalProperties:
-                      from:
-                        uri: timer:tick
-                        steps:
-                        - set-body:
-                            constant: Hello Camel !!!
-                        - to: log:info
+                  - from:
+                      uri: timer:tick
+                      steps:
+                      - setBody:
+                          constant: Hello Camel !!!
+                      - to: log:info
                   traits: {}""", printer.getOutput());
     }
 
@@ -211,13 +241,12 @@ class IntegrationRunTest extends KubeBaseTest {
                   name: route
                 spec:
                   flows:
-                  - additionalProperties:
-                      from:
-                        uri: timer:tick
-                        steps:
-                        - set-body:
-                            constant: Hello Camel !!!
-                        - to: log:info
+                  - from:
+                      uri: timer:tick
+                      steps:
+                      - setBody:
+                          constant: Hello Camel !!!
+                      - to: log:info
                   traits:
                     environment:
                       vars:
@@ -241,13 +270,12 @@ class IntegrationRunTest extends KubeBaseTest {
                   name: route
                 spec:
                   flows:
-                  - additionalProperties:
-                      from:
-                        uri: timer:tick
-                        steps:
-                        - set-body:
-                            constant: Hello Camel !!!
-                        - to: log:info
+                  - from:
+                      uri: timer:tick
+                      steps:
+                      - setBody:
+                          constant: Hello Camel !!!
+                      - to: log:info
                   traits:
                     camel:
                       properties:
@@ -271,13 +299,12 @@ class IntegrationRunTest extends KubeBaseTest {
                   name: route
                 spec:
                   flows:
-                  - additionalProperties:
-                      from:
-                        uri: timer:tick
-                        steps:
-                        - set-body:
-                            constant: Hello Camel !!!
-                        - to: log:info
+                  - from:
+                      uri: timer:tick
+                      steps:
+                      - setBody:
+                          constant: Hello Camel !!!
+                      - to: log:info
                   traits:
                     builder:
                       properties:
@@ -301,13 +328,12 @@ class IntegrationRunTest extends KubeBaseTest {
                   name: route
                 spec:
                   flows:
-                  - additionalProperties:
-                      from:
-                        uri: timer:tick
-                        steps:
-                        - set-body:
-                            constant: Hello Camel !!!
-                        - to: log:info
+                  - from:
+                      uri: timer:tick
+                      steps:
+                      - setBody:
+                          constant: Hello Camel !!!
+                      - to: log:info
                   integrationKit:
                     name: kit-123456789
                   traits: {}""", printer.getOutput());
@@ -329,13 +355,12 @@ class IntegrationRunTest extends KubeBaseTest {
                   name: route
                 spec:
                   flows:
-                  - additionalProperties:
-                      from:
-                        uri: timer:tick
-                        steps:
-                        - set-body:
-                            constant: Hello Camel !!!
-                        - to: log:info
+                  - from:
+                      uri: timer:tick
+                      steps:
+                      - setBody:
+                          constant: Hello Camel !!!
+                      - to: log:info
                   traits: {}""", printer.getOutput());
     }
 
@@ -356,15 +381,14 @@ class IntegrationRunTest extends KubeBaseTest {
                   name: route
                 spec:
                   flows:
-                  - additionalProperties:
-                      from:
-                        uri: timer:tick
-                        steps:
-                        - set-body:
-                            constant: Hello Camel !!!
-                        - to: log:info
+                  - from:
+                      uri: timer:tick
+                      steps:
+                      - setBody:
+                          constant: Hello Camel !!!
+                      - to: log:info
                   traits:
-                    serviceBinding:
+                    service-binding:
                       services:
                       - serving.knative.dev/v1:Service:foo""", 
printer.getOutput());
     }
@@ -386,13 +410,12 @@ class IntegrationRunTest extends KubeBaseTest {
                   name: route
                 spec:
                   flows:
-                  - additionalProperties:
-                      from:
-                        uri: timer:tick
-                        steps:
-                        - set-body:
-                            constant: Hello Camel !!!
-                        - to: log:info
+                  - from:
+                      uri: timer:tick
+                      steps:
+                      - setBody:
+                          constant: Hello Camel !!!
+                      - to: log:info
                   template:
                     spec:
                       containers:
@@ -426,13 +449,12 @@ class IntegrationRunTest extends KubeBaseTest {
                   name: route
                 spec:
                   flows:
-                  - additionalProperties:
-                      from:
-                        uri: timer:tick
-                        steps:
-                        - set-body:
-                            constant: Hello Camel !!!
-                        - to: log:info
+                  - from:
+                      uri: timer:tick
+                      steps:
+                      - setBody:
+                          constant: Hello Camel !!!
+                      - to: log:info
                   traits:
                     mount:
                       configs:
@@ -457,13 +479,12 @@ class IntegrationRunTest extends KubeBaseTest {
                   name: route
                 spec:
                   flows:
-                  - additionalProperties:
-                      from:
-                        uri: timer:tick
-                        steps:
-                        - set-body:
-                            constant: Hello Camel !!!
-                        - to: log:info
+                  - from:
+                      uri: timer:tick
+                      steps:
+                      - setBody:
+                          constant: Hello Camel !!!
+                      - to: log:info
                   traits:
                     mount:
                       resources:
@@ -487,13 +508,12 @@ class IntegrationRunTest extends KubeBaseTest {
                   name: route
                 spec:
                   flows:
-                  - additionalProperties:
-                      from:
-                        uri: timer:tick
-                        steps:
-                        - set-body:
-                            constant: Hello Camel !!!
-                        - to: log:info
+                  - from:
+                      uri: timer:tick
+                      steps:
+                      - setBody:
+                          constant: Hello Camel !!!
+                      - to: log:info
                   traits:
                     openapi:
                       configmaps:
@@ -541,13 +561,12 @@ class IntegrationRunTest extends KubeBaseTest {
                   name: route
                 spec:
                   flows:
-                  - additionalProperties:
-                      from:
-                        uri: timer:tick
-                        steps:
-                        - set-body:
-                            constant: Hello Camel !!!
-                        - to: log:info
+                  - from:
+                      uri: timer:tick
+                      steps:
+                      - setBody:
+                          constant: Hello Camel !!!
+                      - to: log:info
                   traits:
                     affinity:
                       nodeAffinityLabels:
@@ -579,7 +598,7 @@ class IntegrationRunTest extends KubeBaseTest {
                         spec:
                           sources:
                           - compression: true
-                            content: 
ZFNNb6NADL3zK5zk0kr5WO2RPbFpoqKtiBRoqxwnYMAqzLAzZmn+/XoI2UbauSDP2M/vPZtFsIAXylE7LIANcI0QdSqXT2pKHpRF2JteF4rJaHiI0v0jSIgWjEYwFlpjUUByo9nSuWe5aq6AoCqL2KJmtwZIEUf05JDF2x2U1CAU5K5F0nwgrgWHa3IwGPsBpSCpoiDfWDVAWi7aKw2LlbIF6UradhdLVc1gBo3W1dStBSXzMtL9jYm7wo49ReTJ9JOGO7mTC0t4Exjf5Pv6myA9+JT59Dh//AEXKW7VBbRh6B3eIeNnjh0LUWHVdg0pneOXrH8dxIvThGHOrCRdjTLAlPdpoDhYSOV4auYu3GyGYVirke7a2GpzU7d5EUeTdLcaKUvNq27QObHpd09WvD1fQHXCKFdn4dmowQ9unM44dKEwWPFZV0tw09QF5X46X3bd6In
 [...]
+                            content: 
ZFPBbtswDL3nK16TSwukybCjd3LTBDVWOECcrshRsWlbqC15Ej03fz/KSdYA08WgRD6+90jPJjO86pyMpwJswTUh7lQun8yWPChH2NjeFIq1NbiPs80DJCQHawjWobWOBCS3hp0+9ixXzRkQqnJELRn2CyAjGtHT7T5ZrVHqhlBofy6S5oPmWnC41h6DdR8oBUkVhQ6NVQNt5KI903BUKVdoU0nb7uR0VTPsYMj5WncLQdkHGdnmysSfYceeIvJg+4uGG7kXF+b4JTChyffFN0G6DynTy+P04QdOUtyqE4xl9J5ukOkzp46FqLBqu0Yrk9OXrH8dxIvDBcMeWUm6GmXAlrdpUDyZSeV4auYuWi6HYVioke7Cump5Vbd8FUfTbP04UpaaN9OQ92LT71478fZ4guqEUa6OwrNRQxjcOJ1x6EJhcOKzqebwl6kLyu10vuy60hP
 [...]
                             language: yaml
                             name: route.yaml
                           traits: {}""",
@@ -616,7 +635,7 @@ class IntegrationRunTest extends KubeBaseTest {
                       from:
                         uri: timer:tick
                         steps:
-                          - set-body:
+                          - setBody:
                               constant: Hello Camel !!!
                           - to: log:info
                     language: yaml
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/KubeCommandMainTest.java
 
b/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/KubeCommandMainTest.java
index 1edd316d02f..f8c65826148 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/KubeCommandMainTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/KubeCommandMainTest.java
@@ -98,13 +98,12 @@ class KubeCommandMainTest extends KubeBaseTest {
                   name: route
                 spec:
                   flows:
-                  - additionalProperties:
-                      from:
-                        uri: timer:tick
-                        steps:
-                        - set-body:
-                            constant: Hello Camel !!!
-                        - to: log:info
+                  - from:
+                      uri: timer:tick
+                      steps:
+                      - setBody:
+                          constant: Hello Camel !!!
+                      - to: log:info
                   traits: {}""", printer.getOutput());
     }
 
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-k/src/test/resources/org/apache/camel/dsl/jbang/core/commands/k/integration.yaml
 
b/dsl/camel-jbang/camel-jbang-plugin-k/src/test/resources/org/apache/camel/dsl/jbang/core/commands/k/integration.yaml
index 6b85aa4c7a5..a3d6d058745 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-k/src/test/resources/org/apache/camel/dsl/jbang/core/commands/k/integration.yaml
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-k/src/test/resources/org/apache/camel/dsl/jbang/core/commands/k/integration.yaml
@@ -23,13 +23,12 @@ metadata:
   name: routes
 spec:
   flows:
-    - additionalProperties:
-        from:
-          uri: timer:tick
-          steps:
-            - set-body:
-                constant: Hello Camel !!!
-            - to: log:info
+    - from:
+        uri: timer:tick
+        steps:
+          - setBody:
+              constant: Hello Camel !!!
+          - to: log:info
   traits:
     logging:
       level: DEBUG
diff --git a/dsl/camel-jbang/camel-jbang-plugin-k/src/test/resources/route.yaml 
b/dsl/camel-jbang/camel-jbang-plugin-k/src/test/resources/route.yaml
index 4485c1f5379..8f13a54fda0 100644
--- a/dsl/camel-jbang/camel-jbang-plugin-k/src/test/resources/route.yaml
+++ b/dsl/camel-jbang/camel-jbang-plugin-k/src/test/resources/route.yaml
@@ -18,6 +18,6 @@
 from:
   uri: timer:tick
   steps:
-    - set-body:
+    - setBody:
         constant: Hello Camel !!!
     - to: log:info


Reply via email to