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 2023/07/22 01:20:02 UTC

[camel-karavan] branch main updated (0362f7ed -> b8ac47a4)

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

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


    from 0362f7ed Doc improvements #743
     new 365e9d6a karavan-infinispan #817
     new fc9c11fb karavan-headless #817
     new e93a16a3 karavan-infinispan #817
     new 333d04f0 karavan-headless #817
     new b8ac47a4 karavan-app #817

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../karavan-app/Dockerfile.legacy-jar.dockerignore |   5 -
 .../karavan-app/Dockerfile.multistage.dockerignore |   3 -
 karavan-web/karavan-app/pom.xml                    |  60 ++---------
 .../src/main/docker/Dockerfile.legacy-jar          |  41 --------
 .../src/main/docker/Dockerfile.multistage          |  66 ------------
 .../apache/camel/karavan/api/DevModeResource.java  |   4 +-
 .../camel/karavan/docker/DockerEventListener.java  |   5 +-
 .../apache/camel/karavan/docker/DockerService.java |  57 +++++++++--
 .../karavan/kubernetes/KubernetesService.java      |   2 +-
 .../camel/karavan/kubernetes/PodEventHandler.java  |   3 +-
 .../apache/camel/karavan/service/CamelService.java |  42 +++-----
 .../apache/camel/karavan/service/EventService.java |  25 +++--
 .../camel/karavan/service/ScheduledService.java    |  17 ++--
 .../apache/camel/karavan/shared/ConfigService.java |   7 ++
 .../org/apache/camel/karavan/shared/EventType.java |   2 +-
 .../src/main/resources/application.properties      |  15 +--
 .../src/test/resources/application.properties      |  11 --
 .../.dockerignore                                  |   0
 .../.mvn/wrapper/maven-wrapper.properties          |   0
 .../Dockerfile.distroless.dockerignore             |   0
 .../karavan-headless}/mvnw                         |   0
 .../karavan-headless}/mvnw.cmd                     |   0
 .../karavan-headless}/pom.xml                      | 110 ++++++++++----------
 .../src/main/docker/Dockerfile.distroless          |   0
 .../camel/karavan/headless}/CamelService.java      |  63 ++++--------
 .../camel/karavan/headless/EventService.java       |  52 ++++++++++
 .../camel/karavan/headless/HeadlessService.java}   |  38 +++----
 .../src/main/resources/application.properties      |  14 +++
 .../.mvn/wrapper/maven-wrapper.properties          |   0
 .../karavan-infinispan}/mvnw                       |   0
 .../karavan-infinispan}/mvnw.cmd                   |   0
 .../karavan-infinispan}/pom.xml                    | 112 +++++++++++----------
 .../karavan/infinispan/CodeReloadListener.java     |  30 ++++++
 .../karavan/infinispan/InfinispanService.java      |  42 ++++++--
 .../karavan/infinispan/model/CamelStatus.java      |   0
 .../camel/karavan/infinispan/model/CommitInfo.java |   0
 .../karavan/infinispan/model/ContainerInfo.java    |   0
 .../karavan/infinispan/model/ContainerStatus.java  |  33 +-----
 .../karavan/infinispan/model/DeploymentStatus.java |   0
 .../karavan/infinispan/model/DevModeStatus.java    |   0
 .../camel/karavan/infinispan/model/GitConfig.java  |   0
 .../camel/karavan/infinispan/model/GitRepo.java    |   0
 .../karavan/infinispan/model/GitRepoFile.java      |   0
 .../camel/karavan/infinispan/model/GroupedKey.java |   9 ++
 .../karavan/infinispan/model/KaravanSchema.java    |   0
 .../karavan/infinispan/model/PipelineStatus.java   |   0
 .../camel/karavan/infinispan/model/Project.java    |   0
 .../karavan/infinispan/model/ProjectFile.java      |   0
 .../karavan/infinispan/model/ServiceStatus.java    |   0
 .../src/main/resources/application.properties      |  14 +++
 .../main/resources/cache/command-cache-config.xml  |   0
 .../src/main/resources/cache/data-cache-config.xml |   0
 .../camel/karavan/infinispan/DataGridTest.java     |  27 ++++-
 karavan-web/pom.xml                                |   8 +-
 54 files changed, 443 insertions(+), 474 deletions(-)
 delete mode 100644 karavan-web/karavan-app/Dockerfile.legacy-jar.dockerignore
 delete mode 100644 karavan-web/karavan-app/Dockerfile.multistage.dockerignore
 delete mode 100644 karavan-web/karavan-app/src/main/docker/Dockerfile.legacy-jar
 delete mode 100644 karavan-web/karavan-app/src/main/docker/Dockerfile.multistage
 delete mode 100644 karavan-web/karavan-app/src/test/resources/application.properties
 copy karavan-web/{karavan-app => karavan-headless}/.dockerignore (100%)
 copy {karavan-generator => karavan-web/karavan-headless}/.mvn/wrapper/maven-wrapper.properties (100%)
 copy karavan-web/{karavan-app => karavan-headless}/Dockerfile.distroless.dockerignore (100%)
 copy {karavan-generator => karavan-web/karavan-headless}/mvnw (100%)
 copy {karavan-generator => karavan-web/karavan-headless}/mvnw.cmd (100%)
 copy {karavan-generator => karavan-web/karavan-headless}/pom.xml (51%)
 copy karavan-web/{karavan-app => karavan-headless}/src/main/docker/Dockerfile.distroless (100%)
 copy karavan-web/{karavan-app/src/main/java/org/apache/camel/karavan/service => karavan-headless/src/main/java/org/apache/camel/karavan/headless}/CamelService.java (73%)
 create mode 100644 karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/EventService.java
 copy karavan-web/{karavan-app/src/main/java/org/apache/camel/karavan/service/ScheduledService.java => karavan-headless/src/main/java/org/apache/camel/karavan/headless/HeadlessService.java} (56%)
 create mode 100644 karavan-web/karavan-headless/src/main/resources/application.properties
 copy {karavan-generator => karavan-web/karavan-infinispan}/.mvn/wrapper/maven-wrapper.properties (100%)
 copy {karavan-generator => karavan-web/karavan-infinispan}/mvnw (100%)
 copy {karavan-generator => karavan-web/karavan-infinispan}/mvnw.cmd (100%)
 copy {karavan-generator => karavan-web/karavan-infinispan}/pom.xml (50%)
 create mode 100644 karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/CodeReloadListener.java
 rename karavan-web/{karavan-app => karavan-infinispan}/src/main/java/org/apache/camel/karavan/infinispan/InfinispanService.java (93%)
 rename karavan-web/{karavan-app => karavan-infinispan}/src/main/java/org/apache/camel/karavan/infinispan/model/CamelStatus.java (100%)
 rename karavan-web/{karavan-app => karavan-infinispan}/src/main/java/org/apache/camel/karavan/infinispan/model/CommitInfo.java (100%)
 rename karavan-web/{karavan-app => karavan-infinispan}/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerInfo.java (100%)
 rename karavan-web/{karavan-app => karavan-infinispan}/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerStatus.java (77%)
 rename karavan-web/{karavan-app => karavan-infinispan}/src/main/java/org/apache/camel/karavan/infinispan/model/DeploymentStatus.java (100%)
 rename karavan-web/{karavan-app => karavan-infinispan}/src/main/java/org/apache/camel/karavan/infinispan/model/DevModeStatus.java (100%)
 rename karavan-web/{karavan-app => karavan-infinispan}/src/main/java/org/apache/camel/karavan/infinispan/model/GitConfig.java (100%)
 rename karavan-web/{karavan-app => karavan-infinispan}/src/main/java/org/apache/camel/karavan/infinispan/model/GitRepo.java (100%)
 rename karavan-web/{karavan-app => karavan-infinispan}/src/main/java/org/apache/camel/karavan/infinispan/model/GitRepoFile.java (100%)
 rename karavan-web/{karavan-app => karavan-infinispan}/src/main/java/org/apache/camel/karavan/infinispan/model/GroupedKey.java (87%)
 rename karavan-web/{karavan-app => karavan-infinispan}/src/main/java/org/apache/camel/karavan/infinispan/model/KaravanSchema.java (100%)
 rename karavan-web/{karavan-app => karavan-infinispan}/src/main/java/org/apache/camel/karavan/infinispan/model/PipelineStatus.java (100%)
 rename karavan-web/{karavan-app => karavan-infinispan}/src/main/java/org/apache/camel/karavan/infinispan/model/Project.java (100%)
 rename karavan-web/{karavan-app => karavan-infinispan}/src/main/java/org/apache/camel/karavan/infinispan/model/ProjectFile.java (100%)
 rename karavan-web/{karavan-app => karavan-infinispan}/src/main/java/org/apache/camel/karavan/infinispan/model/ServiceStatus.java (100%)
 create mode 100644 karavan-web/karavan-infinispan/src/main/resources/application.properties
 rename karavan-web/{karavan-app => karavan-infinispan}/src/main/resources/cache/command-cache-config.xml (100%)
 rename karavan-web/{karavan-app => karavan-infinispan}/src/main/resources/cache/data-cache-config.xml (100%)
 rename karavan-web/{karavan-app => karavan-infinispan}/src/test/java/org/apache/camel/karavan/infinispan/DataGridTest.java (65%)


[camel-karavan] 05/05: karavan-app #817

Posted by ma...@apache.org.
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

commit b8ac47a41a185e8fe7f9eae1559203d42af7e5bf
Author: Marat Gubaidullin <ma...@gmail.com>
AuthorDate: Fri Jul 21 21:19:51 2023 -0400

    karavan-app #817
---
 karavan-web/karavan-app/pom.xml                    | 60 +++-------------------
 .../apache/camel/karavan/api/DevModeResource.java  |  4 +-
 .../camel/karavan/docker/DockerEventListener.java  |  5 +-
 .../apache/camel/karavan/docker/DockerService.java | 57 ++++++++++++++++----
 .../karavan/kubernetes/KubernetesService.java      |  2 +-
 .../camel/karavan/kubernetes/PodEventHandler.java  |  3 +-
 .../apache/camel/karavan/service/CamelService.java | 42 +++++----------
 .../apache/camel/karavan/service/EventService.java | 25 ++++++---
 .../camel/karavan/service/ScheduledService.java    | 17 +++---
 .../apache/camel/karavan/shared/ConfigService.java |  7 +++
 .../org/apache/camel/karavan/shared/EventType.java |  2 +-
 .../src/main/resources/application.properties      | 15 ++----
 karavan-web/pom.xml                                |  8 +--
 13 files changed, 110 insertions(+), 137 deletions(-)

diff --git a/karavan-web/karavan-app/pom.xml b/karavan-web/karavan-app/pom.xml
index 620584ec..f38269f9 100644
--- a/karavan-web/karavan-app/pom.xml
+++ b/karavan-web/karavan-app/pom.xml
@@ -20,12 +20,17 @@
     <artifactId>karavan</artifactId>
     <parent>
         <groupId>org.apache.camel.karavan</groupId>
-        <artifactId>karavan-cloud</artifactId>
+        <artifactId>karavan-web</artifactId>
         <version>3.21.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 
     <dependencies>
+        <dependency>
+            <groupId>org.apache.camel.karavan</groupId>
+            <artifactId>karavan-infinispan</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>io.quarkus</groupId>
             <artifactId>quarkus-smallrye-reactive-messaging</artifactId>
@@ -104,11 +109,6 @@
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
         </dependency>
-        <!-- Infinispan -->
-        <dependency>
-            <groupId>io.quarkus</groupId>
-            <artifactId>quarkus-infinispan-client</artifactId>
-        </dependency>
         <!-- Docker -->
         <dependency>
             <groupId>com.github.docker-java</groupId>
@@ -144,11 +144,6 @@
             <artifactId>rest-assured</artifactId>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>io.quarkiverse.quinoa</groupId>
-            <artifactId>quarkus-quinoa</artifactId>
-            <version>${quinoa.version}</version>
-        </dependency>
     </dependencies>
     <build>
         <resources>
