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

almost working

Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com>
This commit is contained in:
Jim Ehrismann 2021-12-06 19:30:14 -05:00
parent 879fc04c7d
commit 4f09e01c72
7 changed files with 87 additions and 31 deletions

View File

@ -21,7 +21,7 @@
import React from "react"; import React from "react";
import { boundMethod, cssNames } from "../../utils"; import { boundMethod, cssNames } from "../../utils";
import { openPortForward, PortForwardItem, removePortForward } from "../../port-forward"; import { openPortForward, PortForwardItem, removePortForward, startPortForward, stopPortForward } from "../../port-forward";
import { MenuActions, MenuActionsProps } from "../menu/menu-actions"; import { MenuActions, MenuActionsProps } from "../menu/menu-actions";
import { MenuItem } from "../menu"; import { MenuItem } from "../menu";
import { Icon } from "../icon"; import { Icon } from "../icon";
@ -45,6 +45,26 @@ export class PortForwardMenu extends React.Component<Props> {
} }
} }
renderStartStopMenuItem() {
const { portForward, toolbar } = this.props;
if (portForward.status === "Active") {
return (
<MenuItem onClick={() => stopPortForward(portForward)}>
<Icon material="stop" tooltip="Stop port-forward" interactive={toolbar} />
<span className="title">Stop</span>
</MenuItem>
);
}
return (
<MenuItem onClick={() => startPortForward(portForward)}>
<Icon material="play_arrow" tooltip="Start port-forward" interactive={toolbar} />
<span className="title">Start</span>
</MenuItem>
);
}
renderContent() { renderContent() {
const { portForward, toolbar } = this.props; const { portForward, toolbar } = this.props;
@ -60,6 +80,7 @@ export class PortForwardMenu extends React.Component<Props> {
<Icon material="edit" tooltip="Change port or protocol" interactive={toolbar} /> <Icon material="edit" tooltip="Change port or protocol" interactive={toolbar} />
<span className="title">Edit</span> <span className="title">Edit</span>
</MenuItem> </MenuItem>
{this.renderStartStopMenuItem()}
</> </>
); );
} }

View File

