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

addressed some review comments

Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com>
This commit is contained in:
Jim Ehrismann 2021-10-04 21:56:03 -04:00
parent 0058e9f0e2
commit 6d63c39b11
9 changed files with 80 additions and 109 deletions

View File

@ -23,11 +23,10 @@ import type { RouteProps } from "react-router";
import { buildURL } from "../utils/buildUrl"; import { buildURL } from "../utils/buildUrl";
export const portForwardsRoute: RouteProps = { export const portForwardsRoute: RouteProps = {
path: "/port-forwards/:forwardport?" path: "/port-forwards"
}; };
export interface PortForwardsRouteParams { export interface PortForwardsRouteParams {
forwardport?: string;
} }
export const portForwardsURL = buildURL<PortForwardsRouteParams>(portForwardsRoute.path); export const portForwardsURL = buildURL<PortForwardsRouteParams>(portForwardsRoute.path);

View File

@ -76,7 +76,7 @@ class PortForward {
"port-forward", "port-forward",
"-n", this.namespace, "-n", this.namespace,
`${this.kind}/${this.name}`, `${this.kind}/${this.name}`,
`${this.forwardPort??""}:${this.port}` `${this.forwardPort ?? ""}:${this.port}`
]; ];
this.process = spawn(kubectlBin, args, { this.process = spawn(kubectlBin, args, {
@ -153,7 +153,7 @@ export class PortForwardRoute {
} }
} }
respondJson(response, {port: portForward.internalPort}); respondJson(response, { port: portForward.internalPort });
} catch (error) { } catch (error) {
logger.error(`[PORT-FORWARD-ROUTE]: failed to open a port-forward: ${error}`, { namespace, port, resourceType, resourceName }); logger.error(`[PORT-FORWARD-ROUTE]: failed to open a port-forward: ${error}`, { namespace, port, resourceType, resourceName });
@ -164,7 +164,7 @@ export class PortForwardRoute {
} }
static async routeCurrentPortForward(request: LensApiRequest) { static async routeCurrentPortForward(request: LensApiRequest) {
const { params, response, cluster} = request; const { params, response, cluster } = request;
const { namespace, port, forwardPort, resourceType, resourceName } = params; const { namespace, port, forwardPort, resourceType, resourceName } = params;
const portForward = PortForward.getPortforward({ const portForward = PortForward.getPortforward({
@ -172,32 +172,28 @@ export class PortForwardRoute {
namespace, port, forwardPort namespace, port, forwardPort
}); });
respondJson(response, {port: portForward?.internalPort?? null}); respondJson(response, { port: portForward?.internalPort ?? null });
} }
static async routeAllPortForwards(request: LensApiRequest) { static async routeAllPortForwards(request: LensApiRequest) {
const { response } = request; const { response } = request;
const portForwards: PortForwardArgs[] = []; const portForwards: PortForwardArgs[] = PortForward.portForwards.map(f => (
{
PortForward.portForwards.forEach(f => {
const pf: PortForwardArgs = {
clusterId: f.clusterId, clusterId: f.clusterId,
kind: f.kind, kind: f.kind,
namespace: f.namespace, namespace: f.namespace,
name: f.name, name: f.name,
port: f.port, port: f.port,
forwardPort: f.forwardPort, forwardPort: f.forwardPort,
}; })
);
portForwards.push(pf); respondJson(response, { portForwards });
});
respondJson(response, {portForwards});
} }
static async routeCurrentPortForwardStop(request: LensApiRequest) { static async routeCurrentPortForwardStop(request: LensApiRequest) {
const { params, response, cluster} = request; const { params, response, cluster } = request;
const { namespace, port, forwardPort, resourceType, resourceName } = params; const { namespace, port, forwardPort, resourceType, resourceName } = params;
const portForward = PortForward.getPortforward({ const portForward = PortForward.getPortforward({
@ -207,9 +203,13 @@ export class PortForwardRoute {
try { try {
await portForward.stop(); await portForward.stop();
respondJson(response, {status: true}); respondJson(response, { status: true });
} catch (error) { } catch (error) {
logger.error(error); logger.error("[PORT-FORWARD-ROUTE]: error stopping a port-forward", { namespace, port, forwardPort, resourceType, resourceName });
return respondJson(response, {
message: `error stopping a forward port ${port}`
}, 400);
} }
} }
} }

View File

@ -33,6 +33,7 @@
cursor: pointer; cursor: pointer;
color: $primary; color: $primary;
text-decoration: underline; text-decoration: underline;
padding-right: 1em;
} }
.portInput { .portInput {

View File

@ -24,8 +24,8 @@ import "./service-port-component.scss";
import React from "react"; import React from "react";
import { disposeOnUnmount, observer } from "mobx-react"; import { disposeOnUnmount, observer } from "mobx-react";
import type { Service, ServicePort } from "../../../common/k8s-api/endpoints"; import type { Service, ServicePort } from "../../../common/k8s-api/endpoints";
import { observable, makeObservable, IReactionDisposer, reaction } from "mobx"; import { observable, makeObservable, reaction } from "mobx";
import { cssNames } from "../../utils"; import { cssNames, disposer } from "../../utils";
import { Notifications } from "../notifications"; import { Notifications } from "../notifications";
import { Button } from "../button"; import { Button } from "../button";
import { addPortForward, getPortForward, openPortForward, PortForwardDialog, portForwardStore, removePortForward } from "../../port-forward"; import { addPortForward, getPortForward, openPortForward, PortForwardDialog, portForwardStore, removePortForward } from "../../port-forward";
@ -57,11 +57,9 @@ export class ServicePortComponent extends React.Component<Props> {
} }
watch() { watch() {
const disposers: IReactionDisposer[] = [ return disposer(
reaction(() => portForwardStore.portForwards, () => this.init()), reaction(() => portForwardStore.portForwards, () => this.init()),
]; );
return () => disposers.forEach((dispose) => dispose());
} }
init() { init() {
@ -113,7 +111,7 @@ export class ServicePortComponent extends React.Component<Props> {
openPortForward(portForward); openPortForward(portForward);
this.isPortForwarded = true; this.isPortForwarded = true;
} }
} catch(error) { } catch (error) {
Notifications.error(error); Notifications.error(error);
} finally { } finally {
this.waiting = false; this.waiting = false;
@ -135,7 +133,7 @@ export class ServicePortComponent extends React.Component<Props> {
try { try {
await removePortForward(portForward); await removePortForward(portForward);
this.isPortForwarded = false; this.isPortForwarded = false;
} catch(error) { } catch (error) {
Notifications.error(error); Notifications.error(error);
} finally { } finally {
this.waiting = false; this.waiting = false;
@ -148,7 +146,7 @@ export class ServicePortComponent extends React.Component<Props> {
const portForwardAction = async () => { const portForwardAction = async () => {
if (this.isPortForwarded) { if (this.isPortForwarded) {
await this.stopPortForward(); await this.stopPortForward();
}else { } else {
const portForward: ForwardedPort = { const portForward: ForwardedPort = {
kind: "service", kind: "service",
name: service.getName(), name: service.getName(),
@ -157,20 +155,19 @@ export class ServicePortComponent extends React.Component<Props> {
forwardPort: this.forwardPort.toString() forwardPort: this.forwardPort.toString()
}; };
PortForwardDialog.open(portForward, true); PortForwardDialog.open(portForward, { openInBrowser: true });
} }
}; };
return ( return (
<div className={cssNames("ServicePortComponent", { waiting: this.waiting })}> <div className={cssNames("ServicePortComponent", { waiting: this.waiting })}>
<span title="Open in a browser" onClick={() => this.portForward() }> <span title="Open in a browser" onClick={() => this.portForward()}>
{port.toString()} {port.toString()}
</span>
<Button onClick={() => portForwardAction()}> {this.isPortForwarded ? "Stop" : "Forward..."} </Button>
{this.waiting && ( {this.waiting && (
<Spinner /> <Spinner />
)} )}
</span>
{" "}
<Button onClick={() => portForwardAction()}> {this.isPortForwarded ? "Stop":"Forward..."} </Button>
</div> </div>
); );
} }

View File

@ -34,6 +34,7 @@
color: $primary; color: $primary;
text-decoration: underline; text-decoration: underline;
position: relative; position: relative;
padding-right: 1em;
} }
.portInput { .portInput {

View File

@ -117,7 +117,7 @@ export class PodContainerPort extends React.Component<Props> {
openPortForward(portForward); openPortForward(portForward);
this.isPortForwarded = true; this.isPortForwarded = true;
} }
} catch(error) { } catch (error) {
Notifications.error(error); Notifications.error(error);
} finally { } finally {
this.waiting = false; this.waiting = false;
@ -139,7 +139,7 @@ export class PodContainerPort extends React.Component<Props> {
try { try {
await removePortForward(portForward); await removePortForward(portForward);
this.isPortForwarded = false; this.isPortForwarded = false;
} catch(error) { } catch (error) {
Notifications.error(error); Notifications.error(error);
} finally { } finally {
this.waiting = false; this.waiting = false;
@ -163,20 +163,19 @@ export class PodContainerPort extends React.Component<Props> {
forwardPort: this.forwardPort.toString() forwardPort: this.forwardPort.toString()
}; };
PortForwardDialog.open(portForward, true); PortForwardDialog.open(portForward, { openInBrowser: true });
} }
}; };
return ( return (
<div className={cssNames("PodContainerPort", { waiting: this.waiting })}> <div className={cssNames("PodContainerPort", { waiting: this.waiting })}>
<span title="Open in a browser" onClick={() => this.portForward() }> <span title="Open in a browser" onClick={() => this.portForward()}>
{text} {text}
</span>
<Button onClick={() => portForwardAction()}> {this.isPortForwarded ? "Stop" : "Forward..."} </Button>
{this.waiting && ( {this.waiting && (
<Spinner /> <Spinner />
)} )}
</span>
{" "}
<Button onClick={() => portForwardAction()}> {this.isPortForwarded ? "Stop":"Forward..."} </Button>
</div> </div>
); );
} }

View File

@ -22,7 +22,7 @@
import "./port-forward-dialog.scss"; import "./port-forward-dialog.scss";
import React, { Component } from "react"; import React, { Component } from "react";
import { computed, observable, makeObservable } from "mobx"; import { observable, makeObservable } from "mobx";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Dialog, DialogProps } from "../components/dialog"; import { Dialog, DialogProps } from "../components/dialog";
import { Wizard, WizardStep } from "../components/wizard"; import { Wizard, WizardStep } from "../components/wizard";
@ -30,12 +30,16 @@ import { Input } from "../components/input";
import { Notifications } from "../components/notifications"; import { Notifications } from "../components/notifications";
import { cssNames } from "../utils"; import { cssNames } from "../utils";
import { addPortForward, modifyPortForward } from "./port-forward.store"; import { addPortForward, modifyPortForward } from "./port-forward.store";
import type { ForwardedPort } from "./port-forward.store"; import type { ForwardedPort } from "./port-forward-item";
import { openPortForward } from "."; import { openPortForward } from ".";
interface Props extends Partial<DialogProps> { interface Props extends Partial<DialogProps> {
} }
interface PortForwardDialogOpenOptions {
openInBrowser: boolean
}
const dialogState = observable.object({ const dialogState = observable.object({
isOpen: false, isOpen: false,
data: null as ForwardedPort, data: null as ForwardedPort,
@ -53,10 +57,10 @@ export class PortForwardDialog extends Component<Props> {
makeObservable(this); makeObservable(this);
} }
static open(portForward: ForwardedPort, openInBrowser = false) { static open(portForward: ForwardedPort, options : PortForwardDialogOpenOptions = { openInBrowser: false }) {
dialogState.isOpen = true; dialogState.isOpen = true;
dialogState.data = portForward; dialogState.data = portForward;
dialogState.openInBrowser = openInBrowser; dialogState.openInBrowser = options.openInBrowser;
} }
static close() { static close() {
@ -71,15 +75,6 @@ export class PortForwardDialog extends Component<Props> {
PortForwardDialog.close(); PortForwardDialog.close();
}; };
@computed get scaleMax() {
const { currentPort } = this;
const defaultMax = 50;
return currentPort <= defaultMax
? defaultMax * 2
: currentPort * 2;
}
onOpen = async () => { onOpen = async () => {
const { portForward } = this; const { portForward } = this;

View File

@ -23,6 +23,15 @@
import type { ItemObject } from "../../common/item.store"; import type { ItemObject } from "../../common/item.store";
import { autoBind } from "../../common/utils"; import { autoBind } from "../../common/utils";
export interface ForwardedPort {
clusterId?: string;
kind: string;
namespace: string;
name: string;
port: string;
forwardPort: string;
}
export class PortForwardItem implements ItemObject { export class PortForwardItem implements ItemObject {
clusterId: string; clusterId: string;
kind: string; kind: string;
@ -31,7 +40,14 @@ export class PortForwardItem implements ItemObject {
port: string; port: string;
forwardPort: string; forwardPort: string;
constructor() { constructor(pf: ForwardedPort) {
this.clusterId = pf.clusterId;
this.kind = pf.kind;
this.namespace = pf.namespace;
this.name = pf.name;
this.port = pf.port;
this.forwardPort = pf.forwardPort;
autoBind(this); autoBind(this);
} }

View File

@ -20,24 +20,15 @@
*/ */
import { computed, IReactionDisposer, makeObservable, observable, reaction } from "mobx"; import { makeObservable, observable, reaction } from "mobx";
import { ItemObject, ItemStore } from "../../common/item.store"; import { ItemStore } from "../../common/item.store";
import { autoBind, createStorage, getHostedClusterId, openExternal } from "../utils"; import { autoBind, createStorage, disposer, getHostedClusterId, openExternal } from "../utils";
import { PortForwardItem } from "./port-forward-item"; import { ForwardedPort, PortForwardItem } from "./port-forward-item";
import { apiBase } from "../api"; import { apiBase } from "../api";
import { waitUntilFree } from "tcp-port-used"; import { waitUntilFree } from "tcp-port-used";
import { Notifications } from "../components/notifications"; import { Notifications } from "../components/notifications";
import logger from "../../common/logger"; import logger from "../../common/logger";
export interface ForwardedPort {
clusterId?: string;
kind: string;
namespace: string;
name: string;
port: string;
forwardPort: string;
}
export class PortForwardStore extends ItemStore<PortForwardItem> { export class PortForwardStore extends ItemStore<PortForwardItem> {
private storage = createStorage<ForwardedPort[] | undefined>("port_forwards", undefined); private storage = createStorage<ForwardedPort[] | undefined>("port_forwards", undefined);
@ -56,36 +47,18 @@ export class PortForwardStore extends ItemStore<PortForwardItem> {
if (Array.isArray(savedPortForwards)) { if (Array.isArray(savedPortForwards)) {
logger.info("[PORT_FORWARD] starting saved port-forwards"); logger.info("[PORT_FORWARD] starting saved port-forwards");
await Promise.all(savedPortForwards.map(pf => { await Promise.all(savedPortForwards.map(addPortForward));
const port = new PortForwardItem;
port.clusterId = pf.clusterId; this.reset();
port.kind = pf.kind;
port.namespace = pf.namespace;
port.name = pf.name;
port.port = pf.port;
port.forwardPort = pf.forwardPort;
return addPortForward(port);
}));
this.portForwards = [];
} }
} }
@observable selectedItemId?: string;
@observable portForwards: PortForwardItem[]; @observable portForwards: PortForwardItem[];
@computed get selectedItem() {
return this.portForwards.find((e: ItemObject) => e.getId() === this.selectedItemId);
}
watch() { watch() {
const disposers: IReactionDisposer[] = [ return disposer(
reaction(() => this.portForwards, () => this.loadAll()), reaction(() => this.portForwards, () => this.loadAll()),
]; );
return () => disposers.forEach((dispose) => dispose());
} }
loadAll() { loadAll() {
@ -93,21 +66,11 @@ export class PortForwardStore extends ItemStore<PortForwardItem> {
let portForwards = await getPortForwards(); let portForwards = await getPortForwards();
// filter out any not for this cluster // filter out any not for this cluster
portForwards = portForwards?.filter(pf => pf.clusterId == getHostedClusterId()); portForwards = portForwards.filter(pf => pf.clusterId == getHostedClusterId());
this.storage.set(portForwards); this.storage.set(portForwards);
this.reset(); this.reset();
portForwards?.forEach(pf => { portForwards.map(pf => this.portForwards.push(new PortForwardItem(pf)));
const port = new PortForwardItem;
port.clusterId = pf.clusterId;
port.kind = pf.kind;
port.namespace = pf.namespace;
port.name = pf.name;
port.port = pf.port;
port.forwardPort = pf.forwardPort;
this.portForwards.push(port);
});
return this.portForwards; return this.portForwards;
}); });