@@ -164,13 +159,6 @@
                     <include>**/**.xml</include>
                 </includes>
             </resource>
-            <resource>
-                <directory>target/classes/proto</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>karavan.proto</include>
-                </includes>
-            </resource>
         </resources>
         <plugins>
             <plugin>
@@ -224,42 +212,6 @@
             </plugin>
         </plugins>
     </build>
-    <profiles>
-        <profile>
-            <id>native</id>
-            <activation>
-                <property>
-                    <name>native</name>
-                </property>
-            </activation>
-            <build>
-                <plugins>
-                    <plugin>
-                        <artifactId>maven-failsafe-plugin</artifactId>
-                        <version>${surefire-plugin.version}</version>
-                        <executions>
-                            <execution>
-                                <goals>
-                                    <goal>integration-test</goal>
-                                    <goal>verify</goal>
-                                </goals>
-                                <configuration>
-                                    <systemPropertyVariables>
-                                        <native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
-                                        <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
-                                        <maven.home>${maven.home}</maven.home>
-                                    </systemPropertyVariables>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-            <properties>
-                <quarkus.package.type>native</quarkus.package.type>
-            </properties>
-        </profile>
-    </profiles>
     <repositories>
         <repository>
             <id>apache.snapshots</id>
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/DevModeResource.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/DevModeResource.java
index 4170abd8..a5372ed9 100644
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/DevModeResource.java
+++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/DevModeResource.java
@@ -63,9 +63,9 @@ public class DevModeResource {
         if (status == null) {
             infinispanService.saveDevModeStatus(new DevModeStatus(project.getProjectId(), null, null, false));
             if (ConfigService.inKubernetes()) {
-                kubernetesService.createRunner(project, runnerName, "");
+                kubernetesService.runDevModeContainer(project, runnerName, "");
             } else {
-                dockerService.createRunner(project, runnerName, "");
+                dockerService.runDevmodeContainer(project, runnerName, "");
             }
             return Response.ok(runnerName).build();
         }
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerEventListener.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerEventListener.java
index 64816aea..40c2b858 100644
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerEventListener.java
+++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerEventListener.java
@@ -97,6 +97,7 @@ public class DockerEventListener implements ResultCallback<Event> {
                 String name = container.getNames()[0].replace("/", "");
                 if (Arrays.asList("stop", "die", "kill", "pause", "destroy").contains(event.getStatus())) {
                     String projectId = name.replace(DEVMODE_SUFFIX, "");
+                    infinispanService.deleteDevModeStatus(projectId);
                     infinispanService.deleteContainerStatus(projectId, environment, name);
                     infinispanService.deleteCamelStatuses(projectId, environment);
                 } else if (Arrays.asList("start", "unpause").contains(event.getStatus())) {
@@ -127,9 +128,7 @@ public class DockerEventListener implements ResultCallback<Event> {
         if (infinispanService.isReady()) {
             ContainerStatus ps = infinispanService.getDevModeContainerStatuses(projectId, environment);
             if (ps == null) {
-                ps = new ContainerStatus(name, true, projectId, environment, getCtype(container.getLabels()), Instant.ofEpochSecond(container.getCreated()).toString(), exposedPort);
-            } else {
-                ps.setExposedPort(exposedPort);
+                ps = new ContainerStatus(name, true, projectId, environment, getCtype(container.getLabels()), Instant.ofEpochSecond(container.getCreated()).toString());
             }
             infinispanService.saveContainerStatus(ps);
         }
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
index 40c1d714..f2a8bd8e 100644
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
+++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
@@ -36,6 +36,9 @@ public class DockerService {
 
     private static final Logger LOGGER = Logger.getLogger(DockerService.class.getName());
 
+    public static final String INFINISPAN_CONTAINER_NAME = "infinispan";
+    public static final String KARAVAN_CONTAINER_NAME = "karavan-headless";
+
     public static final String NETWORK_NAME = "karavan";
     public static final String LABEL_TYPE = "type";
     public static final String LABEL_PROJECT_ID = "projectId";
@@ -44,11 +47,16 @@ public class DockerService {
     private static final DecimalFormat formatGiB = new DecimalFormat("0.00");
     private static final Map<String, Tuple2<Long, Long>> previousStats = new ConcurrentHashMap<>();
 
-    @ConfigProperty(name = "runner.image")
-    String runnerImage;
+    @ConfigProperty(name = "karavan.devmode.image")
+    String devmodeImage;
+
+    @ConfigProperty(name = "karavan.headless.image")
+    String headlessImage;
 
     @ConfigProperty(name = "infinispan.image")
     String infinispanImage;
+    @ConfigProperty(name = "infinispan.hosts")
+    String infinispanHosts;
     @ConfigProperty(name = "infinispan.port")
     String infinispanPort;
     @ConfigProperty(name = "infinispan.username")
@@ -62,20 +70,18 @@ public class DockerService {
     @Inject
     EventBus eventBus;
 
-    public void createRunner(Project project, String runnerName, String jBangOptions) throws InterruptedException {
+    public void runDevmodeContainer(Project project, String runnerName, String jBangOptions) throws InterruptedException {
         String projectId = project.getProjectId();
         LOGGER.infof("DevMode starting for %s", projectId);
         HealthCheck healthCheck = new HealthCheck().withTest(List.of("CMD", "curl", "-f", "http://localhost:8080/q/dev/health"))
                 .withInterval(10000000000L).withTimeout(10000000000L).withStartPeriod(10000000000L).withRetries(30);
-        createContainer(runnerName, runnerImage,
-                List.of(), "8080:8080", true,true, healthCheck,
+        createContainer(runnerName, devmodeImage,
+                List.of(), null, false, false, healthCheck,
                 Map.of(LABEL_TYPE, ContainerStatus.CType.devmode.name(), LABEL_PROJECT_ID, projectId));
         startContainer(runnerName);
         LOGGER.infof("DevMode started for %s", projectId);
     }
 
-    public static final String INFINISPAN_CONTAINER_NAME = "infinispan";
-
     public void startInfinispan() {
         try {
             LOGGER.info("Infinispan is starting...");
@@ -94,6 +100,32 @@ public class DockerService {
         }
     }
 
+    public void startKaravanHeadlessContainer() {
+        try {
+            LOGGER.info("Karavan headless is starting...");
+
+            createContainer(KARAVAN_CONTAINER_NAME, headlessImage,
+                    List.of(
+                            "INFINISPAN_HOSTS=infinispan:11222",
+                            "INFINISPAN_USERNAME=" + infinispanUsername,
+                            "INFINISPAN_PASSWORD=" + infinispanPassword
+                    ),
+                    null, false, false, new HealthCheck(), Map.of());
+            startContainer(KARAVAN_CONTAINER_NAME);
+            LOGGER.info("Karavan headless is started");
+        } catch (Exception e) {
+            LOGGER.error(e.getMessage());
+        }
+    }
+
+    public void deleteKaravanHeadlessContainer() {
+        try {
+            deleteContainer(KARAVAN_CONTAINER_NAME);
+        } catch (Exception e) {
+            LOGGER.error(e.getMessage());
+        }
+    }
+
     public void collectContainersStats() {
         getDockerClient().listContainersCmd().exec().forEach(container -> {
             Statistics stats = getContainerStats(container.getId());
@@ -107,7 +139,7 @@ public class DockerService {
                     "memory", memoryUsage + " / " + memoryLimit,
                     "cpu", formatCpu(name, stats)
             );
-            eventBus.publish(CONTAINER_STATS, data);
+            eventBus.publish(CONTAINER_STATISTICS, data);
         });
     }
 
@@ -259,7 +291,12 @@ public class DockerService {
 
     public void pullImage(String image) throws InterruptedException {
         List<Image> images = getDockerClient().listImagesCmd().withShowAll(true).exec();
-        if (!images.stream().filter(i -> Arrays.asList(i.getRepoTags()).contains(image)).findFirst().isPresent()) {
+        List<String> tags = images.stream()
+                .map(i -> Arrays.stream(i.getRepoTags()).collect(Collectors.toList()))
+                .flatMap(Collection::stream)
+                .collect(Collectors.toList());
+
+        if (!images.stream().filter(i -> tags.contains(image)).findFirst().isPresent()) {
             ResultCallback.Adapter<PullResponseItem> pull = getDockerClient().pullImageCmd(image).start().awaitCompletion();
         }
     }
@@ -280,7 +317,7 @@ public class DockerService {
 
     private Map<Integer, Integer> getPortsFromString(String ports) {
         Map<Integer, Integer> p = new HashMap<>();
-        if (!ports.isEmpty()) {
+        if (ports != null && !ports.isEmpty()) {
             Arrays.stream(ports.split(",")).forEach(s -> {
                 String[] values = s.split(":");
                 p.put(Integer.parseInt(values[0]), Integer.parseInt(values[1]));
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/KubernetesService.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/KubernetesService.java
index dc6fb90f..f10a38b6 100644
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/KubernetesService.java
+++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/KubernetesService.java
@@ -385,7 +385,7 @@ public class KubernetesService implements HealthCheck {
         return result;
     }
 
-    public void createRunner(Project project, String runnerName, String jBangOptions) {
+    public void runDevModeContainer(Project project, String runnerName, String jBangOptions) {
         createPVC(runnerName);
         Pod old = kubernetesClient().pods().inNamespace(getNamespace()).withName(runnerName).get();
         if (old == null) {
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/PodEventHandler.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/PodEventHandler.java
index 47378b95..791d6bfc 100644
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/PodEventHandler.java
+++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/PodEventHandler.java
@@ -92,8 +92,7 @@ public class PodEventHandler implements ResourceEventHandler<Pod> {
                     project,
                     kubernetesService.environment,
                     ContainerStatus.CType.pod,
-                    "",
-                    null);
+                    "");
         }
     }
 }
\ No newline at end of file
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/CamelService.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/CamelService.java
index bb675585..38570b9c 100644
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/CamelService.java
+++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/CamelService.java
@@ -76,10 +76,8 @@ public class CamelService {
         LOGGER.info("Reload project code " + projectId);
         String containerName = projectId + DEVMODE_SUFFIX;
         try {
-            ContainerStatus containerStatus = infinispanService.getDevModeContainerStatuses(projectId, environment);
-            Integer exposedPort = containerStatus.getExposedPort();
-            infinispanService.getProjectFiles(projectId).forEach(projectFile -> putRequest(containerName,exposedPort, projectFile.getName(), projectFile.getCode(), 1000));
-            reloadRequest(containerName, exposedPort);
+            infinispanService.getProjectFiles(projectId).forEach(projectFile -> putRequest(containerName, projectFile.getName(), projectFile.getCode(), 1000));
+            reloadRequest(containerName);
             DevModeStatus dms = infinispanService.getDevModeStatus(projectId);
             dms.setCodeLoaded(true);
             infinispanService.saveDevModeStatus(dms);
@@ -89,9 +87,9 @@ public class CamelService {
     }
 
     @CircuitBreaker(requestVolumeThreshold = 10, failureRatio = 0.5, delay = 1000)
-    public boolean putRequest(String containerName, Integer exposedPort, String fileName, String body, int timeout) {
+    public boolean putRequest(String containerName, String fileName, String body, int timeout) {
         try {
-            String url = getContainerAddress(containerName, exposedPort) + "/q/upload/" + fileName;
+            String url = getContainerAddress(containerName) + "/q/upload/" + fileName;
             HttpResponse<Buffer> result = getWebClient().putAbs(url)
                     .timeout(timeout).sendBuffer(Buffer.buffer(body)).subscribeAsCompletionStage().toCompletableFuture().get();
             return result.statusCode() == 200;
@@ -101,8 +99,8 @@ public class CamelService {
         return false;
     }
 
-    public String reloadRequest(String containerName, Integer exposedPort) {
-        String url = getContainerAddress(containerName, exposedPort) + "/q/dev/reload?reload=true";
+    public String reloadRequest(String containerName) {
+        String url = getContainerAddress(containerName) + "/q/dev/reload?reload=true";
         try {
             return result(url, 1000);
         } catch (InterruptedException | ExecutionException e) {
@@ -111,18 +109,14 @@ public class CamelService {
         return null;
     }
 
-    public String getContainerAddress(String containerName, Integer exposedPort) {
-        if (ConfigService.inKubernetes()) {
-            return "http://" + containerName + "." + kubernetesService.getNamespace() + ".svc.cluster.local";
-        } else {
-            return "http://localhost:" + exposedPort;
-        }
+    public String getContainerAddress(String containerName) {
+        return "http://" + containerName + "." + kubernetesService.getNamespace() + ".svc.cluster.local";
     }
 
     public void collectCamelStatuses() {
         if (infinispanService.isReady()) {
             infinispanService.getContainerStatuses(environment).forEach(pod -> {
-                CamelStatusRequest csr = new CamelStatusRequest(pod.getProjectId(), pod.getName(), pod.getExposedPort());
+                CamelStatusRequest csr = new CamelStatusRequest(pod.getProjectId(), pod.getName());
                 eventBus.publish(CMD_COLLECT_CAMEL_STATUS, JsonObject.mapFrom(csr));
             });
         }
@@ -133,8 +127,7 @@ public class CamelService {
         CamelStatusRequest dms = data.mapTo(CamelStatusRequest.class);
         Arrays.stream(CamelStatus.Name.values()).forEach(statusName -> {
             String containerName = dms.getContainerName();
-            Integer exposedPort = dms.getExposedPort();
-            String status = getCamelStatus(containerName, exposedPort, statusName);
+            String status = getCamelStatus(containerName, statusName);
             if (status != null) {
                 CamelStatus cs = new CamelStatus(dms.getProjectId(), containerName, statusName, status, environment);
                 infinispanService.saveCamelStatus(cs);
@@ -179,8 +172,8 @@ public class CamelService {
         }
     }
 
-    public String getCamelStatus(String podName, Integer exposedPort, CamelStatus.Name statusName) {
-        String url = getContainerAddress(podName, exposedPort) + "/q/dev/" + statusName.name();
+    public String getCamelStatus(String podName, CamelStatus.Name statusName) {
+        String url = getContainerAddress(podName) + "/q/dev/" + statusName.name();
         try {
             return result(url, 500);
         } catch (InterruptedException | ExecutionException e) {
@@ -207,15 +200,13 @@ public class CamelService {
     public static class CamelStatusRequest {
         private String projectId;
         private String containerName;
-        private Integer exposedPort;
 
         public CamelStatusRequest() {
         }
 
-        public CamelStatusRequest(String projectId, String containerName, Integer exposedPort) {
+        public CamelStatusRequest(String projectId, String containerName) {
             this.projectId = projectId;
             this.containerName = containerName;
-            this.exposedPort = exposedPort;
         }
 
         public String getProjectId() {
@@ -234,12 +225,5 @@ public class CamelService {
             this.containerName = containerName;
         }
 
-        public Integer getExposedPort() {
-            return exposedPort;
-        }
-
-        public void setExposedPort(Integer exposedPort) {
-            this.exposedPort = exposedPort;
-        }
     }
 }
\ No newline at end of file
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/EventService.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/EventService.java
index 0d0a9759..cc4277a8 100644
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/EventService.java
+++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/EventService.java
@@ -48,11 +48,16 @@ public class EventService {
     @ConsumeEvent(value = START_KARAVAN, blocking = true, ordered = true)
     void startKaravan(String data) {
         if (!ConfigService.inKubernetes()) {
-            LOGGER.info("Starting Karavan with Docker");
-            dockerService.createNetwork();
-            dockerService.startListeners();
-            dockerService.startInfinispan();
-            dockerService.checkInfinispanHealth();
+            if (ConfigService.isHeadless()) {
+                LOGGER.info("Starting Karavan Headless in Docker");
+            } else {
+                LOGGER.info("Starting Karavan with Docker");
+                dockerService.createNetwork();
+                dockerService.startListeners();
+                dockerService.startInfinispan();
+                dockerService.checkInfinispanHealth();
+                dockerService.collectContainersStatuses();
+            }
         } else {
             LOGGER.info("Starting Karavan in " + (kubernetesService.isOpenshift() ? "OpenShift" : "Kubernetes"));
             startServices(HEALTHY);
@@ -60,9 +65,13 @@ public class EventService {
     }
 
     @ConsumeEvent(value = INFINISPAN_STARTED, blocking = true, ordered = true)
-    void startServices(String infinispanHealth){
+    void startServices(String infinispanHealth) {
         if (infinispanHealth.equals(HEALTHY)) {
-            infinispanService.start();
+            if (!ConfigService.inKubernetes()) {
+                dockerService.deleteKaravanHeadlessContainer();
+                dockerService.startKaravanHeadlessContainer();
+            }
+            infinispanService.start(false);
             infinispanService.clearAllStatuses();
             bus.publish(EventType.IMPORT_PROJECTS, "");
             bus.publish(EventType.START_INFRASTRUCTURE_LISTENERS, "");
@@ -103,7 +112,7 @@ public class EventService {
         }
     }
 
-    @ConsumeEvent(value = CONTAINER_STATS, blocking = true, ordered = true)
+    @ConsumeEvent(value = CONTAINER_STATISTICS, blocking = true, ordered = true)
     public void saveStats(JsonObject data) {
         String projectId = data.getString("projectId");
         String memory = data.getString("memory");
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ScheduledService.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ScheduledService.java
index 953b660d..ae586bbb 100644
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ScheduledService.java
+++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ScheduledService.java
@@ -18,6 +18,7 @@ package org.apache.camel.karavan.service;
 
 import io.quarkus.scheduler.Scheduled;
 import org.apache.camel.karavan.docker.DockerService;
+import org.jboss.logging.Logger;
 
 import javax.enterprise.context.ApplicationScoped;
 import javax.inject.Inject;
@@ -25,6 +26,8 @@ import javax.inject.Inject;
 @ApplicationScoped
 public class ScheduledService {
 
+    private static final Logger LOGGER = Logger.getLogger(ScheduledService.class.getName());
+
     @Inject
     DockerService dockerService;
 
@@ -34,23 +37,17 @@ public class ScheduledService {
     @Inject
     CamelService camelService;
 
-    @Scheduled(every = "{karavan.container.status.pull-interval}", concurrentExecution = Scheduled.ConcurrentExecution.SKIP)
-    void collectContainersStatuses() {
-        dockerService.collectContainersStatuses();
-    }
-
-    @Scheduled(every = "{karavan.container.stats.container}", concurrentExecution = Scheduled.ConcurrentExecution.SKIP)
+    @Scheduled(every = "{karavan.container.statistics.container}", concurrentExecution = Scheduled.ConcurrentExecution.SKIP)
     void collectContainersStats() {
         dockerService.collectContainersStats();
     }
 
     @Scheduled(every = "{karavan.camel.status.pull-interval}", concurrentExecution = Scheduled.ConcurrentExecution.SKIP)
     void collectCamelStatuses() {
+        LOGGER.info("Collect info statuses");
+        // collect Camel statuses
         camelService.collectCamelStatuses();
-    }
-
-    @Scheduled(every = "{karavan.camel.status.pull-interval}", concurrentExecution = Scheduled.ConcurrentExecution.SKIP)
-    void cleanupDevModeStatuses() {
+        // clean DevMode statuses if container deleted
         camelService.cleanupDevModeStatuses();
     }
 
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/shared/ConfigService.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/shared/ConfigService.java
index c8efcdb8..233c035d 100644
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/shared/ConfigService.java
+++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/shared/ConfigService.java
@@ -17,6 +17,8 @@
 package org.apache.camel.karavan.shared;
 
 import io.quarkus.runtime.StartupEvent;
+import io.quarkus.runtime.configuration.ConfigUtils;
+import io.quarkus.runtime.configuration.ProfileManager;
 import org.eclipse.microprofile.config.inject.ConfigProperty;
 
 import javax.enterprise.context.ApplicationScoped;
@@ -28,6 +30,7 @@ import java.util.Objects;
 public class ConfigService {
 
     public static final String DEVMODE_SUFFIX = "-devmode";
+    public static final String HEADLESS_MODE = "headless";
 
     @ConfigProperty(name = "karavan.version")
     String version;
@@ -64,4 +67,8 @@ public class ConfigService {
     public static boolean inKubernetes() {
         return Objects.nonNull(System.getenv("KUBERNETES_SERVICE_HOST"));
     }
+
+    public static boolean isHeadless() {
+        return ConfigUtils.isProfileActive(HEADLESS_MODE);
+    }
 }
\ No newline at end of file
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/shared/EventType.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/shared/EventType.java
index f2036913..08bc7fdb 100644
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/shared/EventType.java
+++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/shared/EventType.java
@@ -13,7 +13,7 @@ public class EventType {
 
     public static final String INFINISPAN_STARTED = "INFINISPAN_STARTED";
 
-    public static final String CONTAINER_STATS = "CONTAINER_STATS";
+    public static final String CONTAINER_STATISTICS = "CONTAINER_STATISTICS";
     public static final String DEVMODE_STATUS = "DEVMODE_STATUS";
 
 }
diff --git a/karavan-web/karavan-app/src/main/resources/application.properties b/karavan-web/karavan-app/src/main/resources/application.properties
index 0cb2e699..b0bfda46 100644
--- a/karavan-web/karavan-app/src/main/resources/application.properties
+++ b/karavan-web/karavan-app/src/main/resources/application.properties
@@ -3,11 +3,10 @@ karavan.environment=dev
 karavan.environments=dev,test,prod
 karavan.default-runtime=quarkus
 karavan.runtimes=quarkus,spring-boot
-karavan.camel.status.pull-interval=3s
-karavan.container.status.pull-interval=5s
-karavan.container.stats.container=5s
-quarkus.scheduler.enabled=true
-runner.image=ghcr.io/apache/camel-karavan-runner:3.21.1-snapshot
+karavan.camel.status.pull-interval=off
+karavan.container.statistics.container=3s
+karavan.devmode.image=ghcr.io/apache/camel-karavan-runner:3.21.1-snapshot
+karavan.headless.image=marat/karavan-headless:3.21.1-SNAPSHOT
 
 # Git repository Configuration
 karavan.git.repository=${GIT_REPOSITORY}
@@ -24,9 +23,6 @@ infinispan.password=karavan
 infinispan.hosts=localhost:11222
 
 quarkus.infinispan-client.devservices.enabled=false
-
-# Infinispan client intelligence
-# Use BASIC as a Docker for Mac workaround
 quarkus.infinispan-client.client-intelligence=BASIC
 
 # Public Dev
@@ -92,7 +88,6 @@ quarkus.log.level=INFO
 quarkus.banner.enabled=false
 quarkus.package.type=uber-jar
 quarkus.docker.dockerfile-jvm-path=src/main/docker/Dockerfile.distroless
-#quarkus.docker.dockerfile-jvm-path=src/main/docker/Dockerfile.legacy-jar
 quarkus.container-image.builder=docker
 
 quarkus.qute.strict-rendering=false
@@ -105,7 +100,7 @@ quarkus.kubernetes-client.connection-timeout=2000
 quarkus.kubernetes-client.request-timeout=10000
 quarkus.kubernetes-client.devservices.enabled=false
 
-quarkus.swagger-ui.always-include=true
+%dev.quarkus.swagger-ui.always-include=true
 
 quarkus.quinoa.frozen-lockfile=false
 quarkus.quinoa.package-manager-install=false
diff --git a/karavan-web/pom.xml b/karavan-web/pom.xml
index a16e9e97..54d6d283 100644
--- a/karavan-web/pom.xml
+++ b/karavan-web/pom.xml
@@ -5,7 +5,7 @@
     <modelVersion>4.0.0</modelVersion>
 
     <groupId>org.apache.camel.karavan</groupId>
-    <artifactId>karavan-cloud</artifactId>
+    <artifactId>karavan-web</artifactId>
     <version>3.21.1-SNAPSHOT</version>
     <packaging>pom</packaging>
 
@@ -43,12 +43,6 @@
         <quarkus.version>2.16.7.Final</quarkus.version>
     </properties>
 
-    <modules>
-        <module>karavan-cli</module>
-        <module>karavan-app</module>
-        <module>karavan-operator</module>
-    </modules>
-
     <dependencyManagement>
         <dependencies>
             <dependency>


[camel-karavan] 01/05: karavan-infinispan #817

Posted by ma...@apache.org.
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

commit 365e9d6ae6b22b33d852f0def0a432cc7270fe90
Author: Marat Gubaidullin <ma...@gmail.com>
AuthorDate: Fri Jul 21 20:59:01 2023 -0400

    karavan-infinispan #817
---
 .../.mvn/wrapper/maven-wrapper.properties          |  18 +
 karavan-web/karavan-infinispan/mvnw                | 308 +++++++++++++++
 karavan-web/karavan-infinispan/mvnw.cmd            | 205 ++++++++++
 karavan-web/karavan-infinispan/pom.xml             | 132 +++++++
 .../karavan/infinispan/CodeReloadListener.java     |  30 ++
 .../karavan/infinispan/InfinispanService.java      | 414 +++++++++++++++++++++
 .../karavan/infinispan/model/CamelStatus.java      |  81 ++++
 .../camel/karavan/infinispan/model/CommitInfo.java |  53 +++
 .../karavan/infinispan/model/ContainerInfo.java    |  70 ++++
 .../karavan/infinispan/model/ContainerStatus.java  | 141 +++++++
 .../karavan/infinispan/model/DeploymentStatus.java | 111 ++++++
 .../karavan/infinispan/model/DevModeStatus.java    |  78 ++++
 .../camel/karavan/infinispan/model/GitConfig.java  |  48 +++
 .../camel/karavan/infinispan/model/GitRepo.java    |  49 +++
 .../karavan/infinispan/model/GitRepoFile.java      |  37 ++
 .../camel/karavan/infinispan/model/GroupedKey.java |  81 ++++
 .../karavan/infinispan/model/KaravanSchema.java    |  28 ++
 .../karavan/infinispan/model/PipelineStatus.java   |  83 +++++
 .../camel/karavan/infinispan/model/Project.java    | 125 +++++++
 .../karavan/infinispan/model/ProjectFile.java      |  71 ++++
 .../karavan/infinispan/model/ServiceStatus.java    | 107 ++++++
 .../src/main/resources/application.properties      |  14 +
 .../main/resources/cache/command-cache-config.xml  |   6 +
 .../src/main/resources/cache/data-cache-config.xml |   6 +
 .../camel/karavan/infinispan/DataGridTest.java     |  74 ++++
 25 files changed, 2370 insertions(+)

diff --git a/karavan-web/karavan-infinispan/.mvn/wrapper/maven-wrapper.properties b/karavan-web/karavan-infinispan/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 00000000..70f4f50f
--- /dev/null
+++ b/karavan-web/karavan-infinispan/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,18 @@
+# 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.
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.8/apache-maven-3.8.8-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
diff --git a/karavan-web/karavan-infinispan/mvnw b/karavan-web/karavan-infinispan/mvnw
new file mode 100755
index 00000000..8d937f4c
--- /dev/null
+++ b/karavan-web/karavan-infinispan/mvnw
@@ -0,0 +1,308 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# 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.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.2.0
+#
+# Required ENV vars:
+# ------------------
+#   JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+#   MAVEN_OPTS - parameters passed to the Java VM when running Maven
+#     e.g. to debug Maven itself, use
+#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+  if [ -f /usr/local/etc/mavenrc ] ; then
+    . /usr/local/etc/mavenrc
+  fi
+
+  if [ -f /etc/mavenrc ] ; then
+    . /etc/mavenrc
+  fi
+
+  if [ -f "$HOME/.mavenrc" ] ; then
+    . "$HOME/.mavenrc"
+  fi
+
+fi
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "$(uname)" in
+  CYGWIN*) cygwin=true ;;
+  MINGW*) mingw=true;;
+  Darwin*) darwin=true
+    # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+    # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+    if [ -z "$JAVA_HOME" ]; then
+      if [ -x "/usr/libexec/java_home" ]; then
+        JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
+      else
+        JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
+      fi
+    fi
+    ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+  if [ -r /etc/gentoo-release ] ; then
+    JAVA_HOME=$(java-config --jre-home)
+  fi
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+  [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
+    JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+  javaExecutable="$(which javac)"
+  if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
+    # readlink(1) is not available as standard on Solaris 10.
+    readLink=$(which readlink)
+    if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
+      if $darwin ; then
+        javaHome="$(dirname "\"$javaExecutable\"")"
+        javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
+      else
+        javaExecutable="$(readlink -f "\"$javaExecutable\"")"
+      fi
+      javaHome="$(dirname "\"$javaExecutable\"")"
+      javaHome=$(expr "$javaHome" : '\(.*\)/bin')
+      JAVA_HOME="$javaHome"
+      export JAVA_HOME
+    fi
+  fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+  if [ -n "$JAVA_HOME"  ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+      # IBM's JDK on AIX uses strange locations for the executables
+      JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+      JAVACMD="$JAVA_HOME/bin/java"
+    fi
+  else
+    JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
+  fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+  echo "Error: JAVA_HOME is not defined correctly." >&2
+  echo "  We cannot execute $JAVACMD" >&2
+  exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+  echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+  if [ -z "$1" ]
+  then
+    echo "Path not specified to find_maven_basedir"
+    return 1
+  fi
+
+  basedir="$1"
+  wdir="$1"
+  while [ "$wdir" != '/' ] ; do
+    if [ -d "$wdir"/.mvn ] ; then
+      basedir=$wdir
+      break
+    fi
+    # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+    if [ -d "${wdir}" ]; then
+      wdir=$(cd "$wdir/.." || exit 1; pwd)
+    fi
+    # end of workaround
+  done
+  printf '%s' "$(cd "$basedir" || exit 1; pwd)"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+  if [ -f "$1" ]; then
+    # Remove \r in case we run on Windows within Git Bash
+    # and check out the repository with auto CRLF management
+    # enabled. Otherwise, we may read lines that are delimited with
+    # \r\n and produce $'-Xarg\r' rather than -Xarg due to word
+    # splitting rules.
+    tr -s '\r\n' ' ' < "$1"
+  fi
+}
+
+log() {
+  if [ "$MVNW_VERBOSE" = true ]; then
+    printf '%s\n' "$1"
+  fi
+}
+
+BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
+if [ -z "$BASE_DIR" ]; then
+  exit 1;
+fi
+
+MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
+log "$MAVEN_PROJECTBASEDIR"
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
+if [ -r "$wrapperJarPath" ]; then
+    log "Found $wrapperJarPath"
+else
+    log "Couldn't find $wrapperJarPath, downloading it ..."
+
+    if [ -n "$MVNW_REPOURL" ]; then
+      wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+    else
+      wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+    fi
+    while IFS="=" read -r key value; do
+      # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
+      safeValue=$(echo "$value" | tr -d '\r')
+      case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
+      esac
+    done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+    log "Downloading from: $wrapperUrl"
+
+    if $cygwin; then
+      wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
+    fi
+
+    if command -v wget > /dev/null; then
+        log "Found wget ... using wget"
+        [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
+        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+            wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+        else
+            wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+        fi
+    elif command -v curl > /dev/null; then
+        log "Found curl ... using curl"
+        [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
+        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+            curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+        else
+            curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+        fi
+    else
+        log "Falling back to using Java to download"
+        javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
+        javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
+        # For Cygwin, switch paths to Windows format before running javac
+        if $cygwin; then
+          javaSource=$(cygpath --path --windows "$javaSource")
+          javaClass=$(cygpath --path --windows "$javaClass")
+        fi
+        if [ -e "$javaSource" ]; then
+            if [ ! -e "$javaClass" ]; then
+                log " - Compiling MavenWrapperDownloader.java ..."
+                ("$JAVA_HOME/bin/javac" "$javaSource")
+            fi
+            if [ -e "$javaClass" ]; then
+                log " - Running MavenWrapperDownloader.java ..."
+                ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
+            fi
+        fi
+    fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+# If specified, validate the SHA-256 sum of the Maven wrapper jar file
+wrapperSha256Sum=""
+while IFS="=" read -r key value; do
+  case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
+  esac
+done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+if [ -n "$wrapperSha256Sum" ]; then
+  wrapperSha256Result=false
+  if command -v sha256sum > /dev/null; then
+    if echo "$wrapperSha256Sum  $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
+      wrapperSha256Result=true
+    fi
+  elif command -v shasum > /dev/null; then
+    if echo "$wrapperSha256Sum  $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
+      wrapperSha256Result=true
+    fi
+  else
+    echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
+    echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
+    exit 1
+  fi
+  if [ $wrapperSha256Result = false ]; then
+    echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
+    echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
+    echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
+    exit 1
+  fi
+fi
+
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
+  [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+    MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+# shellcheck disable=SC2086 # safe args
+exec "$JAVACMD" \
+  $MAVEN_OPTS \
+  $MAVEN_DEBUG_OPTS \
+  -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+  "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/karavan-web/karavan-infinispan/mvnw.cmd b/karavan-web/karavan-infinispan/mvnw.cmd
new file mode 100644
index 00000000..f80fbad3
--- /dev/null
+++ b/karavan-web/karavan-infinispan/mvnw.cmd
@@ -0,0 +1,205 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements.  See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership.  The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License.  You may obtain a copy of the License at
+@REM
+@REM    http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied.  See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Apache Maven Wrapper startup batch script, version 3.2.0
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM     e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on"  echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+    IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Found %WRAPPER_JAR%
+    )
+) else (
+    if not "%MVNW_REPOURL%" == "" (
+        SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+    )
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Couldn't find %WRAPPER_JAR%, downloading it ...
+        echo Downloading from: %WRAPPER_URL%
+    )
+
+    powershell -Command "&{"^
+		"$webclient = new-object System.Net.WebClient;"^
+		"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+		"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+		"}"^
+		"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
+		"}"
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Finished downloading %WRAPPER_JAR%
+    )
+)
+@REM End of extension
+
+@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
+SET WRAPPER_SHA_256_SUM=""
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+    IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
+)
+IF NOT %WRAPPER_SHA_256_SUM%=="" (
+    powershell -Command "&{"^
+       "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
+       "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
+       "  Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
+       "  Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
+       "  Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
+       "  exit 1;"^
+       "}"^
+       "}"
+    if ERRORLEVEL 1 goto error
+)
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+  %JVM_CONFIG_MAVEN_PROPS% ^
+  %MAVEN_OPTS% ^
+  %MAVEN_DEBUG_OPTS% ^
+  -classpath %WRAPPER_JAR% ^
+  "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+  %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/karavan-web/karavan-infinispan/pom.xml b/karavan-web/karavan-infinispan/pom.xml
new file mode 100644
index 00000000..3668bac4
--- /dev/null
+++ b/karavan-web/karavan-infinispan/pom.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>karavan-infinispan</artifactId>
+    <packaging>jar</packaging>
+    <parent>
+        <groupId>org.apache.camel.karavan</groupId>
+        <artifactId>karavan-web</artifactId>
+        <version>3.21.1-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <dependencies>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-vertx</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-jackson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-infinispan-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-junit5</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.rest-assured</groupId>
+            <artifactId>rest-assured</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>application.properties</include>
+                    <include>**/**.xml</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>target/classes/proto</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>karavan.proto</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>io.smallrye</groupId>
+                <artifactId>jandex-maven-plugin</artifactId>
+                <version>${jandex-maven-plugin-version}</version>
+                <executions>
+                    <execution>
+                        <id>make-index</id>
+                        <goals>
+                            <goal>jandex</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>${quarkus.platform.group-id}</groupId>
+                <artifactId>quarkus-maven-plugin</artifactId>
+                <version>${quarkus.platform.version}</version>
+                <extensions>true</extensions>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>build</goal>
+                            <goal>generate-code</goal>
+                            <goal>generate-code-tests</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>${compiler-plugin.version}</version>
+                <configuration>
+                    <parameters>${maven.compiler.parameters}</parameters>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>${surefire-plugin.version}</version>
+                <configuration>
+                    <systemPropertyVariables>
+                        <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
+                        <maven.home>${maven.home}</maven.home>
+                    </systemPropertyVariables>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <repositories>
+        <repository>
+            <id>apache.snapshots</id>
+            <name>Apache Development Snapshot Repository</name>
+            <url>https://repository.apache.org/content/repositories/snapshots/</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+</project>
diff --git a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/CodeReloadListener.java b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/CodeReloadListener.java
new file mode 100644
index 00000000..8c369157
--- /dev/null
+++ b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/CodeReloadListener.java
@@ -0,0 +1,30 @@
+package org.apache.camel.karavan.infinispan;
+
+import io.vertx.core.eventbus.EventBus;
+import io.vertx.core.json.JsonObject;
+import org.apache.camel.karavan.infinispan.model.GroupedKey;
+import org.infinispan.client.hotrod.annotation.ClientCacheEntryCreated;
+import org.infinispan.client.hotrod.annotation.ClientCacheEntryModified;
+import org.infinispan.client.hotrod.annotation.ClientListener;
+import org.infinispan.client.hotrod.event.ClientCacheEntryCreatedEvent;
+import org.infinispan.client.hotrod.event.ClientCacheEntryModifiedEvent;
+
+@ClientListener
+public class CodeReloadListener {
+    private final EventBus eventBus;
+
+    public CodeReloadListener(EventBus eventBus) {
+        this.eventBus = eventBus;
+    }
+
+    @ClientCacheEntryCreated
+    public void entryCreated(ClientCacheEntryCreatedEvent<GroupedKey> event) {
+        eventBus.publish(InfinispanService.CODE_RELOAD_COMMAND_INTERNAL, JsonObject.mapFrom(event.getKey()));
+    }
+
+    @ClientCacheEntryModified
+    public void entryModified(ClientCacheEntryModifiedEvent<GroupedKey> event) {
+        eventBus.publish(InfinispanService.CODE_RELOAD_COMMAND_INTERNAL, JsonObject.mapFrom(event.getKey()));
+    }
+
+}
\ No newline at end of file
diff --git a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/InfinispanService.java b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/InfinispanService.java
new file mode 100644
index 00000000..36a9db6e
--- /dev/null
+++ b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/InfinispanService.java
@@ -0,0 +1,414 @@
+/*
+ * 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.karavan.infinispan;
+
+import io.quarkus.vertx.ConsumeEvent;
+import io.smallrye.mutiny.tuples.Tuple2;
+import io.vertx.core.eventbus.EventBus;
+import io.vertx.core.json.JsonObject;
+import org.apache.camel.karavan.infinispan.model.*;
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+import org.infinispan.client.hotrod.RemoteCache;
+import org.infinispan.client.hotrod.RemoteCacheManager;
+import org.infinispan.client.hotrod.Search;
+import org.infinispan.client.hotrod.configuration.ClientIntelligence;
+import org.infinispan.client.hotrod.configuration.ConfigurationBuilder;
+import org.infinispan.commons.configuration.StringConfiguration;
+import org.infinispan.commons.marshall.ProtoStreamMarshaller;
+import org.infinispan.query.dsl.QueryFactory;
+import org.jboss.logging.Logger;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.Default;
+import javax.inject.Inject;
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.time.Instant;
+import java.util.*;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
+
+import static org.infinispan.query.remote.client.ProtobufMetadataManagerConstants.PROTOBUF_METADATA_CACHE_NAME;
+
+@Default
+@ApplicationScoped
+public class InfinispanService {
+
+    @ConfigProperty(name ="infinispan.hosts")
+    String infinispanHosts;
+    @ConfigProperty(name ="infinispan.username")
+    String infinispanUsername;
+    @ConfigProperty(name ="infinispan.password")
+    String infinispanPassword;
+
+    @Inject
+    EventBus eventBus;
+
+    private RemoteCache<GroupedKey, Project> projects;
+    private RemoteCache<GroupedKey, ProjectFile> files;
+    private RemoteCache<GroupedKey, PipelineStatus> pipelineStatuses;
+    private RemoteCache<GroupedKey, DeploymentStatus> deploymentStatuses;
+    private RemoteCache<GroupedKey, ContainerStatus> containerStatuses;
+    private RemoteCache<GroupedKey, ServiceStatus> serviceStatuses;
+    private RemoteCache<GroupedKey, CamelStatus> camelStatuses;
+    private RemoteCache<String, String> commits;
+    private RemoteCache<GroupedKey, DevModeStatus> devmodeStatuses;
+    private RemoteCache<GroupedKey, String> codeReloadCommands;
+    private RemoteCache<GroupedKey, ContainerInfo> containers;
+    private final AtomicBoolean ready = new AtomicBoolean(false);
+
+    private RemoteCacheManager cacheManager;
+
+    private static final Logger LOGGER = Logger.getLogger(InfinispanService.class.getName());
+
+    private static final String DEFAULT_ENVIRONMENT = "dev";
+
+    public static final String CODE_RELOAD_COMMAND = "CODE_RELOAD_COMMAND";
+    public static final String CODE_RELOAD_COMMAND_INTERNAL = "CODE_RELOAD_COMMAND_INTERNAL";
+
+    public void start(boolean startCodeReloadListeners) {
+        LOGGER.info("InfinispanService is starting in remote mode");
+
+        ProtoStreamMarshaller marshaller = new ProtoStreamMarshaller();
+        marshaller.register(new KaravanSchemaImpl());
+
+        ConfigurationBuilder builder = new ConfigurationBuilder();
+        builder.socketTimeout(1000)
+                .connectionTimeout(10000)
+                .addServers(infinispanHosts)
+                .security()
+                .authentication().enable()
+                .username(infinispanUsername)
+                .password(infinispanPassword)
+                .clientIntelligence(ClientIntelligence.BASIC)
+                .marshaller(marshaller);
+
+        cacheManager = new RemoteCacheManager(builder.build());
+
+        projects = getOrCreateCache(Project.CACHE, false);
+        files = getOrCreateCache(ProjectFile.CACHE, false);
+        containerStatuses = getOrCreateCache(ContainerStatus.CACHE, false);
+        pipelineStatuses = getOrCreateCache(PipelineStatus.CACHE, false);
+        deploymentStatuses = getOrCreateCache(DeploymentStatus.CACHE, false);
+        serviceStatuses = getOrCreateCache(ServiceStatus.CACHE, false);
+        camelStatuses = getOrCreateCache(CamelStatus.CACHE, false);
+        commits = getOrCreateCache("commits", false);
+        deploymentStatuses = getOrCreateCache(DeploymentStatus.CACHE, false);
+        devmodeStatuses = getOrCreateCache(DevModeStatus.CACHE, false);
+        containers = getOrCreateCache(ContainerInfo.CACHE, false);
+        codeReloadCommands = getOrCreateCache("code_reload_commands", true);
+
+        cacheManager.getCache(PROTOBUF_METADATA_CACHE_NAME).put("karavan.proto", getResourceFile("/proto/karavan.proto"));
+
+        if (startCodeReloadListeners) {
+            cacheManager.getCache("code_reload_commands").addClientListener(new CodeReloadListener(eventBus));
+        }
+
+        ready.set(true);
+        LOGGER.info("InfinispanService is started in remote mode");
+    }
+
+    private <K, V> RemoteCache<K, V>  getOrCreateCache(String name, boolean command) {
+        String config = getResourceFile(command ? "/cache/command-cache-config.xml" : "/cache/data-cache-config.xml");
+        return cacheManager.administration().getOrCreateCache(name, new StringConfiguration(String.format(config, name)));
+    }
+
+    public boolean isReady() {
+        return ready.get();
+    }
+
+
+    @ConsumeEvent(value = CODE_RELOAD_COMMAND_INTERNAL, blocking = true)
+    void resendCodeReloadCommand(JsonObject message) {
+        GroupedKey key = message.mapTo(GroupedKey.class);
+        deleteCodeReloadCommand(key);
+        eventBus.publish(CODE_RELOAD_COMMAND, key.getProjectId());
+    }
+
+    public void sendCodeReloadCommand(String projectId) {
+        codeReloadCommands.put(GroupedKey.create(projectId, DEFAULT_ENVIRONMENT, UUID.randomUUID().toString()), projectId);
+    }
+
+    public void deleteCodeReloadCommand(GroupedKey key) {
+        codeReloadCommands.remove(key);
+    }
+
+    public List<Project> getProjects() {
+        return projects.values().stream().collect(Collectors.toList());
+    }
+
+    public void saveProject(Project project) {
+        GroupedKey key = GroupedKey.create(project.getProjectId(), DEFAULT_ENVIRONMENT, project.getProjectId());
+        projects.put(key, project);
+        projects.put(key, project);
+    }
+
+    public List<ProjectFile> getProjectFiles(String projectId) {
+        QueryFactory queryFactory = Search.getQueryFactory(files);
+        return queryFactory.<ProjectFile>create("FROM karavan.ProjectFile WHERE projectId = :projectId")
+                .setParameter("projectId", projectId)
+                .execute().list();
+    }
+
+    public Map<GroupedKey, ProjectFile> getProjectFilesMap(String projectId) {
+        QueryFactory queryFactory = Search.getQueryFactory(files);
+        return queryFactory.<ProjectFile>create("FROM karavan.ProjectFile WHERE projectId = :projectId")
+                .setParameter("projectId", projectId)
+                .execute().list().stream()
+                .collect(Collectors.toMap(f -> new GroupedKey(f.getProjectId(), DEFAULT_ENVIRONMENT, f.getName()), f -> f));
+    }
+
+    public ProjectFile getProjectFile(String projectId, String filename) {
+        QueryFactory queryFactory = Search.getQueryFactory(files);
+        List<ProjectFile> list = queryFactory.<ProjectFile>create("FROM karavan.ProjectFile WHERE projectId = :projectId AND name = :name")
+                .setParameter("projectId", projectId)
+                .setParameter("name", filename)
+                .execute().list();
+        return list.size() > 0 ? list.get(0) : null;
+    }
+
+    public void saveProjectFile(ProjectFile file) {
+        files.put(GroupedKey.create(file.getProjectId(), DEFAULT_ENVIRONMENT, file.getName()), file);
+    }
+
+    public void saveProjectFiles(Map<GroupedKey, ProjectFile> f) {
+        Map<GroupedKey, ProjectFile> files = new HashMap<>(f.size());
+        f.forEach((groupedKey, projectFile) -> {
+            projectFile.setLastUpdate(Instant.now().toEpochMilli());
+        });
+        files.putAll(files);
+    }
+
+    public void deleteProject(String projectId) {
+        projects.remove(GroupedKey.create(projectId, DEFAULT_ENVIRONMENT,projectId));
+    }
+
+    public void deleteProjectFile(String projectId, String filename) {
+        files.remove(GroupedKey.create(projectId, DEFAULT_ENVIRONMENT,filename));
+    }
+
+    public Project getProject(String projectId) {
+        return projects.get(GroupedKey.create(projectId, DEFAULT_ENVIRONMENT,projectId));
+    }
+
+    public PipelineStatus getPipelineStatus(String projectId, String environment) {
+        return pipelineStatuses.get(GroupedKey.create(projectId, environment, projectId));
+    }
+
+    public void savePipelineStatus(PipelineStatus status) {
+        pipelineStatuses.put(GroupedKey.create(status.getProjectId(), status.getEnv(), status.getProjectId()), status);
+    }
+
+    public void deletePipelineStatus(PipelineStatus status) {
+        pipelineStatuses.remove(GroupedKey.create(status.getProjectId(), status.getEnv(), status.getProjectId()));
+    }
+
+    public DeploymentStatus getDeploymentStatus(String projectId, String environment) {
+        return deploymentStatuses.get(GroupedKey.create(projectId, environment, projectId));
+    }
+
+    public void saveDeploymentStatus(DeploymentStatus status) {
+        deploymentStatuses.put(GroupedKey.create(status.getProjectId(), status.getEnv(), status.getProjectId()), status);
+    }
+
+    public void deleteDeploymentStatus(DeploymentStatus status) {
+        deploymentStatuses.remove(GroupedKey.create(status.getProjectId(), status.getEnv(), status.getProjectId()));
+    }
+
+    public List<DeploymentStatus> getDeploymentStatuses() {
+        return new ArrayList<>(deploymentStatuses.values());
+    }
+
+    public List<DeploymentStatus> getDeploymentStatuses(String env) {
+        QueryFactory queryFactory = Search.getQueryFactory((RemoteCache<?, ?>) deploymentStatuses);
+        return queryFactory.<DeploymentStatus>create("FROM karavan.DeploymentStatus WHERE env = :env")
+                .setParameter("env", env)
+                .execute().list();
+    }
+
+    public void saveServiceStatus(ServiceStatus status) {
+        serviceStatuses.put(GroupedKey.create(status.getProjectId(), status.getEnv(), status.getProjectId()), status);
+    }
+
+    public void deleteServiceStatus(ServiceStatus status) {
+        serviceStatuses.remove(GroupedKey.create(status.getProjectId(), status.getEnv(), status.getProjectId()));
+    }
+
+    public List<ServiceStatus> getServiceStatuses() {
+        return new ArrayList<>(serviceStatuses.values());
+    }
+
+    public List<ContainerStatus> getContainerStatuses(String projectId, String env) {
+        QueryFactory queryFactory = Search.getQueryFactory(containerStatuses);
+        return queryFactory.<ContainerStatus>create("FROM karavan.ContainerStatus WHERE projectId = :projectId AND env = :env")
+                .setParameter("projectId", projectId)
+                .setParameter("env", env)
+                .execute().list();
+    }
+
+    public ContainerStatus getDevModeContainerStatuses(String projectId, String env) {
+        QueryFactory queryFactory = Search.getQueryFactory(containerStatuses);
+        List<ContainerStatus> list = queryFactory.<ContainerStatus>create("FROM karavan.ContainerStatus WHERE projectId = :projectId AND env = :env AND type = :type")
+                .setParameter("projectId", projectId)
+                .setParameter("env", env)
+                .setParameter("type", ContainerStatus.CType.devmode)
+                .execute().list();
+        return list.size() > 0 ? list.get(0) : null;
+    }
+
+    public List<ContainerStatus> getContainerStatuses(String env) {
+        QueryFactory queryFactory = Search.getQueryFactory(containerStatuses);
+        return queryFactory.<ContainerStatus>create("FROM karavan.ContainerStatus WHERE env = :env")
+                .setParameter("env", env)
+                .execute().list();
+    }
+
+    public List<ContainerStatus> getAllContainerStatuses() {
+        return new ArrayList<>(containerStatuses.values());
+    }
+
+    public void saveContainerStatus(ContainerStatus status) {
+        containerStatuses.put(GroupedKey.create(status.getProjectId(), status.getEnv(), status.getName()), status);
+    }
+
+    public void deleteContainerStatus(ContainerStatus status) {
+        containerStatuses.remove(GroupedKey.create(status.getProjectId(), status.getEnv(), status.getName()));
+    }
+
+    public void deleteContainerStatus(String projectId, String env, String containerName) {
+        containerStatuses.remove(GroupedKey.create(projectId, env, containerName));
+    }
+
+    public CamelStatus getCamelStatus(String projectId, String env, String name) {
+        GroupedKey key = GroupedKey.create(projectId, env, name);
+        return camelStatuses.get(key);
+    }
+
+    public List<CamelStatus> getCamelStatusesByEnv(String env, CamelStatus.Name name) {
+        QueryFactory queryFactory = Search.getQueryFactory(camelStatuses);
+        return queryFactory.<CamelStatus>create("FROM karavan.CamelStatus WHERE env = :env AND name = :name")
+                .setParameter("env", env)
+                .setParameter("name", name)
+                .execute().list();
+    }
+
+    public List<CamelStatus> getCamelStatusesByProjectIdEnv(String projectId, String env) {
+        QueryFactory queryFactory = Search.getQueryFactory(camelStatuses);
+        return queryFactory.<CamelStatus>create("FROM karavan.CamelStatus WHERE projectId = :projectId AND env = :env")
+                .setParameter("projectId", projectId)
+                .setParameter("env", env)
+                .execute().list();
+    }
+
+    public void saveCamelStatus(CamelStatus status) {
+        GroupedKey key = GroupedKey.create(status.getProjectId(), status.getEnv(), status.getName().name());
+        camelStatuses.put(key, status);
+    }
+
+    public void deleteCamelStatus(String projectId, String name, String env) {
+        GroupedKey key = GroupedKey.create(projectId, env, name);
+        camelStatuses.remove(key);
+    }
+
+    public void deleteCamelStatuses(String projectId, String env) {
+        Arrays.stream(CamelStatus.Name.values()).forEach(name -> {
+            GroupedKey key = GroupedKey.create(projectId, env, name.name());
+            camelStatuses.remove(key);
+        });
+    }
+
+    public void saveCommit(String commitId, int time) {
+        commits.put(commitId, String.valueOf(time));
+    }
+
+    public void saveLastCommit(String commitId) {
+        commits.put("lastCommitId", commitId);
+    }
+
+    public Tuple2<String, Integer> getLastCommit() {
+        String lastCommitId = commits.get("lastCommitId");
+        String time = commits.get(lastCommitId);
+        return Tuple2.of(lastCommitId, Integer.parseInt(time));
+    }
+
+    public boolean hasCommit(String commitId) {
+        return commits.get(commitId) != null;
+    }
+
+    public void saveDevModeStatus(DevModeStatus status) {
+        devmodeStatuses.put(GroupedKey.create(status.getProjectId(), DEFAULT_ENVIRONMENT, status.getProjectId()), status);
+    }
+
+    public void deleteDevModeStatus(String projectId) {
+        devmodeStatuses.remove(GroupedKey.create(projectId, DEFAULT_ENVIRONMENT, projectId));
+    }
+
+    public DevModeStatus getDevModeStatus(String projectId) {
+        return devmodeStatuses.get(GroupedKey.create(projectId,DEFAULT_ENVIRONMENT, projectId));
+    }
+
+    public List<DevModeStatus> getLoadedDevModeStatuses() {
+        QueryFactory queryFactory = Search.getQueryFactory(devmodeStatuses);
+        return queryFactory.<DevModeStatus>create("FROM karavan.DevModeStatus WHERE codeLoaded = true")
+                .execute().list();
+    }
+
+    public List<DevModeStatus> getDevModeStatuses() {
+       return new ArrayList<>(devmodeStatuses.values());
+    }
+
+    public void saveContainerInfo(ContainerInfo ci) {
+        containers.put(GroupedKey.create(ci.getContainerName(), ci.getEnv() != null ? ci.getEnv() : DEFAULT_ENVIRONMENT, ci.getContainerName()), ci);
+    }
+
+    public void getContainerInfo(String name, String env) {
+        containers.get(GroupedKey.create(name, env, name));
+    }
+
+    public List<ContainerInfo> getContainerInfos(String env) {
+        QueryFactory queryFactory = Search.getQueryFactory(containers);
+        return queryFactory.<ContainerInfo>create("FROM karavan.ContainerInfo WHERE env = :env")
+                .setParameter("env", env)
+                .execute().list();
+    }
+
+    public void deleteContainerInfo(String containerName) {
+        containers.remove(GroupedKey.create(containerName, DEFAULT_ENVIRONMENT, containerName));
+    }
+
+    public void clearAllStatuses() {
+        CompletableFuture.allOf(
+            deploymentStatuses.clearAsync(),
+            containerStatuses.clearAsync(),
+            pipelineStatuses.clearAsync(),
+            camelStatuses.clearAsync(),
+            devmodeStatuses.clearAsync()
+        ).join();
+    }
+
+    private String getResourceFile(String path) {
+        try {
+            InputStream inputStream = InfinispanService.class.getResourceAsStream(path);
+            return new BufferedReader(new InputStreamReader(inputStream))
+                    .lines().collect(Collectors.joining(System.getProperty("line.separator")));
+        } catch (Exception e) {
+            return null;
+        }
+    }
+}
diff --git a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/CamelStatus.java b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/CamelStatus.java
new file mode 100644
index 00000000..37109261
--- /dev/null
+++ b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/CamelStatus.java
@@ -0,0 +1,81 @@
+package org.apache.camel.karavan.infinispan.model;
+
+import org.infinispan.protostream.annotations.ProtoEnumValue;
+import org.infinispan.protostream.annotations.ProtoFactory;
+import org.infinispan.protostream.annotations.ProtoField;
+
+public class CamelStatus {
+
+    public enum Name {
+
+        @ProtoEnumValue(number = 0, name = "context") context,
+        @ProtoEnumValue (number = 1, name = "inflight") inflight,
+        @ProtoEnumValue (number = 2, name = "memory") memory,
+        @ProtoEnumValue (number = 3, name = "properties") properties,
+        @ProtoEnumValue (number = 4, name = "route") route,
+        @ProtoEnumValue (number = 5, name = "trace") trace,
+        @ProtoEnumValue (number = 6, name = "jvm") jvm,
+        @ProtoEnumValue (number = 7, name = "source") source
+    }
+
+    public static final String CACHE = "camel_statuses";
+    @ProtoField(number = 1)
+    String projectId;
+    @ProtoField(number = 2)
+    String containerName;
+    @ProtoField(number = 3)
+    Name name;
+    @ProtoField(number = 4)
+    String status;
+    @ProtoField(number = 5)
+    String env;
+
+    @ProtoFactory
+    public CamelStatus(String projectId, String containerName, Name name, String status, String env) {
+        this.projectId = projectId;
+        this.containerName = containerName;
+        this.name = name;
+        this.status = status;
+        this.env = env;
+    }
+
+    public String getProjectId() {
+        return projectId;
+    }
+
+    public void setProjectId(String projectId) {
+        this.projectId = projectId;
+    }
+
+    public String getContainerName() {
+        return containerName;
+    }
+
+    public void setContainerName(String containerName) {
+        this.containerName = containerName;
+    }
+
+    public Name getName() {
+        return name;
+    }
+
+    public void setName(Name name) {
+        this.name = name;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public String getEnv() {
+        return env;
+    }
+
+    public void setEnv(String env) {
+        this.env = env;
+    }
+}
diff --git a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/CommitInfo.java b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/CommitInfo.java
new file mode 100644
index 00000000..b7ee2075
--- /dev/null
+++ b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/CommitInfo.java
@@ -0,0 +1,53 @@
+package org.apache.camel.karavan.infinispan.model;
+
+import java.util.List;
+
+public class CommitInfo {
+    private String commitId;
+    private Integer time;
+    private List<GitRepo> repos;
+
+    public CommitInfo(String commitId, Integer time) {
+        this.commitId = commitId;
+        this.time = time;
+    }
+
+    public CommitInfo(String commitId, Integer time, List<GitRepo> repos) {
+        this.commitId = commitId;
+        this.time = time;
+        this.repos = repos;
+    }
+
+    public String getCommitId() {
+        return commitId;
+    }
+
+    public void setCommitId(String commitId) {
+        this.commitId = commitId;
+    }
+
+    public Integer getTime() {
+        return time;
+    }
+
+    public void setTime(Integer time) {
+        this.time = time;
+    }
+
+    public List<GitRepo> getRepos() {
+        return repos;
+    }
+
+    public void setRepos(List<GitRepo> repos) {
+        this.repos = repos;
+    }
+
+    @Override
+    public String toString() {
+        return "CommitInfo{" +
+                "commitId='" + commitId + '\'' +
+                ", time=" + time +
+                ", repos=" + repos +
+                '}';
+    }
+}
diff --git a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerInfo.java b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerInfo.java
new file mode 100644
index 00000000..985e70b3
--- /dev/null
+++ b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerInfo.java
@@ -0,0 +1,70 @@
+package org.apache.camel.karavan.infinispan.model;
+
+import org.infinispan.protostream.annotations.ProtoFactory;
+import org.infinispan.protostream.annotations.ProtoField;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ContainerInfo {
+    public static final String CACHE = "container_infos";
+    @ProtoField(number = 1)
+    String containerName;
+    @ProtoField(number = 2)
+    String containerId;
+    @ProtoField(number = 3)
+    String image;
+    @ProtoField(number = 4, collectionImplementation = ArrayList.class)
+    List<Integer> ports;
+    @ProtoField(number = 5)
+    String env;
+
+    @ProtoFactory
+    public ContainerInfo(String containerName, String containerId, String image, List<Integer> ports, String env) {
+        this.containerName = containerName;
+        this.containerId = containerId;
+        this.image = image;
+        this.ports = ports;
+        this.env = env;
+    }
+
+    public String getEnv() {
+        return env;
+    }
+
+    public void setEnv(String env) {
+        this.env = env;
+    }
+
+    public String getContainerName() {
+        return containerName;
+    }
+
+    public void setContainerName(String containerName) {
+        this.containerName = containerName;
+    }
+
+    public String getContainerId() {
+        return containerId;
+    }
+
+    public void setContainerId(String containerId) {
+        this.containerId = containerId;
+    }
+
+    public String getImage() {
+        return image;
+    }
+
+    public void setImage(String image) {
+        this.image = image;
+    }
+
+    public List<Integer> getPorts() {
+        return ports;
+    }
+
+    public void setPorts(List<Integer> ports) {
+        this.ports = ports;
+    }
+}
diff --git a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerStatus.java b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerStatus.java
new file mode 100644
index 00000000..d8a3db89
--- /dev/null
+++ b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerStatus.java
@@ -0,0 +1,141 @@
+package org.apache.camel.karavan.infinispan.model;
+
+import org.infinispan.protostream.annotations.ProtoEnumValue;
+import org.infinispan.protostream.annotations.ProtoFactory;
+import org.infinispan.protostream.annotations.ProtoField;
+
+public class ContainerStatus {
+
+    public enum CType {
+        @ProtoEnumValue(number = 0, name = "devmode") devmode,
+        @ProtoEnumValue(number = 1, name = "devservice") devservice,
+        @ProtoEnumValue(number = 2, name = "pod") pod,
+        @ProtoEnumValue(number = 3, name = "container") container,
+    }
+
+    public static final String CACHE = "pod_statuses";
+    @ProtoField(number = 1)
+    String name;
+    @ProtoField(number = 2)
+    Boolean ready;
+    @ProtoField(number = 3)
+    String projectId;
+    @ProtoField(number = 4)
+    String env;
+    @ProtoField(number = 5)
+    Integer exposedPort;
+    @ProtoField(number = 6)
+    CType type;
+    @ProtoField(number = 7)
+    String memoryInfo;
+    @ProtoField(number = 8)
+    String cpuInfo;
+    @ProtoField(number = 9)
+    String created;
+
+    @ProtoFactory
+    public ContainerStatus(String name, Boolean ready, String projectId, String env, Integer exposedPort, CType type, String memoryInfo, String cpuInfo, String created) {
+        this.name = name;
+        this.ready = ready;
+        this.projectId = projectId;
+        this.env = env;
+        this.exposedPort = exposedPort;
+        this.type = type;
+        this.memoryInfo = memoryInfo;
+        this.cpuInfo = cpuInfo;
+        this.created = created;
+    }
+
+    public ContainerStatus(String name, Boolean ready, String projectId, String env, CType type, String memoryInfo, String cpuInfo, String created) {
+        this.name = name;
+        this.ready = ready;
+        this.projectId = projectId;
+        this.env = env;
+        this.memoryInfo = memoryInfo;
+        this.cpuInfo = cpuInfo;
+        this.created = created;
+        this.type = type;
+    }
+
+    public ContainerStatus(String name, Boolean ready, String projectId, String env, CType type, String created, Integer exposedPort) {
+        this.name = name;
+        this.ready = ready;
+        this.projectId = projectId;
+        this.env = env;
+        this.created = created;
+        this.exposedPort = exposedPort;
+        this.type = type;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Boolean getReady() {
+        return ready;
+    }
+
+    public void setReady(Boolean ready) {
+        this.ready = ready;
+    }
+
+    public String getProjectId() {
+        return projectId;
+    }
+
+    public void setProjectId(String projectId) {
+        this.projectId = projectId;
+    }
+
+    public String getEnv() {
+        return env;
+    }
+
+    public void setEnv(String env) {
+        this.env = env;
+    }
+
+    public String getMemoryInfo() {
+        return memoryInfo;
+    }
+
+    public void setMemoryInfo(String memoryInfo) {
+        this.memoryInfo = memoryInfo;
+    }
+
+    public String getCpuInfo() {
+        return cpuInfo;
+    }
+
+    public void setCpuInfo(String cpuInfo) {
+        this.cpuInfo = cpuInfo;
+    }
+
+    public String getCreated() {
+        return created;
+    }
+
+    public void setCreated(String created) {
+        this.created = created;
+    }
+
+    public Integer getExposedPort() {
+        return exposedPort;
+    }
+
+    public void setExposedPort(Integer exposedPort) {
+        this.exposedPort = exposedPort;
+    }
+
+    public CType getType() {
+        return type;
+    }
+
+    public void setType(CType type) {
+        this.type = type;
+    }
+}
diff --git a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/DeploymentStatus.java b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/DeploymentStatus.java
new file mode 100644
index 00000000..95e35d67
--- /dev/null
+++ b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/DeploymentStatus.java
@@ -0,0 +1,111 @@
+package org.apache.camel.karavan.infinispan.model;
+
+import org.infinispan.protostream.annotations.ProtoFactory;
+import org.infinispan.protostream.annotations.ProtoField;
+
+public class DeploymentStatus {
+    public static final String CACHE = "deployment_statuses";
+    @ProtoField(number = 1)
+    String projectId;
+    @ProtoField(number = 2)
+    String namespace;
+    @ProtoField(number = 3)
+    String env;
+    @ProtoField(number = 4)
+    String cluster;
+    @ProtoField(number = 5)
+    String image;
+    @ProtoField(number = 6)
+    Integer replicas;
+    @ProtoField(number = 7)
+    Integer readyReplicas;
+    @ProtoField(number = 8)
+    Integer unavailableReplicas;
+
+    public DeploymentStatus(String projectId, String namespace, String cluster, String env) {
+        this.projectId = projectId;
+        this.namespace = namespace;
+        this.cluster = cluster;
+        this.env = env;
+        this.image = "";
+        this.replicas = 0;
+        this.readyReplicas = 0;
+        this.unavailableReplicas = 0;
+    }
+
+    @ProtoFactory
+    public DeploymentStatus(String projectId, String namespace, String cluster, String env, String image, Integer replicas, Integer readyReplicas, Integer unavailableReplicas) {
+        this.projectId = projectId;
+        this.namespace = namespace;
+        this.env = env;
+        this.cluster = cluster;
+        this.image = image;
+        this.replicas = replicas;
+        this.readyReplicas = readyReplicas;
+        this.unavailableReplicas = unavailableReplicas;
+    }
+
+    public String getProjectId() {
+        return projectId;
+    }
+
+    public void setProjectId(String projectId) {
+        this.projectId = projectId;
+    }
+
+    public String getEnv() {
+        return env;
+    }
+
+    public void setEnv(String env) {
+        this.env = env;
+    }
+
+    public String getNamespace() {
+        return namespace;
+    }
+
+    public void setNamespace(String namespace) {
+        this.namespace = namespace;
+    }
+
+    public String getImage() {
+        return image;
+    }
+
+    public void setImage(String image) {
+        this.image = image;
+    }
+
+    public Integer getReplicas() {
+        return replicas;
+    }
+
+    public void setReplicas(Integer replicas) {
+        this.replicas = replicas;
+    }
+
+    public Integer getReadyReplicas() {
+        return readyReplicas;
+    }
+
+    public void setReadyReplicas(Integer readyReplicas) {
+        this.readyReplicas = readyReplicas;
+    }
+
+    public Integer getUnavailableReplicas() {
+        return unavailableReplicas;
+    }
+
+    public void setUnavailableReplicas(Integer unavailableReplicas) {
+        this.unavailableReplicas = unavailableReplicas;
+    }
+
+    public String getCluster() {
+        return cluster;
+    }
+
+    public void setCluster(String cluster) {
+        this.cluster = cluster;
+    }
+}
diff --git a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/DevModeStatus.java b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/DevModeStatus.java
new file mode 100644
index 00000000..c45208d3
--- /dev/null
+++ b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/DevModeStatus.java
@@ -0,0 +1,78 @@
+package org.apache.camel.karavan.infinispan.model;
+
+import org.infinispan.protostream.annotations.ProtoFactory;
+import org.infinispan.protostream.annotations.ProtoField;
+
+public class DevModeStatus {
+    public static final String CACHE = "devmode_statuses";
+    @ProtoField(number = 1)
+    String projectId;
+    @ProtoField(number = 2)
+    String containerName;
+    @ProtoField(number = 3)
+    String containerId;
+    @ProtoField(number = 4)
+    Boolean codeLoaded;
+    @ProtoField(number = 5)
+    Boolean logging;
+
+    @ProtoFactory
+    public DevModeStatus(String projectId, String containerName, String containerId, Boolean codeLoaded, Boolean logging) {
+        this.projectId = projectId;
+        this.containerName = containerName;
+        this.containerId = containerId;
+        this.codeLoaded = codeLoaded;
+        this.logging = logging;
+    }
+
+    public DevModeStatus(String projectId, String containerName, String containerId, Boolean codeLoaded) {
+        this.projectId = projectId;
+        this.containerName = containerName;
+        this.containerId = containerId;
+        this.codeLoaded = codeLoaded;
+        this.logging = false;
+    }
+
+    public DevModeStatus() {
+    }
+
+    public String getProjectId() {
+        return projectId;
+    }
+
+    public void setProjectId(String projectId) {
+        this.projectId = projectId;
+    }
+
+    public String getContainerName() {
+        return containerName;
+    }
+
+    public void setContainerName(String containerName) {
+        this.containerName = containerName;
+    }
+
+    public String getContainerId() {
+        return containerId;
+    }
+
+    public void setContainerId(String containerId) {
+        this.containerId = containerId;
+    }
+
+    public Boolean getCodeLoaded() {
+        return codeLoaded;
+    }
+
+    public void setCodeLoaded(Boolean codeLoaded) {
+        this.codeLoaded = codeLoaded;
+    }
+
+    public Boolean getLogging() {
+        return logging;
+    }
+
+    public void setLogging(Boolean logging) {
+        this.logging = logging;
+    }
+}
diff --git a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/GitConfig.java b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/GitConfig.java
new file mode 100644
index 00000000..285c8017
--- /dev/null
+++ b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/GitConfig.java
@@ -0,0 +1,48 @@
+package org.apache.camel.karavan.infinispan.model;
+
+public class GitConfig {
+    private String uri;
+    private String username;
+    private String password;
+    private String branch;
+
+    public GitConfig(String uri, String username, String password, String branch) {
+        this.uri = uri;
+        this.username = username;
+        this.password = password;
+        this.branch = branch;
+    }
+
+    public String getUri() {
+        return uri;
+    }
+
+    public void setUri(String uri) {
+        this.uri = uri;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getBranch() {
+        return branch;
+    }
+
+    public void setBranch(String branch) {
+        this.branch = branch;
+    }
+
+}
diff --git a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/GitRepo.java b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/GitRepo.java
new file mode 100644
index 00000000..4736814f
--- /dev/null
+++ b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/GitRepo.java
@@ -0,0 +1,49 @@
+package org.apache.camel.karavan.infinispan.model;
+
+import java.util.List;
+
+public class GitRepo {
+    private String name;
+    private String commitId;
+    private Long lastCommitTimestamp;
+    private List<GitRepoFile> files;
+
+    public GitRepo(String name, String commitId, Long lastCommitTimestamp, List<GitRepoFile> files) {
+        this.name = name;
+        this.commitId = commitId;
+        this.lastCommitTimestamp = lastCommitTimestamp;
+        this.files = files;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getCommitId() {
+        return commitId;
+    }
+
+    public void setCommitId(String commitId) {
+        this.commitId = commitId;
+    }
+
+    public Long getLastCommitTimestamp() {
+        return lastCommitTimestamp;
+    }
+
+    public void setLastCommitTimestamp(Long lastCommitTimestamp) {
+        this.lastCommitTimestamp = lastCommitTimestamp;
+    }
+
+    public List<GitRepoFile> getFiles() {
+        return files;
+    }
+
+    public void setFiles(List<GitRepoFile> files) {
+        this.files = files;
+    }
+}
diff --git a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/GitRepoFile.java b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/GitRepoFile.java
new file mode 100644
index 00000000..a1186efe
--- /dev/null
+++ b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/GitRepoFile.java
@@ -0,0 +1,37 @@
+package org.apache.camel.karavan.infinispan.model;
+
+public class GitRepoFile {
+    private String name;
+    private Long lastCommitTimestamp;
+    private String body;
+
+    public GitRepoFile(String name, Long lastCommitTimestamp, String body) {
+        this.name = name;
+        this.lastCommitTimestamp = lastCommitTimestamp;
+        this.body = body;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Long getLastCommitTimestamp() {
+        return lastCommitTimestamp;
+    }
+
+    public void setLastCommitTimestamp(Long lastCommitTimestamp) {
+        this.lastCommitTimestamp = lastCommitTimestamp;
+    }
+
+    public String getBody() {
+        return body;
+    }
+
+    public void setBody(String body) {
+        this.body = body;
+    }
+}
diff --git a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/GroupedKey.java b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/GroupedKey.java
new file mode 100644
index 00000000..e1889dd2
--- /dev/null
+++ b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/GroupedKey.java
@@ -0,0 +1,81 @@
+package org.apache.camel.karavan.infinispan.model;
+
+import org.infinispan.protostream.annotations.ProtoFactory;
+import org.infinispan.protostream.annotations.ProtoField;
+//import org.infinispan.distribution.group.Group;
+
+
+public class GroupedKey {
+
+    @ProtoField(number = 1)
+    String projectId;
+    @ProtoField(number = 2)
+    String env;
+    @ProtoField(number = 3)
+    String key;
+
+    @ProtoFactory
+    public GroupedKey(String projectId, String env, String key) {
+        this.projectId = projectId;
+        this.env = env;
+        this.key = key;
+    }
+
+    public static GroupedKey create(String projectId, String env, String key) {
+        return new GroupedKey(projectId, env, key);
+    }
+
+    public String getEnv() {
+        return env;
+    }
+
+    public void setEnv(String env) {
+        this.env = env;
+    }
+
+    public void setProjectId(String projectId) {
+        this.projectId = projectId;
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public void setKey(String key) {
+        this.key = key;
+    }
+
+//    @Group https://github.com/quarkusio/quarkus/issues/34677
+    public String getProjectId() {
+        return projectId;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        GroupedKey that = (GroupedKey) o;
+
+        if (!projectId.equals(that.projectId)) return false;
+        if (!env.equals(that.env)) return false;
+        return key.equals(that.key);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = projectId.hashCode();
+        result = 31 * result + env.hashCode();
+        result = 31 * result + key.hashCode();
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "GroupedKey{" +
+                "projectId='" + projectId + '\'' +
+                ", env='" + env + '\'' +
+                ", key='" + key + '\'' +
+                '}';
+    }
+}
\ No newline at end of file
diff --git a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/KaravanSchema.java b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/KaravanSchema.java
new file mode 100644
index 00000000..1b2777ca
--- /dev/null
+++ b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/KaravanSchema.java
@@ -0,0 +1,28 @@
+package org.apache.camel.karavan.infinispan.model;
+
+import org.infinispan.protostream.GeneratedSchema;
+import org.infinispan.protostream.annotations.AutoProtoSchemaBuilder;
+
+@AutoProtoSchemaBuilder(
+        includeClasses = {
+                GroupedKey.class,
+                Project.class,
+                Project.Type.class,
+                ProjectFile.class,
+                PipelineStatus.class,
+                CamelStatus.class,
+                CamelStatus.Name.class,
+                DeploymentStatus.class,
+                ContainerStatus.class,
+                ContainerStatus.CType.class,
+                ServiceStatus.class,
+                DevModeStatus.class,
+                ContainerInfo.class
+        },
+        schemaFileName = "karavan.proto",
+        schemaFilePath = "proto/",
+        schemaPackageName = "karavan")
+public interface KaravanSchema extends GeneratedSchema {
+}
+
+
diff --git a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/PipelineStatus.java b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/PipelineStatus.java
new file mode 100644
index 00000000..fd0831d0
--- /dev/null
+++ b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/PipelineStatus.java
@@ -0,0 +1,83 @@
+package org.apache.camel.karavan.infinispan.model;
+
+import org.infinispan.protostream.annotations.ProtoFactory;
+import org.infinispan.protostream.annotations.ProtoField;
+
+public class PipelineStatus {
+    public static final String CACHE = "pipeline_statuses";
+    @ProtoField(number = 1)
+    String projectId;
+    @ProtoField(number = 2)
+    String pipelineName;
+    @ProtoField(number = 3)
+    String result;
+    @ProtoField(number = 5)
+    String startTime;
+    @ProtoField(number = 6)
+    String completionTime;
+    @ProtoField(number = 7)
+    String env;
+
+    @ProtoFactory
+    public PipelineStatus(String projectId, String pipelineName, String result, String startTime, String completionTime, String env) {
+        this.projectId = projectId;
+        this.pipelineName = pipelineName;
+        this.result = result;
+        this.startTime = startTime;
+        this.completionTime = completionTime;
+        this.env = env;
+    }
+
+    public PipelineStatus(String projectId, String env) {
+        this.projectId = projectId;
+        this.env = env;
+    }
+
+    public String getProjectId() {
+        return projectId;
+    }
+
+    public void setProjectId(String projectId) {
+        this.projectId = projectId;
+    }
+
+    public String getPipelineName() {
+        return pipelineName;
+    }
+
+    public void setPipelineName(String pipelineName) {
+        this.pipelineName = pipelineName;
+    }
+
+    public String getResult() {
+        return result;
+    }
+
+    public void setResult(String result) {
+        this.result = result;
+    }
+
+    public String getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(String startTime) {
+        this.startTime = startTime;
+    }
+
+    public String getCompletionTime() {
+        return completionTime;
+    }
+
+    public void setCompletionTime(String completionTime) {
+        this.completionTime = completionTime;
+    }
+
+    public String getEnv() {
+        return env;
+    }
+
+    public void setEnv(String env) {
+        this.env = env;
+    }
+}
diff --git a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/Project.java b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/Project.java
new file mode 100644
index 00000000..9c31e296
--- /dev/null
+++ b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/Project.java
@@ -0,0 +1,125 @@
+package org.apache.camel.karavan.infinispan.model;
+
+import org.infinispan.protostream.annotations.ProtoEnumValue;
+import org.infinispan.protostream.annotations.ProtoFactory;
+import org.infinispan.protostream.annotations.ProtoField;
+
+import java.time.Instant;
+
+public class Project {
+    public static final String CACHE = "projects";
+
+    public enum Type {
+
+        @ProtoEnumValue(number = 0, name = "templates") templates,
+        @ProtoEnumValue (number = 1, name = "kamelets") kamelets,
+        @ProtoEnumValue (number = 2, name = "services") services,
+        @ProtoEnumValue (number = 3, name = "pipelines") pipelines,
+        @ProtoEnumValue (number = 4, name = "normal") normal,
+    }
+
+    @ProtoField(number = 1)
+    String projectId;
+    @ProtoField(number = 2)
+    String name;
+    @ProtoField(number = 3)
+    String description;
+    @ProtoField(number = 4)
+    String runtime;
+    @ProtoField(number = 5)
+    String lastCommit;
+    @ProtoField(number = 6)
+    Long lastCommitTimestamp;
+    @ProtoField(number = 7)
+    Type type;
+
+    @ProtoFactory
+    public Project(String projectId, String name, String description, String runtime, String lastCommit, Long lastCommitTimestamp, Type type) {
+        this.projectId = projectId;
+        this.name = name;
+        this.description = description;
+        this.runtime = runtime;
+        this.lastCommit = lastCommit;
+        this.lastCommitTimestamp = lastCommitTimestamp;
+        this.type = type;
+    }
+
+    public Project(String projectId, String name, String description, String runtime, String lastCommit, Long lastCommitTimestamp) {
+        this.projectId = projectId;
+        this.name = name;
+        this.description = description;
+        this.runtime = runtime;
+        this.lastCommit = lastCommit;
+        this.lastCommitTimestamp = lastCommitTimestamp;
+        this.type = Type.normal;
+    }
+
+    public Project(String projectId, String name, String description, String runtime) {
+        this.projectId = projectId;
+        this.name = name;
+        this.description = description;
+        this.runtime = runtime;
+        this.lastCommitTimestamp = Instant.now().toEpochMilli();
+        this.type = Type.normal;
+    }
+
+    public Project() {
+        this.type = Type.normal;
+    }
+
+    public String getProjectId() {
+        return projectId;
+    }
+
+    public void setProjectId(String projectId) {
+        this.projectId = projectId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getRuntime() {
+        return runtime;
+    }
+
+    public void setRuntime(String runtime) {
+        this.runtime = runtime;
+    }
+
+    public String getLastCommit() {
+        return lastCommit;
+    }
+
+    public void setLastCommit(String lastCommit) {
+        this.lastCommit = lastCommit;
+    }
+
+    public Long getLastCommitTimestamp() {
+        return lastCommitTimestamp;
+    }
+
+    public void setLastCommitTimestamp(Long lastCommitTimestamp) {
+        this.lastCommitTimestamp = lastCommitTimestamp;
+    }
+
+    public Type getType() {
+        return type;
+    }
+
+    public void setType(Type type) {
+        this.type = type;
+    }
+}
diff --git a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/ProjectFile.java b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/ProjectFile.java
new file mode 100644
index 00000000..14cc3adf
--- /dev/null
+++ b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/ProjectFile.java
@@ -0,0 +1,71 @@
+package org.apache.camel.karavan.infinispan.model;
+
+import org.infinispan.protostream.annotations.ProtoDoc;
+import org.infinispan.protostream.annotations.ProtoFactory;
+import org.infinispan.protostream.annotations.ProtoField;
+
+public class ProjectFile {
+    public static final String CACHE = "project_files";
+    @ProtoField(number = 1)
+    String name;
+    @ProtoField(number = 2)
+    String code;
+    @ProtoField(number = 3)
+    @ProtoDoc("@Field(index=Index.YES, analyze = Analyze.YES, store = Store.NO)")
+    String projectId;
+    @ProtoField(number = 4)
+    Long lastUpdate;
+
+    @ProtoFactory
+    public ProjectFile(String name, String code, String projectId, Long lastUpdate) {
+        this.name = name;
+        this.code = code;
+        this.projectId = projectId;
+        this.lastUpdate = lastUpdate;
+    }
+
+    public ProjectFile() {
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getProjectId() {
+        return projectId;
+    }
+
+    public void setProjectId(String projectId) {
+        this.projectId = projectId;
+    }
+
+    public Long getLastUpdate() {
+        return lastUpdate;
+    }
+
+    public void setLastUpdate(Long lastUpdate) {
+        this.lastUpdate = lastUpdate;
+    }
+
+    @Override
+    public String toString() {
+        return "ProjectFile{" +
+                "name='" + name + '\'' +
+                ", code='" + code + '\'' +
+                ", projectId='" + projectId + '\'' +
+                ", lastUpdate=" + lastUpdate +
+                '}';
+    }
+}
diff --git a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/ServiceStatus.java b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/ServiceStatus.java
new file mode 100644
index 00000000..9ce1d073
--- /dev/null
+++ b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/ServiceStatus.java
@@ -0,0 +1,107 @@
+package org.apache.camel.karavan.infinispan.model;
+
+import org.infinispan.protostream.annotations.ProtoFactory;
+import org.infinispan.protostream.annotations.ProtoField;
+
+public class ServiceStatus {
+    public static final String CACHE = "service_statuses";
+    @ProtoField(number = 1)
+    String projectId;
+    @ProtoField(number = 2)
+    String namespace;
+    @ProtoField(number = 3)
+    String env;
+    @ProtoField(number = 4)
+    String cluster;
+    @ProtoField(number = 5)
+    Integer port;
+    @ProtoField(number = 6)
+    Integer targetPort;
+    @ProtoField(number = 7)
+    String clusterIP;
+    @ProtoField(number = 8)
+    String type;
+
+    @ProtoFactory
+    public ServiceStatus(String projectId, String namespace, String env, String cluster, Integer port, Integer targetPort, String clusterIP, String type) {
+        this.projectId = projectId;
+        this.namespace = namespace;
+        this.env = env;
+        this.cluster = cluster;
+        this.port = port;
+        this.targetPort = targetPort;
+        this.clusterIP = clusterIP;
+        this.type = type;
+    }
+
+    public ServiceStatus(String projectId, String namespace, String cluster, String env) {
+        this.projectId = projectId;
+        this.namespace = namespace;
+        this.env = env;
+        this.cluster = cluster;
+    }
+
+    public String getProjectId() {
+        return projectId;
+    }
+
+    public void setProjectId(String projectId) {
+        this.projectId = projectId;
+    }
+
+    public String getNamespace() {
+        return namespace;
+    }
+
+    public void setNamespace(String namespace) {
+        this.namespace = namespace;
+    }
+
+    public String getEnv() {
+        return env;
+    }
+
+    public void setEnv(String env) {
+        this.env = env;
+    }
+
+    public String getCluster() {
+        return cluster;
+    }
+
+    public void setCluster(String cluster) {
+        this.cluster = cluster;
+    }
+
+    public Integer getPort() {
+        return port;
+    }
+
+    public void setPort(Integer port) {
+        this.port = port;
+    }
+
+    public Integer getTargetPort() {
+        return targetPort;
+    }
+
+    public void setTargetPort(Integer targetPort) {
+        this.targetPort = targetPort;
+    }
+
+    public String getClusterIP() {
+        return clusterIP;
+    }
+
+    public void setClusterIP(String clusterIP) {
+        this.clusterIP = clusterIP;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+}
diff --git a/karavan-web/karavan-infinispan/src/main/resources/application.properties b/karavan-web/karavan-infinispan/src/main/resources/application.properties
new file mode 100644
index 00000000..81c48214
--- /dev/null
+++ b/karavan-web/karavan-infinispan/src/main/resources/application.properties
@@ -0,0 +1,14 @@
+infinispan.username=admin
+infinispan.password=password
+infinispan.hosts=localhost:11222
+
+quarkus.infinispan-client.devservices.enabled=true
+quarkus.infinispan-client.devservices.service-name=infinispan
+quarkus.infinispan-client.devservices.image-name=quay.io/infinispan/server:14.0.6.Final
+quarkus.infinispan-client.devservices.port=11222
+quarkus.infinispan-client.health.enabled=false
+
+# Infinispan client intelligence
+# Use BASIC as a Docker for Mac workaround
+quarkus.infinispan-client.client-intelligence=BASIC
+
diff --git a/karavan-web/karavan-infinispan/src/main/resources/cache/command-cache-config.xml b/karavan-web/karavan-infinispan/src/main/resources/cache/command-cache-config.xml
new file mode 100644
index 00000000..27481642
--- /dev/null
+++ b/karavan-web/karavan-infinispan/src/main/resources/cache/command-cache-config.xml
@@ -0,0 +1,6 @@
+<distributed-cache name="%s" mode="SYNC">
+    <encoding media-type="application/x-protostream"/>
+    <locking isolation="REPEATABLE_READ"/>
+    <groups enabled="true"/>
+    <memory max-count="100000" when-full="REMOVE"/>
+</distributed-cache>
\ No newline at end of file
diff --git a/karavan-web/karavan-infinispan/src/main/resources/cache/data-cache-config.xml b/karavan-web/karavan-infinispan/src/main/resources/cache/data-cache-config.xml
new file mode 100644
index 00000000..31f6c304
--- /dev/null
+++ b/karavan-web/karavan-infinispan/src/main/resources/cache/data-cache-config.xml
@@ -0,0 +1,6 @@
+<distributed-cache name="%s" mode="SYNC">
+    <encoding media-type="application/x-protostream"/>
+    <locking isolation="REPEATABLE_READ"/>
+    <groups enabled="true"/>
+    <memory max-count="1000000" when-full="REMOVE"/>
+</distributed-cache>
\ No newline at end of file
diff --git a/karavan-web/karavan-infinispan/src/test/java/org/apache/camel/karavan/infinispan/DataGridTest.java b/karavan-web/karavan-infinispan/src/test/java/org/apache/camel/karavan/infinispan/DataGridTest.java
new file mode 100644
index 00000000..d90d4bcc
--- /dev/null
+++ b/karavan-web/karavan-infinispan/src/test/java/org/apache/camel/karavan/infinispan/DataGridTest.java
@@ -0,0 +1,74 @@
+package org.apache.camel.karavan.infinispan;
+
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.vertx.ConsumeEvent;
+import io.vertx.core.json.JsonObject;
+import org.apache.camel.karavan.infinispan.model.CamelStatus;
+import org.apache.camel.karavan.infinispan.model.ContainerInfo;
+import org.apache.camel.karavan.infinispan.model.ProjectFile;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+
+import javax.inject.Inject;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@QuarkusTest
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+public class DataGridTest {
+
+    @Inject
+    InfinispanService infinispanService;
+
+    @BeforeAll
+    public void setup() {
+        infinispanService.start(true);
+    }
+
+    @Test
+    public void testContainersStatuses() throws InterruptedException {
+        ContainerInfo ci = new ContainerInfo("demo", "id", "image", List.of(8080, 8081, 8082), "dev");
+        infinispanService.saveContainerInfo(ci);
+        List<ContainerInfo> list = infinispanService.getContainerInfos("dev");
+        assertEquals(1, list.size());
+    }
+
+    @Test
+    public void testProjectFiles() throws InterruptedException {
+        List<ProjectFile> files = infinispanService.getProjectFiles("xxx");
+        assertEquals(0, files.size());
+    }
+
+    @Test
+    public void testCamelStatuses() throws InterruptedException {
+        CamelStatus cs = new CamelStatus("test1", "container1", CamelStatus.Name.context, "", "dev");
+        infinispanService.saveCamelStatus(cs);
+        List<CamelStatus> list = infinispanService.getCamelStatusesByEnv("dev", CamelStatus.Name.context);
+        assertEquals(1, list.size());
+    }
+
+
+    private List<String> commandsReceived = new ArrayList<>();
+    @ConsumeEvent(InfinispanService.CODE_RELOAD_COMMAND)
+    void receiveCommand(String message) {
+        System.out.println("receiveCommand " + message);
+        commandsReceived.add(message);
+    }
+
+    @Test
+    public void sendCommand() throws InterruptedException {
+        List<String> commandsSent = List.of("test1", "test2", "test3", "test1");
+
+        commandsSent.forEach(project -> infinispanService.sendCodeReloadCommand(project));
+
+        CountDownLatch latch = new CountDownLatch(4);
+        latch.await(5, TimeUnit.SECONDS);
+        assertEquals(commandsSent.size(),  commandsReceived.size());
+    }
+}


[camel-karavan] 03/05: karavan-infinispan #817

Posted by ma...@apache.org.
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

commit e93a16a316567939afb098ba172bf2131f2a97d4
Author: Marat Gubaidullin <ma...@gmail.com>
AuthorDate: Fri Jul 21 21:18:42 2023 -0400

    karavan-infinispan #817
---
 .../karavan-app/Dockerfile.legacy-jar.dockerignore |   5 -
 .../karavan-app/Dockerfile.multistage.dockerignore |   3 -
 .../src/main/docker/Dockerfile.legacy-jar          |  41 ---
 .../src/main/docker/Dockerfile.multistage          |  66 ----
 .../karavan/infinispan/InfinispanService.java      | 388 ---------------------
 .../karavan/infinispan/model/CamelStatus.java      |  81 -----
 .../camel/karavan/infinispan/model/CommitInfo.java |  53 ---
 .../karavan/infinispan/model/ContainerInfo.java    |  70 ----
 .../karavan/infinispan/model/ContainerStatus.java  | 141 --------
 .../karavan/infinispan/model/DeploymentStatus.java | 111 ------
 .../karavan/infinispan/model/DevModeStatus.java    |  78 -----
 .../camel/karavan/infinispan/model/GitConfig.java  |  48 ---
 .../camel/karavan/infinispan/model/GitRepo.java    |  49 ---
 .../karavan/infinispan/model/GitRepoFile.java      |  37 --
 .../camel/karavan/infinispan/model/GroupedKey.java |  72 ----
 .../karavan/infinispan/model/KaravanSchema.java    |  28 --
 .../karavan/infinispan/model/PipelineStatus.java   |  83 -----
 .../camel/karavan/infinispan/model/Project.java    | 125 -------
 .../karavan/infinispan/model/ProjectFile.java      |  71 ----
 .../karavan/infinispan/model/ServiceStatus.java    | 107 ------
 .../main/resources/cache/command-cache-config.xml  |   6 -
 .../src/main/resources/cache/data-cache-config.xml |   6 -
 .../camel/karavan/infinispan/DataGridTest.java     |  53 ---
 .../src/test/resources/application.properties      |  11 -
 .../karavan/infinispan/model/ContainerStatus.java  |  33 +-
 25 files changed, 5 insertions(+), 1761 deletions(-)

diff --git a/karavan-web/karavan-app/Dockerfile.legacy-jar.dockerignore b/karavan-web/karavan-app/Dockerfile.legacy-jar.dockerignore
deleted file mode 100644
index 94810d00..00000000
--- a/karavan-web/karavan-app/Dockerfile.legacy-jar.dockerignore
+++ /dev/null
@@ -1,5 +0,0 @@
-*
-!target/*-runner
-!target/*-runner.jar
-!target/lib/*
-!target/quarkus-app/*
\ No newline at end of file
diff --git a/karavan-web/karavan-app/Dockerfile.multistage.dockerignore b/karavan-web/karavan-app/Dockerfile.multistage.dockerignore
deleted file mode 100644
index 7e3ec665..00000000
--- a/karavan-web/karavan-app/Dockerfile.multistage.dockerignore
+++ /dev/null
@@ -1,3 +0,0 @@
-target
-karavan/src/main/webapp/build
-karavan/src/main/webapp/node_modules
\ No newline at end of file
diff --git a/karavan-web/karavan-app/src/main/docker/Dockerfile.legacy-jar b/karavan-web/karavan-app/src/main/docker/Dockerfile.legacy-jar
deleted file mode 100644
index ef0505cb..00000000
--- a/karavan-web/karavan-app/src/main/docker/Dockerfile.legacy-jar
+++ /dev/null
@@ -1,41 +0,0 @@
-# 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 registry.access.redhat.com/ubi8/ubi-minimal:8.4 
-
-ARG JAVA_PACKAGE=java-11-openjdk-headless
-ARG RUN_JAVA_VERSION=1.3.8
-ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
-# Install java and the run-java script
-# Also set up permissions for user `1001`
-RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \
-    && microdnf update \
-    && microdnf clean all \
-    && mkdir /deployments \
-    && chown 1001 /deployments \
-    && chmod "g+rwX" /deployments \
-    && chown 1001:root /deployments \
-    && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \
-    && chown 1001 /deployments/run-java.sh \
-    && chmod 540 /deployments/run-java.sh \
-    && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/conf/security/java.security
-
-# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size.
-ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
-COPY target/*-runner.jar /deployments/app.jar
-
-EXPOSE 8080
-USER 1001
-
-ENTRYPOINT [ "/app/run-java.sh" ]
diff --git a/karavan-web/karavan-app/src/main/docker/Dockerfile.multistage b/karavan-web/karavan-app/src/main/docker/Dockerfile.multistage
deleted file mode 100644
index 92f7f2fb..00000000
--- a/karavan-web/karavan-app/src/main/docker/Dockerfile.multistage
+++ /dev/null
@@ -1,66 +0,0 @@
-# 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.
-
-## Stage 1 : build with maven builder image with native capabilities
-FROM quay.io/quarkus/ubi-quarkus-native-image:22.3.0-java11 AS build-gen
-
-## rsync required for npm to build frontend
-USER root
-RUN microdnf install rsync
-
-## Copy code
-COPY --chown=quarkus:quarkus karavan-generator/mvnw /code/mvnw
-COPY --chown=quarkus:quarkus karavan-generator/.mvn /code/.mvn
-COPY --chown=quarkus:quarkus karavan-generator/ /code/karavan-generator/
-COPY --chown=quarkus:quarkus karavan-core/ /code/karavan-core/
-COPY --chown=quarkus:quarkus karavan-app/ /code/karavan-app/
-COPY --chown=quarkus:quarkus karavan-designer/ /code/karavan-designer/
-# Required as output for KameletGenerator:
-COPY --chown=quarkus:quarkus karavan-vscode/ /code/karavan-vscode/
-
-USER quarkus
-WORKDIR /code
-
-# Generate Camel definitions
-RUN ./mvnw clean compile exec:java -Dexec.mainClass="org.apache.camel.karavan.generator.KaravanGenerator" -f karavan-generator
-
-## Stage 2 : build karavan-core
-FROM node:16-alpine AS build-node
-# Root user as we will not be running this image anyway
-USER root
-WORKDIR /code/karavan-core
-
-COPY --chown=root karavan-core/tsconfig.json /code/karavan-core/
-COPY --chown=root karavan-core/package.json /code/karavan-core/
-COPY --chown=root karavan-core/package-lock.json /code/karavan-core/
-RUN npm install --ignore-scripts
-
-COPY --chown=root --from=build-gen /code/karavan-core/ /code/karavan-core/
-RUN npm run build
-
-## Stage 3 : build karavan-app
-FROM build-gen as build-app
-COPY --chown=quarkus:quarkus --from=build-node /code/karavan-core/lib/ /code/karavan-core/lib/
-COPY --chown=quarkus:quarkus --from=build-node /code/karavan-core/node_modules/ /code/karavan-core/node_modules/
-RUN ./mvnw clean package -Pnative -f karavan-app -Dquarkus.profile=public
-
-## Stage 4 : create the docker final image
-FROM quay.io/quarkus/quarkus-distroless-image:2.0
-COPY --chown=nonroot --from=build-app /code/karavan-app/target/*-runner /deployments/application
-
-EXPOSE 8080
-USER nonroot
-WORKDIR /deployments
-CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/InfinispanService.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/InfinispanService.java
deleted file mode 100644
index 9c47ebc3..00000000
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/InfinispanService.java
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * 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.karavan.infinispan;
-
-import io.smallrye.mutiny.tuples.Tuple2;
-import io.vertx.core.eventbus.EventBus;
-import org.apache.camel.karavan.infinispan.model.*;
-import org.eclipse.microprofile.config.inject.ConfigProperty;
-import org.infinispan.client.hotrod.RemoteCache;
-import org.infinispan.client.hotrod.RemoteCacheManager;
-import org.infinispan.client.hotrod.Search;
-import org.infinispan.client.hotrod.configuration.ClientIntelligence;
-import org.infinispan.client.hotrod.configuration.ConfigurationBuilder;
-import org.infinispan.commons.configuration.StringConfiguration;
-import org.infinispan.commons.marshall.ProtoStreamMarshaller;
-import org.infinispan.query.dsl.QueryFactory;
-import org.jboss.logging.Logger;
-
-import javax.enterprise.context.ApplicationScoped;
-import javax.enterprise.inject.Default;
-import javax.inject.Inject;
-import java.io.BufferedReader;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.time.Instant;
-import java.util.*;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.stream.Collectors;
-
-import static org.infinispan.query.remote.client.ProtobufMetadataManagerConstants.PROTOBUF_METADATA_CACHE_NAME;
-
-@Default
-@ApplicationScoped
-public class InfinispanService {
-
-    @ConfigProperty(name ="infinispan.hosts")
-    String infinispanHosts;
-    @ConfigProperty(name ="infinispan.username")
-    String infinispanUsername;
-    @ConfigProperty(name ="infinispan.password")
-    String infinispanPassword;
-
-    private RemoteCache<GroupedKey, Project> projects;
-    private RemoteCache<GroupedKey, ProjectFile> files;
-    private RemoteCache<GroupedKey, PipelineStatus> pipelineStatuses;
-    private RemoteCache<GroupedKey, DeploymentStatus> deploymentStatuses;
-    private RemoteCache<GroupedKey, ContainerStatus> containerStatuses;
-    private RemoteCache<GroupedKey, ServiceStatus> serviceStatuses;
-    private RemoteCache<GroupedKey, CamelStatus> camelStatuses;
-    private RemoteCache<String, String> commits;
-    private RemoteCache<GroupedKey, DevModeStatus> devmodeStatuses;
-    private RemoteCache<GroupedKey, ContainerInfo> containers;
-    private final AtomicBoolean ready = new AtomicBoolean(false);
-
-    private RemoteCacheManager cacheManager;
-
-    @Inject
-    EventBus eventBus;
-
-    private static final Logger LOGGER = Logger.getLogger(InfinispanService.class.getName());
-
-    private static final String DEFAULT_ENVIRONMENT = "dev";
-
-    public void start() {
-        LOGGER.info("InfinispanService is starting in remote mode");
-
-        ProtoStreamMarshaller marshaller = new ProtoStreamMarshaller();
-        marshaller.register(new KaravanSchemaImpl());
-
-        ConfigurationBuilder builder = new ConfigurationBuilder();
-        builder.socketTimeout(1000)
-                .connectionTimeout(10000)
-                .addServers(infinispanHosts)
-                .security()
-                .authentication().enable()
-                .username(infinispanUsername)
-                .password(infinispanPassword)
-                .clientIntelligence(ClientIntelligence.BASIC)
-                .marshaller(marshaller);
-
-        cacheManager = new RemoteCacheManager(builder.build());
-
-        projects = getOrCreateCache(Project.CACHE, false);
-        files = getOrCreateCache(ProjectFile.CACHE, false);
-        containerStatuses = getOrCreateCache(ContainerStatus.CACHE, false);
-        pipelineStatuses = getOrCreateCache(PipelineStatus.CACHE, false);
-        deploymentStatuses = getOrCreateCache(DeploymentStatus.CACHE, false);
-        serviceStatuses = getOrCreateCache(ServiceStatus.CACHE, false);
-        camelStatuses = getOrCreateCache(CamelStatus.CACHE, false);
-        commits = getOrCreateCache("commits", false);
-        deploymentStatuses = getOrCreateCache(DeploymentStatus.CACHE, false);
-        devmodeStatuses = getOrCreateCache(DevModeStatus.CACHE, false);
-        containers = getOrCreateCache(ContainerInfo.CACHE, false);
-
-        // Grab the generated protobuf schema and registers in the server.
-        cacheManager.getCache(PROTOBUF_METADATA_CACHE_NAME).put("karavan.proto", getResourceFile("/proto/karavan.proto"));
-
-        ready.set(true);
-        LOGGER.info("InfinispanService is started in remote mode");
-    }
-
-    public boolean isReady() {
-        return ready.get();
-    }
-
-    private <K, V> RemoteCache<K, V>  getOrCreateCache(String name, boolean command) {
-        String config = getResourceFile(command ? "/cache/command-cache-config.xml" : "/cache/data-cache-config.xml");
-        return cacheManager.administration().getOrCreateCache(name, new StringConfiguration(String.format(config, name)));
-    }
-
-    public List<Project> getProjects() {
-        return projects.values().stream().collect(Collectors.toList());
-    }
-
-    public void saveProject(Project project) {
-        GroupedKey key = GroupedKey.create(project.getProjectId(), DEFAULT_ENVIRONMENT, project.getProjectId());
-        projects.put(key, project);
-        projects.put(key, project);
-    }
-
-    public List<ProjectFile> getProjectFiles(String projectId) {
-        QueryFactory queryFactory = Search.getQueryFactory(files);
-        return queryFactory.<ProjectFile>create("FROM karavan.ProjectFile WHERE projectId = :projectId")
-                .setParameter("projectId", projectId)
-                .execute().list();
-    }
-
-    public Map<GroupedKey, ProjectFile> getProjectFilesMap(String projectId) {
-        QueryFactory queryFactory = Search.getQueryFactory(files);
-        return queryFactory.<ProjectFile>create("FROM karavan.ProjectFile WHERE projectId = :projectId")
-                .setParameter("projectId", projectId)
-                .execute().list().stream()
-                .collect(Collectors.toMap(f -> new GroupedKey(f.getProjectId(), DEFAULT_ENVIRONMENT, f.getName()), f -> f));
-    }
-
-    public ProjectFile getProjectFile(String projectId, String filename) {
-        QueryFactory queryFactory = Search.getQueryFactory(files);
-        List<ProjectFile> list = queryFactory.<ProjectFile>create("FROM karavan.ProjectFile WHERE projectId = :projectId AND name = :name")
-                .setParameter("projectId", projectId)
-                .setParameter("name", filename)
-                .execute().list();
-        return list.size() > 0 ? list.get(0) : null;
-    }
-
-    public void saveProjectFile(ProjectFile file) {
-        files.put(GroupedKey.create(file.getProjectId(), DEFAULT_ENVIRONMENT, file.getName()), file);
-    }
-
-    public void saveProjectFiles(Map<GroupedKey, ProjectFile> f) {
-        Map<GroupedKey, ProjectFile> files = new HashMap<>(f.size());
-        f.forEach((groupedKey, projectFile) -> {
-            projectFile.setLastUpdate(Instant.now().toEpochMilli());
-        });
-        files.putAll(files);
-    }
-
-    public void deleteProject(String projectId) {
-        projects.remove(GroupedKey.create(projectId, DEFAULT_ENVIRONMENT,projectId));
-    }
-
-    public void deleteProjectFile(String projectId, String filename) {
-        files.remove(GroupedKey.create(projectId, DEFAULT_ENVIRONMENT,filename));
-    }
-
-    public Project getProject(String projectId) {
-        return projects.get(GroupedKey.create(projectId, DEFAULT_ENVIRONMENT,projectId));
-    }
-
-    public PipelineStatus getPipelineStatus(String projectId, String environment) {
-        return pipelineStatuses.get(GroupedKey.create(projectId, environment, projectId));
-    }
-
-    public void savePipelineStatus(PipelineStatus status) {
-        pipelineStatuses.put(GroupedKey.create(status.getProjectId(), status.getEnv(), status.getProjectId()), status);
-    }
-
-    public void deletePipelineStatus(PipelineStatus status) {
-        pipelineStatuses.remove(GroupedKey.create(status.getProjectId(), status.getEnv(), status.getProjectId()));
-    }
-
-    public DeploymentStatus getDeploymentStatus(String projectId, String environment) {
-        return deploymentStatuses.get(GroupedKey.create(projectId, environment, projectId));
-    }
-
-    public void saveDeploymentStatus(DeploymentStatus status) {
-        deploymentStatuses.put(GroupedKey.create(status.getProjectId(), status.getEnv(), status.getProjectId()), status);
-    }
-
-    public void deleteDeploymentStatus(DeploymentStatus status) {
-        deploymentStatuses.remove(GroupedKey.create(status.getProjectId(), status.getEnv(), status.getProjectId()));
-    }
-
-    public List<DeploymentStatus> getDeploymentStatuses() {
-        return new ArrayList<>(deploymentStatuses.values());
-    }
-
-    public List<DeploymentStatus> getDeploymentStatuses(String env) {
-        QueryFactory queryFactory = Search.getQueryFactory((RemoteCache<?, ?>) deploymentStatuses);
-        return queryFactory.<DeploymentStatus>create("FROM karavan.DeploymentStatus WHERE env = :env")
-                .setParameter("env", env)
-                .execute().list();
-    }
-
-    public void saveServiceStatus(ServiceStatus status) {
-        serviceStatuses.put(GroupedKey.create(status.getProjectId(), status.getEnv(), status.getProjectId()), status);
-    }
-
-    public void deleteServiceStatus(ServiceStatus status) {
-        serviceStatuses.remove(GroupedKey.create(status.getProjectId(), status.getEnv(), status.getProjectId()));
-    }
-
-    public List<ServiceStatus> getServiceStatuses() {
-        return new ArrayList<>(serviceStatuses.values());
-    }
-
-    public List<ContainerStatus> getContainerStatuses(String projectId, String env) {
-        QueryFactory queryFactory = Search.getQueryFactory(containerStatuses);
-        return queryFactory.<ContainerStatus>create("FROM karavan.ContainerStatus WHERE projectId = :projectId AND env = :env")
-                .setParameter("projectId", projectId)
-                .setParameter("env", env)
-                .execute().list();
-    }
-
-    public ContainerStatus getDevModeContainerStatuses(String projectId, String env) {
-        QueryFactory queryFactory = Search.getQueryFactory(containerStatuses);
-        List<ContainerStatus> list = queryFactory.<ContainerStatus>create("FROM karavan.ContainerStatus WHERE projectId = :projectId AND env = :env AND type = :type")
-                .setParameter("projectId", projectId)
-                .setParameter("env", env)
-                .setParameter("type", ContainerStatus.CType.devmode)
-                .execute().list();
-        return list.size() > 0 ? list.get(0) : null;
-    }
-
-    public List<ContainerStatus> getContainerStatuses(String env) {
-        QueryFactory queryFactory = Search.getQueryFactory(containerStatuses);
-        return queryFactory.<ContainerStatus>create("FROM karavan.ContainerStatus WHERE env = :env")
-                .setParameter("env", env)
-                .execute().list();
-    }
-
-    public List<ContainerStatus> getAllContainerStatuses() {
-        return new ArrayList<>(containerStatuses.values());
-    }
-
-    public void saveContainerStatus(ContainerStatus status) {
-        containerStatuses.put(GroupedKey.create(status.getProjectId(), status.getEnv(), status.getName()), status);
-    }
-
-    public void deleteContainerStatus(ContainerStatus status) {
-        containerStatuses.remove(GroupedKey.create(status.getProjectId(), status.getEnv(), status.getName()));
-    }
-
-    public void deleteContainerStatus(String projectId, String env, String containerName) {
-        containerStatuses.remove(GroupedKey.create(projectId, env, containerName));
-    }
-
-    public CamelStatus getCamelStatus(String projectId, String env, String name) {
-        GroupedKey key = GroupedKey.create(projectId, env, name);
-        return camelStatuses.get(key);
-    }
-
-    public List<CamelStatus> getCamelStatusesByEnv(String env, CamelStatus.Name name) {
-        QueryFactory queryFactory = Search.getQueryFactory(camelStatuses);
-        return queryFactory.<CamelStatus>create("FROM karavan.CamelStatus WHERE env = :env AND name = :name")
-                .setParameter("env", env)
-                .setParameter("name", name)
-                .execute().list();
-    }
-
-    public List<CamelStatus> getCamelStatusesByProjectIdEnv(String projectId, String env) {
-        QueryFactory queryFactory = Search.getQueryFactory(camelStatuses);
-        return queryFactory.<CamelStatus>create("FROM karavan.CamelStatus WHERE projectId = :projectId AND env = :env")
-                .setParameter("projectId", projectId)
-                .setParameter("env", env)
-                .execute().list();
-    }
-
-    public void saveCamelStatus(CamelStatus status) {
-        GroupedKey key = GroupedKey.create(status.getProjectId(), status.getEnv(), status.getName().name());
-        camelStatuses.put(key, status);
-    }
-
-    public void deleteCamelStatus(String projectId, String name, String env) {
-        GroupedKey key = GroupedKey.create(projectId, env, name);
-        camelStatuses.remove(key);
-    }
-
-    public void deleteCamelStatuses(String projectId, String env) {
-        Arrays.stream(CamelStatus.Name.values()).forEach(name -> {
-            GroupedKey key = GroupedKey.create(projectId, env, name.name());
-            camelStatuses.remove(key);
-        });
-    }
-
-    public void saveCommit(String commitId, int time) {
-        commits.put(commitId, String.valueOf(time));
-    }
-
-    public void saveLastCommit(String commitId) {
-        commits.put("lastCommitId", commitId);
-    }
-
-    public Tuple2<String, Integer> getLastCommit() {
-        String lastCommitId = commits.get("lastCommitId");
-        String time = commits.get(lastCommitId);
-        return Tuple2.of(lastCommitId, Integer.parseInt(time));
-    }
-
-    public boolean hasCommit(String commitId) {
-        return commits.get(commitId) != null;
-    }
-
-    public void saveDevModeStatus(DevModeStatus status) {
-        devmodeStatuses.put(GroupedKey.create(status.getProjectId(), DEFAULT_ENVIRONMENT, status.getProjectId()), status);
-    }
-
-    public void deleteDevModeStatus(String projectId) {
-        devmodeStatuses.remove(GroupedKey.create(projectId, DEFAULT_ENVIRONMENT, projectId));
-    }
-
-    public DevModeStatus getDevModeStatus(String projectId) {
-        return devmodeStatuses.get(GroupedKey.create(projectId,DEFAULT_ENVIRONMENT, projectId));
-    }
-
-    public List<DevModeStatus> getLoadedDevModeStatuses() {
-        QueryFactory queryFactory = Search.getQueryFactory(devmodeStatuses);
-        return queryFactory.<DevModeStatus>create("FROM karavan.DevModeStatus WHERE codeLoaded = true")
-                .execute().list();
-    }
-
-    public List<DevModeStatus> getDevModeStatuses() {
-       return new ArrayList<>(devmodeStatuses.values());
-    }
-
-    public void saveContainerInfo(ContainerInfo ci) {
-        containers.put(GroupedKey.create(ci.getContainerName(), ci.getEnv() != null ? ci.getEnv() : DEFAULT_ENVIRONMENT, ci.getContainerName()), ci);
-    }
-
-    public void getContainerInfo(String name, String env) {
-        containers.get(GroupedKey.create(name, env, name));
-    }
-
-    public List<ContainerInfo> getContainerInfos(String env) {
-        QueryFactory queryFactory = Search.getQueryFactory(containers);
-        return queryFactory.<ContainerInfo>create("FROM karavan.ContainerInfo WHERE env = :env")
-                .setParameter("env", env)
-                .execute().list();
-    }
-
-    public void deleteContainerInfo(String containerName) {
-        containers.remove(GroupedKey.create(containerName, DEFAULT_ENVIRONMENT, containerName));
-    }
-
-    public void clearAllStatuses() {
-        CompletableFuture.allOf(
-            deploymentStatuses.clearAsync(),
-            containerStatuses.clearAsync(),
-            pipelineStatuses.clearAsync(),
-            camelStatuses.clearAsync(),
-            devmodeStatuses.clearAsync()
-        ).join();
-    }
-
-    private String getResourceFile(String path) {
-        try {
-            InputStream inputStream = InfinispanService.class.getResourceAsStream(path);
-            return new BufferedReader(new InputStreamReader(inputStream))
-                    .lines().collect(Collectors.joining(System.getProperty("line.separator")));
-        } catch (Exception e) {
-            return null;
-        }
-    }
-}
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/CamelStatus.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/CamelStatus.java
deleted file mode 100644
index 37109261..00000000
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/CamelStatus.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package org.apache.camel.karavan.infinispan.model;
-
-import org.infinispan.protostream.annotations.ProtoEnumValue;
-import org.infinispan.protostream.annotations.ProtoFactory;
-import org.infinispan.protostream.annotations.ProtoField;
-
-public class CamelStatus {
-
-    public enum Name {
-
-        @ProtoEnumValue(number = 0, name = "context") context,
-        @ProtoEnumValue (number = 1, name = "inflight") inflight,
-        @ProtoEnumValue (number = 2, name = "memory") memory,
-        @ProtoEnumValue (number = 3, name = "properties") properties,
-        @ProtoEnumValue (number = 4, name = "route") route,
-        @ProtoEnumValue (number = 5, name = "trace") trace,
-        @ProtoEnumValue (number = 6, name = "jvm") jvm,
-        @ProtoEnumValue (number = 7, name = "source") source
-    }
-
-    public static final String CACHE = "camel_statuses";
-    @ProtoField(number = 1)
-    String projectId;
-    @ProtoField(number = 2)
-    String containerName;
-    @ProtoField(number = 3)
-    Name name;
-    @ProtoField(number = 4)
-    String status;
-    @ProtoField(number = 5)
-    String env;
-
-    @ProtoFactory
-    public CamelStatus(String projectId, String containerName, Name name, String status, String env) {
-        this.projectId = projectId;
-        this.containerName = containerName;
-        this.name = name;
-        this.status = status;
-        this.env = env;
-    }
-
-    public String getProjectId() {
-        return projectId;
-    }
-
-    public void setProjectId(String projectId) {
-        this.projectId = projectId;
-    }
-
-    public String getContainerName() {
-        return containerName;
-    }
-
-    public void setContainerName(String containerName) {
-        this.containerName = containerName;
-    }
-
-    public Name getName() {
-        return name;
-    }
-
-    public void setName(Name name) {
-        this.name = name;
-    }
-
-    public String getStatus() {
-        return status;
-    }
-
-    public void setStatus(String status) {
-        this.status = status;
-    }
-
-    public String getEnv() {
-        return env;
-    }
-
-    public void setEnv(String env) {
-        this.env = env;
-    }
-}
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/CommitInfo.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/CommitInfo.java
deleted file mode 100644
index b7ee2075..00000000
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/CommitInfo.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.apache.camel.karavan.infinispan.model;
-
-import java.util.List;
-
-public class CommitInfo {
-    private String commitId;
-    private Integer time;
-    private List<GitRepo> repos;
-
-    public CommitInfo(String commitId, Integer time) {
-        this.commitId = commitId;
-        this.time = time;
-    }
-
-    public CommitInfo(String commitId, Integer time, List<GitRepo> repos) {
-        this.commitId = commitId;
-        this.time = time;
-        this.repos = repos;
-    }
-
-    public String getCommitId() {
-        return commitId;
-    }
-
-    public void setCommitId(String commitId) {
-        this.commitId = commitId;
-    }
-
-    public Integer getTime() {
-        return time;
-    }
-
-    public void setTime(Integer time) {
-        this.time = time;
-    }
-
-    public List<GitRepo> getRepos() {
-        return repos;
-    }
-
-    public void setRepos(List<GitRepo> repos) {
-        this.repos = repos;
-    }
-
-    @Override
-    public String toString() {
-        return "CommitInfo{" +
-                "commitId='" + commitId + '\'' +
-                ", time=" + time +
-                ", repos=" + repos +
-                '}';
-    }
-}
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerInfo.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerInfo.java
deleted file mode 100644
index 985e70b3..00000000
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerInfo.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package org.apache.camel.karavan.infinispan.model;
-
-import org.infinispan.protostream.annotations.ProtoFactory;
-import org.infinispan.protostream.annotations.ProtoField;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class ContainerInfo {
-    public static final String CACHE = "container_infos";
-    @ProtoField(number = 1)
-    String containerName;
-    @ProtoField(number = 2)
-    String containerId;
-    @ProtoField(number = 3)
-    String image;
-    @ProtoField(number = 4, collectionImplementation = ArrayList.class)
-    List<Integer> ports;
-    @ProtoField(number = 5)
-    String env;
-
-    @ProtoFactory
-    public ContainerInfo(String containerName, String containerId, String image, List<Integer> ports, String env) {
-        this.containerName = containerName;
-        this.containerId = containerId;
-        this.image = image;
-        this.ports = ports;
-        this.env = env;
-    }
-
-    public String getEnv() {
-        return env;
-    }
-
-    public void setEnv(String env) {
-        this.env = env;
-    }
-
-    public String getContainerName() {
-        return containerName;
-    }
-
-    public void setContainerName(String containerName) {
-        this.containerName = containerName;
-    }
-
-    public String getContainerId() {
-        return containerId;
-    }
-
-    public void setContainerId(String containerId) {
-        this.containerId = containerId;
-    }
-
-    public String getImage() {
-        return image;
-    }
-
-    public void setImage(String image) {
-        this.image = image;
-    }
-
-    public List<Integer> getPorts() {
-        return ports;
-    }
-
-    public void setPorts(List<Integer> ports) {
-        this.ports = ports;
-    }
-}
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerStatus.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerStatus.java
deleted file mode 100644
index d8a3db89..00000000
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerStatus.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package org.apache.camel.karavan.infinispan.model;
-
-import org.infinispan.protostream.annotations.ProtoEnumValue;
-import org.infinispan.protostream.annotations.ProtoFactory;
-import org.infinispan.protostream.annotations.ProtoField;
-
-public class ContainerStatus {
-
-    public enum CType {
-        @ProtoEnumValue(number = 0, name = "devmode") devmode,
-        @ProtoEnumValue(number = 1, name = "devservice") devservice,
-        @ProtoEnumValue(number = 2, name = "pod") pod,
-        @ProtoEnumValue(number = 3, name = "container") container,
-    }
-
-    public static final String CACHE = "pod_statuses";
-    @ProtoField(number = 1)
-    String name;
-    @ProtoField(number = 2)
-    Boolean ready;
-    @ProtoField(number = 3)
-    String projectId;
-    @ProtoField(number = 4)
-    String env;
-    @ProtoField(number = 5)
-    Integer exposedPort;
-    @ProtoField(number = 6)
-    CType type;
-    @ProtoField(number = 7)
-    String memoryInfo;
-    @ProtoField(number = 8)
-    String cpuInfo;
-    @ProtoField(number = 9)
-    String created;
-
-    @ProtoFactory
-    public ContainerStatus(String name, Boolean ready, String projectId, String env, Integer exposedPort, CType type, String memoryInfo, String cpuInfo, String created) {
-        this.name = name;
-        this.ready = ready;
-        this.projectId = projectId;
-        this.env = env;
-        this.exposedPort = exposedPort;
-        this.type = type;
-        this.memoryInfo = memoryInfo;
-        this.cpuInfo = cpuInfo;
-        this.created = created;
-    }
-
-    public ContainerStatus(String name, Boolean ready, String projectId, String env, CType type, String memoryInfo, String cpuInfo, String created) {
-        this.name = name;
-        this.ready = ready;
-        this.projectId = projectId;
-        this.env = env;
-        this.memoryInfo = memoryInfo;
-        this.cpuInfo = cpuInfo;
-        this.created = created;
-        this.type = type;
-    }
-
-    public ContainerStatus(String name, Boolean ready, String projectId, String env, CType type, String created, Integer exposedPort) {
-        this.name = name;
-        this.ready = ready;
-        this.projectId = projectId;
-        this.env = env;
-        this.created = created;
-        this.exposedPort = exposedPort;
-        this.type = type;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public Boolean getReady() {
-        return ready;
-    }
-
-    public void setReady(Boolean ready) {
-        this.ready = ready;
-    }
-
-    public String getProjectId() {
-        return projectId;
-    }
-
-    public void setProjectId(String projectId) {
-        this.projectId = projectId;
-    }
-
-    public String getEnv() {
-        return env;
-    }
-
-    public void setEnv(String env) {
-        this.env = env;
-    }
-
-    public String getMemoryInfo() {
-        return memoryInfo;
-    }
-
-    public void setMemoryInfo(String memoryInfo) {
-        this.memoryInfo = memoryInfo;
-    }
-
-    public String getCpuInfo() {
-        return cpuInfo;
-    }
-
-    public void setCpuInfo(String cpuInfo) {
-        this.cpuInfo = cpuInfo;
-    }
-
-    public String getCreated() {
-        return created;
-    }
-
-    public void setCreated(String created) {
-        this.created = created;
-    }
-
-    public Integer getExposedPort() {
-        return exposedPort;
-    }
-
-    public void setExposedPort(Integer exposedPort) {
-        this.exposedPort = exposedPort;
-    }
-
-    public CType getType() {
-        return type;
-    }
-
-    public void setType(CType type) {
-        this.type = type;
-    }
-}
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/DeploymentStatus.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/DeploymentStatus.java
deleted file mode 100644
index 95e35d67..00000000
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/DeploymentStatus.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package org.apache.camel.karavan.infinispan.model;
-
-import org.infinispan.protostream.annotations.ProtoFactory;
-import org.infinispan.protostream.annotations.ProtoField;
-
-public class DeploymentStatus {
-    public static final String CACHE = "deployment_statuses";
-    @ProtoField(number = 1)
-    String projectId;
-    @ProtoField(number = 2)
-    String namespace;
-    @ProtoField(number = 3)
-    String env;
-    @ProtoField(number = 4)
-    String cluster;
-    @ProtoField(number = 5)
-    String image;
-    @ProtoField(number = 6)
-    Integer replicas;
-    @ProtoField(number = 7)
-    Integer readyReplicas;
-    @ProtoField(number = 8)
-    Integer unavailableReplicas;
-
-    public DeploymentStatus(String projectId, String namespace, String cluster, String env) {
-        this.projectId = projectId;
-        this.namespace = namespace;
-        this.cluster = cluster;
-        this.env = env;
-        this.image = "";
-        this.replicas = 0;
-        this.readyReplicas = 0;
-        this.unavailableReplicas = 0;
-    }
-
-    @ProtoFactory
-    public DeploymentStatus(String projectId, String namespace, String cluster, String env, String image, Integer replicas, Integer readyReplicas, Integer unavailableReplicas) {
-        this.projectId = projectId;
-        this.namespace = namespace;
-        this.env = env;
-        this.cluster = cluster;
-        this.image = image;
-        this.replicas = replicas;
-        this.readyReplicas = readyReplicas;
-        this.unavailableReplicas = unavailableReplicas;
-    }
-
-    public String getProjectId() {
-        return projectId;
-    }
-
-    public void setProjectId(String projectId) {
-        this.projectId = projectId;
-    }
-
-    public String getEnv() {
-        return env;
-    }
-
-    public void setEnv(String env) {
-        this.env = env;
-    }
-
-    public String getNamespace() {
-        return namespace;
-    }
-
-    public void setNamespace(String namespace) {
-        this.namespace = namespace;
-    }
-
-    public String getImage() {
-        return image;
-    }
-
-    public void setImage(String image) {
-        this.image = image;
-    }
-
-    public Integer getReplicas() {
-        return replicas;
-    }
-
-    public void setReplicas(Integer replicas) {
-        this.replicas = replicas;
-    }
-
-    public Integer getReadyReplicas() {
-        return readyReplicas;
-    }
-
-    public void setReadyReplicas(Integer readyReplicas) {
-        this.readyReplicas = readyReplicas;
-    }
-
-    public Integer getUnavailableReplicas() {
-        return unavailableReplicas;
-    }
-
-    public void setUnavailableReplicas(Integer unavailableReplicas) {
-        this.unavailableReplicas = unavailableReplicas;
-    }
-
-    public String getCluster() {
-        return cluster;
-    }
-
-    public void setCluster(String cluster) {
-        this.cluster = cluster;
-    }
-}
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/DevModeStatus.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/DevModeStatus.java
deleted file mode 100644
index c45208d3..00000000
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/DevModeStatus.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.apache.camel.karavan.infinispan.model;
-
-import org.infinispan.protostream.annotations.ProtoFactory;
-import org.infinispan.protostream.annotations.ProtoField;
-
-public class DevModeStatus {
-    public static final String CACHE = "devmode_statuses";
-    @ProtoField(number = 1)
-    String projectId;
-    @ProtoField(number = 2)
-    String containerName;
-    @ProtoField(number = 3)
-    String containerId;
-    @ProtoField(number = 4)
-    Boolean codeLoaded;
-    @ProtoField(number = 5)
-    Boolean logging;
-
-    @ProtoFactory
-    public DevModeStatus(String projectId, String containerName, String containerId, Boolean codeLoaded, Boolean logging) {
-        this.projectId = projectId;
-        this.containerName = containerName;
-        this.containerId = containerId;
-        this.codeLoaded = codeLoaded;
-        this.logging = logging;
-    }
-
-    public DevModeStatus(String projectId, String containerName, String containerId, Boolean codeLoaded) {
-        this.projectId = projectId;
-        this.containerName = containerName;
-        this.containerId = containerId;
-        this.codeLoaded = codeLoaded;
-        this.logging = false;
-    }
-
-    public DevModeStatus() {
-    }
-
-    public String getProjectId() {
-        return projectId;
-    }
-
-    public void setProjectId(String projectId) {
-        this.projectId = projectId;
-    }
-
-    public String getContainerName() {
-        return containerName;
-    }
-
-    public void setContainerName(String containerName) {
-        this.containerName = containerName;
-    }
-
-    public String getContainerId() {
-        return containerId;
-    }
-
-    public void setContainerId(String containerId) {
-        this.containerId = containerId;
-    }
-
-    public Boolean getCodeLoaded() {
-        return codeLoaded;
-    }
-
-    public void setCodeLoaded(Boolean codeLoaded) {
-        this.codeLoaded = codeLoaded;
-    }
-
-    public Boolean getLogging() {
-        return logging;
-    }
-
-    public void setLogging(Boolean logging) {
-        this.logging = logging;
-    }
-}
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/GitConfig.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/GitConfig.java
deleted file mode 100644
index 285c8017..00000000
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/GitConfig.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.apache.camel.karavan.infinispan.model;
-
-public class GitConfig {
-    private String uri;
-    private String username;
-    private String password;
-    private String branch;
-
-    public GitConfig(String uri, String username, String password, String branch) {
-        this.uri = uri;
-        this.username = username;
-        this.password = password;
-        this.branch = branch;
-    }
-
-    public String getUri() {
-        return uri;
-    }
-
-    public void setUri(String uri) {
-        this.uri = uri;
-    }
-
-    public String getUsername() {
-        return username;
-    }
-
-    public void setUsername(String username) {
-        this.username = username;
-    }
-
-    public String getPassword() {
-        return password;
-    }
-
-    public void setPassword(String password) {
-        this.password = password;
-    }
-
-    public String getBranch() {
-        return branch;
-    }
-
-    public void setBranch(String branch) {
-        this.branch = branch;
-    }
-
-}
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/GitRepo.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/GitRepo.java
deleted file mode 100644
index 4736814f..00000000
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/GitRepo.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package org.apache.camel.karavan.infinispan.model;
-
-import java.util.List;
-
-public class GitRepo {
-    private String name;
-    private String commitId;
-    private Long lastCommitTimestamp;
-    private List<GitRepoFile> files;
-
-    public GitRepo(String name, String commitId, Long lastCommitTimestamp, List<GitRepoFile> files) {
-        this.name = name;
-        this.commitId = commitId;
-        this.lastCommitTimestamp = lastCommitTimestamp;
-        this.files = files;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getCommitId() {
-        return commitId;
-    }
-
-    public void setCommitId(String commitId) {
-        this.commitId = commitId;
-    }
-
-    public Long getLastCommitTimestamp() {
-        return lastCommitTimestamp;
-    }
-
-    public void setLastCommitTimestamp(Long lastCommitTimestamp) {
-        this.lastCommitTimestamp = lastCommitTimestamp;
-    }
-
-    public List<GitRepoFile> getFiles() {
-        return files;
-    }
-
-    public void setFiles(List<GitRepoFile> files) {
-        this.files = files;
-    }
-}
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/GitRepoFile.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/GitRepoFile.java
deleted file mode 100644
index a1186efe..00000000
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/GitRepoFile.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package org.apache.camel.karavan.infinispan.model;
-
-public class GitRepoFile {
-    private String name;
-    private Long lastCommitTimestamp;
-    private String body;
-
-    public GitRepoFile(String name, Long lastCommitTimestamp, String body) {
-        this.name = name;
-        this.lastCommitTimestamp = lastCommitTimestamp;
-        this.body = body;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public Long getLastCommitTimestamp() {
-        return lastCommitTimestamp;
-    }
-
-    public void setLastCommitTimestamp(Long lastCommitTimestamp) {
-        this.lastCommitTimestamp = lastCommitTimestamp;
-    }
-
-    public String getBody() {
-        return body;
-    }
-
-    public void setBody(String body) {
-        this.body = body;
-    }
-}
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/GroupedKey.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/GroupedKey.java
deleted file mode 100644
index 1f1632ca..00000000
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/GroupedKey.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.apache.camel.karavan.infinispan.model;
-
-import org.infinispan.protostream.annotations.ProtoFactory;
-import org.infinispan.protostream.annotations.ProtoField;
-//import org.infinispan.distribution.group.Group;
-
-
-public class GroupedKey {
-
-    @ProtoField(number = 1)
-    String projectId;
-    @ProtoField(number = 2)
-    String env;
-    @ProtoField(number = 3)
-    String key;
-
-    @ProtoFactory
-    public GroupedKey(String projectId, String env, String key) {
-        this.projectId = projectId;
-        this.env = env;
-        this.key = key;
-    }
-
-    public static GroupedKey create(String projectId, String env, String key) {
-        return new GroupedKey(projectId, env, key);
-    }
-
-    public String getEnv() {
-        return env;
-    }
-
-    public void setEnv(String env) {
-        this.env = env;
-    }
-
-    public void setProjectId(String projectId) {
-        this.projectId = projectId;
-    }
-
-    public String getKey() {
-        return key;
-    }
-
-    public void setKey(String key) {
-        this.key = key;
-    }
-
-//    @Group https://github.com/quarkusio/quarkus/issues/34677
-    public String getProjectId() {
-        return projectId;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        GroupedKey that = (GroupedKey) o;
-
-        if (!projectId.equals(that.projectId)) return false;
-        if (!env.equals(that.env)) return false;
-        return key.equals(that.key);
-    }
-
-    @Override
-    public int hashCode() {
-        int result = projectId.hashCode();
-        result = 31 * result + env.hashCode();
-        result = 31 * result + key.hashCode();
-        return result;
-    }
-}
\ No newline at end of file
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/KaravanSchema.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/KaravanSchema.java
deleted file mode 100644
index 1b2777ca..00000000
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/KaravanSchema.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.apache.camel.karavan.infinispan.model;
-
-import org.infinispan.protostream.GeneratedSchema;
-import org.infinispan.protostream.annotations.AutoProtoSchemaBuilder;
-
-@AutoProtoSchemaBuilder(
-        includeClasses = {
-                GroupedKey.class,
-                Project.class,
-                Project.Type.class,
-                ProjectFile.class,
-                PipelineStatus.class,
-                CamelStatus.class,
-                CamelStatus.Name.class,
-                DeploymentStatus.class,
-                ContainerStatus.class,
-                ContainerStatus.CType.class,
-                ServiceStatus.class,
-                DevModeStatus.class,
-                ContainerInfo.class
-        },
-        schemaFileName = "karavan.proto",
-        schemaFilePath = "proto/",
-        schemaPackageName = "karavan")
-public interface KaravanSchema extends GeneratedSchema {
-}
-
-
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/PipelineStatus.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/PipelineStatus.java
deleted file mode 100644
index fd0831d0..00000000
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/PipelineStatus.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package org.apache.camel.karavan.infinispan.model;
-
-import org.infinispan.protostream.annotations.ProtoFactory;
-import org.infinispan.protostream.annotations.ProtoField;
-
-public class PipelineStatus {
-    public static final String CACHE = "pipeline_statuses";
-    @ProtoField(number = 1)
-    String projectId;
-    @ProtoField(number = 2)
-    String pipelineName;
-    @ProtoField(number = 3)
-    String result;
-    @ProtoField(number = 5)
-    String startTime;
-    @ProtoField(number = 6)
-    String completionTime;
-    @ProtoField(number = 7)
-    String env;
-
-    @ProtoFactory
-    public PipelineStatus(String projectId, String pipelineName, String result, String startTime, String completionTime, String env) {
-        this.projectId = projectId;
-        this.pipelineName = pipelineName;
-        this.result = result;
-        this.startTime = startTime;
-        this.completionTime = completionTime;
-        this.env = env;
-    }
-
-    public PipelineStatus(String projectId, String env) {
-        this.projectId = projectId;
-        this.env = env;
-    }
-
-    public String getProjectId() {
-        return projectId;
-    }
-
-    public void setProjectId(String projectId) {
-        this.projectId = projectId;
-    }
-
-    public String getPipelineName() {
-        return pipelineName;
-    }
-
-    public void setPipelineName(String pipelineName) {
-        this.pipelineName = pipelineName;
-    }
-
-    public String getResult() {
-        return result;
-    }
-
-    public void setResult(String result) {
-        this.result = result;
-    }
-
-    public String getStartTime() {
-        return startTime;
-    }
-
-    public void setStartTime(String startTime) {
-        this.startTime = startTime;
-    }
-
-    public String getCompletionTime() {
-        return completionTime;
-    }
-
-    public void setCompletionTime(String completionTime) {
-        this.completionTime = completionTime;
-    }
-
-    public String getEnv() {
-        return env;
-    }
-
-    public void setEnv(String env) {
-        this.env = env;
-    }
-}
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/Project.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/Project.java
deleted file mode 100644
index 9c31e296..00000000
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/Project.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package org.apache.camel.karavan.infinispan.model;
-
-import org.infinispan.protostream.annotations.ProtoEnumValue;
-import org.infinispan.protostream.annotations.ProtoFactory;
-import org.infinispan.protostream.annotations.ProtoField;
-
-import java.time.Instant;
-
-public class Project {
-    public static final String CACHE = "projects";
-
-    public enum Type {
-
-        @ProtoEnumValue(number = 0, name = "templates") templates,
-        @ProtoEnumValue (number = 1, name = "kamelets") kamelets,
-        @ProtoEnumValue (number = 2, name = "services") services,
-        @ProtoEnumValue (number = 3, name = "pipelines") pipelines,
-        @ProtoEnumValue (number = 4, name = "normal") normal,
-    }
-
-    @ProtoField(number = 1)
-    String projectId;
-    @ProtoField(number = 2)
-    String name;
-    @ProtoField(number = 3)
-    String description;
-    @ProtoField(number = 4)
-    String runtime;
-    @ProtoField(number = 5)
-    String lastCommit;
-    @ProtoField(number = 6)
-    Long lastCommitTimestamp;
-    @ProtoField(number = 7)
-    Type type;
-
-    @ProtoFactory
-    public Project(String projectId, String name, String description, String runtime, String lastCommit, Long lastCommitTimestamp, Type type) {
-        this.projectId = projectId;
-        this.name = name;
-        this.description = description;
-        this.runtime = runtime;
-        this.lastCommit = lastCommit;
-        this.lastCommitTimestamp = lastCommitTimestamp;
-        this.type = type;
-    }
-
-    public Project(String projectId, String name, String description, String runtime, String lastCommit, Long lastCommitTimestamp) {
-        this.projectId = projectId;
-        this.name = name;
-        this.description = description;
-        this.runtime = runtime;
-        this.lastCommit = lastCommit;
-        this.lastCommitTimestamp = lastCommitTimestamp;
-        this.type = Type.normal;
-    }
-
-    public Project(String projectId, String name, String description, String runtime) {
-        this.projectId = projectId;
-        this.name = name;
-        this.description = description;
-        this.runtime = runtime;
-        this.lastCommitTimestamp = Instant.now().toEpochMilli();
-        this.type = Type.normal;
-    }
-
-    public Project() {
-        this.type = Type.normal;
-    }
-
-    public String getProjectId() {
-        return projectId;
-    }
-
-    public void setProjectId(String projectId) {
-        this.projectId = projectId;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    public String getRuntime() {
-        return runtime;
-    }
-
-    public void setRuntime(String runtime) {
-        this.runtime = runtime;
-    }
-
-    public String getLastCommit() {
-        return lastCommit;
-    }
-
-    public void setLastCommit(String lastCommit) {
-        this.lastCommit = lastCommit;
-    }
-
-    public Long getLastCommitTimestamp() {
-        return lastCommitTimestamp;
-    }
-
-    public void setLastCommitTimestamp(Long lastCommitTimestamp) {
-        this.lastCommitTimestamp = lastCommitTimestamp;
-    }
-
-    public Type getType() {
-        return type;
-    }
-
-    public void setType(Type type) {
-        this.type = type;
-    }
-}
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/ProjectFile.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/ProjectFile.java
deleted file mode 100644
index 14cc3adf..00000000
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/ProjectFile.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.apache.camel.karavan.infinispan.model;
-
-import org.infinispan.protostream.annotations.ProtoDoc;
-import org.infinispan.protostream.annotations.ProtoFactory;
-import org.infinispan.protostream.annotations.ProtoField;
-
-public class ProjectFile {
-    public static final String CACHE = "project_files";
-    @ProtoField(number = 1)
-    String name;
-    @ProtoField(number = 2)
-    String code;
-    @ProtoField(number = 3)
-    @ProtoDoc("@Field(index=Index.YES, analyze = Analyze.YES, store = Store.NO)")
-    String projectId;
-    @ProtoField(number = 4)
-    Long lastUpdate;
-
-    @ProtoFactory
-    public ProjectFile(String name, String code, String projectId, Long lastUpdate) {
-        this.name = name;
-        this.code = code;
-        this.projectId = projectId;
-        this.lastUpdate = lastUpdate;
-    }
-
-    public ProjectFile() {
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getCode() {
-        return code;
-    }
-
-    public void setCode(String code) {
-        this.code = code;
-    }
-
-    public String getProjectId() {
-        return projectId;
-    }
-
-    public void setProjectId(String projectId) {
-        this.projectId = projectId;
-    }
-
-    public Long getLastUpdate() {
-        return lastUpdate;
-    }
-
-    public void setLastUpdate(Long lastUpdate) {
-        this.lastUpdate = lastUpdate;
-    }
-
-    @Override
-    public String toString() {
-        return "ProjectFile{" +
-                "name='" + name + '\'' +
-                ", code='" + code + '\'' +
-                ", projectId='" + projectId + '\'' +
-                ", lastUpdate=" + lastUpdate +
-                '}';
-    }
-}
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/ServiceStatus.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/ServiceStatus.java
deleted file mode 100644
index 9ce1d073..00000000
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/ServiceStatus.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package org.apache.camel.karavan.infinispan.model;
-
-import org.infinispan.protostream.annotations.ProtoFactory;
-import org.infinispan.protostream.annotations.ProtoField;
-
-public class ServiceStatus {
-    public static final String CACHE = "service_statuses";
-    @ProtoField(number = 1)
-    String projectId;
-    @ProtoField(number = 2)
-    String namespace;
-    @ProtoField(number = 3)
-    String env;
-    @ProtoField(number = 4)
-    String cluster;
-    @ProtoField(number = 5)
-    Integer port;
-    @ProtoField(number = 6)
-    Integer targetPort;
-    @ProtoField(number = 7)
-    String clusterIP;
-    @ProtoField(number = 8)
-    String type;
-
-    @ProtoFactory
-    public ServiceStatus(String projectId, String namespace, String env, String cluster, Integer port, Integer targetPort, String clusterIP, String type) {
-        this.projectId = projectId;
-        this.namespace = namespace;
-        this.env = env;
-        this.cluster = cluster;
-        this.port = port;
-        this.targetPort = targetPort;
-        this.clusterIP = clusterIP;
-        this.type = type;
-    }
-
-    public ServiceStatus(String projectId, String namespace, String cluster, String env) {
-        this.projectId = projectId;
-        this.namespace = namespace;
-        this.env = env;
-        this.cluster = cluster;
-    }
-
-    public String getProjectId() {
-        return projectId;
-    }
-
-    public void setProjectId(String projectId) {
-        this.projectId = projectId;
-    }
-
-    public String getNamespace() {
-        return namespace;
-    }
-
-    public void setNamespace(String namespace) {
-        this.namespace = namespace;
-    }
-
-    public String getEnv() {
-        return env;
-    }
-
-    public void setEnv(String env) {
-        this.env = env;
-    }
-
-    public String getCluster() {
-        return cluster;
-    }
-
-    public void setCluster(String cluster) {
-        this.cluster = cluster;
-    }
-
-    public Integer getPort() {
-        return port;
-    }
-
-    public void setPort(Integer port) {
-        this.port = port;
-    }
-
-    public Integer getTargetPort() {
-        return targetPort;
-    }
-
-    public void setTargetPort(Integer targetPort) {
-        this.targetPort = targetPort;
-    }
-
-    public String getClusterIP() {
-        return clusterIP;
-    }
-
-    public void setClusterIP(String clusterIP) {
-        this.clusterIP = clusterIP;
-    }
-
-    public String getType() {
-        return type;
-    }
-
-    public void setType(String type) {
-        this.type = type;
-    }
-}
diff --git a/karavan-web/karavan-app/src/main/resources/cache/command-cache-config.xml b/karavan-web/karavan-app/src/main/resources/cache/command-cache-config.xml
deleted file mode 100644
index 27481642..00000000
--- a/karavan-web/karavan-app/src/main/resources/cache/command-cache-config.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<distributed-cache name="%s" mode="SYNC">
-    <encoding media-type="application/x-protostream"/>
-    <locking isolation="REPEATABLE_READ"/>
-    <groups enabled="true"/>
-    <memory max-count="100000" when-full="REMOVE"/>
-</distributed-cache>
\ No newline at end of file
diff --git a/karavan-web/karavan-app/src/main/resources/cache/data-cache-config.xml b/karavan-web/karavan-app/src/main/resources/cache/data-cache-config.xml
deleted file mode 100644
index 31f6c304..00000000
--- a/karavan-web/karavan-app/src/main/resources/cache/data-cache-config.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<distributed-cache name="%s" mode="SYNC">
-    <encoding media-type="application/x-protostream"/>
-    <locking isolation="REPEATABLE_READ"/>
-    <groups enabled="true"/>
-    <memory max-count="1000000" when-full="REMOVE"/>
-</distributed-cache>
\ No newline at end of file
diff --git a/karavan-web/karavan-app/src/test/java/org/apache/camel/karavan/infinispan/DataGridTest.java b/karavan-web/karavan-app/src/test/java/org/apache/camel/karavan/infinispan/DataGridTest.java
deleted file mode 100644
index e19bb048..00000000
--- a/karavan-web/karavan-app/src/test/java/org/apache/camel/karavan/infinispan/DataGridTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.apache.camel.karavan.infinispan;
-
-
-import io.quarkus.test.junit.QuarkusTest;
-import org.apache.camel.karavan.infinispan.model.CamelStatus;
-import org.apache.camel.karavan.infinispan.model.ContainerInfo;
-import org.apache.camel.karavan.infinispan.model.ProjectFile;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestInstance;
-
-import javax.inject.Inject;
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-@QuarkusTest
-@TestInstance(TestInstance.Lifecycle.PER_CLASS)
-public class DataGridTest {
-
-    @Inject
-    InfinispanService infinispanService;
-
-    @BeforeAll
-    public void setup() {
-        infinispanService.start();
-    }
-
-    @Test
-    public void testContainersStatuses() throws InterruptedException {
-        ContainerInfo ci = new ContainerInfo("demo", "id", "image", List.of(8080, 8081, 8082), "dev");
-        infinispanService.saveContainerInfo(ci);
-        List<ContainerInfo> list = infinispanService.getContainerInfos("dev");
-        System.out.println(list);
-        assertEquals(1, list.size());
-    }
-
-    @Test
-    public void testProjectFiles() throws InterruptedException {
-        List<ProjectFile> files = infinispanService.getProjectFiles("xxx");
-        assertEquals(0, files.size());
-    }
-
-    @Test
-    public void testCamelStatuses() throws InterruptedException {
-        CamelStatus cs = new CamelStatus("test1", "container1", CamelStatus.Name.context, "", "dev");
-        infinispanService.saveCamelStatus(cs);
-        List<CamelStatus> list = infinispanService.getCamelStatusesByEnv("dev", CamelStatus.Name.context);
-        System.out.println(list);
-        assertEquals(1, list.size());
-    }
-}
diff --git a/karavan-web/karavan-app/src/test/resources/application.properties b/karavan-web/karavan-app/src/test/resources/application.properties
deleted file mode 100644
index 0eacb003..00000000
--- a/karavan-web/karavan-app/src/test/resources/application.properties
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-#%test.quarkus.infinispan-client.hosts=infinispan:11222
-#%test.quarkus.infinispan-client.username=admin
-#%test.quarkus.infinispan-client.password=password
-#
-#%test.quarkus.infinispan-client.devservices.enabled=true
-#%test.quarkus.infinispan-client.devservices.service-name=infinispan
-#%test.quarkus.infinispan-client.devservices.image-name=quay.io/infinispan/server:14.0.6.Final
-#%test.quarkus.infinispan-client.devservices.port=11222
-#%test.quarkus.infinispan-client.health.enabled=false
-#%test.quarkus.infinispan-client.client-intelligence=BASIC
diff --git a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerStatus.java b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerStatus.java
index d8a3db89..f9204ec8 100644
--- a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerStatus.java
+++ b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerStatus.java
@@ -23,47 +23,32 @@ public class ContainerStatus {
     @ProtoField(number = 4)
     String env;
     @ProtoField(number = 5)
-    Integer exposedPort;
-    @ProtoField(number = 6)
     CType type;
-    @ProtoField(number = 7)
+    @ProtoField(number = 6)
     String memoryInfo;
-    @ProtoField(number = 8)
+    @ProtoField(number = 7)
     String cpuInfo;
-    @ProtoField(number = 9)
+    @ProtoField(number = 8)
     String created;
 
     @ProtoFactory
-    public ContainerStatus(String name, Boolean ready, String projectId, String env, Integer exposedPort, CType type, String memoryInfo, String cpuInfo, String created) {
-        this.name = name;
-        this.ready = ready;
-        this.projectId = projectId;
-        this.env = env;
-        this.exposedPort = exposedPort;
-        this.type = type;
-        this.memoryInfo = memoryInfo;
-        this.cpuInfo = cpuInfo;
-        this.created = created;
-    }
-
     public ContainerStatus(String name, Boolean ready, String projectId, String env, CType type, String memoryInfo, String cpuInfo, String created) {
         this.name = name;
         this.ready = ready;
         this.projectId = projectId;
         this.env = env;
+        this.type = type;
         this.memoryInfo = memoryInfo;
         this.cpuInfo = cpuInfo;
         this.created = created;
-        this.type = type;
     }
 
-    public ContainerStatus(String name, Boolean ready, String projectId, String env, CType type, String created, Integer exposedPort) {
+    public ContainerStatus(String name, Boolean ready, String projectId, String env, CType type, String created) {
         this.name = name;
         this.ready = ready;
         this.projectId = projectId;
         this.env = env;
         this.created = created;
-        this.exposedPort = exposedPort;
         this.type = type;
     }
 
@@ -123,14 +108,6 @@ public class ContainerStatus {
         this.created = created;
     }
 
-    public Integer getExposedPort() {
-        return exposedPort;
-    }
-
-    public void setExposedPort(Integer exposedPort) {
-        this.exposedPort = exposedPort;
-    }
-
     public CType getType() {
         return type;
     }


[camel-karavan] 04/05: karavan-headless #817

Posted by ma...@apache.org.
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

commit 333d04f079a16475f5ac36c82bc4c2865d87654f
Author: Marat Gubaidullin <ma...@gmail.com>
AuthorDate: Fri Jul 21 21:19:01 2023 -0400

    karavan-headless #817
---
 .../camel/karavan/headless/CamelService.java       | 38 ++++++++--------------
 1 file changed, 13 insertions(+), 25 deletions(-)

diff --git a/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/CamelService.java b/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/CamelService.java
index e26a697f..22372f0d 100644
--- a/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/CamelService.java
+++ b/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/CamelService.java
@@ -16,7 +16,6 @@
  */
 package org.apache.camel.karavan.headless;
 
