From 4d8b7b085361f11b1a6f34c4bf4096f697f54222 Mon Sep 17 00:00:00 2001 From: Jari Kolehmainen Date: Fri, 16 Apr 2021 12:28:11 +0300 Subject: [PATCH 1/3] Move catalog to top-level module in extension api (#2527) Signed-off-by: Jari Kolehmainen --- extensions/metrics-cluster-feature/renderer.tsx | 6 +++--- .../metrics-cluster-feature/src/metrics-feature.ts | 10 +++++----- extensions/telemetry/src/tracker.ts | 6 +++--- src/extensions/cluster-feature.ts | 2 +- src/extensions/core-api/catalog.ts | 3 +++ src/extensions/core-api/index.ts | 2 ++ src/extensions/core-api/stores.ts | 3 --- 7 files changed, 17 insertions(+), 15 deletions(-) diff --git a/extensions/metrics-cluster-feature/renderer.tsx b/extensions/metrics-cluster-feature/renderer.tsx index ea8a666103..030228d50c 100644 --- a/extensions/metrics-cluster-feature/renderer.tsx +++ b/extensions/metrics-cluster-feature/renderer.tsx @@ -1,9 +1,9 @@ -import { LensRendererExtension, Store, Interface, Component } from "@k8slens/extensions"; +import { LensRendererExtension, Interface, Component, Catalog} from "@k8slens/extensions"; import { MetricsFeature } from "./src/metrics-feature"; export default class ClusterMetricsFeatureExtension extends LensRendererExtension { onActivate() { - const category = Store.catalogCategories.getForGroupKind("entity.k8slens.dev", "KubernetesCluster"); + const category = Catalog.catalogCategories.getForGroupKind("entity.k8slens.dev", "KubernetesCluster"); if (!category) { return; @@ -12,7 +12,7 @@ export default class ClusterMetricsFeatureExtension extends LensRendererExtensio category.on("contextMenuOpen", this.clusterContextMenuOpen.bind(this)); } - async clusterContextMenuOpen(cluster: Store.KubernetesCluster, ctx: Interface.CatalogEntityContextMenuContext) { + async clusterContextMenuOpen(cluster: Catalog.KubernetesCluster, ctx: Interface.CatalogEntityContextMenuContext) { if (!cluster.status.active) { return; } diff --git a/extensions/metrics-cluster-feature/src/metrics-feature.ts b/extensions/metrics-cluster-feature/src/metrics-feature.ts index 2f830ae92e..747d6030dc 100644 --- a/extensions/metrics-cluster-feature/src/metrics-feature.ts +++ b/extensions/metrics-cluster-feature/src/metrics-feature.ts @@ -1,4 +1,4 @@ -import { ClusterFeature, Store, K8sApi } from "@k8slens/extensions"; +import { ClusterFeature, Catalog, K8sApi } from "@k8slens/extensions"; import semver from "semver"; import * as path from "path"; @@ -49,7 +49,7 @@ export class MetricsFeature extends ClusterFeature.Feature { storageClass: null, }; - async install(cluster: Store.KubernetesCluster): Promise { + async install(cluster: Catalog.KubernetesCluster): Promise { // Check if there are storageclasses const storageClassApi = K8sApi.forCluster(cluster, K8sApi.StorageClass); const scs = await storageClassApi.list(); @@ -62,11 +62,11 @@ export class MetricsFeature extends ClusterFeature.Feature { super.applyResources(cluster, path.join(__dirname, "../resources/")); } - async upgrade(cluster: Store.KubernetesCluster): Promise { + async upgrade(cluster: Catalog.KubernetesCluster): Promise { return this.install(cluster); } - async updateStatus(cluster: Store.KubernetesCluster): Promise { + async updateStatus(cluster: Catalog.KubernetesCluster): Promise { try { const statefulSet = K8sApi.forCluster(cluster, K8sApi.StatefulSet); const prometheus = await statefulSet.get({name: "prometheus", namespace: "lens-metrics"}); @@ -87,7 +87,7 @@ export class MetricsFeature extends ClusterFeature.Feature { return this.status; } - async uninstall(cluster: Store.KubernetesCluster): Promise { + async uninstall(cluster: Catalog.KubernetesCluster): Promise { const namespaceApi = K8sApi.forCluster(cluster, K8sApi.Namespace); const clusterRoleBindingApi = K8sApi.forCluster(cluster, K8sApi.ClusterRoleBinding); const clusterRoleApi = K8sApi.forCluster(cluster, K8sApi.ClusterRole); diff --git a/extensions/telemetry/src/tracker.ts b/extensions/telemetry/src/tracker.ts index 76b046f63b..9a2ad9d7ea 100644 --- a/extensions/telemetry/src/tracker.ts +++ b/extensions/telemetry/src/tracker.ts @@ -1,4 +1,4 @@ -import { EventBus, Util, Store, App } from "@k8slens/extensions"; +import { EventBus, Util, Catalog, App } from "@k8slens/extensions"; import ua from "universal-analytics"; import Analytics from "analytics-node"; import { machineIdSync } from "node-machine-id"; @@ -102,7 +102,7 @@ export class Tracker extends Util.Singleton { } protected reportData() { - const clustersList = Store.catalogEntities.getItemsForApiKind("entity.k8slens.dev/v1alpha1", "KubernetesCluster"); + const clustersList = Catalog.catalogEntities.getItemsForApiKind("entity.k8slens.dev/v1alpha1", "KubernetesCluster"); this.event("generic-data", "report", { appVersion: App.version, @@ -117,7 +117,7 @@ export class Tracker extends Util.Singleton { }); } - protected reportClusterData(cluster: Store.KubernetesCluster) { + protected reportClusterData(cluster: Catalog.KubernetesCluster) { this.event("cluster-data", "report", { id: cluster.metadata.id, managed: cluster.metadata.source !== "local", diff --git a/src/extensions/cluster-feature.ts b/src/extensions/cluster-feature.ts index ad3a258b0e..24e3de5df1 100644 --- a/src/extensions/cluster-feature.ts +++ b/src/extensions/cluster-feature.ts @@ -3,7 +3,7 @@ import path from "path"; import hb from "handlebars"; import { observable } from "mobx"; import { ResourceApplier } from "../main/resource-applier"; -import { KubernetesCluster } from "./core-api/stores"; +import { KubernetesCluster } from "./core-api/catalog"; import logger from "../main/logger"; import { app } from "electron"; import { requestMain } from "../common/ipc"; diff --git a/src/extensions/core-api/catalog.ts b/src/extensions/core-api/catalog.ts index a1dfcb41d0..f81846cd4d 100644 --- a/src/extensions/core-api/catalog.ts +++ b/src/extensions/core-api/catalog.ts @@ -3,6 +3,9 @@ import { computed } from "mobx"; import { CatalogEntity } from "../../common/catalog-entity"; import { catalogEntityRegistry as registry } from "../../common/catalog-entity-registry"; +export { catalogCategoryRegistry as catalogCategories } from "../../common/catalog-category-registry"; +export * from "../../common/catalog-entities"; + export class CatalogEntityRegistry { @computed getItemsForApiKind(apiVersion: string, kind: string): T[] { return registry.getItemsForApiKind(apiVersion, kind); diff --git a/src/extensions/core-api/index.ts b/src/extensions/core-api/index.ts index 19ede51817..9b075f049f 100644 --- a/src/extensions/core-api/index.ts +++ b/src/extensions/core-api/index.ts @@ -9,10 +9,12 @@ import * as Store from "./stores"; import * as Util from "./utils"; import * as ClusterFeature from "./cluster-feature"; import * as Interface from "../interfaces"; +import * as Catalog from "./catalog"; export { App, EventBus, + Catalog, ClusterFeature, Interface, Store, diff --git a/src/extensions/core-api/stores.ts b/src/extensions/core-api/stores.ts index cd01d6ae93..b79c11248a 100644 --- a/src/extensions/core-api/stores.ts +++ b/src/extensions/core-api/stores.ts @@ -1,4 +1 @@ export { ExtensionStore } from "../extension-store"; -export { KubernetesCluster, KubernetesClusterCategory } from "../../common/catalog-entities/kubernetes-cluster"; -export { catalogCategoryRegistry as catalogCategories } from "../../common/catalog-category-registry"; -export { catalogEntities } from "./catalog"; From 0de3bb13caebbeff4c2c62ce27c60a0722c13966 Mon Sep 17 00:00:00 2001 From: Jari Kolehmainen Date: Fri, 16 Apr 2021 13:40:51 +0300 Subject: [PATCH 2/3] Workaround broken reverse name lookup on gh actions (#2545) Signed-off-by: Jari Kolehmainen --- .github/workflows/test.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 69440e27c6..5e1be781cf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,6 +20,11 @@ jobs: with: fetch-depth: 0 + - name: Add the current IP address, long hostname and short hostname record to /etc/hosts file + if: runner.os == 'Linux' + run: | + echo -e "$(ip addr show eth0 | grep "inet\b" | awk '{print $2}' | cut -d/ -f1)\t$(hostname -f) $(hostname -s)" | sudo tee -a /etc/hosts + - name: Using Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: From 61b00b4c12c1b6f4d19eda2cc413bf2861bca56b Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Fri, 16 Apr 2021 17:37:02 -0400 Subject: [PATCH 3/3] display close button on deleted kube details page (#2428) --- .../kube-object/kube-object-list-layout.tsx | 19 ++++----- .../kube-object/kube-object-menu.tsx | 41 ++++++++++++------- 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/src/renderer/components/kube-object/kube-object-list-layout.tsx b/src/renderer/components/kube-object/kube-object-list-layout.tsx index 0ecb602c16..ddae968dc9 100644 --- a/src/renderer/components/kube-object/kube-object-list-layout.tsx +++ b/src/renderer/components/kube-object/kube-object-list-layout.tsx @@ -15,8 +15,14 @@ export interface KubeObjectListLayoutProps extends ItemListLayoutProps { dependentStores?: KubeObjectStore[]; } +const defaultProps: Partial = { + onDetails: (item: KubeObject) => showDetails(item.selfLink), +}; + @observer export class KubeObjectListLayout extends React.Component { + static defaultProps = defaultProps as object; + @computed get selectedItem() { return this.props.store.getByPath(kubeSelectedUrlParam.get()); } @@ -33,14 +39,6 @@ export class KubeObjectListLayout extends React.Component { - if (this.props.onDetails) { - this.props.onDetails(item); - } else { - showDetails(item.selfLink); - } - }; - render() { const { className, store, items = store.contextItems, ...layoutProps } = this.props; @@ -52,10 +50,7 @@ export class KubeObjectListLayout extends React.Component { - return ; - }} + renderItemMenu={(item: KubeObject) => } // safe because we are dealing with KubeObjects here /> ); } diff --git a/src/renderer/components/kube-object/kube-object-menu.tsx b/src/renderer/components/kube-object/kube-object-menu.tsx index 036f0679db..470e98dac4 100644 --- a/src/renderer/components/kube-object/kube-object-menu.tsx +++ b/src/renderer/components/kube-object/kube-object-menu.tsx @@ -7,13 +7,13 @@ import { hideDetails } from "./kube-object-details"; import { apiManager } from "../../api/api-manager"; import { kubeObjectMenuRegistry } from "../../../extensions/registries/kube-object-menu-registry"; -export interface KubeObjectMenuProps extends MenuActionsProps { - object: T; +export interface KubeObjectMenuProps extends MenuActionsProps { + object: T | null | undefined; editable?: boolean; removable?: boolean; } -export class KubeObjectMenu extends React.Component { +export class KubeObjectMenu extends React.Component> { get store() { const { object } = this.props; @@ -52,23 +52,35 @@ export class KubeObjectMenu extends React.Component { @autobind() renderRemoveMessage() { const { object } = this.props; - const resourceKind = object.kind; - const resourceName = object.getName(); + + if (!object) { + return null; + } return ( -

Remove {resourceKind} {resourceName}?

+

Remove {object.kind} {object.getName()}?

); } + getMenuItems(object: T): React.ReactChild[] { + if (!object) { + return []; + } + + return kubeObjectMenuRegistry + .getItemsForKind(object.kind, object.apiVersion) + .map(({components: { MenuItem }}, index) => ( + + )); + } + render() { const { remove, update, renderRemoveMessage, isEditable, isRemovable } = this; - const { className, object, editable, removable, toolbar, ...menuProps } = this.props; - - if (!object) return null; - - const menuItems = kubeObjectMenuRegistry.getItemsForKind(object.kind, object.apiVersion).map((item, index) => { - return ; - }); + const { className, object, editable, removable, ...menuProps } = this.props; return ( { updateAction={isEditable ? update : undefined} removeAction={isRemovable ? remove : undefined} removeConfirmationMessage={renderRemoveMessage} - toolbar={toolbar} {...menuProps} > - {menuItems} + {this.getMenuItems(object)} ); }