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


The following commit(s) were added to refs/heads/main by this push:
     new 3d36c52d change to limit container resoures for docker (#1149)
3d36c52d is described below

commit 3d36c52db74d2607d9d9bf9c886cc887f41272f3
Author: Vidhya Sagar <36588343+vidhyasag...@users.noreply.github.com>
AuthorDate: Tue Feb 27 23:17:13 2024 +0800

    change to limit container resoures for docker (#1149)
    
    Co-authored-by: Vidhya Sagar <vidhyasa...@ascertain.com.my>
---
 .../camel/karavan/docker/DockerForKaravan.java     | 14 ++++++--
 .../apache/camel/karavan/docker/DockerService.java | 12 +++++--
 .../camel/karavan/docker/DockerServiceUtils.java   | 34 ++++++++++++++++--
 .../camel/karavan/model/DockerComposeService.java  | 41 ++++++++++++++++++++++
 .../main/resources/snippets/docker-compose.yaml    |  3 ++
 5 files changed, 96 insertions(+), 8 deletions(-)

diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForKaravan.java
 
b/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForKaravan.java
index 7c07cbc4..42c9d6f0 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForKaravan.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForKaravan.java
@@ -22,7 +22,9 @@ import com.github.dockerjava.api.model.RestartPolicy;
 import jakarta.enterprise.context.ApplicationScoped;
 import jakarta.inject.Inject;
 import org.apache.camel.karavan.model.ContainerStatus;
+import org.apache.camel.karavan.model.DockerComposeService;
 import org.apache.camel.karavan.model.Project;
+import org.apache.camel.karavan.service.ProjectService;
 import org.eclipse.microprofile.config.inject.ConfigProperty;
 import org.jboss.logging.Logger;
 
@@ -46,6 +48,9 @@ public class DockerForKaravan {
     @Inject
     DockerService dockerService;
 
+    @Inject
+    ProjectService projectService;
+
     public void runProjectInDevMode(String projectId, String jBangOptions, 
Map<Integer, Integer> ports,
                                     Map<String, String> files) throws 
Exception {
         Map<String, String> volumes = getMavenVolumes();
@@ -64,13 +69,16 @@ public class DockerForKaravan {
                 ? List.of(ENV_VAR_JBANG_OPTIONS + "=" + jBangOptions)
                 : List.of();
 
+        DockerComposeService composeService = 
projectService.getProjectDockerComposeService(projectId);
+
         return dockerService.createContainer(projectId, devmodeImage,
                 env, ports, healthCheck,
                 Map.of(LABEL_TYPE, 
ContainerStatus.ContainerType.devmode.name(),
                         LABEL_PROJECT_ID, projectId,
                         LABEL_CAMEL_RUNTIME, CamelRuntime.CAMEL_MAIN.getValue()
                 ),
-                volumes, null, RestartPolicy.noRestart(), false);
+                volumes, null, RestartPolicy.noRestart(), false,
+                composeService.getCpus(), composeService.getCpu_percent(), 
composeService.getMem_limit(), composeService.getMem_reservation());
 
     }
 
@@ -96,7 +104,9 @@ public class DockerForKaravan {
                         LABEL_PROJECT_ID, project.getProjectId(),
                         LABEL_TAG, tag
                 ),
-                volumes, null,RestartPolicy.noRestart(), false, 
"/karavan/builder/build.sh");
+                volumes, null,RestartPolicy.noRestart(), false, 
+                null, null, null, null,
+                "/karavan/builder/build.sh");
     }
 
     private Map<String,String> getMavenVolumes(){
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java 
b/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
index f1a41476..bfd49f1a 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
@@ -36,6 +36,7 @@ import org.apache.camel.karavan.model.ContainerStatus;
 import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
 import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.math.NumberUtils;
 import org.eclipse.microprofile.config.inject.ConfigProperty;
 import org.jboss.logging.Logger;
 
@@ -205,8 +206,9 @@ public class DockerService extends DockerServiceUtils {
                 restartPolicy = RestartPolicy.alwaysRestart();
             }
 
-            return createContainer(compose.getContainer_name(), 
compose.getImage(),
-                    env, compose.getPortsMap(), healthCheck, labels, volumes, 
networkName, restartPolicy, pullAlways, command);
+            return createContainer(compose.getContainer_name(), 
compose.getImage(), 
+                    env, compose.getPortsMap(), healthCheck, labels, volumes, 
networkName, restartPolicy, pullAlways, 
+                    compose.getCpus(), compose.getCpu_percent(), 
compose.getMem_limit(), compose.getMem_reservation(), command);
 
         } else {
             LOGGER.info("Compose Service already exists: " + 
containers.get(0).getId());
@@ -222,7 +224,7 @@ public class DockerService extends DockerServiceUtils {
     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, RestartPolicy restartPolicy,
-                                     boolean pullAlways,
+                                     boolean pullAlways, String cpus, String 
cpu_percent, String mem_limit, String mem_reservation,
                                      String... command) throws 
InterruptedException {
         List<Container> containers = findContainer(name);
         if (containers.isEmpty()) {
@@ -249,6 +251,10 @@ public class DockerService extends DockerServiceUtils {
                             .withRestartPolicy(restartPolicy)
                     .withPortBindings(portBindings)
                     .withMounts(mounts)
+                    .withMemory(parseMemory(mem_limit))
+                    .withMemoryReservation(parseMemory(mem_reservation))
+                    .withCpuPercent(NumberUtils.toLong(cpu_percent))
+                    .withNanoCPUs(NumberUtils.toLong(cpus))
                     .withNetworkMode(network != null ? network : networkName));
 
             CreateContainerResponse response = createContainerCmd.exec();
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerServiceUtils.java
 
b/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerServiceUtils.java
index 10a030e9..67b0a6ae 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerServiceUtils.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerServiceUtils.java
@@ -43,6 +43,31 @@ public class DockerServiceUtils {
     protected static final DecimalFormat formatGiB = new DecimalFormat("0.00");
     protected static final Map<String, Tuple2<Long, Long>> previousStats = new 
ConcurrentHashMap<>();
 
+    private static final Map<String, Long> UNIT_MULTIPLIERS = new 
TreeMap<>(String.CASE_INSENSITIVE_ORDER);;
+    static {
+        UNIT_MULTIPLIERS.put("b", 1L);
+        UNIT_MULTIPLIERS.put("k", 1024L);
+        UNIT_MULTIPLIERS.put("m", 1024L * 1024);
+        UNIT_MULTIPLIERS.put("g", 1024L * 1024 * 1024);
+        // Add more units if needed
+    }
+
+    public static Long parseMemory(String memory) {
+
+        if (memory != null && !memory.isEmpty()) {
+            memory = memory.trim();
+            String numericPart = memory.replaceAll("[^\\d.]", "");
+            double numericValue = Double.parseDouble(numericPart);
+            String unitPart = memory.replaceAll("[\\d.]", "").toLowerCase();
+            Long multiplier = UNIT_MULTIPLIERS.get(unitPart);
+            if (multiplier == null) {
+                throw new IllegalArgumentException("Invalid unit in memory: " 
+ unitPart);
+            }
+            return (long) (numericValue * multiplier);
+        }
+        return null;
+    }
+
     protected ContainerStatus getContainerStatus(Container container, String 
environment) {
         String name = container.getNames()[0].replace("/", "");
         List<ContainerPort> ports = Arrays.stream(container.getPorts())
@@ -53,7 +78,8 @@ public class DockerServiceUtils {
         String created = 
Instant.ofEpochSecond(container.getCreated()).toString();
         String projectId = 
container.getLabels().getOrDefault(LABEL_PROJECT_ID, name);
         String camelRuntime = 
container.getLabels().getOrDefault(LABEL_CAMEL_RUNTIME, "");
-        return ContainerStatus.createWithId(projectId, name, environment, 
container.getId(), container.getImage(), ports, type, commands, 
container.getState(), created, camelRuntime);
+        return ContainerStatus.createWithId(projectId, name, environment, 
container.getId(), container.getImage(),
+                ports, type, commands, container.getState(), created, 
camelRuntime);
     }
 
     protected void updateStatistics(ContainerStatus containerStatus, 
Statistics stats) {
@@ -171,8 +197,10 @@ public class DockerServiceUtils {
     protected String formatCpu(String containerName, Statistics stats) {
         try {
             double cpuUsage = 0;
-            long previousCpu = previousStats.containsKey(containerName) ? 
previousStats.get(containerName).getItem1() : -1;
-            long previousSystem = previousStats.containsKey(containerName) ? 
previousStats.get(containerName).getItem2() : -1;
+            long previousCpu = previousStats.containsKey(containerName) ? 
previousStats.get(containerName).getItem1()
+                    : -1;
+            long previousSystem = previousStats.containsKey(containerName) ? 
previousStats.get(containerName).getItem2()
+                    : -1;
 
             CpuStatsConfig cpuStats = stats.getCpuStats();
             if (cpuStats != null) {
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/model/DockerComposeService.java
 
b/karavan-app/src/main/java/org/apache/camel/karavan/model/DockerComposeService.java
index 5936af4f..426ea7f9 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/model/DockerComposeService.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/model/DockerComposeService.java
@@ -28,6 +28,10 @@ public class DockerComposeService {
     private String container_name;
     private String image;
     private String restart;
+    private String cpus;
+    private String cpu_percent;
+    private String mem_limit;
+    private String mem_reservation;
     private List<String> ports;
     private List<String> expose;
     private List<String> depends_on;
@@ -142,12 +146,48 @@ public class DockerComposeService {
         this.networks = networks;
     }
 
+    public String getCpu_percent() {
+        return cpu_percent;
+    }
+
+    public void setCpu_percent(String cpu_percent) {
+        this.cpu_percent = cpu_percent;
+    }
+
+    public String getCpus() {
+        return cpus;
+    }
+
+    public void setCpus(String cpus) {
+        this.cpus = cpus;
+    }
+
+    public String getMem_limit() {
+        return mem_limit;
+    }
+
+    public void setMem_limit(String mem_limit) {
+        this.mem_limit = mem_limit;
+    }
+
+    public String getMem_reservation() {
+        return mem_reservation;
+    }
+
+    public void setMem_reservation(String mem_reservation) {
+        this.mem_reservation = mem_reservation;
+    }
+    
     @Override
     public String toString() {
         return "DockerComposeService {" +
                 "container_name='" + container_name + '\'' +
                 ", image='" + image + '\'' +
                 ", restart='" + restart + '\'' +
+                ", cpus='" + cpus + '\'' +
+                ", cpu_percent='" + cpu_percent + '\'' +
+                ", mem_limit='" + mem_limit + '\'' +
+                ", mem_reservation='" + mem_reservation + '\'' +
                 ", ports=" + ports +
                 ", env_file=" + env_file +
                 ", networks=" + networks +
@@ -157,4 +197,5 @@ public class DockerComposeService {
                 ", healthcheck=" + healthcheck +
                 '}';
     }
+
 }
diff --git a/karavan-app/src/main/resources/snippets/docker-compose.yaml 
b/karavan-app/src/main/resources/snippets/docker-compose.yaml
index 36c668af..15563049 100644
--- a/karavan-app/src/main/resources/snippets/docker-compose.yaml
+++ b/karavan-app/src/main/resources/snippets/docker-compose.yaml
@@ -1,6 +1,9 @@
 services:
   {projectId}:
     image: {projectImage}
+    cpu_percent: 10
+    mem_limit: 1024M
+    mem_reservation: 512M
     restart: always
     ports:
       - "{projectPort}:8080"

Reply via email to