From 0a8cf96415e2edcca97db617d0e5df6202ae44d1 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Wed, 14 Jul 2021 08:30:57 -0400 Subject: [PATCH] Add kube-version and distro on detail panel (#3335) --- .../catalog-entities/kubernetes-cluster.ts | 7 ++- src/extensions/lens-renderer-extension.ts | 3 +- .../catalog-entity-detail-registry.ts | 15 ++++-- src/main/cluster-manager.ts | 22 ++++---- src/main/cluster.ts | 19 ++++--- src/renderer/bootstrap.tsx | 1 + .../catalog-entity-detail-registry.tsx | 50 +++++++++++++++++++ src/renderer/initializers/index.ts | 5 +- 8 files changed, 95 insertions(+), 27 deletions(-) create mode 100644 src/renderer/initializers/catalog-entity-detail-registry.tsx diff --git a/src/common/catalog-entities/kubernetes-cluster.ts b/src/common/catalog-entities/kubernetes-cluster.ts index db948df25a..83a94547bb 100644 --- a/src/common/catalog-entities/kubernetes-cluster.ts +++ b/src/common/catalog-entities/kubernetes-cluster.ts @@ -55,13 +55,18 @@ export interface KubernetesClusterSpec extends CatalogEntitySpec { }; } +export interface KubernetesClusterMetadata extends CatalogEntityMetadata { + distro?: string; + kubeVersion?: string; +} + export type KubernetesClusterStatusPhase = "connected" | "connecting" | "disconnected" | "deleting"; export interface KubernetesClusterStatus extends CatalogEntityStatus { phase: KubernetesClusterStatusPhase; } -export class KubernetesCluster extends CatalogEntity { +export class KubernetesCluster extends CatalogEntity { public static readonly apiVersion = "entity.k8slens.dev/v1alpha1"; public static readonly kind = "KubernetesCluster"; diff --git a/src/extensions/lens-renderer-extension.ts b/src/extensions/lens-renderer-extension.ts index a3026d99a5..dd5670fd67 100644 --- a/src/extensions/lens-renderer-extension.ts +++ b/src/extensions/lens-renderer-extension.ts @@ -23,6 +23,7 @@ import type * as registries from "./registries"; import type { Cluster } from "../main/cluster"; import { LensExtension } from "./lens-extension"; import { getExtensionPageUrl } from "./registries/page-registry"; +import type { CatalogEntity } from "../common/catalog"; export class LensRendererExtension extends LensExtension { globalPages: registries.PageRegistration[] = []; @@ -37,7 +38,7 @@ export class LensRendererExtension extends LensExtension { kubeWorkloadsOverviewItems: registries.WorkloadsOverviewDetailRegistration[] = []; commands: registries.CommandRegistration[] = []; welcomeMenus: registries.WelcomeMenuRegistration[] = []; - catalogEntityDetailItems: registries.CatalogEntityDetailRegistration[] = []; + catalogEntityDetailItems: registries.CatalogEntityDetailRegistration[] = []; topBarItems: registries.TopBarRegistration[] = []; async navigate

(pageId?: string, params?: P) { diff --git a/src/extensions/registries/catalog-entity-detail-registry.ts b/src/extensions/registries/catalog-entity-detail-registry.ts index b4b9fb0dd2..4ee9c4d667 100644 --- a/src/extensions/registries/catalog-entity-detail-registry.ts +++ b/src/extensions/registries/catalog-entity-detail-registry.ts @@ -20,20 +20,25 @@ */ import type React from "react"; +import type { CatalogEntity } from "../common-api/catalog"; import { BaseRegistry } from "./base-registry"; -export interface CatalogEntityDetailComponents { - Details: React.ComponentType; +export interface CatalogEntityDetailsProps { + entity: T; } -export interface CatalogEntityDetailRegistration { +export interface CatalogEntityDetailComponents { + Details: React.ComponentType>; +} + +export interface CatalogEntityDetailRegistration { kind: string; apiVersions: string[]; - components: CatalogEntityDetailComponents; + components: CatalogEntityDetailComponents; priority?: number; } -export class CatalogEntityDetailRegistry extends BaseRegistry { +export class CatalogEntityDetailRegistry extends BaseRegistry> { getItemsForKind(kind: string, apiVersion: string) { const items = this.getItems().filter((item) => { return item.kind === kind && item.apiVersions.includes(apiVersion); diff --git a/src/main/cluster-manager.ts b/src/main/cluster-manager.ts index 42d2dd1d19..73d2c50f46 100644 --- a/src/main/cluster-manager.ts +++ b/src/main/cluster-manager.ts @@ -23,7 +23,7 @@ import "../common/cluster-ipc"; import type http from "http"; import { action, autorun, makeObservable, observable, observe, reaction, toJS } from "mobx"; import { ClusterId, ClusterStore, getClusterIdFromHost } from "../common/cluster-store"; -import type { Cluster } from "./cluster"; +import { Cluster } from "./cluster"; import logger from "./logger"; import { apiKubePrefix } from "../common/vars"; import { Singleton } from "../common/utils"; @@ -103,13 +103,13 @@ export class ClusterManager extends Singleton { this.updateEntityStatus(entity, cluster); - entity.metadata.labels = Object.assign({}, cluster.labels, entity.metadata.labels); - entity.metadata.labels.distro = cluster.distribution; - - if (cluster.preferences?.clusterName) { - entity.metadata.name = cluster.preferences.clusterName; - } - + entity.metadata.labels = { + ...entity.metadata.labels, + ...cluster.labels, + }; + entity.metadata.distro = cluster.distribution; + entity.metadata.kubeVersion = cluster.version; + entity.metadata.name = cluster.name; entity.spec.metrics ||= { source: "local" }; if (entity.spec.metrics.source === "local") { @@ -236,8 +236,10 @@ export function catalogEntityFromCluster(cluster: Cluster) { name: cluster.name, source: "local", labels: { - distro: cluster.distribution, - } + ...cluster.labels, + }, + distro: cluster.distribution, + kubeVersion: cluster.version, }, spec: { kubeconfigPath: cluster.kubeConfigPath, diff --git a/src/main/cluster.ts b/src/main/cluster.ts index bf893f8484..58dbbf944f 100644 --- a/src/main/cluster.ts +++ b/src/main/cluster.ts @@ -235,8 +235,18 @@ export class Cluster implements ClusterModel, ClusterState { return this.preferences.clusterName || this.contextName; } + /** + * The detected kubernetes distribution + */ @computed get distribution(): string { - return this.metadata.distribution?.toString() || "unknown"; + return this.metadata[ClusterMetadataKey.DISTRIBUTION]?.toString() || "unknown"; + } + + /** + * The detected kubernetes version + */ + @computed get version(): string { + return this.metadata[ClusterMetadataKey.VERSION]?.toString() || "unknown"; } /** @@ -251,13 +261,6 @@ export class Cluster implements ClusterModel, ClusterState { return toJS({ prometheus, prometheusProvider }); } - /** - * Kubernetes version - */ - get version(): string { - return String(this.metadata?.version ?? ""); - } - constructor(model: ClusterModel) { makeObservable(this); this.id = model.id; diff --git a/src/renderer/bootstrap.tsx b/src/renderer/bootstrap.tsx index 132abc9cd6..2a36c15089 100644 --- a/src/renderer/bootstrap.tsx +++ b/src/renderer/bootstrap.tsx @@ -80,6 +80,7 @@ export async function bootstrap(App: AppComponent) { initializers.intiKubeObjectDetailRegistry(); initializers.initWelcomeMenuRegistry(); initializers.initWorkloadsOverviewDetailRegistry(); + initializers.initCatalogEntityDetailRegistry(); initializers.initCatalog(); initializers.initIpcRendererListeners(); diff --git a/src/renderer/initializers/catalog-entity-detail-registry.tsx b/src/renderer/initializers/catalog-entity-detail-registry.tsx new file mode 100644 index 0000000000..8cae26afbf --- /dev/null +++ b/src/renderer/initializers/catalog-entity-detail-registry.tsx @@ -0,0 +1,50 @@ +/** + * 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 { KubernetesCluster } from "../../common/catalog-entities"; +import { CatalogEntityDetailRegistry, CatalogEntityDetailsProps } from "../../extensions/registries"; +import { DrawerItem, DrawerTitle } from "../components/drawer"; + +export function initCatalogEntityDetailRegistry() { + CatalogEntityDetailRegistry.getInstance() + .add([ + { + apiVersions: [KubernetesCluster.apiVersion], + kind: KubernetesCluster.kind, + components: { + Details: ({ entity }: CatalogEntityDetailsProps) => ( + <> + +

+ + {entity.metadata.distro || "unknown"} + + + {entity.metadata.kubeVersion || "unknown"} + +
+ + ), + }, + } + ]); +} diff --git a/src/renderer/initializers/index.ts b/src/renderer/initializers/index.ts index 03f32f1a9d..943fef6a30 100644 --- a/src/renderer/initializers/index.ts +++ b/src/renderer/initializers/index.ts @@ -19,12 +19,13 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +export * from "./catalog-entity-detail-registry"; +export * from "./catalog"; export * from "./command-registry"; export * from "./entity-settings-registry"; +export * from "./ipc"; export * from "./kube-object-detail-registry"; export * from "./kube-object-menu-registry"; export * from "./registries"; export * from "./welcome-menu-registry"; export * from "./workloads-overview-detail-registry"; -export * from "./catalog"; -export * from "./ipc";