From 83ed44f67011dfbd3387016212b74b268e815a30 Mon Sep 17 00:00:00 2001 From: Alex Andreev Date: Fri, 15 Jan 2021 11:34:11 +0300 Subject: [PATCH 1/3] Adding logs tab bottom toolbar (#1951) * Adding bottom toolbar to logs tab Signed-off-by: Alex Andreev * Making bottom toolbar responsive Signed-off-by: Alex Andreev * Using generic search input clear button Signed-off-by: Alex Andreev * Fixing log test selectors Signed-off-by: Alex Andreev --- integration/__tests__/app.tests.ts | 14 +- src/extensions/renderer-api/components.ts | 2 +- src/renderer/components/checkbox/checkbox.tsx | 2 +- src/renderer/components/dock/dock-tabs.tsx | 4 +- src/renderer/components/dock/dock.tsx | 6 +- src/renderer/components/dock/info-panel.scss | 1 - .../components/dock/log-controls.scss | 6 + src/renderer/components/dock/log-controls.tsx | 68 ++++++++++ .../dock/{pod-log-list.scss => log-list.scss} | 2 +- .../dock/{pod-log-list.tsx => log-list.tsx} | 16 ++- ...ntrols.scss => log-resource-selector.scss} | 2 +- .../components/dock/log-resource-selector.tsx | 66 +++++++++ .../{pod-log-search.scss => log-search.scss} | 7 +- .../{pod-log-search.tsx => log-search.tsx} | 13 +- .../dock/{pod-logs.store.ts => log.store.ts} | 8 +- .../dock/{pod-logs.tsx => logs.tsx} | 70 ++++++---- .../components/dock/pod-log-controls.tsx | 126 ------------------ 17 files changed, 223 insertions(+), 190 deletions(-) create mode 100644 src/renderer/components/dock/log-controls.scss create mode 100644 src/renderer/components/dock/log-controls.tsx rename src/renderer/components/dock/{pod-log-list.scss => log-list.scss} (99%) rename src/renderer/components/dock/{pod-log-list.tsx => log-list.tsx} (94%) rename src/renderer/components/dock/{pod-log-controls.scss => log-resource-selector.scss} (62%) create mode 100644 src/renderer/components/dock/log-resource-selector.tsx rename src/renderer/components/dock/{pod-log-search.scss => log-search.scss} (61%) rename src/renderer/components/dock/{pod-log-search.tsx => log-search.tsx} (85%) rename src/renderer/components/dock/{pod-logs.store.ts => log.store.ts} (96%) rename src/renderer/components/dock/{pod-logs.tsx => logs.tsx} (62%) delete mode 100644 src/renderer/components/dock/pod-log-controls.tsx diff --git a/integration/__tests__/app.tests.ts b/integration/__tests__/app.tests.ts index d68ab2f011..7182a13107 100644 --- a/integration/__tests__/app.tests.ts +++ b/integration/__tests__/app.tests.ts @@ -505,16 +505,16 @@ describe("Lens integration tests", () => { await app.client.waitForVisible(".Drawer"); await app.client.click(".drawer-title .Menu li:nth-child(2)"); // Check if controls are available - await app.client.waitForVisible(".PodLogs .VirtualList"); - await app.client.waitForVisible(".PodLogControls"); - await app.client.waitForVisible(".PodLogControls .SearchInput"); - await app.client.waitForVisible(".PodLogControls .SearchInput input"); + await app.client.waitForVisible(".Logs .VirtualList"); + await app.client.waitForVisible(".LogResourceSelector"); + await app.client.waitForVisible(".LogResourceSelector .SearchInput"); + await app.client.waitForVisible(".LogResourceSelector .SearchInput input"); // Search for semicolon await app.client.keys(":"); - await app.client.waitForVisible(".PodLogs .list span.active"); + await app.client.waitForVisible(".Logs .list span.active"); // Click through controls - await app.client.click(".PodLogControls .timestamps-icon"); - await app.client.click(".PodLogControls .undo-icon"); + await app.client.click(".LogControls .show-timestamps"); + await app.client.click(".LogControls .show-previous"); }); }); diff --git a/src/extensions/renderer-api/components.ts b/src/extensions/renderer-api/components.ts index 68dd5d6510..a9a519498b 100644 --- a/src/extensions/renderer-api/components.ts +++ b/src/extensions/renderer-api/components.ts @@ -38,4 +38,4 @@ export * from "../../renderer/components/+events/kube-event-details"; // specific exports export * from "../../renderer/components/status-brick"; export { terminalStore, createTerminalTab } from "../../renderer/components/dock/terminal.store"; -export { createPodLogsTab } from "../../renderer/components/dock/pod-logs.store"; +export { createPodLogsTab } from "../../renderer/components/dock/log.store"; diff --git a/src/renderer/components/checkbox/checkbox.tsx b/src/renderer/components/checkbox/checkbox.tsx index 0831e6122f..f97740a874 100644 --- a/src/renderer/components/checkbox/checkbox.tsx +++ b/src/renderer/components/checkbox/checkbox.tsx @@ -30,7 +30,7 @@ export class Checkbox extends React.PureComponent { render() { const { label, inline, className, value, theme, children, ...inputProps } = this.props; - const componentClass = cssNames("Checkbox flex", className, { + const componentClass = cssNames("Checkbox flex align-center", className, { inline, checked: value, disabled: this.props.disabled, diff --git a/src/renderer/components/dock/dock-tabs.tsx b/src/renderer/components/dock/dock-tabs.tsx index 54451ddd89..6bf9280d59 100644 --- a/src/renderer/components/dock/dock-tabs.tsx +++ b/src/renderer/components/dock/dock-tabs.tsx @@ -7,7 +7,7 @@ import { DockTab } from "./dock-tab"; import { IDockTab } from "./dock.store"; import { isEditResourceTab } from "./edit-resource.store"; import { isInstallChartTab } from "./install-chart.store"; -import { isPodLogsTab } from "./pod-logs.store"; +import { isLogsTab } from "./log.store"; import { TerminalTab } from "./terminal-tab"; import { isTerminalTab } from "./terminal.store"; import { isUpgradeChartTab } from "./upgrade-chart.store"; @@ -33,7 +33,7 @@ export const DockTabs = ({ tabs, autoFocus, selectedTab, onChangeTab }: Props) = return } />; } - if (isPodLogsTab(tab)) { + if (isLogsTab(tab)) { return ; } }; diff --git a/src/renderer/components/dock/dock.tsx b/src/renderer/components/dock/dock.tsx index f02502eab7..c8adf82992 100644 --- a/src/renderer/components/dock/dock.tsx +++ b/src/renderer/components/dock/dock.tsx @@ -16,8 +16,8 @@ import { EditResource } from "./edit-resource"; import { isEditResourceTab } from "./edit-resource.store"; import { InstallChart } from "./install-chart"; import { isInstallChartTab } from "./install-chart.store"; -import { PodLogs } from "./pod-logs"; -import { isPodLogsTab } from "./pod-logs.store"; +import { Logs } from "./logs"; +import { isLogsTab } from "./log.store"; import { TerminalWindow } from "./terminal-window"; import { createTerminalTab, isTerminalTab } from "./terminal.store"; import { UpgradeChart } from "./upgrade-chart"; @@ -64,7 +64,7 @@ export class Dock extends React.Component { {isInstallChartTab(tab) && } {isUpgradeChartTab(tab) && } {isTerminalTab(tab) && } - {isPodLogsTab(tab) && } + {isLogsTab(tab) && } ); } diff --git a/src/renderer/components/dock/info-panel.scss b/src/renderer/components/dock/info-panel.scss index 23dcc52243..482dbee02d 100644 --- a/src/renderer/components/dock/info-panel.scss +++ b/src/renderer/components/dock/info-panel.scss @@ -2,7 +2,6 @@ @include hidden-scrollbar; background: $dockInfoBackground; - border-bottom: 1px solid $dockInfoBorderColor; padding: $padding $padding * 2; flex-shrink: 0; diff --git a/src/renderer/components/dock/log-controls.scss b/src/renderer/components/dock/log-controls.scss new file mode 100644 index 0000000000..e446cca235 --- /dev/null +++ b/src/renderer/components/dock/log-controls.scss @@ -0,0 +1,6 @@ +.LogControls { + @include hidden-scrollbar; + + background: $dockInfoBackground; + padding: $padding $padding * 2; +} \ No newline at end of file diff --git a/src/renderer/components/dock/log-controls.tsx b/src/renderer/components/dock/log-controls.tsx new file mode 100644 index 0000000000..cedff7fbb9 --- /dev/null +++ b/src/renderer/components/dock/log-controls.tsx @@ -0,0 +1,68 @@ +import "./log-controls.scss"; + +import React from "react"; +import { observer } from "mobx-react"; + +import { Pod } from "../../api/endpoints"; +import { cssNames, saveFileDialog } from "../../utils"; +import { IPodLogsData, podLogsStore } from "./log.store"; +import { Checkbox } from "../checkbox"; +import { Icon } from "../icon"; + +interface Props { + tabData: IPodLogsData + logs: string[] + save: (data: Partial) => void + reload: () => void +} + +export const LogControls = observer((props: Props) => { + const { tabData, save, reload, logs } = props; + const { showTimestamps, previous } = tabData; + const since = logs.length ? podLogsStore.getTimestamps(logs[0]) : null; + const pod = new Pod(tabData.pod); + + const toggleTimestamps = () => { + save({ showTimestamps: !showTimestamps }); + }; + + const togglePrevious = () => { + save({ previous: !previous }); + reload(); + }; + + const downloadLogs = () => { + const fileName = pod.getName(); + const logsToDownload = showTimestamps ? logs : podLogsStore.logsWithoutTimestamps; + + saveFileDialog(`${fileName}.log`, logsToDownload.join("\n"), "text/plain"); + }; + + return ( +
+
+ {since && `Logs from ${new Date(since[0]).toLocaleString()}`} +
+
+ + + +
+
+ ); +}); diff --git a/src/renderer/components/dock/pod-log-list.scss b/src/renderer/components/dock/log-list.scss similarity index 99% rename from src/renderer/components/dock/pod-log-list.scss rename to src/renderer/components/dock/log-list.scss index 9b923b520b..8a39dcf925 100644 --- a/src/renderer/components/dock/pod-log-list.scss +++ b/src/renderer/components/dock/log-list.scss @@ -1,4 +1,4 @@ -.PodLogList { +.LogList { --overlay-bg: #8cc474b8; --overlay-active-bg: orange; diff --git a/src/renderer/components/dock/pod-log-list.tsx b/src/renderer/components/dock/log-list.tsx similarity index 94% rename from src/renderer/components/dock/pod-log-list.tsx rename to src/renderer/components/dock/log-list.tsx index c876d0c362..74d64d2f58 100644 --- a/src/renderer/components/dock/pod-log-list.tsx +++ b/src/renderer/components/dock/log-list.tsx @@ -1,4 +1,4 @@ -import "./pod-log-list.scss"; +import "./log-list.scss"; import React from "react"; import AnsiUp from "ansi_up"; @@ -14,7 +14,7 @@ import { Button } from "../button"; import { Icon } from "../icon"; import { Spinner } from "../spinner"; import { VirtualList } from "../virtual-list"; -import { podLogsStore } from "./pod-logs.store"; +import { podLogsStore } from "./log.store"; interface Props { logs: string[] @@ -26,7 +26,7 @@ interface Props { const colorConverter = new AnsiUp(); @observer -export class PodLogList extends React.Component { +export class LogList extends React.Component { @observable isJumpButtonVisible = false; @observable isLastLineVisible = true; @@ -206,19 +206,23 @@ export class PodLogList extends React.Component { const rowHeights = new Array(this.logs.length).fill(this.lineHeight); if (isInitLoading) { - return ; + return ( +
+ +
+ ); } if (!this.logs.length) { return ( -
+
There are no logs available for container
); } return ( -
+
) => void + reload: () => void +} + +export const LogResourceSelector = observer((props: Props) => { + const { tabData, save, reload } = props; + const { selectedContainer, containers, initContainers } = tabData; + const pod = new Pod(tabData.pod); + + const onContainerChange = (option: SelectOption) => { + const { containers, initContainers } = tabData; + + save({ + selectedContainer: containers + .concat(initContainers) + .find(container => container.name === option.value) + }); + reload(); + }; + + const getSelectOptions = (containers: IPodContainer[]) => { + return containers.map(container => { + return { + value: container.name, + label: container.name + }; + }); + }; + + const containerSelectOptions = [ + { + label: `Containers`, + options: getSelectOptions(containers) + }, + { + label: `Init Containers`, + options: getSelectOptions(initContainers), + } + ]; + + return ( +
+ Namespace + Pod + Container + -
- {since && ( - <> - Since{" "} - {new Date(since[0]).toLocaleString()} - - )} -
-
- - - - -
-
- ); -}); From 0117cecc332dfd016718b773dd948ac2feb9a990 Mon Sep 17 00:00:00 2001 From: Lauri Nevala Date: Fri, 15 Jan 2021 16:11:41 +0200 Subject: [PATCH 2/3] Prevent initializing clusters multiple times (#1950) * Prevent initializing clusters multiple times Signed-off-by: Lauri Nevala * Do not expose intializing to cluster state Signed-off-by: Lauri Nevala * Convert initializing to observable and ensure it is set to false after init Signed-off-by: Lauri Nevala --- src/main/cluster-manager.ts | 2 +- src/main/cluster.ts | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/cluster-manager.ts b/src/main/cluster-manager.ts index 5717c7278d..1b468e3bb6 100644 --- a/src/main/cluster-manager.ts +++ b/src/main/cluster-manager.ts @@ -14,7 +14,7 @@ export class ClusterManager extends Singleton { // auto-init clusters autorun(() => { clusterStore.enabledClustersList.forEach(cluster => { - if (!cluster.initialized) { + if (!cluster.initialized && !cluster.initializing) { logger.info(`[CLUSTER-MANAGER]: init cluster`, cluster.getMeta()); cluster.init(port); } diff --git a/src/main/cluster.ts b/src/main/cluster.ts index b9ff62e8ac..c6c14f6406 100644 --- a/src/main/cluster.ts +++ b/src/main/cluster.ts @@ -84,6 +84,14 @@ export class Cluster implements ClusterModel, ClusterState { whenInitialized = when(() => this.initialized); whenReady = when(() => this.ready); + /** + * Is cluster object initializinng on-going + * + * @observable + */ + @observable initializing = false; + + /** * Is cluster object initialized * @@ -273,6 +281,7 @@ export class Cluster implements ClusterModel, ClusterState { */ @action async init(port: number) { try { + this.initializing = true; this.contextHandler = new ContextHandler(this); this.kubeconfigManager = await KubeconfigManager.create(this, this.contextHandler, port); this.kubeProxyUrl = `http://localhost:${port}${apiKubePrefix}`; @@ -287,6 +296,8 @@ export class Cluster implements ClusterModel, ClusterState { id: this.id, error: err, }); + } finally { + this.initializing = false; } } From dfe6d72505e798486f5e8429827745ac9f64b27d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Jan 2021 16:12:49 +0200 Subject: [PATCH 3/3] Bump ini from 1.3.5 to 1.3.8 (#1760) Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.8. - [Release notes](https://github.com/isaacs/ini/releases) - [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.8) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 97eae9dc25..27d8c541ce 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6854,9 +6854,9 @@ inherits@2.0.3: integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== init-package-json@^1.10.3: version "1.10.3"