Compare commits

...

22 Commits
dev ... v0.0.1

Author SHA1 Message Date
djeinstine
af75f33e62 update kubernetes.md with gateway-api configuration. 2024-11-13 10:35:07 +00:00
djeinstine
c32f1f1d59 Merge branch 'gethomepage:dev' into integration 2024-11-13 10:33:10 +01:00
djeinstine
11c6f587ab Fix lint issues 2024-11-13 09:11:05 +00:00
djeinstine
a44e6a8f4b Fix null config issue 2024-11-13 09:08:27 +00:00
djeinstine
9b06761964 Fix linting issues 2024-11-13 09:03:39 +00:00
djeinstine
01e30f2ecb Fix linting issues 2024-11-13 08:17:41 +00:00
djeinstine
9326155ab8 Merge branch 'gethomepage:dev' into integration 2024-11-12 20:07:41 +01:00
djeinstine
11c3127aad Merge branch 'gethomepage:dev' into integration 2024-11-11 10:48:31 +01:00
djeinstine
94a934ec65 Applied pnpm prettier rules to code. 2024-11-11 09:31:18 +00:00
djeinstine
ac997ea841 Applied ESLint rules to code. Plus minor rewrite. 2024-11-11 09:29:47 +00:00
djeinstine
60eee26ac4 Add gateway api to docs. And ESLint rules. 2024-11-10 20:21:00 +00:00
djeinstine
c584d5d020 revert docker publish 2024-11-09 20:04:16 +00:00
djeinstine
3d462e5958 trigger docker action 2024-11-09 19:34:45 +00:00
djeinstine
bd1c11a716 trigger docker publish 2024-11-09 19:33:02 +00:00
djeinstine
bbb1ef5a55 Applied prettier to code 2024-11-09 19:30:09 +00:00
djeinstine
cb2c7b9147 fix linter error 2024-11-08 15:13:06 +00:00
djeinstine
d65cb638be Moved crd checker to kubernetes-routes 2024-11-08 15:08:01 +00:00
djeinstine
9367fd761b getUrlSchema now uses async call 2024-11-08 14:23:57 +00:00
djeinstine
29993dad3a Cleaned comments. 2024-11-07 19:52:39 +00:00
djeinstine
a15b5bd692 First step of integrating gateway-api with homepage. 2024-11-06 11:15:52 +00:00
djeinstine
f7810cb67a Merge remote-tracking branch 'origin/dev' into integration 2024-11-06 09:37:33 +00:00
djeinstine
02e1104452 replaced getKubeConfig with getKubeArguments to be in line with getDockerArguments 2024-10-17 13:56:35 +00:00
10 changed files with 333 additions and 158 deletions

View File

