From 0c050f67f701540156a452fbd63cb909ad95e682 Mon Sep 17 00:00:00 2001 From: Comte Date: Mon, 3 Jun 2024 18:16:24 +0200 Subject: [PATCH 01/14] init owner --- .../controller/api/mylab/MyLabController.java | 13 ++++ .../onyxia/api/services/AppsService.java | 3 + .../api/services/impl/HelmAppsService.java | 72 +++++++++++++++++++ .../insee/onyxia/model/service/Service.java | 11 +++ 4 files changed, 99 insertions(+) diff --git a/onyxia-api/src/main/java/fr/insee/onyxia/api/controller/api/mylab/MyLabController.java b/onyxia-api/src/main/java/fr/insee/onyxia/api/controller/api/mylab/MyLabController.java index 8142ffc3..1564ce56 100644 --- a/onyxia-api/src/main/java/fr/insee/onyxia/api/controller/api/mylab/MyLabController.java +++ b/onyxia-api/src/main/java/fr/insee/onyxia/api/controller/api/mylab/MyLabController.java @@ -219,6 +219,19 @@ private void suspendOrResume(Region region, Project project, String serviceId, b } } + @GetMapping("/app/details") + public Service getApp( + @Parameter(hidden = true) Region region, + @Parameter(hidden = true) Project project, + @RequestParam("serviceId") String serviceId) + throws Exception { + if (Service.ServiceType.KUBERNETES.equals(region.getServices().getType())) { + return helmAppsService.getUserServiceDetails( + region, project, userProvider.getUser(region), serviceId); + } + return null; + } + @Operation( summary = "Get the logs of a task in an installed service.", description = diff --git a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/AppsService.java b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/AppsService.java index 1d832598..e9810348 100644 --- a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/AppsService.java +++ b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/AppsService.java @@ -46,6 +46,9 @@ Collection installApp( Service getUserService(Region region, Project project, User user, String serviceId) throws Exception; + Service getUserServiceDetails(Region region, Project project, User user, String serviceId) + throws Exception; + UninstallService destroyService( Region region, Project project, User user, String path, boolean bulk) throws Exception; diff --git a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java index fd5aefc7..88ccb935 100644 --- a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java +++ b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java @@ -30,6 +30,9 @@ import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.Watch; import io.fabric8.kubernetes.client.Watcher; +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.OwnerReference; +import io.fabric8.kubernetes.api.model.Pod; import io.github.inseefrlab.helmwrapper.configuration.HelmConfiguration; import io.github.inseefrlab.helmwrapper.model.HelmInstaller; import io.github.inseefrlab.helmwrapper.model.HelmLs; @@ -324,6 +327,75 @@ public Service getUserService(Region region, Project project, User user, String return getHelmApp(region, user, result); } + @Override + public Service getUserServiceDetails(Region region, Project project, User user, String serviceId) + throws MultipleServiceFound, ParseException { + if (serviceId.startsWith("/")) { + serviceId = serviceId.substring(1); + } + HelmLs result = + getHelmInstallService() + .getAppById( + getHelmConfiguration(region, user), + serviceId, + kubernetesService.determineNamespaceAndCreateIfNeeded( + region, project, user)); + Service res = getHelmApp(region, user, result); + List> podInfoList = new ArrayList<>(); + KubernetesClient client = kubernetesClientProvider.getUserClient(region, user); + List pods = client.pods().inNamespace(kubernetesService.determineNamespaceAndCreateIfNeeded( + region, project, user)).list().getItems(); + for (Pod pod : pods) { + Map podInfo = new HashMap<>(); + podInfo.put("podName", pod.getMetadata().getName()); + podInfo.put("owners", getOwnerReferences(pod)); + podInfoList.add(podInfo); + } + res.setPodsAndOwners(podInfoList); + return res; + } + + private List> getOwnerReferences(HasMetadata resource, KubernetesClient client) { + List> owners = new ArrayList<>(); + + List ownerReferences = resource.getMetadata().getOwnerReferences(); + if (ownerReferences != null) { + for (OwnerReference ownerReference : ownerReferences) { + String kind = ownerReference.getKind(); + String name = ownerReference.getName(); + + // Fetch the owner resource + HasMetadata ownerResource = fetchOwnerResource(resource.getMetadata().getNamespace(), kind, name, client); + if (ownerResource != null) { + Map ownerInfo = new HashMap<>(); + ownerInfo.put("kind", kind); + ownerInfo.put("name", name); + ownerInfo.put("owners", getOwnerReferences(ownerResource)); + + owners.add(ownerInfo); + } + } + } + + return owners; + } + + private HasMetadata fetchOwnerResource(String namespace, String kind, String name, KubernetesClient client) { + switch (kind) { + case "ReplicaSet": + return client.apps().replicaSets().inNamespace(namespace).withName(name).get(); + case "Deployment": + return client.apps().deployments().inNamespace(namespace).withName(name).get(); + case "StatefulSet": + return client.apps().statefulSets().inNamespace(namespace).withName(name).get(); + case "DaemonSet": + return client.apps().daemonSets().inNamespace(namespace).withName(name).get(); + case "Pod": + return client.pods().inNamespace(namespace).withName(name).get(); + default: + return null; // Handle other kinds if needed + } + } @Override public UninstallService destroyService( Region region, Project project, User user, final String path, boolean bulk) diff --git a/onyxia-model/src/main/java/fr/insee/onyxia/model/service/Service.java b/onyxia-model/src/main/java/fr/insee/onyxia/model/service/Service.java index 9aa28743..75c957e1 100644 --- a/onyxia-model/src/main/java/fr/insee/onyxia/model/service/Service.java +++ b/onyxia-model/src/main/java/fr/insee/onyxia/model/service/Service.java @@ -80,6 +80,9 @@ public class Service { @Schema(description = "") private Map labels; + @Schema(description = "") + private List> podsAndOwners; + public String getId() { return id; } @@ -264,6 +267,14 @@ public void setSuspended(boolean suspended) { this.suspended = suspended; } + public List> getPodsAndOwners() { + return podsAndOwners; + } + + public void setPodsAndOwners(List> podsAndOwners) { + this.podsAndOwners = podsAndOwners; + } + @Schema(description = "") public static enum ServiceStatus { DEPLOYING, From 8f66006c47e79aea4974386533020dc635e962fe Mon Sep 17 00:00:00 2001 From: Comte Date: Mon, 3 Jun 2024 18:18:56 +0200 Subject: [PATCH 02/14] fix method name --- .../insee/onyxia/api/controller/api/mylab/MyLabController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onyxia-api/src/main/java/fr/insee/onyxia/api/controller/api/mylab/MyLabController.java b/onyxia-api/src/main/java/fr/insee/onyxia/api/controller/api/mylab/MyLabController.java index 1564ce56..8410164a 100644 --- a/onyxia-api/src/main/java/fr/insee/onyxia/api/controller/api/mylab/MyLabController.java +++ b/onyxia-api/src/main/java/fr/insee/onyxia/api/controller/api/mylab/MyLabController.java @@ -220,7 +220,7 @@ private void suspendOrResume(Region region, Project project, String serviceId, b } @GetMapping("/app/details") - public Service getApp( + public Service getAppDetails( @Parameter(hidden = true) Region region, @Parameter(hidden = true) Project project, @RequestParam("serviceId") String serviceId) From 3c4fb23811e5b4b08eb54f694727d5013e2da44d Mon Sep 17 00:00:00 2001 From: Comte Date: Mon, 3 Jun 2024 18:22:11 +0200 Subject: [PATCH 03/14] fix kub client --- .../fr/insee/onyxia/api/services/impl/HelmAppsService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java index 88ccb935..8d35475f 100644 --- a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java +++ b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java @@ -348,7 +348,7 @@ public Service getUserServiceDetails(Region region, Project project, User user, for (Pod pod : pods) { Map podInfo = new HashMap<>(); podInfo.put("podName", pod.getMetadata().getName()); - podInfo.put("owners", getOwnerReferences(pod)); + podInfo.put("owners", getOwnerReferences(pod,client)); podInfoList.add(podInfo); } res.setPodsAndOwners(podInfoList); @@ -370,7 +370,7 @@ private List> getOwnerReferences(HasMetadata resource, Kuber Map ownerInfo = new HashMap<>(); ownerInfo.put("kind", kind); ownerInfo.put("name", name); - ownerInfo.put("owners", getOwnerReferences(ownerResource)); + ownerInfo.put("owners", getOwnerReferences(ownerResource,client)); owners.add(ownerInfo); } From 2e64578f1efe8fbd6e7520dc2e561b8e4476e479 Mon Sep 17 00:00:00 2001 From: Comte Date: Mon, 3 Jun 2024 20:49:30 +0200 Subject: [PATCH 04/14] filter --- .../api/services/impl/HelmAppsService.java | 30 +++++++++++++++++-- .../insee/onyxia/model/service/Service.java | 11 +++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java index 8d35475f..3d5cdc7b 100644 --- a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java +++ b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java @@ -42,7 +42,9 @@ import java.io.File; import java.io.IOException; import java.text.ParseException; -import java.util.*; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; @@ -341,6 +343,15 @@ public Service getUserServiceDetails(Region region, Project project, User user, kubernetesService.determineNamespaceAndCreateIfNeeded( region, project, user)); Service res = getHelmApp(region, user, result); + + List hasMetadata; + try (InputStream inputStream = + new ByteArrayInputStream(manifest.getBytes(StandardCharsets.UTF_8))) { + hasMetadata = client.load(inputStream).items(); + } catch (IOException e) { + throw new RuntimeException("Exception during loading manifest", e); + } + res.setTemplates(hasMetadata); List> podInfoList = new ArrayList<>(); KubernetesClient client = kubernetesClientProvider.getUserClient(region, user); List pods = client.pods().inNamespace(kubernetesService.determineNamespaceAndCreateIfNeeded( @@ -351,7 +362,7 @@ public Service getUserServiceDetails(Region region, Project project, User user, podInfo.put("owners", getOwnerReferences(pod,client)); podInfoList.add(podInfo); } - res.setPodsAndOwners(podInfoList); + res.setPodsAndOwners(filterPodsByOwnerReferences(podInfoList, hasMetadata)); return res; } @@ -396,6 +407,21 @@ private HasMetadata fetchOwnerResource(String namespace, String kind, String nam return null; // Handle other kinds if needed } } + + private List> filterPodsByOwnerReferences(List> podInfoList, List resourceList) { + Set resourceUids = resourceList.stream() + .map(resource -> resource.getMetadata().getUid()) + .collect(Collectors.toSet()); + + return podInfoList.stream() + .filter(podInfo -> { + List> owners = (List>) podInfo.get("owners"); + return owners.stream() + .anyMatch(owner -> resourceUids.contains(owner.get("uid"))); + }) + .collect(Collectors.toList()); + } + @Override public UninstallService destroyService( Region region, Project project, User user, final String path, boolean bulk) diff --git a/onyxia-model/src/main/java/fr/insee/onyxia/model/service/Service.java b/onyxia-model/src/main/java/fr/insee/onyxia/model/service/Service.java index 75c957e1..f7a5568b 100644 --- a/onyxia-model/src/main/java/fr/insee/onyxia/model/service/Service.java +++ b/onyxia-model/src/main/java/fr/insee/onyxia/model/service/Service.java @@ -5,6 +5,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import io.fabric8.kubernetes.api.model.HasMetadata; @Schema(description = "") public class Service { @@ -83,6 +84,8 @@ public class Service { @Schema(description = "") private List> podsAndOwners; + private List templates; + public String getId() { return id; } @@ -275,6 +278,14 @@ public void setPodsAndOwners(List> podsAndOwners) { this.podsAndOwners = podsAndOwners; } + public List getTemplates() { + return templates; + } + + public void setTemplates(List templates) { + this.templates = templates; + } + @Schema(description = "") public static enum ServiceStatus { DEPLOYING, From 403a3eb78232e04b7d61e95a81f7ca1f874e156a Mon Sep 17 00:00:00 2001 From: Comte Date: Mon, 3 Jun 2024 20:58:47 +0200 Subject: [PATCH 05/14] fix hasmetadata --- .../main/java/fr/insee/onyxia/model/service/Service.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/onyxia-model/src/main/java/fr/insee/onyxia/model/service/Service.java b/onyxia-model/src/main/java/fr/insee/onyxia/model/service/Service.java index f7a5568b..7f83077f 100644 --- a/onyxia-model/src/main/java/fr/insee/onyxia/model/service/Service.java +++ b/onyxia-model/src/main/java/fr/insee/onyxia/model/service/Service.java @@ -5,7 +5,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import io.fabric8.kubernetes.api.model.HasMetadata; @Schema(description = "") public class Service { @@ -84,7 +83,7 @@ public class Service { @Schema(description = "") private List> podsAndOwners; - private List templates; + private List templates; public String getId() { return id; @@ -278,11 +277,11 @@ public void setPodsAndOwners(List> podsAndOwners) { this.podsAndOwners = podsAndOwners; } - public List getTemplates() { + public List getTemplates() { return templates; } - public void setTemplates(List templates) { + public void setTemplates(List templates) { this.templates = templates; } From 708e117174c4fc62fd46f5bc26e6393ea2cd3a1f Mon Sep 17 00:00:00 2001 From: Comte Date: Mon, 3 Jun 2024 21:00:20 +0200 Subject: [PATCH 06/14] fix import --- .../java/fr/insee/onyxia/api/services/impl/HelmAppsService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java index 3d5cdc7b..787be16b 100644 --- a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java +++ b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java @@ -48,6 +48,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; +import java.util.*; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.FastDateFormat; import org.slf4j.Logger; From a39fed2ff4b231420b82f67e38f20ca8ae7784ce Mon Sep 17 00:00:00 2001 From: Comte Date: Mon, 3 Jun 2024 21:08:19 +0200 Subject: [PATCH 07/14] convert --- .../insee/onyxia/api/services/impl/HelmAppsService.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java index 787be16b..8980d971 100644 --- a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java +++ b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java @@ -344,17 +344,18 @@ public Service getUserServiceDetails(Region region, Project project, User user, kubernetesService.determineNamespaceAndCreateIfNeeded( region, project, user)); Service res = getHelmApp(region, user, result); - + KubernetesClient client = kubernetesClientProvider.getUserClient(region, user); List hasMetadata; try (InputStream inputStream = - new ByteArrayInputStream(manifest.getBytes(StandardCharsets.UTF_8))) { + new ByteArrayInputStream(res.getManifest().getBytes(StandardCharsets.UTF_8))) { hasMetadata = client.load(inputStream).items(); } catch (IOException e) { throw new RuntimeException("Exception during loading manifest", e); } - res.setTemplates(hasMetadata); + List manifests = new ArrayList(hasMetadata); + res.setTemplates(manifests); List> podInfoList = new ArrayList<>(); - KubernetesClient client = kubernetesClientProvider.getUserClient(region, user); + List pods = client.pods().inNamespace(kubernetesService.determineNamespaceAndCreateIfNeeded( region, project, user)).list().getItems(); for (Pod pod : pods) { From 76c1af3e5fc461239d56bc907bbefc1ddc18012e Mon Sep 17 00:00:00 2001 From: Comte Date: Mon, 3 Jun 2024 21:16:28 +0200 Subject: [PATCH 08/14] fix --- .../insee/onyxia/api/services/impl/HelmAppsService.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java index 8980d971..c30b88e7 100644 --- a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java +++ b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java @@ -343,11 +343,17 @@ public Service getUserServiceDetails(Region region, Project project, User user, serviceId, kubernetesService.determineNamespaceAndCreateIfNeeded( region, project, user)); + HelmReleaseInfo helmReleaseInfo = + getHelmInstallService() + .getAll( + getHelmConfiguration(region, user), + result.getName(), + result.getNamespace()); Service res = getHelmApp(region, user, result); KubernetesClient client = kubernetesClientProvider.getUserClient(region, user); List hasMetadata; try (InputStream inputStream = - new ByteArrayInputStream(res.getManifest().getBytes(StandardCharsets.UTF_8))) { + new ByteArrayInputStream(helmReleaseInfo.getManifest().getBytes(StandardCharsets.UTF_8))) { hasMetadata = client.load(inputStream).items(); } catch (IOException e) { throw new RuntimeException("Exception during loading manifest", e); From d423fec719218ada6fbdd32384e46bb327100a3b Mon Sep 17 00:00:00 2001 From: Comte Date: Mon, 3 Jun 2024 21:38:25 +0200 Subject: [PATCH 09/14] fix --- .../api/services/impl/HelmAppsService.java | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java index c30b88e7..c254cf30 100644 --- a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java +++ b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java @@ -370,7 +370,7 @@ public Service getUserServiceDetails(Region region, Project project, User user, podInfo.put("owners", getOwnerReferences(pod,client)); podInfoList.add(podInfo); } - res.setPodsAndOwners(filterPodsByOwnerReferences(podInfoList, hasMetadata)); + res.setPodsAndOwners(filterPodsByOwnerReferences(podInfoList, hasMetadata,namespace)); return res; } @@ -416,20 +416,29 @@ private HasMetadata fetchOwnerResource(String namespace, String kind, String nam } } - private List> filterPodsByOwnerReferences(List> podInfoList, List resourceList) { - Set resourceUids = resourceList.stream() - .map(resource -> resource.getMetadata().getUid()) + private List> filterPodsByTopLevelOwnerReferences(List> podInfoList, List resourceList, String namespace) { + Set resourceNamesAndKinds = resourceList.stream() + .map(resource -> resource.getKind() + "/" + resource.getMetadata().getName()) .collect(Collectors.toSet()); return podInfoList.stream() .filter(podInfo -> { List> owners = (List>) podInfo.get("owners"); return owners.stream() - .anyMatch(owner -> resourceUids.contains(owner.get("uid"))); + .anyMatch(owner -> resourceNamesAndKinds.contains(findTopLevelOwner((String) owner.get("kind"), (String) owner.get("name"), namespace))); }) .collect(Collectors.toList()); } + private String findTopLevelOwner(String kind, String name, String namespace,KubernetesClient client) { + HasMetadata resource = fetchOwnerResource(namespace, kind, name,client); + while (resource != null && !resource.getMetadata().getOwnerReferences().isEmpty()) { + OwnerReference ownerReference = resource.getMetadata().getOwnerReferences().get(0); + resource = fetchOwnerResource(namespace, ownerReference.getKind(), ownerReference.getName(),client); + } + return resource != null ? resource.getKind() + "/" + resource.getMetadata().getName() : null; + } + @Override public UninstallService destroyService( Region region, Project project, User user, final String path, boolean bulk) From eef018dd3769a362968581dc8c383a474ec4922e Mon Sep 17 00:00:00 2001 From: Comte Date: Mon, 3 Jun 2024 21:43:03 +0200 Subject: [PATCH 10/14] fix --- .../onyxia/api/services/impl/HelmAppsService.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java index c254cf30..c065d8d7 100644 --- a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java +++ b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java @@ -336,13 +336,14 @@ public Service getUserServiceDetails(Region region, Project project, User user, if (serviceId.startsWith("/")) { serviceId = serviceId.substring(1); } + String namespace = kubernetesService.determineNamespaceAndCreateIfNeeded(region, project, user); HelmLs result = getHelmInstallService() .getAppById( getHelmConfiguration(region, user), serviceId, - kubernetesService.determineNamespaceAndCreateIfNeeded( - region, project, user)); + namespace + ); HelmReleaseInfo helmReleaseInfo = getHelmInstallService() .getAll( @@ -362,8 +363,7 @@ public Service getUserServiceDetails(Region region, Project project, User user, res.setTemplates(manifests); List> podInfoList = new ArrayList<>(); - List pods = client.pods().inNamespace(kubernetesService.determineNamespaceAndCreateIfNeeded( - region, project, user)).list().getItems(); + List pods = client.pods().inNamespace(namespace).list().getItems(); for (Pod pod : pods) { Map podInfo = new HashMap<>(); podInfo.put("podName", pod.getMetadata().getName()); @@ -416,7 +416,7 @@ private HasMetadata fetchOwnerResource(String namespace, String kind, String nam } } - private List> filterPodsByTopLevelOwnerReferences(List> podInfoList, List resourceList, String namespace) { + private List> filterPodsByTopLevelOwnerReferences(List> podInfoList, List resourceList, String namespace,KubernetesClient client) { Set resourceNamesAndKinds = resourceList.stream() .map(resource -> resource.getKind() + "/" + resource.getMetadata().getName()) .collect(Collectors.toSet()); @@ -425,7 +425,7 @@ private List> filterPodsByTopLevelOwnerReferences(List { List> owners = (List>) podInfo.get("owners"); return owners.stream() - .anyMatch(owner -> resourceNamesAndKinds.contains(findTopLevelOwner((String) owner.get("kind"), (String) owner.get("name"), namespace))); + .anyMatch(owner -> resourceNamesAndKinds.contains(findTopLevelOwner((String) owner.get("kind"), (String) owner.get("name"), namespace, client))); }) .collect(Collectors.toList()); } From 976398961e79f0375291af0340a67c9639f57755 Mon Sep 17 00:00:00 2001 From: Comte Date: Mon, 3 Jun 2024 21:44:39 +0200 Subject: [PATCH 11/14] fix --- .../java/fr/insee/onyxia/api/services/impl/HelmAppsService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java index c065d8d7..779af10e 100644 --- a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java +++ b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java @@ -370,7 +370,7 @@ public Service getUserServiceDetails(Region region, Project project, User user, podInfo.put("owners", getOwnerReferences(pod,client)); podInfoList.add(podInfo); } - res.setPodsAndOwners(filterPodsByOwnerReferences(podInfoList, hasMetadata,namespace)); + res.setPodsAndOwners(filterPodsByOwnerReferences(podInfoList, hasMetadata,namespace,client)); return res; } From c395afa54dfbf73313ce9952b32300644ef0b99d Mon Sep 17 00:00:00 2001 From: Comte Date: Mon, 3 Jun 2024 21:47:57 +0200 Subject: [PATCH 12/14] fix --- .../java/fr/insee/onyxia/api/services/impl/HelmAppsService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java index 779af10e..65bf095f 100644 --- a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java +++ b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java @@ -370,7 +370,7 @@ public Service getUserServiceDetails(Region region, Project project, User user, podInfo.put("owners", getOwnerReferences(pod,client)); podInfoList.add(podInfo); } - res.setPodsAndOwners(filterPodsByOwnerReferences(podInfoList, hasMetadata,namespace,client)); + res.setPodsAndOwners(filterPodsByTopLevelOwnerReferences(podInfoList, hasMetadata, namespace, client)); return res; } From 40cd76012800cbb4a3bc2275c666fadd1917324f Mon Sep 17 00:00:00 2001 From: Comte Date: Mon, 10 Jun 2024 17:10:27 +0200 Subject: [PATCH 13/14] add containers info --- .../api/services/impl/HelmAppsService.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java index 65bf095f..74445b85 100644 --- a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java +++ b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java @@ -368,12 +368,41 @@ public Service getUserServiceDetails(Region region, Project project, User user, Map podInfo = new HashMap<>(); podInfo.put("podName", pod.getMetadata().getName()); podInfo.put("owners", getOwnerReferences(pod,client)); + podInfo.put("containers", getContainers(pod)); podInfoList.add(podInfo); } res.setPodsAndOwners(filterPodsByTopLevelOwnerReferences(podInfoList, hasMetadata, namespace, client)); return res; } + private List> getContainers(Pod pod) { + List> containersInfo = new ArrayList<>(); + List containers = pod.getSpec().getContainers(); + List initContainers = pod.getSpec().getInitContainers(); + + for (Container container : containers) { + Map containerInfo = new HashMap<>(); + containerInfo.put("name", container.getName()); + containerInfo.put("image", container.getImage()); + containerInfo.put("resources", container.getResources()); + containerInfo.put("type", "container"); + + containersInfo.add(containerInfo); + } + + for (Container initContainer : initContainers) { + Map initContainerInfo = new HashMap<>(); + initContainerInfo.put("name", initContainer.getName()); + initContainerInfo.put("image", initContainer.getImage()); + initContainerInfo.put("resources", initContainer.getResources()); + initContainerInfo.put("type", "initContainer"); + + containersInfo.add(initContainerInfo); + } + + return containersInfo; + } + private List> getOwnerReferences(HasMetadata resource, KubernetesClient client) { List> owners = new ArrayList<>(); From 7dda39d82b2095f4d9a3650432aa23f38cfe06dd Mon Sep 17 00:00:00 2001 From: Olivier Levitt Date: Mon, 10 Jun 2024 17:19:27 +0200 Subject: [PATCH 14/14] =?UTF-8?q?Fix=20fr=C3=A9do?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/services/impl/HelmAppsService.java | 104 +++++++++++------- 1 file changed, 65 insertions(+), 39 deletions(-) diff --git a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java index 74445b85..0cbca3df 100644 --- a/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java +++ b/onyxia-api/src/main/java/fr/insee/onyxia/api/services/impl/HelmAppsService.java @@ -27,28 +27,28 @@ import fr.insee.onyxia.model.project.Project; import fr.insee.onyxia.model.region.Region; import fr.insee.onyxia.model.service.*; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.Watch; -import io.fabric8.kubernetes.client.Watcher; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.OwnerReference; import io.fabric8.kubernetes.api.model.Pod; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.Watch; +import io.fabric8.kubernetes.client.Watcher; import io.github.inseefrlab.helmwrapper.configuration.HelmConfiguration; import io.github.inseefrlab.helmwrapper.model.HelmInstaller; import io.github.inseefrlab.helmwrapper.model.HelmLs; import io.github.inseefrlab.helmwrapper.model.HelmReleaseInfo; import io.github.inseefrlab.helmwrapper.service.HelmInstallService; import io.github.inseefrlab.helmwrapper.service.HelmInstallService.MultipleServiceFound; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; -import java.text.ParseException; -import java.io.ByteArrayInputStream; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import java.text.ParseException; +import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; -import java.util.*; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.FastDateFormat; import org.slf4j.Logger; @@ -331,19 +331,17 @@ public Service getUserService(Region region, Project project, User user, String } @Override - public Service getUserServiceDetails(Region region, Project project, User user, String serviceId) + public Service getUserServiceDetails( + Region region, Project project, User user, String serviceId) throws MultipleServiceFound, ParseException { if (serviceId.startsWith("/")) { serviceId = serviceId.substring(1); } - String namespace = kubernetesService.determineNamespaceAndCreateIfNeeded(region, project, user); + String namespace = + kubernetesService.determineNamespaceAndCreateIfNeeded(region, project, user); HelmLs result = getHelmInstallService() - .getAppById( - getHelmConfiguration(region, user), - serviceId, - namespace - ); + .getAppById(getHelmConfiguration(region, user), serviceId, namespace); HelmReleaseInfo helmReleaseInfo = getHelmInstallService() .getAll( @@ -354,33 +352,36 @@ public Service getUserServiceDetails(Region region, Project project, User user, KubernetesClient client = kubernetesClientProvider.getUserClient(region, user); List hasMetadata; try (InputStream inputStream = - new ByteArrayInputStream(helmReleaseInfo.getManifest().getBytes(StandardCharsets.UTF_8))) { + new ByteArrayInputStream( + helmReleaseInfo.getManifest().getBytes(StandardCharsets.UTF_8))) { hasMetadata = client.load(inputStream).items(); } catch (IOException e) { throw new RuntimeException("Exception during loading manifest", e); } - List manifests = new ArrayList(hasMetadata); + List manifests = new ArrayList(hasMetadata); res.setTemplates(manifests); List> podInfoList = new ArrayList<>(); - + List pods = client.pods().inNamespace(namespace).list().getItems(); for (Pod pod : pods) { Map podInfo = new HashMap<>(); podInfo.put("podName", pod.getMetadata().getName()); - podInfo.put("owners", getOwnerReferences(pod,client)); + podInfo.put("owners", getOwnerReferences(pod, client)); podInfo.put("containers", getContainers(pod)); podInfoList.add(podInfo); } - res.setPodsAndOwners(filterPodsByTopLevelOwnerReferences(podInfoList, hasMetadata, namespace, client)); + res.setPodsAndOwners( + filterPodsByTopLevelOwnerReferences(podInfoList, hasMetadata, namespace, client)); return res; } private List> getContainers(Pod pod) { List> containersInfo = new ArrayList<>(); - List containers = pod.getSpec().getContainers(); - List initContainers = pod.getSpec().getInitContainers(); + List containers = pod.getSpec().getContainers(); + List initContainers = + pod.getSpec().getInitContainers(); - for (Container container : containers) { + for (io.fabric8.kubernetes.api.model.Container container : containers) { Map containerInfo = new HashMap<>(); containerInfo.put("name", container.getName()); containerInfo.put("image", container.getImage()); @@ -390,7 +391,7 @@ private List> getContainers(Pod pod) { containersInfo.add(containerInfo); } - for (Container initContainer : initContainers) { + for (io.fabric8.kubernetes.api.model.Container initContainer : initContainers) { Map initContainerInfo = new HashMap<>(); initContainerInfo.put("name", initContainer.getName()); initContainerInfo.put("image", initContainer.getImage()); @@ -403,7 +404,8 @@ private List> getContainers(Pod pod) { return containersInfo; } - private List> getOwnerReferences(HasMetadata resource, KubernetesClient client) { + private List> getOwnerReferences( + HasMetadata resource, KubernetesClient client) { List> owners = new ArrayList<>(); List ownerReferences = resource.getMetadata().getOwnerReferences(); @@ -413,12 +415,14 @@ private List> getOwnerReferences(HasMetadata resource, Kuber String name = ownerReference.getName(); // Fetch the owner resource - HasMetadata ownerResource = fetchOwnerResource(resource.getMetadata().getNamespace(), kind, name, client); + HasMetadata ownerResource = + fetchOwnerResource( + resource.getMetadata().getNamespace(), kind, name, client); if (ownerResource != null) { Map ownerInfo = new HashMap<>(); ownerInfo.put("kind", kind); ownerInfo.put("name", name); - ownerInfo.put("owners", getOwnerReferences(ownerResource,client)); + ownerInfo.put("owners", getOwnerReferences(ownerResource, client)); owners.add(ownerInfo); } @@ -428,7 +432,8 @@ private List> getOwnerReferences(HasMetadata resource, Kuber return owners; } - private HasMetadata fetchOwnerResource(String namespace, String kind, String name, KubernetesClient client) { + private HasMetadata fetchOwnerResource( + String namespace, String kind, String name, KubernetesClient client) { switch (kind) { case "ReplicaSet": return client.apps().replicaSets().inNamespace(namespace).withName(name).get(); @@ -445,27 +450,48 @@ private HasMetadata fetchOwnerResource(String namespace, String kind, String nam } } - private List> filterPodsByTopLevelOwnerReferences(List> podInfoList, List resourceList, String namespace,KubernetesClient client) { - Set resourceNamesAndKinds = resourceList.stream() - .map(resource -> resource.getKind() + "/" + resource.getMetadata().getName()) - .collect(Collectors.toSet()); + private List> filterPodsByTopLevelOwnerReferences( + List> podInfoList, + List resourceList, + String namespace, + KubernetesClient client) { + Set resourceNamesAndKinds = + resourceList.stream() + .map( + resource -> + resource.getKind() + "/" + resource.getMetadata().getName()) + .collect(Collectors.toSet()); return podInfoList.stream() - .filter(podInfo -> { - List> owners = (List>) podInfo.get("owners"); - return owners.stream() - .anyMatch(owner -> resourceNamesAndKinds.contains(findTopLevelOwner((String) owner.get("kind"), (String) owner.get("name"), namespace, client))); - }) + .filter( + podInfo -> { + List> owners = + (List>) podInfo.get("owners"); + return owners.stream() + .anyMatch( + owner -> + resourceNamesAndKinds.contains( + findTopLevelOwner( + (String) owner.get("kind"), + (String) owner.get("name"), + namespace, + client))); + }) .collect(Collectors.toList()); } - private String findTopLevelOwner(String kind, String name, String namespace,KubernetesClient client) { - HasMetadata resource = fetchOwnerResource(namespace, kind, name,client); + private String findTopLevelOwner( + String kind, String name, String namespace, KubernetesClient client) { + HasMetadata resource = fetchOwnerResource(namespace, kind, name, client); while (resource != null && !resource.getMetadata().getOwnerReferences().isEmpty()) { OwnerReference ownerReference = resource.getMetadata().getOwnerReferences().get(0); - resource = fetchOwnerResource(namespace, ownerReference.getKind(), ownerReference.getName(),client); + resource = + fetchOwnerResource( + namespace, ownerReference.getKind(), ownerReference.getName(), client); } - return resource != null ? resource.getKind() + "/" + resource.getMetadata().getName() : null; + return resource != null + ? resource.getKind() + "/" + resource.getMetadata().getName() + : null; } @Override