1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Fix: cluster commands disappeared from Command Palette (#2886)

* Cluster commands disappeared from Command Palette, close #2760

Signed-off-by: Roman <ixrock@gmail.com>

* refactoring: get rid of ClusterStore.active && ClusterStore.activeCluster (managed via catalog's entity)

Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman 2021-05-28 14:06:18 +03:00 committed by GitHub
parent d0dbb8744c
commit 643b0d861f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 99 additions and 155 deletions

View File

@ -119,11 +119,6 @@ describe("empty config", () => {
await ClusterStore.getInstance().removeById("foo"); await ClusterStore.getInstance().removeById("foo");
expect(ClusterStore.getInstance().getById("foo")).toBeNull(); expect(ClusterStore.getInstance().getById("foo")).toBeNull();
}); });
it("sets active cluster", () => {
ClusterStore.getInstance().setActive("foo");
expect(ClusterStore.getInstance().active.id).toBe("foo");
});
}); });
describe("with prod and dev clusters added", () => { describe("with prod and dev clusters added", () => {

View File

@ -124,7 +124,6 @@ export class KubernetesCluster extends CatalogEntity<CatalogEntityMetadata, Kube
context.menuItems.push({ context.menuItems.push({
title: "Disconnect", title: "Disconnect",
onClick: async () => { onClick: async () => {
ClusterStore.getInstance().deactivate(this.metadata.uid);
requestMain(clusterDisconnectHandler, this.metadata.uid); requestMain(clusterDisconnectHandler, this.metadata.uid);
} }
}); });

View File

@ -22,7 +22,7 @@
import path from "path"; import path from "path";
import { app, ipcMain, ipcRenderer, remote, webFrame } from "electron"; import { app, ipcMain, ipcRenderer, remote, webFrame } from "electron";
import { unlink } from "fs-extra"; import { unlink } from "fs-extra";
import { action, comparer, computed, observable, reaction, makeObservable } from "mobx"; import { action, comparer, computed, makeObservable, observable, reaction } from "mobx";
import { BaseStore } from "./base-store"; import { BaseStore } from "./base-store";
import { Cluster, ClusterState } from "../main/cluster"; import { Cluster, ClusterState } from "../main/cluster";
import migrations from "../migrations/cluster-store"; import migrations from "../migrations/cluster-store";
@ -32,7 +32,6 @@ import { dumpConfigYaml } from "./kube-helpers";
import { saveToAppFiles } from "./utils/saveToAppFiles"; import { saveToAppFiles } from "./utils/saveToAppFiles";
import type { KubeConfig } from "@kubernetes/client-node"; import type { KubeConfig } from "@kubernetes/client-node";
import { handleRequest, requestMain, subscribeToBroadcast, unsubscribeAllFromBroadcast } from "./ipc"; import { handleRequest, requestMain, subscribeToBroadcast, unsubscribeAllFromBroadcast } from "./ipc";
import type { ResourceType } from "../renderer/components/cluster-settings/components/cluster-metrics-setting";
import { disposer, noop, toJS } from "./utils"; import { disposer, noop, toJS } from "./utils";
export interface ClusterIconUpload { export interface ClusterIconUpload {
@ -52,7 +51,6 @@ export type ClusterPrometheusMetadata = {
}; };
export interface ClusterStoreModel { export interface ClusterStoreModel {
activeCluster?: ClusterId; // last opened cluster
clusters?: ClusterModel[]; clusters?: ClusterModel[];
} }
@ -131,9 +129,8 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
return filePath; return filePath;
} }
@observable activeCluster: ClusterId;
@observable removedClusters = observable.map<ClusterId, Cluster>();
@observable clusters = observable.map<ClusterId, Cluster>(); @observable clusters = observable.map<ClusterId, Cluster>();
@observable removedClusters = observable.map<ClusterId, Cluster>();
private static stateRequestChannel = "cluster:states"; private static stateRequestChannel = "cluster:states";
protected disposer = disposer(); protected disposer = disposer();
@ -217,43 +214,14 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
}); });
} }
get activeClusterId() {
return this.activeCluster;
}
@computed get clustersList(): Cluster[] { @computed get clustersList(): Cluster[] {
return Array.from(this.clusters.values()); return Array.from(this.clusters.values());
} }
@computed get active(): Cluster | null {
return this.getById(this.activeCluster);
}
@computed get connectedClustersList(): Cluster[] { @computed get connectedClustersList(): Cluster[] {
return this.clustersList.filter((c) => !c.disconnected); return this.clustersList.filter((c) => !c.disconnected);
} }
isActive(id: ClusterId) {
return this.activeCluster === id;
}
isMetricHidden(resource: ResourceType) {
return Boolean(this.active?.preferences.hiddenMetrics?.includes(resource));
}
@action
setActive(clusterId: ClusterId) {
this.activeCluster = this.clusters.has(clusterId)
? clusterId
: null;
}
deactivate(id: ClusterId) {
if (this.isActive(id)) {
this.setActive(null);
}
}
hasClusters() { hasClusters() {
return this.clusters.size > 0; return this.clusters.size > 0;
} }
@ -298,10 +266,6 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
if (cluster) { if (cluster) {
this.clusters.delete(clusterId); this.clusters.delete(clusterId);
if (this.activeCluster === clusterId) {
this.setActive(null);
}
// remove only custom kubeconfigs (pasted as text) // remove only custom kubeconfigs (pasted as text)
if (cluster.kubeConfigPath == ClusterStore.getCustomKubeConfigPath(clusterId)) { if (cluster.kubeConfigPath == ClusterStore.getCustomKubeConfigPath(clusterId)) {
await unlink(cluster.kubeConfigPath).catch(noop); await unlink(cluster.kubeConfigPath).catch(noop);
@ -310,7 +274,7 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
} }
@action @action
protected fromStore({ activeCluster, clusters = [] }: ClusterStoreModel = {}) { protected fromStore({ clusters = [] }: ClusterStoreModel = {}) {
const currentClusters = new Map(this.clusters); const currentClusters = new Map(this.clusters);
const newClusters = new Map<ClusterId, Cluster>(); const newClusters = new Map<ClusterId, Cluster>();
const removedClusters = new Map<ClusterId, Cluster>(); const removedClusters = new Map<ClusterId, Cluster>();
@ -338,14 +302,12 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
} }
}); });
this.setActive(activeCluster);
this.clusters.replace(newClusters); this.clusters.replace(newClusters);
this.removedClusters.replace(removedClusters); this.removedClusters.replace(removedClusters);
} }
toJSON(): ClusterStoreModel { toJSON(): ClusterStoreModel {
return toJS({ return toJS({
activeCluster: this.activeCluster,
clusters: this.clustersList.map(cluster => cluster.toJSON()), clusters: this.clustersList.map(cluster => cluster.toJSON()),
}); });
} }

