You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ma...@apache.org on 2022/08/19 20:24:59 UTC

[camel-karavan] branch main updated: Custom Kamelets for Runtime/Export in VS Code and Cloud-Native (#464)

This is an automated email from the ASF dual-hosted git repository.

marat pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-karavan.git


The following commit(s) were added to refs/heads/main by this push:
     new 85908d4  Custom Kamelets for Runtime/Export in VS Code and Cloud-Native (#464)
85908d4 is described below

commit 85908d44caebbdce5a10c8e2c5dfc29a52dc56e0
Author: Marat Gubaidullin <ma...@gmail.com>
AuthorDate: Fri Aug 19 16:24:54 2022 -0400

    Custom Kamelets for Runtime/Export in VS Code and Cloud-Native (#464)
---
 .github/workflows/app.yml                          |  2 +-
 .github/workflows/builder.yml                      |  2 +-
 karavan-app/pom.xml                                |  2 +-
 .../apache/camel/karavan/api/KameletResources.java | 25 ++------
 .../org/apache/camel/karavan/model/Kamelet.java    |  6 ++
 .../org/apache/camel/karavan/model/Project.java    | 12 +++-
 .../apache/camel/karavan/service/GitService.java   | 70 +++++++++++++++++-----
 .../camel/karavan/service/InfinispanService.java   | 39 ++++++------
 .../camel/karavan/service/KaravanService.java      | 18 +++++-
 .../camel/karavan/service/StatusService.java       |  8 ++-
 .../src/main/resources/application.properties      | 24 ++++----
 karavan-app/src/main/webapp/package.json           |  2 +-
 karavan-builder/openshift/karavan-app.yaml         |  2 +-
 .../openshift/karavan-quarkus-task.yaml            | 65 +++++++++++++++-----
 karavan-builder/openshift/karavan-secret.yaml      | 13 ++--
 karavan-core/package.json                          |  2 +-
 karavan-designer/package.json                      |  2 +-
 karavan-generator/pom.xml                          |  2 +-
 karavan-vscode/package.json                        |  2 +-
 karavan-vscode/src/jbang.ts                        |  9 ++-
 20 files changed, 207 insertions(+), 100 deletions(-)

diff --git a/.github/workflows/app.yml b/.github/workflows/app.yml
index 6471573..5f95a32 100644
--- a/.github/workflows/app.yml
+++ b/.github/workflows/app.yml
@@ -52,7 +52,7 @@ jobs:
           mvn package -f karavan-app -DskipTest \
           -Dquarkus.container-image.build=true \
           -Dquarkus.container-image.push=true \
-          -Dquarkus.container-image.image=ghcr.io/${GITHUB_REPOSITORY}:3.18.2 \
+          -Dquarkus.container-image.image=ghcr.io/${GITHUB_REPOSITORY}:3.18.3 \
           -Dquarkus.container-image.username=${{ github.actor }} \
           -Dquarkus.container-image.password=${{ secrets.GITHUB_TOKEN }}
         if: ${{ github.ref == 'refs/heads/main' }}
diff --git a/.github/workflows/builder.yml b/.github/workflows/builder.yml
index 0a87ec2..f4516f6 100644
--- a/.github/workflows/builder.yml
+++ b/.github/workflows/builder.yml
@@ -8,7 +8,7 @@ on:
 env:
   REGISTRY: ghcr.io
   IMAGE_NAME: ${{ github.repository }}-builder
-  TAG: 3.18.2
+  TAG: 3.18.3
 
 jobs:
   build:
diff --git a/karavan-app/pom.xml b/karavan-app/pom.xml
index 903d567..8654db0 100644
--- a/karavan-app/pom.xml
+++ b/karavan-app/pom.xml
@@ -18,7 +18,7 @@
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     <modelVersion>4.0.0</modelVersion>
         <groupId>org.apache.camel.karavan</groupId>
-        <version>3.18.2</version>
+        <version>3.18.3</version>
     <artifactId>karavan</artifactId>
     <properties>
         <compiler-plugin.version>3.10.1</compiler-plugin.version>
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/api/KameletResources.java b/karavan-app/src/main/java/org/apache/camel/karavan/api/KameletResources.java
index 18facd8..7c6ebbf 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/api/KameletResources.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/api/KameletResources.java
@@ -17,6 +17,7 @@
 package org.apache.camel.karavan.api;
 
 import io.vertx.core.Vertx;
+import org.apache.camel.karavan.service.InfinispanService;
 import org.eclipse.microprofile.config.inject.ConfigProperty;
 
 import javax.inject.Inject;
@@ -38,9 +39,8 @@ import java.util.stream.Collectors;
 @Path("/kamelet")
 public class KameletResources {
 
-
-    @ConfigProperty(name = "karavan.folder.kamelets")
-    String kameletsCustom;
+    @Inject
+    InfinispanService infinispanService;
 
     @Inject
     Vertx vertx;
@@ -49,10 +49,7 @@ public class KameletResources {
     @Produces(MediaType.APPLICATION_JSON)
     public List<String> getList() throws Exception {
         List<String> kameletList = getBuildInKameletsList();
-        if (Files.exists(Paths.get(kameletsCustom))) {
-            List<String> customKameletList = getCustomKamelets();
-            kameletList.addAll(customKameletList);
-        }
+        kameletList.addAll(infinispanService.getKameletNames());
         return kameletList;
     }
 
@@ -74,22 +71,12 @@ public class KameletResources {
     }
 
 
-    private List<String> getCustomKamelets() {
-        return vertx.fileSystem().readDirBlocking(Paths.get(kameletsCustom).toString())
-                .stream()
-                .filter(s -> s.endsWith(".yaml"))
-                .map(s -> {
-                    String[] parts = s.split(Pattern.quote(File.separator));
-                    return parts[parts.length - 1];
-                }).collect(Collectors.toList());
-    }
-
     @GET
     @Produces(MediaType.TEXT_PLAIN)
     @Path("/{name}")
     public String getYaml(@PathParam("name") String name) {
-        if (Files.exists(Paths.get(kameletsCustom, name))) {
-            return vertx.fileSystem().readFileBlocking(Paths.get(kameletsCustom, name).toString()).toString();
+        if (infinispanService.getKameletNames().contains(name)) {
+            return infinispanService.getKameletYaml(name);
         } else {
             return getResourceFile(name);
         }
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/model/Kamelet.java b/karavan-app/src/main/java/org/apache/camel/karavan/model/Kamelet.java
new file mode 100644
index 0000000..7974390
--- /dev/null
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/model/Kamelet.java
@@ -0,0 +1,6 @@
+package org.apache.camel.karavan.model;
+
+public abstract class Kamelet {
+    public static final String CACHE = "kamelets";
+
+}
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/model/Project.java b/karavan-app/src/main/java/org/apache/camel/karavan/model/Project.java
index 898b0ab..844e07a 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/model/Project.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/model/Project.java
@@ -17,6 +17,8 @@ public class Project {
     Project.CamelRuntime runtime;
     @ProtoField(number = 5)
     String lastCommit;
+    @ProtoField(number = 6)
+    Boolean deployed;
 
     public enum CamelRuntime {
         @ProtoEnumValue(number = 0, name = "Quarkus")
@@ -28,12 +30,13 @@ public class Project {
     }
 
     @ProtoFactory
-    public Project(String projectId, String name, String description, CamelRuntime runtime, String lastCommit) {
+    public Project(String projectId, String name, String description, CamelRuntime runtime, String lastCommit, Boolean deployed) {
         this.projectId = projectId;
         this.name = name;
         this.description = description;
         this.runtime = runtime;
         this.lastCommit = lastCommit;
+        this.deployed = deployed;
     }
 
     public Project(String projectId, String name, String description, CamelRuntime runtime) {
@@ -86,4 +89,11 @@ public class Project {
         this.lastCommit = lastCommit;
     }
 
+    public Boolean getDeployed() {
+        return deployed;
+    }
+
+    public void setDeployed(Boolean deployed) {
+        this.deployed = deployed;
+    }
 }
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/service/GitService.java b/karavan-app/src/main/java/org/apache/camel/karavan/service/GitService.java
index 0586769..8a5dbf4 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/service/GitService.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/service/GitService.java
@@ -56,6 +56,9 @@ import java.util.UUID;
 @ApplicationScoped
 public class GitService {
 
+    private static final String PROJECTS = "projects";
+    private static final String KAMELETS = "kamelets";
+
     @Inject
     Vertx vertx;
 
@@ -65,31 +68,33 @@ public class GitService {
     private static final Logger LOGGER = Logger.getLogger(GitService.class.getName());
 
     void onStart(@Observes StartupEvent ev) {
-        LOGGER.info("Git service for repo: " + getGitConfig().getUri());
+        LOGGER.info("Git service for projects repo: " + getGitConfig(PROJECTS).getUri());
+        LOGGER.info("Git service for kamelets repo: " + getGitConfig(KAMELETS).getUri());
     }
 
-    private GitConfig getGitConfig() {
-        String mainBranch = ConfigProvider.getConfig().getValue("karavan.git-main", String.class);
+    private GitConfig getGitConfig(String name) {
+        String prefix = "karavan." + name + "-";
+        String mainBranch = ConfigProvider.getConfig().getValue(prefix + "git-main", String.class);
         if (kubernetesService.inKubernetes()){
             Secret secret =  kubernetesService.getKaravanSecret();
-            String uri = new String(Base64.getDecoder().decode(secret.getData().get("git-repository").getBytes(StandardCharsets.UTF_8)));
-            String username = new String(Base64.getDecoder().decode(secret.getData().get("git-username").getBytes(StandardCharsets.UTF_8)));
-            String password = new String(Base64.getDecoder().decode(secret.getData().get("git-password").getBytes(StandardCharsets.UTF_8)));
-            if (secret.getData().containsKey("git-main")){
-                mainBranch = new String(Base64.getDecoder().decode(secret.getData().get("git-main").getBytes(StandardCharsets.UTF_8)));
+            String uri = new String(Base64.getDecoder().decode(secret.getData().get(prefix + "git-repository").getBytes(StandardCharsets.UTF_8)));
+            String username = new String(Base64.getDecoder().decode(secret.getData().get(prefix + "git-username").getBytes(StandardCharsets.UTF_8)));
+            String password = new String(Base64.getDecoder().decode(secret.getData().get(prefix + "git-password").getBytes(StandardCharsets.UTF_8)));
+            if (secret.getData().containsKey(prefix + "git-main")){
+                mainBranch = new String(Base64.getDecoder().decode(secret.getData().get(prefix + "git-main").getBytes(StandardCharsets.UTF_8)));
             }
             return new GitConfig(uri, username, password, mainBranch);
         } else {
-            String uri = ConfigProvider.getConfig().getValue("karavan.git-repository", String.class);
-            String username = ConfigProvider.getConfig().getValue("karavan.git-username", String.class);
-            String password = ConfigProvider.getConfig().getValue("karavan.git-password", String.class);
+            String uri = ConfigProvider.getConfig().getValue(prefix + "git-repository", String.class);
+            String username = ConfigProvider.getConfig().getValue(prefix + "git-username", String.class);
+            String password = ConfigProvider.getConfig().getValue(prefix + "git-password", String.class);
             return new GitConfig(uri, username, password, mainBranch);
         }
     }
 
     public String commitAndPushProject(Project project, List<ProjectFile> files) throws GitAPIException, IOException, URISyntaxException {
         LOGGER.info("Commit and push project " + project.getProjectId());
-        GitConfig gitConfig = getGitConfig();
+        GitConfig gitConfig = getGitConfig(PROJECTS);
         CredentialsProvider cred = new UsernamePasswordCredentialsProvider(gitConfig.getUsername(), gitConfig.getPassword());
         String uuid = UUID.randomUUID().toString();
         String folder = vertx.fileSystem().createTempDirectoryBlocking(uuid);
@@ -109,9 +114,29 @@ public class GitService {
         return commitAddedAndPush(git, gitConfig.getMainBranch(), cred).getId().getName();
     }
 
-    public List<Tuple2<String, Map<String, String>>> readProjectsFromRepository() throws GitAPIException, IOException, URISyntaxException {
+    public List<Tuple2<String, String>> readKameletsFromRepository() {
+        LOGGER.info("Read kamelets from repository");
+        GitConfig gitConfig = getGitConfig(KAMELETS);
+        CredentialsProvider cred = new UsernamePasswordCredentialsProvider(gitConfig.getUsername(), gitConfig.getPassword());
+        String uuid = UUID.randomUUID().toString();
+        String folder = vertx.fileSystem().createTempDirectoryBlocking(uuid);
+        LOGGER.infof("Temp folder created: %s", folder);
+        try {
+            Git git = clone(folder, gitConfig.getUri(), gitConfig.getMainBranch(), cred);
+            checkout(git, false, null, null, gitConfig.getMainBranch());
+            return readKameletsFromFolder(folder);
+        } catch (RefNotFoundException e) {
+            LOGGER.error("New repository");
+            return List.of();
+        } catch (Exception e) {
+            LOGGER.error("Error", e);
+            return List.of();
+        }
+    }
+
+    public List<Tuple2<String, Map<String, String>>> readProjectsFromRepository() {
         LOGGER.info("Read projects from repository");
-        GitConfig gitConfig = getGitConfig();
+        GitConfig gitConfig = getGitConfig(PROJECTS);
         CredentialsProvider cred = new UsernamePasswordCredentialsProvider(gitConfig.getUsername(), gitConfig.getPassword());
         String uuid = UUID.randomUUID().toString();
         String folder = vertx.fileSystem().createTempDirectoryBlocking(uuid);
@@ -136,7 +161,22 @@ public class GitService {
         }
     }
 
-    private List<String> readProjectsFromFolder(String folder) throws IOException {
+    private List<Tuple2<String, String>> readKameletsFromFolder(String folder) {
+        LOGGER.info("Read kamelets from " + folder);
+        List<Tuple2<String, String>> kamelets = new ArrayList<>();
+        vertx.fileSystem().readDirBlocking(folder).stream().filter(f -> f.endsWith("kamelet.yaml")).forEach(f -> {
+            Path path = Paths.get(f);
+            try {
+                String yaml = Files.readString(path);
+                kamelets.add(Tuple2.of(path.getFileName().toString(), yaml));
+            } catch (IOException e) {
+                LOGGER.error("Error during file read", e);
+            }
+        });
+        return kamelets;
+    }
+
+    private List<String> readProjectsFromFolder(String folder) {
         LOGGER.info("Read projects from " + folder);
         List<String> files = new ArrayList<>();
         vertx.fileSystem().readDirBlocking(folder).forEach(f -> {
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/service/InfinispanService.java b/karavan-app/src/main/java/org/apache/camel/karavan/service/InfinispanService.java
index ed42868..e99a406 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/service/InfinispanService.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/service/InfinispanService.java
@@ -20,6 +20,7 @@ import io.quarkus.runtime.StartupEvent;
 import io.quarkus.runtime.configuration.ProfileManager;
 import io.vertx.core.eventbus.EventBus;
 import org.apache.camel.karavan.model.GroupedKey;
+import org.apache.camel.karavan.model.Kamelet;
 import org.apache.camel.karavan.model.Project;
 import org.apache.camel.karavan.model.ProjectFile;
 import org.apache.camel.karavan.model.ProjectStatus;
@@ -56,6 +57,8 @@ public class InfinispanService {
 
     BasicCache<GroupedKey, ProjectStatus> statuses;
 
+    BasicCache<String, String> kamelets;
+
     @Inject
     RemoteCacheManager cacheManager;
 
@@ -92,16 +95,21 @@ public class InfinispanService {
             projects = cacheManager.administration().withFlags(CacheContainerAdmin.AdminFlag.VOLATILE).getOrCreateCache(Project.CACHE, builder.build());
             files = cacheManager.administration().withFlags(CacheContainerAdmin.AdminFlag.VOLATILE).getOrCreateCache(ProjectFile.CACHE, builder.build());
             statuses = cacheManager.administration().withFlags(CacheContainerAdmin.AdminFlag.VOLATILE).getOrCreateCache(ProjectStatus.CACHE, builder.build());
+            kamelets = cacheManager.administration().withFlags(CacheContainerAdmin.AdminFlag.VOLATILE).getOrCreateCache(Kamelet.CACHE, builder.build());
         } else {
             LOGGER.info("InfinispanService is starting in remote mode");
             projects = cacheManager.administration().getOrCreateCache(Project.CACHE, new XMLStringConfiguration(String.format(CACHE_CONFIG, Project.CACHE)));
             files = cacheManager.administration().getOrCreateCache(ProjectFile.CACHE, new XMLStringConfiguration(String.format(CACHE_CONFIG, ProjectFile.CACHE)));
             statuses = cacheManager.administration().getOrCreateCache(ProjectFile.CACHE, new XMLStringConfiguration(String.format(CACHE_CONFIG, ProjectStatus.CACHE)));
+            kamelets = cacheManager.administration().getOrCreateCache(Kamelet.CACHE, new XMLStringConfiguration(String.format(CACHE_CONFIG, Kamelet.CACHE)));
         }
         if (getProjects().isEmpty()) {
             LOGGER.info("No projects found in the Data Grid");
             bus.publish(KaravanService.IMPORT_PROJECTS, "");
         }
+
+        bus.publish(KaravanService.LOAD_CUSTOM_KAMELETS, "");
+
         if (ProfileManager.getLaunchMode().isDevOrTest() && getProjects().isEmpty()){
 //            generateDevProjects();
         }
@@ -164,26 +172,15 @@ public class InfinispanService {
         statuses.put(GroupedKey.create(status.getProjectId(), status.getProjectId()), status);
     }
 
-    private void generateDevProjects() {
-        LOGGER.info("Generate demo projects");
-        for (int i = 0; i < 10; i++){
-            String projectId = "parcel-demo" + i;
-            Project p = new Project(projectId, "Demo project " + i, "Demo project placeholder for UI testing purposes", Project.CamelRuntime.valueOf(runtime));
-            this.saveProject(p);
-
-            files.put(GroupedKey.create(p.getProjectId(),"new-parcels.yaml"), new ProjectFile("new-parcels.yaml", "flows:", p.getProjectId()));
-            files.put(GroupedKey.create(p.getProjectId(),"parcel-confirmation.yaml"), new ProjectFile("parcel-confirmation.yaml", "rest:", p.getProjectId()));
-            files.put(GroupedKey.create(p.getProjectId(),"CustomProcessor.java"), new ProjectFile("CustomProcessor.java", "import org.apache.camel.BindToRegistry;\n" +
-                    "import org.apache.camel.Exchange;\n" +
-                    "import org.apache.camel.Processor;\n" +
-                    "\n" +
-                    "@BindToRegistry(\"myBean\")\n" +
-                    "public class CustomProcessor implements Processor {\n" +
-                    "\n" +
-                    "  public void process(Exchange exchange) throws Exception {\n" +
-                    "      exchange.getIn().setBody(\"Hello world\");\n" +
-                    "  }\n" +
-                    "}", p.getProjectId()));
-        }
+    public List<String> getKameletNames() {
+        return kamelets.keySet().stream().collect(Collectors.toList());
+    }
+
+    public String getKameletYaml(String name) {
+        return kamelets.get(name);
+    }
+
+    public void saveKamelet(String name, String yaml) {
+        kamelets.put(name, yaml);
     }
 }
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/service/KaravanService.java b/karavan-app/src/main/java/org/apache/camel/karavan/service/KaravanService.java
index ebc2384..8d43128 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/service/KaravanService.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/service/KaravanService.java
@@ -39,6 +39,7 @@ public class KaravanService {
 
     private static final Logger LOGGER = Logger.getLogger(KaravanService.class.getName());
     public static final String IMPORT_PROJECTS = "import-projects";
+    public static final String LOAD_CUSTOM_KAMELETS = "load-custom-kamelets";
 
     @Inject
     InfinispanService infinispanService;
@@ -63,7 +64,7 @@ public class KaravanService {
             repo.forEach(p -> {
                 String folderName = p.getItem1();
                 String name = Arrays.stream(folderName.split("-")).map(s -> capitalize(s)).collect(Collectors.joining(" "));
-                Project project = new Project(folderName, name, name, Project.CamelRuntime.valueOf(runtime.toUpperCase()), "");
+                Project project = new Project(folderName, name, name, Project.CamelRuntime.valueOf(runtime.toUpperCase()), "", false);
                 infinispanService.saveProject(project);
 
                 AtomicReference<ProjectFile> properties = new AtomicReference<>();
@@ -87,6 +88,21 @@ public class KaravanService {
         }
     }
 
+    @ConsumeEvent(value = LOAD_CUSTOM_KAMELETS, blocking = true)
+    void loadCustomKamelets(String data) {
+        LOGGER.info("Load custom Kamelets from Git");
+        try {
+            List<Tuple2<String, String>> repo = gitService.readKameletsFromRepository();
+            repo.forEach(p -> {
+                String name = p.getItem1();
+                String yaml = p.getItem2();
+                infinispanService.saveKamelet(name, yaml);
+            });
+        } catch (Exception e) {
+            LOGGER.error("Error during project import", e);
+        }
+    }
+
     private static String capitalize(String str) {
         if(str == null || str.isEmpty()) {
             return str;
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/service/StatusService.java b/karavan-app/src/main/java/org/apache/camel/karavan/service/StatusService.java
index a07889f..0d340c6 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/service/StatusService.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/service/StatusService.java
@@ -72,9 +72,11 @@ public class StatusService {
 
     @ConsumeEvent(value = CMD_COLLECT_STATUSES, blocking = true, ordered = true)
     public void collectStatuses(String projectId) throws Exception {
-        if ((System.currentTimeMillis() - lastCollect) > configuration.statusThreshold()){
-            getStatuses(projectId);
-            lastCollect = System.currentTimeMillis();
+        if ((System.currentTimeMillis() - lastCollect) > configuration.statusThreshold()) {
+            if (infinispanService.getProject(projectId).getDeployed()) {
+                getStatuses(projectId);
+                lastCollect = System.currentTimeMillis();
+            }
         }
     }
 
diff --git a/karavan-app/src/main/resources/application.properties b/karavan-app/src/main/resources/application.properties
index 047f4e9..cf78dab 100644
--- a/karavan-app/src/main/resources/application.properties
+++ b/karavan-app/src/main/resources/application.properties
@@ -1,15 +1,19 @@
 karavan.version=${project.version}
 
-karavan.folder.kamelets=kamelets
-
 karavan.master-username=admin
 karavan.master-password=karavan
 
 # Git repository Configuration
-karavan.git-repository=${GIT_REPOSITORY}
-karavan.git-username=${GIT_USERNAME}
-karavan.git-password=${GIT_TOKEN}
-karavan.git-main=main
+karavan.projects-git-repository=${GIT_REPOSITORY}
+karavan.projects-git-username=${GIT_USERNAME}
+karavan.projects-git-password=${GIT_TOKEN}
+karavan.projects-git-main=main
+
+# Git repository Configuration for custom Kamelets
+karavan.kamelets-git-repository=${KAMELETS_GIT_REPOSITORY}
+karavan.kamelets-git-username=${GIT_USERNAME}
+karavan.kamelets-git-password=${GIT_TOKEN}
+karavan.kamelets-git-main=main
 
 # Projects configuration
 karavan.config.group-id=org.camel.karavan.demo
@@ -68,10 +72,10 @@ quarkus.container-image.tag=${project.version}
 
 quarkus.container-image.builder=docker
 
-quarkus.kubernetes-client.trust-certs=true
-quarkus.kubernetes.deployment-target=openshift
-quarkus.kubernetes-config.enabled=true
-quarkus.kubernetes-config.secrets.enabled=true
+#quarkus.kubernetes-client.trust-certs=true
+#quarkus.kubernetes.deployment-target=openshift
+#quarkus.kubernetes-config.enabled=true
+#quarkus.kubernetes-config.secrets.enabled=true
 
 quarkus.kubernetes-client.connection-timeout=2000
 quarkus.kubernetes-client.request-timeout=10000
diff --git a/karavan-app/src/main/webapp/package.json b/karavan-app/src/main/webapp/package.json
index f2691a5..f3e2f86 100644
--- a/karavan-app/src/main/webapp/package.json
+++ b/karavan-app/src/main/webapp/package.json
@@ -1,6 +1,6 @@
 {
   "name": "karavan",
-  "version": "3.18.2",
+  "version": "3.18.3",
   "private": true,
   "scripts": {
     "copy-designer": "cp -r ../../../../karavan-designer/src/designer src && cp -r ../../../../karavan-designer/src/kamelets src && cp -r ../../../../karavan-designer/src/components src && cp -r ../../../../karavan-designer/src/eip src",
diff --git a/karavan-builder/openshift/karavan-app.yaml b/karavan-builder/openshift/karavan-app.yaml
index 8cb16fd..f568ded 100644
--- a/karavan-builder/openshift/karavan-app.yaml
+++ b/karavan-builder/openshift/karavan-app.yaml
@@ -40,7 +40,7 @@ spec:
               valueFrom:
                 fieldRef:
                   fieldPath: metadata.namespace
-          image: ghcr.io/apache/camel-karavan:3.18.2
+          image: ghcr.io/apache/camel-karavan:3.18.3
           imagePullPolicy: Always
           name: karavan
           resources:
diff --git a/karavan-builder/openshift/karavan-quarkus-task.yaml b/karavan-builder/openshift/karavan-quarkus-task.yaml
index 4b7cb00..db794ee 100644
--- a/karavan-builder/openshift/karavan-quarkus-task.yaml
+++ b/karavan-builder/openshift/karavan-quarkus-task.yaml
@@ -10,21 +10,33 @@ spec:
     - name: karavan-build-deploy
       script: |
           #!/usr/bin/env bash
-          CHECKOUT_DIR="/scripts"
+          KAMELETS_DIR="/kamelets"
+          
+          if  [[ $KAMELETS_GIT_REPOSITORY == https* ]] ;
+          then
+              replacer=https://$KAMELETS_GIT_PASSWORD@
+              prefix=https://
+              url="${KAMELETS_GIT_REPOSITORY/$prefix/$replacer}"    
+              git clone --depth 1 --branch ${KAMELETS_GIT_MAIN} $url ${KAMELETS_DIR}
+          else
+              git clone --depth 1 --branch ${KAMELETS_GIT_MAIN} ${KAMELETS_GIT_REPOSITORY} ${KAMELETS_DIR}    
+          fi
 
-          if  [[ $GIT_REPOSITORY == https* ]] ;
+          CHECKOUT_DIR="/scripts"
+          
+          if  [[ $PROJECTS_GIT_REPOSITORY == https* ]] ;
           then
-              replacer=https://$GIT_PASSWORD@
+              replacer=https://$PROJECTS_GIT_PASSWORD@
               prefix=https://
-              url="${GIT_REPOSITORY/$prefix/$replacer}"    
-              git clone --depth 1 --branch main $url ${CHECKOUT_DIR}
+              url="${PROJECTS_GIT_REPOSITORY/$prefix/$replacer}"    
+              git clone --depth 1 --branch ${PROJECTS_GIT_MAIN} $url ${CHECKOUT_DIR}
           else
-              git clone --depth 1 --branch main ${GIT_REPOSITORY} ${CHECKOUT_DIR}    
+              git clone --depth 1 --branch ${PROJECTS_GIT_MAIN} ${PROJECTS_GIT_REPOSITORY} ${CHECKOUT_DIR}    
           fi
 
           cd ${CHECKOUT_DIR}/$(inputs.params.project) 
 
-          entrypoint -Dcamel.jbang.version=3.18.1 camel@apache/camel export
+          entrypoint -Dcamel.jbang.version=3.18.1 camel@apache/camel export --local-kamelet-dir=${KAMELETS_DIR}
 
           export LAST_COMMIT=$(git rev-parse --short HEAD)
           export DATE=$(date '+%Y%m%d%H%M%S')
@@ -44,23 +56,48 @@ spec:
             -Dquarkus.kubernetes.deploy=true \
             -Dquarkus.container-image.group=${NAMESPACE} \
             -Dquarkus.container-image.tag=${DATE}
-      image: 'ghcr.io/apache/camel-karavan-builder:3.18.2'
+      image: 'ghcr.io/apache/camel-karavan-builder:3.18.3'
       env:
-        - name: GIT_REPOSITORY
+        - name: PROJECTS_GIT_REPOSITORY
+          valueFrom:
+            secretKeyRef:
+              name: karavan
+              key: projects-git-repository
+        - name: PROJECTS_GIT_USERNAME
+          valueFrom:
+            secretKeyRef:
+              name: karavan
+              key: projects-git-username
+        - name: PROJECTS_GIT_PASSWORD
+          valueFrom:
+            secretKeyRef:
+              name: karavan
+              key: projects-git-password
+        - name: PROJECTS_GIT_MAIN
+          valueFrom:
+            secretKeyRef:
+              name: karavan
+              key: projects-git-main
+        - name: KAMELETS_GIT_REPOSITORY
+          valueFrom:
+            secretKeyRef:
+              name: karavan
+              key: kamelets-git-repository
+        - name: KAMELETS_GIT_USERNAME
           valueFrom:
             secretKeyRef:
               name: karavan
-              key: git-repository
-        - name: GIT_USERNAME
+              key: kamelets-git-username
+        - name: KAMELETS_GIT_PASSWORD
           valueFrom:
             secretKeyRef:
               name: karavan
-              key: git-username
-        - name: GIT_PASSWORD
+              key: kamelets-git-password
+        - name: KAMELETS_GIT_MAIN
           valueFrom:
             secretKeyRef:
               name: karavan
-              key: git-password
+              key: kamelets-git-main      
     - name: rollout
       image: >-
         image-registry.openshift-image-registry.svc:5000/openshift/cli:latest
diff --git a/karavan-builder/openshift/karavan-secret.yaml b/karavan-builder/openshift/karavan-secret.yaml
index c7d7333..c515eb9 100644
--- a/karavan-builder/openshift/karavan-secret.yaml
+++ b/karavan-builder/openshift/karavan-secret.yaml
@@ -6,8 +6,11 @@ type: Opaque
 stringData:
   master-username: admin
   master-password: karavan
-  git-repository: https://github.com/mgubaidullin/karavan-demo.git
-  git-password: demo
-  git-username: demo
-  git-main: main
-
+  projects-git-repository: https://github.com/mgubaidullin/karavan-demo.git
+  projects-git-password: demo
+  projects-git-username: demo
+  projects-git-main: main
+  kamelets-git-repository: https://github.com/mgubaidullin/karavan-kamelets.git
+  kamelets-git-password: demo
+  kamelets-git-username: demo
+  kamelets-git-main: main
diff --git a/karavan-core/package.json b/karavan-core/package.json
index bc41752..b65a294 100644
--- a/karavan-core/package.json
+++ b/karavan-core/package.json
@@ -1,7 +1,7 @@
 {
   "name": "karavan-core",
   "publisher": "camel-karavan",
-  "version": "3.18.2",
+  "version": "3.18.3",
   "description": "Apache Camel Karavan Core",
   "scripts": {
     "build": "tsc",
diff --git a/karavan-designer/package.json b/karavan-designer/package.json
index 2648e3f..f16b46c 100644
--- a/karavan-designer/package.json
+++ b/karavan-designer/package.json
@@ -1,6 +1,6 @@
 {
   "name": "karavan-designer",
-  "version": "3.18.2",
+  "version": "3.18.3",
   "license": "Apache-2.0",
   "scripts": {
     "start": "react-scripts start",
diff --git a/karavan-generator/pom.xml b/karavan-generator/pom.xml
index 37c29d6..7079880 100644
--- a/karavan-generator/pom.xml
+++ b/karavan-generator/pom.xml
@@ -19,7 +19,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.apache.camel.karavan</groupId>
     <artifactId>karavan-generator</artifactId>
-    <version>3.18.2</version>
+    <version>3.18.3</version>
     <properties>
         <compiler-plugin.version>3.8.1</compiler-plugin.version>
         <maven.compiler.parameters>true</maven.compiler.parameters>
diff --git a/karavan-vscode/package.json b/karavan-vscode/package.json
index 5d87139..f8bf455 100644
--- a/karavan-vscode/package.json
+++ b/karavan-vscode/package.json
@@ -4,7 +4,7 @@
   "displayName": "Karavan",
   "icon": "icons/karavan.png",
   "description": "Apache Camel Mastering Tool",
-  "version": "3.18.2",
+  "version": "3.18.3",
   "license": "Apache-2.0",
   "preview": true,
   "bugs": {
diff --git a/karavan-vscode/src/jbang.ts b/karavan-vscode/src/jbang.ts
index 6f72e89..6ead790 100644
--- a/karavan-vscode/src/jbang.ts
+++ b/karavan-vscode/src/jbang.ts
@@ -78,8 +78,11 @@ function prepareCommand(command: string): string {
 
 export function camelJbangRun(filename?: string) {
     const maxMessages: number = workspace.getConfiguration().get("camel.maxMessages") || -1;
+    const kameletsPath: string | undefined = workspace.getConfiguration().get("Karavan.kameletsPath");
     const dev: boolean = workspace.getConfiguration().get("camel.dev") || false;
-    const cmd = (filename ? "run " + filename : "run * ") + (maxMessages > -1 ? " --max-messages=" + maxMessages : "");
+    const cmd = (filename ? "run " + filename : "run * ") 
+        + (maxMessages > -1 ? " --max-messages=" + maxMessages : "")
+        + (kameletsPath && kameletsPath.trim().length >0 ? " --local-kamelet-dir=" + kameletsPath : "");
     const command = prepareCommand(cmd) + (dev === true ? " --dev" : "");
     const terminalId = "run_" + filename;
     const existTerminal = TERMINALS.get(terminalId);
@@ -91,7 +94,9 @@ export function camelJbangRun(filename?: string) {
 }
 
 export function camelJbangExport(directory: string) {
-    const cmd = "export  --directory=" + directory;
+    const kameletsPath: string | undefined = workspace.getConfiguration().get("Karavan.kameletsPath");
+    const cmd = "export  --directory=" + directory
+        + (kameletsPath && kameletsPath.trim().length >0 ? " --local-kamelet-dir=" + kameletsPath : "");
     const command = prepareCommand(cmd);
     const terminalId = "export";
     const existTerminal = TERMINALS.get(terminalId);