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

commit a103a902cfa7b13f219268b149177f3ef63c57ed
Author: Thomas Diesler <tdies...@redhat.com>
AuthorDate: Tue Jul 16 20:11:57 2024 +0200

    [CAMEL-20962] camel-jbang: SpringBoot support in Kubernetes plugin
---
 .../dsl/jbang/core/commands/ExportBaseCommand.java |  72 +++++-----
 .../dsl/jbang/core/commands/ExportQuarkus.java     |   3 +-
 .../dsl/jbang/core/commands/ExportSpringBoot.java  |  21 +--
 ...ot-pom.tmpl => spring-boot-kubernetes-pom.tmpl} |  50 ++++---
 .../main/resources/templates/spring-boot-pom.tmpl  |   2 -
 .../jbang/core/commands/SpringBootExportTest.java  |  72 ++++++++++
 .../camel-jbang-core/src/test/resources/route.yaml |  23 ++++
 .../core/commands/kubernetes/KubernetesExport.java |  91 +++++++------
 .../commands/kubernetes/KubernetesExportTest.java  | 150 +++++++++++++++++----
 9 files changed, 356 insertions(+), 128 deletions(-)

diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
index 2b61badb1db..52a044fc207 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
@@ -220,7 +220,9 @@ public abstract class ExportBaseCommand extends 
CamelCommand {
                         description = "Whether to ignore route loading and 
compilation errors (use this with care!)")
     protected boolean ignoreLoadingError;
 
-    protected boolean symbolicLink; // copy source files using symbolic link
+    protected boolean symbolicLink;     // copy source files using symbolic 
link
+
+    public String pomTemplateName;   // support for specialised pom templates
 
     public ExportBaseCommand(CamelJBangMain main) {
         super(main);
@@ -362,45 +364,51 @@ public abstract class ExportBaseCommand extends 
CamelCommand {
                 }
             } else if (line.startsWith("camel.jbang.dependencies=")) {
                 String deps = StringHelper.after(line, 
"camel.jbang.dependencies=");
-                for (String d : deps.split(",")) {
-                    answer.add(d.trim());
-                    if (kamelets && 
d.contains("org.apache.camel:camel-kamelet")) {
-                        // include yaml-dsl and kamelet catalog if we use 
kamelets
-                        answer.add("camel:yaml-dsl");
-                        answer.add("org.apache.camel.kamelets:camel-kamelets:" 
+ kameletsVersion);
+                if (!deps.isEmpty()) {
+                    for (String d : deps.split(",")) {
+                        answer.add(d.trim());
+                        if (kamelets && 
d.contains("org.apache.camel:camel-kamelet")) {
+                            // include yaml-dsl and kamelet catalog if we use 
kamelets
+                            answer.add("camel:yaml-dsl");
+                            
answer.add("org.apache.camel.kamelets:camel-kamelets:" + kameletsVersion);
+                        }
                     }
                 }
             } else if (line.startsWith("camel.jbang.classpathFiles")) {
                 String deps = StringHelper.after(line, 
"camel.jbang.classpathFiles=");
-                for (String d : deps.split(",")) {
-                    // special to include local JARs in export lib folder
-                    if (d.endsWith(".jar")) {
-                        answer.add("lib:" + d.trim());
+                if (!deps.isEmpty()) {
+                    for (String d : deps.split(",")) {
+                        // special to include local JARs in export lib folder
+                        if (d.endsWith(".jar")) {
+                            answer.add("lib:" + d.trim());
+                        }
                     }
                 }
             } else if (line.startsWith("camel.main.routesIncludePattern=")) {
                 String routes = StringHelper.after(line, 
"camel.main.routesIncludePattern=");
-                for (String r : routes.split(",")) {
-                    String ext = FileUtil.onlyExt(r, true);
-                    if (ext != null) {
-                        // java is moved into src/main/java and compiled 
during build
-                        // for the other DSLs we need to add dependencies
-                        if ("groovy".equals(ext)) {
-                            
answer.add("mvn:org.apache.camel:camel-groovy-dsl");
-                        } else if ("js".equals(ext)) {
-                            answer.add("mvn:org.apache.camel:camel-js-dsl");
-                        } else if ("jsh".equals(ext)) {
-                            answer.add("mvn:org.apache.camel:camel-jsh-dsl");
-                        } else if ("kts".equals(ext)) {
-                            
answer.add("mvn:org.apache.camel:camel-kotlin-dsl");
-                        } else if ("xml".equals(ext)) {
-                            
answer.add("mvn:org.apache.camel:camel-xml-io-dsl");
-                        } else if ("yaml".equals(ext)) {
-                            answer.add("mvn:org.apache.camel:camel-yaml-dsl");
-                            // is it a kamelet?
-                            ext = FileUtil.onlyExt(r, false);
-                            if ("kamelet.yaml".equals(ext)) {
-                                
answer.add("mvn:org.apache.camel.kamelets:camel-kamelets:" + kameletsVersion);
+                if (!routes.isEmpty()) {
+                    for (String r : routes.split(",")) {
+                        String ext = FileUtil.onlyExt(r, true);
+                        if (ext != null) {
+                            // java is moved into src/main/java and compiled 
during build
+                            // for the other DSLs we need to add dependencies
+                            if ("groovy".equals(ext)) {
+                                
answer.add("mvn:org.apache.camel:camel-groovy-dsl");
+                            } else if ("js".equals(ext)) {
+                                
answer.add("mvn:org.apache.camel:camel-js-dsl");
+                            } else if ("jsh".equals(ext)) {
+                                
answer.add("mvn:org.apache.camel:camel-jsh-dsl");
+                            } else if ("kts".equals(ext)) {
+                                
answer.add("mvn:org.apache.camel:camel-kotlin-dsl");
+                            } else if ("xml".equals(ext)) {
+                                
answer.add("mvn:org.apache.camel:camel-xml-io-dsl");
+                            } else if ("yaml".equals(ext)) {
+                                
answer.add("mvn:org.apache.camel:camel-yaml-dsl");
+                                // is it a kamelet?
+                                ext = FileUtil.onlyExt(r, false);
+                                if ("kamelet.yaml".equals(ext)) {
+                                    
answer.add("mvn:org.apache.camel.kamelets:camel-kamelets:" + kameletsVersion);
+                                }
                             }
                         }
                     }
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java
index 348bf73a3f5..9efec45e0fa 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java
@@ -47,6 +47,7 @@ class ExportQuarkus extends Export {
 
     public ExportQuarkus(CamelJBangMain main) {
         super(main);
+        pomTemplateName = "quarkus-pom.tmpl";
     }
 
     @Override
@@ -351,7 +352,7 @@ class ExportQuarkus extends Export {
     private void createMavenPom(File settings, File pom, Set<String> deps) 
throws Exception {
         String[] ids = gav.split(":");
 
-        InputStream is = 
ExportQuarkus.class.getClassLoader().getResourceAsStream("templates/quarkus-pom.tmpl");
+        InputStream is = 
ExportQuarkus.class.getClassLoader().getResourceAsStream("templates/" + 
pomTemplateName);
         String context = IOHelper.loadText(is);
         IOHelper.close(is);
 
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportSpringBoot.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportSpringBoot.java
index a9941b44a15..36a42e9d85c 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportSpringBoot.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportSpringBoot.java
@@ -46,6 +46,7 @@ class ExportSpringBoot extends Export {
 
     public ExportSpringBoot(CamelJBangMain main) {
         super(main);
+        pomTemplateName = "spring-boot-pom.tmpl";
     }
 
     @Override
@@ -165,27 +166,27 @@ class ExportSpringBoot extends Export {
         // First try to load a specialized template from the catalog, if the 
catalog does not provide it
         // fallback to the template defined in camel-jbang-core
         String context;
-        InputStream template = catalog.loadResource("camel-jbang", 
"spring-boot-pom.tmpl");
+        InputStream template = catalog.loadResource("camel-jbang", 
pomTemplateName);
         if (template != null) {
             context = IOHelper.loadText(template);
         } else {
-            context = readResourceTemplate("templates/spring-boot-pom.tmpl");
+            context = readResourceTemplate("templates/" + pomTemplateName);
         }
 
         String camelVersion = catalog.getLoadedVersion();
 
-        context = context.replaceFirst("\\{\\{ \\.GroupId }}", ids[0]);
-        context = context.replaceFirst("\\{\\{ \\.ArtifactId }}", ids[1]);
-        context = context.replaceFirst("\\{\\{ \\.Version }}", ids[2]);
+        context = context.replaceAll("\\{\\{ \\.GroupId }}", ids[0]);
+        context = context.replaceAll("\\{\\{ \\.ArtifactId }}", ids[1]);
+        context = context.replaceAll("\\{\\{ \\.Version }}", ids[2]);
         context = context.replaceAll("\\{\\{ \\.SpringBootVersion }}", 
springBootVersion);
-        context = context.replaceFirst("\\{\\{ \\.JavaVersion }}", 
javaVersion);
-        context = context.replaceFirst("\\{\\{ \\.CamelVersion }}", 
camelVersion);
+        context = context.replaceAll("\\{\\{ \\.JavaVersion }}", javaVersion);
+        context = context.replaceAll("\\{\\{ \\.CamelVersion }}", 
camelVersion);
         if (camelSpringBootVersion != null) {
-            context = context.replaceFirst("\\{\\{ \\.CamelSpringBootVersion 
}}", camelSpringBootVersion);
+            context = context.replaceAll("\\{\\{ \\.CamelSpringBootVersion 
}}", camelSpringBootVersion);
         } else {
-            context = context.replaceFirst("\\{\\{ \\.CamelSpringBootVersion 
}}", camelVersion);
+            context = context.replaceAll("\\{\\{ \\.CamelSpringBootVersion 
}}", camelVersion);
         }
-        if (additionalProperties != null) {
+        if (additionalProperties != null && !additionalProperties.isEmpty()) {
             String properties = Arrays.stream(additionalProperties.split(","))
                     .map(property -> {
                         String[] keyValueProperty = property.split("=");
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-pom.tmpl
 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-kubernetes-pom.tmpl
similarity index 67%
copy from 
dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-pom.tmpl
copy to 
dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-kubernetes-pom.tmpl
index 0d656b1b00f..d1c7490e43f 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-pom.tmpl
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-kubernetes-pom.tmpl
@@ -16,7 +16,6 @@
 
     <properties>
         <java.version>{{ .JavaVersion }}</java.version>
-{{ .jkubeProperties }}
 {{ .AdditionalProperties }}
     </properties>
 
@@ -52,13 +51,11 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-actuator</artifactId>
         </dependency>
-
         <dependency>
             <groupId>org.apache.camel.springboot</groupId>
             <artifactId>camel-spring-boot-starter</artifactId>
         </dependency>
 {{ .CamelDependencies }}
-
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-test</artifactId>
@@ -77,26 +74,41 @@
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-maven-plugin</artifactId>
             </plugin>
+            <plugin>
+                <groupId>com.google.cloud.tools</groupId>
+                <artifactId>jib-maven-plugin</artifactId>
+                <configuration>
+                    <from>
+                        <image>eclipse-temurin:{{ .JavaVersion }}</image>
+                        <platforms>
+                            <platform>
+                                <architecture>amd64</architecture>
+                                <os>linux</os>
+                            </platform>
+                            <platform>
+                                <architecture>arm64</architecture>
+                                <os>linux</os>
+                            </platform>
+                        </platforms>
+                    </from>
+                    <to>
+                        
<image>${camel.springboot.kubernetes.image-name}</image>
+                    </to>
+                    
<allowInsecureRegistries>${camel.springboot.container-image.insecure}</allowInsecureRegistries>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>dockerBuild</goal>
+                        </goals>
+                        <phase>package</phase>
+                    </execution>
+                </executions>
+            </plugin>
         </plugins>
     </build>
 
     <profiles>
-{{ .jkubeProfiles }}
-        <profile>
-            <id>camel.debug</id>
-            <activation>
-                <property>
-                    <name>camel.debug</name>
-                    <value>true</value>
-                </property>
-            </activation>
-            <dependencies>
-                <dependency>
-                    <groupId>org.apache.camel.springboot</groupId>
-                    <artifactId>camel-debug-starter</artifactId>
-                </dependency>
-            </dependencies>
-        </profile>
     </profiles>
 
 </project>
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-pom.tmpl
 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-pom.tmpl
index 0d656b1b00f..843c2b47d43 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-pom.tmpl
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-pom.tmpl
@@ -52,13 +52,11 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-actuator</artifactId>
         </dependency>
-
         <dependency>
             <groupId>org.apache.camel.springboot</groupId>
             <artifactId>camel-spring-boot-starter</artifactId>
         </dependency>
 {{ .CamelDependencies }}
-
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-test</artifactId>
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/SpringBootExportTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/SpringBootExportTest.java
new file mode 100644
index 00000000000..a014369065a
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/SpringBootExportTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.Arrays;
+
+import org.apache.maven.model.Model;
+import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import picocli.CommandLine;
+
+class SpringBootExportTest {
+
+    private File workingDir;
+
+    @BeforeEach
+    public void setup() throws IOException {
+        workingDir = Files.createTempDirectory("camel-export").toFile();
+        workingDir.deleteOnExit();
+    }
+
+    @Test
+    public void shouldGenerateSpringBootProject() throws Exception {
+        ExportSpringBoot command = createCommand(new String[] { 
"classpath:route.yaml" },
+                "--gav=examples:route:1.0.0", "--dir=" + workingDir, 
"--quiet");
+        int exit = command.doCall();
+
+        Assertions.assertEquals(0, exit);
+        Model model = readMavenModel();
+        Assertions.assertEquals("examples", model.getGroupId());
+        Assertions.assertEquals("route", model.getArtifactId());
+        Assertions.assertEquals("1.0.0", model.getVersion());
+    }
+
+    private ExportSpringBoot createCommand(String[] files, String... args) {
+        ExportSpringBoot command = new ExportSpringBoot(new CamelJBangMain());
+        CommandLine.populateCommand(command, "--gav=examples:route:1.0.0", 
"--dir=" + workingDir, "--quiet",
+                "--runtime=spring-boot");
+        command.files = Arrays.asList(files);
+        return command;
+    }
+
+    private Model readMavenModel() throws Exception {
+        File f = workingDir.toPath().resolve("pom.xml").toFile();
+        Assertions.assertTrue(f.isFile(), "Not a pom.xml file: " + f);
+        MavenXpp3Reader mavenReader = new MavenXpp3Reader();
+        Model model = mavenReader.read(new FileReader(f));
+        model.setPomFile(f);
+        return model;
+    }
+}
diff --git a/dsl/camel-jbang/camel-jbang-core/src/test/resources/route.yaml 
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/route.yaml
new file mode 100644
index 00000000000..8f13a54fda0
--- /dev/null
+++ b/dsl/camel-jbang/camel-jbang-core/src/test/resources/route.yaml
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+from:
+  uri: timer:tick
+  steps:
+    - setBody:
+        constant: Hello Camel !!!
+    - to: log:info
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 d7bfc5a5603..4ad53f87b1d 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
@@ -29,6 +29,7 @@ import java.util.stream.Collectors;
 
 import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
 import org.apache.camel.dsl.jbang.core.commands.Export;
+import org.apache.camel.dsl.jbang.core.commands.ExportBaseCommand;
 import 
org.apache.camel.dsl.jbang.core.commands.kubernetes.traits.ContainerTrait;
 import org.apache.camel.dsl.jbang.core.commands.kubernetes.traits.TraitCatalog;
 import org.apache.camel.dsl.jbang.core.commands.kubernetes.traits.TraitContext;
@@ -37,6 +38,7 @@ import 
org.apache.camel.dsl.jbang.core.commands.kubernetes.traits.TraitProfile;
 import org.apache.camel.dsl.jbang.core.common.RuntimeType;
 import org.apache.camel.util.StringHelper;
 import org.apache.camel.v1.integrationspec.Traits;
+import org.apache.camel.v1.integrationspec.traits.Container;
 import picocli.CommandLine;
 import picocli.CommandLine.Command;
 
@@ -162,28 +164,29 @@ public class KubernetesExport extends Export {
 
             // Quarkus specific properties
             exportProps.put("quarkus.container-image.build", "true");
+        }
 
-            if (resolvedImageRegistry != null) {
-                exportProps.put("quarkus.container-image.registry", 
resolvedImageRegistry);
-                if (resolvedImageRegistry.startsWith("localhost")) {
-                    exportProps.put("quarkus.container-image.insecure", 
"true");
-                }
-            }
+        String propPrefix;
+        if (runtime == RuntimeType.springBoot) {
+            propPrefix = "camel.springboot";
+        } else {
+            propPrefix = runtime.runtime();
+        }
 
-            if (resolvedImageGroup != null) {
-                exportProps.put("quarkus.container-image.group", 
resolvedImageGroup);
-            }
+        if (resolvedImageGroup != null) {
+            exportProps.put("%s.container-image.group".formatted(propPrefix), 
resolvedImageGroup);
         }
 
-        additionalProperties = 
Optional.ofNullable(additionalProperties).orElse("");
-        if (additionalProperties.isEmpty()) {
-            additionalProperties = exportProps.entrySet().stream()
-                    .map(entry -> "%s=%s".formatted(entry.getKey(), 
entry.getValue())).collect(Collectors.joining(","));
-        } else {
-            additionalProperties += "," + exportProps.entrySet().stream()
-                    .map(entry -> "%s=%s".formatted(entry.getKey(), 
entry.getValue())).collect(Collectors.joining(","));
+        if (resolvedImageRegistry != null) {
+            var allowInsecure = resolvedImageRegistry.startsWith("localhost");
+            
exportProps.put("%s.container-image.registry".formatted(propPrefix), 
resolvedImageRegistry);
+            
exportProps.put("%s.container-image.insecure".formatted(propPrefix), 
"%b".formatted(allowInsecure));
         }
 
+        additionalProperties = 
Optional.ofNullable(additionalProperties).map(str -> str + ",").orElse("");
+        additionalProperties += exportProps.entrySet().stream()
+                .map(entry -> "%s=%s".formatted(entry.getKey(), 
entry.getValue())).collect(Collectors.joining(","));
+
         String projectName = getProjectName();
         TraitContext context = new TraitContext(projectName, getVersion());
         if (annotations != null) {
@@ -193,12 +196,11 @@ public class KubernetesExport extends Export {
                     .collect(Collectors.toMap(parts -> parts[0], parts -> 
parts[1])));
         }
 
-        if (labels != null) {
-            context.addLabels(Arrays.stream(labels)
-                    .map(item -> item.split("="))
-                    .filter(parts -> parts.length == 2)
-                    .collect(Collectors.toMap(parts -> parts[0], parts -> 
parts[1])));
-        }
+        labels = Optional.ofNullable(labels).orElse(new String[0]);
+        context.addLabels(Arrays.stream(labels)
+                .map(item -> item.split("="))
+                .filter(parts -> parts.length == 2)
+                .collect(Collectors.toMap(parts -> parts[0], parts -> 
parts[1])));
 
         if (traitProfile != null) {
             context.setProfile(TraitProfile.valueOf(traitProfile));
@@ -209,27 +211,29 @@ public class KubernetesExport extends Export {
         TraitHelper.configureMountTrait(traitsSpec, configs, resources, 
volumes);
         TraitHelper.configureOpenApiSpec(traitsSpec, openApis);
         TraitHelper.configureProperties(traitsSpec, properties);
-        TraitHelper.configureContainerImage(traitsSpec, image, 
resolvedImageRegistry, resolvedImageGroup, projectName,
-                getVersion());
+        TraitHelper.configureContainerImage(traitsSpec, image,
+                resolvedImageRegistry, resolvedImageGroup, projectName, 
getVersion());
         TraitHelper.configureEnvVars(traitsSpec, envVars);
         TraitHelper.configureConnects(traitsSpec, connects);
 
-        // Need to set quarkus.container properties, otherwise these settings 
get overwritten by Quarkus
-        if (RuntimeType.quarkus == runtime && traitsSpec.getContainer() != 
null) {
-            if (traitsSpec.getContainer().getName() != null && 
!traitsSpec.getContainer().getName().equals(projectName)) {
-                additionalProperties += 
",quarkus.kubernetes.container-name=%s".formatted(traitsSpec.getContainer().getName());
-            }
-
-            if (traitsSpec.getContainer().getPort() != null) {
-                additionalProperties += 
",quarkus.kubernetes.ports.%s.container-port=%s"
-                        
.formatted(Optional.ofNullable(traitsSpec.getContainer().getPortName())
-                                
.orElse(ContainerTrait.DEFAULT_CONTAINER_PORT_NAME), 
traitsSpec.getContainer().getPort());
-            }
+        Container container = traitsSpec.getContainer();
 
-            if (traitsSpec.getContainer().getImagePullPolicy() != null) {
-                additionalProperties += 
",quarkus.kubernetes.image-pull-policy=%s"
-                        
.formatted(StringHelper.camelCaseToDash(traitsSpec.getContainer().getImagePullPolicy().getValue()));
-            }
+        // Need to set quarkus.container properties, otherwise these settings 
get overwritten by Quarkus
+        if (container.getName() != null && 
!container.getName().equals(projectName)) {
+            additionalProperties += 
",%s.kubernetes.container-name=%s".formatted(propPrefix, container.getName());
+        }
+        if (container.getImage() != null) {
+            additionalProperties += 
",%s.kubernetes.image-name=%s".formatted(propPrefix, container.getImage());
+        }
+        if (container.getPort() != null) {
+            additionalProperties += 
",%s.kubernetes.ports.%s.container-port=%s".formatted(propPrefix,
+                    Optional.ofNullable(container.getPortName()).orElse(
+                            ContainerTrait.DEFAULT_CONTAINER_PORT_NAME),
+                    container.getPort());
+        }
+        if (container.getImagePullPolicy() != null) {
+            additionalProperties += ",%s.kubernetes.image-pull-policy=%s"
+                    .formatted(propPrefix, 
StringHelper.camelCaseToDash(container.getImagePullPolicy().getValue()));
         }
 
         // run export
@@ -258,12 +262,19 @@ public class KubernetesExport extends Export {
         return 0;
     }
 
+    protected Integer export(ExportBaseCommand cmd) throws Exception {
+        if (runtime == RuntimeType.springBoot) {
+            cmd.pomTemplateName = "spring-boot-kubernetes-pom.tmpl";
+        }
+        return super.export(cmd);
+    }
+
     protected Traits getTraitSpec() {
         Traits traitsSpec;
         if (traits != null && traits.length > 0) {
             traitsSpec = TraitHelper.parseTraits(traits, annotations);
         } else if (annotations != null && annotations.length > 0) {
-            traitsSpec = TraitHelper.parseTraits(new String[] {}, annotations);
+            traitsSpec = TraitHelper.parseTraits(new String[0], annotations);
         } else {
             traitsSpec = new Traits();
         }
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 83accb91fa7..c1fd9711cbe 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
@@ -22,13 +22,12 @@ import java.io.FileInputStream;
 import java.io.FileReader;
 import java.io.IOException;
 import java.nio.file.Files;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Optional;
+import java.util.*;
 
 import io.fabric8.kubernetes.api.model.apps.Deployment;
 import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
 import org.apache.camel.dsl.jbang.core.commands.kubernetes.traits.BaseTrait;
+import org.apache.camel.dsl.jbang.core.common.RuntimeType;
 import org.apache.maven.model.Model;
 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
 import org.junit.jupiter.api.Assertions;
@@ -50,7 +49,17 @@ class KubernetesExportTest {
 
     @Test
     public void shouldGenerateQuarkusProject() throws Exception {
-        KubernetesExport command = createCommand(new String[] { 
"classpath:route.yaml" }, "--gav=examples:route:1.0.0");
+        shouldGenerateProject(RuntimeType.quarkus);
+    }
+
+    @Test
+    public void shouldGenerateSpringBootProject() throws Exception {
+        shouldGenerateProject(RuntimeType.springBoot);
+    }
+
+    void shouldGenerateProject(RuntimeType rt) throws Exception {
+        KubernetesExport command = createCommand(new String[] { 
"classpath:route.yaml" },
+                "--gav=examples:route:1.0.0", "--runtime=" + rt.runtime());
         int exit = command.doCall();
 
         Assertions.assertEquals(0, exit);
@@ -61,8 +70,18 @@ class KubernetesExportTest {
     }
 
     @Test
-    public void shouldGenerateKubernetesManifest() throws Exception {
-        KubernetesExport command = createCommand(new String[] { 
"classpath:route.yaml" }, "--image-group=camel-test");
+    public void shouldGenerateQuarkusKubernetesManifest() throws Exception {
+        shouldGenerateKubernetesManifest(RuntimeType.quarkus);
+    }
+
+    @Test
+    public void shouldGenerateSpringBootKubernetesManifest() throws Exception {
+        shouldGenerateKubernetesManifest(RuntimeType.springBoot);
+    }
+
+    void shouldGenerateKubernetesManifest(RuntimeType rt) throws Exception {
+        KubernetesExport command = createCommand(new String[] { 
"classpath:route.yaml" },
+                "--image-group=camel-test", "--runtime=" + rt.runtime());
         int exit = command.doCall();
 
         Assertions.assertEquals(0, exit);
@@ -79,8 +98,18 @@ class KubernetesExportTest {
     }
 
     @Test
-    public void shouldAddContainerSpec() throws Exception {
-        KubernetesExport command = createCommand(new String[] { 
"classpath:route.yaml" }, "--gav=camel-test:route:1.0.0");
+    public void shouldAddQuarkusContainerSpec() throws Exception {
+        shouldAddContainerSpec(RuntimeType.quarkus);
+    }
+
+    @Test
+    public void shouldAddSpringBootContainerSpec() throws Exception {
+        shouldAddContainerSpec(RuntimeType.springBoot);
+    }
+
+    void shouldAddContainerSpec(RuntimeType rt) throws Exception {
+        KubernetesExport command = createCommand(new String[] { 
"classpath:route.yaml" },
+                "--gav=camel-test:route:1.0.0", "--runtime=" + rt.runtime());
         command.traits = new String[] { "container.port=8088", 
"container.image-pull-policy=IfNotPresent" };
         command.doCall();
 
@@ -99,8 +128,17 @@ class KubernetesExportTest {
     }
 
     @Test
-    public void shouldAddVolumes() throws Exception {
-        KubernetesExport command = createCommand(new String[] { 
"classpath:route.yaml" });
+    public void shouldAddQuarkusVolumes() throws Exception {
+        shouldAddVolumes(RuntimeType.quarkus);
+    }
+
+    @Test
+    public void shouldAddSpringBootVolumes() throws Exception {
+        shouldAddVolumes(RuntimeType.springBoot);
+    }
+
+    void shouldAddVolumes(RuntimeType rt) throws Exception {
+        KubernetesExport command = createCommand(new String[] { 
"classpath:route.yaml" }, "--runtime=" + rt.runtime());
         command.volumes = new String[] { "pvc-foo:/container/path/foo", 
"pvc-bar:/container/path/bar" };
         command.doCall();
 
@@ -127,8 +165,17 @@ class KubernetesExportTest {
     }
 
     @Test
-    public void shouldAddEnvVars() throws Exception {
-        KubernetesExport command = createCommand(new String[] { 
"classpath:route.yaml" });
+    public void shouldAddQuarkusEnvVars() throws Exception {
+        shouldAddEnvVars(RuntimeType.quarkus);
+    }
+
+    @Test
+    public void shouldAddSpringBootEnvVars() throws Exception {
+        shouldAddEnvVars(RuntimeType.springBoot);
+    }
+
+    void shouldAddEnvVars(RuntimeType rt) throws Exception {
+        KubernetesExport command = createCommand(new String[] { 
"classpath:route.yaml" }, "--runtime=" + rt.runtime());
         command.envVars = new String[] { "CAMEL_FOO=bar", "MY_ENV=foo" };
         command.doCall();
 
@@ -147,8 +194,17 @@ class KubernetesExportTest {
     }
 
     @Test
-    public void shouldAddAnnotations() throws Exception {
-        KubernetesExport command = createCommand(new String[] { 
"classpath:route.yaml" });
+    public void shouldAddQuarkusAnnotations() throws Exception {
+        shouldAddAnnotations(RuntimeType.quarkus);
+    }
+
+    @Test
+    public void shouldAddSpringBootAnnotations() throws Exception {
+        shouldAddAnnotations(RuntimeType.springBoot);
+    }
+
+    void shouldAddAnnotations(RuntimeType rt) throws Exception {
+        KubernetesExport command = createCommand(new String[] { 
"classpath:route.yaml" }, "--runtime=" + rt.runtime());
         command.annotations = new String[] { "foo=bar" };
         command.doCall();
 
@@ -159,8 +215,18 @@ class KubernetesExportTest {
     }
 
     @Test
-    public void shouldAddLabels() throws Exception {
-        KubernetesExport command = createCommand(new String[] { 
"classpath:route.yaml" }, "--label=foo=bar");
+    public void shouldAddQuarkusLabels() throws Exception {
+        shouldAddLabels(RuntimeType.quarkus);
+    }
+
+    @Test
+    public void shouldAddSpringBootLabels() throws Exception {
+        shouldAddLabels(RuntimeType.springBoot);
+    }
+
+    void shouldAddLabels(RuntimeType rt) throws Exception {
+        KubernetesExport command = createCommand(new String[] { 
"classpath:route.yaml" },
+                "--label=foo=bar", "--runtime=" + rt.runtime());
         command.doCall();
 
         Deployment deployment = getDeployment(workingDir);
@@ -171,8 +237,17 @@ class KubernetesExportTest {
     }
 
     @Test
-    public void shouldAddConfigs() throws Exception {
-        KubernetesExport command = createCommand(new String[] { 
"classpath:route.yaml" });
+    public void shouldAddQuarkusConfigs() throws Exception {
+        shouldAddConfigs(RuntimeType.quarkus);
+    }
+
+    @Test
+    public void shouldAddSpringBootConfigs() throws Exception {
+        shouldAddConfigs(RuntimeType.springBoot);
+    }
+
+    void shouldAddConfigs(RuntimeType rt) throws Exception {
+        KubernetesExport command = createCommand(new String[] { 
"classpath:route.yaml" }, "--runtime=" + rt.runtime());
         command.configs = new String[] { "secret:foo", "configmap:bar" };
         command.doCall();
 
@@ -196,8 +271,17 @@ class KubernetesExportTest {
     }
 
     @Test
-    public void shouldAddResources() throws Exception {
-        KubernetesExport command = createCommand(new String[] { 
"classpath:route.yaml" });
+    public void shouldAddQuarkusResources() throws Exception {
+        shouldAddResources(RuntimeType.quarkus);
+    }
+
+    @Test
+    public void shouldAddSpringBootResources() throws Exception {
+        shouldAddResources(RuntimeType.springBoot);
+    }
+
+    void shouldAddResources(RuntimeType rt) throws Exception {
+        KubernetesExport command = createCommand(new String[] { 
"classpath:route.yaml" }, "--runtime=" + rt.runtime());
         command.resources = new String[] { "configmap:foo/file.txt" };
         command.doCall();
 
@@ -215,8 +299,17 @@ class KubernetesExportTest {
     }
 
     @Test
-    public void shouldAddOpenApis() throws Exception {
-        KubernetesExport command = createCommand(new String[] { 
"classpath:route.yaml" });
+    public void shouldAddQuarkusOpenApis() throws Exception {
+        shouldAddOpenApis(RuntimeType.quarkus);
+    }
+
+    @Test
+    public void shouldAddSpringBootOpenApis() throws Exception {
+        shouldAddOpenApis(RuntimeType.springBoot);
+    }
+
+    void shouldAddOpenApis(RuntimeType rt) throws Exception {
+        KubernetesExport command = createCommand(new String[] { 
"classpath:route.yaml" }, "--runtime=" + rt.runtime());
         command.openApis = new String[] { "configmap:openapi/spec.yaml" };
         command.doCall();
 
@@ -234,8 +327,17 @@ class KubernetesExportTest {
     }
 
     @Test
-    public void shouldUseImage() throws Exception {
-        KubernetesExport command = createCommand(new String[] { 
"classpath:route.yaml" });
+    public void shouldUseQuarkusImage() throws Exception {
+        shouldUseImage(RuntimeType.quarkus);
+    }
+
+    @Test
+    public void shouldUseSpringBootImage() throws Exception {
+        shouldUseImage(RuntimeType.springBoot);
+    }
+
+    public void shouldUseImage(RuntimeType rt) throws Exception {
+        KubernetesExport command = createCommand(new String[] { 
"classpath:route.yaml" }, "--runtime=" + rt.runtime());
         command.image = "quay.io/camel/demo-app:1.0";
         command.doCall();
 


Reply via email to