From dc633ead9d53c132705e6fcd820779b6ebe18e5e Mon Sep 17 00:00:00 2001 From: Andreas Dinauer Date: Sat, 7 Jun 2025 11:22:52 +0200 Subject: [PATCH] :alembic: Installing kubectl inside container --- Dockerfile | 32 ++++++++++++++----- src/main/java/dev/dinauer/NodeResource.java | 18 +++++++++-- .../dev/dinauer/utils/ClientProvider.java | 15 +++++---- .../dev/dinauer/utils/StartupService.java | 2 ++ 4 files changed, 50 insertions(+), 17 deletions(-) diff --git a/Dockerfile b/Dockerfile index 638123a..e64b609 100644 --- a/Dockerfile +++ b/Dockerfile @@ -78,20 +78,36 @@ # accessed directly. (example: "foo.example.com,bar.example.com") # ### -FROM registry.access.redhat.com/ubi9/openjdk-21:1.21 +FROM eclipse-temurin:21-jdk ENV LANGUAGE='en_US:en' +WORKDIR /root + +RUN apt-get update && \ + apt-get install -y apt-transport-https ca-certificates curl gnupg && \ + curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg && \ + chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg && \ + echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /' | tee /etc/apt/sources.list.d/kubernetes.list && \ + chmod 644 /etc/apt/sources.list.d/kubernetes.list && \ + apt-get update && \ + apt-get install -y kubectl + +RUN useradd -m quarkus + +WORKDIR /etc/build # We make four distinct layers so if there are application changes the library layers can be re-used -COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/ -COPY --chown=185 target/quarkus-app/*.jar /deployments/ -COPY --chown=185 target/quarkus-app/app/ /deployments/app/ -COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/ +COPY target/quarkus-app/lib/ /deployments/lib/ +COPY target/quarkus-app/*.jar /deployments/ +COPY target/quarkus-app/app/ /deployments/app/ +COPY target/quarkus-app/quarkus/ /deployments/quarkus/ EXPOSE 8080 -USER 185 -ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" + +USER quarkus + +ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0" ENV JAVA_APP_JAR="/deployments/quarkus-run.jar" -ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ] +CMD ["java","-jar","/deployments/quarkus-run.jar"] \ No newline at end of file diff --git a/src/main/java/dev/dinauer/NodeResource.java b/src/main/java/dev/dinauer/NodeResource.java index f7726ce..334c61c 100644 --- a/src/main/java/dev/dinauer/NodeResource.java +++ b/src/main/java/dev/dinauer/NodeResource.java @@ -12,6 +12,8 @@ import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.BufferedReader; import java.io.IOException; @@ -24,6 +26,8 @@ import java.util.List; @Authenticated public class NodeResource { + private static final Logger LOG = LoggerFactory.getLogger(NodeResource.class); + @Inject ClientProvider clientProvider; @@ -34,6 +38,7 @@ public class NodeResource List result = new ArrayList<>(); List stats = getTopNodes(); + for(String nodeName : stats) { String[] parts = nodeName.split("\\s+"); @@ -53,7 +58,9 @@ public class NodeResource private List getTopNodes() throws IOException, InterruptedException { - ProcessBuilder pb = new ProcessBuilder(List.of("kubectl", "top", "nodes", "--no-headers")); + List commands = List.of("kubectl", String.format("--kubeconfig=%s", clientProvider.pathToKubeconfig()), "top", "nodes", "--no-headers"); + LOG.info("Executing command: {}", String.join(" ", commands)); + ProcessBuilder pb = new ProcessBuilder(commands); Process p = pb.start(); List text = new ArrayList<>(); @@ -65,8 +72,13 @@ public class NodeResource text.add(line); } } - p.waitFor(); - return text; + int exitCode = p.waitFor(); + if(exitCode == 0) + { + LOG.info("Found {} nodes", text.size()); + return text; + } + throw new RuntimeException("Failed to retrieve top nodes."); } public record NodeStats(Node node, Integer absoluteCpuUsage, Integer relativeCpuUsage, Integer totalCpu, Integer absoluteMemory, Integer relativeMemory, Integer totalMemory) diff --git a/src/main/java/dev/dinauer/utils/ClientProvider.java b/src/main/java/dev/dinauer/utils/ClientProvider.java index ecee9fa..27fc724 100644 --- a/src/main/java/dev/dinauer/utils/ClientProvider.java +++ b/src/main/java/dev/dinauer/utils/ClientProvider.java @@ -1,29 +1,32 @@ package dev.dinauer.utils; import io.fabric8.kubernetes.client.Config; -import io.fabric8.kubernetes.client.DefaultKubernetesClient; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.KubernetesClientBuilder; -import io.fabric8.kubernetes.client.extension.ExtensionAdapter; -import io.fabric8.kubernetes.client.http.HttpClient; -import io.fabric8.kubernetes.client.vertx.VertxHttpClientBuilder; import io.fabric8.kubernetes.client.vertx.VertxHttpClientFactory; import io.vertx.mutiny.core.Vertx; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -import org.eclipse.microprofile.config.ConfigProvider; +import org.eclipse.microprofile.config.inject.ConfigProperty; import java.io.File; @ApplicationScoped public class ClientProvider { + @ConfigProperty(name = "dev.dinauer.kobooboo.kubeconfigs.dir") + String configFilePath; + @Inject Vertx vertx; public KubernetesClient getClient() { - String configFilePath = ConfigProvider.getConfig().getValue("dev.dinauer.kobooboo.kubeconfigs.dir", String.class); return new KubernetesClientBuilder().withConfig(Config.fromKubeconfig(new File(configFilePath))).withHttpClientFactory(new VertxHttpClientFactory(vertx.getDelegate())).build(); } + + public String pathToKubeconfig() + { + return configFilePath; + } } diff --git a/src/main/java/dev/dinauer/utils/StartupService.java b/src/main/java/dev/dinauer/utils/StartupService.java index b8e901a..2382447 100644 --- a/src/main/java/dev/dinauer/utils/StartupService.java +++ b/src/main/java/dev/dinauer/utils/StartupService.java @@ -3,6 +3,7 @@ package dev.dinauer.utils; import dev.dinauer.login.User; import dev.dinauer.login.UserRepo; import io.quarkus.elytron.security.common.BcryptUtil; +import io.quarkus.runtime.Startup; import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -10,6 +11,7 @@ import jakarta.inject.Inject; import java.io.IOException; import java.util.Set; +@Startup @ApplicationScoped public class StartupService {