-import io.quarkus.vertx.ConsumeEvent;
 import io.vertx.core.json.JsonObject;
 import io.vertx.mutiny.core.Vertx;
 import io.vertx.mutiny.core.buffer.Buffer;
@@ -70,9 +69,8 @@ public class CamelService {
         LOGGER.info("Reload project code " + projectId);
         try {
             ContainerStatus containerStatus = infinispanService.getDevModeContainerStatuses(projectId, environment);
-            Integer exposedPort = containerStatus.getExposedPort();
-            infinispanService.getProjectFiles(projectId).forEach(projectFile -> putRequest(projectId,exposedPort, projectFile.getName(), projectFile.getCode(), 1000));
-            reloadRequest(projectId, exposedPort);
+            infinispanService.getProjectFiles(projectId).forEach(projectFile -> putRequest(projectId, projectFile.getName(), projectFile.getCode(), 1000));
+            reloadRequest(projectId);
             DevModeStatus dms = infinispanService.getDevModeStatus(projectId);
             dms.setCodeLoaded(true);
             infinispanService.saveDevModeStatus(dms);
@@ -82,9 +80,9 @@ public class CamelService {
     }
 
     @CircuitBreaker(requestVolumeThreshold = 10, failureRatio = 0.5, delay = 1000)
-    public boolean putRequest(String containerName, Integer exposedPort, String fileName, String body, int timeout) {
+    public boolean putRequest(String containerName, String fileName, String body, int timeout) {
         try {
-            String url = getContainerAddress(containerName, exposedPort) + "/q/upload/" + fileName;
+            String url = getContainerAddress(containerName) + "/q/upload/" + fileName;
             HttpResponse<Buffer> result = getWebClient().putAbs(url)
                     .timeout(timeout).sendBuffer(Buffer.buffer(body)).subscribeAsCompletionStage().toCompletableFuture().get();
             return result.statusCode() == 200;
@@ -94,8 +92,8 @@ public class CamelService {
         return false;
     }
 
-    public void reloadRequest(String containerName, Integer exposedPort) {
-        String url = getContainerAddress(containerName, exposedPort) + "/q/dev/reload?reload=true";
+    public void reloadRequest(String containerName) {
+        String url = getContainerAddress(containerName) + "/q/dev/reload?reload=true";
         try {
             result(url, 1000);
         } catch (InterruptedException | ExecutionException e) {
@@ -103,14 +101,14 @@ public class CamelService {
         }
     }
 
-    public String getContainerAddress(String containerName, Integer exposedPort) {
-        return "http://localhost:" + exposedPort;
+    public String getContainerAddress(String containerName) {
+        return "http://localhost:8080";
     }
 
     public void collectCamelStatuses() {
         if (infinispanService.isReady()) {
             infinispanService.getContainerStatuses(environment).forEach(pod -> {
-                CamelStatusRequest csr = new CamelStatusRequest(pod.getProjectId(), pod.getName(), pod.getExposedPort());
+                CamelStatusRequest csr = new CamelStatusRequest(pod.getProjectId(), pod.getName());
                 eventBus.publish(CMD_COLLECT_CAMEL_STATUS, JsonObject.mapFrom(csr));
             });
         }
@@ -120,8 +118,7 @@ public class CamelService {
         CamelStatusRequest dms = data.mapTo(CamelStatusRequest.class);
         Arrays.stream(CamelStatus.Name.values()).forEach(statusName -> {
             String containerName = dms.getContainerName();
-            Integer exposedPort = dms.getExposedPort();
-            String status = getCamelStatus(containerName, exposedPort, statusName);
+            String status = getCamelStatus(containerName, statusName);
             if (status != null) {
                 CamelStatus cs = new CamelStatus(dms.getProjectId(), containerName, statusName, status, environment);
                 infinispanService.saveCamelStatus(cs);
@@ -164,8 +161,8 @@ public class CamelService {
         }
     }
 
-    public String getCamelStatus(String podName, Integer exposedPort, CamelStatus.Name statusName) {
-        String url = getContainerAddress(podName, exposedPort) + "/q/dev/" + statusName.name();
+    public String getCamelStatus(String podName, CamelStatus.Name statusName) {
+        String url = getContainerAddress(podName) + "/q/dev/" + statusName.name();
         try {
             return result(url, 500);
         } catch (InterruptedException | ExecutionException e) {
@@ -192,15 +189,13 @@ public class CamelService {
     public static class CamelStatusRequest {
         private String projectId;
         private String containerName;
-        private Integer exposedPort;
 
         public CamelStatusRequest() {
         }
 
-        public CamelStatusRequest(String projectId, String containerName, Integer exposedPort) {
+        public CamelStatusRequest(String projectId, String containerName) {
             this.projectId = projectId;
             this.containerName = containerName;
-            this.exposedPort = exposedPort;
         }
 
         public String getProjectId() {
@@ -219,12 +214,5 @@ public class CamelService {
             this.containerName = containerName;
         }
 
-        public Integer getExposedPort() {
-            return exposedPort;
-        }
-
-        public void setExposedPort(Integer exposedPort) {
-            this.exposedPort = exposedPort;
-        }
     }
 }
\ No newline at end of file


[camel-karavan] 02/05: karavan-headless #817

Posted by ma...@apache.org.
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

commit fc9c11fbbebad3c006ee9344f2718bf4f68a8558
Author: Marat Gubaidullin <ma...@gmail.com>
AuthorDate: Fri Jul 21 20:59:25 2023 -0400

    karavan-headless #817
---
 karavan-web/karavan-headless/.dockerignore         |   6 +
 .../.mvn/wrapper/maven-wrapper.properties          |  18 ++
 .../Dockerfile.distroless.dockerignore             |   6 +
 karavan-web/karavan-headless/mvnw                  | 308 +++++++++++++++++++++
 karavan-web/karavan-headless/mvnw.cmd              | 205 ++++++++++++++
 karavan-web/karavan-headless/pom.xml               | 126 +++++++++
 .../src/main/docker/Dockerfile.distroless          |  18 ++
 .../camel/karavan/headless/CamelService.java       | 230 +++++++++++++++
 .../camel/karavan/headless/EventService.java       |  52 ++++
 .../camel/karavan/headless/HeadlessService.java    |  54 ++++
 .../src/main/resources/application.properties      |  14 +
 11 files changed, 1037 insertions(+)

diff --git a/karavan-web/karavan-headless/.dockerignore b/karavan-web/karavan-headless/.dockerignore
new file mode 100644
index 00000000..855da0f3
--- /dev/null
+++ b/karavan-web/karavan-headless/.dockerignore
@@ -0,0 +1,6 @@
+*
+!target/*-runner
+!target/*-runner.jar
+!target/lib/*
+!target/quarkus-app/*
+src/*
\ No newline at end of file
diff --git a/karavan-web/karavan-headless/.mvn/wrapper/maven-wrapper.properties b/karavan-web/karavan-headless/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 00000000..70f4f50f
--- /dev/null
+++ b/karavan-web/karavan-headless/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,18 @@
+# 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.
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.8/apache-maven-3.8.8-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
diff --git a/karavan-web/karavan-headless/Dockerfile.distroless.dockerignore b/karavan-web/karavan-headless/Dockerfile.distroless.dockerignore
new file mode 100644
index 00000000..855da0f3
--- /dev/null
+++ b/karavan-web/karavan-headless/Dockerfile.distroless.dockerignore
@@ -0,0 +1,6 @@
+*
+!target/*-runner
+!target/*-runner.jar
+!target/lib/*
+!target/quarkus-app/*
+src/*
\ No newline at end of file
diff --git a/karavan-web/karavan-headless/mvnw b/karavan-web/karavan-headless/mvnw
new file mode 100755
index 00000000..8d937f4c
--- /dev/null
+++ b/karavan-web/karavan-headless/mvnw
@@ -0,0 +1,308 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# 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.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.2.0
+#
+# Required ENV vars:
+# ------------------
+#   JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+#   MAVEN_OPTS - parameters passed to the Java VM when running Maven
+#     e.g. to debug Maven itself, use
+#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+  if [ -f /usr/local/etc/mavenrc ] ; then
+    . /usr/local/etc/mavenrc
+  fi
+
+  if [ -f /etc/mavenrc ] ; then
+    . /etc/mavenrc
+  fi
+
+  if [ -f "$HOME/.mavenrc" ] ; then
+    . "$HOME/.mavenrc"
+  fi
+
+fi
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "$(uname)" in
+  CYGWIN*) cygwin=true ;;
+  MINGW*) mingw=true;;
+  Darwin*) darwin=true
+    # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+    # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+    if [ -z "$JAVA_HOME" ]; then
+      if [ -x "/usr/libexec/java_home" ]; then
+        JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
+      else
+        JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
+      fi
+    fi
+    ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+  if [ -r /etc/gentoo-release ] ; then
+    JAVA_HOME=$(java-config --jre-home)
+  fi
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+  [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
+    JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+  javaExecutable="$(which javac)"
+  if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
+    # readlink(1) is not available as standard on Solaris 10.
+    readLink=$(which readlink)
+    if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
+      if $darwin ; then
+        javaHome="$(dirname "\"$javaExecutable\"")"
+        javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
+      else
+        javaExecutable="$(readlink -f "\"$javaExecutable\"")"
+      fi
+      javaHome="$(dirname "\"$javaExecutable\"")"
+      javaHome=$(expr "$javaHome" : '\(.*\)/bin')
+      JAVA_HOME="$javaHome"
+      export JAVA_HOME
+    fi
+  fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+  if [ -n "$JAVA_HOME"  ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+      # IBM's JDK on AIX uses strange locations for the executables
+      JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+      JAVACMD="$JAVA_HOME/bin/java"
+    fi
+  else
+    JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
+  fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+  echo "Error: JAVA_HOME is not defined correctly." >&2
+  echo "  We cannot execute $JAVACMD" >&2
+  exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+  echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+  if [ -z "$1" ]
+  then
+    echo "Path not specified to find_maven_basedir"
+    return 1
+  fi
+
+  basedir="$1"
+  wdir="$1"
+  while [ "$wdir" != '/' ] ; do
+    if [ -d "$wdir"/.mvn ] ; then
+      basedir=$wdir
+      break
+    fi
+    # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+    if [ -d "${wdir}" ]; then
+      wdir=$(cd "$wdir/.." || exit 1; pwd)
+    fi
+    # end of workaround
+  done
+  printf '%s' "$(cd "$basedir" || exit 1; pwd)"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+  if [ -f "$1" ]; then
+    # Remove \r in case we run on Windows within Git Bash
+    # and check out the repository with auto CRLF management
+    # enabled. Otherwise, we may read lines that are delimited with
+    # \r\n and produce $'-Xarg\r' rather than -Xarg due to word
+    # splitting rules.
+    tr -s '\r\n' ' ' < "$1"
+  fi
+}
+
+log() {
+  if [ "$MVNW_VERBOSE" = true ]; then
+    printf '%s\n' "$1"
+  fi
+}
+
+BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
+if [ -z "$BASE_DIR" ]; then
+  exit 1;
+fi
+
+MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
+log "$MAVEN_PROJECTBASEDIR"
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
+if [ -r "$wrapperJarPath" ]; then
+    log "Found $wrapperJarPath"
+else
+    log "Couldn't find $wrapperJarPath, downloading it ..."
+
+    if [ -n "$MVNW_REPOURL" ]; then
+      wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+    else
+      wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+    fi
+    while IFS="=" read -r key value; do
+      # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
+      safeValue=$(echo "$value" | tr -d '\r')
+      case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
+      esac
+    done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+    log "Downloading from: $wrapperUrl"
+
+    if $cygwin; then
+      wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
+    fi
+
+    if command -v wget > /dev/null; then
+        log "Found wget ... using wget"
+        [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
+        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+            wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+        else
+            wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+        fi
+    elif command -v curl > /dev/null; then
+        log "Found curl ... using curl"
+        [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
+        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+            curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+        else
+            curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+        fi
+    else
+        log "Falling back to using Java to download"
+        javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
+        javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
+        # For Cygwin, switch paths to Windows format before running javac
+        if $cygwin; then
+          javaSource=$(cygpath --path --windows "$javaSource")
+          javaClass=$(cygpath --path --windows "$javaClass")
+        fi
+        if [ -e "$javaSource" ]; then
+            if [ ! -e "$javaClass" ]; then
+                log " - Compiling MavenWrapperDownloader.java ..."
+                ("$JAVA_HOME/bin/javac" "$javaSource")
+            fi
+            if [ -e "$javaClass" ]; then
+                log " - Running MavenWrapperDownloader.java ..."
+                ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
+            fi
+        fi
+    fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+# If specified, validate the SHA-256 sum of the Maven wrapper jar file
+wrapperSha256Sum=""
+while IFS="=" read -r key value; do
+  case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
+  esac
+done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+if [ -n "$wrapperSha256Sum" ]; then
+  wrapperSha256Result=false
+  if command -v sha256sum > /dev/null; then
+    if echo "$wrapperSha256Sum  $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
+      wrapperSha256Result=true
+    fi
+  elif command -v shasum > /dev/null; then
+    if echo "$wrapperSha256Sum  $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
+      wrapperSha256Result=true
+    fi
+  else
+    echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
+    echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
+    exit 1
+  fi
+  if [ $wrapperSha256Result = false ]; then
+    echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
+    echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
+    echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
+    exit 1
+  fi
+fi
+
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
+  [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+    MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+# shellcheck disable=SC2086 # safe args
+exec "$JAVACMD" \
+  $MAVEN_OPTS \
+  $MAVEN_DEBUG_OPTS \
+  -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+  "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/karavan-web/karavan-headless/mvnw.cmd b/karavan-web/karavan-headless/mvnw.cmd
new file mode 100644
index 00000000..f80fbad3
--- /dev/null
+++ b/karavan-web/karavan-headless/mvnw.cmd
@@ -0,0 +1,205 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements.  See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership.  The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License.  You may obtain a copy of the License at
+@REM
+@REM    http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied.  See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Apache Maven Wrapper startup batch script, version 3.2.0
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM     e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on"  echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+    IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Found %WRAPPER_JAR%
+    )
+) else (
+    if not "%MVNW_REPOURL%" == "" (
+        SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+    )
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Couldn't find %WRAPPER_JAR%, downloading it ...
+        echo Downloading from: %WRAPPER_URL%
+    )
+
+    powershell -Command "&{"^
+		"$webclient = new-object System.Net.WebClient;"^
+		"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+		"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+		"}"^
+		"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
+		"}"
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Finished downloading %WRAPPER_JAR%
+    )
+)
+@REM End of extension
+
+@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
+SET WRAPPER_SHA_256_SUM=""
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+    IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
+)
+IF NOT %WRAPPER_SHA_256_SUM%=="" (
+    powershell -Command "&{"^
+       "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
+       "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
+       "  Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
+       "  Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
+       "  Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
+       "  exit 1;"^
+       "}"^
+       "}"
+    if ERRORLEVEL 1 goto error
+)
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+  %JVM_CONFIG_MAVEN_PROPS% ^
+  %MAVEN_OPTS% ^
+  %MAVEN_DEBUG_OPTS% ^
+  -classpath %WRAPPER_JAR% ^
+  "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+  %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/karavan-web/karavan-headless/pom.xml b/karavan-web/karavan-headless/pom.xml
new file mode 100644
index 00000000..9c1b5eb6
--- /dev/null
+++ b/karavan-web/karavan-headless/pom.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>karavan-headless</artifactId>
+    <parent>
+        <groupId>org.apache.camel.karavan</groupId>
+        <artifactId>karavan-web</artifactId>
+        <version>3.21.1-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.camel.karavan</groupId>
+            <artifactId>karavan-infinispan</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-smallrye-reactive-messaging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-scheduler</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.smallrye.reactive</groupId>
+            <artifactId>smallrye-mutiny-vertx-web-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-smallrye-fault-tolerance</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-arc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-container-image-docker</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-junit5</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.rest-assured</groupId>
+            <artifactId>rest-assured</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>${quarkus.platform.group-id}</groupId>
+                <artifactId>quarkus-maven-plugin</artifactId>
+                <version>${quarkus.platform.version}</version>
+                <extensions>true</extensions>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>build</goal>
+                            <goal>generate-code</goal>
+                            <goal>generate-code-tests</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>${compiler-plugin.version}</version>
+                <configuration>
+                    <parameters>${maven.compiler.parameters}</parameters>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>${surefire-plugin.version}</version>
+                <configuration>
+                    <systemPropertyVariables>
+                        <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
+                        <maven.home>${maven.home}</maven.home>
+                    </systemPropertyVariables>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <repositories>
+        <repository>
+            <id>apache.snapshots</id>
+            <name>Apache Development Snapshot Repository</name>
+            <url>https://repository.apache.org/content/repositories/snapshots/</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+</project>
diff --git a/karavan-web/karavan-headless/src/main/docker/Dockerfile.distroless b/karavan-web/karavan-headless/src/main/docker/Dockerfile.distroless
new file mode 100644
index 00000000..2e9ab688
--- /dev/null
+++ b/karavan-web/karavan-headless/src/main/docker/Dockerfile.distroless
@@ -0,0 +1,18 @@
+# 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 gcr.io/distroless/java:11
+COPY target/*-runner.jar /deployments/karavan.jar
+WORKDIR /deployments
+CMD ["karavan.jar"]
\ No newline at end of file
diff --git a/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/CamelService.java b/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/CamelService.java
new file mode 100644
index 00000000..e26a697f
--- /dev/null
+++ b/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/CamelService.java
@@ -0,0 +1,230 @@
+/*
+ * 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.karavan.headless;
+
+import io.quarkus.vertx.ConsumeEvent;
+import io.vertx.core.json.JsonObject;
+import io.vertx.mutiny.core.Vertx;
+import io.vertx.mutiny.core.buffer.Buffer;
+import io.vertx.mutiny.core.eventbus.EventBus;
+import io.vertx.mutiny.ext.web.client.HttpResponse;
+import io.vertx.mutiny.ext.web.client.WebClient;
+import org.apache.camel.karavan.infinispan.InfinispanService;
+import org.apache.camel.karavan.infinispan.model.CamelStatus;
+import org.apache.camel.karavan.infinispan.model.ContainerStatus;
+import org.apache.camel.karavan.infinispan.model.DevModeStatus;
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
+import org.jboss.logging.Logger;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.concurrent.ExecutionException;
+
+import static org.apache.camel.karavan.headless.EventService.CMD_COLLECT_CAMEL_STATUS;
+import static org.apache.camel.karavan.headless.EventService.CMD_DELETE_CAMEL_STATUS;
+
+@ApplicationScoped
+public class CamelService {
+
+    private static final Logger LOGGER = Logger.getLogger(CamelService.class.getName());
+
+    @Inject
+    InfinispanService infinispanService;
+
+    @ConfigProperty(name = "karavan.environment")
+    String environment;
+
+    @Inject
+    Vertx vertx;
+
+    @Inject
+    EventBus eventBus;
+
+    WebClient webClient;
+
+    public WebClient getWebClient() {
+        if (webClient == null) {
+            webClient = WebClient.create(vertx);
+        }
+        return webClient;
+    }
+
+    public void reloadProjectCode(String projectId) {
+        LOGGER.info("Reload project code " + projectId);
+        try {
+            ContainerStatus containerStatus = infinispanService.getDevModeContainerStatuses(projectId, environment);
+            Integer exposedPort = containerStatus.getExposedPort();
+            infinispanService.getProjectFiles(projectId).forEach(projectFile -> putRequest(projectId,exposedPort, projectFile.getName(), projectFile.getCode(), 1000));
+            reloadRequest(projectId, exposedPort);
+            DevModeStatus dms = infinispanService.getDevModeStatus(projectId);
+            dms.setCodeLoaded(true);
+            infinispanService.saveDevModeStatus(dms);
+        } catch (Exception ex) {
+            LOGGER.error(ex.getMessage());
+        }
+    }
+
+    @CircuitBreaker(requestVolumeThreshold = 10, failureRatio = 0.5, delay = 1000)
+    public boolean putRequest(String containerName, Integer exposedPort, String fileName, String body, int timeout) {
+        try {
+            String url = getContainerAddress(containerName, exposedPort) + "/q/upload/" + fileName;
+            HttpResponse<Buffer> result = getWebClient().putAbs(url)
+                    .timeout(timeout).sendBuffer(Buffer.buffer(body)).subscribeAsCompletionStage().toCompletableFuture().get();
+            return result.statusCode() == 200;
+        } catch (Exception e) {
+            LOGGER.info(e.getMessage());
+        }
+        return false;
+    }
+
+    public void reloadRequest(String containerName, Integer exposedPort) {
+        String url = getContainerAddress(containerName, exposedPort) + "/q/dev/reload?reload=true";
+        try {
+            result(url, 1000);
+        } catch (InterruptedException | ExecutionException e) {
+            LOGGER.error(e.getMessage());
+        }
+    }
+
+    public String getContainerAddress(String containerName, Integer exposedPort) {
+        return "http://localhost:" + exposedPort;
+    }
+
+    public void collectCamelStatuses() {
+        if (infinispanService.isReady()) {
+            infinispanService.getContainerStatuses(environment).forEach(pod -> {
+                CamelStatusRequest csr = new CamelStatusRequest(pod.getProjectId(), pod.getName(), pod.getExposedPort());
+                eventBus.publish(CMD_COLLECT_CAMEL_STATUS, JsonObject.mapFrom(csr));
+            });
+        }
+    }
+
+    public void collectCamelStatuses(JsonObject data) {
+        CamelStatusRequest dms = data.mapTo(CamelStatusRequest.class);
+        Arrays.stream(CamelStatus.Name.values()).forEach(statusName -> {
+            String containerName = dms.getContainerName();
+            Integer exposedPort = dms.getExposedPort();
+            String status = getCamelStatus(containerName, exposedPort, statusName);
+            if (status != null) {
+                CamelStatus cs = new CamelStatus(dms.getProjectId(), containerName, statusName, status, environment);
+                infinispanService.saveCamelStatus(cs);
+            }
+        });
+    }
+
+    public void cleanupDevModeStatuses() {
+        if (infinispanService.isReady()) {
+            infinispanService.getDevModeStatuses().forEach(dms -> {
+                ContainerStatus pod = infinispanService.getDevModeContainerStatuses(dms.getProjectId(), environment);
+                if (pod == null) {
+                    eventBus.publish(CMD_DELETE_CAMEL_STATUS, JsonObject.mapFrom(dms));
+                }
+            });
+        }
+    }
+
+    public void cleanupDevModeStatus(JsonObject data) {
+        DevModeStatus dms = data.mapTo(DevModeStatus.class);
+        Arrays.stream(CamelStatus.Name.values()).forEach(name -> {
+            infinispanService.deleteCamelStatus(dms.getProjectId(), name.name(), environment);
+        });
+    }
+
+    private void reloadCode(String podName, String oldContext, String newContext) {
+        String newState = getContextState(newContext);
+        String oldState = getContextState(oldContext);
+        if (newContext != null && !Objects.equals(newState, oldState) && "Started".equals(newState)) {
+            reloadProjectCode(podName);
+        }
+    }
+
+    private String getContextState(String context) {
+        if (context != null) {
+            JsonObject obj = new JsonObject(context);
+            return obj.getJsonObject("context").getString("state");
+        } else {
+            return null;
+        }
+    }
+
+    public String getCamelStatus(String podName, Integer exposedPort, CamelStatus.Name statusName) {
+        String url = getContainerAddress(podName, exposedPort) + "/q/dev/" + statusName.name();
+        try {
+            return result(url, 500);
+        } catch (InterruptedException | ExecutionException e) {
+            LOGGER.error(e.getMessage());
+        }
+        return null;
+    }
+
+    @CircuitBreaker(requestVolumeThreshold = 10, failureRatio = 0.5, delay = 1000)
+    public String result(String url, int timeout) throws InterruptedException, ExecutionException {
+        try {
+            HttpResponse<Buffer> result = getWebClient().getAbs(url).putHeader("Accept", "application/json")
+                    .timeout(timeout).send().subscribeAsCompletionStage().toCompletableFuture().get();
+            if (result.statusCode() == 200) {
+                JsonObject res = result.bodyAsJsonObject();
+                return res.encodePrettily();
+            }
+        } catch (Exception e) {
+            LOGGER.info(e.getMessage());
+        }
+        return null;
+    }
+
+    public static class CamelStatusRequest {
+        private String projectId;
+        private String containerName;
+        private Integer exposedPort;
+
+        public CamelStatusRequest() {
+        }
+
+        public CamelStatusRequest(String projectId, String containerName, Integer exposedPort) {
+            this.projectId = projectId;
+            this.containerName = containerName;
+            this.exposedPort = exposedPort;
+        }
+
+        public String getProjectId() {
+            return projectId;
+        }
+
+        public void setProjectId(String projectId) {
+            this.projectId = projectId;
+        }
+
+        public String getContainerName() {
+            return containerName;
+        }
+
+        public void setContainerName(String containerName) {
+            this.containerName = containerName;
+        }
+
+        public Integer getExposedPort() {
+            return exposedPort;
+        }
+
+        public void setExposedPort(Integer exposedPort) {
+            this.exposedPort = exposedPort;
+        }
+    }
+}
\ No newline at end of file
diff --git a/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/EventService.java b/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/EventService.java
new file mode 100644
index 00000000..234d99db
--- /dev/null
+++ b/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/EventService.java
@@ -0,0 +1,52 @@
+/*
+ * 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.karavan.headless;
+
+import io.quarkus.vertx.ConsumeEvent;
+import io.vertx.core.json.JsonObject;
+import org.apache.camel.karavan.infinispan.InfinispanService;
+import org.jboss.logging.Logger;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+@ApplicationScoped
+public class EventService {
+
+    private static final Logger LOGGER = Logger.getLogger(EventService.class.getName());
+    public static final String CMD_COLLECT_CAMEL_STATUS = "collect-camel-status";
+    public static final String CMD_DELETE_CAMEL_STATUS = "delete-camel-status";
+
+    @Inject
+    CamelService camelService;
+
+    @ConsumeEvent(value = CMD_COLLECT_CAMEL_STATUS, blocking = true)
+    public void collectCamelStatuses(JsonObject data) {
+        camelService.collectCamelStatuses();
+    }
+
+    @ConsumeEvent(value = CMD_DELETE_CAMEL_STATUS, blocking = true)
+    public void cleanupDevModeStatus(JsonObject data) {
+        camelService.cleanupDevModeStatuses();
+    }
+
+    @ConsumeEvent(value = InfinispanService.CODE_RELOAD_COMMAND, blocking = true)
+    public void reloadProjectCode(String projectId) {
+        camelService.reloadProjectCode(projectId);
+    }
+
+}
\ No newline at end of file
diff --git a/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/HeadlessService.java b/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/HeadlessService.java
new file mode 100644
index 00000000..224f37f0
--- /dev/null
+++ b/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/HeadlessService.java
@@ -0,0 +1,54 @@
+/*
+ * 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.karavan.headless;
+
+import io.quarkus.runtime.StartupEvent;
+import io.quarkus.scheduler.Scheduled;
+import org.apache.camel.karavan.infinispan.InfinispanService;
+import org.jboss.logging.Logger;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.event.Observes;
+import javax.inject.Inject;
+
+@ApplicationScoped
+public class HeadlessService {
+
+    private static final Logger LOGGER = Logger.getLogger(HeadlessService.class.getName());
+
+    @Inject
+    InfinispanService infinispanService;
+
+    @Inject
+    CamelService camelService;
+
+    void onStart(@Observes StartupEvent ev) {
+        LOGGER.info("Starting Headless Karavan");
+        infinispanService.start(true);
+        infinispanService.clearAllStatuses();
+    }
+
+    @Scheduled(every = "{karavan.camel.status.pull-interval}", concurrentExecution = Scheduled.ConcurrentExecution.SKIP)
+    void collectCamelStatuses() {
+        LOGGER.info("Collect info statuses");
+        // collect Camel statuses
+        camelService.collectCamelStatuses();
+        // clean DevMode statuses if container deleted
+        camelService.cleanupDevModeStatuses();
+    }
+
+}
diff --git a/karavan-web/karavan-headless/src/main/resources/application.properties b/karavan-web/karavan-headless/src/main/resources/application.properties
new file mode 100644
index 00000000..dedfb854
--- /dev/null
+++ b/karavan-web/karavan-headless/src/main/resources/application.properties
@@ -0,0 +1,14 @@
+karavan.environment=dev
+karavan.camel.status.pull-interval=3s
+
+infinispan.hosts=infinispan:11222
+infinispan.username=admin
+infinispan.password=karavan
+
+# Quarkus configuration
+quarkus.infinispan-client.devservices.enabled=false
+quarkus.log.level=INFO
+quarkus.banner.enabled=false
+quarkus.package.type=uber-jar
+quarkus.docker.dockerfile-jvm-path=src/main/docker/Dockerfile.distroless
+quarkus.container-image.builder=docker
\ No newline at end of file