From 22c9d03edbf4abcda8dafcd5a51ebf9f23131749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luca=20Kr=C3=B6ger?= Date: Mon, 7 Jun 2021 16:47:27 +0200 Subject: [PATCH] Add container attach feature (#2927) --- extensions/pod-menu/renderer.tsx | 8 ++ extensions/pod-menu/src/attach-menu.tsx | 101 +++++++++++++++++++ integration/__tests__/cluster-pages.tests.ts | 2 +- 3 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 extensions/pod-menu/src/attach-menu.tsx diff --git a/extensions/pod-menu/renderer.tsx b/extensions/pod-menu/renderer.tsx index 66da38f7ba..d25ab12d3f 100644 --- a/extensions/pod-menu/renderer.tsx +++ b/extensions/pod-menu/renderer.tsx @@ -20,12 +20,20 @@ */ import { Renderer } from "@k8slens/extensions"; +import { PodAttachMenu, PodAttachMenuProps } from "./src/attach-menu"; import { PodShellMenu, PodShellMenuProps } from "./src/shell-menu"; import { PodLogsMenu, PodLogsMenuProps } from "./src/logs-menu"; import React from "react"; export default class PodMenuRendererExtension extends Renderer.LensExtension { kubeObjectMenuItems = [ + { + kind: "Pod", + apiVersions: ["v1"], + components: { + MenuItem: (props: PodAttachMenuProps) => + } + }, { kind: "Pod", apiVersions: ["v1"], diff --git a/extensions/pod-menu/src/attach-menu.tsx b/extensions/pod-menu/src/attach-menu.tsx new file mode 100644 index 0000000000..bb43d151bc --- /dev/null +++ b/extensions/pod-menu/src/attach-menu.tsx @@ -0,0 +1,101 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +import React from "react"; +import { Renderer, Common } from "@k8slens/extensions"; + +type Pod = Renderer.K8sApi.Pod; + +const { + Component: { + createTerminalTab, + terminalStore, + MenuItem, + Icon, + SubMenu, + StatusBrick, + }, + Navigation, +} = Renderer; +const { + Util, +} = Common; + +export interface PodAttachMenuProps extends Renderer.Component.KubeObjectMenuProps { +} + +export class PodAttachMenu extends React.Component { + async attachToPod(container?: string) { + const { object: pod } = this.props; + const containerParam = container ? `-c ${container}` : ""; + let command = `kubectl attach -i -t -n ${pod.getNs()} ${pod.getName()} ${containerParam}`; + + if (window.navigator.platform !== "Win32") { + command = `exec ${command}`; + } + + const shell = createTerminalTab({ + title: `Pod: ${pod.getName()} (namespace: ${pod.getNs()}) [Attached]` + }); + + terminalStore.sendCommand(command, { + enter: true, + tabId: shell.id + }); + + Navigation.hideDetails(); + } + + render() { + const { object, toolbar } = this.props; + const containers = object.getRunningContainers(); + + if (!containers.length) return null; + + return ( + this.attachToPod(containers[0].name))}> + + Attach Pod + {containers.length > 1 && ( + <> + + + { + containers.map(container => { + const { name } = container; + + return ( + this.attachToPod(name))} className="flex align-center"> + + {name} + + ); + }) + } + + + )} + + ); + } +} diff --git a/integration/__tests__/cluster-pages.tests.ts b/integration/__tests__/cluster-pages.tests.ts index ca5e2aaad3..24ad38dcfc 100644 --- a/integration/__tests__/cluster-pages.tests.ts +++ b/integration/__tests__/cluster-pages.tests.ts @@ -410,7 +410,7 @@ describe("Lens cluster pages", () => { await app.client.click(".list .TableRow:first-child"); await app.client.waitForVisible(".Drawer"); await app.client.waitForVisible(`ul.KubeObjectMenu li.MenuItem i[title="Logs"]`); - await app.client.click(".drawer-title .Menu li:nth-child(2)"); + await app.client.click("ul.KubeObjectMenu li.MenuItem i[title='Logs']"); // Check if controls are available await app.client.waitForVisible(".LogList .VirtualList"); await app.client.waitForVisible(".LogResourceSelector");