View File

@ -22,7 +22,6 @@
// Extensions API -> Commands // Extensions API -> Commands
import { BaseRegistry } from "./base-registry"; import { BaseRegistry } from "./base-registry";
import { makeObservable, observable } from "mobx";
import type { LensExtension } from "../lens-extension"; import type { LensExtension } from "../lens-extension";
import type { CatalogEntity } from "../../common/catalog"; import type { CatalogEntity } from "../../common/catalog";
@ -39,14 +38,6 @@ export interface CommandRegistration {
} }
export class CommandRegistry extends BaseRegistry<CommandRegistration> { export class CommandRegistry extends BaseRegistry<CommandRegistration> {
@observable.ref activeEntity: CatalogEntity;
constructor() {
super();
makeObservable(this);
}
add(items: CommandRegistration | CommandRegistration[], extension?: LensExtension) { add(items: CommandRegistration | CommandRegistration[], extension?: LensExtension) {
const itemArray = [items].flat(); const itemArray = [items].flat();

View File

@ -50,6 +50,19 @@ export enum ClusterMetadataKey {
PROMETHEUS = "prometheus" PROMETHEUS = "prometheus"
} }
export enum ClusterMetricsResourceType {
Cluster = "Cluster",
Node = "Node",
Pod = "Pod",
Deployment = "Deployment",
StatefulSet = "StatefulSet",
Container = "Container",
Ingress = "Ingress",
VolumeClaim = "VolumeClaim",
ReplicaSet = "ReplicaSet",
DaemonSet = "DaemonSet",
}
export type ClusterRefreshOptions = { export type ClusterRefreshOptions = {
refreshMetadata?: boolean refreshMetadata?: boolean
}; };
@ -709,4 +722,8 @@ export class Cluster implements ClusterModel, ClusterState {
return true; // allowed by default for other resources return true; // allowed by default for other resources
} }
isMetricHidden(resource: ClusterMetricsResourceType): boolean {
return Boolean(this.preferences.hiddenMetrics?.includes(resource));
}
} }

View File

