You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ma...@apache.org on 2022/10/28 00:16:52 UTC

[camel-karavan] 02/08: Redesigned status monitoring

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 8073ff981e52b6669d190aed12a950de9a18228f
Author: Marat Gubaidullin <ma...@gmail.com>
AuthorDate: Wed Oct 26 20:22:46 2022 -0400

    Redesigned status monitoring
---
 .../camel/karavan/api/ConfigurationResource.java   |  17 ++-
 .../camel/karavan/api/KubernetesResource.java      | 165 ++++++++-------------
 .../apache/camel/karavan/api/StatusResource.java   |   8 +-
 .../camel/karavan/model/DeploymentStatus.java      |  64 ++++----
 .../apache/camel/karavan/model/Environment.java    |  57 +++++++
 .../org/apache/camel/karavan/model/GroupedKey.java |   2 -
 .../camel/karavan/model/KaravanConfiguration.java  |  24 ---
 .../apache/camel/karavan/model/PipelineStatus.java |  19 ++-
 .../org/apache/camel/karavan/model/PodStatus.java  |  17 ++-
 .../org/apache/camel/karavan/model/Project.java    |  12 +-
 .../camel/karavan/model/ProjectStoreSchema.java    |   2 +-
 .../apache/camel/karavan/service/GitService.java   |   2 +-
 .../{KaravanService.java => ImportService.java}    |  23 +--
 .../camel/karavan/service/InfinispanService.java   |  99 +++++++++----
 .../camel/karavan/service/KaravanService.java      | 108 +++-----------
 .../camel/karavan/service/KubernetesService.java   | 131 +++++++---------
 .../camel/karavan/service/StatusService.java       |  21 ++-
 .../camel/karavan/watcher/DeploymentWatcher.java   |  59 +++++---
 .../camel/karavan/watcher/PipelineRunWatcher.java  |   7 +-
 .../apache/camel/karavan/watcher/PodWatcher.java   |  12 +-
 .../src/main/resources/application.properties      |  28 +---
 karavan-app/src/main/webapp/package-lock.json      |   6 +-
 karavan-app/src/main/webapp/src/api/KaravanApi.tsx |   4 +-
 .../src/main/webapp/src/projects/ProjectInfo.tsx   |   2 +-
 24 files changed, 422 insertions(+), 467 deletions(-)

diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/api/ConfigurationResource.java b/karavan-app/src/main/java/org/apache/camel/karavan/api/ConfigurationResource.java
index 9d0b9ed..cf17e9b 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/api/ConfigurationResource.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/api/ConfigurationResource.java
@@ -16,7 +16,7 @@
  */
 package org.apache.camel.karavan.api;
 
-import org.apache.camel.karavan.model.KaravanConfiguration;
+import org.apache.camel.karavan.service.InfinispanService;
 import org.eclipse.microprofile.config.inject.ConfigProperty;
 
 import javax.inject.Inject;
