1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Add links for ingresses

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-01-05 10:08:35 -05:00
parent a76fc6df84
commit d8a50bc0ec
3 changed files with 89 additions and 71 deletions

View File

@ -4,7 +4,7 @@
*/
import { KubeObject } from "../kube-object";
import { autoBind } from "../../utils";
import { autoBind, iter } from "../../utils";
import { IMetrics, metricsApi } from "./metrics.api";
import { KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api";
@ -61,23 +61,30 @@ export interface IIngressService {
};
}
export const getBackendServiceNamePort = (backend: IIngressBackend) => {
/**
* Format an ingress backend into the name of the service and port
* @param backend The ingress target
*/
export function getBackendServiceNamePort(backend: IIngressBackend): string {
// .service is available with networking.k8s.io/v1, otherwise using extensions/v1beta1 interface
const serviceName = "service" in backend ? backend.service.name : backend.serviceName;
// Port is specified either with a number or name
const servicePort = "service" in backend ? backend.service.port.number ?? backend.service.port.name : backend.servicePort;
return { serviceName, servicePort };
};
if ("service" in backend) {
const { name, port } = backend.service;
return `${name}:${port.number ?? port.name}`;
}
return `${backend.serviceName}:${backend.servicePort}`;
}
export interface Ingress {
spec: {
tls: {
tls?: {
secretName: string;
}[];
rules?: {
host?: string;
http: {
http?: {
paths: {
path?: string;
backend: IIngressBackend;
@ -106,6 +113,11 @@ export interface Ingress {
};
}
export interface ComputedIngressRoute {
url: string;
service: string;
}
export class Ingress extends KubeObject {
static kind = "Ingress";
static namespaced = true;
@ -116,30 +128,22 @@ export class Ingress extends KubeObject {
autoBind(this);
}
getRoutes() {
const { spec: { tls, rules }} = this;
getRoutes(): string[] {
return this.getRouteDecls().map(({ url, service }) => `${url}${service}`);
}
if (!rules) return [];
getRouteDecls(): ComputedIngressRoute[] {
const { spec: { tls = [], rules = [] }} = this;
const protocol = tls.length === 0
? "http"
: "https";
let protocol = "http";
const routes: string[] = [];
if (tls && tls.length > 0) {
protocol += "s";
}
rules.map(rule => {
const host = rule.host ? rule.host : "*";
if (rule.http && rule.http.paths) {
rule.http.paths.forEach(path => {
const { serviceName, servicePort } = getBackendServiceNamePort(path.backend);
routes.push(`${protocol}://${host}${path.path || "/"}${serviceName}:${servicePort}`);
});
}
});
return routes;
return rules.flatMap(({ host = "*", http: { paths } = { paths: [] }}) => (
paths.map(({ path = "/", backend }) => ({
url: `${protocol}://${host}${path}`,
service: getBackendServiceNamePort(backend),
}))
));
}
getServiceNamePort(): IExtensionsBackend {
@ -155,11 +159,9 @@ export class Ingress extends KubeObject {
}
getHosts() {
const { spec: { rules }} = this;
const { spec: { rules = [] }} = this;
if (!rules) return [];
return rules.filter(rule => rule.host).map(rule => rule.host);
return [...iter.filterMap(rules, rule => rule.host)];
}
getPorts() {

View File

@ -49,44 +49,51 @@ export class IngressDetails extends React.Component<IngressDetailsProps> {
}
renderPaths(ingress: Ingress) {
const { spec: { rules }} = ingress;
const { spec: { rules = [], tls = [] }} = ingress;
const protocol = tls.length === 0
? "http"
: "https";
if (!rules || !rules.length) return null;
return rules.map((rule, index) => {
return (
<div className="rules" key={index}>
{rule.host && (
<div className="host-title">
<>Host: {rule.host}</>
</div>
)}
{rule.http && (
<Table className="paths">
<TableHead>
<TableCell className="path">Path</TableCell>
<TableCell className="backends">Backends</TableCell>
</TableHead>
{
rule.http.paths.map((path, index) => {
const { serviceName, servicePort } = getBackendServiceNamePort(path.backend);
const backend = `${serviceName}:${servicePort}`;
return rules.map((rule, index) => (
<div className="rules" key={index}>
{rule.host && (
<div className="host-title">
<>Host: {rule.host}</>
</div>
)}
{rule.http && (
<Table className="paths">
<TableHead>
<TableCell className="path">Path</TableCell>
<TableCell className="link">Link</TableCell>
<TableCell className="backends">Backends</TableCell>
</TableHead>
{
rule.http.paths
.map(({ path = "/", backend }, index) => {
const link = `${protocol}://${rule.host || "*"}${path}`;
return (
<TableRow key={index}>
<TableCell className="path">{path.path || ""}</TableCell>
<TableCell className="backends">
<p key={backend}>{backend}</p>
<TableCell className="path">{path}</TableCell>
<TableCell className="link">
<a
href={link}
rel="noreferrer"
target="_blank"
>
{link}
</a>
</TableCell>
<TableCell className="backends">{getBackendServiceNamePort(backend)}</TableCell>
</TableRow>
);
})
}
</Table>
)}
</div>
);
});
}
</Table>
)}
</div>
));
}
renderIngressPoints(ingressPoints: ILoadBalancerIngress[]) {
@ -99,15 +106,14 @@ export class IngressDetails extends React.Component<IngressDetailsProps> {
<TableCell className="name">Hostname</TableCell>
<TableCell className="ingresspoints">IP</TableCell>
</TableHead>
{ingressPoints.map(({ hostname, ip }, index) => {
return (
{
ingressPoints.map(({ hostname, ip }, index) => (
<TableRow key={index}>
<TableCell className="name">{hostname ? hostname : "-"}</TableCell>
<TableCell className="ingresspoints">{ip ? ip : "-"}</TableCell>
</TableRow>
);
})
})
))
}
</Table>
</div>
);

View File

@ -56,7 +56,17 @@ export class Ingresses extends React.Component<IngressesProps> {
<KubeObjectStatusIcon key="icon" object={ingress} />,
ingress.getNs(),
ingress.getLoadBalancers().map(lb => <p key={lb}>{lb}</p>),
ingress.getRoutes().map(route => <p key={route}>{route}</p>),
ingress.getRouteDecls().map(route => (
<a
key={route.url}
href={route.url}
rel="noreferrer"
target="_blank"
onClick={e => e.stopPropagation()}
>
{route.url}
</a>
)),
<KubeObjectAge key="age" object={ingress} />,
]}
tableProps={{