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/09/08 23:48:34 UTC
[camel-karavan] 01/05: Run prod container for #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 b9985be44545422ab24fd62852f045fc9234e096
Author: Marat Gubaidullin <ma...@talismancloud.io>
AuthorDate: Fri Sep 8 17:52:42 2023 -0400
Run prod container for #817
---
karavan-designer/src/designer/karavan.css | 3 +-
...ructureResource.java => ContainerResource.java} | 190 +++------------------
.../apache/camel/karavan/api/ImagesResource.java | 15 ++
.../camel/karavan/api/InfrastructureResource.java | 154 +----------------
.../camel/karavan/docker/DockerForKaravan.java | 18 +-
.../apache/camel/karavan/docker/DockerService.java | 46 +++--
.../karavan/infinispan/model/ContainerStatus.java | 33 ++++
.../apache/camel/karavan/service/CamelService.java | 27 +--
.../karavan/service/ContainerStatusService.java | 56 ++++++
.../camel/karavan/service/ProjectService.java | 8 +
.../camel/karavan/service/ScheduledService.java | 100 -----------
.../camel-main-docker-application.properties | 3 +
.../src/main/webui/src/api/KaravanApi.tsx | 27 ++-
.../src/main/webui/src/api/ProjectModels.ts | 2 +-
.../src/main/webui/src/project/BuildToolbar.tsx | 84 ++++++++-
.../webui/src/project/build/ProjectBuildTab.tsx | 2 +-
.../src/project/trace/RunnerInfoTraceModal.tsx | 1 -
17 files changed, 288 insertions(+), 481 deletions(-)
diff --git a/karavan-designer/src/designer/karavan.css b/karavan-designer/src/designer/karavan.css
index 11324971..bf4d9d49 100644
--- a/karavan-designer/src/designer/karavan.css
+++ b/karavan-designer/src/designer/karavan.css
@@ -38,7 +38,8 @@
height: 36px;
}
-.karavan .pf-v5-c-switch__input:focus ~ .pf-v5-c-switch__toggle {
+.karavan .pf-v5-c-switch__input:focus ~ .pf-v5-c-switch__toggle,
+.pf-v5-c-modal-box .pf-v5-c-switch__input:focus ~ .pf-v5-c-switch__toggle {
outline: transparent;
outline-offset: 0;
}
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/InfrastructureResource.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ContainerResource.java
similarity index 52%
copy from karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/InfrastructureResource.java
copy to karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ContainerResource.java
index f6408f84..8a237d20 100644
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/InfrastructureResource.java
+++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ContainerResource.java
@@ -20,26 +20,23 @@ 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 jakarta.inject.Inject;
+import jakarta.ws.rs.*;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import org.apache.camel.karavan.code.CodeService;
import org.apache.camel.karavan.code.DockerComposeConverter;
+import org.apache.camel.karavan.code.model.DockerComposeService;
import org.apache.camel.karavan.docker.DockerForKaravan;
import org.apache.camel.karavan.docker.DockerService;
-import org.apache.camel.karavan.code.model.DockerComposeService;
import org.apache.camel.karavan.infinispan.InfinispanService;
import org.apache.camel.karavan.infinispan.model.ContainerStatus;
-import org.apache.camel.karavan.infinispan.model.DeploymentStatus;
-import org.apache.camel.karavan.infinispan.model.Project;
-import org.apache.camel.karavan.infinispan.model.ServiceStatus;
import org.apache.camel.karavan.kubernetes.KubernetesService;
-import org.apache.camel.karavan.code.CodeService;
-import org.apache.camel.karavan.service.ProjectService;
import org.apache.camel.karavan.service.ConfigService;
+import org.apache.camel.karavan.service.ProjectService;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.jboss.logging.Logger;
-import jakarta.inject.Inject;
-import jakarta.ws.rs.*;
-import jakarta.ws.rs.core.MediaType;
-import jakarta.ws.rs.core.Response;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
@@ -47,8 +44,8 @@ import java.util.stream.Collectors;
import static org.apache.camel.karavan.service.ContainerStatusService.CONTAINER_STATUS;
-@Path("/api/infrastructure")
-public class InfrastructureResource {
+@Path("/api/container")
+public class ContainerResource {
@Inject
EventBus eventBus;
@@ -74,109 +71,10 @@ public class InfrastructureResource {
@ConfigProperty(name = "karavan.environment")
String environment;
- private static final Logger LOGGER = Logger.getLogger(InfrastructureResource.class.getName());
-
- @POST
- @Produces(MediaType.APPLICATION_JSON)
- @Consumes(MediaType.APPLICATION_JSON)
- @Path("/pipeline/{env}")
- public String createPipeline(@PathParam("env") String env, Project project) throws Exception {
- Project p = infinispanService.getProject(project.getProjectId());
- return kubernetesService.createPipelineRun(project);
- }
+ private static final Logger LOGGER = Logger.getLogger(ContainerResource.class.getName());
@GET
@Produces(MediaType.APPLICATION_JSON)
- @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/{env}/{name}")
- public Response getPipelineLog(@PathParam("env") String env,
- @PathParam("name") String name) throws Exception {
- return Response.ok(kubernetesService.getPipelineRunLog(name, kubernetesService.getNamespace())).build();
- }
-
- @DELETE
- @Produces(MediaType.APPLICATION_JSON)
- @Consumes(MediaType.APPLICATION_JSON)
- @Path("/pipelinerun/{env}/{name}")
- public Response stopPipelineRun(@PathParam("env") String env, @PathParam("name") String name) throws Exception {
- kubernetesService.stopPipelineRun(name, kubernetesService.getNamespace());
- return Response.ok().build();
- }
-
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- @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> getAllDeploymentStatuses() throws Exception {
- if (infinispanService.isReady()) {
- return infinispanService.getDeploymentStatuses().stream()
- .sorted(Comparator.comparing(DeploymentStatus::getProjectId))
- .collect(Collectors.toList());
- } else {
- return List.of();
- }
- }
-
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- @Path("/deployment/{env}")
- public List<DeploymentStatus> getDeploymentStatusesByEnv(@PathParam("env") String env) throws Exception {
- if (infinispanService.isReady()) {
- return infinispanService.getDeploymentStatuses(env).stream()
- .sorted(Comparator.comparing(DeploymentStatus::getProjectId))
- .collect(Collectors.toList());
- } else {
- return List.of();
- }
- }
-
- @POST
- @Produces(MediaType.APPLICATION_JSON)
- @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/{env}/{name}")
- public Response deleteDeployment(@PathParam("env") String env, @PathParam("name") String name) throws Exception {
- kubernetesService.deleteDeployment(name, kubernetesService.getNamespace());
- return Response.ok().build();
- }
-
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- @Path("/service")
- public List<ServiceStatus> getAllServiceStatuses() throws Exception {
- if (infinispanService.isReady()) {
- return infinispanService.getServiceStatuses().stream()
- .sorted(Comparator.comparing(ServiceStatus::getProjectId))
- .collect(Collectors.toList());
- } else {
- return List.of();
- }
- }
-
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- @Path("/container")
public List<ContainerStatus> getAllContainerStatuses() throws Exception {
if (infinispanService.isReady()) {
return infinispanService.getContainerStatuses().stream()
@@ -190,7 +88,7 @@ public class InfrastructureResource {
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
- @Path("/container/{env}/{type}/{name}")
+ @Path("/{env}/{type}/{name}")
public Response manageContainer(@PathParam("env") String env, @PathParam("type") String type, @PathParam("name") String name, JsonObject command) throws Exception {
if (infinispanService.isReady()) {
// set container statuses
@@ -202,7 +100,13 @@ public class InfrastructureResource {
String code = projectService.getDevServiceCode();
DockerComposeService dockerComposeService = DockerComposeConverter.fromCode(code, name);
if (dockerComposeService != null) {
- dockerForKaravan.createDevserviceContainer(dockerComposeService);
+ dockerService.createContainerFromCompose(dockerComposeService, ContainerStatus.ContainerType.devmode);
+ dockerService.runContainer(dockerComposeService.getContainer_name());
+ }
+ } else if (Objects.equals(type, ContainerStatus.ContainerType.project.name())) {
+ DockerComposeService dockerComposeService = projectService.getProjectDockerComposeService(name);
+ if (dockerComposeService != null) {
+ dockerService.createContainerFromCompose(dockerComposeService, ContainerStatus.ContainerType.project);
dockerService.runContainer(dockerComposeService.getContainer_name());
}
} else if (Objects.equals(type, ContainerStatus.ContainerType.devmode.name())) {
@@ -217,6 +121,9 @@ public class InfrastructureResource {
} else if (command.getString("command").equalsIgnoreCase("pause")) {
dockerService.pauseContainer(name);
return Response.ok().build();
+ } else if (command.getString("command").equalsIgnoreCase("delete")) {
+ dockerService.deleteContainer(name);
+ return Response.ok().build();
}
}
}
@@ -234,7 +141,7 @@ public class InfrastructureResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
- @Path("/container/{env}")
+ @Path("/{env}")
public List<ContainerStatus> getContainerStatusesByEnv(@PathParam("env") String env) throws Exception {
return infinispanService.getContainerStatuses(env).stream()
.sorted(Comparator.comparing(ContainerStatus::getProjectId))
@@ -243,7 +150,7 @@ public class InfrastructureResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
- @Path("/container/{projectId}/{env}")
+ @Path("/{projectId}/{env}")
public List<ContainerStatus> getContainerStatusesByProjectAndEnv(@PathParam("projectId") String projectId, @PathParam("env") String env) throws Exception {
return infinispanService.getContainerStatuses(projectId, env).stream()
.filter(podStatus -> Objects.equals(podStatus.getType(), ContainerStatus.ContainerType.project))
@@ -254,7 +161,7 @@ public class InfrastructureResource {
@DELETE
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
- @Path("/container/{env}/{type}/{name}")
+ @Path("/{env}/{type}/{name}")
public Response deleteContainer(@PathParam("env") String env, @PathParam("type") String type, @PathParam("name") String name) {
if (infinispanService.isReady()) {
// set container statuses
@@ -274,56 +181,9 @@ public class InfrastructureResource {
return Response.notModified().build();
}
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- @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("/configmaps")
- public Response getConfigMaps() throws Exception {
- if (ConfigService.inKubernetes()) {
- return Response.ok(kubernetesService.getConfigMaps(kubernetesService.getNamespace())).build();
- } else {
- return Response.ok(List.of()).build();
- }
- }
-
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- @Path("/secrets")
- public Response getSecrets() throws Exception {
- if (ConfigService.inKubernetes()) {
- return Response.ok(kubernetesService.getSecrets(kubernetesService.getNamespace())).build();
- } else {
- return Response.ok(List.of()).build();
- }
- }
-
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- @Path("/services")
- public Response getServices() throws Exception {
- if (infinispanService.isReady()) {
- if (ConfigService.inKubernetes()) {
- return Response.ok(kubernetesService.getServices(kubernetesService.getNamespace())).build();
- } else {
- List<String> list = infinispanService.getContainerStatuses(environment).stream()
- .map(ci -> ci.getPorts().stream().map(i -> ci.getContainerName() + ":" + i).collect(Collectors.toList()))
- .flatMap(List::stream).collect(Collectors.toList());
- return Response.ok(list).build();
- }
- } else {
- return Response.ok(List.of()).build();
- }
- }
-
// TODO: implement log watch
@GET
- @Path("/container/log/watch/{env}/{name}")
+ @Path("/log/watch/{env}/{name}")
@Produces(MediaType.SERVER_SENT_EVENTS)
public Multi<String> getContainerLogWatch(@PathParam("env") String env, @PathParam("name") String name) {
LOGGER.info("Start sourcing");
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ImagesResource.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ImagesResource.java
index 9d4e0371..fe1a9f7a 100644
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ImagesResource.java
+++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ImagesResource.java
@@ -23,9 +23,12 @@ import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.apache.camel.karavan.docker.DockerService;
import org.apache.camel.karavan.infinispan.model.Project;
+import org.apache.camel.karavan.service.ConfigService;
import org.apache.camel.karavan.service.ProjectService;
import org.apache.camel.karavan.service.RegistryService;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
import java.util.Comparator;
import java.util.List;
@@ -65,4 +68,16 @@ public class ImagesResource {
return Response.serverError().entity(e.getMessage()).build();
}
}
+
+ @DELETE
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("/{imageName}")
+ public Response deleteImage(@HeaderParam("username") String username, @PathParam("imageName") String imageName) {
+ if (ConfigService.inKubernetes()) {
+ return Response.ok().build();
+ } else {
+ dockerService.deleteImage(imageName);
+ return Response.ok().build();
+ }
+ }
}
\ No newline at end of file
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/InfrastructureResource.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/InfrastructureResource.java
index f6408f84..7c2a6b6a 100644
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/InfrastructureResource.java
+++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/InfrastructureResource.java
@@ -16,61 +16,32 @@
*/
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.code.DockerComposeConverter;
-import org.apache.camel.karavan.docker.DockerForKaravan;
-import org.apache.camel.karavan.docker.DockerService;
-import org.apache.camel.karavan.code.model.DockerComposeService;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.*;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
import org.apache.camel.karavan.infinispan.InfinispanService;
-import org.apache.camel.karavan.infinispan.model.ContainerStatus;
import org.apache.camel.karavan.infinispan.model.DeploymentStatus;
import org.apache.camel.karavan.infinispan.model.Project;
import org.apache.camel.karavan.infinispan.model.ServiceStatus;
import org.apache.camel.karavan.kubernetes.KubernetesService;
-import org.apache.camel.karavan.code.CodeService;
-import org.apache.camel.karavan.service.ProjectService;
import org.apache.camel.karavan.service.ConfigService;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.jboss.logging.Logger;
-import jakarta.inject.Inject;
-import jakarta.ws.rs.*;
-import jakarta.ws.rs.core.MediaType;
-import jakarta.ws.rs.core.Response;
import java.util.Comparator;
import java.util.List;
-import java.util.Objects;
import java.util.stream.Collectors;
-import static org.apache.camel.karavan.service.ContainerStatusService.CONTAINER_STATUS;
-
@Path("/api/infrastructure")
public class InfrastructureResource {
- @Inject
- EventBus eventBus;
-
@Inject
InfinispanService infinispanService;
@Inject
KubernetesService kubernetesService;
- @Inject
- DockerForKaravan dockerForKaravan;
-
- @Inject
- DockerService dockerService;
-
- @Inject
- ProjectService projectService;
-
- @Inject
- CodeService codeService;
-
@ConfigProperty(name = "karavan.environment")
String environment;
@@ -110,14 +81,6 @@ public class InfrastructureResource {
return Response.ok().build();
}
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- @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")
@@ -174,106 +137,6 @@ public class InfrastructureResource {
}
}
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- @Path("/container")
- public List<ContainerStatus> getAllContainerStatuses() throws Exception {
- if (infinispanService.isReady()) {
- return infinispanService.getContainerStatuses().stream()
- .sorted(Comparator.comparing(ContainerStatus::getProjectId))
- .collect(Collectors.toList());
- } else {
- return List.of();
- }
- }
-
- @POST
- @Produces(MediaType.APPLICATION_JSON)
- @Consumes(MediaType.APPLICATION_JSON)
- @Path("/container/{env}/{type}/{name}")
- public Response manageContainer(@PathParam("env") String env, @PathParam("type") String type, @PathParam("name") String name, JsonObject command) throws Exception {
- if (infinispanService.isReady()) {
- // set container statuses
- setContainerStatusTransit(name, type);
- // exec docker commands
- if (command.containsKey("command")) {
- if (command.getString("command").equalsIgnoreCase("run")) {
- if (Objects.equals(type, ContainerStatus.ContainerType.devservice.name())) {
- String code = projectService.getDevServiceCode();
- DockerComposeService dockerComposeService = DockerComposeConverter.fromCode(code, name);
- if (dockerComposeService != null) {
- dockerForKaravan.createDevserviceContainer(dockerComposeService);
- dockerService.runContainer(dockerComposeService.getContainer_name());
- }
- } else if (Objects.equals(type, ContainerStatus.ContainerType.devmode.name())) {
-// TODO: merge with DevMode service
-// dockerForKaravan.createDevmodeContainer(name, "");
-// dockerService.runContainer(name);
- }
- return Response.ok().build();
- } else if (command.getString("command").equalsIgnoreCase("stop")) {
- dockerService.stopContainer(name);
- return Response.ok().build();
- } else if (command.getString("command").equalsIgnoreCase("pause")) {
- dockerService.pauseContainer(name);
- return Response.ok().build();
- }
- }
- }
- return Response.notModified().build();
- }
-
- private void setContainerStatusTransit(String name, String type){
- ContainerStatus status = infinispanService.getContainerStatus(name, environment, name);
- if (status == null) {
- status = ContainerStatus.createByType(name, environment, ContainerStatus.ContainerType.valueOf(type));
- }
- status.setInTransit(true);
- eventBus.send(CONTAINER_STATUS, JsonObject.mapFrom(status));
- }
-
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- @Path("/container/{env}")
- public List<ContainerStatus> getContainerStatusesByEnv(@PathParam("env") String env) throws Exception {
- return infinispanService.getContainerStatuses(env).stream()
- .sorted(Comparator.comparing(ContainerStatus::getProjectId))
- .collect(Collectors.toList());
- }
-
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- @Path("/container/{projectId}/{env}")
- public List<ContainerStatus> getContainerStatusesByProjectAndEnv(@PathParam("projectId") String projectId, @PathParam("env") String env) throws Exception {
- return infinispanService.getContainerStatuses(projectId, env).stream()
- .filter(podStatus -> Objects.equals(podStatus.getType(), ContainerStatus.ContainerType.project))
- .sorted(Comparator.comparing(ContainerStatus::getContainerName))
- .collect(Collectors.toList());
- }
-
- @DELETE
- @Produces(MediaType.APPLICATION_JSON)
- @Consumes(MediaType.APPLICATION_JSON)
- @Path("/container/{env}/{type}/{name}")
- public Response deleteContainer(@PathParam("env") String env, @PathParam("type") String type, @PathParam("name") String name) {
- if (infinispanService.isReady()) {
- // set container statuses
- setContainerStatusTransit(name, type);
- try {
- if (ConfigService.inKubernetes()) {
- kubernetesService.deletePod(name, kubernetesService.getNamespace());
- } else {
- dockerService.deleteContainer(name);
- }
- return Response.accepted().build();
- } catch (Exception e) {
- LOGGER.error(e.getMessage());
- return Response.notModified().build();
- }
- }
- return Response.notModified().build();
- }
-
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/imagetag/{env}/{projectId}")
@@ -320,13 +183,4 @@ public class InfrastructureResource {
return Response.ok(List.of()).build();
}
}
-
- // TODO: implement log watch
- @GET
- @Path("/container/log/watch/{env}/{name}")
- @Produces(MediaType.SERVER_SENT_EVENTS)
- public Multi<String> getContainerLogWatch(@PathParam("env") String env, @PathParam("name") String name) {
- LOGGER.info("Start sourcing");
- return eventBus.<String>consumer(name + "-" + kubernetesService.getNamespace()).toMulti().map(Message::body);
- }
}
\ No newline at end of file
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForKaravan.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForKaravan.java
index cfa74f84..41861af7 100644
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForKaravan.java
+++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForKaravan.java
@@ -69,27 +69,23 @@ public class DockerForKaravan {
}
public void runBuildProject(String projectId, String script, Map<String, String> files, List<String> env, Map<String, String> volumes, String tag) throws Exception {
- dockerService.deleteContainer(projectId + BUILDER_SUFFIX);
- Container c = createBuildContainer(projectId, env, volumes, tag);
+ String containerName = projectId + BUILDER_SUFFIX;
+ dockerService.deleteContainer(containerName);
+ Container c = createBuildContainer(containerName, projectId, env, volumes, tag);
dockerService.copyFiles(c.getId(), "/code", files);
dockerService.copyExecFile(c.getId(), "/karavan", "build.sh", script);
- dockerService.runContainer(projectId);
+ dockerService.runContainer(c);
}
- protected Container createBuildContainer(String projectId, List<String> env, Map<String, String> volumes, String tag) throws InterruptedException {
- LOGGER.infof("Starting Build Container for %s ", projectId);
+ protected Container createBuildContainer(String containerName, String projectId, List<String> env, Map<String, String> volumes, String tag) throws InterruptedException {
+ LOGGER.infof("Starting Build Container ", containerName);
- return dockerService.createContainer(projectId + BUILDER_SUFFIX, devmodeImage,
+ return dockerService.createContainer(containerName, devmodeImage,
env, Map.of(), new HealthCheck(),
Map.of(LABEL_TYPE, ContainerStatus.ContainerType.build.name(), LABEL_PROJECT_ID, projectId, LABEL_TAG, tag),
volumes, null,"/karavan/build.sh");
}
- public void createDevserviceContainer(DockerComposeService dockerComposeService) throws InterruptedException {
- LOGGER.infof("DevService starting for ", dockerComposeService.getContainer_name());
- dockerService.createContainerFromCompose(dockerComposeService, ContainerStatus.ContainerType.devservice);
- }
-
public void syncImage(String projectId, String tag) throws InterruptedException {
String image = registryService.getRegistryWithGroup() + "/" + projectId + ":" + tag;
dockerService.pullImage(image);
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
index 0f680ad8..9d5ac75f 100644
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
+++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
@@ -103,6 +103,7 @@ public class DockerService extends DockerServiceUtils {
public void stopListeners() throws IOException {
dockerEventListener.close();
}
+
public void createNetwork() {
if (!getDockerClient().listNetworksCmd().exec().stream()
.filter(n -> n.getName().equals(NETWORK_NAME))
@@ -124,7 +125,7 @@ public class DockerService extends DockerServiceUtils {
}
public Container getContainerByName(String name) {
- List<Container> containers = getDockerClient().listContainersCmd().withShowAll(true).withNameFilter(List.of(name)).exec();
+ List<Container> containers = findContainer(name);
return containers.size() > 0 ? containers.get(0) : null;
}
@@ -142,7 +143,7 @@ public class DockerService extends DockerServiceUtils {
}
public Container createContainerFromCompose(DockerComposeService compose, ContainerStatus.ContainerType type) throws InterruptedException {
- List<Container> containers = getDockerClient().listContainersCmd().withShowAll(true).withNameFilter(List.of(compose.getContainer_name())).exec();
+ List<Container> containers = findContainer(compose.getContainer_name());
if (containers.isEmpty()) {
LOGGER.infof("Compose Service starting for %s", compose.getContainer_name());
@@ -160,10 +161,15 @@ public class DockerService extends DockerServiceUtils {
}
}
+ public List<Container> findContainer(String containerName) {
+ return getDockerClient().listContainersCmd().withShowAll(true).withNameFilter(List.of(containerName)).exec()
+ .stream().filter(c -> Objects.equals(c.getNames()[0].replaceFirst("/", ""), containerName)).toList();
+ }
+
public Container createContainer(String name, String image, List<String> env, Map<Integer, Integer> ports,
HealthCheck healthCheck, Map<String, String> labels,
Map<String, String> volumes, String network, String... command) throws InterruptedException {
- List<Container> containers = getDockerClient().listContainersCmd().withShowAll(true).withNameFilter(List.of(name)).exec();
+ List<Container> containers = findContainer(name);
if (containers.size() == 0) {
pullImage(image);
@@ -186,7 +192,7 @@ public class DockerService extends DockerServiceUtils {
}
createContainerCmd.withHostConfig(new HostConfig()
.withPortBindings(portBindings)
- .withMounts(mounts)
+ .withMounts(mounts)
.withNetworkMode(network != null ? network : NETWORK_NAME));
CreateContainerResponse response = createContainerCmd.exec();
@@ -200,14 +206,17 @@ public class DockerService extends DockerServiceUtils {
}
public void runContainer(String name) {
- List<Container> containers = getDockerClient().listContainersCmd().withShowAll(true).withNameFilter(List.of(name)).exec();
+ List<Container> containers = findContainer(name);
if (containers.size() == 1) {
- Container container = containers.get(0);
- if (container.getState().equals("paused")) {
- getDockerClient().unpauseContainerCmd(container.getId()).exec();
- } else if (!container.getState().equals("running")) {
- getDockerClient().startContainerCmd(container.getId()).exec();
- }
+ runContainer(containers.get(0));
+ }
+ }
+
+ public void runContainer(Container container) {
+ if (container.getState().equals("paused")) {
+ getDockerClient().unpauseContainerCmd(container.getId()).exec();
+ } else if (!container.getState().equals("running")) {
+ getDockerClient().startContainerCmd(container.getId()).exec();
}
}
@@ -247,10 +256,10 @@ public class DockerService extends DockerServiceUtils {
}
public void copyFiles(String containerId, String containerPath, Map<String, String> files) {
- String temp = vertx.fileSystem().createTempDirectoryBlocking(containerId);
- files.forEach((fileName, code) -> addFile(temp, fileName, code));
- dockerClient.copyArchiveToContainerCmd(containerId).withRemotePath(containerPath)
- .withDirChildrenOnly(true).withHostResource(temp).exec();
+ String temp = vertx.fileSystem().createTempDirectoryBlocking(containerId);
+ files.forEach((fileName, code) -> addFile(temp, fileName, code));
+ dockerClient.copyArchiveToContainerCmd(containerId).withRemotePath(containerPath)
+ .withDirChildrenOnly(true).withHostResource(temp).exec();
}
public void copyExecFile(String containerId, String containerPath, String filename, String script) {
@@ -259,7 +268,7 @@ public class DockerService extends DockerServiceUtils {
vertx.fileSystem().writeFileBlocking(path, Buffer.buffer(script));
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
- TarArchiveOutputStream tarArchive = new TarArchiveOutputStream(byteArrayOutputStream)) {
+ TarArchiveOutputStream tarArchive = new TarArchiveOutputStream(byteArrayOutputStream)) {
tarArchive.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
tarArchive.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_POSIX);
@@ -328,7 +337,7 @@ public class DockerService extends DockerServiceUtils {
}
public void deleteContainer(String name) {
- List<Container> containers = getDockerClient().listContainersCmd().withShowAll(true).withNameFilter(List.of(name)).exec();
+ List<Container> containers = findContainer(name);
if (containers.size() == 1) {
Container container = containers.get(0);
getDockerClient().removeContainerCmd(container.getId()).withForce(true).exec();
@@ -382,4 +391,7 @@ public class DockerService extends DockerServiceUtils {
return getDockerClient().listImagesCmd().withShowAll(true).exec().stream()
.map(image -> image.getRepoTags()[0]).toList();
}
+
+ public void deleteImage(String imageName) {
+ }
}
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerStatus.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerStatus.java
index ab7c04b8..e734abc4 100644
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerStatus.java
+++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerStatus.java
@@ -4,6 +4,7 @@ import org.infinispan.protostream.annotations.ProtoEnumValue;
import org.infinispan.protostream.annotations.ProtoFactory;
import org.infinispan.protostream.annotations.ProtoField;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
@@ -65,8 +66,29 @@ public class ContainerStatus {
Boolean codeLoaded;
@ProtoField(number = 15)
Boolean inTransit = false;
+ @ProtoField(number = 16)
+ String initDate;
@ProtoFactory
+ public ContainerStatus(String projectId, String containerName, String containerId, String image, List<Integer> ports, String env, ContainerType type, String memoryInfo, String cpuInfo, String created, String finished, List<Command> commands, String state, Boolean codeLoaded, Boolean inTransit, String initDate) {
+ this.projectId = projectId;
+ this.containerName = containerName;
+ this.containerId = containerId;
+ this.image = image;
+ this.ports = ports;
+ this.env = env;
+ this.type = type;
+ this.memoryInfo = memoryInfo;
+ this.cpuInfo = cpuInfo;
+ this.created = created;
+ this.finished = finished;
+ this.commands = commands;
+ this.state = state;
+ this.codeLoaded = codeLoaded;
+ this.inTransit = inTransit;
+ this.initDate = initDate;
+ }
+
public ContainerStatus(String projectId, String containerName, String containerId, String image, List<Integer> ports, String env, ContainerType type, String memoryInfo, String cpuInfo, String created, String finished, List<Command> commands, String state, Boolean codeLoaded, Boolean inTransit) {
this.projectId = projectId;
this.containerName = containerName;
@@ -83,6 +105,7 @@ public class ContainerStatus {
this.state = state;
this.codeLoaded = codeLoaded;
this.inTransit = inTransit;
+ this.initDate = Instant.now().toString();
}
public ContainerStatus(String containerName, List<Command> commands, String projectId, String env, ContainerType type, String memoryInfo, String cpuInfo, String created) {
@@ -94,6 +117,7 @@ public class ContainerStatus {
this.memoryInfo = memoryInfo;
this.cpuInfo = cpuInfo;
this.created = created;
+ this.initDate = Instant.now().toString();
}
public ContainerStatus(String containerName, List<Command> commands, String projectId, String env, ContainerType type, String created) {
@@ -103,6 +127,7 @@ public class ContainerStatus {
this.env = env;
this.created = created;
this.type = type;
+ this.initDate = Instant.now().toString();
}
public static ContainerStatus createDevMode(String projectId, String env) {
@@ -242,6 +267,14 @@ public class ContainerStatus {
this.finished = finished;
}
+ public String getInitDate() {
+ return initDate;
+ }
+
+ public void setInitDate(String initDate) {
+ this.initDate = initDate;
+ }
+
@Override
public String toString() {
return "ContainerStatus{" +
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/CamelService.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/CamelService.java
index 7f054871..8bc62635 100644
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/CamelService.java
+++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/CamelService.java
@@ -16,6 +16,7 @@
*/
package org.apache.camel.karavan.service;
+import io.quarkus.scheduler.Scheduled;
import io.quarkus.vertx.ConsumeEvent;
import io.vertx.core.json.JsonObject;
import io.vertx.mutiny.core.Vertx;
@@ -70,6 +71,19 @@ public class CamelService {
return webClient;
}
+ @Scheduled(every = "{karavan.camel.status.interval}", concurrentExecution = Scheduled.ConcurrentExecution.SKIP)
+ public void collectCamelStatuses() {
+ if (infinispanService.isReady()) {
+ infinispanService.getContainerStatuses(environment).stream()
+ .filter(cs ->
+ cs.getType() == ContainerStatus.ContainerType.project
+ || cs.getType() == ContainerStatus.ContainerType.devmode
+ ).forEach(pod -> {
+ CamelStatusRequest csr = new CamelStatusRequest(pod.getProjectId(), pod.getContainerName());
+ eventBus.publish(CMD_COLLECT_CAMEL_STATUS, JsonObject.mapFrom(csr));
+ });
+ }
+ }
private boolean camelIsStarted(CamelStatus camelStatus) {
try {
@@ -129,19 +143,6 @@ public class CamelService {
}
}
- public void collectCamelStatuses() {
- if (infinispanService.isReady()) {
- infinispanService.getContainerStatuses(environment).stream()
- .filter(cs ->
- cs.getType() == ContainerStatus.ContainerType.project
- || cs.getType() == ContainerStatus.ContainerType.devmode
- ).forEach(pod -> {
- CamelStatusRequest csr = new CamelStatusRequest(pod.getProjectId(), pod.getContainerName());
- eventBus.publish(CMD_COLLECT_CAMEL_STATUS, JsonObject.mapFrom(csr));
- });
- }
- }
-
@ConsumeEvent(value = CMD_COLLECT_CAMEL_STATUS, blocking = true, ordered = true)
public void collectCamelStatuses(JsonObject data) {
CamelStatusRequest dms = data.mapTo(CamelStatusRequest.class);
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ContainerStatusService.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ContainerStatusService.java
index 5fc126eb..c3b310bc 100644
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ContainerStatusService.java
+++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ContainerStatusService.java
@@ -1,14 +1,20 @@
package org.apache.camel.karavan.service;
+import io.quarkus.scheduler.Scheduled;
import io.quarkus.vertx.ConsumeEvent;
+import io.vertx.core.eventbus.EventBus;
import io.vertx.core.json.JsonObject;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
+import org.apache.camel.karavan.docker.DockerService;
import org.apache.camel.karavan.infinispan.InfinispanService;
import org.apache.camel.karavan.infinispan.model.ContainerStatus;
+import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.jboss.logging.Logger;
import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.List;
import java.util.Objects;
@ApplicationScoped
@@ -16,10 +22,60 @@ public class ContainerStatusService {
public static final String CONTAINER_STATUS = "CONTAINER_STATUS";
private static final Logger LOGGER = Logger.getLogger(ContainerStatusService.class.getName());
+ @ConfigProperty(name = "karavan.environment")
+ String environment;
@Inject
InfinispanService infinispanService;
+ @Inject
+ DockerService dockerService;
+
+ @Inject
+ EventBus eventBus;
+
+ @Scheduled(every = "{karavan.container.statistics.interval}", concurrentExecution = Scheduled.ConcurrentExecution.SKIP)
+ void collectContainersStatistics() {
+ if (infinispanService.isReady()) {
+ List<ContainerStatus> statusesInDocker = dockerService.collectContainersStatistics();
+ statusesInDocker.forEach(containerStatus -> {
+ eventBus.send(ContainerStatusService.CONTAINER_STATUS, JsonObject.mapFrom(containerStatus));
+ });
+ }
+ }
+
+ @Scheduled(every = "{karavan.container.status.interval}", concurrentExecution = Scheduled.ConcurrentExecution.SKIP)
+ void collectContainersStatuses() {
+ if (infinispanService.isReady()) {
+ List<ContainerStatus> statusesInDocker = dockerService.collectContainersStatuses();
+ statusesInDocker.forEach(containerStatus -> {
+ eventBus.send(ContainerStatusService.CONTAINER_STATUS, JsonObject.mapFrom(containerStatus));
+ });
+ cleanContainersStatuses(statusesInDocker);
+ }
+ }
+
+ void cleanContainersStatuses(List<ContainerStatus> statusesInDocker) {
+ if (infinispanService.isReady()) {
+ List<String> namesInDocker = statusesInDocker.stream().map(ContainerStatus::getContainerName).toList();
+ List<ContainerStatus> statusesInInfinispan = infinispanService.getContainerStatuses(environment);
+ // clean deleted
+ statusesInInfinispan.stream()
+ .filter(cs -> !checkTransit(cs))
+ .filter(cs -> !namesInDocker.contains(cs.getContainerName()))
+ .forEach(containerStatus -> {
+ infinispanService.deleteContainerStatus(containerStatus);
+ infinispanService.deleteCamelStatuses(containerStatus.getProjectId(), containerStatus.getEnv());
+ });
+ }
+ }
+
+ private boolean checkTransit(ContainerStatus cs) {
+ if (cs.getContainerId() == null && cs.getInTransit()) {
+ return Instant.parse(cs.getInitDate()).until(Instant.now(), ChronoUnit.SECONDS) < 10;
+ }
+ return false;
+ }
@ConsumeEvent(value = CONTAINER_STATUS, blocking = true, ordered = true)
public void saveContainerStatus(JsonObject data) {
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ProjectService.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ProjectService.java
index 5ce1e34f..ebd49e08 100644
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ProjectService.java
+++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ProjectService.java
@@ -387,4 +387,12 @@ public class ProjectService implements HealthCheck {
}
}
}
+
+ public DockerComposeService getProjectDockerComposeService(String projectId) {
+ ProjectFile file = infinispanService.getProjectFile(projectId, PROJECT_COMPOSE_FILENAME);
+ if (file != null) {
+ return DockerComposeConverter.fromCode(file.getCode(), projectId);
+ }
+ return null;
+ }
}
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ScheduledService.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ScheduledService.java
deleted file mode 100644
index 1a90dc6c..00000000
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ScheduledService.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.karavan.service;
-
-import io.quarkus.scheduler.Scheduled;
-import io.vertx.core.eventbus.EventBus;
-import io.vertx.core.json.JsonObject;
-import org.apache.camel.karavan.docker.DockerForInfinispan;
-import org.apache.camel.karavan.docker.DockerService;
-import org.apache.camel.karavan.infinispan.InfinispanService;
-import org.apache.camel.karavan.infinispan.model.ContainerStatus;
-import org.eclipse.microprofile.config.inject.ConfigProperty;
-import org.jboss.logging.Logger;
-
-import jakarta.enterprise.context.ApplicationScoped;
-import jakarta.inject.Inject;
-import java.util.List;
-
-@ApplicationScoped
-public class ScheduledService {
-
- private static final Logger LOGGER = Logger.getLogger(ScheduledService.class.getName());
-
- @ConfigProperty(name = "karavan.environment")
- String environment;
-
- @Inject
- DockerService dockerService;
-
- @Inject
- DockerForInfinispan dockerForInfinispan;
-
- @Inject
- ProjectService projectService;
-
- @Inject
- CamelService camelService;
-
- @Inject
- InfinispanService infinispanService;
-
- @Inject
- EventBus eventBus;
-
- @Scheduled(every = "{karavan.container.statistics.interval}", concurrentExecution = Scheduled.ConcurrentExecution.SKIP)
- void collectContainersStatistics() {
- if (infinispanService.isReady()) {
- List<ContainerStatus> statusesInDocker = dockerService.collectContainersStatistics();
- statusesInDocker.forEach(containerStatus -> {
- eventBus.send(ContainerStatusService.CONTAINER_STATUS, JsonObject.mapFrom(containerStatus));
- });
- }
- }
-
- @Scheduled(every = "{karavan.container.status.interval}", concurrentExecution = Scheduled.ConcurrentExecution.SKIP)
- void collectContainersStatuses() {
- if (infinispanService.isReady()) {
- List<ContainerStatus> statusesInDocker = dockerService.collectContainersStatuses();
- statusesInDocker.forEach(containerStatus -> {
- eventBus.send(ContainerStatusService.CONTAINER_STATUS, JsonObject.mapFrom(containerStatus));
- });
- cleanContainersStatuses(statusesInDocker);
- }
- }
-
- void cleanContainersStatuses(List<ContainerStatus> statusesInDocker) {
- if (infinispanService.isReady()) {
- List<String> namesInDocker = statusesInDocker.stream().map(ContainerStatus::getContainerName).toList();
- List<ContainerStatus> statusesInInfinispan = infinispanService.getContainerStatuses(environment);
- // clean deleted
- statusesInInfinispan.stream()
- .filter(cs -> !(cs.getContainerId() == null && cs.getInTransit()))
- .filter(cs -> !namesInDocker.contains(cs.getContainerName()))
- .forEach(containerStatus -> {
- infinispanService.deleteContainerStatus(containerStatus);
- infinispanService.deleteCamelStatuses(containerStatus.getProjectId(), containerStatus.getEnv());
- });
- }
- }
-
-
- @Scheduled(every = "{karavan.camel.status.interval}", concurrentExecution = Scheduled.ConcurrentExecution.SKIP)
- void collectCamelStatuses() {
- camelService.collectCamelStatuses();
- }
-}
diff --git a/karavan-web/karavan-app/src/main/resources/snippets/camel-main-docker-application.properties b/karavan-web/karavan-app/src/main/resources/snippets/camel-main-docker-application.properties
index 5048638c..2ce5adb2 100644
--- a/karavan-web/karavan-app/src/main/resources/snippets/camel-main-docker-application.properties
+++ b/karavan-web/karavan-app/src/main/resources/snippets/camel-main-docker-application.properties
@@ -5,6 +5,9 @@ camel.jbang.gav=org.camel.karavan.demo:{projectId}:1
camel.jbang.runtime=camel-main
camel.jbang.version=4.0.0-RC2
camel.jbang.dependencies=camel-console,camel-platform-http-main
+camel.context.dev-console=true
+camel.main.backlogTracing=true
+camel.main.beanIntrospectionExtendedStatistics=true
camel.health.enabled=true
camel.health.exposure-level=full
camel.server.enabled=true
diff --git a/karavan-web/karavan-app/src/main/webui/src/api/KaravanApi.tsx b/karavan-web/karavan-app/src/main/webui/src/api/KaravanApi.tsx
index d6bcfcd2..fd66d5cd 100644
--- a/karavan-web/karavan-app/src/main/webui/src/api/KaravanApi.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/api/KaravanApi.tsx
@@ -412,7 +412,7 @@ export class KaravanApi {
}
static async getContainerLog(environment: string, name: string, after: (res: AxiosResponse<string>) => void) {
- instance.get('/api/infrastructure/container/log/' + environment + "/" + name)
+ instance.get('/api/container/log/' + environment + "/" + name)
.then(res => {
if (res.status === 200) {
after(res.data);
@@ -434,7 +434,7 @@ export class KaravanApi {
}
static async getAllContainerStatuses(after: (statuses: ContainerStatus[]) => void) {
- instance.get('/api/infrastructure/container')
+ instance.get('/api/container')
.then(res => {
if (res.status === 200) {
after(res.data);
@@ -484,19 +484,12 @@ export class KaravanApi {
});
}
- static async getProjectPodStatuses(project: string, env: string, after: (statuses: ContainerStatus[]) => void) {
- instance.get('/api/infrastructure/container/' + project + "/" + env)
- .then(res => {
- if (res.status === 200) {
- after(res.data);
- }
- }).catch(err => {
- console.log(err);
- });
- }
-
- static async manageContainer(environment: string, type: 'devmove' | 'devservice' | 'project' | 'internal' | 'unknown', name: string, command: 'run' | 'pause' | 'stop', after: (res: AxiosResponse<any>) => void) {
- instance.post('/api/infrastructure/container/' + environment + '/' + type + "/" + name, {command: command})
+ static async manageContainer(environment: string,
+ type: 'devmove' | 'devservice' | 'project' | 'internal' | 'build' | 'unknown',
+ name: string,
+ command: 'run' | 'pause' | 'stop' | 'delete',
+ after: (res: AxiosResponse<any>) => void) {
+ instance.post('/api/container/' + environment + '/' + type + "/" + name, {command: command})
.then(res => {
after(res);
}).catch(err => {
@@ -504,8 +497,8 @@ export class KaravanApi {
});
}
- static async deleteContainer(environment: string, type: 'devmove' | 'devservice' | 'project' | 'internal' | 'unknown', name: string, after: (res: AxiosResponse<any>) => void) {
- instance.delete('/api/infrastructure/container/' + environment + '/' + type + "/" + name)
+ static async deleteContainer(environment: string, type: 'devmove' | 'devservice' | 'project' | 'internal' | 'build' | 'unknown', name: string, after: (res: AxiosResponse<any>) => void) {
+ instance.delete('/api/container/' + environment + '/' + type + "/" + name)
.then(res => {
after(res);
}).catch(err => {
diff --git a/karavan-web/karavan-app/src/main/webui/src/api/ProjectModels.ts b/karavan-web/karavan-app/src/main/webui/src/api/ProjectModels.ts
index 460690b7..8dd5e485 100644
--- a/karavan-web/karavan-app/src/main/webui/src/api/ProjectModels.ts
+++ b/karavan-web/karavan-app/src/main/webui/src/api/ProjectModels.ts
@@ -73,7 +73,7 @@ export class ContainerStatus {
deployment: string = '';
projectId: string = '';
env: string = '';
- type: 'devmove' | 'devservice' | 'project' | 'internal' | 'unknown' = 'unknown';
+ type: 'devmove' | 'devservice' | 'project' | 'internal' | 'build' | 'unknown' = 'unknown';
memoryInfo: string = '';
cpuInfo: string = '';
created: string = '';
diff --git a/karavan-web/karavan-app/src/main/webui/src/project/BuildToolbar.tsx b/karavan-web/karavan-app/src/main/webui/src/project/BuildToolbar.tsx
index 1fa7a8f0..e18284c5 100644
--- a/karavan-web/karavan-app/src/main/webui/src/project/BuildToolbar.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/project/BuildToolbar.tsx
@@ -1,9 +1,18 @@
import React from 'react';
-import {Button, Flex, FlexItem} from '@patternfly/react-core';
+import {Button, Flex, FlexItem, Label, Spinner, Tooltip, TooltipPosition} from '@patternfly/react-core';
import '../designer/karavan.css';
import DeleteIcon from "@patternfly/react-icons/dist/esm/icons/trash-icon";
-import {useAppConfigStore} from "../api/ProjectStore";
+import {useAppConfigStore, useDevModeStore, useLogStore, useProjectStore, useStatusesStore} from "../api/ProjectStore";
import {shallow} from "zustand/shallow";
+import UpIcon from "@patternfly/react-icons/dist/esm/icons/check-circle-icon";
+import DownIcon from "@patternfly/react-icons/dist/esm/icons/error-circle-o-icon";
+import RunIcon from "@patternfly/react-icons/dist/esm/icons/play-icon";
+import {ProjectService} from "../api/ProjectService";
+import ReloadIcon from "@patternfly/react-icons/dist/esm/icons/bolt-icon";
+import {KaravanApi} from "../api/KaravanApi";
+import {ProjectEventBus} from "../api/ProjectEventBus";
+import {EventBus} from "../designer/utils/EventBus";
+import StopIcon from "@patternfly/react-icons/dist/js/icons/stop-icon";
interface Props {
reloadOnly?: boolean
@@ -12,11 +21,78 @@ interface Props {
export function BuildToolbar (props: Props) {
const [config] = useAppConfigStore((state) => [state.config], shallow)
+ const [status] = useDevModeStore((state) => [state.status], shallow)
+ const [project] = useProjectStore((state) => [state.project], shallow)
+ const [containers] = useStatusesStore((state) => [state.containers], shallow);
+ const [setShowLog] = useLogStore((s) => [s.setShowLog], shallow);
+
+ const containerStatus = containers.filter(c => c.containerName === project.projectId).at(0);
+ const commands = containerStatus?.commands || ['run'];
+ const isRunning = containerStatus?.state === 'running';
+ const inTransit = containerStatus?.inTransit;
+ const isLoading = status === 'wip';
+ const color = containerStatus?.state === 'running' ? "green" : "grey";
+ const icon = isRunning ? <UpIcon/> : <DownIcon/>;
return (<Flex className="toolbar" direction={{default: "row"}} alignItems={{default: "alignItemsCenter"}}>
<FlexItem>
- <Button style={{visibility:"hidden"}} size="sm" variant={"control"} icon={<DeleteIcon/>} onClick={() => {}}>
+ {(inTransit || isLoading) && <Spinner size="lg" aria-label="spinner"/>}
+ </FlexItem>
+ {containerStatus?.containerId && <FlexItem>
+ <Label icon={icon} color={color}>
+ <Tooltip content={"Show log"} position={TooltipPosition.bottom}>
+ <Button className='labeled-button' variant="link" isDisabled={!isRunning}
+ onClick={e =>
+ setShowLog(true, 'container', containerStatus.containerName)}>
+ {containerStatus.containerName}
+ </Button>
+ </Tooltip>
+ </Label>
+ </FlexItem>}
+ {!isRunning && <FlexItem>
+ <Tooltip content="Run container" position={TooltipPosition.bottom}>
+ <Button size="sm"
+ isDisabled={(!(commands.length === 0) && !commands.includes('run')) || inTransit}
+ variant={"primary"}
+ icon={<RunIcon/>}
+ onClick={() => {
+ KaravanApi.manageContainer('dev', 'project', project.projectId, 'run', res => {
+ setShowLog(false, 'container', undefined)
+ });
+ }}>
+ {"Run"}
</Button>
+ </Tooltip>
+ </FlexItem>}
+ {config.infrastructure !== 'kubernetes' &&
+ <FlexItem>
+ <Tooltip content="Stop container" position={TooltipPosition.bottom}>
+ <Button size="sm"
+ isDisabled={!commands.includes('stop') || inTransit}
+ variant={"control"}
+ icon={<StopIcon/>}
+ onClick={() => {
+ KaravanApi.manageContainer('dev', 'project', project.projectId, 'stop', res => {
+ setShowLog(false, 'container', undefined)
+ });
+ }}>
+ </Button>
+ </Tooltip>
+ </FlexItem>
+ }
+ <FlexItem>
+ <Tooltip content="Delete container" position={TooltipPosition.bottom}>
+ <Button size="sm"
+ isDisabled={!commands.includes('delete') || inTransit}
+ variant={"control"}
+ icon={<DeleteIcon/>}
+ onClick={() => {
+ KaravanApi.manageContainer('dev', 'project', project.projectId, 'delete', res => {
+ setShowLog(false, 'container', undefined)
+ });
+ }}>
+ </Button>
+ </Tooltip>
</FlexItem>
</Flex>);
-}
+}
\ No newline at end of file
diff --git a/karavan-web/karavan-app/src/main/webui/src/project/build/ProjectBuildTab.tsx b/karavan-web/karavan-app/src/main/webui/src/project/build/ProjectBuildTab.tsx
index 6c916da4..e761bbcb 100644
--- a/karavan-web/karavan-app/src/main/webui/src/project/build/ProjectBuildTab.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/project/build/ProjectBuildTab.tsx
@@ -14,7 +14,7 @@ export function ProjectBuildTab () {
<div>
{/*{["dev", "test", "prod"].map(env =>*/}
{config.environments.map(env =>
- <BuildPanel env={env}/>
+ <BuildPanel key={env} env={env}/>
)}
</div>
</PageSection>
diff --git a/karavan-web/karavan-app/src/main/webui/src/project/trace/RunnerInfoTraceModal.tsx b/karavan-web/karavan-app/src/main/webui/src/project/trace/RunnerInfoTraceModal.tsx
index 6a2b9986..af950b60 100644
--- a/karavan-web/karavan-app/src/main/webui/src/project/trace/RunnerInfoTraceModal.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/project/trace/RunnerInfoTraceModal.tsx
@@ -42,7 +42,6 @@ export function RunnerInfoTraceModal (props: Props) {
return Array.from(new Set((props.nodes).map((item: any) => item?.routeId)));
}
- console.log(props.nodes)
return (
<Modal
title={"Exchange: " + props.exchangeId}