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/13 16:10:10 UTC

[camel-karavan] 06/07: Hot reload In docker #817

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 f4db398c1a3ff5fd4006c0697c77b9f4c709d788
Author: Marat Gubaidullin <ma...@gmail.com>
AuthorDate: Thu Jul 13 11:43:11 2023 -0400

    Hot reload In docker #817
---
 .../apache/camel/karavan/api/DevModeResource.java  | 11 +++-----
 .../camel/karavan/handler/PodEventHandler.java     |  2 +-
 .../karavan/listener/DevModeCommandListener.java   |  2 +-
 .../karavan/listener/DevModeStatusListener.java    | 29 ++++++++++++++++++++++
 .../{CamelStatusService.java => CamelService.java} | 11 ++++----
 .../camel/karavan/bashi/ConductorService.java      | 14 +++++------
 .../karavan/bashi/docker/DockerEventListener.java  | 11 +++++++-
 .../camel/karavan/bashi/docker/DockerService.java  |  7 ++++--
 .../camel/karavan/datagrid/DatagridService.java    | 20 +++++++++------
 ...erListener.java => DevModeCommandListener.java} |  4 +--
 ...nerListener.java => DevModeStatusListener.java} |  8 +++---
 11 files changed, 80 insertions(+), 39 deletions(-)

diff --git a/karavan-cloud/karavan-app/src/main/java/org/apache/camel/karavan/api/DevModeResource.java b/karavan-cloud/karavan-app/src/main/java/org/apache/camel/karavan/api/DevModeResource.java
index 3cdef756..f56ad4d3 100644
--- a/karavan-cloud/karavan-app/src/main/java/org/apache/camel/karavan/api/DevModeResource.java
+++ b/karavan-cloud/karavan-app/src/main/java/org/apache/camel/karavan/api/DevModeResource.java
@@ -18,7 +18,7 @@ package org.apache.camel.karavan.api;
 
 import org.apache.camel.karavan.datagrid.DatagridService;
 import org.apache.camel.karavan.datagrid.model.*;
-import org.apache.camel.karavan.service.CamelStatusService;
+import org.apache.camel.karavan.service.CamelService;
 import org.eclipse.microprofile.config.inject.ConfigProperty;
 
 import javax.inject.Inject;
@@ -34,7 +34,7 @@ import javax.ws.rs.core.Response;
 import java.time.Instant;
 import java.util.Optional;
 
