✨ Add env, secrets and CRDs
This commit is contained in:
parent
282a12111c
commit
855e48f6b2
6
src/main/java/dev/dinauer/EnvVar.java
Normal file
6
src/main/java/dev/dinauer/EnvVar.java
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package dev.dinauer;
|
||||||
|
|
||||||
|
public record EnvVar(String key, String value)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
7
src/main/java/dev/dinauer/KubernetesLog.java
Normal file
7
src/main/java/dev/dinauer/KubernetesLog.java
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package dev.dinauer;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
public record KubernetesLog(LocalDateTime timestamp, String message)
|
||||||
|
{
|
||||||
|
}
|
||||||
@ -12,7 +12,12 @@ import jakarta.enterprise.context.ApplicationScoped;
|
|||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.ws.rs.*;
|
import jakarta.ws.rs.*;
|
||||||
import jakarta.ws.rs.core.MediaType;
|
import jakarta.ws.rs.core.MediaType;
|
||||||
|
import org.jboss.resteasy.reactive.common.NotImplementedYet;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@ -28,16 +33,44 @@ public class LogResource
|
|||||||
@Inject
|
@Inject
|
||||||
PodService podService;
|
PodService podService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ProcessRunner processRunner;
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public List<String> getLogs(@PathParam("pod-id") String podId)
|
public List<KubernetesLog> getLogs(@PathParam("pod-id") String podId)
|
||||||
{
|
{
|
||||||
Optional<Pod> podOptional = podService.findPodById(podId);
|
Optional<Pod> podOptional = podService.findPodById(podId);
|
||||||
if(podOptional.isPresent())
|
if(podOptional.isPresent())
|
||||||
{
|
{
|
||||||
Pod pod = podOptional.get();
|
Pod pod = podOptional.get();
|
||||||
return List.of(clientProvider.getClient().pods().inNamespace(pod.getMetadata().getNamespace()).withName(pod.getMetadata().getName()).getLog().split("\\r?\\n"));
|
return getLogs(pod, null);
|
||||||
}
|
}
|
||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<KubernetesLog> getLogs(Pod pod, LocalDateTime from)
|
||||||
|
{
|
||||||
|
String command = String.format("kubectl logs %s -n %s --timestamps", pod.getMetadata().getName(), pod.getMetadata().getNamespace());
|
||||||
|
List<KubernetesLog> result = new ArrayList<>();
|
||||||
|
List<String> logs = processRunner.runToLines(command);
|
||||||
|
for (String log : logs)
|
||||||
|
{
|
||||||
|
int indexFirstSpace = log.indexOf(" ");
|
||||||
|
if (indexFirstSpace != -1)
|
||||||
|
{
|
||||||
|
String timestampRaw = log.substring(0, indexFirstSpace);
|
||||||
|
String message = log.substring(indexFirstSpace).trim();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
result.add(new KubernetesLog(LocalDateTime.parse(timestampRaw, DateTimeFormatter.ISO_DATE_TIME), message));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,25 +14,42 @@ import jakarta.ws.rs.core.MediaType;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Path("/pods")
|
@Path("/pods")
|
||||||
@Startup
|
@Startup
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
@Blocking
|
|
||||||
@Authenticated
|
|
||||||
public class PodResource
|
public class PodResource
|
||||||
{
|
{
|
||||||
@Inject
|
@Inject
|
||||||
PodService podService;
|
PodService podService;
|
||||||
|
|
||||||
@DELETE
|
@Inject
|
||||||
@Produces
|
ProcessRunner processRunner;
|
||||||
@Consumes
|
|
||||||
@Path("/{namespace}/{name}")
|
|
||||||
@RolesAllowed({"admin", "maintainer"})
|
|
||||||
public void getEnv()
|
|
||||||
{
|
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes
|
||||||
|
@Blocking
|
||||||
|
@Path("/{namespace}/{name}/env")
|
||||||
|
public List<EnvVar> getEnv(@PathParam("namespace") String namespace, @PathParam("name") String name)
|
||||||
|
{
|
||||||
|
return getVars(podService.findByNameAndNamespace(name, namespace));
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<EnvVar> getVars(Pod pod)
|
||||||
|
{
|
||||||
|
List<EnvVar> result = new ArrayList<>();
|
||||||
|
List<String> lines = processRunner.runToLines(String.format("kubectl exec -it %s -n %s -- env", pod.getMetadata().getName(), pod.getMetadata().getNamespace()));
|
||||||
|
for (String line : lines)
|
||||||
|
{
|
||||||
|
int indexOfFirstEquals = line.indexOf("=");
|
||||||
|
if (indexOfFirstEquals != -1)
|
||||||
|
{
|
||||||
|
result.add(new EnvVar(line.substring(0, indexOfFirstEquals), line.substring(indexOfFirstEquals + 1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,6 @@ import java.io.InputStreamReader;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
public class ProcessRunner
|
public class ProcessRunner
|
||||||
@ -18,14 +17,30 @@ public class ProcessRunner
|
|||||||
@Inject
|
@Inject
|
||||||
Logger LOG;
|
Logger LOG;
|
||||||
|
|
||||||
public String run(String command) throws IOException, InterruptedException
|
public String runToText(String command)
|
||||||
|
{
|
||||||
|
return String.join("\n", runToLines(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> runToLines(String command)
|
||||||
{
|
{
|
||||||
LOG.infof("Running command: %s", command);
|
LOG.infof("Running command: %s", command);
|
||||||
ProcessBuilder pb = new ProcessBuilder(command.split("\\s+"));
|
ProcessBuilder pb = new ProcessBuilder(command.split("\\s+"));
|
||||||
pb.redirectErrorStream(true);
|
pb.redirectErrorStream(true);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
Process p = pb.start();
|
Process p = pb.start();
|
||||||
|
return runAndCollectLogs(p);
|
||||||
|
}
|
||||||
|
catch (IOException | InterruptedException e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException("Failed to run command " + command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> runAndCollectLogs(Process p) throws InterruptedException
|
||||||
|
{
|
||||||
List<String> text = new ArrayList<>();
|
List<String> text = new ArrayList<>();
|
||||||
try(BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())))
|
try(BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())))
|
||||||
{
|
{
|
||||||
@ -35,20 +50,19 @@ public class ProcessRunner
|
|||||||
text.add(line);
|
text.add(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
boolean endedInTime = p.waitFor(10, TimeUnit.SECONDS);
|
boolean endedInTime = p.waitFor(10, TimeUnit.SECONDS);
|
||||||
p.destroy();
|
|
||||||
if (endedInTime)
|
if (endedInTime)
|
||||||
{
|
{
|
||||||
int exitCode = p.exitValue();
|
int exitCode = p.exitValue();
|
||||||
if(exitCode == 0)
|
if(exitCode == 0)
|
||||||
{
|
{
|
||||||
return String.join("\n", text);
|
return text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
throw new InterruptedException();
|
||||||
{
|
|
||||||
LOG.error("Process did not end in time.");
|
|
||||||
}
|
|
||||||
throw new RuntimeException("Error executing command: " + command);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import jakarta.inject.Inject;
|
|||||||
import jakarta.ws.rs.*;
|
import jakarta.ws.rs.*;
|
||||||
import jakarta.ws.rs.core.MediaType;
|
import jakarta.ws.rs.core.MediaType;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.reactive.common.NotImplementedYet;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@ -38,6 +37,9 @@ public class ResourceResource
|
|||||||
@Inject
|
@Inject
|
||||||
NodeService nodeService;
|
NodeService nodeService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
SecretService secretService;
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
public List<?> get(@PathParam("resource") String resourceType)
|
public List<?> get(@PathParam("resource") String resourceType)
|
||||||
{
|
{
|
||||||
@ -122,6 +124,10 @@ public class ResourceResource
|
|||||||
{
|
{
|
||||||
return nodeService;
|
return nodeService;
|
||||||
}
|
}
|
||||||
|
case ResourceType.SECRET ->
|
||||||
|
{
|
||||||
|
return secretService;
|
||||||
|
}
|
||||||
default ->
|
default ->
|
||||||
{
|
{
|
||||||
LOG.errorf("Invalid resource type %s.", resourceType);
|
LOG.errorf("Invalid resource type %s.", resourceType);
|
||||||
|
|||||||
@ -9,4 +9,5 @@ public class ResourceType
|
|||||||
public static final String POD = "pods";
|
public static final String POD = "pods";
|
||||||
public static final String CUSTOM_RESOURCE_DEFINITION = "custom-resource-definitions";
|
public static final String CUSTOM_RESOURCE_DEFINITION = "custom-resource-definitions";
|
||||||
public static final String NODE = "nodes";
|
public static final String NODE = "nodes";
|
||||||
|
public static final String SECRET = "secrets";
|
||||||
}
|
}
|
||||||
|
|||||||
73
src/main/java/dev/dinauer/monitoring/TopNodesService.java
Normal file
73
src/main/java/dev/dinauer/monitoring/TopNodesService.java
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package dev.dinauer.monitoring;
|
||||||
|
|
||||||
|
import dev.dinauer.ProcessRunner;
|
||||||
|
import dev.dinauer.monitoring.nodes.NodeStats;
|
||||||
|
import dev.dinauer.utils.ClientProvider;
|
||||||
|
import io.fabric8.kubernetes.api.model.Node;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class TopNodesService
|
||||||
|
{
|
||||||
|
@Inject
|
||||||
|
ClientProvider clientProvider;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ProcessRunner processRunner;
|
||||||
|
|
||||||
|
public List<NodeStats> findAll()
|
||||||
|
{
|
||||||
|
List<NodeStats> result = new ArrayList<>();
|
||||||
|
|
||||||
|
List<String> stats = runTopNodesCommand();
|
||||||
|
|
||||||
|
|
||||||
|
for(String nodeName : stats)
|
||||||
|
{
|
||||||
|
String[] parts = nodeName.split("\\s+");
|
||||||
|
if(parts.length == 5)
|
||||||
|
{
|
||||||
|
String name = parts[0];
|
||||||
|
Node node = clientProvider.getClient().nodes().withName(name).get();
|
||||||
|
Integer absoluteCpu = extractInteger(parts[1]);
|
||||||
|
Integer relativeCpu = extractInteger(parts[2]);
|
||||||
|
Integer absoluteMemory = extractMemory(parts[3]);
|
||||||
|
Integer relativeMemory = extractInteger(parts[4]);
|
||||||
|
result.add(new NodeStats(node, absoluteCpu, relativeCpu, Integer.parseInt(node.getStatus().getAllocatable().get("cpu").getAmount()) * 1000, absoluteMemory, relativeMemory, extractMemory(node.getStatus().getAllocatable().get("memory").getAmount())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> runTopNodesCommand()
|
||||||
|
{
|
||||||
|
String command = String.format("kubectl --kubeconfig=%s top nodes --no-headers", clientProvider.pathToKubeconfig());
|
||||||
|
return processRunner.runToLines(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer extractInteger(String input)
|
||||||
|
{
|
||||||
|
return Integer.valueOf(input.replace("m", "").replace("%", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer extractMemory(String input)
|
||||||
|
{
|
||||||
|
if(input.contains("Ki"))
|
||||||
|
{
|
||||||
|
return Integer.parseInt(input.replace("Ki", ""));
|
||||||
|
}
|
||||||
|
if(input.contains("Mi"))
|
||||||
|
{
|
||||||
|
return Integer.parseInt(input.replace("Mi", "")) * 1024;
|
||||||
|
}
|
||||||
|
if(input.contains("Gi"))
|
||||||
|
{
|
||||||
|
return Integer.parseInt(input.replace("Gi", "")) * 1024 * 1024;
|
||||||
|
}
|
||||||
|
return Integer.parseInt(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,9 @@
|
|||||||
package dev.dinauer.monitoring.nodes;
|
package dev.dinauer.monitoring.nodes;
|
||||||
|
|
||||||
import dev.dinauer.ProcessRunner;
|
import dev.dinauer.ProcessRunner;
|
||||||
|
import dev.dinauer.monitoring.TopNodesService;
|
||||||
import dev.dinauer.monitoring.indexing.IndexingService;
|
import dev.dinauer.monitoring.indexing.IndexingService;
|
||||||
|
import dev.dinauer.service.NodeService;
|
||||||
import dev.dinauer.utils.ClientProvider;
|
import dev.dinauer.utils.ClientProvider;
|
||||||
import io.smallrye.common.annotation.Blocking;
|
import io.smallrye.common.annotation.Blocking;
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
@ -15,65 +17,22 @@ import java.util.Map;
|
|||||||
public class NodeMonitoringService
|
public class NodeMonitoringService
|
||||||
{
|
{
|
||||||
@Inject
|
@Inject
|
||||||
ClientProvider clientProvider;
|
TopNodesService topNodesService;
|
||||||
|
|
||||||
@Inject
|
|
||||||
ProcessRunner processRunner;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
IndexingService indexingService;
|
IndexingService indexingService;
|
||||||
|
|
||||||
public void run() throws IOException, InterruptedException
|
public void run() throws IOException, InterruptedException
|
||||||
{
|
{
|
||||||
List<NodeStats> result = new ArrayList<>();
|
List<NodeStats> nodes = topNodesService.findAll();
|
||||||
|
for (NodeStats node : nodes)
|
||||||
String[] stats = getTopNodes().split("\n");
|
|
||||||
|
|
||||||
for(String nodeName : stats)
|
|
||||||
{
|
{
|
||||||
String[] parts = nodeName.split("\\s+");
|
|
||||||
if(parts.length == 5)
|
|
||||||
{
|
|
||||||
String name = parts[0];
|
|
||||||
String node = clientProvider.getClient().nodes().withName(name).get().getMetadata().getUid();
|
|
||||||
int absoluteCpu = extractInteger(parts[1]);
|
|
||||||
int relativeCpu = extractInteger(parts[2]);
|
|
||||||
int absoluteMemory = extractMemory(parts[3]);
|
|
||||||
int relativeMemory = extractInteger(parts[4]);
|
|
||||||
Map<String, Long> metrics = Map.ofEntries(
|
Map<String, Long> metrics = Map.ofEntries(
|
||||||
Map.entry("RELATIVE_CPU", (long) relativeCpu),
|
Map.entry("RELATIVE_CPU", (long) node.relativeCpuUsage()),
|
||||||
Map.entry("RELATIVE_MEMORY", (long) relativeMemory),
|
Map.entry("RELATIVE_MEMORY", (long) node.relativeMemory()),
|
||||||
Map.entry("ABSOLUTE_MEMORY", (long) absoluteMemory));
|
Map.entry("ABSOLUTE_MEMORY", (long) node.absoluteMemory()),
|
||||||
|
Map.entry("ABSOLUTE_CPU", (long) node.absoluteCpuUsage()));
|
||||||
indexingService.index(String.format("NODE-%s", node), "NODE_METRICS", metrics);
|
indexingService.index(String.format("NODE-%s", node), "NODE_METRICS", metrics);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getTopNodes() throws IOException, InterruptedException
|
|
||||||
{
|
|
||||||
String command = String.format("kubectl --kubeconfig=%s top nodes --no-headers", clientProvider.pathToKubeconfig());
|
|
||||||
return processRunner.run(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Integer extractInteger(String input)
|
|
||||||
{
|
|
||||||
return Integer.valueOf(input.replace("m", "").replace("%", ""));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Integer extractMemory(String input)
|
|
||||||
{
|
|
||||||
if(input.contains("Ki"))
|
|
||||||
{
|
|
||||||
return Integer.parseInt(input.replace("Ki", ""));
|
|
||||||
}
|
|
||||||
if(input.contains("Mi"))
|
|
||||||
{
|
|
||||||
return Integer.parseInt(input.replace("Mi", "")) * 1024;
|
|
||||||
}
|
|
||||||
if(input.contains("Gi"))
|
|
||||||
{
|
|
||||||
return Integer.parseInt(input.replace("Gi", "")) * 1024 * 1024;
|
|
||||||
}
|
|
||||||
return Integer.parseInt(input);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -31,7 +31,7 @@ public class CustomResourceDefinitionService implements ResourceService<CustomRe
|
|||||||
@Override
|
@Override
|
||||||
public List<CustomResourceDefinition> findByNamespace(String namespace)
|
public List<CustomResourceDefinition> findByNamespace(String namespace)
|
||||||
{
|
{
|
||||||
throw new UnsupportedOperationException();
|
return findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -1,122 +1,22 @@
|
|||||||
package dev.dinauer.service;
|
package dev.dinauer.service;
|
||||||
|
|
||||||
|
import dev.dinauer.monitoring.TopNodesService;
|
||||||
import dev.dinauer.monitoring.nodes.NodeStats;
|
import dev.dinauer.monitoring.nodes.NodeStats;
|
||||||
import dev.dinauer.utils.ClientProvider;
|
|
||||||
import io.fabric8.kubernetes.api.model.Node;
|
|
||||||
import io.smallrye.common.annotation.Blocking;
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.ws.rs.GET;
|
|
||||||
import jakarta.ws.rs.Produces;
|
|
||||||
import jakarta.ws.rs.core.MediaType;
|
|
||||||
import org.jboss.resteasy.reactive.common.NotImplementedYet;
|
import org.jboss.resteasy.reactive.common.NotImplementedYet;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
public class NodeService implements ResourceService<NodeStats>
|
public class NodeService implements ResourceService<NodeStats>
|
||||||
{
|
{
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(NodeService.class);
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ClientProvider clientProvider;
|
TopNodesService topNodesService;
|
||||||
|
|
||||||
@GET
|
|
||||||
@Blocking
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
public List<NodeStats> findAll()
|
public List<NodeStats> findAll()
|
||||||
{
|
{
|
||||||
List<NodeStats> result = new ArrayList<>();
|
return topNodesService.findAll();
|
||||||
|
|
||||||
List<String> stats = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
stats = getTopNodes();
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
catch (InterruptedException e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(String nodeName : stats)
|
|
||||||
{
|
|
||||||
String[] parts = nodeName.split("\\s+");
|
|
||||||
if(parts.length == 5)
|
|
||||||
{
|
|
||||||
String name = parts[0];
|
|
||||||
Node node = clientProvider.getClient().nodes().withName(name).get();
|
|
||||||
Integer absoluteCpu = extractInteger(parts[1]);
|
|
||||||
Integer relativeCpu = extractInteger(parts[2]);
|
|
||||||
Integer absoluteMemory = extractMemory(parts[3]);
|
|
||||||
Integer relativeMemory = extractInteger(parts[4]);
|
|
||||||
result.add(new NodeStats(node, absoluteCpu, relativeCpu, Integer.parseInt(node.getStatus().getAllocatable().get("cpu").getAmount()) * 1000, absoluteMemory, relativeMemory, extractMemory(node.getStatus().getAllocatable().get("memory").getAmount())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> getTopNodes() throws IOException, InterruptedException
|
|
||||||
{
|
|
||||||
List<String> 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<String> text = new ArrayList<>();
|
|
||||||
try(BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())))
|
|
||||||
{
|
|
||||||
String line;
|
|
||||||
while((line = br.readLine()) != null)
|
|
||||||
{
|
|
||||||
text.add(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
boolean hasEndedInTime = p.waitFor(10, TimeUnit.SECONDS);
|
|
||||||
p.destroy();
|
|
||||||
if (hasEndedInTime)
|
|
||||||
{
|
|
||||||
int exitCode = p.waitFor();
|
|
||||||
if(exitCode == 0)
|
|
||||||
{
|
|
||||||
LOG.info("Found {} nodes", text.size());
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new RuntimeException("Failed to retrieve top nodes.");
|
|
||||||
}
|
|
||||||
|
|
||||||
private Integer extractInteger(String input)
|
|
||||||
{
|
|
||||||
return Integer.valueOf(input.replace("m", "").replace("%", ""));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Integer extractMemory(String input)
|
|
||||||
{
|
|
||||||
if(input.contains("Ki"))
|
|
||||||
{
|
|
||||||
return Integer.parseInt(input.replace("Ki", ""));
|
|
||||||
}
|
|
||||||
if(input.contains("Mi"))
|
|
||||||
{
|
|
||||||
return Integer.parseInt(input.replace("Mi", "")) * 1024;
|
|
||||||
}
|
|
||||||
if(input.contains("Gi"))
|
|
||||||
{
|
|
||||||
return Integer.parseInt(input.replace("Gi", "")) * 1024 * 1024;
|
|
||||||
}
|
|
||||||
return Integer.parseInt(input);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -134,7 +34,7 @@ public class NodeService implements ResourceService<NodeStats>
|
|||||||
@Override
|
@Override
|
||||||
public List<NodeStats> findByNamespace(String namespace)
|
public List<NodeStats> findByNamespace(String namespace)
|
||||||
{
|
{
|
||||||
throw new NotImplementedYet();
|
return findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
47
src/main/java/dev/dinauer/service/SecretService.java
Normal file
47
src/main/java/dev/dinauer/service/SecretService.java
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package dev.dinauer.service;
|
||||||
|
|
||||||
|
import dev.dinauer.utils.ClientProvider;
|
||||||
|
import io.fabric8.kubernetes.api.model.Secret;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import org.jboss.resteasy.reactive.common.NotImplementedYet;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class SecretService implements ResourceService<Secret>
|
||||||
|
{
|
||||||
|
@Inject
|
||||||
|
ClientProvider clientProvider;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete(String name, String namespace)
|
||||||
|
{
|
||||||
|
throw new NotImplementedYet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Secret findByNameAndNamespace(String name, String namespace)
|
||||||
|
{
|
||||||
|
throw new NotImplementedYet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Secret> findByNamespace(String namespace)
|
||||||
|
{
|
||||||
|
return clientProvider.getClient().secrets().inNamespace(namespace).list().getItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Secret> findAll()
|
||||||
|
{
|
||||||
|
return clientProvider.getClient().secrets().inAnyNamespace().list().getItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Secret> findOptionalByNameAndNamespace(String name, String namespace)
|
||||||
|
{
|
||||||
|
throw new NotImplementedYet();
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user