@ -19,15 +19,17 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
import { computed, observable, makeObservable } from "mobx"; import { computed, makeObservable, observable } from "mobx";
import { subscribeToBroadcast } from "../../common/ipc"; import { subscribeToBroadcast } from "../../common/ipc";
import { CatalogCategory, CatalogEntity, CatalogEntityData, catalogCategoryRegistry, CatalogCategoryRegistry, CatalogEntityKindData } from "../../common/catalog"; import { CatalogCategory, catalogCategoryRegistry, CatalogCategoryRegistry, CatalogEntity, CatalogEntityData, CatalogEntityKindData } from "../../common/catalog";
import "../../common/catalog-entities"; import "../../common/catalog-entities";
import { iter } from "../utils"; import { iter } from "../utils";
import type { Cluster } from "../../main/cluster";
import { ClusterStore } from "../../common/cluster-store";
export class CatalogEntityRegistry { export class CatalogEntityRegistry {
protected rawItems = observable.array<CatalogEntityData & CatalogEntityKindData>([], { deep: true }); protected rawItems = observable.array<CatalogEntityData & CatalogEntityKindData>();
@observable protected _activeEntity: CatalogEntity; @observable.ref activeEntity?: CatalogEntity;
constructor(private categoryRegistry: CatalogCategoryRegistry) { constructor(private categoryRegistry: CatalogCategoryRegistry) {
makeObservable(this); makeObservable(this);
@ -39,14 +41,6 @@ export class CatalogEntityRegistry {
}); });
} }
set activeEntity(entity: CatalogEntity) {
this._activeEntity = entity;
}
get activeEntity() {
return this._activeEntity;
}
@computed get items() { @computed get items() {
return Array.from(iter.filterMap(this.rawItems, rawItem => this.categoryRegistry.getEntityForData(rawItem))); return Array.from(iter.filterMap(this.rawItems, rawItem => this.categoryRegistry.getEntityForData(rawItem)));
} }
@ -74,3 +68,7 @@ export class CatalogEntityRegistry {
} }
export const catalogEntityRegistry = new CatalogEntityRegistry(catalogCategoryRegistry); export const catalogEntityRegistry = new CatalogEntityRegistry(catalogCategoryRegistry);
export function getActiveClusterEntity(): Cluster | undefined {
return ClusterStore.getInstance().getById(catalogEntityRegistry.activeEntity?.getId());
}

View File

