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 c8a13f22531c1fa0521b8517bcca623824f12312
Author: Marat Gubaidullin <ma...@talismancloud.io>
AuthorDate: Thu Aug 31 10:48:45 2023 -0400

    Unifying Docker deployment for #817
---
 .../camel/karavan/api/InfrastructureResource.java  |  10 +-
 .../camel/karavan/docker/DockerForGitea.java       |  46 ++-------
 .../camel/karavan/docker/DockerForInfinispan.java  |  24 +----
 .../camel/karavan/docker/DockerForKaravan.java     |  23 ++---
 .../apache/camel/karavan/docker/DockerService.java | 105 +++++++++++++++++++--
 .../camel/karavan/docker/DockerServiceUtils.java   |  77 +++++++++------
 .../{DevService.java => DockerComposeService.java} |   6 +-
 .../src/main/resources/application.properties      |   1 -
 .../karavan-app/src/main/resources/gitea/app.ini   |  94 ++++++++++++++++++
 .../src/main/resources/services/internal.yaml      |  31 ++++++
 10 files changed, 299 insertions(+), 118 deletions(-)

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 17f4c526..5c5f9fae 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
@@ -22,7 +22,7 @@ import io.vertx.mutiny.core.eventbus.EventBus;
 import io.vertx.mutiny.core.eventbus.Message;
 import org.apache.camel.karavan.docker.DockerForKaravan;
 import org.apache.camel.karavan.docker.DockerService;
