Add gateway api to docs. And ESLint rules.

This commit is contained in:
djeinstine 2024-11-10 20:21:00 +00:00
parent c584d5d020
commit 60eee26ac4
5 changed files with 58 additions and 37 deletions

View File

@ -8,6 +8,7 @@ The Kubernetes connectivity has the following requirements:
- Kubernetes 1.19+
- Metrics Service
- An Ingress controller
- Optionally: Gateway-API
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
```
To enable Kubernetes gateway-api compatibility, add the following setting:
```yaml
route: gateway
```
## Services
Once the Kubernetes connection is configured, individual services can be configured to pull statistics. Only CPU and Memory are currently supported.
@ -140,6 +147,9 @@ spec:
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
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:
- get
- list
# if using gateway api add the following:
# - apiGroups:
# - gateway.networking.k8s.io
# resources:
# - httproutes
# - gateways
# verbs:
# - get
# - list
- apiGroups:
- metrics.k8s.io
resources:

View File

@ -7,30 +7,27 @@ import { KubeConfig } from "@kubernetes/client-node";
import checkAndCopyConfig, { CONF_DIR, substituteEnvironmentVars } from "utils/config/config";
const extractKubeData = (config) => {
//kubeconfig
// kubeconfig
const kc = new KubeConfig();
kc.loadFromCluster();
//route
// route
let route = "ingress";
if (config?.route == "gateway") {
if (config?.route === "gateway") {
route = "gateway";
}
//traefik
// traefik
let traefik = true;
if (config?.traefik == "disable") {
if (config?.traefik === "disable") {
traefik = false;
}
//traefik
let metrics = true;
if (config?.metrics == "disable") {
metrics = false;
}
//return
return { config: kc, route: route, traefik: traefik, metrics: metrics };
return {
"config": kc,
"route": route,
"traefik": traefik
};
};
export default function getKubeArguments() {

View File

@ -3,7 +3,6 @@ import path from "path";
import yaml from "js-yaml";
import Docker from "dockerode";
import { ApiextensionsV1Api } from "@kubernetes/client-node";
import createLogger from "utils/logger";
import checkAndCopyConfig, { CONF_DIR, getSettings, substituteEnvironmentVars } from "utils/config/config";
@ -159,7 +158,7 @@ export async function servicesFromKubernetes() {
checkAndCopyConfig("kubernetes.yaml");
try {
const routeList = await getRouteList();
const routeList = await getRouteList(ANNOTATION_BASE);
if (!routeList) {
return [];

View File

@ -1,4 +1,5 @@
import { CustomObjectsApi, NetworkingV1Api, CoreV1Api, ApiextensionsV1Api } from "@kubernetes/client-node";
import getKubeArguments from "utils/config/kubernetes";
import createLogger from "utils/logger";
@ -16,7 +17,7 @@ let networking;
let routingType;
let traefik;
export async function checkCRD(kc, name) {
export async function checkCRD(name) {
const apiExtensions = kc.makeApiClient(ApiextensionsV1Api);
const exist = await apiExtensions
.readCustomResourceDefinitionStatus(name)
@ -37,19 +38,24 @@ export async function checkCRD(kc, name) {
}
const getSchemaFromGateway = async (gatewayRef) => {
try {
const gateway = await crd.getNamespacedCustomObject(
apiGroup,
version,
gatewayRef.namespace,
"gateways",
gatewayRef.name,
);
const listener = gateway.body.spec.listeners.filter((listener) => listener.name == gatewayRef.sectionName)[0];
return listener.protocol.toLowerCase();
} catch (err) {
console.error(err);
}
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) {
@ -67,7 +73,7 @@ function getUrlFromIngress(ingress) {
}
async function getHttpRouteList() {
const httpRouteList = new Array();
const httpRouteList = [];
const namespaces = await core
.listNamespace()
@ -95,7 +101,7 @@ async function getHttpRouteList() {
return httpRouteList;
}
async function getIngressList() {
async function getIngressList(ANNOTATION_BASE) {
const ingressList = await networking
.listIngressForAllNamespaces(null, null, null, null)
.then((response) => response.body)
@ -106,8 +112,8 @@ async function getIngressList() {
});
if (traefik) {
const traefikContainoExists = await checkCRD(kc, "ingressroutes.traefik.containo.us");
const traefikExists = await checkCRD(kc, "ingressroutes.traefik.io");
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")
@ -156,8 +162,8 @@ async function getIngressList() {
return ingressList.items;
}
export async function getRouteList() {
let routeList = new Array();
export async function getRouteList(ANNOTATION_BASE) {
let routeList = [];
if (!kc) {
return [];
@ -172,13 +178,13 @@ export async function getRouteList() {
switch (routingType) {
case "ingress":
routeList = await getIngressList();
routeList = await getIngressList(ANNOTATION_BASE);
break;
case "gateway":
routeList = await getHttpRouteList();
break;
default:
routeList = await getIngressList();
routeList = await getIngressList(ANNOTATION_BASE);
}
return routeList;