From f53bb9be931d9f76b08dfa22b2df12387b7b5529 Mon Sep 17 00:00:00 2001 From: Mario Sarcher Date: Mon, 7 Jun 2021 13:33:30 +0200 Subject: [PATCH 01/27] Publish NPM package on push to master branch (#2973) Signed-off-by: Mario Sarcher --- .github/workflows/publish-master-npm.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-master-npm.yml b/.github/workflows/publish-master-npm.yml index c6c4284e6a..daa3d1abe3 100644 --- a/.github/workflows/publish-master-npm.yml +++ b/.github/workflows/publish-master-npm.yml @@ -1,6 +1,6 @@ name: Publish NPM Package `master` on: - pull_request: + push: branches: - master types: From c272ccb48a8c8eed332f2b50fe1607d096f9cc2a Mon Sep 17 00:00:00 2001 From: Mario Sarcher Date: Mon, 7 Jun 2021 13:43:52 +0200 Subject: [PATCH 02/27] Publish npm master remove type (#2974) * Publish NPM package on push to master branch Signed-off-by: Mario Sarcher * Remove type closed to run properly on master branch commits Signed-off-by: Mario Sarcher --- .github/workflows/publish-master-npm.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/publish-master-npm.yml b/.github/workflows/publish-master-npm.yml index daa3d1abe3..2be9721d3e 100644 --- a/.github/workflows/publish-master-npm.yml +++ b/.github/workflows/publish-master-npm.yml @@ -3,8 +3,6 @@ on: push: branches: - master - types: - - closed jobs: publish: name: Publish NPM Package `master` From d21f99e6096b89fb5d296942089f64a7da006ce9 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Mon, 7 Jun 2021 08:08:39 -0400 Subject: [PATCH 03/27] Await `onActivate`/`onDeactive` of extensions (#2963) Signed-off-by: Sebastian Malton --- src/extensions/extension-loader.ts | 7 ++- src/extensions/lens-extension.ts | 73 ++++++++++++------------------ 2 files changed, 32 insertions(+), 48 deletions(-) diff --git a/src/extensions/extension-loader.ts b/src/extensions/extension-loader.ts index 6a4af088e8..da2669550f 100644 --- a/src/extensions/extension-loader.ts +++ b/src/extensions/extension-loader.ts @@ -26,7 +26,7 @@ import { action, computed, makeObservable, observable, reaction, when } from "mo import path from "path"; import { getHostedCluster } from "../common/cluster-store"; import { broadcastMessage, handleRequest, requestMain, subscribeToBroadcast } from "../common/ipc"; -import { Singleton, toJS } from "../common/utils"; +import { Disposer, Singleton, toJS } from "../common/utils"; import logger from "../main/logger"; import type { InstalledExtension } from "./extension-discovery"; import { ExtensionsStore } from "./extensions-store"; @@ -296,7 +296,7 @@ export class ExtensionLoader extends Singleton { }); } - protected autoInitExtensions(register: (ext: LensExtension) => Promise) { + protected autoInitExtensions(register: (ext: LensExtension) => Promise) { return reaction(() => this.toJSON(), installedExtensions => { for (const [extId, extension] of installedExtensions) { const alreadyInit = this.instances.has(extId); @@ -311,8 +311,7 @@ export class ExtensionLoader extends Singleton { const instance = new LensExtensionClass(extension); - instance.whenEnabled(() => register(instance)); - instance.enable(); + instance.enable(register); this.instances.set(extId, instance); } catch (err) { logger.error(`${logModule}: activation extension error`, { ext: extension, err }); diff --git a/src/extensions/lens-extension.ts b/src/extensions/lens-extension.ts index 6f03829121..f3910308fd 100644 --- a/src/extensions/lens-extension.ts +++ b/src/extensions/lens-extension.ts @@ -20,11 +20,11 @@ */ import type { InstalledExtension } from "./extension-discovery"; -import { action, observable, reaction, makeObservable } from "mobx"; +import { action, observable, makeObservable } from "mobx"; import { FilesystemProvisionerStore } from "../main/extension-filesystem"; import logger from "../main/logger"; import type { ProtocolHandlerRegistration } from "./registries"; -import { disposer } from "../common/utils"; +import { Disposer, disposer } from "../common/utils"; export type LensExtensionId = string; // path to manifest (package.json) export type LensExtensionConstructor = new (...args: ConstructorParameters) => LensExtension; @@ -83,59 +83,44 @@ export class LensExtension { } @action - async enable() { - if (this.isEnabled) return; - this.isEnabled = true; - this.onActivate?.(); - logger.info(`[EXTENSION]: enabled ${this.name}@${this.version}`); + async enable(register: (ext: LensExtension) => Promise) { + if (this.isEnabled) { + return; + } + + try { + await this.onActivate(); + this.isEnabled = true; + + this[Disposers].push(...await register(this)); + logger.info(`[EXTENSION]: enabled ${this.name}@${this.version}`); + } catch (error) { + logger.error(`[EXTENSION]: failed to activate ${this.name}@${this.version}: ${error}`); + } } @action async disable() { - if (!this.isEnabled) return; - this.isEnabled = false; - this.onDeactivate?.(); - this[Disposers](); - logger.info(`[EXTENSION]: disabled ${this.name}@${this.version}`); - } + if (!this.isEnabled) { + return; + } - toggle(enable?: boolean) { - if (typeof enable === "boolean") { - enable ? this.enable() : this.disable(); - } else { - this.isEnabled ? this.disable() : this.enable(); + this.isEnabled = false; + + try { + await this.onDeactivate(); + this[Disposers](); + logger.info(`[EXTENSION]: disabled ${this.name}@${this.version}`); + } catch (error) { + logger.error(`[EXTENSION]: disabling ${this.name}@${this.version} threw an error: ${error}`); } } - async whenEnabled(handlers: () => Promise) { - const disposers: Function[] = []; - const unregisterHandlers = () => { - disposers.forEach(unregister => unregister()); - disposers.length = 0; - }; - const cancelReaction = reaction(() => this.isEnabled, async (isEnabled) => { - if (isEnabled) { - const handlerDisposers = await handlers(); - - disposers.push(...handlerDisposers); - } else { - unregisterHandlers(); - } - }, { - fireImmediately: true - }); - - return () => { - unregisterHandlers(); - cancelReaction(); - }; - } - - protected onActivate(): void { + protected onActivate(): Promise | void { return; } - protected onDeactivate(): void { + protected onDeactivate(): Promise | void { return; } } From cb4a7497dd7b26abd20eb089535362061129c176 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Mon, 7 Jun 2021 08:13:26 -0400 Subject: [PATCH 04/27] Remove Namespace filter from ItemListLayout (#2952) --- .../+namespaces/namespace-select-filter.tsx | 4 +- .../item-object-list/filter-icon.tsx | 3 - .../item-object-list/item-list-layout.tsx | 20 +-- .../item-object-list/page-filters-select.tsx | 136 ------------------ .../item-object-list/page-filters.store.ts | 1 - 5 files changed, 2 insertions(+), 162 deletions(-) delete mode 100644 src/renderer/components/item-object-list/page-filters-select.tsx diff --git a/src/renderer/components/+namespaces/namespace-select-filter.tsx b/src/renderer/components/+namespaces/namespace-select-filter.tsx index 25b14ae9e6..8ae2e97958 100644 --- a/src/renderer/components/+namespaces/namespace-select-filter.tsx +++ b/src/renderer/components/+namespaces/namespace-select-filter.tsx @@ -26,8 +26,6 @@ import { observer } from "mobx-react"; import { components, PlaceholderProps } from "react-select"; import { Icon } from "../icon"; -import { FilterIcon } from "../item-object-list/filter-icon"; -import { FilterType } from "../item-object-list/page-filters.store"; import { NamespaceSelect } from "./namespace-select"; import { namespaceStore } from "./namespace.store"; @@ -63,7 +61,7 @@ export class NamespaceSelectFilter extends React.Component { return (
- + {namespace} {isSelected && }
diff --git a/src/renderer/components/item-object-list/filter-icon.tsx b/src/renderer/components/item-object-list/filter-icon.tsx index f5534b2f71..87f41c524f 100644 --- a/src/renderer/components/item-object-list/filter-icon.tsx +++ b/src/renderer/components/item-object-list/filter-icon.tsx @@ -31,9 +31,6 @@ export function FilterIcon(props: Props) { const { type, ...iconProps } = props; switch (type) { - case FilterType.NAMESPACE: - return ; - case FilterType.SEARCH: return ; diff --git a/src/renderer/components/item-object-list/item-list-layout.tsx b/src/renderer/components/item-object-list/item-list-layout.tsx index f894f90a4a..647cbcaec9 100644 --- a/src/renderer/components/item-object-list/item-list-layout.tsx +++ b/src/renderer/components/item-object-list/item-list-layout.tsx @@ -35,7 +35,6 @@ import type { ItemObject, ItemStore } from "../../item.store"; import { SearchInputUrl } from "../input"; import { Filter, FilterType, pageFilters } from "./page-filters.store"; import { PageFiltersList } from "./page-filters-list"; -import { PageFiltersSelect } from "./page-filters-select"; import { ThemeStore } from "../../theme.store"; import { MenuActions } from "../menu/menu-actions"; import { MenuItem } from "../menu"; @@ -179,16 +178,6 @@ export class ItemListLayout extends React.Component { return items; }, - - [FilterType.NAMESPACE]: items => { - const filterValues = pageFilters.getValues(FilterType.NAMESPACE); - - if (filterValues.length > 0) { - return items.filter(item => filterValues.includes(item.getNs())); - } - - return items; - }, }; @computed get isReady() { @@ -401,14 +390,7 @@ export class ItemListLayout extends React.Component { const placeholders: IHeaderPlaceholders = { title:
{title}
, info: this.renderInfo(), - filters: ( - <> - {showNamespaceSelectFilter && } - - - ), + filters: showNamespaceSelectFilter && , search: , }; let header = this.renderHeaderContent(placeholders); diff --git a/src/renderer/components/item-object-list/page-filters-select.tsx b/src/renderer/components/item-object-list/page-filters-select.tsx deleted file mode 100644 index 418c82045b..0000000000 --- a/src/renderer/components/item-object-list/page-filters-select.tsx +++ /dev/null @@ -1,136 +0,0 @@ -/** - * 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 { observer } from "mobx-react"; -import { computed, makeObservable } from "mobx"; -import { GroupSelectOption, Select, SelectOption, SelectProps } from "../select"; -import { FilterType, pageFilters } from "./page-filters.store"; -import { namespaceStore } from "../+namespaces/namespace.store"; -import { Icon } from "../icon"; -import { FilterIcon } from "./filter-icon"; - -export interface SelectOptionFilter extends SelectOption { - type: FilterType; - selected?: boolean; -} - -interface Props extends SelectProps { - allowEmpty?: boolean; - disableFilters?: { - [filterType: string]: boolean; - }; -} - -@observer -export class PageFiltersSelect extends React.Component { - static defaultProps: Props = { - allowEmpty: true, - disableFilters: {}, - }; - - constructor(props: Props) { - super(props); - makeObservable(this); - } - - @computed get groupedOptions() { - const options: GroupSelectOption[] = []; - const { disableFilters } = this.props; - - if (!disableFilters[FilterType.NAMESPACE]) { - const selectedValues = pageFilters.getValues(FilterType.NAMESPACE); - - options.push({ - label: "Namespace", - options: namespaceStore.items.map(ns => { - const name = ns.getName(); - - return { - type: FilterType.NAMESPACE, - value: name, - icon: , - selected: selectedValues.includes(name), - }; - }) - }); - } - - return options; - } - - @computed get options(): SelectOptionFilter[] { - return this.groupedOptions.reduce((options, optGroup) => { - options.push(...optGroup.options); - - return options; - }, []); - } - - private formatLabel = (option: SelectOptionFilter) => { - const { label, value, type, selected } = option; - - return ( -
- - {label || String(value)} - {selected && } -
- ); - }; - - private onSelect = (option: SelectOptionFilter) => { - const { type, value, selected } = option; - const { addFilter, removeFilter } = pageFilters; - const filter = { type, value }; - - if (!selected) { - addFilter(filter); - } - else { - removeFilter(filter); - } - }; - - render() { - const { groupedOptions, formatLabel, onSelect, options } = this; - - if (!options.length && this.props.allowEmpty) { - return null; - } - const { allowEmpty, disableFilters, ...selectProps } = this.props; - const selectedOptions = options.filter(opt => opt.selected); - - return ( - this.proxyServer = value} - theme="round-black" - /> - - {"A HTTP proxy server URL (format: http://
:)."} - - + {this.allErrors.length > 0 && ( + <> +

KubeConfig Yaml Validation Errors:

+ {...this.allErrors.map(error =>
{error}
)} + )} - {this.error && ( -
{this.error}
- )} -
diff --git a/src/renderer/components/cluster-manager/cluster-status.tsx b/src/renderer/components/cluster-manager/cluster-status.tsx index 2d4ccf3a38..c821f2874e 100644 --- a/src/renderer/components/cluster-manager/cluster-status.tsx +++ b/src/renderer/components/cluster-manager/cluster-status.tsx @@ -19,21 +19,23 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import type { KubeAuthProxyLog } from "../../../main/kube-auth-proxy"; - import "./cluster-status.scss"; -import React from "react"; -import { observer } from "mobx-react"; + import { ipcRenderer } from "electron"; import { computed, observable, makeObservable } from "mobx"; -import { requestMain, subscribeToBroadcast } from "../../../common/ipc"; -import { Icon } from "../icon"; -import { Button } from "../button"; -import { cssNames, IClassName } from "../../utils"; -import type { Cluster } from "../../../main/cluster"; -import { ClusterId, ClusterStore } from "../../../common/cluster-store"; -import { CubeSpinner } from "../spinner"; +import { observer } from "mobx-react"; +import React from "react"; import { clusterActivateHandler } from "../../../common/cluster-ipc"; +import { ClusterId, ClusterStore } from "../../../common/cluster-store"; +import { requestMain, subscribeToBroadcast } from "../../../common/ipc"; +import type { Cluster } from "../../../main/cluster"; +import { cssNames, IClassName } from "../../utils"; +import { Button } from "../button"; +import { Icon } from "../icon"; +import { CubeSpinner } from "../spinner"; +import type { KubeAuthProxyLog } from "../../../main/kube-auth-proxy"; +import { navigate } from "../../navigation"; +import { entitySettingsURL } from "../+entity-settings"; interface Props { className?: IClassName; @@ -82,6 +84,15 @@ export class ClusterStatus extends React.Component { this.isReconnecting = false; }; + manageProxySettings = () => { + navigate(entitySettingsURL({ + params: { + entityId: this.props.clusterId, + }, + fragment: "http-proxy", + })); + }; + renderContent() { const { authOutput, cluster, hasErrors } = this; const failureReason = cluster.failureReason; @@ -89,7 +100,7 @@ export class ClusterStatus extends React.Component { if (!hasErrors || this.isReconnecting) { return ( <> - +
             

{this.isReconnecting ? "Reconnecting..." : "Connecting..."}

{authOutput.map(({ data, error }, index) => { @@ -102,7 +113,7 @@ export class ClusterStatus extends React.Component { return ( <> - +

{cluster.preferences.clusterName}

@@ -121,6 +132,12 @@ export class ClusterStatus extends React.Component { onClick={this.reconnect} waiting={this.isReconnecting} /> +