@@ -34,8 +34,14 @@ public class ConfigurationResource {
     @ConfigProperty(name = "karavan.version")
     String version;
 
+    @ConfigProperty(name = "karavan.environment")
+    String environment;
+
+    @ConfigProperty(name = "karavan.config.runtime")
+    String runtime;
+
     @Inject
-    KaravanConfiguration configuration;
+    InfinispanService infinispanService;
 
     @GET
     @Produces(MediaType.APPLICATION_JSON)
@@ -43,10 +49,9 @@ public class ConfigurationResource {
         return Response.ok(
                 Map.of(
                         "version", version,
-                        "environments", configuration.environments().stream()
-                                        .filter(e -> e.active())
-                                .map(e -> e.name()).collect(Collectors.toList()),
-                        "runtime", configuration.runtime()
+                        "environment", environment,
+                        "environments", infinispanService.getEnvironments().stream().map(e -> e.getName()).collect(Collectors.toList()),
+                        "runtime", runtime
                 )
         ).build();
     }
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/api/KubernetesResource.java b/karavan-app/src/main/java/org/apache/camel/karavan/api/KubernetesResource.java
index e7586a8..a817434 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/api/KubernetesResource.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/api/KubernetesResource.java
@@ -17,27 +17,28 @@
 package org.apache.camel.karavan.api;
 
 import io.smallrye.mutiny.Multi;
-import io.vertx.core.json.JsonObject;
 import io.vertx.mutiny.core.eventbus.EventBus;
 import io.vertx.mutiny.core.eventbus.Message;
-import org.apache.camel.karavan.model.KaravanConfiguration;
+import org.apache.camel.karavan.model.DeploymentStatus;
 import org.apache.camel.karavan.model.Project;
 import org.apache.camel.karavan.service.InfinispanService;
 import org.apache.camel.karavan.service.KubernetesService;
+import org.eclipse.microprofile.config.inject.ConfigProperty;
 import org.jboss.logging.Logger;
 
 import javax.inject.Inject;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
-import javax.ws.rs.HeaderParam;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
-import java.util.Optional;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
 
 @Path("/api/kubernetes")
 public class KubernetesResource {
@@ -51,162 +52,124 @@ public class KubernetesResource {
     @Inject
     KubernetesService kubernetesService;
 
-    @Inject
-    KaravanConfiguration configuration;
+    @ConfigProperty(name = "karavan.environment")
+    String environment;
+
+    @ConfigProperty(name = "karavan.pipeline")
+    String pipeline;
+
 
     private static final Logger LOGGER = Logger.getLogger(KubernetesResource.class.getName());
 
     @POST
     @Produces(MediaType.APPLICATION_JSON)
     @Consumes(MediaType.APPLICATION_JSON)
-    @Path("/pipeline/{environment}")
-    public Project createPipeline(@PathParam("environment") String environment, Project project) throws Exception {
+    @Path("/pipeline/{env}")
+    public Project createPipeline(@PathParam("env") String env, Project project) throws Exception {
         Project p = infinispanService.getProject(project.getProjectId());
-        Optional<KaravanConfiguration.Environment> env = configuration.environments().stream().filter(e -> e.name().equals(environment)).findFirst();
-        if (env.isPresent()) {
-            kubernetesService.createPipelineRun(project, env.get().pipeline(), env.get().namespace());
-            p.setDeployed(true); // TODO:  Replace this update by updating from Pipeline
-            infinispanService.saveProject(p); // TODO:  Replace this update by updating from Pipeline
-        }
+        kubernetesService.createPipelineRun(project, pipeline, kubernetesService.getNamespace());
+//            p.setDeployed(true); // TODO:  Replace this update by updating from Pipeline
+//        infinispanService.saveProject(p); // TODO:  Replace this update by updating from Pipeline
         return p;
     }
 
     @GET
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("/pipeline/{environment}/{name}")
-    public Response getPipeline(@PathParam("environment") String environment,
-                        @PathParam("name") String name) throws Exception {
-        Optional<KaravanConfiguration.Environment> env = configuration.environments().stream().filter(e -> e.name().equals(environment)).findFirst();
-        if (env.isPresent()) {
-            return Response.ok(kubernetesService.getPipelineRun(name, env.get().namespace())).build();
-        } else {
-            return Response.noContent().build();
-        }
+    @Path("/pipeline/{env}/{name}")
+    public Response getPipeline(@PathParam("env") String env,
+                                @PathParam("name") String name) throws Exception {
+        return Response.ok(kubernetesService.getPipelineRun(name, kubernetesService.getNamespace())).build();
     }
 
     @GET
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("/pipeline/log/{environment}/{name}")
-    public Response getPipelineLog(@PathParam("environment") String environment,
-                        @PathParam("name") String name) throws Exception {
-        Optional<KaravanConfiguration.Environment> env = configuration.environments().stream().filter(e -> e.name().equals(environment)).findFirst();
-        if (env.isPresent()) {
-            return Response.ok(kubernetesService.getPipelineRunLog(name, env.get().namespace())).build();
-        } else {
-            return Response.noContent().build();
-        }
+    @Path("/pipeline/log/{env}/{name}")
+    public Response getPipelineLog(@PathParam("env") String env,
+                                   @PathParam("name") String name) throws Exception {
+        return Response.ok(kubernetesService.getPipelineRunLog(name, kubernetesService.getNamespace())).build();
     }
 
     @GET
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("/container/log/{environment}/{name}")
-    public Response getContainerLog(@PathParam("environment") String environment,
-                                   @PathParam("name") String name) throws Exception {
-        Optional<KaravanConfiguration.Environment> env = configuration.environments().stream().filter(e -> e.name().equals(environment)).findFirst();
-        if (env.isPresent()) {
-            return Response.ok(kubernetesService.getContainerLog(name, env.get().namespace())).build();
-        } else {
-            return Response.noContent().build();
-        }
+    @Path("/container/log/{env}/{name}")
+    public Response getContainerLog(@PathParam("env") String env,
+                                    @PathParam("name") String name) throws Exception {
+        return Response.ok(kubernetesService.getContainerLog(name, kubernetesService.getNamespace())).build();
+    }
+
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/deployment/")
+    public List<DeploymentStatus> getAll() throws Exception {
+        return infinispanService.getDeploymentStatuses().stream()
+                .sorted(Comparator.comparing(DeploymentStatus::getName))
+                .collect(Collectors.toList());
     }
 
     @POST
     @Produces(MediaType.APPLICATION_JSON)
     @Consumes(MediaType.APPLICATION_JSON)
-    @Path("/deployment/rollout/{environment}/{name}")
-    public Response rollout(@PathParam("environment") String environment, @PathParam("name") String name) throws Exception {
-        Optional<KaravanConfiguration.Environment> env = configuration.environments().stream().filter(e -> e.name().equals(environment)).findFirst();
-        if (env.isPresent()) {
-            kubernetesService.rolloutDeployment(name, env.get().namespace());
-            return Response.ok().build();
-        }
-        return Response.noContent().build();
+    @Path("/deployment/rollout/{env}/{name}")
+    public Response rollout(@PathParam("env") String env, @PathParam("name") String name) throws Exception {
+        kubernetesService.rolloutDeployment(name, kubernetesService.getNamespace());
+        return Response.ok().build();
     }
 
     @DELETE
     @Produces(MediaType.APPLICATION_JSON)
     @Consumes(MediaType.APPLICATION_JSON)
-    @Path("/deployment/{environment}/{name}")
-    public Response deleteDeployment(@PathParam("environment") String environment, @PathParam("name") String name) throws Exception {
-        Optional<KaravanConfiguration.Environment> env = configuration.environments().stream().filter(e -> e.name().equals(environment)).findFirst();
-        if (env.isPresent()) {
-            kubernetesService.deleteDeployment(name, env.get().namespace());
+    @Path("/deployment/{env}/{name}")
+    public Response deleteDeployment(@PathParam("env") String env, @PathParam("name") String name) throws Exception {
+        kubernetesService.deleteDeployment(name, kubernetesService.getNamespace());
 //            Project p = infinispanService.getProject(name); // TODO: p.setDeployed(false) than karavan keeps pod/camel statuses up forever
 //            p.setDeployed(false);
 //            infinispanService.saveProject(p);
-            return Response.ok().build();
-        }
-        return Response.noContent().build();
+        return Response.ok().build();
     }
 
     @DELETE
     @Produces(MediaType.APPLICATION_JSON)
     @Consumes(MediaType.APPLICATION_JSON)
-    @Path("/pod/{environment}/{name}")
-    public Response deletePod(@PathParam("environment") String environment, @PathParam("name") String name) throws Exception {
-        Optional<KaravanConfiguration.Environment> env = configuration.environments().stream().filter(e -> e.name().equals(environment)).findFirst();
-        if (env.isPresent()) {
-            kubernetesService.deletePod(name, env.get().namespace());
-            return Response.ok().build();
-        }
-        return Response.noContent().build();
+    @Path("/pod/{env}/{name}")
+    public Response deletePod(@PathParam("env") String env, @PathParam("name") String name) throws Exception {
+        kubernetesService.deletePod(name, kubernetesService.getNamespace());
+        return Response.ok().build();
     }
 
     @GET
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("/imagetag/{environment}/{projectId}")
-    public Response getProjectImageTags(@PathParam("environment") String environment, @PathParam("projectId") String projectId) throws Exception {
-        Optional<KaravanConfiguration.Environment> env = configuration.environments().stream().filter(e -> e.name().equals(environment)).findFirst();
-        if (env.isPresent()) {
-            return Response.ok(kubernetesService.getProjectImageTags(projectId, env.get().namespace())).build();
-        }
-        return Response.noContent().build();
+    @Path("/imagetag/{env}/{projectId}")
+    public Response getProjectImageTags(@PathParam("env") String env, @PathParam("projectId") String projectId) throws Exception {
+        return Response.ok(kubernetesService.getProjectImageTags(projectId, kubernetesService.getNamespace())).build();
     }
 
     @GET
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("/configmap/{environment}")
-    public Response getConfigMaps(@PathParam("environment") String environment) throws Exception {
-        Optional<KaravanConfiguration.Environment> env = configuration.environments().stream().filter(e -> e.name().equals(environment)).findFirst();
-        if (env.isPresent()) {
-            return Response.ok(kubernetesService.getConfigMaps(env.get().namespace())).build();
-        }
-        return Response.noContent().build();
+    @Path("/configmap/{env}")
+    public Response getConfigMaps(@PathParam("env") String env) throws Exception {
+        return Response.ok(kubernetesService.getConfigMaps(kubernetesService.getNamespace())).build();
     }
 
     @GET
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("/secret/{environment}")
-    public Response getSecrets(@PathParam("environment") String environment) throws Exception {
-        Optional<KaravanConfiguration.Environment> env = configuration.environments().stream().filter(e -> e.name().equals(environment)).findFirst();
-        if (env.isPresent()) {
-            return Response.ok(kubernetesService.getSecrets(env.get().namespace())).build();
-        }
-        return Response.noContent().build();
+    @Path("/secret/{env}")
+    public Response getSecrets(@PathParam("env") String env) throws Exception {
+        return Response.ok(kubernetesService.getSecrets(kubernetesService.getNamespace())).build();
     }
 
     @GET
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("/service/{environment}")
-    public Response getServices(@PathParam("environment") String environment) throws Exception {
-        Optional<KaravanConfiguration.Environment> env = configuration.environments().stream().filter(e -> e.name().equals(environment)).findFirst();
-        if (env.isPresent()) {
-            return Response.ok(kubernetesService.getServices(env.get().namespace())).build();
-        }
-        return Response.noContent().build();
+    @Path("/service/{env}")
+    public Response getServices(@PathParam("env") String env) throws Exception {
+        return Response.ok(kubernetesService.getServices(kubernetesService.getNamespace())).build();
     }
 
     // TODO: implement log watch
     @GET
-    @Path("/container/log/watch/{environment}/{name}")
+    @Path("/container/log/watch/{env}/{name}")
     @Produces(MediaType.SERVER_SENT_EVENTS)
-    public Multi<String> getContainerLogWatch(@PathParam("environment") String environment, @PathParam("name") String name){
+    public Multi<String> getContainerLogWatch(@PathParam("env") String env, @PathParam("name") String name) {
         LOGGER.info("Start sourcing");
-        Optional<KaravanConfiguration.Environment> env = configuration.environments().stream().filter(e -> e.name().equals(environment)).findFirst();
-        if (env.isPresent()) {
-//            eventBus.publish(podName + "-" + namespace, new String(is.readNBytes(i)));
-//            kubernetesService.startContainerLogWatch(name, env.get().namespace());
-        }
-        return eventBus.<String>consumer(name + "-" + env.get().namespace()).toMulti().map(Message::body);
+        return eventBus.<String>consumer(name + "-" + kubernetesService.getNamespace()).toMulti().map(Message::body);
     }
 }
\ No newline at end of file
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/api/StatusResource.java b/karavan-app/src/main/java/org/apache/camel/karavan/api/StatusResource.java
index b68aaac..f869b26 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/api/StatusResource.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/api/StatusResource.java
@@ -19,7 +19,6 @@ package org.apache.camel.karavan.api;
 import io.vertx.core.eventbus.EventBus;
 import org.apache.camel.karavan.model.CamelStatus;
 import org.apache.camel.karavan.model.DeploymentStatus;
-import org.apache.camel.karavan.model.KaravanConfiguration;
 import org.apache.camel.karavan.model.PipelineStatus;
 import org.apache.camel.karavan.service.InfinispanService;
 import org.apache.camel.karavan.service.StatusService;
@@ -27,7 +26,6 @@ import org.jboss.logging.Logger;
 
 import javax.inject.Inject;
 import javax.ws.rs.GET;
-import javax.ws.rs.HeaderParam;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
@@ -59,9 +57,9 @@ public class StatusResource {
 
     @GET
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("/deployment/{projectId}")
-    public Response getDeploymentStatus(@PathParam("projectId") String projectId) {
-        DeploymentStatus status = infinispanService.getDeploymentStatus(projectId);
+    @Path("/deployment/{name}/{env}")
+    public Response getDeploymentStatus(@PathParam("name") String name, @PathParam("env") String env) {
+        DeploymentStatus status = infinispanService.getDeploymentStatus(name, env);
         if (status != null) {
             return Response.ok(status).build();
         } else {
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/model/DeploymentStatus.java b/karavan-app/src/main/java/org/apache/camel/karavan/model/DeploymentStatus.java
index 732bdb1..c366be1 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/model/DeploymentStatus.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/model/DeploymentStatus.java
@@ -3,50 +3,66 @@ package org.apache.camel.karavan.model;
 import org.infinispan.protostream.annotations.ProtoFactory;
 import org.infinispan.protostream.annotations.ProtoField;
 
-import java.util.ArrayList;
-import java.util.List;
-
 public class DeploymentStatus {
     public static final String CACHE = "deployment_statuses";
     @ProtoField(number = 1)
-    String projectId;
+    String name;
     @ProtoField(number = 2)
-    String image;
+    String namespace;
     @ProtoField(number = 3)
-    Integer replicas;
+    String env;
     @ProtoField(number = 4)
-    Integer readyReplicas;
+    String image;
     @ProtoField(number = 5)
+    Integer replicas;
+    @ProtoField(number = 6)
+    Integer readyReplicas;
+    @ProtoField(number = 7)
     Integer unavailableReplicas;
-    @ProtoField(number = 6, collectionImplementation = ArrayList.class)
-    List<PodStatus> podStatuses;
-
 
-    public DeploymentStatus(String projectId) {
-        this.projectId = projectId;
+    public DeploymentStatus(String name, String namespace, String env) {
+        this.name = name;
+        this.namespace = namespace;
+        this.env = env;
         this.image = "";
         this.replicas = 0;
         this.readyReplicas = 0;
         this.unavailableReplicas = 0;
-        this.podStatuses = new ArrayList<>(0);
     }
 
     @ProtoFactory
-    public DeploymentStatus(String projectId, String image, Integer replicas, Integer readyReplicas, Integer unavailableReplicas, List<PodStatus> podStatuses) {
-        this.projectId = projectId;
+    public DeploymentStatus(String name, String namespace, String env, String image, Integer replicas, Integer readyReplicas, Integer unavailableReplicas) {
+        this.name = name;
+        this.env = env;
+        this.namespace = namespace;
         this.image = image;
         this.replicas = replicas;
         this.readyReplicas = readyReplicas;
         this.unavailableReplicas = unavailableReplicas;
-        this.podStatuses = podStatuses;
     }
 
-    public String getProjectId() {
-        return projectId;
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
     }
 
-    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() {
@@ -80,12 +96,4 @@ public class DeploymentStatus {
     public void setUnavailableReplicas(Integer unavailableReplicas) {
         this.unavailableReplicas = unavailableReplicas;
     }
-
-    public List<PodStatus> getPodStatuses() {
-        return podStatuses;
-    }
-
-    public void setPodStatuses(List<PodStatus> podStatuses) {
-        this.podStatuses = podStatuses;
-    }
 }
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/model/Environment.java b/karavan-app/src/main/java/org/apache/camel/karavan/model/Environment.java
new file mode 100644
index 0000000..e37fbdf
--- /dev/null
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/model/Environment.java
@@ -0,0 +1,57 @@
+package org.apache.camel.karavan.model;
+
+import org.infinispan.protostream.annotations.ProtoFactory;
+import org.infinispan.protostream.annotations.ProtoField;
+
+public class Environment {
+    public static final String CACHE = "environments";
+
+    @ProtoField(number = 1)
+    String name;
+    @ProtoField(number = 2)
+    String cluster;
+    @ProtoField(number = 3)
+    String namespace;
+    @ProtoField(number = 4)
+    String pipeline;
+
+    @ProtoFactory
+    public Environment(String name, String cluster, String namespace, String pipeline) {
+        this.name = name;
+        this.cluster = cluster;
+        this.namespace = namespace;
+        this.pipeline = pipeline;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getCluster() {
+        return cluster;
+    }
+
+    public void setCluster(String cluster) {
+        this.cluster = cluster;
+    }
+
+    public String getNamespace() {
+        return namespace;
+    }
+
+    public void setNamespace(String namespace) {
+        this.namespace = namespace;
+    }
+
+    public String getPipeline() {
+        return pipeline;
+    }
+
+    public void setPipeline(String pipeline) {
+        this.pipeline = pipeline;
+    }
+}
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/model/GroupedKey.java b/karavan-app/src/main/java/org/apache/camel/karavan/model/GroupedKey.java
index c657309..a50e5ce 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/model/GroupedKey.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/model/GroupedKey.java
@@ -3,8 +3,6 @@ package org.apache.camel.karavan.model;
 import org.infinispan.protostream.annotations.ProtoFactory;
 import org.infinispan.protostream.annotations.ProtoField;
 
-import java.util.Objects;
-
 public class GroupedKey {
 
 
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/model/KaravanConfiguration.java b/karavan-app/src/main/java/org/apache/camel/karavan/model/KaravanConfiguration.java
deleted file mode 100644
index 5d028c3..0000000
--- a/karavan-app/src/main/java/org/apache/camel/karavan/model/KaravanConfiguration.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.apache.camel.karavan.model;
-
-import io.smallrye.config.ConfigMapping;
-
-import java.util.List;
-
-@ConfigMapping(prefix = "karavan.config")
-public interface KaravanConfiguration {
-
-    String groupId();
-    String imageGroup();
-    String runtime();
-    String runtimeVersion();
-    Long statusThreshold();
-    List<Environment> environments();
-
-    interface Environment {
-        String name();
-        String cluster();
-        String namespace();
-        String pipeline();
-        Boolean active();
-    }
-}
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/model/PipelineStatus.java b/karavan-app/src/main/java/org/apache/camel/karavan/model/PipelineStatus.java
index 8f6f807..b80c379 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/model/PipelineStatus.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/model/PipelineStatus.java
@@ -15,21 +15,22 @@ public class PipelineStatus {
     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) {
+    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) {
+    public PipelineStatus(String projectId, String env) {
         this.projectId = projectId;
-    }
-
-    public PipelineStatus() {
+        this.env = env;
     }
 
     public String getProjectId() {
@@ -71,4 +72,12 @@ public class PipelineStatus {
     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-app/src/main/java/org/apache/camel/karavan/model/PodStatus.java b/karavan-app/src/main/java/org/apache/camel/karavan/model/PodStatus.java
index 7d9c9a4..8c70909 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/model/PodStatus.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/model/PodStatus.java
@@ -4,6 +4,7 @@ import org.infinispan.protostream.annotations.ProtoFactory;
 import org.infinispan.protostream.annotations.ProtoField;
 
 public class PodStatus {
+    public static final String CACHE = "pod_statuses";
     @ProtoField(number = 1)
     String name;
     @ProtoField(number = 2)
@@ -14,22 +15,26 @@ public class PodStatus {
     String reason;
     @ProtoField(number = 5)
     String deployment;
+    @ProtoField(number = 6)
+    String env;
 
-    public PodStatus() {
+    public PodStatus(String env) {
         this.name = "";
         this.started = false;
         this.ready = false;
         this.reason = "";
         this.deployment = "";
+        this.env = "";
     }
 
     @ProtoFactory
-    public PodStatus(String name, Boolean started, Boolean ready, String reason, String deployment) {
+    public PodStatus(String name, Boolean started, Boolean ready, String reason, String deployment, String env) {
         this.name = name;
         this.started = started;
         this.ready = ready;
         this.reason = reason;
         this.deployment = deployment;
+        this.env = env;
     }
 
     public String getName() {
@@ -71,4 +76,12 @@ public class PodStatus {
     public void setDeployment(String deployment) {
         this.deployment = deployment;
     }
+
+    public String getEnv() {
+        return env;
+    }
+
+    public void setEnv(String env) {
+        this.env = env;
+    }
 }
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/model/Project.java b/karavan-app/src/main/java/org/apache/camel/karavan/model/Project.java
index 844e07a..898b0ab 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/model/Project.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/model/Project.java
@@ -17,8 +17,6 @@ public class Project {
     Project.CamelRuntime runtime;
     @ProtoField(number = 5)
     String lastCommit;
-    @ProtoField(number = 6)
-    Boolean deployed;
 
     public enum CamelRuntime {
         @ProtoEnumValue(number = 0, name = "Quarkus")
@@ -30,13 +28,12 @@ public class Project {
     }
 
     @ProtoFactory
-    public Project(String projectId, String name, String description, CamelRuntime runtime, String lastCommit, Boolean deployed) {
+    public Project(String projectId, String name, String description, CamelRuntime runtime, String lastCommit) {
         this.projectId = projectId;
         this.name = name;
         this.description = description;
         this.runtime = runtime;
         this.lastCommit = lastCommit;
-        this.deployed = deployed;
     }
 
     public Project(String projectId, String name, String description, CamelRuntime runtime) {
@@ -89,11 +86,4 @@ public class Project {
         this.lastCommit = lastCommit;
     }
 
-    public Boolean getDeployed() {
-        return deployed;
-    }
-
-    public void setDeployed(Boolean deployed) {
-        this.deployed = deployed;
-    }
 }
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/model/ProjectStoreSchema.java b/karavan-app/src/main/java/org/apache/camel/karavan/model/ProjectStoreSchema.java
index 5e8d3d5..6a94007 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/model/ProjectStoreSchema.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/model/ProjectStoreSchema.java
@@ -6,7 +6,7 @@ import org.infinispan.protostream.annotations.AutoProtoSchemaBuilder;
 @AutoProtoSchemaBuilder(
         includeClasses = {
                 GroupedKey.class, Project.class, ProjectFile.class, PipelineStatus.class, CamelStatus.class, DeploymentStatus.class,
-                PodStatus.class
+                PodStatus.class, Environment.class
         },
         schemaPackageName = "karavan")
 public interface ProjectStoreSchema extends GeneratedSchema {
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/service/GitService.java b/karavan-app/src/main/java/org/apache/camel/karavan/service/GitService.java
index 1c12dc1..6780c94 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/service/GitService.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/service/GitService.java
@@ -76,7 +76,7 @@ public class GitService {
         String propertiesPrefix = "karavan." + name + "-";
         String branch = ConfigProvider.getConfig().getValue(propertiesPrefix + "git-branch", String.class);
         if (kubernetesService.inKubernetes()){
-            LOGGER.info("inKubernetes " + kubernetesService.currentNamespace);
+            LOGGER.info("inKubernetes " + kubernetesService.getNamespace());
             String kubernetesPrefix = name + "-";
             Secret secret =  kubernetesService.getKaravanSecret();
             String uri = new String(Base64.getDecoder().decode(secret.getData().get(kubernetesPrefix + "git-repository").getBytes(StandardCharsets.UTF_8)));
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/service/KaravanService.java b/karavan-app/src/main/java/org/apache/camel/karavan/service/ImportService.java
similarity index 85%
copy from karavan-app/src/main/java/org/apache/camel/karavan/service/KaravanService.java
copy to karavan-app/src/main/java/org/apache/camel/karavan/service/ImportService.java
index 33b2ac0..c83a121 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/service/KaravanService.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/service/ImportService.java
@@ -16,18 +16,14 @@
  */
 package org.apache.camel.karavan.service;
 
-import io.quarkus.runtime.StartupEvent;
 import io.quarkus.vertx.ConsumeEvent;
 import io.smallrye.mutiny.tuples.Tuple2;
-import io.vertx.core.eventbus.EventBus;
-import org.apache.camel.karavan.model.KaravanConfiguration;
 import org.apache.camel.karavan.model.Project;
 import org.apache.camel.karavan.model.ProjectFile;
 import org.eclipse.microprofile.config.inject.ConfigProperty;
 import org.jboss.logging.Logger;
 
 import javax.enterprise.context.ApplicationScoped;
-import javax.enterprise.event.Observes;
 import javax.inject.Inject;
 import java.util.Arrays;
 import java.util.List;
@@ -36,12 +32,11 @@ import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
 
 @ApplicationScoped
-public class KaravanService {
+public class ImportService {
 
-    private static final Logger LOGGER = Logger.getLogger(KaravanService.class.getName());
-    public static final String START_WATCHERS = "start-watchers";
+    private static final Logger LOGGER = Logger.getLogger(ImportService.class.getName());
     public static final String IMPORT_PROJECTS = "import-projects";
-    public static final String LOAD_CUSTOM_KAMELETS = "load-custom-kamelets";
+    public static final String IMPORT_KAMELETS = "import-kamelets";
 
     @Inject
     InfinispanService infinispanService;
@@ -52,13 +47,6 @@ public class KaravanService {
     @ConfigProperty(name = "karavan.config.runtime")
     String runtime;
 
-    @Inject
-    KaravanConfiguration configuration;
-
-    void onStart(@Observes StartupEvent ev) {
-        infinispanService.start();
-    }
-
     @ConsumeEvent(value = IMPORT_PROJECTS, blocking = true)
     void importProjects(String data) {
         LOGGER.info("Import projects from Git");
@@ -67,7 +55,7 @@ public class KaravanService {
             repo.forEach(p -> {
                 String folderName = p.getItem1();
                 String name = Arrays.stream(folderName.split("-")).map(s -> capitalize(s)).collect(Collectors.joining(" "));
-                Project project = new Project(folderName, name, name, Project.CamelRuntime.valueOf(runtime.toUpperCase()), "", false);
+                Project project = new Project(folderName, name, name, Project.CamelRuntime.valueOf(runtime.toUpperCase()), "");
                 infinispanService.saveProject(project);
 
                 AtomicReference<ProjectFile> properties = new AtomicReference<>();
@@ -89,10 +77,9 @@ public class KaravanService {
         } catch (Exception e) {
             LOGGER.error("Error during project import", e);
         }
-        loadCustomKamelets("");
     }
 
-    @ConsumeEvent(value = LOAD_CUSTOM_KAMELETS, blocking = true)
+    @ConsumeEvent(value = IMPORT_KAMELETS, blocking = true)
     void loadCustomKamelets(String data) {
         LOGGER.info("Load custom Kamelets from Git");
         try {
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/service/InfinispanService.java b/karavan-app/src/main/java/org/apache/camel/karavan/service/InfinispanService.java
index 136f130..88db2e3 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/service/InfinispanService.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/service/InfinispanService.java
@@ -16,13 +16,13 @@
  */
 package org.apache.camel.karavan.service;
 
-import io.quarkus.runtime.configuration.ProfileManager;
-import io.vertx.core.eventbus.EventBus;
 import org.apache.camel.karavan.model.CamelStatus;
 import org.apache.camel.karavan.model.DeploymentStatus;
+import org.apache.camel.karavan.model.Environment;
 import org.apache.camel.karavan.model.GroupedKey;
 import org.apache.camel.karavan.model.Kamelet;
 import org.apache.camel.karavan.model.PipelineStatus;
+import org.apache.camel.karavan.model.PodStatus;
 import org.apache.camel.karavan.model.Project;
 import org.apache.camel.karavan.model.ProjectFile;
 import org.eclipse.microprofile.config.inject.ConfigProperty;
@@ -51,16 +51,13 @@ import java.util.stream.Collectors;
 public class InfinispanService {
 
     BasicCache<GroupedKey, Project> projects;
-
     BasicCache<GroupedKey, ProjectFile> files;
-
     BasicCache<GroupedKey, PipelineStatus> pipelineStatuses;
-
-    BasicCache<GroupedKey, DeploymentStatus> deploymentStatus;
-
-    BasicCache<GroupedKey, CamelStatus> camelStatus;
-
+    BasicCache<GroupedKey, DeploymentStatus> deploymentStatuses;
+    BasicCache<GroupedKey, PodStatus> podStatuses;
+    BasicCache<GroupedKey, CamelStatus> camelStatuses;
     BasicCache<String, String> kamelets;
+    BasicCache<String, Environment> environments;
 
     @Inject
     RemoteCacheManager cacheManager;
@@ -68,9 +65,6 @@ public class InfinispanService {
     @Inject
     GeneratorService generatorService;
 
-    @Inject
-    EventBus bus;
-
     @ConfigProperty(name = "karavan.config.runtime")
     String runtime;
 
@@ -95,26 +89,25 @@ public class InfinispanService {
                     .shared(false)
                     .preload(true)
                     .fetchPersistentState(true);
+            environments = cacheManager.administration().withFlags(CacheContainerAdmin.AdminFlag.VOLATILE).getOrCreateCache(Environment.CACHE, builder.build());
             projects = cacheManager.administration().withFlags(CacheContainerAdmin.AdminFlag.VOLATILE).getOrCreateCache(Project.CACHE, builder.build());
             files = cacheManager.administration().withFlags(CacheContainerAdmin.AdminFlag.VOLATILE).getOrCreateCache(ProjectFile.CACHE, builder.build());
             pipelineStatuses = cacheManager.administration().withFlags(CacheContainerAdmin.AdminFlag.VOLATILE).getOrCreateCache(PipelineStatus.CACHE, builder.build());
-            deploymentStatus = cacheManager.administration().withFlags(CacheContainerAdmin.AdminFlag.VOLATILE).getOrCreateCache(DeploymentStatus.CACHE, builder.build());
-            camelStatus = cacheManager.administration().withFlags(CacheContainerAdmin.AdminFlag.VOLATILE).getOrCreateCache(CamelStatus.CACHE, builder.build());
+            deploymentStatuses = cacheManager.administration().withFlags(CacheContainerAdmin.AdminFlag.VOLATILE).getOrCreateCache(DeploymentStatus.CACHE, builder.build());
+            podStatuses = cacheManager.administration().withFlags(CacheContainerAdmin.AdminFlag.VOLATILE).getOrCreateCache(PodStatus.CACHE, builder.build());
+            camelStatuses = cacheManager.administration().withFlags(CacheContainerAdmin.AdminFlag.VOLATILE).getOrCreateCache(CamelStatus.CACHE, builder.build());
             kamelets = cacheManager.administration().withFlags(CacheContainerAdmin.AdminFlag.VOLATILE).getOrCreateCache(Kamelet.CACHE, builder.build());
         } else {
             LOGGER.info("InfinispanService is starting in remote mode");
+            environments = cacheManager.administration().getOrCreateCache(Environment.CACHE, new XMLStringConfiguration(String.format(CACHE_CONFIG, Environment.CACHE)));
             projects = cacheManager.administration().getOrCreateCache(Project.CACHE, new XMLStringConfiguration(String.format(CACHE_CONFIG, Project.CACHE)));
             files = cacheManager.administration().getOrCreateCache(ProjectFile.CACHE, new XMLStringConfiguration(String.format(CACHE_CONFIG, ProjectFile.CACHE)));
-            pipelineStatuses = cacheManager.administration().getOrCreateCache(ProjectFile.CACHE, new XMLStringConfiguration(String.format(CACHE_CONFIG, PipelineStatus.CACHE)));
-            deploymentStatus = cacheManager.administration().getOrCreateCache(ProjectFile.CACHE, new XMLStringConfiguration(String.format(CACHE_CONFIG, DeploymentStatus.CACHE)));
-            camelStatus = cacheManager.administration().getOrCreateCache(ProjectFile.CACHE, new XMLStringConfiguration(String.format(CACHE_CONFIG, CamelStatus.CACHE)));
+            pipelineStatuses = cacheManager.administration().getOrCreateCache(PipelineStatus.CACHE, new XMLStringConfiguration(String.format(CACHE_CONFIG, PipelineStatus.CACHE)));
+            deploymentStatuses = cacheManager.administration().getOrCreateCache(DeploymentStatus.CACHE, new XMLStringConfiguration(String.format(CACHE_CONFIG, DeploymentStatus.CACHE)));
+            podStatuses = cacheManager.administration().getOrCreateCache(PodStatus.CACHE, new XMLStringConfiguration(String.format(CACHE_CONFIG, PodStatus.CACHE)));
+            camelStatuses = cacheManager.administration().getOrCreateCache(CamelStatus.CACHE, new XMLStringConfiguration(String.format(CACHE_CONFIG, CamelStatus.CACHE)));
             kamelets = cacheManager.administration().getOrCreateCache(Kamelet.CACHE, new XMLStringConfiguration(String.format(CACHE_CONFIG, Kamelet.CACHE)));
         }
-        if (getProjects().isEmpty()) {
-            LOGGER.info("No projects found in the Data Grid");
-            bus.publish(KaravanService.IMPORT_PROJECTS, "");
-        }
-        bus.publish(KaravanService.START_WATCHERS, "");
     }
 
     public List<Project> getProjects() {
@@ -171,23 +164,64 @@ public class InfinispanService {
     }
 
     public void savePipelineStatus(PipelineStatus status) {
-        pipelineStatuses.put(GroupedKey.create(status.getProjectId(), status.getProjectId()), status);
+        pipelineStatuses.put(GroupedKey.create(status.getProjectId(), status.getEnv()), status);
     }
 
-    public DeploymentStatus getDeploymentStatus(String projectId) {
-        return deploymentStatus.get(GroupedKey.create(projectId, projectId));
+    public DeploymentStatus getDeploymentStatus(String name, String env) {
+        return deploymentStatuses.get(GroupedKey.create(name, env));
     }
 
     public void saveDeploymentStatus(DeploymentStatus status) {
-        deploymentStatus.put(GroupedKey.create(status.getProjectId(), status.getProjectId()), status);
+        deploymentStatuses.put(GroupedKey.create(status.getName(), status.getEnv()), status);
+    }
+
+    public void deleteDeploymentStatus(DeploymentStatus status) {
+        deploymentStatuses.remove(GroupedKey.create(status.getName(), status.getEnv()));
+    }
+
+    public List<DeploymentStatus> getDeploymentStatuses() {
+        return deploymentStatuses.values().stream().collect(Collectors.toList());
+    }
+
+    public List<DeploymentStatus> getDeploymentStatuses(String env) {
+        if (cacheManager == null) {
+            QueryFactory queryFactory = org.infinispan.query.Search.getQueryFactory((Cache<?, ?>) files);
+            return queryFactory.<DeploymentStatus>create("FROM org.apache.camel.karavan.model.DeploymentStatus WHERE env = :env")
+                    .setParameter("env", env)
+                    .execute().list();
+        } else {
+            QueryFactory queryFactory = Search.getQueryFactory((RemoteCache<?, ?>) files);
+            return queryFactory.<DeploymentStatus>create("FROM karavan.DeploymentStatus WHERE env = :env")
+                    .setParameter("env", env)
+                    .execute().list();
+        }
+    }
+
+    public List<PodStatus> getPodStatuses(String projectId, String env) {
+        if (cacheManager == null) {
+            QueryFactory queryFactory = org.infinispan.query.Search.getQueryFactory((Cache<?, ?>) files);
+            return queryFactory.<PodStatus>create("FROM org.apache.camel.karavan.model.PodStatus WHERE deployment = :deployment AND env = :env")
+                    .setParameter("deployment", projectId)
+                    .setParameter("env", env)
+                    .execute().list();
+        } else {
+            QueryFactory queryFactory = Search.getQueryFactory((RemoteCache<?, ?>) files);
+            return queryFactory.<PodStatus>create("FROM karavan.PodStatus WHERE deployment = :deployment AND env = :env")
+                    .setParameter("deployment", projectId)
+                    .setParameter("env", env)
+                    .execute().list();
+        }
     }
 
+    public void savePodStatus(PodStatus status) {
+        podStatuses.put(GroupedKey.create(status.getDeployment(), status.getName()), status);
+    }
     public CamelStatus getCamelStatus(String projectId) {
-        return camelStatus.get(GroupedKey.create(projectId, projectId));
+        return camelStatuses.get(GroupedKey.create(projectId, projectId));
     }
 
     public void saveCamelStatus(CamelStatus status) {
-        camelStatus.put(GroupedKey.create(status.getProjectId(), status.getProjectId()), status);
+        camelStatuses.put(GroupedKey.create(status.getProjectId(), status.getProjectId()), status);
     }
 
     public List<String> getKameletNames() {
@@ -201,4 +235,13 @@ public class InfinispanService {
     public void saveKamelet(String name, String yaml) {
         kamelets.put(name, yaml);
     }
+
+    public List<Environment> getEnvironments() {
+        return environments.values().stream().collect(Collectors.toList());
+    }
+
+    public void saveEnvironment(Environment environment) {
+        environments.put(environment.getName(), environment);
+    }
+
 }
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/service/KaravanService.java b/karavan-app/src/main/java/org/apache/camel/karavan/service/KaravanService.java
index 33b2ac0..717e7c5 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/service/KaravanService.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/service/KaravanService.java
@@ -17,119 +17,57 @@
 package org.apache.camel.karavan.service;
 
 import io.quarkus.runtime.StartupEvent;
-import io.quarkus.vertx.ConsumeEvent;
-import io.smallrye.mutiny.tuples.Tuple2;
 import io.vertx.core.eventbus.EventBus;
-import org.apache.camel.karavan.model.KaravanConfiguration;
-import org.apache.camel.karavan.model.Project;
-import org.apache.camel.karavan.model.ProjectFile;
+import org.apache.camel.karavan.model.Environment;
 import org.eclipse.microprofile.config.inject.ConfigProperty;
 import org.jboss.logging.Logger;
 
 import javax.enterprise.context.ApplicationScoped;
 import javax.enterprise.event.Observes;
 import javax.inject.Inject;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.stream.Collectors;
 
 @ApplicationScoped
 public class KaravanService {
 
     private static final Logger LOGGER = Logger.getLogger(KaravanService.class.getName());
-    public static final String START_WATCHERS = "start-watchers";
-    public static final String IMPORT_PROJECTS = "import-projects";
-    public static final String LOAD_CUSTOM_KAMELETS = "load-custom-kamelets";
 
     @Inject
     InfinispanService infinispanService;
 
     @Inject
-    GitService gitService;
-
-    @ConfigProperty(name = "karavan.config.runtime")
-    String runtime;
+    KubernetesService kubernetesService;
 
     @Inject
-    KaravanConfiguration configuration;
+    EventBus bus;
+
+    @ConfigProperty(name = "karavan.environment")
+    String environment;
+
+    @ConfigProperty(name = "karavan.pipeline")
+    String pipeline;
 
     void onStart(@Observes StartupEvent ev) {
         infinispanService.start();
+        setEnvironment();
+        initialImport();
+        startInformers();
     }
 
-    @ConsumeEvent(value = IMPORT_PROJECTS, blocking = true)
-    void importProjects(String data) {
-        LOGGER.info("Import projects from Git");
-        try {
-            List<Tuple2<String, Map<String, String>>> repo = gitService.readProjectsFromRepository();
-            repo.forEach(p -> {
-                String folderName = p.getItem1();
-                String name = Arrays.stream(folderName.split("-")).map(s -> capitalize(s)).collect(Collectors.joining(" "));
-                Project project = new Project(folderName, name, name, Project.CamelRuntime.valueOf(runtime.toUpperCase()), "", false);
-                infinispanService.saveProject(project);
-
-                AtomicReference<ProjectFile> properties = new AtomicReference<>();
-                p.getItem2().forEach((key, value) -> {
-                    ProjectFile file = new ProjectFile(key, value, folderName);
-                    infinispanService.saveProjectFile(file);
-                    if (isApplicationProperties(file)) {
-                        properties.set(file);
-                    }
-                });
-                // update project
-                if (properties != null){
-                    project.setDescription(getProjectDescription(properties.get()));
-                    project.setName(getProjectName(properties.get()));
-                    infinispanService.saveProject(project);
-                }
-
-            });
-        } catch (Exception e) {
-            LOGGER.error("Error during project import", e);
-        }
-        loadCustomKamelets("");
+    void setEnvironment() {
+        String cluster = kubernetesService.getCluster();
+        String namespace = kubernetesService.getNamespace();
+        infinispanService.saveEnvironment(new Environment(environment, cluster, namespace, pipeline));
     }
 
-    @ConsumeEvent(value = LOAD_CUSTOM_KAMELETS, blocking = true)
-    void loadCustomKamelets(String data) {
-        LOGGER.info("Load custom Kamelets from Git");
-        try {
-            List<Tuple2<String, String>> repo = gitService.readKameletsFromRepository();
-            repo.forEach(p -> {
-                String name = p.getItem1();
-                String yaml = p.getItem2();
-                infinispanService.saveKamelet(name, yaml);
-            });
-        } catch (Exception e) {
-            LOGGER.error("Error during project import", e);
+    void initialImport() {
+        if (infinispanService.getProjects().isEmpty()) {
+            LOGGER.info("No projects found in the Data Grid");
+            bus.publish(ImportService.IMPORT_PROJECTS, "");
         }
+        bus.publish(ImportService.IMPORT_KAMELETS, "");
     }
 
-    private static String capitalize(String str) {
-        if(str == null || str.isEmpty()) {
-            return str;
-        }
-        return str.substring(0, 1).toUpperCase() + str.substring(1);
-    }
-
-    private static boolean isApplicationProperties(ProjectFile file) {
-        return file.getName().equalsIgnoreCase("application.properties");
-    }
-
-    private static String getProperty(ProjectFile file, String property) {
-        String prefix = property + "=";
-        return  Arrays.stream(file.getCode().split(System.lineSeparator())).filter(s -> s.startsWith(prefix))
-                .findFirst().orElseGet(() -> "")
-                .replace(prefix, "");
-    }
-
-    private static String getProjectDescription(ProjectFile file) {
-        return getProperty(file, "camel.jbang.project-description");
-    }
-
-    private static String getProjectName(ProjectFile file) {
-        return getProperty(file, "camel.jbang.project-name");
+    void startInformers() {
+        bus.publish(KubernetesService.START_WATCHERS, "");
     }
 }
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/service/KubernetesService.java b/karavan-app/src/main/java/org/apache/camel/karavan/service/KubernetesService.java
index 20bac71..626eb93 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/service/KubernetesService.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/service/KubernetesService.java
@@ -40,9 +40,7 @@ import io.quarkus.runtime.ShutdownEvent;
 import io.quarkus.vertx.ConsumeEvent;
 import io.vertx.mutiny.core.eventbus.EventBus;
 import org.apache.camel.karavan.model.DeploymentStatus;
-import org.apache.camel.karavan.model.KaravanConfiguration;
 import org.apache.camel.karavan.model.PipelineRunLog;
-import org.apache.camel.karavan.model.PodStatus;
 import org.apache.camel.karavan.model.Project;
 import org.apache.camel.karavan.watcher.DeploymentWatcher;
 import org.apache.camel.karavan.watcher.PipelineRunWatcher;
@@ -61,22 +59,17 @@ import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.Optional;
 import java.util.stream.Collectors;
 
-import static org.apache.camel.karavan.service.KaravanService.START_WATCHERS;
 
 @ApplicationScoped
 public class KubernetesService {
 
-    @Inject
-    EventBus eventBus;
-
-    @ConfigProperty(name = "kubernetes.namespace", defaultValue = "localhost")
-    String currentNamespace;
+    private static final Logger LOGGER = Logger.getLogger(KubernetesService.class.getName());
+    public static final String START_WATCHERS = "start-watchers";
 
     @Inject
-    KaravanConfiguration config;
+    EventBus eventBus;
 
     @Inject
     InfinispanService infinispanService;
@@ -96,36 +89,33 @@ public class KubernetesService {
         return kubernetesClient().adapt(OpenShiftClient.class);
     }
 
-    private static final Logger LOGGER = Logger.getLogger(KubernetesService.class.getName());
+    @ConfigProperty(name = "karavan.environment")
+    public
+    String environment;
 
     private List<Watch> watches = new ArrayList<>();
 
     @ConsumeEvent(value = START_WATCHERS, blocking = true)
     void start(String data) {
         LOGGER.info("Start KubernetesService");
-        Optional<KaravanConfiguration.Environment> env = config.environments().stream()
-                .filter(environment -> environment.name().equals("dev")).findFirst();
-        if (env.isPresent()) {
-            String labelName = getRuntimeLabel();
-            try {
-                watches.add(kubernetesClient().apps().deployments().inNamespace(currentNamespace).withLabel(labelName, "camel")
-                        .watch(new DeploymentWatcher(infinispanService, this)));
-            } catch (Exception e) {
-                LOGGER.error(e.getMessage());
-            }
-            try {
-                watches.add(kubernetesClient().pods().inNamespace(currentNamespace).withLabel(labelName, "camel")
-                        .watch(new PodWatcher(infinispanService, this)));
-            } catch (Exception e){
-                LOGGER.error(e.getMessage());
-            }
-            try {
-                watches.add(tektonClient().v1beta1().pipelineRuns().inNamespace(currentNamespace)
-                        .watch(new PipelineRunWatcher(infinispanService)));
-            } catch (Exception e) {
-                LOGGER.error(e.getMessage());
-            }
-
+        String labelName = getRuntimeLabel();
+        try {
+            watches.add(kubernetesClient().apps().deployments().inNamespace(getNamespace()).withLabel(labelName, "camel")
+                    .watch(new DeploymentWatcher(infinispanService, this)));
+        } catch (Exception e) {
+            LOGGER.error(e.getMessage());
+        }
+        try {
+            watches.add(kubernetesClient().pods().inNamespace(getNamespace()).withLabel(labelName, "camel")
+                    .watch(new PodWatcher(infinispanService, this)));
+        } catch (Exception e){
+            LOGGER.error(e.getMessage());
+        }
+        try {
+            watches.add(tektonClient().v1beta1().pipelineRuns().inNamespace(getNamespace())
+                    .watch(new PipelineRunWatcher(infinispanService, this)));
+        } catch (Exception e) {
+            LOGGER.error(e.getMessage());
         }
     }
 
@@ -242,49 +232,27 @@ public class KubernetesService {
         }
     }
 
-    public DeploymentStatus getDeploymentStatus(String name, Deployment deployment) {
-        try {
-            String dsImage = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage();
-            String imageName = dsImage.startsWith("image-registry.openshift-image-registry.svc")
-                    ? dsImage.replace("image-registry.openshift-image-registry.svc:5000/", "")
-                    : dsImage;
-
-            List<PodStatus> podStatuses = getDeploymentPodsStatuses(name, deployment.getMetadata().getNamespace());
-
-            return new DeploymentStatus(
-                    name,
-                    imageName,
-                    deployment.getSpec().getReplicas(),
-                    deployment.getStatus().getReadyReplicas(),
-                    deployment.getStatus().getUnavailableReplicas(),
-                    podStatuses
-            );
-        } catch (Exception ex) {
-            LOGGER.error(ex.getMessage());
-            return new DeploymentStatus(name);
-        }
-    }
 
-    public List<PodStatus> getDeploymentPodsStatuses(String name, String namespace) {
-        try {
-            String labelName = getRuntimeLabel();
-            List<Pod> pods = kubernetesClient().pods().inNamespace(namespace)
-                    .withLabel("app.kubernetes.io/name", name)
-                    .withLabel(labelName, "camel")
-                    .list().getItems();
-
-            return pods.stream().map(pod -> new PodStatus(
-                    pod.getMetadata().getName(),
-                    pod.getStatus().getContainerStatuses().get(0).getStarted(),
-                    pod.getStatus().getContainerStatuses().get(0).getReady(),
-                    getPodReason(pod),
-                    pod.getMetadata().getLabels().get("app.kubernetes.io/name")
-            )).collect(Collectors.toList());
-        } catch (Exception ex) {
-            LOGGER.error(ex.getMessage());
-            return List.of();
-        }
-    }
+//    public List<PodStatus> getDeploymentPodsStatuses(String name, String namespace) {
+//        try {
+//            String labelName = getRuntimeLabel();
+//            List<Pod> pods = kubernetesClient().pods().inNamespace(namespace)
+//                    .withLabel("app.kubernetes.io/name", name)
+//                    .withLabel(labelName, "camel")
+//                    .list().getItems();
+//
+//            return pods.stream().map(pod -> new PodStatus(
+//                    pod.getMetadata().getName(),
+//                    pod.getStatus().getContainerStatuses().get(0).getStarted(),
+//                    pod.getStatus().getContainerStatuses().get(0).getReady(),
+//                    getPodReason(pod),
+//                    pod.getMetadata().getLabels().get("app.kubernetes.io/name")
+//            )).collect(Collectors.toList());
+//        } catch (Exception ex) {
+//            LOGGER.error(ex.getMessage());
+//            return List.of();
+//        }
+//    }
 
     public Deployment getDeployment(String name, String namespace) {
         try {
@@ -370,7 +338,7 @@ public class KubernetesService {
     }
 
     public Secret getKaravanSecret() {
-        return kubernetesClient().secrets().inNamespace(currentNamespace).withName("karavan").get();
+        return kubernetesClient().secrets().inNamespace(getNamespace()).withName("karavan").get();
     }
 
     public String getRuntimeLabel() {
@@ -381,7 +349,14 @@ public class KubernetesService {
         return kubernetesClient().isAdaptable(OpenShiftClient.class);
     }
 
+    public String getCluster() {
+        return kubernetesClient().getMasterUrl().getHost();
+    }
+    public String getNamespace() {
+        return kubernetesClient().getNamespace();
+    }
+
     public boolean inKubernetes() {
-        return !Objects.equals(currentNamespace, "localhost");
+        return !Objects.equals(getNamespace(), "localhost");
     }
 }
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/service/StatusService.java b/karavan-app/src/main/java/org/apache/camel/karavan/service/StatusService.java
index 33cc888..a103326 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/service/StatusService.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/service/StatusService.java
@@ -24,7 +24,7 @@ import io.vertx.mutiny.core.buffer.Buffer;
 import io.vertx.mutiny.ext.web.client.HttpResponse;
 import io.vertx.mutiny.ext.web.client.WebClient;
 import org.apache.camel.karavan.model.CamelStatus;
-import org.apache.camel.karavan.model.KaravanConfiguration;
+import org.eclipse.microprofile.config.inject.ConfigProperty;
 import org.jboss.logging.Logger;
 
 import javax.enterprise.context.ApplicationScoped;
@@ -45,8 +45,8 @@ public class StatusService {
     @Inject
     KubernetesService kubernetesService;
 
-    @Inject
-    KaravanConfiguration configuration;
+    @ConfigProperty(name = "karavan.camel-status-threshold")
+    int threshold;
 
     private long lastCollect = 0;
 
@@ -65,21 +65,18 @@ public class StatusService {
 
     @ConsumeEvent(value = CMD_COLLECT_STATUSES, blocking = true, ordered = true)
     public void collectStatuses(String projectId) throws Exception {
-        if ((System.currentTimeMillis() - lastCollect) > configuration.statusThreshold()) {
+        if ((System.currentTimeMillis() - lastCollect) > threshold) {
             collectStatusesForProject(projectId);
             lastCollect = System.currentTimeMillis();
         }
     }
 
     private void collectStatusesForProject(String projectId) {
-        configuration.environments().stream().filter(e -> e.active()).forEach(e -> {
-            String url = ProfileManager.getActiveProfile().equals("dev")
-                    ? String.format("http://%s-%s.%s/q/health", projectId, e.namespace(), e.cluster())
-                    : String.format("http://%s.%s.%s/q/health", projectId, e.namespace(), e.cluster());
-            CamelStatus cs = getCamelStatus(projectId, url);
-            infinispanService.saveCamelStatus(cs);
-        });
-
+        String url = ProfileManager.getActiveProfile().equals("dev")
+                ? String.format("http://%s-%s.%s/q/health", projectId, kubernetesService.getNamespace(), kubernetesService.getCluster())
+                : String.format("http://%s.%s.%s/q/health", projectId, kubernetesService.getNamespace(), kubernetesService.getCluster());
+        CamelStatus cs = getCamelStatus(projectId, url);
+        infinispanService.saveCamelStatus(cs);
     }
 
     private CamelStatus getCamelStatus(String projectId, String url) {
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/watcher/DeploymentWatcher.java b/karavan-app/src/main/java/org/apache/camel/karavan/watcher/DeploymentWatcher.java
index 8f635f3..3177e1e 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/watcher/DeploymentWatcher.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/watcher/DeploymentWatcher.java
@@ -26,29 +26,42 @@ public class DeploymentWatcher implements Watcher<Deployment> {
     @Override
     public void eventReceived(Watcher.Action action, Deployment deployment) {
         LOGGER.info(action.name() + " " + deployment.getMetadata().getName());
-        Project project = infinispanService.getProject(deployment.getMetadata().getName());
-        if (project != null) {
-            switch (action.name()) {
-                case "ADDED":
-                    project.setDeployed(true);
-                    infinispanService.saveProject(project);
-                    DeploymentStatus s = kubernetesService.getDeploymentStatus(project.getProjectId(), deployment);
-                    infinispanService.saveDeploymentStatus(s);
-                    break;
-                case "MODIFIED":
-                    if (!project.getDeployed()) {
-                        project.setDeployed(true);
-                        infinispanService.saveProject(project);
-                    }
-                    DeploymentStatus ds = kubernetesService.getDeploymentStatus(project.getProjectId(), deployment);
-                    infinispanService.saveDeploymentStatus(ds);
-                    break;
-                case "DELETED":
-                    project.setDeployed(false);
-                    infinispanService.saveProject(project);
-                    infinispanService.saveDeploymentStatus(new DeploymentStatus(project.getProjectId()));
-                    break;
-            }
+        DeploymentStatus ds = getDeploymentStatus(deployment);
+        switch (action.name()) {
+            case "ADDED":
+                infinispanService.saveDeploymentStatus(ds);
+                break;
+            case "MODIFIED":
+                infinispanService.saveDeploymentStatus(ds);
+                break;
+            case "DELETED":
+                infinispanService.deleteDeploymentStatus(ds);
+                break;
+        }
+    }
+
+    public DeploymentStatus getDeploymentStatus(Deployment deployment) {
+        try {
+            String dsImage = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage();
+            String imageName = dsImage.startsWith("image-registry.openshift-image-registry.svc")
+                    ? dsImage.replace("image-registry.openshift-image-registry.svc:5000/", "")
+                    : dsImage;
+
+            return new DeploymentStatus(
+                    deployment.getMetadata().getName(),
+                    deployment.getMetadata().getNamespace(),
+                    kubernetesService.environment,
+                    imageName,
+                    deployment.getSpec().getReplicas(),
+                    deployment.getStatus().getReadyReplicas(),
+                    deployment.getStatus().getUnavailableReplicas()
+            );
+        } catch (Exception ex) {
+            LOGGER.error(ex.getMessage());
+            return new DeploymentStatus(
+                    deployment.getMetadata().getName(),
+                    deployment.getMetadata().getNamespace(),
+                    kubernetesService.environment);
         }
     }
 
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/watcher/PipelineRunWatcher.java b/karavan-app/src/main/java/org/apache/camel/karavan/watcher/PipelineRunWatcher.java
index df966a3..1e1ba3a 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/watcher/PipelineRunWatcher.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/watcher/PipelineRunWatcher.java
@@ -6,6 +6,7 @@ import io.fabric8.tekton.pipeline.v1beta1.PipelineRun;
 import org.apache.camel.karavan.model.PipelineStatus;
 import org.apache.camel.karavan.model.Project;
 import org.apache.camel.karavan.service.InfinispanService;
+import org.apache.camel.karavan.service.KubernetesService;
 import org.jboss.logging.Logger;
 
 import java.time.Instant;
@@ -15,9 +16,11 @@ public class PipelineRunWatcher implements Watcher<PipelineRun> {
 
     private static final Logger LOGGER = Logger.getLogger(PipelineRunWatcher.class.getName());
     private InfinispanService infinispanService;
+    private KubernetesService kubernetesService;
 
-    public PipelineRunWatcher(InfinispanService infinispanService) {
+    public PipelineRunWatcher(InfinispanService infinispanService, KubernetesService kubernetesService) {
         this.infinispanService = infinispanService;
+        this.kubernetesService = kubernetesService;
     }
 
     @Override
@@ -28,7 +31,7 @@ public class PipelineRunWatcher implements Watcher<PipelineRun> {
             Project project = infinispanService.getProject(projectId);
             if (project != null && List.of("MODIFIED", "ADDED").contains(action.name())) {
                 PipelineStatus pipelineStatus = infinispanService.getPipelineStatus(projectId);
-                if (pipelineStatus == null) pipelineStatus = new PipelineStatus(project.getProjectId());
+                if (pipelineStatus == null) pipelineStatus = new PipelineStatus(project.getProjectId(), kubernetesService.environment);
 
                 if (pipelineRun.getStatus() != null) {
                     LOGGER.info(action.name()+ " " + pipelineRun.getMetadata().getName() + " " + pipelineRun.getStatus().getConditions().get(0).getReason());
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/watcher/PodWatcher.java b/karavan-app/src/main/java/org/apache/camel/karavan/watcher/PodWatcher.java
index 23fb200..99e0982 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/watcher/PodWatcher.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/watcher/PodWatcher.java
@@ -25,12 +25,12 @@ public class PodWatcher implements Watcher<Pod> {
     public void eventReceived(Action action, Pod pod) {
         LOGGER.info(action.name() + " " + pod.getMetadata().getName());
         String name = pod.getMetadata().getLabels().get("app.kubernetes.io/name");
-        Project project = infinispanService.getProject(name);
-        Deployment deployment = kubernetesService.getDeployment(name, pod.getMetadata().getNamespace());
-        if (project != null && deployment != null) {
-            DeploymentStatus s = kubernetesService.getDeploymentStatus(project.getProjectId(), deployment);
-            infinispanService.saveDeploymentStatus(s);
-        }
+//        Project project = infinispanService.getProject(name);
+//        Deployment deployment = kubernetesService.getDeployment(name, pod.getMetadata().getNamespace());
+//        if (project != null && deployment != null) {
+//            DeploymentStatus s = kubernetesService.getDeploymentStatus(project.getProjectId(), deployment);
+//            infinispanService.saveDeploymentStatus(s);
+//        }
     }
 
     @Override
diff --git a/karavan-app/src/main/resources/application.properties b/karavan-app/src/main/resources/application.properties
index a0f2b84..6c1a38c 100644
--- a/karavan-app/src/main/resources/application.properties
+++ b/karavan-app/src/main/resources/application.properties
@@ -1,4 +1,7 @@
 karavan.version=3.18.5
+karavan.environment=dev
+karavan.pipeline=karavan-pipeline-build-quarkus
+karavan.camel-status-threshold=2000
 
 # Git repository Configuration
 karavan.projects-git-repository=${GIT_REPOSITORY}
@@ -12,34 +15,11 @@ karavan.kamelets-git-username=${GIT_USERNAME}
 karavan.kamelets-git-password=${GIT_TOKEN}
 karavan.kamelets-git-branch=main
 
-# Projects configuration
+# Projects default configuration
 karavan.config.group-id=org.camel.karavan.demo
 karavan.config.image-group=karavan
 karavan.config.runtime=QUARKUS
 karavan.config.runtime-version=2.13.3.Final
-karavan.config.status-threshold=2000
-
-karavan.config.environments[0].name=dev
-karavan.config.environments[0].namespace=karavan
-karavan.config.environments[0].pipeline=karavan-quarkus
-karavan.config.environments[0].cluster=svc.cluster.local
-karavan.config.environments[0].active=true
-
-karavan.config.environments[1].name=test
-karavan.config.environments[1].namespace=test
-karavan.config.environments[1].pipeline=karavan-quarkus
-karavan.config.environments[1].cluster=svc.cluster.local
-karavan.config.environments[1].active=false
-
-karavan.config.environments[2].name=prod
-karavan.config.environments[2].namespace=prod
-karavan.config.environments[2].pipeline=karavan-quarkus
-karavan.config.environments[2].cluster=svc.cluster.local
-karavan.config.environments[2].active=false
-
-%dev.karavan.config.environments[0].cluster=apps.home.myocp.net 
-%dev.karavan.config.environments[1].cluster=apps.home.myocp.net
-%dev.karavan.config.environments[2].cluster=apps.home.myocp.net
 
 # Infinispan Server address
 #quarkus.infinispan-client.server-list=localhost:12345
diff --git a/karavan-app/src/main/webapp/package-lock.json b/karavan-app/src/main/webapp/package-lock.json
index 81e84ae..6af2d60 100644
--- a/karavan-app/src/main/webapp/package-lock.json
+++ b/karavan-app/src/main/webapp/package-lock.json
@@ -47,7 +47,8 @@
         "@types/js-yaml": "^4.0.5",
         "@types/uuid": "^8.3.4",
         "typescript": "^4.5.5",
-        "uuid": "8.3.2"
+        "uuid": "8.3.2",
+        "yaml": "^2.1.3"
       },
       "devDependencies": {
         "@types/chai": "^4.3.0",
@@ -24573,7 +24574,8 @@
         "mocha": "^9.2.0",
         "ts-node": "^10.4.0",
         "typescript": "^4.5.5",
-        "uuid": "8.3.2"
+        "uuid": "8.3.2",
+        "yaml": "^2.1.3"
       }
     },
     "keycloak-js": {
diff --git a/karavan-app/src/main/webapp/src/api/KaravanApi.tsx b/karavan-app/src/main/webapp/src/api/KaravanApi.tsx
index 0d400b2..50379ba 100644
--- a/karavan-app/src/main/webapp/src/api/KaravanApi.tsx
+++ b/karavan-app/src/main/webapp/src/api/KaravanApi.tsx
@@ -160,8 +160,8 @@ export class KaravanApi {
         });
     }
 
-    static async getProjectDeploymentStatus(projectId: string, after: (status: DeploymentStatus) => void) {
-        instance.get('/api/status/deployment/' + projectId)
+    static async getProjectDeploymentStatus(projectId: string, env: string, after: (status: DeploymentStatus) => void) {
+        instance.get('/api/status/deployment/' + projectId + "/" + env)
             .then(res => {
                 if (res.status === 200) {
                     after(res.data);
diff --git a/karavan-app/src/main/webapp/src/projects/ProjectInfo.tsx b/karavan-app/src/main/webapp/src/projects/ProjectInfo.tsx
index 24eed8e..16ce1a3 100644
--- a/karavan-app/src/main/webapp/src/projects/ProjectInfo.tsx
+++ b/karavan-app/src/main/webapp/src/projects/ProjectInfo.tsx
@@ -85,7 +85,7 @@ export class ProjectInfo extends React.Component<Props, State> {
                 this.setState({key: Math.random().toString(), pipelineStatus: status});
                 // console.log(status);
             });
-            KaravanApi.getProjectDeploymentStatus(this.props.project.projectId, (status: DeploymentStatus) => {
+            KaravanApi.getProjectDeploymentStatus(this.props.project.projectId, this.state.environment, (status: DeploymentStatus) => {
                 this.setState({key: Math.random().toString(), deploymentStatus: status});
                 // console.log(status);
             });