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 9f9715f9479b526685880309247a060085b55e0d
Author: Marat Gubaidullin <ma...@talismancloud.io>
AuthorDate: Thu Oct 24 09:00:17 2024 -0400

    Kubernetes Improvements
---
 .../karavan/kubernetes/KubernetesService.java      | 187 ++++++++++++++++++---
 .../kubernetes/KubernetesStatusService.java        |   6 +-
 .../listener/KubernetesCommandListener.java        |  40 +++++
 .../camel/karavan/model/KubernetesConfigMap.java   |  33 ++++
 .../camel/karavan/model/KubernetesSecret.java      |  33 ++++
 5 files changed, 274 insertions(+), 25 deletions(-)

diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/KubernetesService.java
 
b/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/KubernetesService.java
index b5e5cba8..8e5b5967 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/KubernetesService.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/KubernetesService.java
@@ -28,7 +28,10 @@ import jakarta.enterprise.context.ApplicationScoped;
 import jakarta.enterprise.inject.Default;
 import jakarta.enterprise.inject.Produces;
 import jakarta.inject.Inject;
-import org.apache.camel.karavan.model.PodContainerStatus;
+import org.apache.camel.karavan.KaravanConstants;
+import org.apache.camel.karavan.model.ContainerType;
+import org.apache.camel.karavan.model.KubernetesConfigMap;
+import org.apache.camel.karavan.model.KubernetesSecret;
 import org.apache.camel.karavan.model.Project;
 import org.apache.camel.karavan.service.CodeService;
 import org.apache.camel.karavan.service.ConfigService;
