services need to be awaited as they are now promises. Also cleaned up ANNOTATION_BASE constant

This commit is contained in:
djeinstine
2025-02-10 13:19:30 +00:00
parent 6cf702684b
commit 702a547de4
3 changed files with 226 additions and 203 deletions

View File

@@ -191,32 +191,33 @@ export async function servicesFromKubernetes() {
if (!resources) {
return [];
}
const services = resources
const services = await Promise.all( resources
.filter(resource => kubernetes.isDiscoverable(resource, instanceName))
.map(resource => kubernetes.constructedServiceFromResource(resource));
.map(async (resource) => kubernetes.constructedServiceFromResource(resource)));
// const mappedServiceGroups = services.reduce((groups, serverService) => {
// let serverGroup = groups.find(group => group.name === serverService.group);
const mappedServiceGroups = services.reduce((groups, serverService) => {
let serverGroup = groups.find(group => group.name === serverService.group);
// if (!serverGroup) {
// serverGroup = {
// name: serverService.group,
// services: []
// };
// groups.push(serverGroup);
// }
if (!serverGroup) {
serverGroup = {
name: serverService.group,
services: []
};
groups.push(serverGroup);
}
// const { name: serviceName, group: _, ...pushedService } = serverService;
const { name: serviceName, group: _, ...pushedService } = serverService;
// serverGroup.services.push({
// name: serviceName,
// ...pushedService
// });
serverGroup.services.push({
name: serviceName,
...pushedService
});
// return groups;
// }, []);
return groups;
}, []);
// console.log(mappedServiceGroups);
// const routeList = await getRouteList(ANNOTATION_BASE);
// if (!routeList) {
@@ -282,26 +283,26 @@ export async function servicesFromKubernetes() {
// }),
// );
const mappedServiceGroups = [];
// const mappedServiceGroups = [];
services.forEach((serverService) => {
let serverGroup = mappedServiceGroups.find((searchedGroup) => searchedGroup.name === serverService.group);
if (!serverGroup) {
mappedServiceGroups.push({
name: serverService.group,
services: [],
});
serverGroup = mappedServiceGroups[mappedServiceGroups.length - 1];
}
// services.forEach((serverService) => {
// let serverGroup = mappedServiceGroups.find((searchedGroup) => searchedGroup.name === serverService.group);
// if (!serverGroup) {
// mappedServiceGroups.push({
// name: serverService.group,
// services: [],
// });
// serverGroup = mappedServiceGroups[mappedServiceGroups.length - 1];
// }
const { name: serviceName, group: serverServiceGroup, ...pushedService } = serverService;
const result = {
name: serviceName,
...pushedService,
};
// const { name: serviceName, group: serverServiceGroup, ...pushedService } = serverService;
// const result = {
// name: serviceName,
// ...pushedService,
// };
serverGroup.services.push(result);
});
// serverGroup.services.push(result);
// });
return mappedServiceGroups;
} catch (e) {

View File

@@ -1,6 +1,6 @@
import { CustomObjectsApi, NetworkingV1Api, CoreV1Api } from "@kubernetes/client-node";
import { CustomObjectsApi } from "@kubernetes/client-node";
import getKubeArguments,{checkCRD} from "utils/config/kubernetes";
import getKubeArguments from "utils/config/kubernetes";
import createLogger from "utils/logger";
const logger = createLogger("service-helpers");
@@ -27,172 +27,196 @@ const getSchemaFromGateway = async (gatewayRef) => {
return schema;
};
async function getUrlFromHttpRoute(ingress) {
let url = null
if (ingress.spec.has("hostnames")) {
if (ingress.spec.rules[0].matches[0].path.type!=="RegularExpression"){
const urlHost = ingress.spec.hostnames[0];
const urlPath = ingress.spec.rules[0].matches[0].path.value;
const urlSchema = (await getSchemaFromGateway(ingress.spec.parentRefs[0])) ? "https" : "http";
async function getUrlFromHttpRoute(resource) {
let url = null;
const hasHostName = resource.spec?.hostnames;
const isHttpRoute = resource.kind === "HTTPRoute";
if (isHttpRoute && hasHostName) {
if (resource.spec.rules[0].matches[0].path.type!=="RegularExpression"){
const urlHost = resource.spec.hostnames[0];
const urlPath = resource.spec.rules[0].matches[0].path.value;
const urlSchema = (await getSchemaFromGateway(resource.spec.parentRefs[0])) ? "https" : "http";
url = `${urlSchema}://${urlHost}${urlPath}`;
}
}
return url;
};
}
function getUrlFromIngress(ingress) {
const urlHost = ingress.spec.rules[0].host;
const urlPath = ingress.spec.rules[0].http.paths[0].path;
const urlSchema = ingress.spec.tls ? "https" : "http";
return `${urlSchema}://${urlHost}${urlPath}`;
};
function getUrlFromIngress(resource) {
const isNotHttpRoute = resource.kind !== "HTTPRoute";
let url = null
async function getHttpRouteList() {
if (isNotHttpRoute){
const urlHost = resource.spec.rules[0].host;
const urlPath = resource.spec.rules[0].http.paths[0].path;
const urlSchema = resource.spec.tls ? "https" : "http";
url = `${urlSchema}://${urlHost}${urlPath}`;
}
return url;
}
// async function getHttpRouteList() {
const crd = kc.makeApiClient(CustomObjectsApi);
const core = kc.makeApiClient(CoreV1Api);
// const crd = kc.makeApiClient(CustomObjectsApi);
// const core = kc.makeApiClient(CoreV1Api);
// 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;
});
// // 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;
});
// // 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;
// });
let httpRouteList = [];
if (namespaces) {
const httpRouteListUnfiltered = await Promise.all(
namespaces.map(async (namespace) => {
const httpRoute = await getHttpRoute(namespace);
return httpRoute;
}),
);
// let httpRouteList = [];
// 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;
};
// httpRouteList = httpRouteListUnfiltered.filter((httpRoute) => httpRoute !== undefined);
// }
// return httpRouteList;
// }
async function getIngressList(annotationBase) {
// async function getIngressList(annotationBase) {
const {traefik} = kubeArguments;
const networking = kc.makeApiClient(NetworkingV1Api);
// const { traefik } = kubeArguments;
// 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;
});
// 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;
// });
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);
// 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);
}
// 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 [];
});
// 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);
}
// 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 [];
});
// return [];
// });
const traefikIngressList = [...(traefikIngressListContaino?.items ?? []), ...(traefikIngressListIo?.items ?? [])];
// const traefikIngressList = [...(traefikIngressListContaino?.items ?? []), ...(traefikIngressListIo?.items ?? [])];
if (traefikIngressList.length > 0) {
const traefikServices = traefikIngressList.filter(
(ingress) => ingress.metadata.annotations && ingress.metadata.annotations[`${annotationBase}/href`],
);
ingressList.items.push(...traefikServices);
}
}
// if (traefikIngressList.length > 0) {
// const traefikServices = traefikIngressList.filter(
// (ingress) => ingress.metadata.annotations && ingress.metadata.annotations[`${annotationBase}/href`],
// );
// ingressList.items.push(...traefikServices);
// }
// }
return ingressList.items;
};
// return ingressList.items;
// }
export async function getRouteList(annotationBase) {
let routeList = [];
// export async function getRouteList(annotationBase) {
// let routeList = [];
if (!kc) {
return [];
}
// if (!kc) {
// return [];
// }
const routingType = kubeArguments.route;
// if (kubeArguments.ingress){
// routeList = await getIngressList(annotationBase);
// }else if (kubeArguments.gateway) {
// routeList = await getHttpRouteList();
// }else{
// routeList = await getIngressList(annotationBase);
// }
switch (routingType) {
case "ingress":
routeList = await getIngressList(annotationBase);
break;
case "gateway":
routeList = await getHttpRouteList();
break;
default:
routeList = await getIngressList(annotationBase);
}
// // const routingType = kubeArguments.route;
return routeList;
};
// // switch (routingType) {
// // case "ingress":
// // routeList = await getIngressList(annotationBase);
// // break;
// // case "gateway":
// // routeList = await getHttpRouteList();
// // break;
// // default:
// // routeList = await getIngressList(annotationBase);
// // }
export async function getUrlSchema(route) {
// return routeList;
// }
export default async function getUrlSchema(resource) {
let urlSchema;
const routingType = kubeArguments.route;
switch (routingType) {
case "ingress":
urlSchema = getUrlFromIngress(route);
break;
case "gateway":
urlSchema = await getUrlFromHttpRoute(route);
break;
default:
urlSchema = getUrlFromIngress(route);
if (kubeArguments.ingress){
urlSchema = getUrlFromIngress(resource);
}else if (kubeArguments.gateway){
urlSchema = await getUrlFromHttpRoute(resource);
}else{
urlSchema = getUrlFromIngress(resource);
}
// const routingType = kubeArguments.route;
// switch (routingType) {
// case "ingress":
// urlSchema = getUrlFromIngress(route);
// break;
// case "gateway":
// urlSchema = await getUrlFromHttpRoute(route);
// break;
// default:
// urlSchema = getUrlFromIngress(route);
// }
return urlSchema;
};
}

View File

@@ -1,49 +1,47 @@
import getUrlSchema from "utils/kubernetes/kubernetes-routes";
import { substituteEnvironmentVars } from "utils/config/config";
import { ANNOTATION_BASE,ANNOTATION_WIDGET_BASE } from "utils/config/kubernetes";
import createLogger from "utils/logger";
import * as shvl from "utils/config/shvl";
const logger = createLogger("resource-helpers");
export function isDiscoverable(resource,instanceName,annotationBase) {
export function isDiscoverable(resource,instanceName) {
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.`;
resource.metadata.annotations[`${ANNOTATION_BASE}/enabled`] === "true" &&
(!resource.metadata.annotations[`${ANNOTATION_BASE}/instance`] ||
resource.metadata.annotations[`${ANNOTATION_BASE}/instance`] === instanceName ||
`${ANNOTATION_BASE}/instance.${instanceName}` in resource.metadata.annotations)
};
export async function constructedServiceFromResource (resource){
let constructedService = {
app: resource.metadata.annotations[`${annotationBase}/app`] || resource.metadata.name,
app: resource.metadata.annotations[`${ANNOTATION_BASE}/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`] || "",
href: resource.metadata.annotations[`${ANNOTATION_BASE}/href`] || (await getUrlSchema(resource)),
name: resource.metadata.annotations[`${ANNOTATION_BASE}/name`] || resource.metadata.name,
group: resource.metadata.annotations[`${ANNOTATION_BASE}/group`] || "Kubernetes",
weight: resource.metadata.annotations[`${ANNOTATION_BASE}/weight`] || "0",
icon: resource.metadata.annotations[`${ANNOTATION_BASE}/icon`] || "",
description: resource.metadata.annotations[`${ANNOTATION_BASE}/description`] || "",
external: false,
type: "service",
};
if (resource.metadata.annotations[`${annotationBase}/external`]) {
if (resource.metadata.annotations[`${ANNOTATION_BASE}/external`]) {
constructedService.external =
String(resource.metadata.annotations[`${annotationBase}/external`]).toLowerCase() === "true";
String(resource.metadata.annotations[`${ANNOTATION_BASE}/external`]).toLowerCase() === "true";
}
if (resource.metadata.annotations[`${annotationBase}/pod-selector`] !== undefined) {
constructedService.podSelector = resource.metadata.annotations[`${annotationBase}/pod-selector`];
if (resource.metadata.annotations[`${ANNOTATION_BASE}/pod-selector`] !== undefined) {
constructedService.podSelector = resource.metadata.annotations[`${ANNOTATION_BASE}/pod-selector`];
}
if (resource.metadata.annotations[`${annotationBase}/ping`]) {
constructedService.ping = resource.metadata.annotations[`${annotationBase}/ping`];
if (resource.metadata.annotations[`${ANNOTATION_BASE}/ping`]) {
constructedService.ping = resource.metadata.annotations[`${ANNOTATION_BASE}/ping`];
}
if (resource.metadata.annotations[`${annotationBase}/siteMonitor`]) {
constructedService.siteMonitor = resource.metadata.annotations[`${annotationBase}/siteMonitor`];
if (resource.metadata.annotations[`${ANNOTATION_BASE}/siteMonitor`]) {
constructedService.siteMonitor = resource.metadata.annotations[`${ANNOTATION_BASE}/siteMonitor`];
}
if (resource.metadata.annotations[`${annotationBase}/statusStyle`]) {
constructedService.statusStyle = resource.metadata.annotations[`${annotationBase}/statusStyle`];
if (resource.metadata.annotations[`${ANNOTATION_BASE}/statusStyle`]) {
constructedService.statusStyle = resource.metadata.annotations[`${ANNOTATION_BASE}/statusStyle`];
}
Object
@@ -52,7 +50,7 @@ export async function constructedServiceFromResource (resource,annotationBase){
if (annotation.startsWith(ANNOTATION_WIDGET_BASE)) {
shvl.set(
constructedService,
annotation.replace(`${annotationBase}/`, ""),
annotation.replace(`${ANNOTATION_BASE}/`, ""),
resource.metadata.annotations[annotation],
);
}