-import org.apache.camel.karavan.docker.model.DevService;
+import org.apache.camel.karavan.docker.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;
@@ -195,10 +195,10 @@ public class InfrastructureResource {
                 if (command.getString("command").equalsIgnoreCase("run")) {
                     if (Objects.equals(type, 
ContainerStatus.ContainerType.devservice.name())) {
                         String code = projectService.getDevServiceCode();
-                        DevService devService = 
dockerService.getDevService(code, name);
-                        if (devService != null) {
-                            
dockerForKaravan.createDevserviceContainer(devService);
-                            
dockerService.runContainer(devService.getContainer_name());
+                        DockerComposeService dockerComposeService = 
dockerService.convertToDockerComposeService(code, name);
+                        if (dockerComposeService != null) {
+                            
dockerForKaravan.createDevserviceContainer(dockerComposeService);
+                            
dockerService.runContainer(dockerComposeService.getContainer_name());
                         }
                     } else if (Objects.equals(type, 
ContainerStatus.ContainerType.devmode.name())) {
                         dockerForKaravan.createDevmodeContainer(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 9e5d6c6e..8cde9667 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
@@ -18,21 +18,14 @@ package org.apache.camel.karavan.docker;
 
 import com.github.dockerjava.api.command.ExecCreateCmdResponse;
 import com.github.dockerjava.api.model.Container;
-import com.github.dockerjava.api.model.HealthCheck;
 import jakarta.enterprise.context.ApplicationScoped;
 import jakarta.inject.Inject;
 import org.apache.camel.karavan.infinispan.model.ContainerStatus;
 import org.apache.camel.karavan.infinispan.model.GitConfig;
 import org.apache.camel.karavan.service.GitService;
 import org.apache.camel.karavan.service.GiteaService;
-import org.eclipse.microprofile.config.inject.ConfigProperty;
 import org.jboss.logging.Logger;
 
-import java.util.List;
-import java.util.Map;
-
-import static org.apache.camel.karavan.shared.Constants.LABEL_TYPE;
-
 @ApplicationScoped
 public class DockerForGitea {
 
@@ -40,11 +33,6 @@ public class DockerForGitea {
 
     protected static final String GITEA_CONTAINER_NAME = "gitea";
 
-    private static final List<String> giteaHealthCheckCMD = List.of("CMD", 
"curl", "-fss", "127.0.0.1:3000/api/healthz");
-
-    @ConfigProperty(name = "karavan.gitea.image")
-    String giteaImage;
-
     @Inject
     DockerService dockerService;
 
@@ -57,39 +45,22 @@ public class DockerForGitea {
     public void startGitea() {
         try {
             LOGGER.info("Gitea container is starting...");
-
-            HealthCheck healthCheck = new 
HealthCheck().withTest(giteaHealthCheckCMD)
-                    
.withInterval(10000000000L).withTimeout(10000000000L).withStartPeriod(10000000000L).withRetries(30);
-
-            dockerService.createContainer(GITEA_CONTAINER_NAME, giteaImage,
-                    List.of(), "3000:3000", false, List.of("3000"), 
healthCheck,
-                    Map.of(LABEL_TYPE, 
ContainerStatus.ContainerType.internal.name()));
-
+            var compose = 
dockerService.getInternalDockerComposeService(GITEA_CONTAINER_NAME);
+            Container c = dockerService.createContainerFromCompose(compose, 
ContainerStatus.ContainerType.internal);
+            copyAppIni(c.getId());
             dockerService.runContainer(GITEA_CONTAINER_NAME);
-
             LOGGER.info("Gitea container is started");
         } catch (Exception e) {
             LOGGER.error(e.getMessage());
         }
     }
 
-    protected void createGiteaInstance() {
+    protected void copyAppIni(String containerId) {
         try {
-            LOGGER.info("Creating Gitea Instance");
-            Container gitea = 
dockerService.getContainerByName(GITEA_CONTAINER_NAME);
-            ExecCreateCmdResponse instance = 
dockerService.execCreate(gitea.getId(),
-                            "curl", "-X", "POST", "localhost:3000", "-d",
-                            
"db_type=sqlite3&db_host=localhost%3A3306&db_user=root&db_passwd=&db_name=gitea"
 +
-                                    
"&ssl_mode=disable&db_schema=&db_path=%2Fvar%2Flib%2Fgitea%2Fdata%2Fgitea.db&app_name=Gitea%3A+Git+with+a+cup+of+tea"
 +
-                                    
"&repo_root_path=%2Fvar%2Flib%2Fgitea%2Fgit%2Frepositories&lfs_root_path=%2Fvar%2Flib%2Fgitea%2Fgit%2Flfs&run_user=git"
 +
-                                    
"&domain=localhost&ssh_port=2222&http_port=3000&app_url=http%3A%2F%2Flocalhost%3A3000%2F&log_root_path=%2Fvar%2Flib%2Fgitea%2Fdata%2Flog"
 +
-                                    
"&smtp_addr=&smtp_port=&smtp_from=&smtp_user=&smtp_passwd=&enable_federated_avatar=on&enable_open_id_sign_in=on"
 +
-                                    
"&enable_open_id_sign_up=on&default_allow_create_organization=on&default_enable_timetracking=on"
 +
-                                    
"&no_reply_address=noreply.localhost&password_algorithm=pbkdf2&admin_name=&admin_email=&admin_passwd=&admin_confirm_passwd=",
-                            "-H", "'Content-Type: 
application/x-www-form-urlencoded'");
-
-            dockerService.execStart(instance.getId());
-            LOGGER.info("Created Gitea Instance");
+            LOGGER.info("Copying Gitea app.ini");
+            String ini = DockerServiceUtils.getResourceFile("/gitea/app.ini");
+            dockerService.copyFile(containerId, "/etc/gitea","app.ini", ini);
+            LOGGER.info("Copied Gitea app.ini");
         } catch (Exception e) {
             LOGGER.error(e.getMessage());
         }
@@ -128,7 +99,6 @@ public class DockerForGitea {
     }
 
     public void installGitea() {
-        createGiteaInstance();
         checkGiteaInstance();
     }
 }
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForInfinispan.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForInfinispan.java
index 802d8de2..b6b6673e 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForInfinispan.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForInfinispan.java
@@ -17,7 +17,6 @@
 package org.apache.camel.karavan.docker;
 
 import com.github.dockerjava.api.command.HealthState;
-import com.github.dockerjava.api.model.HealthCheck;
 import io.vertx.core.eventbus.EventBus;
 import jakarta.enterprise.context.ApplicationScoped;
 import jakarta.inject.Inject;
@@ -26,9 +25,6 @@ import org.eclipse.microprofile.config.inject.ConfigProperty;
 import org.jboss.logging.Logger;
 
 import java.util.List;
-import java.util.Map;
-
-import static org.apache.camel.karavan.shared.Constants.LABEL_TYPE;
 import static org.apache.camel.karavan.shared.EventType.INFINISPAN_STARTED;
 
 @ApplicationScoped
@@ -38,12 +34,6 @@ public class DockerForInfinispan {
 
     protected static final String INFINISPAN_CONTAINER_NAME = "infinispan";
 
-    private static final List<String> infinispanHealthCheckCMD = 
List.of("CMD", "curl", "-f", 
"http://localhost:11222/rest/v2/cache-managers/default/health/status";);
-
-    @ConfigProperty(name = "karavan.infinispan.image")
-    String infinispanImage;
-    @ConfigProperty(name = "karavan.infinispan.port")
-    String infinispanPort;
     @ConfigProperty(name = "karavan.infinispan.username")
     String infinispanUsername;
     @ConfigProperty(name = "karavan.infinispan.password")
@@ -58,17 +48,9 @@ public class DockerForInfinispan {
     public void startInfinispan() {
         try {
             LOGGER.info("Infinispan is starting...");
-
-            HealthCheck healthCheck = new 
HealthCheck().withTest(infinispanHealthCheckCMD)
-                    
.withInterval(10000000000L).withTimeout(10000000000L).withStartPeriod(10000000000L).withRetries(30);
-
-            List<String> exposedPorts = List.of(infinispanPort.split(":")[0]);
-
-            dockerService.createContainer(INFINISPAN_CONTAINER_NAME, 
infinispanImage,
-                    List.of("USER=" + infinispanUsername, "PASS=" + 
infinispanPassword),
-                    infinispanPort, false, exposedPorts, healthCheck,
-                    Map.of(LABEL_TYPE, 
ContainerStatus.ContainerType.internal.name()));
-
+            var compose = 
dockerService.getInternalDockerComposeService(INFINISPAN_CONTAINER_NAME);
+            compose.getEnvironmentList().addAll(List.of("USER=" + 
infinispanUsername, "PASS=" + infinispanPassword));
+            dockerService.createContainerFromCompose(compose, 
ContainerStatus.ContainerType.internal);
             dockerService.runContainer(INFINISPAN_CONTAINER_NAME);
             LOGGER.info("Infinispan is started");
         } catch (Exception e) {
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 ee0a6864..c6d2b728 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
@@ -19,7 +19,7 @@ package org.apache.camel.karavan.docker;
 import com.github.dockerjava.api.model.HealthCheck;
 import jakarta.enterprise.context.ApplicationScoped;
 import jakarta.inject.Inject;
-import org.apache.camel.karavan.docker.model.DevService;
+import org.apache.camel.karavan.docker.model.DockerComposeService;
 import org.apache.camel.karavan.infinispan.model.ContainerStatus;
 import org.eclipse.microprofile.config.inject.ConfigProperty;
 import org.jboss.logging.Logger;
@@ -62,23 +62,15 @@ public class DockerForKaravan {
 
         dockerService.createContainer(projectId, devmodeImage,
                 env, null, false, List.of(), healthCheck,
-                Map.of(LABEL_TYPE, 
ContainerStatus.ContainerType.devmode.name(), LABEL_PROJECT_ID, projectId));
+                Map.of(LABEL_TYPE, 
ContainerStatus.ContainerType.devmode.name(), LABEL_PROJECT_ID, projectId),
+                Map.of());
 
         LOGGER.infof("DevMode started for %s", projectId);
     }
 
-    public void createDevserviceContainer(DevService devService) throws 
InterruptedException {
-        LOGGER.infof("DevService starting for ", 
devService.getContainer_name());
-
-        HealthCheck healthCheck = 
dockerService.getHealthCheck(devService.getHealthcheck());
-        List<String> env = devService.getEnvironment() != null ? 
devService.getEnvironmentList() : List.of();
-        String ports = String.join(",", devService.getPorts());
-
-        dockerService.createContainer(devService.getContainer_name(), 
devService.getImage(),
-                env, ports, false, devService.getExpose(), healthCheck,
-                Map.of(LABEL_TYPE, 
ContainerStatus.ContainerType.devservice.name()));
-
-        LOGGER.infof("DevService started for %s", 
devService.getContainer_name());
+    public void createDevserviceContainer(DockerComposeService 
dockerComposeService) throws InterruptedException {
+        LOGGER.infof("DevService starting for ", 
dockerComposeService.getContainer_name());
+        dockerService.createContainerFromCompose(dockerComposeService, 
ContainerStatus.ContainerType.devservice);
     }
 
     public void startKaravanHeadlessContainer() {
@@ -92,7 +84,8 @@ public class DockerForKaravan {
                             "INFINISPAN_PASSWORD=" + infinispanPassword
                     ),
                     null, false, List.of(), new HealthCheck(),
-                    Map.of(LABEL_TYPE, 
ContainerStatus.ContainerType.internal.name()));
+                    Map.of(LABEL_TYPE, 
ContainerStatus.ContainerType.internal.name()),
+                    Map.of());
 
             dockerService.runContainer(KARAVAN_CONTAINER_NAME);
             LOGGER.info("Karavan headless is started");
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 5f4a3b10..10c8018e 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
@@ -24,20 +24,30 @@ import com.github.dockerjava.core.DefaultDockerClientConfig;
 import com.github.dockerjava.core.DockerClientConfig;
 import com.github.dockerjava.core.DockerClientImpl;
 import com.github.dockerjava.core.InvocationBuilder;
+import com.github.dockerjava.core.util.CompressArchiveUtil;
 import com.github.dockerjava.transport.DockerHttpClient;
 import com.github.dockerjava.zerodep.ZerodepDockerHttpClient;
-import io.vertx.core.eventbus.EventBus;
+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.docker.model.DockerComposeService;
 import org.apache.camel.karavan.infinispan.model.ContainerStatus;
+import org.apache.commons.compress.archivers.ArchiveEntry;
+import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
+import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
 import org.eclipse.microprofile.config.inject.ConfigProperty;
 import org.jboss.logging.Logger;
 
-import java.io.IOException;
+import java.io.*;
+import java.nio.file.LinkOption;
+import java.nio.file.Paths;
 import java.time.Instant;
 import java.util.*;
 import java.util.stream.Collectors;
 
+import static org.apache.camel.karavan.shared.Constants.LABEL_TYPE;
+
 @ApplicationScoped
 public class DockerService extends DockerServiceUtils {
 
@@ -52,7 +62,7 @@ public class DockerService extends DockerServiceUtils {
     DockerEventListener dockerEventListener;
 
     @Inject
-    EventBus eventBus;
+    Vertx vertx;
 
     private DockerClient dockerClient;
 
@@ -132,8 +142,40 @@ public class DockerService extends DockerServiceUtils {
         return stats;
     }
 
+    public Container createContainerFromCompose(DockerComposeService compose, 
ContainerStatus.ContainerType type) throws InterruptedException {
+        List<Container> containers = 
getDockerClient().listContainersCmd().withShowAll(true).withNameFilter(List.of(compose.getContainer_name())).exec();
+        if (containers.isEmpty()) {
+            LOGGER.infof("Compose Service starting for ", 
compose.getContainer_name());
+
+            HealthCheck healthCheck = getHealthCheck(compose.getHealthcheck());
+            List<String> env = compose.getEnvironment() != null ? 
compose.getEnvironmentList() : List.of();
+            String ports = String.join(",", compose.getPorts());
+
+            LOGGER.infof("Compose Service started for %s", 
compose.getContainer_name());
+
+            return createContainer(compose.getContainer_name(), 
compose.getImage(),
+                    env, ports, false, compose.getExpose(), healthCheck,
+                    Map.of(LABEL_TYPE, type.name()),
+                    Map.of());
+
+        } else {
+            LOGGER.info("Compose Service already exists: " + 
containers.get(0).getId());
+            return containers.get(0);
+        }
+    }
+
+    public Container createContainerFromCompose(String yaml, String name, 
ContainerStatus.ContainerType type) throws Exception {
+        var compose = convertToDockerComposeService(yaml, name);
+        if (compose != null) {
+            return createContainerFromCompose(compose, type);
+        } else {
+            throw new Exception("Service not found in compose YAML!");
+        }
+    }
+
     public Container createContainer(String name, String image, List<String> 
env, String ports, boolean inRange,
-                                     List<String> exposed, HealthCheck 
healthCheck, Map<String, String> labels) throws InterruptedException {
+                                     List<String> exposed, HealthCheck 
healthCheck, Map<String, String> labels,
+                                     Map<String, String> volumes) throws 
InterruptedException {
         List<Container> containers = 
getDockerClient().listContainersCmd().withShowAll(true).withNameFilter(List.of(name)).exec();
         if (containers.size() == 0) {
             pullImage(image);
@@ -141,14 +183,29 @@ public class DockerService extends DockerServiceUtils {
             CreateContainerCmd createContainerCmd = 
getDockerClient().createContainerCmd(image)
                     
.withName(name).withLabels(labels).withEnv(env).withHostName(name).withHealthcheck(healthCheck);
 
+            Ports portBindings;
+            List<ExposedPort> exposedPorts = new ArrayList<>();
             if (exposed != null) {
-                List<ExposedPort> exposedPorts = exposed.stream().map(i -> 
ExposedPort.tcp(Integer.parseInt(i))).collect(Collectors.toList());
-                createContainerCmd.withExposedPorts(exposedPorts);
-                createContainerCmd.withHostConfig(getHostConfig(ports, 
exposedPorts, inRange, NETWORK_NAME));
+                exposedPorts.addAll(exposed.stream().map(i -> 
ExposedPort.tcp(Integer.parseInt(i))).toList());
+                portBindings = getPortBindings(ports,exposedPorts, inRange);
             } else {
-                createContainerCmd.withHostConfig(getHostConfig(ports, 
List.of(), inRange, NETWORK_NAME));
+                portBindings = getPortBindings(ports,exposedPorts, inRange);
             }
 
+            List<Mount> mounts = new ArrayList<>();
+            if (volumes != null && !volumes.isEmpty()) {
+                volumes.forEach((hostPath, containerPath) -> {
+                    mounts.add(new 
Mount().withType(MountType.BIND).withSource(hostPath).withTarget(containerPath));
+                });
+            }
+
+            createContainerCmd.withExposedPorts(exposedPorts);
+            createContainerCmd.withHostConfig(new HostConfig()
+                    .withPortBindings(portBindings)
+                            .withMounts(mounts)
+                    .withNetworkMode(NETWORK_NAME));
+
+
             CreateContainerResponse response = createContainerCmd.exec();
             LOGGER.info("Container created: " + response.getId());
             return getDockerClient().listContainersCmd().withShowAll(true)
@@ -170,10 +227,23 @@ public class DockerService extends DockerServiceUtils {
             }
         }
     }
+
     public List<Container> listContainers(Boolean showAll) {
         return 
getDockerClient().listContainersCmd().withShowAll(showAll).exec();
     }
 
+    public List<InspectVolumeResponse> listVolumes() {
+        return getDockerClient().listVolumesCmd().exec().getVolumes();
+    }
+
+    public InspectVolumeResponse getVolume(String name) {
+        return getDockerClient().inspectVolumeCmd(name).exec();
+    }
+
+    public CreateVolumeResponse createVolume(String name) {
+        return getDockerClient().createVolumeCmd().withName(name).exec();
+    }
+
     public InspectContainerResponse inspectContainer(String id) {
         return getDockerClient().inspectContainerCmd(id).exec();
     }
@@ -189,10 +259,29 @@ public class DockerService extends DockerServiceUtils {
     public void execStart(String id) throws InterruptedException {
         getDockerClient().execStartCmd(id).start().awaitCompletion();
     }
+
     public void execStart(String id, ResultCallback.Adapter<Frame> callBack) 
throws InterruptedException {
         getDockerClient().execStartCmd(id).exec(callBack).awaitCompletion();
     }
 
+    public void copyFile(String id, String containerPath, String filename, 
String text) throws IOException {
+//        try (ByteArrayOutputStream byteArrayOutputStream = new 
ByteArrayOutputStream();
+//                TarArchiveOutputStream tarArchive = new 
TarArchiveOutputStream(byteArrayOutputStream)) {
+//            
tarArchive.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
+//            
tarArchive.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_POSIX);
+//
+//            String temp = 
vertx.fileSystem().createTempDirectoryBlocking("x");
+//            String path = temp + File.separator + filename;
+//            vertx.fileSystem().writeFileBlocking(path, Buffer.buffer(text));
+//
+//            ArchiveEntry archive = 
tarArchive.createArchiveEntry(Paths.get(path), "app.ini");
+//            tarArchive.putArchiveEntry(archive);;
+//            tarArchive.finish();
+            
getDockerClient().copyArchiveToContainerCmd(id).withRemotePath("/data")
+                    
.withHostResource("/Users/marat/projects/camel-karavan/karavan-web/karavan-app/src/main/resources/gitea").exec();
+//        }
+    }
+
     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/docker/DockerServiceUtils.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerServiceUtils.java
index 3d7cb8e3..703f33ae 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerServiceUtils.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerServiceUtils.java
@@ -18,28 +18,32 @@ package org.apache.camel.karavan.docker;
 
 import com.github.dockerjava.api.model.*;
 import io.smallrye.mutiny.tuples.Tuple2;
+import io.vertx.core.json.JsonArray;
 import io.vertx.core.json.JsonObject;
 import org.apache.camel.karavan.api.KameletResources;
-import org.apache.camel.karavan.docker.model.DevService;
+import org.apache.camel.karavan.docker.model.DockerComposeService;
 import org.apache.camel.karavan.docker.model.HealthCheckConfig;
 import org.apache.camel.karavan.infinispan.model.ContainerStatus;
 import org.apache.camel.karavan.service.CodeService;
 import org.yaml.snakeyaml.Yaml;
 
 import jakarta.inject.Inject;
-import java.io.BufferedReader;
-import java.io.InputStream;
-import java.io.InputStreamReader;
+
+import java.io.*;
 import java.text.DecimalFormat;
+import java.time.Duration;
 import java.time.Instant;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 import static org.apache.camel.karavan.shared.Constants.LABEL_TYPE;
 
 public class DockerServiceUtils {
 
+    protected static final String ENVIRONMENT = "environment";
+
     protected static final DecimalFormat formatCpu = new DecimalFormat("0.00");
     protected static final DecimalFormat formatMiB = new DecimalFormat("0.0");
     protected static final DecimalFormat formatGiB = new DecimalFormat("0.00");
@@ -67,42 +71,57 @@ public class DockerServiceUtils {
         }
     }
 
-    public DevService getDevService(String code, String name) {
+    public DockerComposeService getInternalDockerComposeService (String name) {
+        String composeText = getResourceFile("/services/internal.yaml");
+        return convertToDockerComposeService(composeText, name);
+    }
+
+    public DockerComposeService convertToDockerComposeService(String code, 
String name) {
         Yaml yaml = new Yaml();
         Map<String, Object> obj = yaml.load(code);
         JsonObject json = JsonObject.mapFrom(obj);
         JsonObject services = json.getJsonObject("services");
         if (services.containsKey(name)) {
-            DevService ds = 
services.getJsonObject(name).mapTo(DevService.class);
-            if (ds.getContainer_name() == null) {
-                ds.setContainer_name(name);
-            }
-            return ds;
+            JsonObject service = services.getJsonObject(name);
+            return convertToDockerComposeService(name, service);
         } else {
             Optional<JsonObject> j = services.fieldNames().stream()
                     .map(services::getJsonObject)
-                    .filter(s -> {
-                        s.getJsonObject("container_name");
-                        return false;
-                    }).findFirst();
+                    .filter(s -> 
s.getString("container_name").equalsIgnoreCase(name)).findFirst();
             if (j.isPresent()) {
-                return j.get().mapTo(DevService.class);
+                return convertToDockerComposeService(name, j.get());
             }
         }
         return null;
     }
 
+    public DockerComposeService convertToDockerComposeService(String name, 
JsonObject service) {
+        if (service.containsKey(ENVIRONMENT) && service.getValue(ENVIRONMENT) 
instanceof JsonArray) {
+            JsonObject env = new JsonObject();
+            service.getJsonArray(ENVIRONMENT).forEach(o -> {
+                String[] kv = o.toString().split("=");
+                env.put(kv[0], kv[1]);
+            });
+            service.put(ENVIRONMENT, env);
+        }
+        DockerComposeService ds = service.mapTo(DockerComposeService.class);
+        if (ds.getContainer_name() == null) {
+            ds.setContainer_name(name);
+        }
+        return ds;
+    }
+
     protected HealthCheck getHealthCheck(HealthCheckConfig config) {
         if (config != null) {
             HealthCheck healthCheck = new 
HealthCheck().withTest(config.getTest());
             if (config.getInterval() != null) {
-                
healthCheck.withInterval(convertDuration(config.getInterval()));
+                healthCheck.withInterval(durationNanos(config.getInterval()));
             }
             if (config.getTimeout() != null) {
-                healthCheck.withTimeout(convertDuration(config.getTimeout()));
+                healthCheck.withTimeout(durationNanos(config.getTimeout()));
             }
             if (config.getStart_period() != null) {
-                
healthCheck.withStartPeriod(convertDuration(config.getStart_period()));
+                
healthCheck.withStartPeriod(durationNanos(config.getStart_period()));
             }
             if (config.getRetries() != null) {
                 healthCheck.withRetries(config.getRetries());
@@ -112,11 +131,7 @@ public class DockerServiceUtils {
         return new HealthCheck();
     }
 
-    protected Long convertDuration(String value) {
-        return Long.parseLong(value.replace("s", "")) * 1000000000L;
-    }
-
-    protected String getResourceFile(String path) {
+    protected static String getResourceFile(String path) {
         try {
             InputStream inputStream = 
KameletResources.class.getResourceAsStream(path);
             return new BufferedReader(new InputStreamReader(inputStream))
@@ -126,7 +141,17 @@ public class DockerServiceUtils {
         }
     }
 
-    protected HostConfig getHostConfig(String ports, List<ExposedPort> 
exposedPorts, boolean inRange, String network) {
+    protected static long durationNanos(String s) {
+        if (Pattern.compile("\\d+d\\s").matcher(s).find()) {
+            int idxSpace = s.indexOf(" ");
+            s = "P" + s.substring(0, idxSpace) + "T" + s.substring(idxSpace + 
1);
+        } else
+            s = "PT" + s;
+        s = s.replace(" ", "");
+        return Duration.parse(s).toMillis() * 1000000L;
+    }
+
+    protected Ports getPortBindings(String ports, List<ExposedPort> 
exposedPorts, boolean inRange) {
         Ports portBindings = new Ports();
 
         getPortsFromString(ports).forEach((hostPort, containerPort) -> {
@@ -135,9 +160,7 @@ public class DockerServiceUtils {
                     : Ports.Binding.bindPort(hostPort);
             portBindings.bind(ExposedPort.tcp(containerPort), binding);
         });
-        return new HostConfig()
-                .withPortBindings(portBindings)
-                .withNetworkMode(network);
+        return portBindings;
     }
 
     protected Map<Integer, Integer> getPortsFromString(String ports) {
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/model/DevService.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/model/DockerComposeService.java
similarity index 95%
rename from 
karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/model/DevService.java
rename to 
karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/model/DockerComposeService.java
index af218774..eed5fa37 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/model/DevService.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/model/DockerComposeService.java
@@ -4,7 +4,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 
-public class DevService {
+public class DockerComposeService {
 
     private String container_name;
     private String image;
@@ -15,7 +15,7 @@ public class DevService {
     private Map<String,String> environment;
     private HealthCheckConfig healthcheck;
 
-    public DevService() {
+    public DockerComposeService() {
     }
 
     public String getContainer_name() {
@@ -89,7 +89,7 @@ public class DevService {
 
     @Override
     public String toString() {
-        return "DevService{" +
+        return "DockerComposeService {" +
                 "container_name='" + container_name + '\'' +
                 ", image='" + image + '\'' +
                 ", restart='" + restart + '\'' +
diff --git a/karavan-web/karavan-app/src/main/resources/application.properties 
b/karavan-web/karavan-app/src/main/resources/application.properties
index 80c50b65..79e37e0a 100644
--- a/karavan-web/karavan-app/src/main/resources/application.properties
+++ b/karavan-web/karavan-app/src/main/resources/application.properties
@@ -16,7 +16,6 @@ karavan.git-password=karavan
 karavan.git-branch=main
 karavan.git-install-gitea=true
 karavan.git-pull-interval=disabled
-karavan.gitea.image=gitea/gitea:1.20.2-rootless
 
 # Infinispan container config in Docker
 karavan.infinispan.image=quay.io/infinispan/server:14.0.6.Final
diff --git a/karavan-web/karavan-app/src/main/resources/gitea/app.ini 
b/karavan-web/karavan-app/src/main/resources/gitea/app.ini
new file mode 100644
index 00000000..fb1fcf37
--- /dev/null
+++ b/karavan-web/karavan-app/src/main/resources/gitea/app.ini
@@ -0,0 +1,94 @@
+APP_NAME = Karavan
+RUN_USER = git
+RUN_MODE = prod
+WORK_PATH = /var/lib/gitea
+
+[repository]
+ROOT =/var/lib/gitea/data/repositories
+
+[repository.local]
+LOCAL_COPY_PATH = /tmp/gitea/local-repo
+
+[repository.upload]
+TEMP_PATH = /tmp/gitea/uploads
+
+[server]
+APP_DATA_PATH = /var/lib/gitea
+SSH_DOMAIN = 0.0.0.0
+HTTP_PORT = 3000
+ROOT_URL = http://0.0.0.0:3000/
+DISABLE_SSH = false
+; In rootless gitea container only internal ssh server is supported
+START_SSH_SERVER = true
+SSH_PORT = 2222
+SSH_LISTEN_PORT = 2222
+BUILTIN_SSH_SERVER_USER = git
+LFS_START_SERVER = false
+DOMAIN = 0.0.0.0
+OFFLINE_MODE = false
+
+[database]
+PATH =/var/lib/gitea/data/gitea.db
+DB_TYPE = sqlite3
+HOST = localhost:3306
+NAME = gitea
+USER = root
+PASSWD = 
+SCHEMA = 
+SSL_MODE = disable
+LOG_SQL = false
+
+[session]
+PROVIDER_CONFIG = /var/lib/gitea/data/sessions
+PROVIDER = file
+
+[picture]
+AVATAR_UPLOAD_PATH = /var/lib/gitea/data/avatars
+REPOSITORY_AVATAR_UPLOAD_PATH = /var/lib/gitea/data/repo-avatars
+
+[attachment]
+PATH = /var/lib/gitea/data/attachments
+
+[log]
+ROOT_PATH =/var/lib/gitea/data/log
+MODE = console
+LEVEL = info
+
+[security]
+INSTALL_LOCK = true
+SECRET_KEY = 
+REVERSE_PROXY_LIMIT = 1
+REVERSE_PROXY_TRUSTED_PROXIES = *
+PASSWORD_HASH_ALGO = pbkdf2
+
+[service]
+DISABLE_REGISTRATION = true
+REQUIRE_SIGNIN_VIEW = true
+REGISTER_EMAIL_CONFIRM = false
+ENABLE_NOTIFY_MAIL = false
+ALLOW_ONLY_EXTERNAL_REGISTRATION = false
+ENABLE_CAPTCHA = false
+DEFAULT_KEEP_EMAIL_PRIVATE = false
+DEFAULT_ALLOW_CREATE_ORGANIZATION = false
+DEFAULT_ENABLE_TIMETRACKING = false
+NO_REPLY_ADDRESS = noreply.localhost
+ENABLE_BASIC_AUTHENTICATION = true
+
+[lfs]
+PATH = /var/lib/gitea/git/lfs
+
+[mailer]
+ENABLED = false
+
+[openid]
+ENABLE_OPENID_SIGNIN = false
+ENABLE_OPENID_SIGNUP = false
+
+[cron.update_checker]
+ENABLED = false
+
+[repository.pull-request]
+DEFAULT_MERGE_STYLE = merge
+
+[repository.signing]
+DEFAULT_TRUST_MODEL = committer
diff --git a/karavan-web/karavan-app/src/main/resources/services/internal.yaml 
b/karavan-web/karavan-app/src/main/resources/services/internal.yaml
new file mode 100644
index 00000000..5c970982
--- /dev/null
+++ b/karavan-web/karavan-app/src/main/resources/services/internal.yaml
@@ -0,0 +1,31 @@
+version: '3.8'
+
+services:
+
+  infinispan:
+    image: quay.io/infinispan/server:14.0.6.Final
+    restart: always
+    ports:
+      - "11222:11222"
+    healthcheck:
+      test: [ "CMD", "curl", "-f", 
"http://localhost:11222/rest/v2/cache-managers/default/health/status"; ]
+      interval: 30s
+      timeout: 10s
+      retries: 10
+      start_period: 10s
+
+  gitea:
+    image: gitea/gitea:1.20.2-rootless
+    restart: always
+    environment:
+      GITEA__server__APP_DATA_PATH: /data
+#      - USER_UID=1000
+#      - USER_GID=1000
+    ports:
+      - "3000:3000"
+    healthcheck:
+      test: [ "CMD", "curl", "-fss", "127.0.0.1:3000/api/healthz" ]
+      interval: 30s
+      timeout: 10s
+      retries: 10
+      start_period: 10s


Reply via email to