@ -51,7 +51,7 @@ export class ServicePortComponent extends React.Component<Props> {
componentDidMount() { componentDidMount() {
disposeOnUnmount(this, [ disposeOnUnmount(this, [
reaction(() => [portForwardStore.portForwards, this.props.service], () => this.checkExistingPortForwarding()), reaction(() => [portForwardStore.portForwards.slice(), this.props.service], () => this.checkExistingPortForwarding()),
]); ]);
} }

View File

@ -34,6 +34,7 @@ $service-status-color-list: (
$port-forward-status-color-list: ( $port-forward-status-color-list: (
active: var(--colorOk), active: var(--colorOk),
disabled: var(--colorSoftError)
); );
@mixin port-forward-status-colors { @mixin port-forward-status-colors {

View File

@ -55,7 +55,7 @@ export class PodContainerPort extends React.Component<Props> {
componentDidMount() { componentDidMount() {
disposeOnUnmount(this, [ disposeOnUnmount(this, [
reaction(() => [portForwardStore.portForwards, this.props.pod], () => this.checkExistingPortForwarding()), reaction(() => [portForwardStore.portForwards.slice(), this.props.pod], () => this.checkExistingPortForwarding()),
]); ]);
} }

View File

@ -25,7 +25,6 @@ import { autoBind } from "../../common/utils";
export type forwardedPortStatus = "Active" | "Disabled"; export type forwardedPortStatus = "Active" | "Disabled";
export interface ForwardedPort { export interface ForwardedPort {
clusterId?: string;
kind: string; kind: string;
namespace: string; namespace: string;
name: string; name: string;
@ -36,7 +35,6 @@ export interface ForwardedPort {
} }
export class PortForwardItem implements ItemObject { export class PortForwardItem implements ItemObject {
clusterId: string;
kind: string; kind: string;
namespace: string; namespace: string;
name: string; name: string;
@ -46,7 +44,6 @@ export class PortForwardItem implements ItemObject {
status: forwardedPortStatus; status: forwardedPortStatus;
constructor(pf: ForwardedPort) { constructor(pf: ForwardedPort) {
this.clusterId = pf.clusterId;
this.kind = pf.kind; this.kind = pf.kind;
this.namespace = pf.namespace; this.namespace = pf.namespace;
this.name = pf.name; this.name = pf.name;

View File

@ -35,7 +35,6 @@ export function openPortForward(portForward: ForwardedPort) {
openExternal(browseTo) openExternal(browseTo)
.catch(error => { .catch(error => {
logger.error(`failed to open in browser: ${error}`, { logger.error(`failed to open in browser: ${error}`, {
clusterId: portForward.clusterId,
port: portForward.port, port: portForward.port,
kind: portForward.kind, kind: portForward.kind,
namespace: portForward.namespace, namespace: portForward.namespace,

View File

@ -53,7 +53,7 @@ export class PortForwardStore extends ItemStore<PortForwardItem> {
for (const result of results) { for (const result of results) {
if (result.status === "rejected") { if (result.status === "rejected") {
Notifications.info("One or more port-forwards could not be started"); Notifications.error("One or more port-forwards could not be started", { timeout: 10_000 });
return; return;
} }
@ -105,7 +105,6 @@ interface PortForwardsResult {
function portForwardsEqual(portForward: ForwardedPort) { function portForwardsEqual(portForward: ForwardedPort) {
return (pf: ForwardedPort) => ( return (pf: ForwardedPort) => (
pf.clusterId == portForward.clusterId &&
pf.kind == portForward.kind && pf.kind == portForward.kind &&
pf.name == portForward.name && pf.name == portForward.name &&
pf.namespace == portForward.namespace && pf.namespace == portForward.namespace &&
@ -118,41 +117,65 @@ function findPortForward(portForward: ForwardedPort) {
} }
export async function addPortForward(portForward: ForwardedPort): Promise<number> { export async function startPortForward(portForward: ForwardedPort): Promise<number> {
const pf = findPortForward(portForward);
if (!pf) {
const error = new Error("port-forward not found");
logger.warn("[PORT-FORWARD-STORE] Error starting port-forward:", error, portForward);
throw(error);
}
const { port, forwardPort } = portForward; const { port, forwardPort } = portForward;
let response: PortForwardResult; let response: PortForwardResult;
try {
const protocol = portForward.protocol ?? "http";
response = await apiBase.post<PortForwardResult>(`/pods/port-forward/${portForward.namespace}/${portForward.kind}/${portForward.name}`, { query: { port, forwardPort, protocol }});
// expecting the received port to be the specified port, unless the specified port is 0, which indicates any available port is suitable
if (portForward.forwardPort && response?.port && response.port != +portForward.forwardPort) {
logger.warn(`[PORT-FORWARD-STORE] specified ${portForward.forwardPort}, got ${response.port}`);
}
pf.forwardPort = response.port;
pf.status = "Active";
} catch (error) {
logger.warn("[PORT-FORWARD-STORE] Error adding port-forward:", error, portForward);
pf.status = "Disabled";
throw (error);
}
return response?.port;
}
export async function addPortForward(portForward: ForwardedPort): Promise<number> {
const pf = findPortForward(portForward); const pf = findPortForward(portForward);
if (pf) { if (pf) {
return pf.forwardPort; return pf.forwardPort;
} }
portForwardStore.portForwards.push(new PortForwardItem(portForward));
if (!portForward.status) { if (!portForward.status) {
portForward.status = "Active"; portForward.status = "Active";
} }
try { try {
if (portForward.status === "Active") { if (portForward.status === "Active") {
const protocol = portForward.protocol ?? "http"; const port = await startPortForward(portForward);
response = await apiBase.post<PortForwardResult>(`/pods/port-forward/${portForward.namespace}/${portForward.kind}/${portForward.name}`, { query: { port, forwardPort, protocol }}); portForward.forwardPort = port;
// expecting the received port to be the specified port, unless the specified port is 0, which indicates any available port is suitable
if (portForward.forwardPort && response?.port && response.port != +portForward.forwardPort) {
logger.warn(`[PORT-FORWARD-STORE] specified ${portForward.forwardPort} got ${response.port}`);
}
portForward.forwardPort = response.port;
} }
} catch (error) { } catch (error) {
logger.warn("[PORT-FORWARD-STORE] Error starting port-forward:", error, portForward); logger.warn("[PORT-FORWARD-STORE] Error starting port-forward:", error, portForward);
portForward.status = "Disabled";
throw(error); throw(error);
} finally {
portForwardStore.portForwards.push(new PortForwardItem(portForward));
} }
return response?.port; return portForward.forwardPort;
} }
export async function getActivePortForward(portForward: ForwardedPort): Promise<number> { export async function getActivePortForward(portForward: ForwardedPort): Promise<number> {
@ -180,12 +203,15 @@ export async function getPortForward(portForward: ForwardedPort): Promise<number
throw (error); throw (error);
} }
let port = pf.port; let port = pf.forwardPort;
try { try {
port = await getActivePortForward(portForward); port = await getActivePortForward(portForward);
pf.status = "Active"; pf.status = "Active";
pf.forwardPort = port;
if (port !== pf.forwardPort) {
logger.warn(`[PORT-FORWARD-STORE] local port, expected ${pf.forwardPort}, got ${port}`);
}
} catch (error) { } catch (error) {
// port is not active // port is not active
pf.status = "Disabled"; pf.status = "Disabled";
@ -205,7 +231,17 @@ export async function modifyPortForward(portForward: ForwardedPort, desiredPort:
} }
export async function removeActivePortForward(portForward: ForwardedPort) { export async function stopPortForward(portForward: ForwardedPort) {
const pf = findPortForward(portForward);
if (!pf) {
const error = new Error("port-forward not found");
logger.warn("[PORT-FORWARD-STORE] Error getting port-forward:", error, portForward);
return;
}
const { port, forwardPort } = portForward; const { port, forwardPort } = portForward;
try { try {
@ -215,27 +251,29 @@ export async function removeActivePortForward(portForward: ForwardedPort) {
logger.warn("[PORT-FORWARD-STORE] Error removing active port-forward:", error, portForward); logger.warn("[PORT-FORWARD-STORE] Error removing active port-forward:", error, portForward);
throw (error); throw (error);
} }
pf.status = "Disabled";
} }
export async function removePortForward(portForward: ForwardedPort) { export async function removePortForward(portForward: ForwardedPort) {
const pf = findPortForward(portForward); const pf = findPortForward(portForward);
if (!pf) { if (!pf) {
const error = new Error("port-forward not found"); const error = new Error("port-forward not found");
logger.warn("[PORT-FORWARD-STORE] Error getting port-forward:", error, portForward); logger.warn("[PORT-FORWARD-STORE] Error getting port-forward:", error, portForward);
throw (error);
return;
} }
try { try {
await removeActivePortForward(portForward); await stopPortForward(portForward);
} catch (error) { } catch (error) {
if (pf.status === "Active") { if (pf.status === "Active") {
logger.warn("[PORT-FORWARD-STORE] Error removing port-forward:", error, portForward); logger.warn("[PORT-FORWARD-STORE] Error removing port-forward:", error, portForward);
} }
} }
portForwardStore.portForwards.filter(item => item !== pf); portForwardStore.portForwards = portForwardStore.portForwards.filter(item => item !== pf);
console.log("portForwards:", portForwardStore.portForwards);
} }
export async function getActivePortForwards(clusterId?: string): Promise<ForwardedPort[]> { export async function getActivePortForwards(clusterId?: string): Promise<ForwardedPort[]> {