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 f12ed08d8694789c4020105534e3ece5a1485d8c Author: Marat Gubaidullin <ma...@talismancloud.io> AuthorDate: Sun Sep 10 17:46:18 2023 -0400 Fix Kubernetess mode for #817 --- .../apache/camel/karavan/api/ImagesResource.java | 8 +++-- .../org/apache/camel/karavan/code/CodeService.java | 25 ++++++++++++--- .../camel/karavan/docker/DockerForGitea.java | 1 - .../apache/camel/karavan/docker/DockerService.java | 16 +++------- .../org/apache/camel/karavan/git/GitService.java | 3 +- .../org/apache/camel/karavan/git/GiteaService.java | 21 +++++++++++-- .../karavan/kubernetes/KubernetesService.java | 28 +++++++++++------ .../camel/karavan/kubernetes/PodEventHandler.java | 20 ++++++------ .../apache/camel/karavan/service/CamelService.java | 36 +++++++++++++++++----- .../camel/karavan/service/ConfigService.java | 3 +- .../karavan/service/ContainerStatusService.java | 20 +++++++----- .../camel/karavan/service/KaravanService.java | 12 +++++--- .../camel/karavan/service/ProjectService.java | 3 +- .../src/main/resources/application.properties | 7 ++++- 14 files changed, 138 insertions(+), 65 deletions(-) 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 0c172856..9f5e64b0 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 @@ -49,9 +49,13 @@ public class ImagesResource { @Produces(MediaType.APPLICATION_JSON) @Path("/{projectId}") public List<String> getImagesForProject(@HeaderParam("username") String username, - @PathParam("projectId") String projectId) throws Exception { + @PathParam("projectId") String projectId) { String pattern = registryService.getRegistryWithGroup() + "/" + projectId; - return dockerService.getImages().stream().filter(s -> s.startsWith(pattern)).sorted(Comparator.reverseOrder()).toList(); + if (ConfigService.inKubernetes()) { + return List.of(); + } else { + return dockerService.getImages().stream().filter(s -> s.startsWith(pattern)).sorted(Comparator.reverseOrder()).toList(); + } } @POST diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/CodeService.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/CodeService.java index c86eefc6..b0ea0b9a 100644 --- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/CodeService.java +++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/CodeService.java @@ -23,6 +23,8 @@ import io.apicurio.datamodels.openapi.models.OasDocument; import io.quarkus.qute.Engine; import io.quarkus.qute.Template; import io.quarkus.qute.TemplateInstance; +import io.vertx.core.Vertx; +import io.vertx.core.buffer.Buffer; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import org.apache.camel.CamelContext; @@ -43,10 +45,7 @@ import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.SafeConstructor; -import java.io.BufferedReader; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.io.InputStreamReader; +import java.io.*; import java.time.Instant; import java.util.*; import java.util.stream.Collectors; @@ -76,6 +75,9 @@ public class CodeService { @Inject Engine engine; + @Inject + Vertx vertx; + List<String> runtimes = List.of("quarkus", "spring-boot", "camel-main"); List<String> targets = List.of("openshift", "kubernetes", "docker"); List<String> interfaces = List.of("org.apache.camel.AggregationStrategy.java", "org.apache.camel.Processor.java"); @@ -106,6 +108,21 @@ public class CodeService { return new ProjectFile(APPLICATION_PROPERTIES_FILENAME, code, project.getProjectId(), Instant.now().toEpochMilli()); } + public String saveProjectFilesInTemp(Map<String, String> files) { + String temp = vertx.fileSystem().createTempDirectoryBlocking("temp"); + files.forEach((fileName, code) -> addFile(temp, fileName, code)); + return temp; + } + + private void addFile(String temp, String fileName, String code) { + try { + String path = temp + File.separator + fileName; + vertx.fileSystem().writeFileBlocking(path, Buffer.buffer(code)); + } catch (Exception e) { + LOGGER.error(e.getMessage()); + } + } + public String getTemplateText(String fileName) { try { List<ProjectFile> files = infinispanService.getProjectFiles(Project.Type.templates.name()); diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForGitea.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForGitea.java index d1dd236f..ab7bf72d 100644 --- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForGitea.java +++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForGitea.java @@ -72,7 +72,6 @@ public class DockerForGitea { "--admin"); dockerService.execStart(user.getId(), new LoggerCallback()); LOGGER.info("Created Gitea User"); - giteaService.createRepository(); } catch (Exception e) { LOGGER.error(e.getMessage()); } 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 f15d5b4e..a3e35ee0 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 @@ -30,6 +30,7 @@ import io.vertx.core.Vertx; import io.vertx.core.buffer.Buffer; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; +import org.apache.camel.karavan.code.CodeService; import org.apache.camel.karavan.code.model.DockerComposeService; import org.apache.camel.karavan.infinispan.model.ContainerStatus; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; @@ -60,6 +61,9 @@ public class DockerService extends DockerServiceUtils { @Inject DockerEventListener dockerEventListener; + @Inject + CodeService codeService; + @Inject Vertx vertx; @@ -256,8 +260,7 @@ 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)); + String temp = codeService.saveProjectFilesInTemp(files); dockerClient.copyArchiveToContainerCmd(containerId).withRemotePath(containerPath) .withDirChildrenOnly(true).withHostResource(temp).exec(); } @@ -289,15 +292,6 @@ public class DockerService extends DockerServiceUtils { } } - private void addFile(String temp, String fileName, String code) { - try { - String path = temp + File.separator + fileName; - vertx.fileSystem().writeFileBlocking(path, Buffer.buffer(code)); - } catch (Exception e) { - LOGGER.error(e.getMessage()); - } - } - public void logContainer(String containerName, LogCallback callback) { try { Container container = getContainerByName(containerName); diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/git/GitService.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/git/GitService.java index 534781e6..71a2f363 100644 --- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/git/GitService.java +++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/git/GitService.java @@ -88,7 +88,6 @@ public class GitService { String propertiesPrefix = "karavan."; String branch = ConfigProvider.getConfig().getValue(propertiesPrefix + "git-branch", String.class); if (ConfigService.inKubernetes()) { - LOGGER.info("inKubernetes " + kubernetesService.getNamespace()); Secret secret = kubernetesService.getKaravanSecret(); String uri = new String(Base64.getDecoder().decode(secret.getData().get("git-repository").getBytes(StandardCharsets.UTF_8))); String username = new String(Base64.getDecoder().decode(secret.getData().get("git-username").getBytes(StandardCharsets.UTF_8))); @@ -443,7 +442,7 @@ public class GitService { return files; } - @Retry(maxRetries = 100, delay = 2000) +// @Retry(maxRetries = 100, delay = 2000) public boolean checkGit() throws Exception { LOGGER.info("Check git"); GitConfig gitConfig = getGitConfig(); diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/git/GiteaService.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/git/GiteaService.java index 7ad208e7..8c7b281a 100644 --- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/git/GiteaService.java +++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/git/GiteaService.java @@ -28,6 +28,8 @@ import org.apache.camel.karavan.service.ConfigService; import org.eclipse.microprofile.faulttolerance.Retry; import org.jboss.logging.Logger; +import java.net.MalformedURLException; +import java.net.URL; import java.util.List; import java.util.Map; @@ -110,7 +112,8 @@ public class GiteaService { } LOGGER.info("Creating Gitea User Token"); GitConfig config = gitService.getGitConfig(); - HttpResponse<Buffer> result = getWebClient().postAbs(getGiteaBaseUrl() + "/api/v1/users/" + config.getUsername() + "/tokens").timeout(500) + String uri = getGiteaBaseUrl() + "/api/v1/users/" + config.getUsername() + "/tokens"; + HttpResponse<Buffer> result = getWebClient().postAbs(uri).timeout(500) .putHeader("Content-Type", "application/json") .putHeader("accept", "application/json") .basicAuthentication(config.getUsername(), config.getPassword()) @@ -123,6 +126,7 @@ public class GiteaService { } else if (result.statusCode() == 201) { JsonObject res = result.bodyAsJsonObject(); token = res.getString("sha1"); + LOGGER.info("Gitea User Token received"); return token; } else { LOGGER.info("Error getting token"); @@ -145,7 +149,18 @@ public class GiteaService { } } - private String getGiteaBaseUrl(){ - return ConfigService.inDocker() ? "http://gitea:3000" : "http://localhost:3000"; + private String getGiteaBaseUrl() throws MalformedURLException { + if (ConfigService.inDocker()) { + return "http://gitea:3000"; + } else if (ConfigService.inKubernetes()) { + String uri = gitService.getGitConfig().getUri(); + URL url = new URL(uri); + String protocol = url.getProtocol(); + String host = url.getHost(); + int port = url.getPort(); + return protocol + "://" + host + (port > 0 ? ":" + port : ""); + } else { + return "http://localhost:3000"; + } } } \ No newline at end of file diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/KubernetesService.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/KubernetesService.java index 4c84c03d..f04949e2 100644 --- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/KubernetesService.java +++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/KubernetesService.java @@ -35,6 +35,7 @@ import org.apache.camel.karavan.infinispan.model.ProjectFile; import org.apache.camel.karavan.code.CodeService; import org.apache.camel.karavan.service.ConfigService; import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.eclipse.microprofile.faulttolerance.Retry; import org.eclipse.microprofile.health.HealthCheck; import org.eclipse.microprofile.health.HealthCheckResponse; import org.eclipse.microprofile.health.Readiness; @@ -44,6 +45,10 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Default; import jakarta.enterprise.inject.Produces; import jakarta.inject.Inject; + +import java.io.ByteArrayInputStream; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.*; import java.util.stream.Collectors; @@ -56,7 +61,7 @@ import static org.apache.camel.karavan.shared.Constants.*; public class KubernetesService implements HealthCheck { private static final Logger LOGGER = Logger.getLogger(KubernetesService.class.getName()); - protected static final int INFORMERS = 4; + protected static final int INFORMERS = 3; private static final String CAMEL_PREFIX = "camel"; private static final String KARAVAN_PREFIX = "karavan"; private static final String JBANG_CACHE_SUFFIX = "jbang-cache"; @@ -69,6 +74,9 @@ public class KubernetesService implements HealthCheck { @Inject InfinispanService infinispanService; + @Inject + CodeService codeService; + @Produces public KubernetesClient kubernetesClient() { return new DefaultKubernetesClient(); @@ -107,10 +115,10 @@ public class KubernetesService implements HealthCheck { serviceInformer.addEventHandlerWithResyncPeriod(new ServiceEventHandler(infinispanService, this), 30 * 1000L); informers.add(serviceInformer); - SharedIndexInformer<PipelineRun> pipelineRunInformer = tektonClient().v1beta1().pipelineRuns().inNamespace(getNamespace()) - .withLabels(getRuntimeLabels()).inform(); - pipelineRunInformer.addEventHandlerWithResyncPeriod(new PipelineRunEventHandler(infinispanService, this), 30 * 1000L); - informers.add(pipelineRunInformer); +// SharedIndexInformer<PipelineRun> pipelineRunInformer = tektonClient().v1beta1().pipelineRuns().inNamespace(getNamespace()) +// .withLabels(getRuntimeLabels()).inform(); +// pipelineRunInformer.addEventHandlerWithResyncPeriod(new PipelineRunEventHandler(infinispanService, this), 30 * 1000L); +// informers.add(pipelineRunInformer); SharedIndexInformer<Pod> podRunInformer = kubernetesClient().pods().inNamespace(getNamespace()) .withLabels(getRuntimeLabels()).inform(); @@ -426,6 +434,7 @@ public class KubernetesService implements HealthCheck { labels.putAll(getRuntimeLabels()); labels.putAll(getKaravanRunnerLabels(name)); labels.put(LABEL_PROJECT_ID, projectId); + labels.put(LABEL_TYPE, ContainerStatus.ContainerType.devmode.name()); ResourceRequirements resources = getResourceRequirements(containerResources); @@ -448,10 +457,11 @@ public class KubernetesService implements HealthCheck { .withResources(resources) .withImagePullPolicy("Always") .withEnv(new EnvVarBuilder().withName(ENV_VAR_JBANG_OPTIONS).withValue(jbangOptions).build()) - .withVolumeMounts( - new VolumeMountBuilder().withName(name).withMountPath("/karavan/.jbang/cache").build(), - new VolumeMountBuilder().withName("maven-settings").withSubPath("maven-settings.xml") - .withMountPath("/karavan-config-map/maven-settings.xml").build()) +// .withVolumeMounts( +// new VolumeMountBuilder().withName(name).withMountPath("/karavan/.jbang/cache").build() +// new VolumeMountBuilder().withName("maven-settings").withSubPath("maven-settings.xml") +// .withMountPath("/karavan-config-map/maven-settings.xml").build() +// ) .build(); PodSpec spec = new PodSpecBuilder() diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/PodEventHandler.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/PodEventHandler.java index a783df7c..1eaf01b8 100644 --- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/PodEventHandler.java +++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/PodEventHandler.java @@ -9,14 +9,17 @@ import io.vertx.core.json.JsonObject; import io.vertx.mutiny.core.eventbus.EventBus; import org.apache.camel.karavan.infinispan.InfinispanService; import org.apache.camel.karavan.infinispan.model.ContainerStatus; +import org.apache.camel.karavan.infinispan.model.ProjectFile; import org.jboss.logging.Logger; import java.util.List; import java.util.Objects; import static org.apache.camel.karavan.code.CodeService.DEFAULT_CONTAINER_RESOURCES; +import static org.apache.camel.karavan.service.CamelService.RELOAD_PROJECT_CODE; import static org.apache.camel.karavan.shared.Constants.LABEL_PROJECT_ID; import static org.apache.camel.karavan.service.ContainerStatusService.CONTAINER_STATUS; +import static org.apache.camel.karavan.shared.Constants.LABEL_TYPE; public class PodEventHandler implements ResourceEventHandler<Pod> { @@ -39,7 +42,7 @@ public class PodEventHandler implements ResourceEventHandler<Pod> { if (ps != null) { eventBus.send(CONTAINER_STATUS, JsonObject.mapFrom(ps)); } - } catch (Exception e){ + } catch (Exception e) { LOGGER.error(e.getMessage(), e.getCause()); } } @@ -52,16 +55,9 @@ public class PodEventHandler implements ResourceEventHandler<Pod> { ContainerStatus ps = getPodStatus(newPod); if (ps != null) { eventBus.send(CONTAINER_STATUS, JsonObject.mapFrom(ps)); - if (Objects.equals(ps.getState(), ContainerStatus.State.running.name())) { -// Map<String, Object> message = Map.of( -// LABEL_PROJECT_ID, ps.getProjectId(), -// RELOAD_TRY_COUNT, 1 -// ); -// eventBus.publish(DEVMODE_CONTAINER_READY, JsonObject.mapFrom(message)); - } } } - } catch (Exception e){ + } catch (Exception e) { LOGGER.error(e.getMessage(), e.getCause()); } } @@ -74,7 +70,7 @@ public class PodEventHandler implements ResourceEventHandler<Pod> { String projectId = deployment != null ? deployment : pod.getMetadata().getLabels().get(LABEL_PROJECT_ID); infinispanService.deleteContainerStatus(projectId, kubernetesService.environment, pod.getMetadata().getName()); infinispanService.deleteCamelStatuses(projectId, kubernetesService.environment); - } catch (Exception e){ + } catch (Exception e) { LOGGER.error(e.getMessage(), e.getCause()); } } @@ -83,6 +79,8 @@ public class PodEventHandler implements ResourceEventHandler<Pod> { public ContainerStatus getPodStatus(Pod pod) { String deployment = pod.getMetadata().getLabels().get("app"); String projectId = deployment != null ? deployment : pod.getMetadata().getLabels().get(LABEL_PROJECT_ID); + String type = deployment != null ? deployment : pod.getMetadata().getLabels().get(LABEL_TYPE); + ContainerStatus.ContainerType containerType = type != null ? ContainerStatus.ContainerType.valueOf(type) : ContainerStatus.ContainerType.unknown; try { boolean ready = pod.getStatus().getConditions().stream().anyMatch(c -> c.getType().equals("Ready")); String creationTimestamp = pod.getMetadata().getCreationTimestamp(); @@ -100,7 +98,7 @@ public class PodEventHandler implements ResourceEventHandler<Pod> { List.of(ContainerStatus.Command.delete), projectId, kubernetesService.environment, - pod.getMetadata().getName().equals(projectId) ? ContainerStatus.ContainerType.devmode : ContainerStatus.ContainerType.project, + containerType, requestMemory + " / " + limitMemory, requestCpu + " / " + limitCpu, creationTimestamp); 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 8bc62635..d9ca389a 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 @@ -27,14 +27,18 @@ import io.vertx.mutiny.ext.web.client.WebClient; import org.apache.camel.karavan.infinispan.InfinispanService; import org.apache.camel.karavan.infinispan.model.CamelStatus; import org.apache.camel.karavan.infinispan.model.ContainerStatus; +import org.apache.camel.karavan.infinispan.model.ProjectFile; import org.apache.camel.karavan.kubernetes.KubernetesService; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.faulttolerance.CircuitBreaker; +import org.eclipse.microprofile.faulttolerance.Retry; import org.jboss.logging.Logger; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import java.util.Arrays; +import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.concurrent.ExecutionException; @@ -43,6 +47,7 @@ public class CamelService { 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 RELOAD_PROJECT_CODE = "RELOAD_PROJECT_CODE"; @Inject InfinispanService infinispanService; @@ -78,9 +83,11 @@ public class CamelService { .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)); + ).forEach(cs -> { + CamelStatusRequest csr = new CamelStatusRequest(cs.getProjectId(), cs.getContainerName()); + eventBus.publish(CMD_COLLECT_CAMEL_STATUS, + JsonObject.mapFrom(Map.of("containerStatus", cs, "camelStatusRequest", csr)) + ); }); } } @@ -95,11 +102,12 @@ public class CamelService { } } + @ConsumeEvent(value = RELOAD_PROJECT_CODE, blocking = true, ordered = true) public void reloadProjectCode(String projectId) { LOGGER.info("Reload project code " + projectId); try { - infinispanService.getProjectFiles(projectId).forEach(projectFile -> - putRequest(projectId, projectFile.getName(), projectFile.getCode(), 1000)); + List<ProjectFile> files = infinispanService.getProjectFiles(projectId); + files.forEach(projectFile -> putRequest(projectId, projectFile.getName(), projectFile.getCode(), 1000)); reloadRequest(projectId); ContainerStatus containerStatus = infinispanService.getDevModeContainerStatus(projectId, environment); containerStatus.setCodeLoaded(true); @@ -134,7 +142,7 @@ public class CamelService { public String getContainerAddress(String containerName) { if (ConfigService.inKubernetes()) { - return "http://" + containerName + "." + kubernetesService.getNamespace() + ".svc.cluster.local"; + return "http://" + containerName + "." + kubernetesService.getNamespace(); } else if (ConfigService.inDocker()) { return "http://" + containerName + ":8080"; } else { @@ -145,7 +153,8 @@ public class CamelService { @ConsumeEvent(value = CMD_COLLECT_CAMEL_STATUS, blocking = true, ordered = true) public void collectCamelStatuses(JsonObject data) { - CamelStatusRequest dms = data.mapTo(CamelStatusRequest.class); + CamelStatusRequest dms = data.getJsonObject("camelStatusRequest").mapTo(CamelStatusRequest.class); + ContainerStatus containerStatus = data.getJsonObject("containerStatus").mapTo(ContainerStatus.class); String projectId = dms.getProjectId(); Arrays.stream(CamelStatus.Name.values()).forEach(statusName -> { String containerName = dms.getContainerName(); @@ -153,10 +162,23 @@ public class CamelService { if (status != null) { CamelStatus cs = new CamelStatus(projectId, containerName, statusName, status, environment); infinispanService.saveCamelStatus(cs); + if (ConfigService.inKubernetes() && Objects.equals(statusName, CamelStatus.Name.context)) { + checkReloadRequired(containerStatus); + } } }); } + private void checkReloadRequired(ContainerStatus cs) { + if (ConfigService.inKubernetes()) { + if (!Objects.equals(cs.getCodeLoaded(), true) + && Objects.equals(cs.getState(), ContainerStatus.State.running.name()) + && Objects.equals(cs.getType(), ContainerStatus.ContainerType.devmode)) { + eventBus.publish(RELOAD_PROJECT_CODE, cs.getProjectId()); + } + } + } + public String getCamelStatus(String podName, CamelStatus.Name statusName) { String url = getContainerAddress(podName) + "/q/dev/" + statusName.name(); try { diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ConfigService.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ConfigService.java index a1e24955..349a41e2 100644 --- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ConfigService.java +++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ConfigService.java @@ -27,6 +27,7 @@ import org.eclipse.microprofile.config.inject.ConfigProperty; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.event.Observes; +import java.nio.file.Files; import java.nio.file.Paths; import java.util.List; import java.util.Objects; @@ -77,7 +78,7 @@ public class ConfigService { public static boolean inDocker() { if (inDocker == null) { - inDocker = Vertx.vertx().fileSystem().existsBlocking(".dockerenv"); + inDocker = !inKubernetes() && Files.exists(Paths.get(".dockerenv")); } return inDocker; } 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 c3b310bc..f6dbec9d 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 @@ -17,6 +17,8 @@ import java.time.temporal.ChronoUnit; import java.util.List; import java.util.Objects; +import static org.apache.camel.karavan.service.CamelService.RELOAD_PROJECT_CODE; + @ApplicationScoped public class ContainerStatusService { @@ -36,7 +38,7 @@ public class ContainerStatusService { @Scheduled(every = "{karavan.container.statistics.interval}", concurrentExecution = Scheduled.ConcurrentExecution.SKIP) void collectContainersStatistics() { - if (infinispanService.isReady()) { + if (infinispanService.isReady() && !ConfigService.inKubernetes()) { List<ContainerStatus> statusesInDocker = dockerService.collectContainersStatistics(); statusesInDocker.forEach(containerStatus -> { eventBus.send(ContainerStatusService.CONTAINER_STATUS, JsonObject.mapFrom(containerStatus)); @@ -46,17 +48,19 @@ public class ContainerStatusService { @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); + if (infinispanService.isReady() && !ConfigService.inKubernetes()) { + if (!ConfigService.inKubernetes()) { + 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()) { + if (infinispanService.isReady() && !ConfigService.inKubernetes()) { List<String> namesInDocker = statusesInDocker.stream().map(ContainerStatus::getContainerName).toList(); List<ContainerStatus> statusesInInfinispan = infinispanService.getContainerStatuses(environment); // clean deleted diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/KaravanService.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/KaravanService.java index 77f536d0..1b58d660 100644 --- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/KaravanService.java +++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/KaravanService.java @@ -80,7 +80,7 @@ public class KaravanService implements HealthCheck { @Inject ProjectService projectService; - private static final String START_KUBERNETES_LISTENERS = "START_KUBERNETES_LISTENERS"; + private static final String START_KUBERNETES_SERVICES = "START_KUBERNETES_LISTENERS"; private static final String START_INTERNAL_DOCKER_SERVICES = "START_INTERNAL_DOCKER_SERVICES"; private static final String START_SERVICES = "START_SERVICES"; @@ -93,7 +93,7 @@ public class KaravanService implements HealthCheck { if (!ConfigService.inKubernetes()) { eventBus.publish(START_INTERNAL_DOCKER_SERVICES, null); } else { - eventBus.publish(START_KUBERNETES_LISTENERS, null); + eventBus.publish(START_KUBERNETES_SERVICES, null); } eventBus.publish(START_SERVICES, null); } @@ -112,6 +112,7 @@ public class KaravanService implements HealthCheck { dockerForGitea.startGitea(); giteaService.install(); dockerForGitea.createGiteaUser(); + giteaService.createRepository(); } if (registryInstall) { dockerForRegistry.startRegistry(); @@ -119,9 +120,12 @@ public class KaravanService implements HealthCheck { } } - @ConsumeEvent(value = START_KUBERNETES_LISTENERS, blocking = true) - void startKubernetesListeners(String data) throws Exception { + @ConsumeEvent(value = START_KUBERNETES_SERVICES, blocking = true) + void startKubernetesServices(String data) throws Exception { LOGGER.info("Starting Karavan in Kubernetes"); + if (giteaInstall) { + giteaService.createRepository(); + } kubernetesService.startInformers(null); } 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 b92d8e23..6f3cac08 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 @@ -111,6 +111,7 @@ public class ProjectService implements HealthCheck { Map<String, String> files = infinispanService.getProjectFiles(project.getProjectId()).stream() .filter(f -> !Objects.equals(f.getName(), PROJECT_COMPOSE_FILENAME)) .collect(Collectors.toMap(ProjectFile::getName, ProjectFile::getCode)); + ProjectFile compose = infinispanService.getProjectFile(project.getProjectId(), PROJECT_COMPOSE_FILENAME); DockerComposeService dcs = DockerComposeConverter.fromCode(compose.getCode(), project.getProjectId()); Map<String, String> volumes = mavenCache @@ -206,7 +207,7 @@ public class ProjectService implements HealthCheck { return codeService.getProjectPort(composeFile); } - @Retry(maxRetries = 100, delay = 2000) +// @Retry(maxRetries = 100, delay = 2000) public void tryStart() throws Exception { if (infinispanService.isReady() && gitService.checkGit()) { if (infinispanService.getProjects().isEmpty()) { diff --git a/karavan-web/karavan-app/src/main/resources/application.properties b/karavan-web/karavan-app/src/main/resources/application.properties index 4575a8b0..0b3dc433 100644 --- a/karavan-web/karavan-app/src/main/resources/application.properties +++ b/karavan-web/karavan-app/src/main/resources/application.properties @@ -3,11 +3,16 @@ karavan.environment=dev karavan.environments=dev karavan.default-runtime=camel-main karavan.runtimes=camel-main,quarkus,spring-boot + karavan.camel.status.interval=2s karavan.container.status.interval=2s +# karavan.container.status.interval should be off in kubernetes + karavan.container.statistics.interval=10s +# karavan.container.statistics.interval should be off in kubernetes + karavan.devmode.image=ghcr.io/apache/camel-karavan-devmode:4.0.0-RC2 -karavan.maven.cach +karavan.maven.cache= # Git repository Configuration karavan.git-repository=http://gitea:3000/karavan/karavan.git