-import static org.apache.camel.karavan.service.CamelStatusService.DEVMODE_SUFFIX;
+import static org.apache.camel.karavan.service.CamelService.DEVMODE_SUFFIX;
 
 @Path("/api/devmode")
 public class DevModeResource {
@@ -43,7 +43,7 @@ public class DevModeResource {
     String environment;
 
     @Inject
-    CamelStatusService camelStatusService;
+    CamelService camelService;
 
     @Inject
     DatagridService datagridService;
@@ -74,10 +74,7 @@ public class DevModeResource {
     @Produces(MediaType.APPLICATION_JSON)
     @Path("/reload/{projectId}")
     public Response reload(@PathParam("projectId") String projectId) {
-        camelStatusService.reloadProjectCode(projectId);
-        DevModeStatus dms = datagridService.getDevModeStatus(projectId);
-        dms.setCodeLoaded(true);
-        datagridService.saveDevModeStatus(dms);
+        camelService.reloadProjectCode(projectId);
         return Response.ok().build();
     }
 
diff --git a/karavan-cloud/karavan-app/src/main/java/org/apache/camel/karavan/handler/PodEventHandler.java b/karavan-cloud/karavan-app/src/main/java/org/apache/camel/karavan/handler/PodEventHandler.java
index a834829b..2a79bd7b 100644
--- a/karavan-cloud/karavan-app/src/main/java/org/apache/camel/karavan/handler/PodEventHandler.java
+++ b/karavan-cloud/karavan-app/src/main/java/org/apache/camel/karavan/handler/PodEventHandler.java
@@ -11,7 +11,7 @@ import org.apache.camel.karavan.service.KubernetesService;
 import org.jboss.logging.Logger;
 
 import static org.apache.camel.karavan.service.CodeService.DEFAULT_CONTAINER_RESOURCES;
-import static org.apache.camel.karavan.service.CamelStatusService.DEVMODE_SUFFIX;
+import static org.apache.camel.karavan.service.CamelService.DEVMODE_SUFFIX;
 
 public class PodEventHandler implements ResourceEventHandler<Pod> {
 
diff --git a/karavan-cloud/karavan-app/src/main/java/org/apache/camel/karavan/listener/DevModeCommandListener.java b/karavan-cloud/karavan-app/src/main/java/org/apache/camel/karavan/listener/DevModeCommandListener.java
index 32d83ce8..26fea711 100644
--- a/karavan-cloud/karavan-app/src/main/java/org/apache/camel/karavan/listener/DevModeCommandListener.java
+++ b/karavan-cloud/karavan-app/src/main/java/org/apache/camel/karavan/listener/DevModeCommandListener.java
@@ -14,7 +14,7 @@ import javax.inject.Inject;
 
 import java.util.Objects;
 
-import static org.apache.camel.karavan.service.CamelStatusService.DEVMODE_SUFFIX;
+import static org.apache.camel.karavan.service.CamelService.DEVMODE_SUFFIX;
 
 @ApplicationScoped
 public class DevModeCommandListener {
diff --git a/karavan-cloud/karavan-app/src/main/java/org/apache/camel/karavan/listener/DevModeStatusListener.java b/karavan-cloud/karavan-app/src/main/java/org/apache/camel/karavan/listener/DevModeStatusListener.java
new file mode 100644
index 00000000..15d63519
--- /dev/null
+++ b/karavan-cloud/karavan-app/src/main/java/org/apache/camel/karavan/listener/DevModeStatusListener.java
@@ -0,0 +1,29 @@
+package org.apache.camel.karavan.listener;
+
+import io.quarkus.vertx.ConsumeEvent;
+import io.vertx.core.json.JsonObject;
+import org.apache.camel.karavan.datagrid.DatagridService;
+import org.apache.camel.karavan.datagrid.model.DevModeStatus;
+import org.apache.camel.karavan.service.CamelService;
+import org.jboss.logging.Logger;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+@ApplicationScoped
+public class DevModeStatusListener {
+
+    private static final Logger LOGGER = Logger.getLogger(DevModeStatusListener.class.getName());
+
+    @Inject
+    CamelService camelService;
+
+    @ConsumeEvent(value = DatagridService.ADDRESS_DEVMODE_STATUS, blocking = true, ordered = true)
+    void receiveCommand(JsonObject message) {
+        LOGGER.info("received Status " + message);
+        DevModeStatus status = message.mapTo(DevModeStatus.class);
+        if (!status.isCodeLoaded() && status.getContainerId() != null) {
+            camelService.reloadProjectCode(status.getProjectId());
+        }
+    }
+}
\ No newline at end of file
diff --git a/karavan-cloud/karavan-app/src/main/java/org/apache/camel/karavan/service/CamelStatusService.java b/karavan-cloud/karavan-app/src/main/java/org/apache/camel/karavan/service/CamelService.java
similarity index 96%
rename from karavan-cloud/karavan-app/src/main/java/org/apache/camel/karavan/service/CamelStatusService.java
rename to karavan-cloud/karavan-app/src/main/java/org/apache/camel/karavan/service/CamelService.java
index a3ef1288..3f3ee96d 100644
--- a/karavan-cloud/karavan-app/src/main/java/org/apache/camel/karavan/service/CamelStatusService.java
+++ b/karavan-cloud/karavan-app/src/main/java/org/apache/camel/karavan/service/CamelService.java
@@ -37,9 +37,9 @@ import java.util.Objects;
 import java.util.concurrent.ExecutionException;
 
 @ApplicationScoped
-public class CamelStatusService {
+public class CamelService {
 
-    private static final Logger LOGGER = Logger.getLogger(CamelStatusService.class.getName());
+    private static final Logger LOGGER = Logger.getLogger(CamelService.class.getName());
     public static final String CMD_COLLECT_CAMEL_STATUS = "collect-camel-status";
     public static final String CMD_DELETE_CAMEL_STATUS = "delete-camel-status";
     public static final String DEVMODE_SUFFIX = "devmode";
@@ -74,10 +74,12 @@ public class CamelStatusService {
         try {
             datagridService.getProjectFiles(projectId).forEach(projectFile -> putRequest(containerName, projectFile.getName(), projectFile.getCode(), 1000));
             reloadRequest(containerName);
+            DevModeStatus dms = datagridService.getDevModeStatus(projectId);
+            dms.setCodeLoaded(true);
+            datagridService.saveDevModeStatus(dms);
         } catch (Exception ex) {
             LOGGER.error(ex.getMessage());
         }
-        datagridService.deleteDevModeStatus(projectId);
     }
 
     @CircuitBreaker(requestVolumeThreshold = 10, failureRatio = 0.5, delay = 1000)
@@ -113,7 +115,6 @@ public class CamelStatusService {
 
     @Scheduled(every = "{karavan.devmode-status-interval}", concurrentExecution = Scheduled.ConcurrentExecution.SKIP)
     void collectDevModeStatuses() {
-        System.out.println("Collect DevMode Statuses");
         if (datagridService.isReady()) {
             datagridService.getDevModeStatuses().forEach(dms -> {
                 CamelStatusRequest csr = new CamelStatusRequest(dms.getProjectId(), dms.getContainerName());
@@ -124,7 +125,6 @@ public class CamelStatusService {
 
     @Scheduled(every = "{karavan.camel-status-interval}", concurrentExecution = Scheduled.ConcurrentExecution.SKIP)
     void collectNonDevModeStatuses() {
-        System.out.println("Collect NonDevMode Statuses");
         if (datagridService.isReady()) {
             datagridService.getPodStatuses(environment).forEach(pod -> {
                 CamelStatusRequest csr = new CamelStatusRequest(pod.getProjectId(), pod.getName());
@@ -148,7 +148,6 @@ public class CamelStatusService {
 
     @Scheduled(every = "{karavan.devmode-status-interval}", concurrentExecution = Scheduled.ConcurrentExecution.SKIP)
     void cleanupDevModeStatuses() {
-        System.out.println("Clean DevMode Statuses");
         if (datagridService.isReady()) {
             datagridService.getDevModeStatuses().forEach(dms -> {
                 PodStatus pod = datagridService.getDevModePodStatuses(dms.getProjectId(), environment);
diff --git a/karavan-cloud/karavan-bashi/src/main/java/org/apache/camel/karavan/bashi/ConductorService.java b/karavan-cloud/karavan-bashi/src/main/java/org/apache/camel/karavan/bashi/ConductorService.java
index 7f4f0147..09548632 100644
--- a/karavan-cloud/karavan-bashi/src/main/java/org/apache/camel/karavan/bashi/ConductorService.java
+++ b/karavan-cloud/karavan-bashi/src/main/java/org/apache/camel/karavan/bashi/ConductorService.java
@@ -110,17 +110,17 @@ public class ConductorService {
         Project p = datagridService.getProject(command.getProjectId());
         if (Objects.equals(command.getCommandName(), CommandName.RUN)) {
             LOGGER.infof("DevMode starting for %s", p.getProjectId());
-            Container container = dockerService.createContainer(containerName, runnerImage,
-                    List.of(), "", false, new HealthCheck(), Map.of("type", "runner")
+
+            HealthCheck healthCheck = new HealthCheck().withTest(List.of("CMD", "curl", "-f", "http://localhost:8080/q/dev/health"))
+                    .withInterval(10000000000L).withTimeout(10000000000L).withStartPeriod(10000000000L).withRetries(30);
+
+            dockerService.createContainer(containerName, runnerImage,
+                    List.of(), "", false, healthCheck,
+                    Map.of("type", "devmode", "projectId", p.getProjectId())
             );
             dockerService.startContainer(containerName);
             LOGGER.infof("DevMode started for %s", p.getProjectId());
 
-            // update DevModeStatus
-            DevModeStatus dms = datagridService.getDevModeStatus(p.getProjectId());
-            dms.setContainerName(containerName);
-            dms.setContainerId(container.getId());
-            datagridService.saveDevModeStatus(dms);
         } else if (Objects.equals(command.getCommandName(), CommandName.DELETE)){
             dockerService.stopContainer(containerName);
             dockerService.deleteContainer(containerName);
diff --git a/karavan-cloud/karavan-bashi/src/main/java/org/apache/camel/karavan/bashi/docker/DockerEventListener.java b/karavan-cloud/karavan-bashi/src/main/java/org/apache/camel/karavan/bashi/docker/DockerEventListener.java
index db7b8358..4910e603 100644
--- a/karavan-cloud/karavan-bashi/src/main/java/org/apache/camel/karavan/bashi/docker/DockerEventListener.java
+++ b/karavan-cloud/karavan-bashi/src/main/java/org/apache/camel/karavan/bashi/docker/DockerEventListener.java
@@ -8,6 +8,7 @@ import io.vertx.core.eventbus.EventBus;
 import org.apache.camel.karavan.bashi.ConductorService;
 import org.apache.camel.karavan.bashi.Constants;
 import org.apache.camel.karavan.datagrid.DatagridService;
+import org.apache.camel.karavan.datagrid.model.DevModeStatus;
 import org.apache.camel.karavan.datagrid.model.PodStatus;
 import org.eclipse.microprofile.config.inject.ConfigProperty;
 import org.jboss.logging.Logger;
@@ -44,7 +45,6 @@ public class DockerEventListener implements ResultCallback<Event> {
 
     @Override
     public void onNext(Event event) {
-//        LOGGER.info(event.getType() + " : " + event.getStatus());
         try {
             if (Objects.equals(event.getType(), EventType.CONTAINER)) {
                 Container container = dockerService.getContainer(event.getId());
@@ -53,6 +53,15 @@ public class DockerEventListener implements ResultCallback<Event> {
                     String health = status.replace("health_status: ", "");
                     LOGGER.infof("Container %s health status: %s", container.getNames()[0], health);
                     eventBus.publish(ConductorService.ADDRESS_INFINISPAN_HEALTH, health);
+                } else if (Objects.equals(container.getLabels().get("type"), "devmode") && status.startsWith("health_status:")) {
+                    String health = status.replace("health_status: ", "");
+                    LOGGER.infof("Container %s health status: %s", container.getNames()[0], health);
+//                     update DevModeStatus
+                    String containerName = container.getNames()[0].replace("/", "");
+                    DevModeStatus dms = datagridService.getDevModeStatus(container.getLabels().get("projectId"));
+                    dms.setContainerName(containerName);
+                    dms.setContainerId(container.getId());
+                    datagridService.saveDevModeStatus(dms);
                 } else if (container.getNames()[0].endsWith(Constants.DEVMODE_SUFFIX)) {
                     if (Arrays.asList("stop", "die", "kill", "pause", "destroy").contains(event.getStatus())) {
                         String name = container.getNames()[0].replace("/", "");
diff --git a/karavan-cloud/karavan-bashi/src/main/java/org/apache/camel/karavan/bashi/docker/DockerService.java b/karavan-cloud/karavan-bashi/src/main/java/org/apache/camel/karavan/bashi/docker/DockerService.java
index 80558b5f..eb4c8ef3 100644
--- a/karavan-cloud/karavan-bashi/src/main/java/org/apache/camel/karavan/bashi/docker/DockerService.java
+++ b/karavan-cloud/karavan-bashi/src/main/java/org/apache/camel/karavan/bashi/docker/DockerService.java
@@ -49,7 +49,6 @@ public class DockerService {
 
     @Scheduled(every = "{karavan.container-stats-interval}", concurrentExecution = Scheduled.ConcurrentExecution.SKIP)
     void collectContainersStats() {
-        System.out.println("collectContainersStats ");
         getDockerClient().listContainersCmd().exec().forEach(container -> {
             Statistics stats = getContainerStats(container.getId());
 
@@ -106,7 +105,11 @@ public class DockerService {
         if (!getDockerClient().listNetworksCmd().exec().stream()
                 .filter(n -> n.getName().equals(NETWORK_NAME))
                 .findFirst().isPresent()) {
-            CreateNetworkResponse res = getDockerClient().createNetworkCmd().withName(NETWORK_NAME).withAttachable(true).exec();
+            CreateNetworkResponse res = getDockerClient().createNetworkCmd()
+                    .withName(NETWORK_NAME)
+                    .withDriver("bridge")
+                    .withInternal(false)
+                    .withAttachable(true).exec();
             LOGGER.info("Network created: {}" + res);
         } else {
             LOGGER.info("Network already exists with name: " + NETWORK_NAME);
diff --git a/karavan-cloud/karavan-datagrid/src/main/java/org/apache/camel/karavan/datagrid/DatagridService.java b/karavan-cloud/karavan-datagrid/src/main/java/org/apache/camel/karavan/datagrid/DatagridService.java
index 5535211c..38f40026 100644
--- a/karavan-cloud/karavan-datagrid/src/main/java/org/apache/camel/karavan/datagrid/DatagridService.java
+++ b/karavan-cloud/karavan-datagrid/src/main/java/org/apache/camel/karavan/datagrid/DatagridService.java
@@ -28,11 +28,9 @@ 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.client.hotrod.impl.query.RemoteQuery;
 import org.infinispan.commons.configuration.StringConfiguration;
 import org.infinispan.commons.marshall.ProtoStreamMarshaller;
 import org.infinispan.query.dsl.QueryFactory;
-import org.infinispan.query.remote.client.ProtobufMetadataManagerConstants;
 import org.jboss.logging.Logger;
 
 import javax.enterprise.context.ApplicationScoped;
@@ -41,10 +39,6 @@ import javax.inject.Inject;
 import java.io.BufferedReader;
 import java.io.InputStream;
 import java.io.InputStreamReader;
-import java.net.URISyntaxException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.time.Instant;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
@@ -58,7 +52,9 @@ import static org.infinispan.query.remote.client.ProtobufMetadataManagerConstant
 public class DatagridService  {
 
     public static final String ADDRESS_DEVMODE_COMMAND = "ADDRESS_DEVMODE_COMMAND";
+    public static final String ADDRESS_DEVMODE_STATUS = "ADDRESS_DEVMODE_STATUS";
     protected static final String ADDRESS_DEVMODE_COMMAND_INTERNAL = "ADDRESS_DEVMODE_COMMAND_INTERNAL";
+    protected static final String ADDRESS_DEVMODE_STATUS_INTERNAL = "ADDRESS_DEVMODE_STATUS_INTERNAL";
 
     @ConfigProperty(name ="quarkus.infinispan-client.hosts")
     String infinispanHosts;
@@ -126,7 +122,8 @@ public class DatagridService  {
         devmodeStatuses = getOrCreateCache(DevModeStatus.CACHE, false);
         devmodeCommands = getOrCreateCache(DevModeCommand.CACHE, true);
 
-        cacheManager.getCache(DevModeCommand.CACHE).addClientListener(new ClientRunnerListener(eventBus));
+        cacheManager.getCache(DevModeCommand.CACHE).addClientListener(new DevModeCommandListener(eventBus));
+        cacheManager.getCache(DevModeStatus.CACHE).addClientListener(new DevModeStatusListener(eventBus));
         // Grab the generated protobuf schema and registers in the server.
         cacheManager.getCache(PROTOBUF_METADATA_CACHE_NAME).put("karavan.proto", getResourceFile("/proto/karavan.proto"));
 
@@ -153,12 +150,19 @@ public class DatagridService  {
     }
 
     @ConsumeEvent(value = ADDRESS_DEVMODE_COMMAND_INTERNAL, blocking = true, ordered = true, local = false)
-    void replyAsync(JsonObject message) {
+    void sendCommand(JsonObject message) {
         GroupedKey key = message.mapTo(GroupedKey.class);
         DevModeCommand command = getDevModeCommand(key);
         eventBus.publish(DatagridService.ADDRESS_DEVMODE_COMMAND, JsonObject.mapFrom(command));
     }
 
+    @ConsumeEvent(value = ADDRESS_DEVMODE_STATUS_INTERNAL, blocking = true, ordered = true, local = false)
+    void sendStatus(JsonObject message) {
+        GroupedKey key = message.mapTo(GroupedKey.class);
+        DevModeStatus status = devmodeStatuses.get(key);
+        eventBus.publish(DatagridService.ADDRESS_DEVMODE_STATUS, JsonObject.mapFrom(status));
+    }
+
     public List<Project> getProjects() {
         return projects.values().stream().collect(Collectors.toList());
     }
diff --git a/karavan-cloud/karavan-datagrid/src/main/java/org/apache/camel/karavan/datagrid/ClientRunnerListener.java b/karavan-cloud/karavan-datagrid/src/main/java/org/apache/camel/karavan/datagrid/DevModeCommandListener.java
similarity index 92%
copy from karavan-cloud/karavan-datagrid/src/main/java/org/apache/camel/karavan/datagrid/ClientRunnerListener.java
copy to karavan-cloud/karavan-datagrid/src/main/java/org/apache/camel/karavan/datagrid/DevModeCommandListener.java
index 8c33ac90..09f07eaa 100644
--- a/karavan-cloud/karavan-datagrid/src/main/java/org/apache/camel/karavan/datagrid/ClientRunnerListener.java
+++ b/karavan-cloud/karavan-datagrid/src/main/java/org/apache/camel/karavan/datagrid/DevModeCommandListener.java
@@ -10,11 +10,11 @@ import org.infinispan.client.hotrod.event.ClientCacheEntryCreatedEvent;
 import org.infinispan.client.hotrod.event.ClientCacheEntryModifiedEvent;
 
 @ClientListener
-public class ClientRunnerListener {
+public class DevModeCommandListener {
 
     private final EventBus eventBus;
 
-    public ClientRunnerListener(EventBus eventBus) {
+    public DevModeCommandListener(EventBus eventBus) {
         this.eventBus = eventBus;
     }
 
diff --git a/karavan-cloud/karavan-datagrid/src/main/java/org/apache/camel/karavan/datagrid/ClientRunnerListener.java b/karavan-cloud/karavan-datagrid/src/main/java/org/apache/camel/karavan/datagrid/DevModeStatusListener.java
similarity index 73%
rename from karavan-cloud/karavan-datagrid/src/main/java/org/apache/camel/karavan/datagrid/ClientRunnerListener.java
rename to karavan-cloud/karavan-datagrid/src/main/java/org/apache/camel/karavan/datagrid/DevModeStatusListener.java
index 8c33ac90..7d9a88b4 100644
--- a/karavan-cloud/karavan-datagrid/src/main/java/org/apache/camel/karavan/datagrid/ClientRunnerListener.java
+++ b/karavan-cloud/karavan-datagrid/src/main/java/org/apache/camel/karavan/datagrid/DevModeStatusListener.java
@@ -10,22 +10,22 @@ import org.infinispan.client.hotrod.event.ClientCacheEntryCreatedEvent;
 import org.infinispan.client.hotrod.event.ClientCacheEntryModifiedEvent;
 
 @ClientListener
-public class ClientRunnerListener {
+public class DevModeStatusListener {
 
     private final EventBus eventBus;
 
-    public ClientRunnerListener(EventBus eventBus) {
+    public DevModeStatusListener(EventBus eventBus) {
         this.eventBus = eventBus;
     }
 
     @ClientCacheEntryCreated
     public void entryCreated(ClientCacheEntryCreatedEvent<GroupedKey> event) {
-        eventBus.publish(DatagridService.ADDRESS_DEVMODE_COMMAND_INTERNAL, JsonObject.mapFrom(event.getKey()));
+        eventBus.publish(DatagridService.ADDRESS_DEVMODE_STATUS_INTERNAL, JsonObject.mapFrom(event.getKey()));
     }
 
     @ClientCacheEntryModified
     public void entryModified(ClientCacheEntryModifiedEvent<GroupedKey> event) {
-        eventBus.publish(DatagridService.ADDRESS_DEVMODE_COMMAND_INTERNAL, JsonObject.mapFrom(event.getKey()));
+        eventBus.publish(DatagridService.ADDRESS_DEVMODE_STATUS_INTERNAL, JsonObject.mapFrom(event.getKey()));
     }
 
 }
\ No newline at end of file