@@ -48,6 +51,9 @@ public class KubernetesService {
 
     private static final Logger LOGGER = 
Logger.getLogger(KubernetesService.class.getName());
 
+    @ConfigProperty(name = "karavan.environment", defaultValue = 
KaravanConstants.DEV)
+    private String environment;
+
     @Inject
     CodeService codeService;
 
@@ -111,7 +117,7 @@ public class KubernetesService {
     public void runBuildProject(Project project, String podFragment) {
         try (KubernetesClient client = kubernetesClient()) {
             String containerName = project.getProjectId() + BUILDER_SUFFIX;
-            Map<String, String> labels = getLabels(containerName, project, 
PodContainerStatus.ContainerType.build);
+            Map<String, String> labels = getLabels(containerName, project, 
ContainerType.build);
 
 //        Delete old build pod
             Pod old = 
client.pods().inNamespace(getNamespace()).withName(containerName).get();
@@ -128,17 +134,17 @@ public class KubernetesService {
         }
     }
 
-    private Map<String, String> getLabels(String name, Project project, 
PodContainerStatus.ContainerType type) {
+    private Map<String, String> getLabels(String name, Project project, 
ContainerType type) {
         Map<String, String> labels = new HashMap<>();
-        labels.putAll(getRuntimeLabels());
         labels.putAll(getPartOfLabels());
         labels.put("app.kubernetes.io/name", name);
         labels.put(LABEL_PROJECT_ID, project.getProjectId());
         if (type != null) {
             labels.put(LABEL_TYPE, type.name());
         }
-        if (Objects.equals(type, PodContainerStatus.ContainerType.devmode)) {
+        if (Objects.equals(type, ContainerType.devmode)) {
             labels.put(LABEL_CAMEL_RUNTIME, 
CamelRuntime.CAMEL_MAIN.getValue());
+            labels.putAll(getRuntimeLabels());
         }
         return labels;
     }
@@ -229,7 +235,7 @@ public class KubernetesService {
 
     public boolean hasDockerConfigSecret() {
         try (KubernetesClient client = kubernetesClient()) {
-            return 
client.secrets().inNamespace(namespace).withName(BUILD_DOCKER_CONFIG_SECRET).get()
 != null;
+            return 
client.secrets().inNamespace(getNamespace()).withName(BUILD_DOCKER_CONFIG_SECRET).get()
 != null;
         } catch (Exception ex) {
             LOGGER.error(ex.getMessage());
             return false;
@@ -244,16 +250,21 @@ public class KubernetesService {
 
     public void rolloutDeployment(String name) {
         try (KubernetesClient client = kubernetesClient()) {
-            
client.apps().deployments().inNamespace(namespace).withName(name).rolling().restart();
+            
client.apps().deployments().inNamespace(getNamespace()).withName(name).rolling().restart();
         } catch (Exception ex) {
             LOGGER.error(ex.getMessage());
         }
     }
 
-    public void startDeployment(String resources) {
+    public void startDeployment(String resources, Map<String, String> labels) {
         try (KubernetesClient client = kubernetesClient()) {
             KubernetesList list = Serialization.unmarshal(resources, 
KubernetesList.class);
-            list.getItems().forEach(item -> 
client.resource(item).serverSideApply());
+            list.getItems().forEach(item -> {
+                if (labels != null ) {
+                    item.getMetadata().getLabels().putAll(labels);
+                }
+                
client.resource(item).inNamespace(getNamespace()).serverSideApply();
+            });
         } catch (Exception ex) {
             LOGGER.error(ex.getMessage());
         }
@@ -261,9 +272,9 @@ public class KubernetesService {
 
     public void deleteDeployment(String name) {
         try (KubernetesClient client = kubernetesClient()) {
-            LOGGER.info("Delete deployment: " + name + " in the namespace: " + 
namespace);
-            
client.apps().deployments().inNamespace(namespace).withName(name).delete();
-            client.services().inNamespace(namespace).withName(name).delete();
+            LOGGER.info("Delete deployment: " + name + " in the namespace: " + 
getNamespace());
+            
client.apps().deployments().inNamespace(getNamespace()).withName(name).delete();
+            
client.services().inNamespace(getNamespace()).withName(name).delete();
         } catch (Exception ex) {
             LOGGER.error(ex.getMessage());
         }
@@ -322,9 +333,10 @@ public class KubernetesService {
         return result;
     }
 
-    public void runDevModeContainer(Project project, String jBangOptions, 
Map<String, String> files, String projectDevmodeImage, String 
deploymentFragment) {
+    public void runDevModeContainer(Project project, String jBangOptions, 
Map<String, String> files, String projectDevmodeImage, String 
deploymentFragment, Map<String, String> labels, Map<String, String> envVars) {
         String name = project.getProjectId();
-        Map<String, String> labels = getLabels(name, project, 
PodContainerStatus.ContainerType.devmode);
+        Map<String, String> podLabels = new HashMap<>(labels);
+        podLabels.putAll(getLabels(name, project, ContainerType.devmode));
 
         try (KubernetesClient client = kubernetesClient()) {
             if (devmodePVC.orElse(false)) {
@@ -332,13 +344,13 @@ public class KubernetesService {
             }
             Pod old = 
client.pods().inNamespace(getNamespace()).withName(name).get();
             if (old == null) {
-                Pod pod = getDevModePod(name, jBangOptions, labels, 
projectDevmodeImage, deploymentFragment);
+                Pod pod = getDevModePod(name, jBangOptions, podLabels, 
projectDevmodeImage, deploymentFragment, envVars);
                 Pod result = client.resource(pod).serverSideApply();
                 copyFilesToContainer(result, files, "/karavan/code");
                 LOGGER.info("Created pod " + result.getMetadata().getName());
             }
         }
-        createService(name, labels);
+        createService(name, podLabels);
     }
 
     private void copyFilesToContainer(Pod pod, Map<String, String> files, 
String dirName) {
@@ -375,7 +387,7 @@ public class KubernetesService {
                 .build();
     }
 
-    private Pod getDevModePod(String name, String jbangOptions, Map<String, 
String> labels, String projectDevmodeImage, String deploymentFragment) {
+    private Pod getDevModePod(String name, String jbangOptions, Map<String, 
String> labels, String projectDevmodeImage, String deploymentFragment, 
Map<String, String> envVars) {
 
         Deployment deployment = Serialization.unmarshal(deploymentFragment, 
Deployment.class);
         PodSpec podSpec = null;
@@ -404,13 +416,17 @@ public class KubernetesService {
                 .withProtocol("TCP")
                 .build();
 
+        List<EnvVar> environmentVariables = new ArrayList<>();
+        envVars.forEach((k, v) -> environmentVariables.add(new 
EnvVarBuilder().withName(k).withValue(v).build()));
+        environmentVariables.add(new 
EnvVarBuilder().withName(ENV_VAR_JBANG_OPTIONS).withValue(jbangOptions).build());
+
         Container container = new ContainerBuilder()
                 .withName(name)
                 .withImage(projectDevmodeImage != null ? projectDevmodeImage : 
devmodeImage)
                 .withPorts(port)
                 .withResources(resources)
                 
.withImagePullPolicy(devmodeImagePullPolicy.orElse("IfNotPresent"))
-                .withEnv(new 
EnvVarBuilder().withName(ENV_VAR_JBANG_OPTIONS).withValue(jbangOptions).build())
+                .withEnv(environmentVariables)
                 .withVolumeMounts(volumeMounts)
                 .build();
 
@@ -486,6 +502,20 @@ public class KubernetesService {
         }
     }
 
+    public void createConfigMap(String name, Map<String, String> data, 
Map<String, String> labels) {
+        try (KubernetesClient client = kubernetesClient()) {
+            ConfigMap configMap = new ConfigMapBuilder()
+                    .withNewMetadata()
+                    .withName(name)
+                    .withNamespace(getNamespace())
+                    .withLabels(labels)
+                    .endMetadata()
+                    .withData(data)
+                    .build();
+            client.resource(configMap).serverSideApply();
+        }
+    }
+
     public Secret getSecret(String name) {
         try (KubernetesClient client = kubernetesClient()) {
             return 
client.secrets().inNamespace(getNamespace()).withName(name).get();
@@ -521,16 +551,16 @@ public class KubernetesService {
         return null;
     }
 
-    public boolean isOpenshift() {
-        return isOpenShift.isPresent() && isOpenShift.get();
-    }
-
-    public String getCluster() {
+    public ConfigMap getConfigMap(String name) {
         try (KubernetesClient client = kubernetesClient()) {
-            return client.getMasterUrl().getHost();
+            return 
client.configMaps().inNamespace(getNamespace()).withName(name).get();
         }
     }
 
+    public boolean isOpenshift() {
+        return isOpenShift.isPresent() && isOpenShift.get();
+    }
+
     public String getNamespace() {
         if (namespace == null) {
             try (KubernetesClient client = kubernetesClient()) {
@@ -545,4 +575,113 @@ public class KubernetesService {
             client.resource(secret).update();
         }
     }
+
+    public void updateConfigMap(ConfigMap configMap) {
+        try (KubernetesClient client = kubernetesClient()) {
+            client.resource(configMap).update();
+        }
+    }
+
+    public String getSecretValue(String secretName, String secretKey) {
+        return getSecret(secretName).getData().get(secretKey);
+    }
+
+    public void setSecretValue(String secretName, String secretKey, String 
value) {
+        Secret secret = getSecret(secretName);
+        if (secret != null) {
+            secret.getData().put(secretKey, value);
+            updateSecret(secret);
+        }
+    }
+
+    public void createSecret(String secretName) {
+        Secret secret = getSecret(secretName);
+        if (secret == null) {
+            createSecret(secretName, Map.of(), Map.of());
+        }
+    }
+
+    public void deleteSecretValue(String secretName, String secretKey) {
+        Secret secret = getSecret(secretName);
+        if (secret != null) {
+            secret.getData().remove(secretKey);
+            updateSecret(secret);
+        }
+    }
+
+    public List<KubernetesSecret> getSecrets() {
+        List<KubernetesSecret> result = new ArrayList<>();
+        try (KubernetesClient client = kubernetesClient()) {
+            
client.secrets().inNamespace(getNamespace()).list().getItems().forEach(secret 
-> {
+                Map<String, String> data = new HashMap<>(secret.getData());
+                data.replaceAll((s, s2) -> "");
+                result.add(new 
KubernetesSecret(secret.getMetadata().getName(), data));
+            });
+        } catch (Exception e) {
+            LOGGER.error(e);
+        }
+        return result;
+    }
+
+    public void deleteSecret(String secretName) {
+        Secret secret = getSecret(secretName);
+        if (secret != null) {
+            try (KubernetesClient client = kubernetesClient()) {
+                
client.secrets().inNamespace(getNamespace()).withName(secretName).delete();
+            }
+        }
+    }
+
+    public List<KubernetesConfigMap> getConfigMaps() {
+        List<KubernetesConfigMap> result = new ArrayList<>();
+        try (KubernetesClient client = kubernetesClient()) {
+            client.configMaps().inNamespace(getNamespace()).list().getItems()
+                    .forEach(secret -> result.add(new 
KubernetesConfigMap(secret.getMetadata().getName(), new 
HashMap<>(secret.getData()))));
+        } catch (Exception e) {
+            LOGGER.error(e);
+        }
+        return result;
+    }
+
+    public void deleteConfigMap(String configMapName) {
+        ConfigMap configMap = getConfigMap(configMapName);
+        if (configMap != null) {
+            try (KubernetesClient client = kubernetesClient()) {
+                
client.configMaps().inNamespace(getNamespace()).withName(configMapName).delete();
+            }
+        }
+    }
+
+    public void setConfigMapValue(String configMapName, String configMapKey, 
String value) {
+        ConfigMap configMap = getConfigMap(configMapName);
+        if (configMap != null) {
+            configMap.getData().put(configMapKey, value);
+            updateConfigMap(configMap);
+        }
+    }
+
+    public void createConfigMap(String configMapName) {
+        ConfigMap configMap = getConfigMap(configMapName);
+        if (configMap == null) {
+            createConfigMap(configMapName, Map.of(), Map.of());
+        }
+    }
+
+    public void deleteConfigMapValue(String configMapName, String 
configMapKey) {
+        ConfigMap configMap = getConfigMap(configMapName);
+        if (configMap != null) {
+            configMap.getData().remove(configMapKey);
+            updateConfigMap(configMap);
+        }
+    }
+
+    public String getCluster() {
+        try (KubernetesClient client = kubernetesClient()) {
+            return client.getMasterUrl().getHost();
+        }
+    }
+
+    public String getEnvironment() {
+        return environment;
+    }
 }
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/KubernetesStatusService.java
 
b/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/KubernetesStatusService.java
index 35716a87..40cf3de9 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/KubernetesStatusService.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/KubernetesStatusService.java
@@ -62,7 +62,7 @@ public class KubernetesStatusService implements HealthCheck {
     }
 
     @ConfigProperty(name = "karavan.environment", defaultValue = 
KaravanConstants.DEV)
-    public String environment;
+    private String environment;
 
     @ConfigProperty(name = "karavan.openshift")
     Optional<Boolean> isOpenShift;
@@ -169,4 +169,8 @@ public class KubernetesStatusService implements HealthCheck 
{
                 .addToLimits("memory", new 
Quantity(containerResources.get("limits.memory")))
                 .build();
     }
+
+    public String getEnvironment() {
+        return environment;
+    }
 }
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/listener/KubernetesCommandListener.java
 
b/karavan-app/src/main/java/org/apache/camel/karavan/listener/KubernetesCommandListener.java
new file mode 100644
index 00000000..c47f91c6
--- /dev/null
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/listener/KubernetesCommandListener.java
@@ -0,0 +1,40 @@
+/*
+ * 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.listener;
+
+import io.quarkus.vertx.ConsumeEvent;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import org.apache.camel.karavan.kubernetes.KubernetesStatusService;
+import org.apache.camel.karavan.service.ConfigService;
+
+import static org.apache.camel.karavan.KaravanEvents.CMD_RESTART_INFORMERS;
+
+@ApplicationScoped
+public class KubernetesCommandListener {
+
+    @Inject
+    KubernetesStatusService kubernetesStatusService;
+
+    @ConsumeEvent(value = CMD_RESTART_INFORMERS, blocking = true)
+    public void restartInformers(String dummy) {
+        if (ConfigService.inKubernetes()) {
+            kubernetesStatusService.startInformers();
+        }
+    }
+}
\ No newline at end of file
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/model/KubernetesConfigMap.java
 
b/karavan-app/src/main/java/org/apache/camel/karavan/model/KubernetesConfigMap.java
new file mode 100644
index 00000000..9929ddbc
--- /dev/null
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/model/KubernetesConfigMap.java
@@ -0,0 +1,33 @@
+package org.apache.camel.karavan.model;
+
+import java.util.Map;
+
+public class KubernetesConfigMap {
+
+    private String name;
+    private Map<String, String> data;
+
+    public KubernetesConfigMap() {
+    }
+
+    public KubernetesConfigMap(String name, Map<String, String> data) {
+        this.name = name;
+        this.data = data;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Map<String, String> getData() {
+        return data;
+    }
+
+    public void setData(Map<String, String> data) {
+        this.data = data;
+    }
+}
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/model/KubernetesSecret.java
 
b/karavan-app/src/main/java/org/apache/camel/karavan/model/KubernetesSecret.java
new file mode 100644
index 00000000..9159d1b3
--- /dev/null
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/model/KubernetesSecret.java
@@ -0,0 +1,33 @@
+package org.apache.camel.karavan.model;
+
+import java.util.Map;
+
+public class KubernetesSecret {
+
+    private String name;
+    private Map<String, String> data;
+
+    public KubernetesSecret() {
+    }
+
+    public KubernetesSecret(String name, Map<String, String> data) {
+        this.name = name;
+        this.data = data;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Map<String, String> getData() {
+        return data;
+    }
+
+    public void setData(Map<String, String> data) {
+        this.data = data;
+    }
+}

Reply via email to