diff --git a/src/main/router.ts b/src/main/router.ts index 9ee3a47c73..5ccd914593 100644 --- a/src/main/router.ts +++ b/src/main/router.ts @@ -123,7 +123,7 @@ export class Router { this.router.add({ method: "post", path: `${apiBase}/metrics` }, metricsRoute.routeMetrics.bind(metricsRoute)) // Port-forward API - this.router.add({ method: "post", path: `${apiBase}/services/{namespace}/{service}/port-forward/{port}` }, portForwardRoute.routeServicePortForward.bind(portForwardRoute)) + this.router.add({ method: 'post', path: `${apiBase}/pods/{namespace}/{resourceType}/{resourceName}/port-forward/{port}` }, portForwardRoute.routePortForward.bind(portForwardRoute)) // Helm API this.router.add({ method: "get", path: `${apiHelm}/v2/charts` }, helmApi.listCharts.bind(helmApi)) diff --git a/src/main/routes/port-forward.ts b/src/main/routes/port-forward.ts index 27b1158700..ca222596a1 100644 --- a/src/main/routes/port-forward.ts +++ b/src/main/routes/port-forward.ts @@ -14,7 +14,7 @@ class PortForward { return PortForward.portForwards.find((pf) => { return ( pf.clusterId == forward.clusterId && - pf.kind == "service" && + pf.kind == forward.kind && pf.name == forward.name && pf.namespace == forward.namespace && pf.port == forward.port @@ -42,7 +42,7 @@ class PortForward { "--kubeconfig", this.kubeConfig, "port-forward", "-n", this.namespace, - `service/${this.name}`, + `${this.kind}/${this.name}`, `${this.localPort}:${this.port}` ] @@ -72,21 +72,22 @@ class PortForward { class PortForwardRoute extends LensApi { - public async routeServicePortForward(request: LensApiRequest) { + public async routePortForward(request: LensApiRequest) { const { params, response, cluster} = request + const { namespace, port, resourceType, resourceName } = params let portForward = PortForward.getPortforward({ - clusterId: cluster.id, kind: "service", name: params.service, - namespace: params.namespace, port: params.port + clusterId: cluster.id, kind: resourceType, name: resourceName, + namespace: namespace, port: port }) if (!portForward) { - logger.info(`Creating a new port-forward ${params.namespace}/${params.service}:${params.port}`) + logger.info(`Creating a new port-forward ${namespace}/${resourceType}/${resourceName}:${port}`) portForward = new PortForward({ clusterId: cluster.id, - kind: "service", - namespace: params.namespace, - name: params.service, - port: params.port, + kind: resourceType, + namespace: namespace, + name: resourceName, + port: port, kubeConfig: cluster.proxyKubeconfigPath() }) const started = await portForward.start() diff --git a/src/renderer/components/+network-services/service-ports.tsx b/src/renderer/components/+network-services/service-ports.tsx index 3335be6907..1c9128892d 100644 --- a/src/renderer/components/+network-services/service-ports.tsx +++ b/src/renderer/components/+network-services/service-ports.tsx @@ -22,13 +22,13 @@ export class ServicePorts extends React.Component { async portForward(port: ServicePort) { const { service } = this.props; this.waiting = true; - apiBase.post(`/services/${service.getNs()}/${service.getName()}/port-forward/${port.port}`, {}) - .catch(error => { - Notifications.error(error); - }) - .finally(() => { - this.waiting = false; - }); + try { + await apiBase.post(`/pods/${service.getNs()}/service/${service.getName()}/port-forward/${port.port}`, {}) + } catch(error) { + Notifications.error(error); + } finally { + this.waiting = false; + } } render() { diff --git a/src/renderer/components/+workloads-pods/pod-container-ports.scss b/src/renderer/components/+workloads-pods/pod-container-ports.scss new file mode 100644 index 0000000000..0424c82125 --- /dev/null +++ b/src/renderer/components/+workloads-pods/pod-container-ports.scss @@ -0,0 +1,24 @@ +.PodContainerPorts { + &.waiting { + opacity: 0.5; + pointer-events: none; + } + + p { + &:not(:last-child) { + margin-bottom: $margin; + } + + span { + cursor: pointer; + color: $primary; + text-decoration: underline; + } + } + + .Spinner { + --spinner-size: #{$unit * 2}; + margin-left: $margin; + position: static; + } +} diff --git a/src/renderer/components/+workloads-pods/pod-container-ports.tsx b/src/renderer/components/+workloads-pods/pod-container-ports.tsx new file mode 100644 index 0000000000..0209a99dd5 --- /dev/null +++ b/src/renderer/components/+workloads-pods/pod-container-ports.tsx @@ -0,0 +1,57 @@ +import "./pod-container-ports.scss" + +import React from "react"; +import { observer } from "mobx-react"; +import { t } from "@lingui/macro"; +import { Pod, IPodContainer } from "../../api/endpoints"; +import { _i18n } from "../../i18n"; +import { apiBase } from "../../api" +import { observable } from "mobx"; +import { cssNames } from "../../utils"; +import { Notifications } from "../notifications"; +import { Spinner } from "../spinner" + +interface Props { + pod: Pod; + container: IPodContainer; +} + +@observer +export class PodContainerPorts extends React.Component { + @observable waiting = false; + + async portForward(port: number) { + const { pod } = this.props; + this.waiting = true; + try { + await apiBase.post(`/pods/${pod.getNs()}/pod/${pod.getName()}/port-forward/${port}`, {}) + } catch(error) { + Notifications.error(error); + } finally { + this.waiting = false; + } + } + + render() { + const { container } = this.props; + return ( +
+ { + container.ports.map((port) => { + const key = `${container.name}-port-${port.containerPort}-${port.protocol}` + const text = (port.name ? port.name + ': ' : '')+`${port.containerPort}/${port.protocol}` + return( +

+ this.portForward(port.containerPort) }> + {text} + {this.waiting && ( + + )} + +

+ ); + })} +
+ ); + } +} diff --git a/src/renderer/components/+workloads-pods/pod-details-container.tsx b/src/renderer/components/+workloads-pods/pod-details-container.tsx index a5cdcc1fbd..576b98581e 100644 --- a/src/renderer/components/+workloads-pods/pod-details-container.tsx +++ b/src/renderer/components/+workloads-pods/pod-details-container.tsx @@ -8,6 +8,7 @@ import { cssNames } from "../../utils"; import { StatusBrick } from "../status-brick"; import { Badge } from "../badge"; import { ContainerEnvironment } from "./pod-container-env"; +import { PodContainerPorts } from "./pod-container-ports"; import { ResourceMetrics } from "../resource-metrics"; import { IMetrics } from "../../api/endpoints/metrics.api"; import { ContainerCharts } from "./container-charts"; @@ -63,17 +64,7 @@ export class PodDetailsContainer extends React.Component { } {ports && ports.length > 0 && Ports}> - { - ports.map(port => { - const { name, containerPort, protocol } = port; - const key = `${container.name}-port-${containerPort}-${protocol}` - return ( -
- {name ? name + ': ' : ''}{containerPort}/{protocol} -
- ) - }) - } +
} {}