@ -20,8 +20,8 @@
*/ */
import { navigate } from "../navigation"; import { navigate } from "../navigation";
import { commandRegistry } from "../../extensions/registries"; import type { CatalogEntity } from "../../common/catalog";
import type { CatalogEntity } from "../../common/catalog"; import { catalogEntityRegistry } from "./catalog-entity-registry";
export { CatalogCategory, CatalogEntity } from "../../common/catalog"; export { CatalogCategory, CatalogEntity } from "../../common/catalog";
export type { export type {
@ -37,6 +37,6 @@ export type {
export const catalogEntityRunContext = { export const catalogEntityRunContext = {
navigate: (url: string) => navigate(url), navigate: (url: string) => navigate(url),
setCommandPaletteContext: (entity?: CatalogEntity) => { setCommandPaletteContext: (entity?: CatalogEntity) => {
commandRegistry.activeEntity = entity; catalogEntityRegistry.activeEntity = entity;
} }
}; };

View File

@ -26,7 +26,7 @@ import { reaction } from "mobx";
import { disposeOnUnmount, observer } from "mobx-react"; import { disposeOnUnmount, observer } from "mobx-react";
import { nodesStore } from "../+nodes/nodes.store"; import { nodesStore } from "../+nodes/nodes.store";
import { podsStore } from "../+workloads-pods/pods.store"; import { podsStore } from "../+workloads-pods/pods.store";
import { ClusterStore, getHostedCluster } from "../../../common/cluster-store"; import { getHostedCluster } from "../../../common/cluster-store";
import { interval } from "../../utils"; import { interval } from "../../utils";
import { TabLayout } from "../layout/tab-layout"; import { TabLayout } from "../layout/tab-layout";
import { Spinner } from "../spinner"; import { Spinner } from "../spinner";
@ -34,7 +34,8 @@ import { ClusterIssues } from "./cluster-issues";
import { ClusterMetrics } from "./cluster-metrics"; import { ClusterMetrics } from "./cluster-metrics";
import { clusterOverviewStore } from "./cluster-overview.store"; import { clusterOverviewStore } from "./cluster-overview.store";
import { ClusterPieCharts } from "./cluster-pie-charts"; import { ClusterPieCharts } from "./cluster-pie-charts";
import { ResourceType } from "../cluster-settings/components/cluster-metrics-setting"; import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
import { ClusterMetricsResourceType } from "../../../main/cluster";
@observer @observer
export class ClusterOverview extends React.Component { export class ClusterOverview extends React.Component {
@ -87,12 +88,12 @@ export class ClusterOverview extends React.Component {
render() { render() {
const isLoaded = nodesStore.isLoaded && podsStore.isLoaded; const isLoaded = nodesStore.isLoaded && podsStore.isLoaded;
const isMetricsHidden = ClusterStore.getInstance().isMetricHidden(ResourceType.Cluster); const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Cluster);
return ( return (
<TabLayout> <TabLayout>
<div className="ClusterOverview"> <div className="ClusterOverview">
{this.renderClusterOverview(isLoaded, isMetricsHidden)} {this.renderClusterOverview(isLoaded, isMetricHidden)}
</div> </div>
</TabLayout> </TabLayout>
); );

View File

@ -35,8 +35,8 @@ import { IngressCharts } from "./ingress-charts";
import { KubeObjectMeta } from "../kube-object/kube-object-meta"; import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry"; import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
import { getBackendServiceNamePort } from "../../api/endpoints/ingress.api"; import { getBackendServiceNamePort } from "../../api/endpoints/ingress.api";
import { ResourceType } from "../cluster-settings/components/cluster-metrics-setting"; import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
import { ClusterStore } from "../../../common/cluster-store"; import { ClusterMetricsResourceType } from "../../../main/cluster";
interface Props extends KubeObjectDetailsProps<Ingress> { interface Props extends KubeObjectDetailsProps<Ingress> {
} }
@ -74,7 +74,7 @@ export class IngressDetails extends React.Component<Props> {
{ {
rule.http.paths.map((path, index) => { rule.http.paths.map((path, index) => {
const { serviceName, servicePort } = getBackendServiceNamePort(path.backend); const { serviceName, servicePort } = getBackendServiceNamePort(path.backend);
const backend =`${serviceName}:${servicePort}`; const backend = `${serviceName}:${servicePort}`;
return ( return (
<TableRow key={index}> <TableRow key={index}>
@ -94,22 +94,23 @@ export class IngressDetails extends React.Component<Props> {
} }
renderIngressPoints(ingressPoints: ILoadBalancerIngress[]) { renderIngressPoints(ingressPoints: ILoadBalancerIngress[]) {
if (!ingressPoints || ingressPoints.length === 0) return null; if (!ingressPoints || ingressPoints.length === 0) return null;
return ( return (
<div> <div>
<Table className="ingress-points"> <Table className="ingress-points">
<TableHead> <TableHead>
<TableCell className="name" >Hostname</TableCell> <TableCell className="name">Hostname</TableCell>
<TableCell className="ingresspoints">IP</TableCell> <TableCell className="ingresspoints">IP</TableCell>
</TableHead> </TableHead>
{ingressPoints.map(({hostname, ip}, index) => { {ingressPoints.map(({ hostname, ip }, index) => {
return ( return (
<TableRow key={index}> <TableRow key={index}>
<TableCell className="name">{hostname ? hostname : "-"}</TableCell> <TableCell className="name">{hostname ? hostname : "-"}</TableCell>
<TableCell className="ingresspoints">{ip ? ip : "-"}</TableCell> <TableCell className="ingresspoints">{ip ? ip : "-"}</TableCell>
</TableRow> </TableRow>
);}) );
})
}) })
</Table> </Table>
</div> </div>
@ -130,7 +131,7 @@ export class IngressDetails extends React.Component<Props> {
"Network", "Network",
"Duration", "Duration",
]; ];
const isMetricHidden = ClusterStore.getInstance().isMetricHidden(ResourceType.Ingress); const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Ingress);
const { serviceName, servicePort } = ingress.getServiceNamePort(); const { serviceName, servicePort } = ingress.getServiceNamePort();
return ( return (

View File

@ -38,8 +38,8 @@ import { PodDetailsList } from "../+workloads-pods/pod-details-list";
import { KubeObjectMeta } from "../kube-object/kube-object-meta"; import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { KubeEventDetails } from "../+events/kube-event-details"; import { KubeEventDetails } from "../+events/kube-event-details";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry"; import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
import { ResourceType } from "../cluster-settings/components/cluster-metrics-setting"; import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
import { ClusterStore } from "../../../common/cluster-store"; import { ClusterMetricsResourceType } from "../../../main/cluster";
import { NodeDetailsResources } from "./node-details-resources"; import { NodeDetailsResources } from "./node-details-resources";
import { DrawerTitle } from "../drawer/drawer-title"; import { DrawerTitle } from "../drawer/drawer-title";
@ -77,7 +77,7 @@ export class NodeDetails extends React.Component<Props> {
"Disk", "Disk",
"Pods", "Pods",
]; ];
const isMetricHidden = ClusterStore.getInstance().isMetricHidden(ResourceType.Node); const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Node);
return ( return (
<div className="NodeDetails"> <div className="NodeDetails">

View File

@ -35,8 +35,8 @@ import { VolumeClaimDiskChart } from "./volume-claim-disk-chart";
import { getDetailsUrl, KubeObjectDetailsProps, KubeObjectMeta } from "../kube-object"; import { getDetailsUrl, KubeObjectDetailsProps, KubeObjectMeta } from "../kube-object";
import type { PersistentVolumeClaim } from "../../api/endpoints"; import type { PersistentVolumeClaim } from "../../api/endpoints";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry"; import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
import { ResourceType } from "../cluster-settings/components/cluster-metrics-setting"; import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
import { ClusterStore } from "../../../common/cluster-store"; import { ClusterMetricsResourceType } from "../../../main/cluster";
interface Props extends KubeObjectDetailsProps<PersistentVolumeClaim> { interface Props extends KubeObjectDetailsProps<PersistentVolumeClaim> {
} }
@ -64,7 +64,7 @@ export class PersistentVolumeClaimDetails extends React.Component<Props> {
const metricTabs = [ const metricTabs = [
"Disk" "Disk"
]; ];
const isMetricHidden = ClusterStore.getInstance().isMetricHidden(ResourceType.VolumeClaim); const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.VolumeClaim);
return ( return (
<div className="PersistentVolumeClaimDetails"> <div className="PersistentVolumeClaimDetails">

View File

@ -39,8 +39,8 @@ import { reaction } from "mobx";
import { PodDetailsList } from "../+workloads-pods/pod-details-list"; import { PodDetailsList } from "../+workloads-pods/pod-details-list";
import { KubeObjectMeta } from "../kube-object/kube-object-meta"; import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry"; import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
import { ResourceType } from "../cluster-settings/components/cluster-metrics-setting"; import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
import { ClusterStore } from "../../../common/cluster-store"; import { ClusterMetricsResourceType } from "../../../main/cluster";
interface Props extends KubeObjectDetailsProps<DaemonSet> { interface Props extends KubeObjectDetailsProps<DaemonSet> {
} }
@ -70,7 +70,7 @@ export class DaemonSetDetails extends React.Component<Props> {
const nodeSelector = daemonSet.getNodeSelectors(); const nodeSelector = daemonSet.getNodeSelectors();
const childPods = daemonSetStore.getChildPods(daemonSet); const childPods = daemonSetStore.getChildPods(daemonSet);
const metrics = daemonSetStore.metrics; const metrics = daemonSetStore.metrics;
const isMetricHidden = ClusterStore.getInstance().isMetricHidden(ResourceType.DaemonSet); const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.DaemonSet);
return ( return (
<div className="DaemonSetDetails"> <div className="DaemonSetDetails">

View File

@ -40,10 +40,10 @@ import { reaction } from "mobx";
import { PodDetailsList } from "../+workloads-pods/pod-details-list"; import { PodDetailsList } from "../+workloads-pods/pod-details-list";
import { KubeObjectMeta } from "../kube-object/kube-object-meta"; import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry"; import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
import { ResourceType } from "../cluster-settings/components/cluster-metrics-setting";
import { ClusterStore } from "../../../common/cluster-store";
import { replicaSetStore } from "../+workloads-replicasets/replicasets.store"; import { replicaSetStore } from "../+workloads-replicasets/replicasets.store";
import { DeploymentReplicaSets } from "./deployment-replicasets"; import { DeploymentReplicaSets } from "./deployment-replicasets";
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
import { ClusterMetricsResourceType } from "../../../main/cluster";
interface Props extends KubeObjectDetailsProps<Deployment> { interface Props extends KubeObjectDetailsProps<Deployment> {
} }
@ -74,7 +74,7 @@ export class DeploymentDetails extends React.Component<Props> {
const childPods = deploymentStore.getChildPods(deployment); const childPods = deploymentStore.getChildPods(deployment);
const replicaSets = replicaSetStore.getReplicaSetsByOwner(deployment); const replicaSets = replicaSetStore.getReplicaSetsByOwner(deployment);
const metrics = deploymentStore.metrics; const metrics = deploymentStore.metrics;
const isMetricHidden = ClusterStore.getInstance().isMetricHidden(ResourceType.Deployment); const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Deployment);
return ( return (
<div className="DeploymentDetails"> <div className="DeploymentDetails">

View File

@ -32,9 +32,9 @@ import { PodContainerPort } from "./pod-container-port";
import { ResourceMetrics } from "../resource-metrics"; import { ResourceMetrics } from "../resource-metrics";
import type { IMetrics } from "../../api/endpoints/metrics.api"; import type { IMetrics } from "../../api/endpoints/metrics.api";
import { ContainerCharts } from "./container-charts"; import { ContainerCharts } from "./container-charts";
import { ResourceType } from "../cluster-settings/components/cluster-metrics-setting";
import { LocaleDate } from "../locale-date"; import { LocaleDate } from "../locale-date";
import { ClusterStore } from "../../../common/cluster-store"; import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
import { ClusterMetricsResourceType } from "../../../main/cluster";
interface Props { interface Props {
pod: Pod; pod: Pod;
@ -89,7 +89,7 @@ export class PodDetailsContainer extends React.Component<Props> {
"Memory", "Memory",
"Filesystem", "Filesystem",
]; ];
const isMetricHidden = ClusterStore.getInstance().isMetricHidden(ResourceType.Container); const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Container);
return ( return (
<div className="PodDetailsContainer"> <div className="PodDetailsContainer">
@ -125,7 +125,7 @@ export class PodDetailsContainer extends React.Component<Props> {
ports.map((port) => { ports.map((port) => {
const key = `${container.name}-port-${port.containerPort}-${port.protocol}`; const key = `${container.name}-port-${port.containerPort}-${port.protocol}`;
return( return (
<PodContainerPort pod={pod} port={port} key={key}/> <PodContainerPort pod={pod} port={port} key={key}/>
); );
}) })

View File

@ -43,8 +43,8 @@ import { getItemMetrics } from "../../api/endpoints/metrics.api";
import { PodCharts, podMetricTabs } from "./pod-charts"; import { PodCharts, podMetricTabs } from "./pod-charts";
import { KubeObjectMeta } from "../kube-object/kube-object-meta"; import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry"; import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
import { ResourceType } from "../cluster-settings/components/cluster-metrics-setting"; import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
import { ClusterStore } from "../../../common/cluster-store"; import { ClusterMetricsResourceType } from "../../../main/cluster";
interface Props extends KubeObjectDetailsProps<Pod> { interface Props extends KubeObjectDetailsProps<Pod> {
} }
@ -94,7 +94,7 @@ export class PodDetails extends React.Component<Props> {
const nodeSelector = pod.getNodeSelectors(); const nodeSelector = pod.getNodeSelectors();
const volumes = pod.getVolumes(); const volumes = pod.getVolumes();
const metrics = podsStore.metrics; const metrics = podsStore.metrics;
const isMetricHidden = ClusterStore.getInstance().isMetricHidden(ResourceType.Pod); const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Pod);
return ( return (
<div className="PodDetails"> <div className="PodDetails">

View File

@ -38,8 +38,8 @@ import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts";
import { PodDetailsList } from "../+workloads-pods/pod-details-list"; import { PodDetailsList } from "../+workloads-pods/pod-details-list";
import { KubeObjectMeta } from "../kube-object/kube-object-meta"; import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry"; import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
import { ResourceType } from "../cluster-settings/components/cluster-metrics-setting"; import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
import { ClusterStore } from "../../../common/cluster-store"; import { ClusterMetricsResourceType } from "../../../main/cluster";
interface Props extends KubeObjectDetailsProps<ReplicaSet> { interface Props extends KubeObjectDetailsProps<ReplicaSet> {
} }
@ -70,7 +70,7 @@ export class ReplicaSetDetails extends React.Component<Props> {
const nodeSelector = replicaSet.getNodeSelectors(); const nodeSelector = replicaSet.getNodeSelectors();
const images = replicaSet.getImages(); const images = replicaSet.getImages();
const childPods = replicaSetStore.getChildPods(replicaSet); const childPods = replicaSetStore.getChildPods(replicaSet);
const isMetricHidden = ClusterStore.getInstance().isMetricHidden(ResourceType.ReplicaSet); const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.ReplicaSet);
return ( return (
<div className="ReplicaSetDetails"> <div className="ReplicaSetDetails">

View File

@ -39,8 +39,8 @@ import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts";
import { PodDetailsList } from "../+workloads-pods/pod-details-list"; import { PodDetailsList } from "../+workloads-pods/pod-details-list";
import { KubeObjectMeta } from "../kube-object/kube-object-meta"; import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry"; import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
import { ResourceType } from "../cluster-settings/components/cluster-metrics-setting"; import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
import { ClusterStore } from "../../../common/cluster-store"; import { ClusterMetricsResourceType } from "../../../main/cluster";
interface Props extends KubeObjectDetailsProps<StatefulSet> { interface Props extends KubeObjectDetailsProps<StatefulSet> {
} }
@ -69,7 +69,7 @@ export class StatefulSetDetails extends React.Component<Props> {
const nodeSelector = statefulSet.getNodeSelectors(); const nodeSelector = statefulSet.getNodeSelectors();
const childPods = statefulSetStore.getChildPods(statefulSet); const childPods = statefulSetStore.getChildPods(statefulSet);
const metrics = statefulSetStore.metrics; const metrics = statefulSetStore.metrics;
const isMetricHidden = ClusterStore.getInstance().isMetricHidden(ResourceType.StatefulSet); const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.StatefulSet);
return ( return (
<div className="StatefulSetDetails"> <div className="StatefulSetDetails">
@ -117,7 +117,6 @@ export class StatefulSetDetails extends React.Component<Props> {
} }
} }
kubeObjectDetailRegistry.add({ kubeObjectDetailRegistry.add({
kind: "StatefulSet", kind: "StatefulSet",
apiVersions: ["apps/v1"], apiVersions: ["apps/v1"],

View File

@ -35,6 +35,8 @@ import { catalogURL } from "../+catalog/catalog.route";
@observer @observer
export class ClusterView extends React.Component { export class ClusterView extends React.Component {
private store = ClusterStore.getInstance();
constructor(props: {}) { constructor(props: {}) {
super(props); super(props);
makeObservable(this); makeObservable(this);
@ -45,7 +47,7 @@ export class ClusterView extends React.Component {
} }
@computed get cluster(): Cluster | undefined { @computed get cluster(): Cluster | undefined {
return ClusterStore.getInstance().getById(this.clusterId); return this.store.getById(this.clusterId);
} }
@computed get isReady(): boolean { @computed get isReady(): boolean {

View File

@ -22,7 +22,7 @@
import { navigate } from "../../navigation"; import { navigate } from "../../navigation";
import { commandRegistry } from "../../../extensions/registries/command-registry"; import { commandRegistry } from "../../../extensions/registries/command-registry";
import { entitySettingsURL } from "../+entity-settings"; import { entitySettingsURL } from "../+entity-settings";
import { ClusterStore } from "../../../common/cluster-store"; import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
commandRegistry.add({ commandRegistry.add({
id: "cluster.viewCurrentClusterSettings", id: "cluster.viewCurrentClusterSettings",
@ -30,7 +30,7 @@ commandRegistry.add({
scope: "global", scope: "global",
action: () => navigate(entitySettingsURL({ action: () => navigate(entitySettingsURL({
params: { params: {
entityId: ClusterStore.getInstance().active.id entityId: getActiveClusterEntity()?.id,
} }
})), })),
isActive: (context) => !!context.entity isActive: (context) => !!context.entity

View File

@ -25,26 +25,13 @@ import { Select, SelectOption } from "../../select/select";
import { Icon } from "../../icon/icon"; import { Icon } from "../../icon/icon";
import { Button } from "../../button/button"; import { Button } from "../../button/button";
import { SubTitle } from "../../layout/sub-title"; import { SubTitle } from "../../layout/sub-title";
import type { Cluster } from "../../../../main/cluster"; import { Cluster, ClusterMetricsResourceType } from "../../../../main/cluster";
import { observable, reaction, makeObservable } from "mobx"; import { observable, reaction, makeObservable } from "mobx";
interface Props { interface Props {
cluster: Cluster; cluster: Cluster;
} }
export enum ResourceType {
Cluster = "Cluster",
Node = "Node",
Pod = "Pod",
Deployment = "Deployment",
StatefulSet = "StatefulSet",
Container = "Container",
Ingress = "Ingress",
VolumeClaim = "VolumeClaim",
ReplicaSet = "ReplicaSet",
DaemonSet = "DaemonSet",
}
@observer @observer
export class ClusterMetricsSetting extends React.Component<Props> { export class ClusterMetricsSetting extends React.Component<Props> {
@observable hiddenMetrics = observable.set<string>(); @observable hiddenMetrics = observable.set<string>();
@ -68,7 +55,7 @@ export class ClusterMetricsSetting extends React.Component<Props> {
this.props.cluster.preferences.hiddenMetrics = Array.from(this.hiddenMetrics); this.props.cluster.preferences.hiddenMetrics = Array.from(this.hiddenMetrics);
}; };
onChangeSelect = (values: SelectOption<ResourceType>[]) => { onChangeSelect = (values: SelectOption<ClusterMetricsResourceType>[]) => {
for (const { value } of values) { for (const { value } of values) {
if (this.hiddenMetrics.has(value)) { if (this.hiddenMetrics.has(value)) {
this.hiddenMetrics.delete(value); this.hiddenMetrics.delete(value);
@ -80,7 +67,7 @@ export class ClusterMetricsSetting extends React.Component<Props> {
}; };
onChangeButton = () => { onChangeButton = () => {
Object.keys(ResourceType).map(value => Object.keys(ClusterMetricsResourceType).map(value =>
this.hiddenMetrics.add(value) this.hiddenMetrics.add(value)
); );
this.save(); this.save();
@ -91,7 +78,7 @@ export class ClusterMetricsSetting extends React.Component<Props> {
this.save(); this.save();
}; };
formatOptionLabel = ({ value: resource }: SelectOption<ResourceType>) => ( formatOptionLabel = ({ value: resource }: SelectOption<ClusterMetricsResourceType>) => (
<div className="flex gaps align-center"> <div className="flex gaps align-center">
<span>{resource}</span> <span>{resource}</span>
{this.hiddenMetrics.has(resource) && <Icon smallest material="check" className="box right" />} {this.hiddenMetrics.has(resource) && <Icon smallest material="check" className="box right" />}
@ -110,7 +97,7 @@ export class ClusterMetricsSetting extends React.Component<Props> {
onMenuClose={this.save} onMenuClose={this.save}
closeMenuOnSelect={false} closeMenuOnSelect={false}
controlShouldRenderValue={false} controlShouldRenderValue={false}
options={Object.values(ResourceType)} options={Object.values(ClusterMetricsResourceType)}
onChange={this.onChangeSelect} onChange={this.onChangeSelect}
formatOptionLabel={this.formatOptionLabel} formatOptionLabel={this.formatOptionLabel}
/> />

View File

@ -30,6 +30,7 @@ import { subscribeToBroadcast } from "../../../common/ipc";
import { CommandDialog } from "./command-dialog"; import { CommandDialog } from "./command-dialog";
import { CommandRegistration, commandRegistry } from "../../../extensions/registries/command-registry"; import { CommandRegistration, commandRegistry } from "../../../extensions/registries/command-registry";
import type { ClusterId } from "../../../common/cluster-store"; import type { ClusterId } from "../../../common/cluster-store";
import { catalogEntityRegistry } from "../../api/catalog-entity-registry";
export type CommandDialogEvent = { export type CommandDialogEvent = {
component: React.ReactElement component: React.ReactElement
@ -78,7 +79,7 @@ export class CommandContainer extends React.Component<CommandContainerProps> {
private runCommand(command: CommandRegistration) { private runCommand(command: CommandRegistration) {
command.action({ command.action({
entity: commandRegistry.activeEntity entity: catalogEntityRegistry.activeEntity
}); });
} }

View File

@ -25,11 +25,12 @@ import { computed, makeObservable, observable } from "mobx";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import React from "react"; import React from "react";
import { commandRegistry } from "../../../extensions/registries/command-registry"; import { commandRegistry } from "../../../extensions/registries/command-registry";
import { ClusterStore } from "../../../common/cluster-store";
import { CommandOverlay } from "./command-container"; import { CommandOverlay } from "./command-container";
import { broadcastMessage } from "../../../common/ipc"; import { broadcastMessage } from "../../../common/ipc";
import { navigate } from "../../navigation"; import { navigate } from "../../navigation";
import { clusterViewURL } from "../cluster-manager/cluster-view.route"; import { clusterViewURL } from "../cluster-manager/cluster-view.route";
import { catalogEntityRegistry } from "../../api/catalog-entity-registry";
import type { CatalogEntity } from "../../../common/catalog";
@observer @observer
export class CommandDialog extends React.Component { export class CommandDialog extends React.Component {
@ -40,13 +41,17 @@ export class CommandDialog extends React.Component {
makeObservable(this); makeObservable(this);
} }
@computed get activeEntity(): CatalogEntity | undefined {
return catalogEntityRegistry.activeEntity;
}
@computed get options() { @computed get options() {
const context = { const context = {
entity: commandRegistry.activeEntity entity: this.activeEntity
}; };
return commandRegistry.getItems().filter((command) => { return commandRegistry.getItems().filter((command) => {
if (command.scope === "entity" && !ClusterStore.getInstance().active) { if (command.scope === "entity" && !this.activeEntity) {
return false; return false;
} }
@ -78,15 +83,15 @@ export class CommandDialog extends React.Component {
if (command.scope === "global") { if (command.scope === "global") {
command.action({ command.action({
entity: commandRegistry.activeEntity entity: this.activeEntity
}); });
} else if(commandRegistry.activeEntity) { } else if(this.activeEntity) {
navigate(clusterViewURL({ navigate(clusterViewURL({
params: { params: {
clusterId: commandRegistry.activeEntity.metadata.uid clusterId: this.activeEntity.metadata.uid
} }
})); }));
broadcastMessage(`command-palette:run-action:${commandRegistry.activeEntity.metadata.uid}`, command.id); broadcastMessage(`command-palette:run-action:${this.activeEntity.metadata.uid}`, command.id);
} }
} catch(error) { } catch(error) {
console.error("[COMMAND-DIALOG] failed to execute command", command.id, error); console.error("[COMMAND-DIALOG] failed to execute command", command.id, error);

View File

@ -31,13 +31,11 @@ import { ConfirmDialog } from "./components/confirm-dialog";
import { ExtensionLoader } from "../extensions/extension-loader"; import { ExtensionLoader } from "../extensions/extension-loader";
import { broadcastMessage } from "../common/ipc"; import { broadcastMessage } from "../common/ipc";
import { CommandContainer } from "./components/command-palette/command-container"; import { CommandContainer } from "./components/command-palette/command-container";
import { LensProtocolRouterRenderer, bindProtocolAddRouteHandlers } from "./protocol-handler"; import { bindProtocolAddRouteHandlers, LensProtocolRouterRenderer } from "./protocol-handler";
import { registerIpcHandlers } from "./ipc"; import { registerIpcHandlers } from "./ipc";
import { ipcRenderer } from "electron"; import { ipcRenderer } from "electron";
import { IpcRendererNavigationEvents } from "./navigation/events"; import { IpcRendererNavigationEvents } from "./navigation/events";
import { catalogEntityRegistry } from "./api/catalog-entity-registry"; import { catalogEntityRegistry } from "./api/catalog-entity-registry";
import { commandRegistry } from "../extensions/registries";
import { reaction } from "mobx";
@observer @observer
export class LensApp extends React.Component { export class LensApp extends React.Component {
@ -54,18 +52,6 @@ export class LensApp extends React.Component {
ipcRenderer.send(IpcRendererNavigationEvents.LOADED); ipcRenderer.send(IpcRendererNavigationEvents.LOADED);
} }
componentDidMount() {
reaction(() => catalogEntityRegistry.items, (items) => {
if (!commandRegistry.activeEntity) {
return;
}
if (!items.includes(commandRegistry.activeEntity)) {
commandRegistry.activeEntity = null;
}
});
}
render() { render() {
return ( return (
<Router history={history}> <Router history={history}>