@@ -8,6 +8,7 @@ The Kubernetes connectivity has the following requirements:
- Kubernetes 1.19+ - Kubernetes 1.19+
- Metrics Service - Metrics Service
- An Ingress controller - An Ingress controller
- Optionally: Gateway-API
The Kubernetes connection is configured in the `kubernetes.yaml` file. There are 3 modes to choose from: The Kubernetes connection is configured in the `kubernetes.yaml` file. There are 3 modes to choose from:
@@ -19,6 +20,12 @@ The Kubernetes connection is configured in the `kubernetes.yaml` file. There are
mode: default mode: default
``` ```
To enable Kubernetes gateway-api compatibility, add the following setting:
```yaml
route: gateway
```
## Services ## Services
Once the Kubernetes connection is configured, individual services can be configured to pull statistics. Only CPU and Memory are currently supported. Once the Kubernetes connection is configured, individual services can be configured to pull statistics. Only CPU and Memory are currently supported.
@@ -140,6 +147,10 @@ spec:
If the `href` attribute is not present, Homepage will ignore the specific IngressRoute. If the `href` attribute is not present, Homepage will ignore the specific IngressRoute.
### Gateway API HttpRoute support
Homepage also features automatic service discovery for gateway-api. Service definitions are read by annotating the HttpRoute custom resource definition and are indentical to the Ingress example as defined in [Automatic Service Discovery](#automatic-service-discovery).
## Caveats ## Caveats
Similarly to Docker service discovery, there currently is no rigid ordering to discovered services and discovered services will be displayed above those specified in the `services.yaml`. Similarly to Docker service discovery, there currently is no rigid ordering to discovered services and discovered services will be displayed above those specified in the `services.yaml`.

View File

@@ -215,6 +215,15 @@ rules:
verbs: verbs:
- get - get
- list - list
# if using gateway api add the following:
# - apiGroups:
# - gateway.networking.k8s.io
# resources:
# - httproutes
# - gateways
# verbs:
# - get
# - list
- apiGroups: - apiGroups:
- metrics.k8s.io - metrics.k8s.io
resources: resources:

View File

@@ -23,6 +23,12 @@ Set the `mode` in the `kubernetes.yaml` to `cluster`.
mode: default mode: default
``` ```
To enable Kubernetes gateway-api compatibility, set `route` to `gateway`.
```yaml
route: gateway
```
## Widgets ## Widgets
The Kubernetes widget can show a high-level overview of the cluster, The Kubernetes widget can show a high-level overview of the cluster,

View File

@@ -1,6 +1,6 @@
import { CoreV1Api, Metrics } from "@kubernetes/client-node"; import { CoreV1Api, Metrics } from "@kubernetes/client-node";
import getKubeConfig from "../../../../utils/config/kubernetes"; import getKubeArguments from "../../../../utils/config/kubernetes";
import { parseCpu, parseMemory } from "../../../../utils/kubernetes/kubernetes-utils"; import { parseCpu, parseMemory } from "../../../../utils/kubernetes/kubernetes-utils";
import createLogger from "../../../../utils/logger"; import createLogger from "../../../../utils/logger";
@@ -20,7 +20,7 @@ export default async function handler(req, res) {
const labelSelector = podSelector !== undefined ? podSelector : `${APP_LABEL}=${appName}`; const labelSelector = podSelector !== undefined ? podSelector : `${APP_LABEL}=${appName}`;
try { try {
const kc = getKubeConfig(); const kc = getKubeArguments().config;
if (!kc) { if (!kc) {
res.status(500).send({ res.status(500).send({
error: "No kubernetes configuration", error: "No kubernetes configuration",

View File

@@ -1,6 +1,6 @@
import { CoreV1Api } from "@kubernetes/client-node"; import { CoreV1Api } from "@kubernetes/client-node";
import getKubeConfig from "../../../../utils/config/kubernetes"; import getKubeArguments from "../../../../utils/config/kubernetes";
import createLogger from "../../../../utils/logger"; import createLogger from "../../../../utils/logger";
const logger = createLogger("kubernetesStatusService"); const logger = createLogger("kubernetesStatusService");
@@ -18,7 +18,7 @@ export default async function handler(req, res) {
} }
const labelSelector = podSelector !== undefined ? podSelector : `${APP_LABEL}=${appName}`; const labelSelector = podSelector !== undefined ? podSelector : `${APP_LABEL}=${appName}`;
try { try {
const kc = getKubeConfig(); const kc = getKubeArguments().config;
if (!kc) { if (!kc) {
res.status(500).send({ res.status(500).send({
error: "No kubernetes configuration", error: "No kubernetes configuration",

View File

@@ -1,6 +1,6 @@
import { CoreV1Api, Metrics } from "@kubernetes/client-node"; import { CoreV1Api, Metrics } from "@kubernetes/client-node";
import getKubeConfig from "../../../utils/config/kubernetes"; import getKubeArguments from "../../../utils/config/kubernetes";
import { parseCpu, parseMemory } from "../../../utils/kubernetes/kubernetes-utils"; import { parseCpu, parseMemory } from "../../../utils/kubernetes/kubernetes-utils";
import createLogger from "../../../utils/logger"; import createLogger from "../../../utils/logger";
@@ -8,7 +8,7 @@ const logger = createLogger("kubernetes-widget");
export default async function handler(req, res) { export default async function handler(req, res) {
try { try {
const kc = getKubeConfig(); const kc = getKubeArguments().config;
if (!kc) { if (!kc) {
return res.status(500).send({ return res.status(500).send({
error: "No kubernetes configuration", error: "No kubernetes configuration",

View File

@@ -6,26 +6,50 @@ import { KubeConfig } from "@kubernetes/client-node";
import checkAndCopyConfig, { CONF_DIR, substituteEnvironmentVars } from "utils/config/config"; import checkAndCopyConfig, { CONF_DIR, substituteEnvironmentVars } from "utils/config/config";
export default function getKubeConfig() { const extractKubeData = (config) => {
// kubeconfig
const kc = new KubeConfig();
kc.loadFromCluster();
// route
let route = "ingress";
if (config?.route === "gateway") {
route = "gateway";
}
// traefik
let traefik = true;
if (config?.traefik === "disable") {
traefik = false;
}
return {
config: kc,
route,
traefik,
};
};
export default function getKubeArguments() {
checkAndCopyConfig("kubernetes.yaml"); checkAndCopyConfig("kubernetes.yaml");
const configFile = path.join(CONF_DIR, "kubernetes.yaml"); const configFile = path.join(CONF_DIR, "kubernetes.yaml");
const rawConfigData = readFileSync(configFile, "utf8"); const rawConfigData = readFileSync(configFile, "utf8");
const configData = substituteEnvironmentVars(rawConfigData); const configData = substituteEnvironmentVars(rawConfigData);
const config = yaml.load(configData); const config = yaml.load(configData);
const kc = new KubeConfig(); let kubeData;
switch (config?.mode) { switch (config?.mode) {
case "cluster": case "cluster":
kc.loadFromCluster(); kubeData = extractKubeData(config);
break; break;
case "default": case "default":
kc.loadFromDefault(); kubeData = extractKubeData(config);
break; break;
case "disabled": case "disabled":
default: default:
return null; kubeData = { config: null };
} }
return kc; return kubeData;
} }

View File

@@ -3,12 +3,11 @@ import path from "path";
import yaml from "js-yaml"; import yaml from "js-yaml";
import Docker from "dockerode"; import Docker from "dockerode";
import { CustomObjectsApi, NetworkingV1Api, ApiextensionsV1Api } from "@kubernetes/client-node";
import createLogger from "utils/logger"; import createLogger from "utils/logger";
import checkAndCopyConfig, { CONF_DIR, getSettings, substituteEnvironmentVars } from "utils/config/config"; import checkAndCopyConfig, { CONF_DIR, getSettings, substituteEnvironmentVars } from "utils/config/config";
import getDockerArguments from "utils/config/docker"; import getDockerArguments from "utils/config/docker";
import getKubeConfig from "utils/config/kubernetes"; import { getUrlSchema, getRouteList } from "utils/kubernetes/kubernetes-routes";
import * as shvl from "utils/config/shvl"; import * as shvl from "utils/config/shvl";
const logger = createLogger("service-helpers"); const logger = createLogger("service-helpers");
@@ -151,33 +150,6 @@ export async function servicesFromDocker() {
return mappedServiceGroups; return mappedServiceGroups;
} }
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}`;
}
export async function checkCRD(kc, name) {
const apiExtensions = kc.makeApiClient(ApiextensionsV1Api);
const exist = await apiExtensions
.readCustomResourceDefinitionStatus(name)
.then(() => true)
.catch(async (error) => {
if (error.statusCode === 403) {
logger.error(
"Error checking if CRD %s exists. Make sure to add the following permission to your RBAC: %d %s %s",
name,
error.statusCode,
error.body.message,
);
}
return false;
});
return exist;
}
export async function servicesFromKubernetes() { export async function servicesFromKubernetes() {
const ANNOTATION_BASE = "gethomepage.dev"; const ANNOTATION_BASE = "gethomepage.dev";
const ANNOTATION_WIDGET_BASE = `${ANNOTATION_BASE}/widget.`; const ANNOTATION_WIDGET_BASE = `${ANNOTATION_BASE}/widget.`;
@@ -186,128 +158,70 @@ export async function servicesFromKubernetes() {
checkAndCopyConfig("kubernetes.yaml"); checkAndCopyConfig("kubernetes.yaml");
try { try {
const kc = getKubeConfig(); const routeList = await getRouteList(ANNOTATION_BASE);
if (!kc) {
if (!routeList) {
return []; return [];
} }
const networking = kc.makeApiClient(NetworkingV1Api);
const crd = kc.makeApiClient(CustomObjectsApi);
const ingressList = await networking const services = await Promise.all(
.listIngressForAllNamespaces(null, null, null, null) routeList
.then((response) => response.body) .filter(
.catch((error) => { (route) =>
logger.error("Error getting ingresses: %d %s %s", error.statusCode, error.body, error.response); route.metadata.annotations &&
logger.debug(error); route.metadata.annotations[`${ANNOTATION_BASE}/enabled`] === "true" &&
return null; (!route.metadata.annotations[`${ANNOTATION_BASE}/instance`] ||
}); route.metadata.annotations[`${ANNOTATION_BASE}/instance`] === instanceName ||
`${ANNOTATION_BASE}/instance.${instanceName}` in route.metadata.annotations),
const traefikContainoExists = await checkCRD(kc, "ingressroutes.traefik.containo.us"); )
const traefikExists = await checkCRD(kc, "ingressroutes.traefik.io"); .map(async (route) => {
let constructedService = {
const traefikIngressListContaino = await crd app: route.metadata.annotations[`${ANNOTATION_BASE}/app`] || route.metadata.name,
.listClusterCustomObject("traefik.containo.us", "v1alpha1", "ingressroutes") namespace: route.metadata.namespace,
.then((response) => response.body) href: route.metadata.annotations[`${ANNOTATION_BASE}/href`] || (await getUrlSchema(route)),
.catch(async (error) => { name: route.metadata.annotations[`${ANNOTATION_BASE}/name`] || route.metadata.name,
if (traefikContainoExists) { group: route.metadata.annotations[`${ANNOTATION_BASE}/group`] || "Kubernetes",
logger.error( weight: route.metadata.annotations[`${ANNOTATION_BASE}/weight`] || "0",
"Error getting traefik ingresses from traefik.containo.us: %d %s %s", icon: route.metadata.annotations[`${ANNOTATION_BASE}/icon`] || "",
error.statusCode, description: route.metadata.annotations[`${ANNOTATION_BASE}/description`] || "",
error.body, external: false,
error.response, type: "service",
); };
logger.debug(error); if (route.metadata.annotations[`${ANNOTATION_BASE}/external`]) {
} constructedService.external =
String(route.metadata.annotations[`${ANNOTATION_BASE}/external`]).toLowerCase() === "true";
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[`${ANNOTATION_BASE}/href`],
);
ingressList.items.push(...traefikServices);
}
if (!ingressList) {
return [];
}
const services = ingressList.items
.filter(
(ingress) =>
ingress.metadata.annotations &&
ingress.metadata.annotations[`${ANNOTATION_BASE}/enabled`] === "true" &&
(!ingress.metadata.annotations[`${ANNOTATION_BASE}/instance`] ||
ingress.metadata.annotations[`${ANNOTATION_BASE}/instance`] === instanceName ||
`${ANNOTATION_BASE}/instance.${instanceName}` in ingress.metadata.annotations),
)
.map((ingress) => {
let constructedService = {
app: ingress.metadata.annotations[`${ANNOTATION_BASE}/app`] || ingress.metadata.name,
namespace: ingress.metadata.namespace,
href: ingress.metadata.annotations[`${ANNOTATION_BASE}/href`] || getUrlFromIngress(ingress),
name: ingress.metadata.annotations[`${ANNOTATION_BASE}/name`] || ingress.metadata.name,
group: ingress.metadata.annotations[`${ANNOTATION_BASE}/group`] || "Kubernetes",
weight: ingress.metadata.annotations[`${ANNOTATION_BASE}/weight`] || "0",
icon: ingress.metadata.annotations[`${ANNOTATION_BASE}/icon`] || "",
description: ingress.metadata.annotations[`${ANNOTATION_BASE}/description`] || "",
external: false,
type: "service",
};
if (ingress.metadata.annotations[`${ANNOTATION_BASE}/external`]) {
constructedService.external =
String(ingress.metadata.annotations[`${ANNOTATION_BASE}/external`]).toLowerCase() === "true";
}
if (ingress.metadata.annotations[`${ANNOTATION_BASE}/pod-selector`] !== undefined) {
constructedService.podSelector = ingress.metadata.annotations[`${ANNOTATION_BASE}/pod-selector`];
}
if (ingress.metadata.annotations[`${ANNOTATION_BASE}/ping`]) {
constructedService.ping = ingress.metadata.annotations[`${ANNOTATION_BASE}/ping`];
}
if (ingress.metadata.annotations[`${ANNOTATION_BASE}/siteMonitor`]) {
constructedService.siteMonitor = ingress.metadata.annotations[`${ANNOTATION_BASE}/siteMonitor`];
}
if (ingress.metadata.annotations[`${ANNOTATION_BASE}/statusStyle`]) {
constructedService.statusStyle = ingress.metadata.annotations[`${ANNOTATION_BASE}/statusStyle`];
}
Object.keys(ingress.metadata.annotations).forEach((annotation) => {
if (annotation.startsWith(ANNOTATION_WIDGET_BASE)) {
shvl.set(
constructedService,
annotation.replace(`${ANNOTATION_BASE}/`, ""),
ingress.metadata.annotations[annotation],
);
} }
}); if (route.metadata.annotations[`${ANNOTATION_BASE}/pod-selector`] !== undefined) {
constructedService.podSelector = route.metadata.annotations[`${ANNOTATION_BASE}/pod-selector`];
}
if (route.metadata.annotations[`${ANNOTATION_BASE}/ping`]) {
constructedService.ping = route.metadata.annotations[`${ANNOTATION_BASE}/ping`];
}
if (route.metadata.annotations[`${ANNOTATION_BASE}/siteMonitor`]) {
constructedService.siteMonitor = route.metadata.annotations[`${ANNOTATION_BASE}/siteMonitor`];
}
if (route.metadata.annotations[`${ANNOTATION_BASE}/statusStyle`]) {
constructedService.statusStyle = route.metadata.annotations[`${ANNOTATION_BASE}/statusStyle`];
}
Object.keys(route.metadata.annotations).forEach((annotation) => {
if (annotation.startsWith(ANNOTATION_WIDGET_BASE)) {
shvl.set(
constructedService,
annotation.replace(`${ANNOTATION_BASE}/`, ""),
route.metadata.annotations[annotation],
);
}
});
try { try {
constructedService = JSON.parse(substituteEnvironmentVars(JSON.stringify(constructedService))); constructedService = JSON.parse(substituteEnvironmentVars(JSON.stringify(constructedService)));
} catch (e) { } catch (e) {
logger.error("Error attempting k8s environment variable substitution."); logger.error("Error attempting k8s environment variable substitution.");
logger.debug(e); logger.debug(e);
} }
return constructedService;
return constructedService; }),
}); );
const mappedServiceGroups = []; const mappedServiceGroups = [];

View File

View File

@@ -0,0 +1,211 @@
import { CustomObjectsApi, NetworkingV1Api, CoreV1Api, ApiextensionsV1Api } from "@kubernetes/client-node";
import getKubeArguments from "utils/config/kubernetes";
import createLogger from "utils/logger";
const logger = createLogger("service-helpers");
const kubeArguments = getKubeArguments();
const kc = kubeArguments.config;
const apiGroup = "gateway.networking.k8s.io";
const version = "v1";
let crd;
let core;
let networking;
let routingType;
let traefik;
export async function checkCRD(name) {
const apiExtensions = kc.makeApiClient(ApiextensionsV1Api);
const exist = await apiExtensions
.readCustomResourceDefinitionStatus(name)
.then(() => true)
.catch(async (error) => {
if (error.statusCode === 403) {
logger.error(
"Error checking if CRD %s exists. Make sure to add the following permission to your RBAC: %d %s %s",
name,
error.statusCode,
error.body.message,
);
}
return false;
});
return exist;
}
const getSchemaFromGateway = async (gatewayRef) => {
const schema = await crd
.getNamespacedCustomObject(apiGroup, version, gatewayRef.namespace, "gateways", gatewayRef.name)
.then((response) => {
const listner = response.body.spec.listeners.filter((listener) => listener.name === gatewayRef.sectionName)[0];
return listner.protocol.toLowerCase();
})
.catch((error) => {
logger.error("Error getting gateways: %d %s %s", error.statusCode, error.body, error.response);
logger.debug(error);
return "";
});
return schema;
};
async function getUrlFromHttpRoute(ingress) {
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";
return `${urlSchema}://${urlHost}${urlPath}`;
}
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}`;
}
async function getHttpRouteList() {
// 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;
});
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;
}
async function getIngressList(ANNOTATION_BASE) {
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 traefikContainoExists = await checkCRD("ingressroutes.traefik.containo.us");
const traefikExists = await checkCRD("ingressroutes.traefik.io");
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[`${ANNOTATION_BASE}/href`],
);
ingressList.items.push(...traefikServices);
}
}
return ingressList.items;
}
export async function getRouteList(ANNOTATION_BASE) {
let routeList = [];
if (!kc) {
return [];
}
crd = kc.makeApiClient(CustomObjectsApi);
core = kc.makeApiClient(CoreV1Api);
networking = kc.makeApiClient(NetworkingV1Api);
routingType = kubeArguments.route;
traefik = kubeArguments.traefik;
switch (routingType) {
case "ingress":
routeList = await getIngressList(ANNOTATION_BASE);
break;
case "gateway":
routeList = await getHttpRouteList();
break;
default:
routeList = await getIngressList(ANNOTATION_BASE);
}
return routeList;
}
export async function getUrlSchema(route) {
let urlSchema;
switch (routingType) {
case "ingress":
urlSchema = getUrlFromIngress(route);
break;
case "gateway":
urlSchema = await getUrlFromHttpRoute(route);
break;
default:
urlSchema = getUrlFromIngress(route);
}
return urlSchema;
}