diff --git a/src/utils/kubernetes/kubernetes-crd.js b/src/utils/kubernetes/kubernetes-crd.js deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/utils/kubernetes/kubernetes-httproute-list.js b/src/utils/kubernetes/kubernetes-httproute-list.js new file mode 100644 index 00000000000..a92db429b2a --- /dev/null +++ b/src/utils/kubernetes/kubernetes-httproute-list.js @@ -0,0 +1,50 @@ + +import { CustomObjectsApi, CoreV1Api } from "@kubernetes/client-node"; +import createLogger from "utils/logger"; + + + +export async function getHttpRouteList(kc) { + + const logger = createLogger("service-helpers"); + const crd = kc.makeApiClient(CustomObjectsApi); + const core = kc.makeApiClient(CoreV1Api); + let httpRouteList = []; + + // httproutes + const getHttpRoute = async (namespace) => + crd + .listNamespacedCustomObject(apiGroup, version, namespace, "httproutes") + .then((response) => { + const [httpRoute] = response.body.items; + return httpRoute; + }) + .catch((error) => { + logger.error("Error getting httproutes: %d %s %s", error.statusCode, error.body, error.response); + logger.debug(error); + return null; + }); + + // namespaces + const namespaces = await core + .listNamespace() + .then((response) => response.body.items.map((ns) => ns.metadata.name)) + .catch((error) => { + logger.error("Error getting namespaces: %d %s %s", error.statusCode, error.body, error.response); + logger.debug(error); + return null; + }); + + if (namespaces) { + const httpRouteListUnfiltered = await Promise.all( + namespaces.map(async (namespace) => { + const httpRoute = await getHttpRoute(namespace); + return httpRoute; + }), + ); + + httpRouteList = httpRouteListUnfiltered.filter((httpRoute) => httpRoute !== undefined); + } + + return httpRouteList; +} \ No newline at end of file diff --git a/src/utils/kubernetes/kubernetes-ingress-list.js b/src/utils/kubernetes/kubernetes-ingress-list.js new file mode 100644 index 00000000000..c0db16c8ab0 --- /dev/null +++ b/src/utils/kubernetes/kubernetes-ingress-list.js @@ -0,0 +1,18 @@ +import NetworkingV1Api from "@kubernetes/client-node"; + + +export async function listIngress(kc) { + + const networking = kc.makeApiClient(NetworkingV1Api); + + const ingressList = await networking + .listIngressForAllNamespaces(null, null, null, null) + .then((response) => response.body) + .catch((error) => { + logger.error("Error getting ingresses: %d %s %s", error.statusCode, error.body, error.response); + logger.debug(error); + return null; + }); + + return ingressList; +} \ No newline at end of file diff --git a/src/utils/kubernetes/kubernetes-service-helpers.js b/src/utils/kubernetes/kubernetes-service-helpers.js new file mode 100644 index 00000000000..d83c2448d0c --- /dev/null +++ b/src/utils/kubernetes/kubernetes-service-helpers.js @@ -0,0 +1,64 @@ +import getUrlSchema from "utils/kubernetes/kubernetes-routes"; + +export function isDiscoverable(resource,instanceName,annotationBase) { + return resource.metadata.annotations && + resource.metadata.annotations[`${annotationBase}/enabled`] === "true" && + (!resource.metadata.annotations[`${annotationBase}/instance`] || + resource.metadata.annotations[`${annotationBase}/instance`] === instanceName || + `${annotationBase}/instance.${instanceName}` in resource.metadata.annotations) +} + +export async function constructedServiceFromResource (resource,annotationBase){ + + const ANNOTATION_WIDGET_BASE = `${annotationBase}/widget.`; + + let constructedService = { + app: resource.metadata.annotations[`${annotationBase}/app`] || resource.metadata.name, + namespace: resource.metadata.namespace, + href: resource.metadata.annotations[`${annotationBase}/href`] || (await getUrlSchema(resource)), + name: resource.metadata.annotations[`${annotationBase}/name`] || resource.metadata.name, + group: resource.metadata.annotations[`${annotationBase}/group`] || "Kubernetes", + weight: resource.metadata.annotations[`${annotationBase}/weight`] || "0", + icon: resource.metadata.annotations[`${annotationBase}/icon`] || "", + description: resource.metadata.annotations[`${annotationBase}/description`] || "", + external: false, + type: "service", + }; + if (resource.metadata.annotations[`${annotationBase}/external`]) { + constructedService.external = + String(resource.metadata.annotations[`${annotationBase}/external`]).toLowerCase() === "true"; + } + if (resource.metadata.annotations[`${annotationBase}/pod-selector`] !== undefined) { + constructedService.podSelector = resource.metadata.annotations[`${annotationBase}/pod-selector`]; + } + if (resource.metadata.annotations[`${annotationBase}/ping`]) { + constructedService.ping = resource.metadata.annotations[`${annotationBase}/ping`]; + } + if (resource.metadata.annotations[`${annotationBase}/siteMonitor`]) { + constructedService.siteMonitor = resource.metadata.annotations[`${annotationBase}/siteMonitor`]; + } + if (resource.metadata.annotations[`${annotationBase}/statusStyle`]) { + constructedService.statusStyle = resource.metadata.annotations[`${annotationBase}/statusStyle`]; + } + + Object + .keys(resource.metadata.annotations) + .forEach((annotation) => { + if (annotation.startsWith(ANNOTATION_WIDGET_BASE)) { + shvl.set( + constructedService, + annotation.replace(`${annotationBase}/`, ""), + resource.metadata.annotations[annotation], + ); + } + }); + + try { + constructedService = JSON.parse(substituteEnvironmentVars(JSON.stringify(constructedService))); + } catch (e) { + logger.error("Error attempting k8s environment variable substitution."); + logger.debug(e); + } + + return constructedService; +} \ No newline at end of file diff --git a/src/utils/kubernetes/kubernetes-traefik-list.js b/src/utils/kubernetes/kubernetes-traefik-list.js new file mode 100644 index 00000000000..4129cd63664 --- /dev/null +++ b/src/utils/kubernetes/kubernetes-traefik-list.js @@ -0,0 +1,60 @@ +import CustomObjectsApi from "@kubernetes/client-node"; +import createLogger from "utils/logger"; + +export async function listIngress(annotationBase,kc) { + + const logger = createLogger("service-helpers"); + const traefik = kubeArguments.traefik; + let traefikList = []; + + if (traefik) { + const crd = kc.makeApiClient(CustomObjectsApi); + const traefikContainoExists = await checkCRD("ingressroutes.traefik.containo.us",kc,logger); + const traefikExists = await checkCRD("ingressroutes.traefik.io",kc,logger); + + const traefikIngressListContaino = await crd + .listClusterCustomObject("traefik.containo.us", "v1alpha1", "ingressroutes") + .then((response) => response.body) + .catch(async (error) => { + if (traefikContainoExists) { + logger.error( + "Error getting traefik ingresses from traefik.containo.us: %d %s %s", + error.statusCode, + error.body, + error.response, + ); + logger.debug(error); + } + + return []; + }); + + const traefikIngressListIo = await crd + .listClusterCustomObject("traefik.io", "v1alpha1", "ingressroutes") + .then((response) => response.body) + .catch(async (error) => { + if (traefikExists) { + logger.error( + "Error getting traefik ingresses from traefik.io: %d %s %s", + error.statusCode, + error.body, + error.response, + ); + logger.debug(error); + } + + return []; + }); + + const traefikIngressList = [...(traefikIngressListContaino?.items ?? []), ...(traefikIngressListIo?.items ?? [])]; + + if (traefikIngressList.length > 0) { + const traefikServices = traefikIngressList.filter( + (ingress) => ingress.metadata.annotations && ingress.metadata.annotations[`${annotationBase}/href`], + ); + traefikList.items.push(...traefikServices); + } + } + + return traefikList; +} \ No newline at end of file