Add gateway api to docs. And ESLint rules.
This commit is contained in:
parent
c584d5d020
commit
60eee26ac4
@ -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,9 @@ 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`.
|
||||||
|
|||||||
@ -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:
|
||||||
|
|||||||
@ -7,30 +7,27 @@ import { KubeConfig } from "@kubernetes/client-node";
|
|||||||
import checkAndCopyConfig, { CONF_DIR, substituteEnvironmentVars } from "utils/config/config";
|
import checkAndCopyConfig, { CONF_DIR, substituteEnvironmentVars } from "utils/config/config";
|
||||||
|
|
||||||
const extractKubeData = (config) => {
|
const extractKubeData = (config) => {
|
||||||
//kubeconfig
|
// kubeconfig
|
||||||
const kc = new KubeConfig();
|
const kc = new KubeConfig();
|
||||||
kc.loadFromCluster();
|
kc.loadFromCluster();
|
||||||
|
|
||||||
//route
|
// route
|
||||||
let route = "ingress";
|
let route = "ingress";
|
||||||
if (config?.route == "gateway") {
|
if (config?.route === "gateway") {
|
||||||
route = "gateway";
|
route = "gateway";
|
||||||
}
|
}
|
||||||
|
|
||||||
//traefik
|
// traefik
|
||||||
let traefik = true;
|
let traefik = true;
|
||||||
if (config?.traefik == "disable") {
|
if (config?.traefik === "disable") {
|
||||||
traefik = false;
|
traefik = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//traefik
|
return {
|
||||||
let metrics = true;
|
"config": kc,
|
||||||
if (config?.metrics == "disable") {
|
"route": route,
|
||||||
metrics = false;
|
"traefik": traefik
|
||||||
}
|
};
|
||||||
|
|
||||||
//return
|
|
||||||
return { config: kc, route: route, traefik: traefik, metrics: metrics };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function getKubeArguments() {
|
export default function getKubeArguments() {
|
||||||
|
|||||||
@ -3,7 +3,6 @@ import path from "path";
|
|||||||
|
|
||||||
import yaml from "js-yaml";
|
import yaml from "js-yaml";
|
||||||
import Docker from "dockerode";
|
import Docker from "dockerode";
|
||||||
import { 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";
|
||||||
@ -159,7 +158,7 @@ export async function servicesFromKubernetes() {
|
|||||||
checkAndCopyConfig("kubernetes.yaml");
|
checkAndCopyConfig("kubernetes.yaml");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const routeList = await getRouteList();
|
const routeList = await getRouteList(ANNOTATION_BASE);
|
||||||
|
|
||||||
if (!routeList) {
|
if (!routeList) {
|
||||||
return [];
|
return [];
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { CustomObjectsApi, NetworkingV1Api, CoreV1Api, ApiextensionsV1Api } from "@kubernetes/client-node";
|
import { CustomObjectsApi, NetworkingV1Api, CoreV1Api, ApiextensionsV1Api } from "@kubernetes/client-node";
|
||||||
|
|
||||||
import getKubeArguments from "utils/config/kubernetes";
|
import getKubeArguments from "utils/config/kubernetes";
|
||||||
import createLogger from "utils/logger";
|
import createLogger from "utils/logger";
|
||||||
|
|
||||||
@ -16,7 +17,7 @@ let networking;
|
|||||||
let routingType;
|
let routingType;
|
||||||
let traefik;
|
let traefik;
|
||||||
|
|
||||||
export async function checkCRD(kc, name) {
|
export async function checkCRD(name) {
|
||||||
const apiExtensions = kc.makeApiClient(ApiextensionsV1Api);
|
const apiExtensions = kc.makeApiClient(ApiextensionsV1Api);
|
||||||
const exist = await apiExtensions
|
const exist = await apiExtensions
|
||||||
.readCustomResourceDefinitionStatus(name)
|
.readCustomResourceDefinitionStatus(name)
|
||||||
@ -37,19 +38,24 @@ export async function checkCRD(kc, name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const getSchemaFromGateway = async (gatewayRef) => {
|
const getSchemaFromGateway = async (gatewayRef) => {
|
||||||
try {
|
|
||||||
const gateway = await crd.getNamespacedCustomObject(
|
const schema = await crd.getNamespacedCustomObject(
|
||||||
apiGroup,
|
apiGroup,
|
||||||
version,
|
version,
|
||||||
gatewayRef.namespace,
|
gatewayRef.namespace,
|
||||||
"gateways",
|
"gateways",
|
||||||
gatewayRef.name,
|
gatewayRef.name,
|
||||||
);
|
)
|
||||||
const listener = gateway.body.spec.listeners.filter((listener) => listener.name == gatewayRef.sectionName)[0];
|
.then((response) => {
|
||||||
return listener.protocol.toLowerCase();
|
const listner = response.body.spec.listeners.filter((listener) => listener.name === gatewayRef.sectionName)[0]
|
||||||
} catch (err) {
|
return listner.protocol.toLowerCase();
|
||||||
console.error(err);
|
})
|
||||||
}
|
.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) {
|
async function getUrlFromHttpRoute(ingress) {
|
||||||
@ -67,7 +73,7 @@ function getUrlFromIngress(ingress) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function getHttpRouteList() {
|
async function getHttpRouteList() {
|
||||||
const httpRouteList = new Array();
|
const httpRouteList = [];
|
||||||
|
|
||||||
const namespaces = await core
|
const namespaces = await core
|
||||||
.listNamespace()
|
.listNamespace()
|
||||||
@ -95,7 +101,7 @@ async function getHttpRouteList() {
|
|||||||
return httpRouteList;
|
return httpRouteList;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getIngressList() {
|
async function getIngressList(ANNOTATION_BASE) {
|
||||||
const ingressList = await networking
|
const ingressList = await networking
|
||||||
.listIngressForAllNamespaces(null, null, null, null)
|
.listIngressForAllNamespaces(null, null, null, null)
|
||||||
.then((response) => response.body)
|
.then((response) => response.body)
|
||||||
@ -106,8 +112,8 @@ async function getIngressList() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (traefik) {
|
if (traefik) {
|
||||||
const traefikContainoExists = await checkCRD(kc, "ingressroutes.traefik.containo.us");
|
const traefikContainoExists = await checkCRD("ingressroutes.traefik.containo.us");
|
||||||
const traefikExists = await checkCRD(kc, "ingressroutes.traefik.io");
|
const traefikExists = await checkCRD("ingressroutes.traefik.io");
|
||||||
|
|
||||||
const traefikIngressListContaino = await crd
|
const traefikIngressListContaino = await crd
|
||||||
.listClusterCustomObject("traefik.containo.us", "v1alpha1", "ingressroutes")
|
.listClusterCustomObject("traefik.containo.us", "v1alpha1", "ingressroutes")
|
||||||
@ -156,8 +162,8 @@ async function getIngressList() {
|
|||||||
return ingressList.items;
|
return ingressList.items;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getRouteList() {
|
export async function getRouteList(ANNOTATION_BASE) {
|
||||||
let routeList = new Array();
|
let routeList = [];
|
||||||
|
|
||||||
if (!kc) {
|
if (!kc) {
|
||||||
return [];
|
return [];
|
||||||
@ -172,13 +178,13 @@ export async function getRouteList() {
|
|||||||
|
|
||||||
switch (routingType) {
|
switch (routingType) {
|
||||||
case "ingress":
|
case "ingress":
|
||||||
routeList = await getIngressList();
|
routeList = await getIngressList(ANNOTATION_BASE);
|
||||||
break;
|
break;
|
||||||
case "gateway":
|
case "gateway":
|
||||||
routeList = await getHttpRouteList();
|
routeList = await getHttpRouteList();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
routeList = await getIngressList();
|
routeList = await getIngressList(ANNOTATION_BASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return routeList;
|
return routeList;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user