From f52cba81d50aa720df17b50c68eea9594392b8a2 Mon Sep 17 00:00:00 2001 From: "andreas.dinauer" Date: Sat, 8 Nov 2025 13:57:01 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20namespace,=20pvc,=20pv=20and?= =?UTF-8?q?=20stateful=20sets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 4 + .../java/dev/dinauer/ResourceResource.java | 12 +- src/main/java/dev/dinauer/ResourceType.java | 52 ++++++-- .../inspect/websocket/ResourceWebsocket.java | 38 ++---- .../inspect/websocket/ServiceFactory.java | 111 ++++++++++++++++++ .../java/dev/dinauer/login/LoginResource.java | 2 - .../dev/dinauer/service/ConfigMapService.java | 17 +++ .../CustomResourceDefinitionService.java | 8 ++ .../dinauer/service/DeploymentService.java | 19 +++ .../dev/dinauer/service/IngressService.java | 20 ++++ .../dev/dinauer/service/NamespaceService.java | 55 +++++++++ .../java/dev/dinauer/service/NodeService.java | 9 ++ .../java/dev/dinauer/service/PodService.java | 18 +++ .../java/dev/dinauer/service/PvService.java | 55 +++++++++ .../java/dev/dinauer/service/PvcService.java | 63 ++++++++++ .../dev/dinauer/service/ResourceService.java | 4 + .../dev/dinauer/service/SecretService.java | 17 +++ .../dev/dinauer/service/ServiceService.java | 17 +++ .../dinauer/service/StatefulSetService.java | 30 ++++- src/main/resources/application.properties | 5 +- src/main/resources/banner.txt | 5 + src/main/resources/import.sql | 4 +- 22 files changed, 514 insertions(+), 51 deletions(-) create mode 100644 src/main/java/dev/dinauer/inspect/websocket/ServiceFactory.java create mode 100644 src/main/java/dev/dinauer/service/NamespaceService.java create mode 100644 src/main/java/dev/dinauer/service/PvService.java create mode 100644 src/main/java/dev/dinauer/service/PvcService.java create mode 100644 src/main/resources/banner.txt diff --git a/pom.xml b/pom.xml index 43911ef..b8fe5cc 100644 --- a/pom.xml +++ b/pom.xml @@ -73,6 +73,10 @@ io.quarkus quarkus-websockets + + io.quarkus + quarkus-mutiny + diff --git a/src/main/java/dev/dinauer/ResourceResource.java b/src/main/java/dev/dinauer/ResourceResource.java index 8e229a0..178b419 100644 --- a/src/main/java/dev/dinauer/ResourceResource.java +++ b/src/main/java/dev/dinauer/ResourceResource.java @@ -45,21 +45,21 @@ public class ResourceResource ConfigMapService configMapService; @GET - public List get(@PathParam("resource") String resourceType) + public List get(@PathParam("resource") ResourceType resourceType) { return getService(resourceType).findAll(); } @GET @Path("/{namespace}") - public List getByNamespace(@PathParam("resource") String resourceType, @PathParam("namespace") String namespace) + public List getByNamespace(@PathParam("resource") ResourceType resourceType, @PathParam("namespace") String namespace) { return getService(resourceType).findByNamespace(namespace); } @GET @Path("/{namespace}/{name}") - public Object getByNamespaceAndName(@PathParam("resource") String resourceType, @PathParam("namespace") String namespace, @PathParam("name") String name) + public Object getByNamespaceAndName(@PathParam("resource") ResourceType resourceType, @PathParam("namespace") String namespace, @PathParam("name") String name) { Optional resourceOptional = getService(resourceType).findOptionalByNameAndNamespace(name, namespace); if (resourceOptional.isPresent()) @@ -71,7 +71,7 @@ public class ResourceResource @DELETE @Path("/{namespace}/{name}") - public void deleteByNamespaceAndName(@PathParam("resource") String resourceType, @PathParam("namespace") String namespace, @PathParam("name") String name) + public void deleteByNamespaceAndName(@PathParam("resource") ResourceType resourceType, @PathParam("namespace") String namespace, @PathParam("name") String name) { getService(resourceType).delete(name, namespace); } @@ -81,7 +81,7 @@ public class ResourceResource @Consumes(MediaType.TEXT_PLAIN) @Produces @RolesAllowed("admin") - public void rescaleDeployment(@PathParam("resource") String resourceType, @PathParam("namespace") String namespace, @PathParam("name") String name, Integer replicaCount) + public void rescaleDeployment(@PathParam("resource") ResourceType resourceType, @PathParam("namespace") String namespace, @PathParam("name") String name, Integer replicaCount) { if (ResourceType.DEPLOYMENT.equals(resourceType)) { @@ -96,7 +96,7 @@ public class ResourceResource } } - private ResourceService getService(String resourceType) + private ResourceService getService(ResourceType resourceType) { switch (resourceType) { diff --git a/src/main/java/dev/dinauer/ResourceType.java b/src/main/java/dev/dinauer/ResourceType.java index 0896e70..10953d6 100644 --- a/src/main/java/dev/dinauer/ResourceType.java +++ b/src/main/java/dev/dinauer/ResourceType.java @@ -1,14 +1,46 @@ package dev.dinauer; -public class ResourceType +public enum ResourceType { - public static final String STATEFUL_SET = "stateful-sets"; - public static final String DEPLOYMENT = "deployments"; - public static final String SERVICE = "services"; - public static final String INGRESS = "ingresses"; - public static final String POD = "pods"; - public static final String CUSTOM_RESOURCE_DEFINITION = "custom-resource-definitions"; - public static final String NODE = "nodes"; - public static final String SECRET = "secrets"; - public static final String CONFIG_MAP = "config-maps"; + // Cluster Resources + NODE("nodes"), + NAMESPACE("namespaces"), + CUSTOM_RESOURCE_DEFINITION("custom-resource-definitions"), + + // Workloads + STATEFUL_SET("stateful-sets"), + DEPLOYMENT("deployments"), + POD("pods"), + + // Networking + SERVICE("services"), + INGRESS("ingresses"), + + // Config + SECRET("secrets"), + CONFIG_MAP("config-maps"), + + // Storage + PVC("pvcs"), + PV("pvs"); + + private final String value; + + ResourceType(String value) { + this.value = value; + } + + public static ResourceType fromString(String text) { + for (ResourceType type : ResourceType.values()) { + if (type.value.equalsIgnoreCase(text)) { + return type; + } + } + throw new IllegalArgumentException("Unknown resource type: " + text); + } + + @Override + public String toString() { + return value; + } } \ No newline at end of file diff --git a/src/main/java/dev/dinauer/inspect/websocket/ResourceWebsocket.java b/src/main/java/dev/dinauer/inspect/websocket/ResourceWebsocket.java index c8d0e06..f880fdd 100644 --- a/src/main/java/dev/dinauer/inspect/websocket/ResourceWebsocket.java +++ b/src/main/java/dev/dinauer/inspect/websocket/ResourceWebsocket.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import dev.dinauer.ResourceEvent; import dev.dinauer.ResourceType; +import dev.dinauer.service.ResourceService; import dev.dinauer.utils.ClientProvider; import io.fabric8.kubernetes.client.Watch; import io.fabric8.kubernetes.client.Watcher; @@ -50,44 +51,23 @@ public class ResourceWebsocket @Inject JWTParser parser; + @Inject + ServiceFactory serviceFactory; + private final Map sessions = new HashMap<>(); @OnOpen - public void onOpen(Session session, @PathParam("resource-type") String resourceType, @PathParam("namespace") String namespace) throws ParseException + public void onOpen(Session session, @PathParam("resource-type") String rawResourceType, @PathParam("namespace") String namespace) throws ParseException { + ResourceType resourceType = ResourceType.fromString(rawResourceType); JsonWebToken token = getToken(session.getQueryString()); if (isValid(token)) { executor.runAsync(() -> { - if (ResourceType.POD.equals(resourceType)) - { - String version = clientProvider.getClient().pods().inAnyNamespace().list().getMetadata().getResourceVersion(); - if (isGlobal(namespace)) - { - send(session, EventType.INIT, clientProvider.getClient().pods().inAnyNamespace().list().getItems()); - sessions.put(session, clientProvider.getClient().pods().inAnyNamespace().withResourceVersion(version).watch(getWatcher(session))); - } - else - { - send(session, EventType.INIT, clientProvider.getClient().pods().inNamespace(namespace).list().getItems()); - sessions.put(session, clientProvider.getClient().pods().inNamespace(namespace).withResourceVersion(version).watch(getWatcher(session))); - } - } - if (ResourceType.CONFIG_MAP.equals(resourceType)) - { - String version = clientProvider.getClient().configMaps().inAnyNamespace().list().getMetadata().getResourceVersion(); - if (isGlobal(namespace)) - { - send(session, EventType.INIT, clientProvider.getClient().configMaps().inAnyNamespace().list().getItems()); - sessions.put(session, clientProvider.getClient().configMaps().inAnyNamespace().withResourceVersion(version).watch(getWatcher(session))); - } - else - { - send(session, EventType.INIT, clientProvider.getClient().configMaps().inNamespace(namespace).list().getItems()); - sessions.put(session, clientProvider.getClient().configMaps().inNamespace(namespace).withResourceVersion(version).watch(getWatcher(session))); - } - } + ResourceService service = serviceFactory.getService(resourceType); + send(session, EventType.INIT, service.findByNamespace(namespace)); + sessions.put(session, service.watch(namespace, getWatcher(session))); }); } } diff --git a/src/main/java/dev/dinauer/inspect/websocket/ServiceFactory.java b/src/main/java/dev/dinauer/inspect/websocket/ServiceFactory.java new file mode 100644 index 0000000..f81c528 --- /dev/null +++ b/src/main/java/dev/dinauer/inspect/websocket/ServiceFactory.java @@ -0,0 +1,111 @@ +package dev.dinauer.inspect.websocket; + +import dev.dinauer.ResourceType; +import dev.dinauer.service.*; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.BadRequestException; +import org.jboss.logging.Logger; + +@ApplicationScoped +public class ServiceFactory +{ + @Inject + Logger LOG; + + @Inject + StatefulSetService statefulSetService; + + @Inject + DeploymentService deploymentService; + + @Inject + PodService podService; + + @Inject + CustomResourceDefinitionService customResourceDefinitionService; + + @Inject + IngressService ingressService; + + @Inject + ServiceService serviceService; + + @Inject + NodeService nodeService; + + @Inject + SecretService secretService; + + @Inject + ConfigMapService configMapService; + + @Inject + PvcService pvcService; + + @Inject + PvService pvService; + + @Inject + NamespaceService namespaceService; + + public ResourceService getService(ResourceType resourceType) + { + switch (resourceType) + { + case ResourceType.STATEFUL_SET -> + { + return statefulSetService; + } + case ResourceType.DEPLOYMENT -> + { + return deploymentService; + } + case ResourceType.SERVICE -> + { + return serviceService; + } + case ResourceType.INGRESS -> + { + return ingressService; + } + case ResourceType.POD -> + { + return podService; + } + case ResourceType.CUSTOM_RESOURCE_DEFINITION -> + { + return customResourceDefinitionService; + } + case ResourceType.NODE -> + { + return nodeService; + } + case ResourceType.SECRET -> + { + return secretService; + } + case ResourceType.CONFIG_MAP -> + { + return configMapService; + } + case ResourceType.PVC -> + { + return pvcService; + } + case ResourceType.PV -> + { + return pvService; + } + case ResourceType.NAMESPACE -> + { + return namespaceService; + } + default -> + { + LOG.errorf("Invalid resource type %s.", resourceType); + throw new BadRequestException(); + } + } + } +} diff --git a/src/main/java/dev/dinauer/login/LoginResource.java b/src/main/java/dev/dinauer/login/LoginResource.java index 2c9b7d6..1ad9550 100644 --- a/src/main/java/dev/dinauer/login/LoginResource.java +++ b/src/main/java/dev/dinauer/login/LoginResource.java @@ -20,8 +20,6 @@ import java.util.Optional; @ApplicationScoped public class LoginResource { - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - @Inject Logger LOG; diff --git a/src/main/java/dev/dinauer/service/ConfigMapService.java b/src/main/java/dev/dinauer/service/ConfigMapService.java index 6fca852..c11e595 100644 --- a/src/main/java/dev/dinauer/service/ConfigMapService.java +++ b/src/main/java/dev/dinauer/service/ConfigMapService.java @@ -2,6 +2,8 @@ package dev.dinauer.service; import dev.dinauer.utils.ClientProvider; import io.fabric8.kubernetes.api.model.ConfigMap; +import io.fabric8.kubernetes.client.Watch; +import io.fabric8.kubernetes.client.Watcher; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import org.jboss.resteasy.reactive.common.NotImplementedYet; @@ -30,6 +32,10 @@ public class ConfigMapService implements ResourceService @Override public List findByNamespace(String namespace) { + if (namespace.equals("_all")) + { + return clientProvider.getClient().configMaps().inAnyNamespace().list().getItems(); + } return clientProvider.getClient().configMaps().inNamespace(namespace).list().getItems(); } @@ -44,4 +50,15 @@ public class ConfigMapService implements ResourceService { throw new NotImplementedYet(); } + + @Override + public Watch watch(String namespace, Watcher watcher) + { + String version = clientProvider.getClient().configMaps().inAnyNamespace().list().getMetadata().getResourceVersion(); + if (namespace.equals("_all")) + { + return clientProvider.getClient().configMaps().inAnyNamespace().withResourceVersion(version).watch(watcher); + } + return clientProvider.getClient().configMaps().inNamespace(namespace).withResourceVersion(version).watch(watcher); + } } diff --git a/src/main/java/dev/dinauer/service/CustomResourceDefinitionService.java b/src/main/java/dev/dinauer/service/CustomResourceDefinitionService.java index 4f7b019..2805391 100644 --- a/src/main/java/dev/dinauer/service/CustomResourceDefinitionService.java +++ b/src/main/java/dev/dinauer/service/CustomResourceDefinitionService.java @@ -2,6 +2,8 @@ package dev.dinauer.service; import dev.dinauer.utils.ClientProvider; import io.fabric8.kubernetes.api.model.apiextensions.v1.CustomResourceDefinition; +import io.fabric8.kubernetes.client.Watch; +import io.fabric8.kubernetes.client.Watcher; import io.fabric8.kubernetes.client.dsl.ApiextensionsAPIGroupDSL; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -48,4 +50,10 @@ public class CustomResourceDefinitionService implements ResourceService watcher) + { + throw new NotImplementedYet(); + } } diff --git a/src/main/java/dev/dinauer/service/DeploymentService.java b/src/main/java/dev/dinauer/service/DeploymentService.java index 75abadb..ac10695 100644 --- a/src/main/java/dev/dinauer/service/DeploymentService.java +++ b/src/main/java/dev/dinauer/service/DeploymentService.java @@ -2,6 +2,8 @@ package dev.dinauer.service; import dev.dinauer.utils.ClientProvider; import io.fabric8.kubernetes.api.model.apps.Deployment; +import io.fabric8.kubernetes.client.Watch; +import io.fabric8.kubernetes.client.Watcher; import io.fabric8.kubernetes.client.dsl.AppsAPIGroupDSL; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -33,6 +35,10 @@ public class DeploymentService implements ResourceService { try(AppsAPIGroupDSL dsl = clientProvider.getClient().apps()) { + if (namespace.equals("_all")) + { + return dsl.deployments().inAnyNamespace().list().getItems(); + } return dsl.deployments().inNamespace(namespace).list().getItems(); } } @@ -51,6 +57,19 @@ public class DeploymentService implements ResourceService return Optional.empty(); } + @Override + public Watch watch(String namespace, Watcher watcher) + { + try (AppsAPIGroupDSL dsl = clientProvider.getClient().apps()) { + String version = dsl.deployments().inAnyNamespace().list().getMetadata().getResourceVersion(); + if (namespace.equals("_all")) + { + return dsl.deployments().inAnyNamespace().withResourceVersion(version).watch(watcher); + } + return dsl.deployments().inNamespace(namespace).withResourceVersion(version).watch(watcher); + } + } + public void rescale(String namespace, String name, int replicaCount) { try(AppsAPIGroupDSL dsl = clientProvider.getClient().apps()) diff --git a/src/main/java/dev/dinauer/service/IngressService.java b/src/main/java/dev/dinauer/service/IngressService.java index 76c710a..f1bd2e5 100644 --- a/src/main/java/dev/dinauer/service/IngressService.java +++ b/src/main/java/dev/dinauer/service/IngressService.java @@ -4,6 +4,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import dev.dinauer.utils.ClientProvider; import io.fabric8.kubernetes.api.model.ObjectMeta; import io.fabric8.kubernetes.api.model.networking.v1.Ingress; +import io.fabric8.kubernetes.client.Watch; +import io.fabric8.kubernetes.client.Watcher; import io.fabric8.kubernetes.client.dsl.NetworkAPIGroupDSL; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -47,6 +49,10 @@ public class IngressService implements ResourceService { try(NetworkAPIGroupDSL dsl = clientProvider.getClient().network()) { + if (namespace.equals("_all")) + { + return dsl.v1().ingresses().inAnyNamespace().list().getItems(); + } return dsl.v1().ingresses().inNamespace(namespace).list().getItems(); } } @@ -64,4 +70,18 @@ public class IngressService implements ResourceService { return Optional.ofNullable(findByNameAndNamespace(name, namespace)); } + + @Override + public Watch watch(String namespace, Watcher watcher) + { + try(NetworkAPIGroupDSL dsl = clientProvider.getClient().network()) + { + String version = dsl.v1().ingresses().inAnyNamespace().list().getMetadata().getResourceVersion(); + if (namespace.equals("_all")) + { + return dsl.v1().ingresses().inAnyNamespace().withResourceVersion(version).watch(watcher); + } + return dsl.v1().ingresses().inNamespace(namespace).withResourceVersion(version).watch(watcher); + } + } } diff --git a/src/main/java/dev/dinauer/service/NamespaceService.java b/src/main/java/dev/dinauer/service/NamespaceService.java new file mode 100644 index 0000000..30501e9 --- /dev/null +++ b/src/main/java/dev/dinauer/service/NamespaceService.java @@ -0,0 +1,55 @@ +package dev.dinauer.service; + +import dev.dinauer.utils.ClientProvider; +import io.fabric8.kubernetes.api.model.Namespace; +import io.fabric8.kubernetes.client.Watch; +import io.fabric8.kubernetes.client.Watcher; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import java.util.List; +import java.util.Optional; + +@ApplicationScoped +public class NamespaceService implements ResourceService +{ + @Inject + ClientProvider clientProvider; + + @Override + public void delete(String name, String namespace) + { + + } + + @Override + public Namespace findByNameAndNamespace(String name, String namespace) + { + return null; + } + + @Override + public List findByNamespace(String namespace) + { + return clientProvider.getClient().namespaces().list().getItems(); + } + + @Override + public List findAll() + { + return List.of(); + } + + @Override + public Optional findOptionalByNameAndNamespace(String name, String namespace) + { + return Optional.empty(); + } + + @Override + public Watch watch(String namespace, Watcher watcher) + { + String version = clientProvider.getClient().namespaces().list().getMetadata().getResourceVersion(); + return clientProvider.getClient().namespaces().withResourceVersion(version).watch(watcher); + } +} diff --git a/src/main/java/dev/dinauer/service/NodeService.java b/src/main/java/dev/dinauer/service/NodeService.java index ad881a6..eea74a6 100644 --- a/src/main/java/dev/dinauer/service/NodeService.java +++ b/src/main/java/dev/dinauer/service/NodeService.java @@ -2,6 +2,9 @@ package dev.dinauer.service; import dev.dinauer.monitoring.TopNodesService; import dev.dinauer.monitoring.nodes.MonitoredNode; +import io.fabric8.kubernetes.api.model.Node; +import io.fabric8.kubernetes.client.Watch; +import io.fabric8.kubernetes.client.Watcher; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import org.jboss.resteasy.reactive.common.NotImplementedYet; @@ -42,4 +45,10 @@ public class NodeService implements ResourceService { throw new NotImplementedYet(); } + + @Override + public Watch watch(String namespace, Watcher watcher) + { + throw new NotImplementedYet(); + } } diff --git a/src/main/java/dev/dinauer/service/PodService.java b/src/main/java/dev/dinauer/service/PodService.java index 447577f..752720d 100644 --- a/src/main/java/dev/dinauer/service/PodService.java +++ b/src/main/java/dev/dinauer/service/PodService.java @@ -3,9 +3,12 @@ package dev.dinauer.service; import dev.dinauer.utils.ClientProvider; import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.apps.StatefulSet; +import io.fabric8.kubernetes.client.Watch; +import io.fabric8.kubernetes.client.Watcher; import io.fabric8.kubernetes.client.dsl.AppsAPIGroupDSL; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; +import org.jboss.resteasy.reactive.common.NotImplementedYet; import java.util.List; import java.util.Map; @@ -40,6 +43,10 @@ public class PodService implements ResourceService public List findByNamespace(String namespace) { + if (namespace.equals("_all")) + { + return clientProvider.getClient().pods().inAnyNamespace().list().getItems(); + } return clientProvider.getClient().pods().inNamespace(namespace).list().getItems(); } @@ -72,6 +79,17 @@ public class PodService implements ResourceService return Optional.ofNullable(findByNameAndNamespace(name, namespace)); } + @Override + public Watch watch(String namespace, Watcher watcher) + { + String version = clientProvider.getClient().pods().inAnyNamespace().list().getMetadata().getResourceVersion(); + if (namespace.equals("_all")) + { + return clientProvider.getClient().pods().inAnyNamespace().withResourceVersion(version).watch(watcher); + } + return clientProvider.getClient().pods().inNamespace(namespace).withResourceVersion(version).watch(watcher); + } + public Optional findPodById(String id) { for(Pod pod : clientProvider.getClient().pods().inAnyNamespace().list().getItems()) diff --git a/src/main/java/dev/dinauer/service/PvService.java b/src/main/java/dev/dinauer/service/PvService.java new file mode 100644 index 0000000..51ec68b --- /dev/null +++ b/src/main/java/dev/dinauer/service/PvService.java @@ -0,0 +1,55 @@ +package dev.dinauer.service; + +import dev.dinauer.utils.ClientProvider; +import io.fabric8.kubernetes.api.model.PersistentVolume; +import io.fabric8.kubernetes.client.Watch; +import io.fabric8.kubernetes.client.Watcher; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import java.util.List; +import java.util.Optional; + +@ApplicationScoped +public class PvService implements ResourceService +{ + @Inject + ClientProvider clientProvider; + + @Override + public void delete(String name, String namespace) + { + + } + + @Override + public PersistentVolume findByNameAndNamespace(String name, String namespace) + { + return null; + } + + @Override + public List findByNamespace(String namespace) + { + return clientProvider.getClient().persistentVolumes().list().getItems(); + } + + @Override + public List findAll() + { + return List.of(); + } + + @Override + public Optional findOptionalByNameAndNamespace(String name, String namespace) + { + return Optional.empty(); + } + + @Override + public Watch watch(String namespace, Watcher watcher) + { + String version = clientProvider.getClient().persistentVolumes().list().getMetadata().getResourceVersion(); + return clientProvider.getClient().persistentVolumes().withResourceVersion(version).watch(watcher); + } +} diff --git a/src/main/java/dev/dinauer/service/PvcService.java b/src/main/java/dev/dinauer/service/PvcService.java new file mode 100644 index 0000000..c774ce0 --- /dev/null +++ b/src/main/java/dev/dinauer/service/PvcService.java @@ -0,0 +1,63 @@ +package dev.dinauer.service; + +import dev.dinauer.utils.ClientProvider; +import io.fabric8.kubernetes.api.model.PersistentVolumeClaim; +import io.fabric8.kubernetes.client.Watch; +import io.fabric8.kubernetes.client.Watcher; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import java.util.List; +import java.util.Optional; + +@ApplicationScoped +public class PvcService implements ResourceService +{ + @Inject + ClientProvider clientProvider; + + @Override + public void delete(String name, String namespace) + { + + } + + @Override + public PersistentVolumeClaim findByNameAndNamespace(String name, String namespace) + { + return null; + } + + @Override + public List findByNamespace(String namespace) + { + if (namespace.equals("_all")) + { + return clientProvider.getClient().persistentVolumeClaims().inAnyNamespace().list().getItems(); + } + return clientProvider.getClient().persistentVolumeClaims().inNamespace(namespace).list().getItems(); + } + + @Override + public List findAll() + { + return List.of(); + } + + @Override + public Optional findOptionalByNameAndNamespace(String name, String namespace) + { + return Optional.empty(); + } + + @Override + public Watch watch(String namespace, Watcher watcher) + { + String version = clientProvider.getClient().persistentVolumeClaims().inAnyNamespace().list().getMetadata().getResourceVersion(); + if (namespace.equals("_all")) + { + return clientProvider.getClient().persistentVolumeClaims().inAnyNamespace().withResourceVersion(version).watch(watcher); + } + return clientProvider.getClient().persistentVolumeClaims().inNamespace(namespace).withResourceVersion(version).watch(watcher); + } +} diff --git a/src/main/java/dev/dinauer/service/ResourceService.java b/src/main/java/dev/dinauer/service/ResourceService.java index 6a8a9e1..065b79c 100644 --- a/src/main/java/dev/dinauer/service/ResourceService.java +++ b/src/main/java/dev/dinauer/service/ResourceService.java @@ -1,5 +1,8 @@ package dev.dinauer.service; +import io.fabric8.kubernetes.client.Watch; +import io.fabric8.kubernetes.client.Watcher; + import java.util.List; import java.util.Optional; @@ -10,4 +13,5 @@ public interface ResourceService List findByNamespace(String namespace); List findAll(); Optional findOptionalByNameAndNamespace(String name, String namespace); + Watch watch(String namespace, Watcher watcher); } diff --git a/src/main/java/dev/dinauer/service/SecretService.java b/src/main/java/dev/dinauer/service/SecretService.java index b40e1ee..044ca9e 100644 --- a/src/main/java/dev/dinauer/service/SecretService.java +++ b/src/main/java/dev/dinauer/service/SecretService.java @@ -2,6 +2,8 @@ package dev.dinauer.service; import dev.dinauer.utils.ClientProvider; import io.fabric8.kubernetes.api.model.Secret; +import io.fabric8.kubernetes.client.Watch; +import io.fabric8.kubernetes.client.Watcher; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import org.jboss.resteasy.reactive.common.NotImplementedYet; @@ -30,6 +32,10 @@ public class SecretService implements ResourceService @Override public List findByNamespace(String namespace) { + if (namespace.equals("_all")) + { + return clientProvider.getClient().secrets().inAnyNamespace().list().getItems(); + } return clientProvider.getClient().secrets().inNamespace(namespace).list().getItems(); } @@ -44,4 +50,15 @@ public class SecretService implements ResourceService { throw new NotImplementedYet(); } + + @Override + public Watch watch(String namespace, Watcher watcher) + { + String version = clientProvider.getClient().secrets().inAnyNamespace().list().getMetadata().getResourceVersion(); + if (namespace.equals("_all")) + { + return clientProvider.getClient().secrets().inAnyNamespace().withResourceVersion(version).watch(watcher); + } + return clientProvider.getClient().secrets().inNamespace(namespace).withResourceVersion(version).watch(watcher); + } } diff --git a/src/main/java/dev/dinauer/service/ServiceService.java b/src/main/java/dev/dinauer/service/ServiceService.java index 18bd8c9..bb527d4 100644 --- a/src/main/java/dev/dinauer/service/ServiceService.java +++ b/src/main/java/dev/dinauer/service/ServiceService.java @@ -5,6 +5,8 @@ import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.KubernetesClientBuilder; +import io.fabric8.kubernetes.client.Watch; +import io.fabric8.kubernetes.client.Watcher; import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -33,6 +35,10 @@ public class ServiceService implements ResourceService public List findByNamespace(String namespace) { + if (namespace.equals("_all")) + { + return clientProvider.getClient().services().inAnyNamespace().list().getItems(); + } return clientProvider.getClient().services().inNamespace(namespace).list().getItems(); } @@ -47,6 +53,17 @@ public class ServiceService implements ResourceService return Optional.ofNullable(findByNameAndNamespace(name, namespace)); } + @Override + public Watch watch(String namespace, Watcher watcher) + { + String version = clientProvider.getClient().services().inAnyNamespace().list().getMetadata().getResourceVersion(); + if (namespace.equals("_all")) + { + return clientProvider.getClient().services().inAnyNamespace().withResourceVersion(version).watch(watcher); + } + return clientProvider.getClient().services().inNamespace(namespace).withResourceVersion(version).watch(watcher); + } + public Optional findById(String id) { for(Service service : clientProvider.getClient().services().list().getItems()) diff --git a/src/main/java/dev/dinauer/service/StatefulSetService.java b/src/main/java/dev/dinauer/service/StatefulSetService.java index e56bb4a..f530150 100644 --- a/src/main/java/dev/dinauer/service/StatefulSetService.java +++ b/src/main/java/dev/dinauer/service/StatefulSetService.java @@ -1,7 +1,12 @@ package dev.dinauer.service; +import dev.dinauer.utils.ClientProvider; import io.fabric8.kubernetes.api.model.apps.StatefulSet; +import io.fabric8.kubernetes.client.Watch; +import io.fabric8.kubernetes.client.Watcher; +import io.fabric8.kubernetes.client.dsl.AppsAPIGroupDSL; import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; import org.jboss.resteasy.reactive.common.NotImplementedYet; import java.util.List; @@ -11,6 +16,9 @@ import java.util.Optional; public class StatefulSetService implements ResourceService { + @Inject + ClientProvider clientProvider; + @Override public void delete(String name, String namespace) { @@ -26,7 +34,14 @@ public class StatefulSetService implements ResourceService @Override public List findByNamespace(String namespace) { - return List.of(); + try(AppsAPIGroupDSL dsl = clientProvider.getClient().apps()) + { + if (namespace.equals("_all")) + { + return dsl.statefulSets().inAnyNamespace().list().getItems(); + } + return dsl.statefulSets().inNamespace(namespace).list().getItems(); + } } @Override @@ -40,4 +55,17 @@ public class StatefulSetService implements ResourceService { return Optional.empty(); } + + @Override + public Watch watch(String namespace, Watcher watcher) + { + try (AppsAPIGroupDSL dsl = clientProvider.getClient().apps()) { + String version = dsl.statefulSets().inAnyNamespace().list().getMetadata().getResourceVersion(); + if (namespace.equals("_all")) + { + return dsl.statefulSets().inAnyNamespace().withResourceVersion(version).watch(watcher); + } + return dsl.statefulSets().inNamespace(namespace).withResourceVersion(version).watch(watcher); + } + } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 854b2ba..a39bd7a 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -23,4 +23,7 @@ quarkus.datasource.db-kind = postgresql %prod.quarkus.datasource.username=${DB_USER} %prod.quarkus.datasource.password=${DB_PASSWORD} %prod.quarkus.datasource.jdbc.url=jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_DATABASE}?currentSchema=${DB_SCHEMA} -%prod.quarkus.hibernate-orm.schema-management.strategy=drop-and-create \ No newline at end of file +%prod.quarkus.hibernate-orm.schema-management.strategy=drop-and-create + +# Banner +quarkus.banner.path=banner.txt \ No newline at end of file diff --git a/src/main/resources/banner.txt b/src/main/resources/banner.txt new file mode 100644 index 0000000..6e8285d --- /dev/null +++ b/src/main/resources/banner.txt @@ -0,0 +1,5 @@ + __ __ __ __ + / //_/_ __/ /_ ____ ____ / /_ ____ ____ + / ,< / / / / __ \/ __ \/ __ \/ __ \/ __ \/ __ \ + / /| / /_/ / /_/ / /_/ / /_/ / /_/ / /_/ / /_/ / +/_/ |_\__,_/_.___/\____/\____/_.___/\____/\____/ \ No newline at end of file diff --git a/src/main/resources/import.sql b/src/main/resources/import.sql index 2454683..51f20be 100644 --- a/src/main/resources/import.sql +++ b/src/main/resources/import.sql @@ -1,11 +1,11 @@ INSERT INTO monitoring_config (id, config_name, type, interval) -VALUES ('5da234f4-3a34-4b1c-b72a-7330ca3b1dcf', 'Postgres Cluster', 'VOLUME', '30s'); +VALUES ('5da234f4-3a34-4b1c-b72a-7330ca3b1dcf', 'Postgres Cluster', 'VOLUME', '10m'); INSERT INTO target_config (id, type, namespace, labels, deployment_name, stateful_set_name, config_id) VALUES ('4bd2f449-ed11-4f3f-830a-e4dc39cb21f5', 'LABELS', 'tavolio-prod', '{"cnpg.io/cluster":"postgres-cluster"}', null, null, '5da234f4-3a34-4b1c-b72a-7330ca3b1dcf'); INSERT INTO volume_config (id, container_name, mount_path, config_id) VALUES ('4090a60c-4517-4d76-b460-a0454014f30d', 'postgres', '/var/lib/postgresql/data', '5da234f4-3a34-4b1c-b72a-7330ca3b1dcf'); INSERT INTO monitoring_config (id, config_name, type, interval) -VALUES ('2da234f4-3a34-4b1c-b72a-7330ca3b1dcf', 'Postgres Cluster', 'MEMORY', '40s'); +VALUES ('2da234f4-3a34-4b1c-b72a-7330ca3b1dcf', 'Postgres Cluster', 'MEMORY', '10m'); INSERT INTO target_config (id, type, namespace, labels, deployment_name, stateful_set_name, config_id) VALUES ('2bd2f449-ed11-4f3f-830a-e4dc39cb21f5', 'LABELS', 'tavolio-prod', '{"cnpg.io/cluster":"postgres-cluster"}', null, null, '2da234f4-3a34-4b1c-b72a-7330ca3b1dcf'); \ No newline at end of file