From d7d9c99005af89ee8e0aad2fc2b8d9ebad0bc3cb Mon Sep 17 00:00:00 2001 From: Roman Date: Fri, 17 Jul 2020 23:19:41 +0300 Subject: [PATCH] cluster-status -- part 1 (ex. ClusterPage.vue) Signed-off-by: Roman --- src/common/base-store.ts | 2 +- src/main/cluster-manager.ts | 8 +++ src/main/cluster.ts | 3 +- src/main/kube-auth-proxy.ts | 30 ++++++----- .../cluster-manager/cluster-status.scss | 3 ++ .../cluster-manager/cluster-status.tsx | 53 +++++++++++++++++++ .../components/dialog/logs-dialog.tsx | 2 + 7 files changed, 85 insertions(+), 16 deletions(-) create mode 100644 src/renderer/components/cluster-manager/cluster-status.scss create mode 100644 src/renderer/components/cluster-manager/cluster-status.tsx diff --git a/src/common/base-store.ts b/src/common/base-store.ts index 77969fbac8..8747388ffa 100644 --- a/src/common/base-store.ts +++ b/src/common/base-store.ts @@ -118,7 +118,7 @@ export class BaseStore extends Singleton { protected async onModelChange(model: T) { if (ipcMain) { this.save(model); // save config file - sendMessage({ channel: this.syncChannel, args: model }); // broadcast to renderer views + sendMessage({ channel: this.syncChannel, args: [model] }); // broadcast to renderer views } // send "update-request" to main-process if (ipcRenderer) { diff --git a/src/main/cluster-manager.ts b/src/main/cluster-manager.ts index c6254c6ae7..53b8dbc35a 100644 --- a/src/main/cluster-manager.ts +++ b/src/main/cluster-manager.ts @@ -48,6 +48,14 @@ export class ClusterManager { this.getCluster(clusterId)?.destroy(); } + // todo + protected reconnectCluster(clusterId: ClusterId) { + tracker.event("cluster", "reconnect"); + logger.info(`[CLUSTER-MANAGER]: reconnect cluster`, { + meta: this.getCluster(clusterId)?.getMeta() + }); + } + getClusterForRequest(req: http.IncomingMessage): Cluster { let cluster: Cluster = null diff --git a/src/main/cluster.ts b/src/main/cluster.ts index e03a307cf3..c5fa80fb36 100644 --- a/src/main/cluster.ts +++ b/src/main/cluster.ts @@ -15,6 +15,7 @@ import logger from "./logger" export enum ClusterIpcEvent { STOP = "cluster:stop", + RECONNECT = "cluster:reconnect", } export enum ClusterStatus { @@ -111,7 +112,7 @@ export class Cluster implements ClusterModel { sendMessage({ channel: "cluster:state", webContentId: viewId, - args: clusterState, + args: [clusterState], }) }, { fireImmediately: true diff --git a/src/main/kube-auth-proxy.ts b/src/main/kube-auth-proxy.ts index 26349300e5..d793128c34 100644 --- a/src/main/kube-auth-proxy.ts +++ b/src/main/kube-auth-proxy.ts @@ -5,6 +5,11 @@ import type { Cluster } from "./cluster" import { bundledKubectl, Kubectl } from "./kubectl" import logger from "./logger" +export interface KubeAuthProxyResponse { + data: string; + stream: "stderr" | "stdout"; +} + export class KubeAuthProxy { public lastError: string @@ -43,13 +48,9 @@ export class KubeAuthProxy { }) this.proxyProcess.on("exit", (code) => { if (code) { - logger.error(`proxy ${this.cluster.contextName} exited with code ${code}`) - } else { - logger.info(`proxy ${this.cluster.contextName} exited successfully`) + logger.error(`[KUBE-AUTH]: proxying ${this.cluster.contextName} exited with code ${code}`, this.cluster.getMeta()); } - this.sendIpcLogMessage(`proxy exited with code ${code}`, "stderr").catch((err: Error) => { - logger.debug("failed to send IPC log message: " + err.message) - }) + this.sendIpcLogMessage({ data: `proxy exited with code ${code}`, stream: "stderr" }) this.proxyProcess = null }) this.proxyProcess.stdout.on('data', (data) => { @@ -57,13 +58,11 @@ export class KubeAuthProxy { if (logItem.startsWith("Starting to serve on")) { logItem = "Authentication proxy started\n" } - logger.debug(`proxy ${this.cluster.contextName} stdout: ${logItem}`) - this.sendIpcLogMessage(logItem, "stdout") + this.sendIpcLogMessage({ data: logItem, stream: "stdout" }) }) this.proxyProcess.stderr.on('data', (data) => { this.lastError = this.parseError(data.toString()) - logger.debug(`proxy ${this.cluster.contextName} stderr: ${data}`) - this.sendIpcLogMessage(data.toString(), "stderr") + this.sendIpcLogMessage({ data: data.toString(), stream: "stderr" }) }) return waitUntilUsed(this.port, 500, 10000) @@ -84,11 +83,14 @@ export class KubeAuthProxy { return errorMsg } - protected async sendIpcLogMessage(data: string, stream: string) { + protected async sendIpcLogMessage(res: KubeAuthProxyResponse) { const channel = `kube-auth:${this.cluster.id}` - const message = { data, stream }; - logger.debug(channel, message); - sendMessage({ channel, args: message }); // todo: send message only to cluster's window + logger.debug(`[KUBE-AUTH]: output for ${channel}`, { ...res, meta: this.cluster.getMeta() }); + sendMessage({ + // webContentId: null, // todo: send a message only to single cluster's window + channel: channel, + args: [res], + }); } public exit() { diff --git a/src/renderer/components/cluster-manager/cluster-status.scss b/src/renderer/components/cluster-manager/cluster-status.scss new file mode 100644 index 0000000000..ad1fc1d11e --- /dev/null +++ b/src/renderer/components/cluster-manager/cluster-status.scss @@ -0,0 +1,3 @@ +.ClusterStatus { + +} \ No newline at end of file diff --git a/src/renderer/components/cluster-manager/cluster-status.tsx b/src/renderer/components/cluster-manager/cluster-status.tsx new file mode 100644 index 0000000000..6863d855ba --- /dev/null +++ b/src/renderer/components/cluster-manager/cluster-status.tsx @@ -0,0 +1,53 @@ +import "./cluster-manager.scss" +import type { KubeAuthProxyResponse } from "../../../main/kube-auth-proxy"; +import { Cluster, ClusterIpcEvent } from "../../../main/cluster"; +import React from "react"; +import { ipcRenderer } from "electron"; +import { computed, observable } from "mobx"; +import { observer } from "mobx-react"; +import { Icon } from "../icon"; +import { Button } from "../button"; +import { Trans } from "@lingui/macro"; + +interface Props { + cluster: Cluster; +} + +@observer +export class ClusterStatus extends React.Component { + @observable authProxyOutput = "Connecting ...\n" + + @computed get clusterId() { + return this.props.cluster.id; + } + + componentDidMount() { + ipcRenderer.on(`kube-auth:${this.clusterId}`, (evt, authResponse: KubeAuthProxyResponse) => { + this.authProxyOutput += authResponse.data; + }) + } + + componentWillUnmount() { + ipcRenderer.removeAllListeners(`kube-auth:${this.clusterId}`); + } + + reconnectCluster = () => { + ipcRenderer.send(ClusterIpcEvent.RECONNECT, this.clusterId); + } + + render() { + const { authProxyOutput } = this; + const { contextName, online } = this.props.cluster; + return ( +
+ +

{contextName}

+
{authProxyOutput}
+
+ ) + } +} diff --git a/src/renderer/components/dialog/logs-dialog.tsx b/src/renderer/components/dialog/logs-dialog.tsx index 3e24e7d712..4ce1b3b27f 100644 --- a/src/renderer/components/dialog/logs-dialog.tsx +++ b/src/renderer/components/dialog/logs-dialog.tsx @@ -10,6 +10,8 @@ import { Button } from "../button"; import { Icon } from "../icon"; import { _i18n } from "../../i18n"; +// todo: make as external BrowserWindow (?) + interface Props extends DialogProps { title: string; logs: string;