diff --git a/package-lock.json b/package-lock.json index 19a759a92702..9f974ed20bdf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4634,6 +4634,10 @@ "resolved": "packages/technical-features/messaging/electron/renderer", "link": true }, + "node_modules/@k8slens/metrics": { + "resolved": "packages/metrics", + "link": true + }, "node_modules/@k8slens/node-fetch": { "resolved": "packages/node-fetch", "link": true @@ -38340,6 +38344,7 @@ "@astronautlabs/jsonpath": "^1.1.0", "@hapi/call": "^9.0.1", "@hapi/subtext": "^7.1.0", + "@k8slens/metrics": "^6.5.0-alpha.1", "@k8slens/node-fetch": "^6.5.0-alpha.1", "@k8slens/react-application": "^1.0.0-alpha.0", "@kubernetes/client-node": "^0.18.1", @@ -42604,6 +42609,20 @@ "node": ">=10.13.0" } }, + "packages/metrics": { + "name": "@k8slens/metrics", + "version": "6.5.0-alpha.1", + "license": "MIT", + "devDependencies": { + "@k8slens/eslint-config": "6.5.0-alpha.1", + "@k8slens/jest": "6.5.0-alpha.1", + "@k8slens/typescript": "6.5.0-alpha.1" + }, + "peerDependencies": { + "@ogre-tools/injectable": "^15.1.2", + "react": "^17.0.2" + } + }, "packages/node-fetch": { "name": "@k8slens/node-fetch", "version": "6.5.0-alpha.1", diff --git a/packages/core/package.json b/packages/core/package.json index 6ddb5ae7948c..2ea1d36165bb 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -112,6 +112,7 @@ "@astronautlabs/jsonpath": "^1.1.0", "@hapi/call": "^9.0.1", "@hapi/subtext": "^7.1.0", + "@k8slens/metrics": "^6.5.0-alpha.1", "@k8slens/node-fetch": "^6.5.0-alpha.1", "@k8slens/react-application": "^1.0.0-alpha.0", "@kubernetes/client-node": "^0.18.1", diff --git a/packages/core/src/features/metrics/metrics-feature.ts b/packages/core/src/features/metrics/metrics-feature.ts new file mode 100644 index 000000000000..4bfb8454cfa5 --- /dev/null +++ b/packages/core/src/features/metrics/metrics-feature.ts @@ -0,0 +1,164 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getFeature } from "@k8slens/feature-core"; +import { clusterOverviewUIBlockInjectionToken, daemonSetDetailsMetricsInjectionToken, deploymentDetailsMetricsInjectionToken, jobDetailsMetricsInjectionToken, namespaceDetailsMetricsInjectionToken, ingressDetailsMetricsInjectionToken, nodeDetailsMetricsInjectionToken, persistentVolumeClaimDetailsMetricsInjectionToken, podDetailsContainerMetricsInjectionToken, podDetailsMetricsInjectionToken, replicaSetDetailsMetricsInjectionToken, statefulSetDetailsMetricsInjectionToken } from "@k8slens/metrics"; +import { getInjectable } from "@ogre-tools/injectable"; +import { ClusterMetrics } from "../../renderer/components/+cluster/cluster-metrics"; +import { ClusterPieCharts } from "../../renderer/components/+cluster/cluster-pie-charts"; +import { NamespaceMetricsDetailsComponent } from "../../renderer/components/+namespaces/metrics-details-component"; +import { NodeMetricsDetailsComponent } from "../../renderer/components/+nodes/metrics-details-component"; +import { PersistentVolumeClaimMetricsDetailsComponent } from "../../renderer/components/+storage-volume-claims/metrics-details-component"; +import { DaemonSetMetricsDetailsComponent } from "../../renderer/components/+workloads-daemonsets/metrics-details-component"; +import { DeploymentMetricsDetailsComponent } from "../../renderer/components/+workloads-deployments/metrics-details-component"; +import { JobMetricsDetailsComponent } from "../../renderer/components/+workloads-jobs/metrics-details-component"; +import { PodDetailsContainerMetrics } from "../../renderer/components/+workloads-pods/pod-details-container-metrics"; +import PodMetricsDetailsComponent from "../../renderer/components/+workloads-pods/pod-metrics-details-component"; +import { ReplicaSetMetricsDetailsComponent } from "../../renderer/components/+workloads-replicasets/metrics-details-component"; +import { StatefulSetMetricsDetailsComponent } from "../../renderer/components/+workloads-statefulsets/metrics-details-component"; +import { IngressMetricsDetailsComponent } from "../../renderer/components/+network-ingresses/metrics-details-component"; + +const clusterPieChartsClusterOverviewInjectable = getInjectable({ + id: "cluster-pie-charts-cluster-overview", + + instantiate: () => ({ + id: "cluster-pie-charts-cluster-overview", + Component: ClusterPieCharts, + orderNumber: 2, + }), + + injectionToken: clusterOverviewUIBlockInjectionToken, +}); + +const clusterMetricsOverviewBlockInjectable = getInjectable({ + id: "cluster-metrics-overview-block", + + instantiate: () => ({ + id: "cluster-metrics-overview-block", + Component: ClusterMetrics, + orderNumber: 1, + }), + + injectionToken: clusterOverviewUIBlockInjectionToken, +}); + +const podDetailsMetricsInjectable = getInjectable({ + id: "pod-details-metrics-injectable", + instantiate: () => ({ + id: "pod-details-metrics", + Component: PodMetricsDetailsComponent, + }), + injectionToken: podDetailsMetricsInjectionToken, +}); + +const deploymentDetailsMetricsInjectable = getInjectable({ + id: "deployment-details-metrics-injectable", + instantiate: () => ({ + id: "deployment-details-metrics", + Component: DeploymentMetricsDetailsComponent, + }), + injectionToken: deploymentDetailsMetricsInjectionToken, +}); + +const podDetailsContainerMetricsInjectable = getInjectable({ + id: "pod-details-container-metrics-injectable", + instantiate: () => ({ + id: "pod-details-container-metrics", + Component: PodDetailsContainerMetrics, + }), + injectionToken: podDetailsContainerMetricsInjectionToken, +}); + +const nodeDetailsMetricsInjectable = getInjectable({ + id: "node-details-metrics-injectable", + instantiate: () => ({ + id: "node-details-metrics", + Component: NodeMetricsDetailsComponent, + }), + injectionToken: nodeDetailsMetricsInjectionToken, +}); + +const replicaSetDetailsMetricsInjectable = getInjectable({ + id: "replica-set-details-metrics-injectable", + instantiate: () => ({ + id: "replica-set-details-metrics", + Component: ReplicaSetMetricsDetailsComponent, + }), + injectionToken: replicaSetDetailsMetricsInjectionToken, +}); + +const persistentVolumeClaimDetailsMetricsInjectable = getInjectable({ + id: "persistent-volume-claim-details-metrics-injectable", + instantiate: () => ({ + id: "persistent-volume-claim-details-metrics", + Component: PersistentVolumeClaimMetricsDetailsComponent, + }), + injectionToken: persistentVolumeClaimDetailsMetricsInjectionToken, +}); + +const statefulSetDetailsMetricsInjectable = getInjectable({ + id: "stateful-set-details-metrics-injectable", + instantiate: () => ({ + id: "stateful-set-details-metrics", + Component: StatefulSetMetricsDetailsComponent, + }), + injectionToken: statefulSetDetailsMetricsInjectionToken, +}); + +const namespaceDetailsMetricsInjectable = getInjectable({ + id: "namespace-details-metrics-injectable", + instantiate: () => ({ + id: "namespace-details-metrics", + Component: NamespaceMetricsDetailsComponent, + }), + injectionToken: namespaceDetailsMetricsInjectionToken, +}); + +const jobDetailsMetricsInjectable = getInjectable({ + id: "job-details-metrics-injectable", + instantiate: () => ({ + id: "job-details-metrics", + Component: JobMetricsDetailsComponent, + }), + injectionToken: jobDetailsMetricsInjectionToken, +}); + +const daemonSetDetailsMetricsInjectable = getInjectable({ + id: "daemon-set-details-metrics-injectable", + instantiate: () => ({ + id: "daemon-set-details-metrics", + Component: DaemonSetMetricsDetailsComponent, + }), + injectionToken: daemonSetDetailsMetricsInjectionToken, +}); + +const ingressDetailsMetricsInjectable = getInjectable({ + id: "network-ingress-details-metrics-injectable", + instantiate: () => ({ + id: "network-ingress-details-metrics", + Component: IngressMetricsDetailsComponent, + }), + injectionToken: ingressDetailsMetricsInjectionToken, +}); + +export const metricsFeature = getFeature({ + id: "core-metrics-feature", + + register: (di) => { + di.register(clusterPieChartsClusterOverviewInjectable); + di.register(clusterMetricsOverviewBlockInjectable); + + di.register(podDetailsMetricsInjectable); + di.register(podDetailsContainerMetricsInjectable); + di.register(deploymentDetailsMetricsInjectable); + di.register(nodeDetailsMetricsInjectable); + di.register(replicaSetDetailsMetricsInjectable); + di.register(persistentVolumeClaimDetailsMetricsInjectable); + di.register(statefulSetDetailsMetricsInjectable); + di.register(namespaceDetailsMetricsInjectable); + di.register(jobDetailsMetricsInjectable); + di.register(daemonSetDetailsMetricsInjectable); + di.register(ingressDetailsMetricsInjectable); + }, +}); diff --git a/packages/core/src/renderer/components/+cluster/cluster-overview.tsx b/packages/core/src/renderer/components/+cluster/cluster-overview.tsx index 75b3e8cd1e31..5b8f6c0bb192 100644 --- a/packages/core/src/renderer/components/+cluster/cluster-overview.tsx +++ b/packages/core/src/renderer/components/+cluster/cluster-overview.tsx @@ -15,9 +15,7 @@ import { interval } from "@k8slens/utilities"; import { TabLayout } from "../layout/tab-layout"; import { Spinner } from "../spinner"; import { ClusterIssues } from "./cluster-issues"; -import { ClusterMetrics } from "./cluster-metrics"; import type { ClusterOverviewStore } from "./cluster-overview-store/cluster-overview-store"; -import { ClusterPieCharts } from "./cluster-pie-charts"; import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import type { EventStore } from "../+events/store"; import { withInjectables } from "@ogre-tools/injectable-react"; @@ -28,6 +26,10 @@ import podStoreInjectable from "../+workloads-pods/store.injectable"; import eventStoreInjectable from "../+events/store.injectable"; import nodeStoreInjectable from "../+nodes/store.injectable"; import enabledMetricsInjectable from "../../api/catalog/entity/metrics-enabled.injectable"; +import type { ClusterOverviewUIBlock } from "@k8slens/metrics"; +import { clusterOverviewUIBlockInjectionToken } from "@k8slens/metrics"; +import { orderByOrderNumber } from "../../../common/utils/composable-responsibilities/orderable/orderable"; +import { computedInjectManyInjectable } from "@ogre-tools/injectable-extension-for-mobx"; interface Dependencies { subscribeStores: SubscribeStores; @@ -36,6 +38,7 @@ interface Dependencies { eventStore: EventStore; nodeStore: NodeStore; clusterMetricsAreVisible: IComputedValue; + uiBlocks: IComputedValue; } @observer @@ -76,8 +79,9 @@ class NonInjectedClusterOverview extends React.Component { return ( <> - - + {orderByOrderNumber(this.props.uiBlocks.get()).map((block) => ( + + ))} ); } @@ -118,5 +122,6 @@ export const ClusterOverview = withInjectables(NonInjectedClusterO podStore: di.inject(podStoreInjectable), eventStore: di.inject(eventStoreInjectable), nodeStore: di.inject(nodeStoreInjectable), + uiBlocks: di.inject(computedInjectManyInjectable)(clusterOverviewUIBlockInjectionToken), }), }); diff --git a/packages/core/src/renderer/components/+namespaces/metrics-details-component.injectable.tsx b/packages/core/src/renderer/components/+namespaces/metrics-details-component.tsx similarity index 55% rename from packages/core/src/renderer/components/+namespaces/metrics-details-component.injectable.tsx rename to packages/core/src/renderer/components/+namespaces/metrics-details-component.tsx index 026aace4f5fe..35590208f514 100644 --- a/packages/core/src/renderer/components/+namespaces/metrics-details-component.injectable.tsx +++ b/packages/core/src/renderer/components/+namespaces/metrics-details-component.tsx @@ -2,17 +2,13 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectable } from "@ogre-tools/injectable"; import type { IAsyncComputed } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react"; import React from "react"; import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts"; -import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import type { Namespace } from "../../../common/k8s-api/endpoints"; import type { PodMetricInNamespaceData } from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-in-namespace.injectable"; -import metricsDetailsComponentEnabledInjectable from "../../api/catalog/entity/metrics-details-component-enabled.injectable"; import type { KubeObjectDetailsProps } from "../kube-object-details"; -import { kubeObjectDetailItemInjectionToken } from "../kube-object-details/kube-object-detail-items/kube-object-detail-item-injection-token"; import { ResourceMetrics } from "../resource-metrics"; import namespaceMetricsInjectable from "./metrics.injectable"; @@ -33,21 +29,9 @@ const NonInjectedNamespaceMetricsDetailsComponent = ({ ); -const NamespaceMetricsDetailsComponent = withInjectables>(NonInjectedNamespaceMetricsDetailsComponent, { +export const NamespaceMetricsDetailsComponent = withInjectables>(NonInjectedNamespaceMetricsDetailsComponent, { getProps: (di, props) => ({ metrics: di.inject(namespaceMetricsInjectable, props.object), ...props, }), }); - -const namespaceMetricsDetailsComponentInjectable = getInjectable({ - id: "namespace-metrics-details-component", - instantiate: (di) => ({ - Component: NamespaceMetricsDetailsComponent, - enabled: di.inject(metricsDetailsComponentEnabledInjectable, ClusterMetricsResourceType.Namespace), - orderNumber: -1, - }), - injectionToken: kubeObjectDetailItemInjectionToken, -}); - -export default namespaceMetricsDetailsComponentInjectable; diff --git a/packages/core/src/renderer/components/+network-ingresses/metrics-details-component.injectable.tsx b/packages/core/src/renderer/components/+network-ingresses/metrics-details-component.tsx similarity index 55% rename from packages/core/src/renderer/components/+network-ingresses/metrics-details-component.injectable.tsx rename to packages/core/src/renderer/components/+network-ingresses/metrics-details-component.tsx index 62d8569ee59e..12f51d5fc78e 100644 --- a/packages/core/src/renderer/components/+network-ingresses/metrics-details-component.injectable.tsx +++ b/packages/core/src/renderer/components/+network-ingresses/metrics-details-component.tsx @@ -2,16 +2,12 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectable } from "@ogre-tools/injectable"; import type { IAsyncComputed } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react"; import React from "react"; -import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import type { Ingress } from "../../../common/k8s-api/endpoints"; import type { IngressMetricData } from "../../../common/k8s-api/endpoints/metrics.api/request-ingress-metrics.injectable"; -import metricsDetailsComponentEnabledInjectable from "../../api/catalog/entity/metrics-details-component-enabled.injectable"; import type { KubeObjectDetailsProps } from "../kube-object-details"; -import { kubeObjectDetailItemInjectionToken } from "../kube-object-details/kube-object-detail-items/kube-object-detail-item-injection-token"; import { ResourceMetrics } from "../resource-metrics"; import { IngressCharts } from "./ingress-charts"; import ingressMetricsInjectable from "./metrics.injectable"; @@ -36,21 +32,9 @@ const NonInjectedIngressMetricsDetailsComponent = ({ ); -const IngressMetricsDetailsComponent = withInjectables>(NonInjectedIngressMetricsDetailsComponent, { +export const IngressMetricsDetailsComponent = withInjectables>(NonInjectedIngressMetricsDetailsComponent, { getProps: (di, props) => ({ metrics: di.inject(ingressMetricsInjectable, props.object), ...props, }), }); - -const ingressMetricsDetailsComponentInjectable = getInjectable({ - id: "ingress-metrics-details-component", - instantiate: (di) => ({ - Component: IngressMetricsDetailsComponent, - enabled: di.inject(metricsDetailsComponentEnabledInjectable, ClusterMetricsResourceType.Ingress), - orderNumber: -1, - }), - injectionToken: kubeObjectDetailItemInjectionToken, -}); - -export default ingressMetricsDetailsComponentInjectable; diff --git a/packages/core/src/renderer/components/+nodes/metrics-details-component.injectable.tsx b/packages/core/src/renderer/components/+nodes/metrics-details-component.tsx similarity index 56% rename from packages/core/src/renderer/components/+nodes/metrics-details-component.injectable.tsx rename to packages/core/src/renderer/components/+nodes/metrics-details-component.tsx index 9a8d593d741a..c6eb33367f2c 100644 --- a/packages/core/src/renderer/components/+nodes/metrics-details-component.injectable.tsx +++ b/packages/core/src/renderer/components/+nodes/metrics-details-component.tsx @@ -2,16 +2,12 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectable } from "@ogre-tools/injectable"; import type { IAsyncComputed } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react"; import React from "react"; -import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import type { Node } from "../../../common/k8s-api/endpoints"; import type { ClusterMetricData } from "../../../common/k8s-api/endpoints/metrics.api/request-cluster-metrics-by-node-names.injectable"; -import metricsDetailsComponentEnabledInjectable from "../../api/catalog/entity/metrics-details-component-enabled.injectable"; import type { KubeObjectDetailsProps } from "../kube-object-details"; -import { kubeObjectDetailItemInjectionToken } from "../kube-object-details/kube-object-detail-items/kube-object-detail-item-injection-token"; import { ResourceMetrics } from "../resource-metrics"; import nodeMetricsInjectable from "./metrics.injectable"; import { NodeCharts } from "./node-charts"; @@ -38,21 +34,9 @@ const NonInjectedNodeMetricsDetailsComponent = ({ ); -const NodeMetricsDetailsComponent = withInjectables>(NonInjectedNodeMetricsDetailsComponent, { +export const NodeMetricsDetailsComponent = withInjectables>(NonInjectedNodeMetricsDetailsComponent, { getProps: (di, props) => ({ metrics: di.inject(nodeMetricsInjectable, props.object), ...props, }), }); - -const nodeMetricsDetailsComponentInjectable = getInjectable({ - id: "node-metrics-details-component", - instantiate: (di) => ({ - Component: NodeMetricsDetailsComponent, - enabled: di.inject(metricsDetailsComponentEnabledInjectable, ClusterMetricsResourceType.Node), - orderNumber: -1, - }), - injectionToken: kubeObjectDetailItemInjectionToken, -}); - -export default nodeMetricsDetailsComponentInjectable; diff --git a/packages/core/src/renderer/components/+storage-volume-claims/metrics-details-component.injectable.tsx b/packages/core/src/renderer/components/+storage-volume-claims/metrics-details-component.tsx similarity index 55% rename from packages/core/src/renderer/components/+storage-volume-claims/metrics-details-component.injectable.tsx rename to packages/core/src/renderer/components/+storage-volume-claims/metrics-details-component.tsx index b9edddf15746..d59d04ba23ea 100644 --- a/packages/core/src/renderer/components/+storage-volume-claims/metrics-details-component.injectable.tsx +++ b/packages/core/src/renderer/components/+storage-volume-claims/metrics-details-component.tsx @@ -2,16 +2,12 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectable } from "@ogre-tools/injectable"; import type { IAsyncComputed } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react"; import React from "react"; -import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import type { PersistentVolumeClaim } from "../../../common/k8s-api/endpoints"; import type { PersistentVolumeClaimMetricData } from "../../../common/k8s-api/endpoints/metrics.api/request-persistent-volume-claim-metrics.injectable"; -import metricsDetailsComponentEnabledInjectable from "../../api/catalog/entity/metrics-details-component-enabled.injectable"; import type { KubeObjectDetailsProps } from "../kube-object-details"; -import { kubeObjectDetailItemInjectionToken } from "../kube-object-details/kube-object-detail-items/kube-object-detail-item-injection-token"; import { ResourceMetrics } from "../resource-metrics"; import persistentVolumeClaimMetricsInjectable from "./metrics.injectable"; import { VolumeClaimDiskChart } from "./volume-claim-disk-chart"; @@ -35,21 +31,9 @@ const NonInjectedPersistentVolumeClaimMetricsDetailsComponent = ({ ); -const PersistentVolumeClaimMetricsDetailsComponent = withInjectables>(NonInjectedPersistentVolumeClaimMetricsDetailsComponent, { +export const PersistentVolumeClaimMetricsDetailsComponent = withInjectables>(NonInjectedPersistentVolumeClaimMetricsDetailsComponent, { getProps: (di, props) => ({ metrics: di.inject(persistentVolumeClaimMetricsInjectable, props.object), ...props, }), }); - -const persistentVolumeClaimMetricsDetailsComponentInjectable = getInjectable({ - id: "persistent-volume-claim-metrics-details-component", - instantiate: (di) => ({ - Component: PersistentVolumeClaimMetricsDetailsComponent, - enabled: di.inject(metricsDetailsComponentEnabledInjectable, ClusterMetricsResourceType.VolumeClaim), - orderNumber: -1, - }), - injectionToken: kubeObjectDetailItemInjectionToken, -}); - -export default persistentVolumeClaimMetricsDetailsComponentInjectable; diff --git a/packages/core/src/renderer/components/+workloads-daemonsets/metrics-details-component.injectable.tsx b/packages/core/src/renderer/components/+workloads-daemonsets/metrics-details-component.tsx similarity index 55% rename from packages/core/src/renderer/components/+workloads-daemonsets/metrics-details-component.injectable.tsx rename to packages/core/src/renderer/components/+workloads-daemonsets/metrics-details-component.tsx index 3975308f46e4..777e716609d9 100644 --- a/packages/core/src/renderer/components/+workloads-daemonsets/metrics-details-component.injectable.tsx +++ b/packages/core/src/renderer/components/+workloads-daemonsets/metrics-details-component.tsx @@ -2,17 +2,13 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectable } from "@ogre-tools/injectable"; import type { IAsyncComputed } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react"; import React from "react"; import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts"; -import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import type { DaemonSet } from "../../../common/k8s-api/endpoints"; import type { DaemonSetPodMetricData } from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-for-daemon-sets.injectable"; -import metricsDetailsComponentEnabledInjectable from "../../api/catalog/entity/metrics-details-component-enabled.injectable"; import type { KubeObjectDetailsProps } from "../kube-object-details"; -import { kubeObjectDetailItemInjectionToken } from "../kube-object-details/kube-object-detail-items/kube-object-detail-item-injection-token"; import { ResourceMetrics } from "../resource-metrics"; import daemonSetMetricsInjectable from "./metrics.injectable"; @@ -33,21 +29,9 @@ const NonInjectedDaemonSetMetricsDetailsComponent = ({ ); -const DaemonSetMetricsDetailsComponent = withInjectables>(NonInjectedDaemonSetMetricsDetailsComponent, { +export const DaemonSetMetricsDetailsComponent = withInjectables>(NonInjectedDaemonSetMetricsDetailsComponent, { getProps: (di, props) => ({ metrics: di.inject(daemonSetMetricsInjectable, props.object), ...props, }), }); - -const daemonSetMetricsDetailsComponentInjectable = getInjectable({ - id: "daemon-set-metrics-details-component", - instantiate: (di) => ({ - Component: DaemonSetMetricsDetailsComponent, - enabled: di.inject(metricsDetailsComponentEnabledInjectable, ClusterMetricsResourceType.DaemonSet), - orderNumber: -1, - }), - injectionToken: kubeObjectDetailItemInjectionToken, -}); - -export default daemonSetMetricsDetailsComponentInjectable; diff --git a/packages/core/src/renderer/components/+workloads-deployments/metrics-details-component.injectable.tsx b/packages/core/src/renderer/components/+workloads-deployments/metrics-details-component.tsx similarity index 55% rename from packages/core/src/renderer/components/+workloads-deployments/metrics-details-component.injectable.tsx rename to packages/core/src/renderer/components/+workloads-deployments/metrics-details-component.tsx index d40e93641dd0..196601c0d512 100644 --- a/packages/core/src/renderer/components/+workloads-deployments/metrics-details-component.injectable.tsx +++ b/packages/core/src/renderer/components/+workloads-deployments/metrics-details-component.tsx @@ -2,17 +2,13 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectable } from "@ogre-tools/injectable"; import type { IAsyncComputed } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react"; import React from "react"; import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts"; -import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import type { Deployment } from "../../../common/k8s-api/endpoints"; import type { DeploymentPodMetricData } from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-for-deployments.injectable"; -import metricsDetailsComponentEnabledInjectable from "../../api/catalog/entity/metrics-details-component-enabled.injectable"; import type { KubeObjectDetailsProps } from "../kube-object-details"; -import { kubeObjectDetailItemInjectionToken } from "../kube-object-details/kube-object-detail-items/kube-object-detail-item-injection-token"; import { ResourceMetrics } from "../resource-metrics"; import deploymentMetricsInjectable from "./metrics.injectable"; @@ -33,21 +29,9 @@ const NonInjectedDeploymentMetricsDetailsComponent = ({ ); -const DeploymentMetricsDetailsComponent = withInjectables>(NonInjectedDeploymentMetricsDetailsComponent, { +export const DeploymentMetricsDetailsComponent = withInjectables>(NonInjectedDeploymentMetricsDetailsComponent, { getProps: (di, props) => ({ metrics: di.inject(deploymentMetricsInjectable, props.object), ...props, }), }); - -const deploymentMetricsDetailsComponentInjectable = getInjectable({ - id: "deployment-metrics-details-component", - instantiate: (di) => ({ - Component: DeploymentMetricsDetailsComponent, - enabled: di.inject(metricsDetailsComponentEnabledInjectable, ClusterMetricsResourceType.Deployment), - orderNumber: -1, - }), - injectionToken: kubeObjectDetailItemInjectionToken, -}); - -export default deploymentMetricsDetailsComponentInjectable; diff --git a/packages/core/src/renderer/components/+workloads-jobs/metrics-details-component.injectable.tsx b/packages/core/src/renderer/components/+workloads-jobs/metrics-details-component.tsx similarity index 54% rename from packages/core/src/renderer/components/+workloads-jobs/metrics-details-component.injectable.tsx rename to packages/core/src/renderer/components/+workloads-jobs/metrics-details-component.tsx index 479086c17ca2..6588359fc5b5 100644 --- a/packages/core/src/renderer/components/+workloads-jobs/metrics-details-component.injectable.tsx +++ b/packages/core/src/renderer/components/+workloads-jobs/metrics-details-component.tsx @@ -2,16 +2,12 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectable } from "@ogre-tools/injectable"; import { type IAsyncComputed, withInjectables } from "@ogre-tools/injectable-react"; import React from "react"; import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts"; -import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import type { Job } from "../../../common/k8s-api/endpoints"; import type { JobPodMetricData } from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-for-jobs.injectable"; -import metricsDetailsComponentEnabledInjectable from "../../api/catalog/entity/metrics-details-component-enabled.injectable"; import type { KubeObjectDetailsProps } from "../kube-object-details"; -import { kubeObjectDetailItemInjectionToken } from "../kube-object-details/kube-object-detail-items/kube-object-detail-item-injection-token"; import { ResourceMetrics } from "../resource-metrics"; import jobMetricsInjectable from "./metrics.injectable"; @@ -32,21 +28,10 @@ const NonInjectedJobMetricsDetailsComponent = ({ ); -const JobMetricsDetailsComponent = withInjectables>(NonInjectedJobMetricsDetailsComponent, { +export const JobMetricsDetailsComponent = withInjectables>(NonInjectedJobMetricsDetailsComponent, { getProps: (di, props) => ({ metrics: di.inject(jobMetricsInjectable, props.object), ...props, }), }); -const jobMetricsDetailsComponentInjectable = getInjectable({ - id: "job-metrics-details-component", - instantiate: (di) => ({ - Component: JobMetricsDetailsComponent, - enabled: di.inject(metricsDetailsComponentEnabledInjectable, ClusterMetricsResourceType.Job), - orderNumber: -1, - }), - injectionToken: kubeObjectDetailItemInjectionToken, -}); - -export default jobMetricsDetailsComponentInjectable; diff --git a/packages/core/src/renderer/components/+workloads-pods/details/containers/pod-details-containers.tsx b/packages/core/src/renderer/components/+workloads-pods/details/containers/pod-details-containers.tsx new file mode 100644 index 000000000000..1ee0636bc6eb --- /dev/null +++ b/packages/core/src/renderer/components/+workloads-pods/details/containers/pod-details-containers.tsx @@ -0,0 +1,32 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import React from "react"; +import { DrawerTitle } from "../../../drawer"; +import { PodDetailsContainer } from "../../pod-details-container"; +import type { Pod } from "../../../../../common/k8s-api/endpoints"; +import { observer } from "mobx-react"; + +interface PodDetailsContainersProps { + pod: Pod; +} + +const PodDetailsContainers = observer(({ pod }: PodDetailsContainersProps) => { + const containers = pod.getContainers(); + + return ( + <> + Containers + {containers.map(container => ( + + ))} + + ); +}); + +export { PodDetailsContainers }; diff --git a/packages/core/src/renderer/components/+workloads-pods/details/containers/pod-details-init-containers.tsx b/packages/core/src/renderer/components/+workloads-pods/details/containers/pod-details-init-containers.tsx new file mode 100644 index 000000000000..a66143323be4 --- /dev/null +++ b/packages/core/src/renderer/components/+workloads-pods/details/containers/pod-details-init-containers.tsx @@ -0,0 +1,36 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import React from "react"; +import { DrawerTitle } from "../../../drawer"; +import { PodDetailsContainer } from "../../pod-details-container"; +import type { Pod } from "../../../../../common/k8s-api/endpoints"; +import { observer } from "mobx-react"; + +interface PodDetailsContainersProps { + pod: Pod; +} + +const PodDetailsInitContainers = observer(({ pod }: PodDetailsContainersProps) => { + const initContainers = pod.getInitContainers(); + + if (initContainers.length === 0) { + return null; + } + + return ( + <> + Init Containers + {initContainers.map(container => ( + + ))} + + ); +}); + +export { PodDetailsInitContainers }; diff --git a/packages/core/src/renderer/components/+workloads-pods/pod-details-container-metrics.tsx b/packages/core/src/renderer/components/+workloads-pods/pod-details-container-metrics.tsx new file mode 100644 index 000000000000..57907f87af66 --- /dev/null +++ b/packages/core/src/renderer/components/+workloads-pods/pod-details-container-metrics.tsx @@ -0,0 +1,53 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { IAsyncComputed } from "@ogre-tools/injectable-react"; +import { withInjectables } from "@ogre-tools/injectable-react"; +import { toJS } from "mobx"; +import { observer } from "mobx-react-lite"; +import React from "react"; +import type { Container, Pod } from "../../../common/k8s-api/endpoints"; +import { getItemMetrics } from "../../../common/k8s-api/endpoints/metrics.api"; +import type { PodMetricData } from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics.injectable"; +import { ResourceMetrics } from "../resource-metrics"; +import { ContainerCharts } from "./container-charts"; +import podContainerMetricsInjectable from "./container-metrics.injectable"; + +interface ContainerMetricsProps { + container: Container; + pod: Pod; +} + +interface Dependencies { + podContainerMetrics: IAsyncComputed; +} + +const NonInjectedPodDetailsContainerMetrics = observer(({ pod, container, podContainerMetrics }: ContainerMetricsProps & Dependencies) => { + const metrics = getItemMetrics(toJS(podContainerMetrics.value.get()), container.name); + + if (!metrics) { + return null; + } + + return ( + + + + ); +}); + +export const PodDetailsContainerMetrics = withInjectables(NonInjectedPodDetailsContainerMetrics, { + getProps: (di, props) => ({ + ...props, + podContainerMetrics: di.inject(podContainerMetricsInjectable, props.pod), + }), +}); diff --git a/packages/core/src/renderer/components/+workloads-pods/pod-details-container.tsx b/packages/core/src/renderer/components/+workloads-pods/pod-details-container.tsx index d066497780d9..d5127d978a56 100644 --- a/packages/core/src/renderer/components/+workloads-pods/pod-details-container.tsx +++ b/packages/core/src/renderer/components/+workloads-pods/pod-details-container.tsx @@ -13,9 +13,6 @@ import { StatusBrick } from "../status-brick"; import { Badge } from "../badge"; import { ContainerEnvironment } from "./pod-container-env"; import { PodContainerPort } from "./pod-container-port"; -import { ResourceMetrics } from "../resource-metrics"; -import type { MetricData } from "../../../common/k8s-api/endpoints/metrics.api"; -import { ContainerCharts } from "./container-charts"; import { LocaleDate } from "../locale-date"; import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import type { PortForwardStore } from "../../port-forward"; @@ -24,16 +21,18 @@ import { withInjectables } from "@ogre-tools/injectable-react"; import portForwardStoreInjectable from "../../port-forward/port-forward-store/port-forward-store.injectable"; import type { IComputedValue } from "mobx"; import enabledMetricsInjectable from "../../api/catalog/entity/metrics-enabled.injectable"; +import type { PodDetailsContainerMetricsComponent } from "@k8slens/metrics"; +import { podDetailsContainerMetricsInjectionToken } from "@k8slens/metrics"; export interface PodDetailsContainerProps { pod: Pod; container: Container; - metrics?: Partial>; } interface Dependencies { portForwardStore: PortForwardStore; containerMetricsVisible: IComputedValue; + containerMetrics: PodDetailsContainerMetricsComponent[]; } @observer @@ -84,7 +83,7 @@ class NonInjectedPodDetailsContainer extends React.Component {name} - {(isMetricVisible && !isInitContainer && metrics) && ( - - - + {(isMetricVisible && !isInitContainer) && ( + <> + {containerMetrics.map(ContainerMetrics => ( + + ))} + )} {status && ( @@ -218,5 +214,6 @@ export const PodDetailsContainer = withInjectables { } @@ -45,13 +41,12 @@ interface Dependencies { runtimeClassApi: RuntimeClassApi; serviceAccountApi: ServiceAccountApi; logger: Logger; - containerMetrics: IAsyncComputed; } @observer class NonInjectedPodDetails extends React.Component { render() { - const { object: pod, getDetailsUrl, nodeApi, logger, containerMetrics } = this.props; + const { object: pod, getDetailsUrl, nodeApi, logger } = this.props; if (!pod) { return null; @@ -68,8 +63,6 @@ class NonInjectedPodDetails extends React.Component - {initContainers.length > 0 && ( - <> - Init Containers - {initContainers.map(container => ( - - ))} - - )} - - Containers - {containers.map(container => ( - - ))} + + + @@ -207,6 +181,5 @@ export const PodDetails = withInjectables(NonInje runtimeClassApi: di.inject(runtimeClassApiInjectable), serviceAccountApi: di.inject(serviceAccountApiInjectable), logger: di.inject(loggerInjectable), - containerMetrics: di.inject(podContainerMetricsInjectable, props.object), }), }); diff --git a/packages/core/src/renderer/components/+workloads-pods/metrics-detail-container.injectable.tsx b/packages/core/src/renderer/components/+workloads-pods/pod-metrics-details-component.tsx similarity index 60% rename from packages/core/src/renderer/components/+workloads-pods/metrics-detail-container.injectable.tsx rename to packages/core/src/renderer/components/+workloads-pods/pod-metrics-details-component.tsx index aab325ab9b1b..0647a57f6c7b 100644 --- a/packages/core/src/renderer/components/+workloads-pods/metrics-detail-container.injectable.tsx +++ b/packages/core/src/renderer/components/+workloads-pods/pod-metrics-details-component.tsx @@ -2,15 +2,11 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectable } from "@ogre-tools/injectable"; import { type IAsyncComputed, withInjectables } from "@ogre-tools/injectable-react"; import React from "react"; -import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import type { Pod } from "../../../common/k8s-api/endpoints"; import type { PodMetricData } from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics.injectable"; -import metricsDetailsComponentEnabledInjectable from "../../api/catalog/entity/metrics-details-component-enabled.injectable"; import type { KubeObjectDetailsProps } from "../kube-object-details"; -import { kubeObjectDetailItemInjectionToken } from "../kube-object-details/kube-object-detail-items/kube-object-detail-item-injection-token"; import { ResourceMetrics } from "../resource-metrics"; import podMetricsInjectable from "./metrics.injectable"; import { PodCharts, podMetricTabs } from "./pod-charts"; @@ -39,14 +35,4 @@ const PodMetricsDetailsComponent = withInjectables ({ - Component: PodMetricsDetailsComponent, - enabled: di.inject(metricsDetailsComponentEnabledInjectable, ClusterMetricsResourceType.Pod), - orderNumber: -1, - }), - injectionToken: kubeObjectDetailItemInjectionToken, -}); - -export default podMetricsDetailsComponentInjectable; +export default PodMetricsDetailsComponent; diff --git a/packages/core/src/renderer/components/+workloads-replicasets/metrics-details-component.injectable.tsx b/packages/core/src/renderer/components/+workloads-replicasets/metrics-details-component.tsx similarity index 54% rename from packages/core/src/renderer/components/+workloads-replicasets/metrics-details-component.injectable.tsx rename to packages/core/src/renderer/components/+workloads-replicasets/metrics-details-component.tsx index 9c57bea78eb1..5b9ea8d99c84 100644 --- a/packages/core/src/renderer/components/+workloads-replicasets/metrics-details-component.injectable.tsx +++ b/packages/core/src/renderer/components/+workloads-replicasets/metrics-details-component.tsx @@ -2,16 +2,12 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectable } from "@ogre-tools/injectable"; import { type IAsyncComputed, withInjectables } from "@ogre-tools/injectable-react"; import React from "react"; import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts"; -import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import type { ReplicaSet } from "../../../common/k8s-api/endpoints"; import type { ReplicaSetPodMetricData } from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-for-replica-sets.injectable"; -import metricsDetailsComponentEnabledInjectable from "../../api/catalog/entity/metrics-details-component-enabled.injectable"; import type { KubeObjectDetailsProps } from "../kube-object-details"; -import { kubeObjectDetailItemInjectionToken } from "../kube-object-details/kube-object-detail-items/kube-object-detail-item-injection-token"; import { ResourceMetrics } from "../resource-metrics"; import replicaSetMetricsInjectable from "./metrics.injectable"; @@ -32,21 +28,9 @@ const NonInjectedReplicaSetMetricsDetailsComponent = ({ ); -const ReplicaSetMetricsDetailsComponent = withInjectables>(NonInjectedReplicaSetMetricsDetailsComponent, { +export const ReplicaSetMetricsDetailsComponent = withInjectables>(NonInjectedReplicaSetMetricsDetailsComponent, { getProps: (di, props) => ({ metrics: di.inject(replicaSetMetricsInjectable, props.object), ...props, }), }); - -const replicaSetMetricsDetailsComponentInjectable = getInjectable({ - id: "replica-set-metrics-details-component", - instantiate: (di) => ({ - Component: ReplicaSetMetricsDetailsComponent, - enabled: di.inject(metricsDetailsComponentEnabledInjectable, ClusterMetricsResourceType.ReplicaSet), - orderNumber: -1, - }), - injectionToken: kubeObjectDetailItemInjectionToken, -}); - -export default replicaSetMetricsDetailsComponentInjectable; diff --git a/packages/core/src/renderer/components/+workloads-statefulsets/metrics-details-component.injectable.tsx b/packages/core/src/renderer/components/+workloads-statefulsets/metrics-details-component.tsx similarity index 54% rename from packages/core/src/renderer/components/+workloads-statefulsets/metrics-details-component.injectable.tsx rename to packages/core/src/renderer/components/+workloads-statefulsets/metrics-details-component.tsx index ad4bb6d67772..3b104ca8c310 100644 --- a/packages/core/src/renderer/components/+workloads-statefulsets/metrics-details-component.injectable.tsx +++ b/packages/core/src/renderer/components/+workloads-statefulsets/metrics-details-component.tsx @@ -2,16 +2,12 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectable } from "@ogre-tools/injectable"; import { type IAsyncComputed, withInjectables } from "@ogre-tools/injectable-react"; import React from "react"; import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts"; -import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import type { StatefulSet } from "../../../common/k8s-api/endpoints"; import type { StatefulSetPodMetricData } from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-for-stateful-sets.injectable"; -import metricsDetailsComponentEnabledInjectable from "../../api/catalog/entity/metrics-details-component-enabled.injectable"; import type { KubeObjectDetailsProps } from "../kube-object-details"; -import { kubeObjectDetailItemInjectionToken } from "../kube-object-details/kube-object-detail-items/kube-object-detail-item-injection-token"; import { ResourceMetrics } from "../resource-metrics"; import statefulSetMetricsInjectable from "./metrics.injectable"; @@ -32,21 +28,9 @@ const NonInjectedStatefulSetMetricsDetailsComponent = ({ ); -const StatefulSetMetricsDetailsComponent = withInjectables>(NonInjectedStatefulSetMetricsDetailsComponent, { +export const StatefulSetMetricsDetailsComponent = withInjectables>(NonInjectedStatefulSetMetricsDetailsComponent, { getProps: (di, props) => ({ metrics: di.inject(statefulSetMetricsInjectable, props.object), ...props, }), }); - -const statefulSetMetricsDetailsComponentInjectable = getInjectable({ - id: "stateful-set-metrics-details-component", - instantiate: (di) => ({ - Component: StatefulSetMetricsDetailsComponent, - enabled: di.inject(metricsDetailsComponentEnabledInjectable, ClusterMetricsResourceType.StatefulSet), - orderNumber: -1, - }), - injectionToken: kubeObjectDetailItemInjectionToken, -}); - -export default statefulSetMetricsDetailsComponentInjectable; diff --git a/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/daemon-set-details-metrics.injectable.ts b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/daemon-set-details-metrics.injectable.ts new file mode 100644 index 000000000000..e7f5771afa13 --- /dev/null +++ b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/daemon-set-details-metrics.injectable.ts @@ -0,0 +1,24 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { daemonSetDetailsMetricsInjectionToken } from "@k8slens/metrics"; +import { getInjectable } from "@ogre-tools/injectable"; +import { ClusterMetricsResourceType } from "../../../../../common/cluster-types"; +import { kubeObjectDetailItemInjectionToken } from "../kube-object-detail-item-injection-token"; +import { getMetricsKubeObjectDetailItemInjectable } from "./get-metrics-kube-object-detail-item.injectable"; + +const daemonSetMetricsInjectable = getInjectable({ + id: "daemon-set-details-metrics", + instantiate: (di) => { + const getMetricsKubeObjectDetailItem = di.inject(getMetricsKubeObjectDetailItemInjectable); + + return getMetricsKubeObjectDetailItem( + daemonSetDetailsMetricsInjectionToken, + ClusterMetricsResourceType.DaemonSet, + ); + }, + injectionToken: kubeObjectDetailItemInjectionToken, +}); + +export default daemonSetMetricsInjectable; diff --git a/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/deployment-details-metrics.injectable.ts b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/deployment-details-metrics.injectable.ts new file mode 100644 index 000000000000..31edffb12ff3 --- /dev/null +++ b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/deployment-details-metrics.injectable.ts @@ -0,0 +1,24 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { ClusterMetricsResourceType } from "../../../../../common/cluster-types"; +import { kubeObjectDetailItemInjectionToken } from "../kube-object-detail-item-injection-token"; +import { deploymentDetailsMetricsInjectionToken } from "@k8slens/metrics"; +import { getMetricsKubeObjectDetailItemInjectable } from "./get-metrics-kube-object-detail-item.injectable"; + +const deploymentMetricsInjectable = getInjectable({ + id: "deployment-details-metrics", + instantiate: (di) => { + const getMetricsKubeObjectDetailItem = di.inject(getMetricsKubeObjectDetailItemInjectable); + + return getMetricsKubeObjectDetailItem( + deploymentDetailsMetricsInjectionToken, + ClusterMetricsResourceType.Deployment, + ); + }, + injectionToken: kubeObjectDetailItemInjectionToken, +}); + +export default deploymentMetricsInjectable; diff --git a/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/details-metrics-container.tsx b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/details-metrics-container.tsx new file mode 100644 index 000000000000..bed0d62fc921 --- /dev/null +++ b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/details-metrics-container.tsx @@ -0,0 +1,22 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { KubeObjectDetailMetrics } from "@k8slens/metrics"; +import type { IComputedValue } from "mobx"; +import { observer } from "mobx-react"; +import React from "react"; +import type { KubeObject } from "../../../../../common/k8s-api/kube-object"; + +interface DetailsMetricsContainerProps { + metrics: IComputedValue; + object?: Kube; +} + +export const DetailsMetricsContainer = observer(({ metrics, object }: DetailsMetricsContainerProps) => ( + <> + {metrics.get().map((metrics) => ( + + ))} + +)); diff --git a/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/get-metrics-kube-object-detail-item.injectable.tsx b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/get-metrics-kube-object-detail-item.injectable.tsx new file mode 100644 index 000000000000..7aa3b874de01 --- /dev/null +++ b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/get-metrics-kube-object-detail-item.injectable.tsx @@ -0,0 +1,32 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import React from "react"; +import type { KubeObjectDetailMetrics } from "@k8slens/metrics"; +import type { InjectionToken } from "@ogre-tools/injectable"; +import { getInjectable } from "@ogre-tools/injectable"; +import type { ClusterMetricsResourceType } from "../../../../../common/cluster-types"; +import metricsDetailsComponentEnabledInjectable from "../../../../api/catalog/entity/metrics-details-component-enabled.injectable"; +import type { KubeObjectDetailItem } from "../kube-object-detail-item-injection-token"; +import { DetailsMetricsContainer } from "./details-metrics-container"; +import { computedInjectManyInjectable } from "@ogre-tools/injectable-extension-for-mobx"; +import type { KubeObjectDetailsProps } from "../../kube-object-details"; + +type GetMetricsKubeObjectDetailItem = (token: InjectionToken, metricResourceType: ClusterMetricsResourceType) => KubeObjectDetailItem; + +export const getMetricsKubeObjectDetailItemInjectable = getInjectable({ + id: "get-metrics-kube-object-detail-item", + instantiate: (di) : GetMetricsKubeObjectDetailItem => (token, metricResourceType) => { + const computedInjectedMany = di.inject(computedInjectManyInjectable); + const metrics = computedInjectedMany(token); + const Component = (props: KubeObjectDetailsProps) => ; + + return { + Component, + enabled: di.inject(metricsDetailsComponentEnabledInjectable, metricResourceType), + orderNumber: -1, + }; + }, +}); + diff --git a/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/ingress-details-metrics.injectable.ts b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/ingress-details-metrics.injectable.ts new file mode 100644 index 000000000000..3a97753b3744 --- /dev/null +++ b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/ingress-details-metrics.injectable.ts @@ -0,0 +1,24 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { ingressDetailsMetricsInjectionToken } from "@k8slens/metrics"; +import { getInjectable } from "@ogre-tools/injectable"; +import { ClusterMetricsResourceType } from "../../../../../common/cluster-types"; +import { kubeObjectDetailItemInjectionToken } from "../kube-object-detail-item-injection-token"; +import { getMetricsKubeObjectDetailItemInjectable } from "./get-metrics-kube-object-detail-item.injectable"; + +const ingressMetricsInjectable = getInjectable({ + id: "ingress-details-metrics", + instantiate: (di) => { + const getMetricsKubeObjectDetailItem = di.inject(getMetricsKubeObjectDetailItemInjectable); + + return getMetricsKubeObjectDetailItem( + ingressDetailsMetricsInjectionToken, + ClusterMetricsResourceType.Ingress, + ); + }, + injectionToken: kubeObjectDetailItemInjectionToken, +}); + +export default ingressMetricsInjectable; diff --git a/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/job-details-metrics.injectable.ts b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/job-details-metrics.injectable.ts new file mode 100644 index 000000000000..409c3e76966e --- /dev/null +++ b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/job-details-metrics.injectable.ts @@ -0,0 +1,24 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { jobDetailsMetricsInjectionToken } from "@k8slens/metrics"; +import { getInjectable } from "@ogre-tools/injectable"; +import { ClusterMetricsResourceType } from "../../../../../common/cluster-types"; +import { kubeObjectDetailItemInjectionToken } from "../kube-object-detail-item-injection-token"; +import { getMetricsKubeObjectDetailItemInjectable } from "./get-metrics-kube-object-detail-item.injectable"; + +const jobMetricsInjectable = getInjectable({ + id: "job-details-metrics", + instantiate: (di) => { + const getMetricsKubeObjectDetailItem = di.inject(getMetricsKubeObjectDetailItemInjectable); + + return getMetricsKubeObjectDetailItem( + jobDetailsMetricsInjectionToken, + ClusterMetricsResourceType.Job, + ); + }, + injectionToken: kubeObjectDetailItemInjectionToken, +}); + +export default jobMetricsInjectable; diff --git a/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/namespace-details-metrics.injectable.ts b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/namespace-details-metrics.injectable.ts new file mode 100644 index 000000000000..ea5e07c4ca7a --- /dev/null +++ b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/namespace-details-metrics.injectable.ts @@ -0,0 +1,24 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { namespaceDetailsMetricsInjectionToken } from "@k8slens/metrics"; +import { getInjectable } from "@ogre-tools/injectable"; +import { ClusterMetricsResourceType } from "../../../../../common/cluster-types"; +import { kubeObjectDetailItemInjectionToken } from "../kube-object-detail-item-injection-token"; +import { getMetricsKubeObjectDetailItemInjectable } from "./get-metrics-kube-object-detail-item.injectable"; + +const namespaceMetricsInjectable = getInjectable({ + id: "namespace-details-metrics", + instantiate: (di) => { + const getMetricsKubeObjectDetailItem = di.inject(getMetricsKubeObjectDetailItemInjectable); + + return getMetricsKubeObjectDetailItem( + namespaceDetailsMetricsInjectionToken, + ClusterMetricsResourceType.Namespace, + ); + }, + injectionToken: kubeObjectDetailItemInjectionToken, +}); + +export default namespaceMetricsInjectable; diff --git a/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/node-details-metrics.injectable.ts b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/node-details-metrics.injectable.ts new file mode 100644 index 000000000000..6aac70683eef --- /dev/null +++ b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/node-details-metrics.injectable.ts @@ -0,0 +1,24 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { nodeDetailsMetricsInjectionToken } from "@k8slens/metrics"; +import { getInjectable } from "@ogre-tools/injectable"; +import { ClusterMetricsResourceType } from "../../../../../common/cluster-types"; +import { kubeObjectDetailItemInjectionToken } from "../kube-object-detail-item-injection-token"; +import { getMetricsKubeObjectDetailItemInjectable } from "./get-metrics-kube-object-detail-item.injectable"; + +const nodeMetricsInjectable = getInjectable({ + id: "node-details-metrics", + instantiate: (di) => { + const getMetricsKubeObjectDetailItem = di.inject(getMetricsKubeObjectDetailItemInjectable); + + return getMetricsKubeObjectDetailItem( + nodeDetailsMetricsInjectionToken, + ClusterMetricsResourceType.Node, + ); + }, + injectionToken: kubeObjectDetailItemInjectionToken, +}); + +export default nodeMetricsInjectable; diff --git a/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/persistent-volume-claim-metrics.injectable.ts b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/persistent-volume-claim-metrics.injectable.ts new file mode 100644 index 000000000000..06471a33dddd --- /dev/null +++ b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/persistent-volume-claim-metrics.injectable.ts @@ -0,0 +1,24 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { persistentVolumeClaimDetailsMetricsInjectionToken } from "@k8slens/metrics"; +import { getInjectable } from "@ogre-tools/injectable"; +import { ClusterMetricsResourceType } from "../../../../../common/cluster-types"; +import { kubeObjectDetailItemInjectionToken } from "../kube-object-detail-item-injection-token"; +import { getMetricsKubeObjectDetailItemInjectable } from "./get-metrics-kube-object-detail-item.injectable"; + +const persistentVolumeClaimMetricsInjectable = getInjectable({ + id: "persistent-volume-claim-details-metrics", + instantiate: (di) => { + const getMetricsKubeObjectDetailItem = di.inject(getMetricsKubeObjectDetailItemInjectable); + + return getMetricsKubeObjectDetailItem( + persistentVolumeClaimDetailsMetricsInjectionToken, + ClusterMetricsResourceType.VolumeClaim, + ); + }, + injectionToken: kubeObjectDetailItemInjectionToken, +}); + +export default persistentVolumeClaimMetricsInjectable; diff --git a/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/pod-details-pod-metrics.injectable.ts b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/pod-details-pod-metrics.injectable.ts new file mode 100644 index 000000000000..5ce56f218759 --- /dev/null +++ b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/pod-details-pod-metrics.injectable.ts @@ -0,0 +1,24 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { podDetailsMetricsInjectionToken } from "@k8slens/metrics"; +import { getInjectable } from "@ogre-tools/injectable"; +import { ClusterMetricsResourceType } from "../../../../../common/cluster-types"; +import { kubeObjectDetailItemInjectionToken } from "../kube-object-detail-item-injection-token"; +import { getMetricsKubeObjectDetailItemInjectable } from "./get-metrics-kube-object-detail-item.injectable"; + +const podMetricsInjectable = getInjectable({ + id: "pod-details-pod-metrics", + instantiate: (di) => { + const getMetricsKubeObjectDetailItem = di.inject(getMetricsKubeObjectDetailItemInjectable); + + return getMetricsKubeObjectDetailItem( + podDetailsMetricsInjectionToken, + ClusterMetricsResourceType.Pod, + ); + }, + injectionToken: kubeObjectDetailItemInjectionToken, +}); + +export default podMetricsInjectable; diff --git a/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/replica-set-details-metrics.injectable.ts b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/replica-set-details-metrics.injectable.ts new file mode 100644 index 000000000000..9abc61890619 --- /dev/null +++ b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/replica-set-details-metrics.injectable.ts @@ -0,0 +1,24 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { replicaSetDetailsMetricsInjectionToken } from "@k8slens/metrics"; +import { getInjectable } from "@ogre-tools/injectable"; +import { ClusterMetricsResourceType } from "../../../../../common/cluster-types"; +import { kubeObjectDetailItemInjectionToken } from "../kube-object-detail-item-injection-token"; +import { getMetricsKubeObjectDetailItemInjectable } from "./get-metrics-kube-object-detail-item.injectable"; + +const replicaSetMetricsInjectable = getInjectable({ + id: "replica-set-details-metrics", + instantiate: (di) => { + const getMetricsKubeObjectDetailItem = di.inject(getMetricsKubeObjectDetailItemInjectable); + + return getMetricsKubeObjectDetailItem( + replicaSetDetailsMetricsInjectionToken, + ClusterMetricsResourceType.ReplicaSet, + ); + }, + injectionToken: kubeObjectDetailItemInjectionToken, +}); + +export default replicaSetMetricsInjectable; diff --git a/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/stateful-set-details-metrics.injectable.ts b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/stateful-set-details-metrics.injectable.ts new file mode 100644 index 000000000000..5a36e0355d75 --- /dev/null +++ b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/metrics/stateful-set-details-metrics.injectable.ts @@ -0,0 +1,24 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { ClusterMetricsResourceType } from "../../../../../common/cluster-types"; +import { kubeObjectDetailItemInjectionToken } from "../kube-object-detail-item-injection-token"; +import { statefulSetDetailsMetricsInjectionToken } from "@k8slens/metrics"; +import { getMetricsKubeObjectDetailItemInjectable } from "./get-metrics-kube-object-detail-item.injectable"; + +const statefulSetMetricsInjectable = getInjectable({ + id: "stateful-set-details-metrics", + instantiate: (di) => { + const getMetricsKubeObjectDetailItem = di.inject(getMetricsKubeObjectDetailItemInjectable); + + return getMetricsKubeObjectDetailItem( + statefulSetDetailsMetricsInjectionToken, + ClusterMetricsResourceType.StatefulSet, + ); + }, + injectionToken: kubeObjectDetailItemInjectionToken, +}); + +export default statefulSetMetricsInjectable; diff --git a/packages/core/src/renderer/library.ts b/packages/core/src/renderer/library.ts index 41c7dea0e7a9..5dbe66518a2a 100644 --- a/packages/core/src/renderer/library.ts +++ b/packages/core/src/renderer/library.ts @@ -20,3 +20,4 @@ export * as ReactRouter from "react-router"; export * as ReactRouterDom from "react-router-dom"; export * as rendererExtensionApi from "../extensions/renderer-api"; export * as commonExtensionApi from "../extensions/common-api"; +export { metricsFeature } from "../features/metrics/metrics-feature"; diff --git a/packages/metrics/.eslintrc.js b/packages/metrics/.eslintrc.js new file mode 100644 index 000000000000..f404cf0ace57 --- /dev/null +++ b/packages/metrics/.eslintrc.js @@ -0,0 +1,6 @@ +module.exports = { + extends: "@k8slens/eslint-config/eslint", + parserOptions: { + project: "./tsconfig.json", + }, + }; diff --git a/packages/metrics/.prettierrc b/packages/metrics/.prettierrc new file mode 100644 index 000000000000..edd47b479e93 --- /dev/null +++ b/packages/metrics/.prettierrc @@ -0,0 +1 @@ +"@k8slens/eslint-config/prettier" diff --git a/packages/metrics/index.ts b/packages/metrics/index.ts new file mode 100644 index 000000000000..03581af59729 --- /dev/null +++ b/packages/metrics/index.ts @@ -0,0 +1,81 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type React from "react"; +import { getInjectionToken } from "@ogre-tools/injectable"; + +export type ClusterOverviewUIBlock = { + id: string; + Component: React.ElementType; + orderNumber: number; +}; + +// this should be moved to cluster-overview package when there is one +export const clusterOverviewUIBlockInjectionToken = getInjectionToken({ + id: "cluster-overview-ui-block-injection-token", +}); + +export type KubeObjectDetailMetricsComponentProps = { + object: any; +}; + +export type KubeObjectDetailMetrics = { + id: string; + Component: React.ComponentType; +}; + +export const podDetailsMetricsInjectionToken = getInjectionToken({ + id: "pod-details-metrics-injection-token", +}); + +export const deploymentDetailsMetricsInjectionToken = getInjectionToken({ + id: "deployment-details-metrics-injection-token", +}); + +export const nodeDetailsMetricsInjectionToken = getInjectionToken({ + id: "node-details-metrics-injection-token", +}); + +export const replicaSetDetailsMetricsInjectionToken = getInjectionToken({ + id: "replica-set-details-metrics-injection-token", +}); + +export const persistentVolumeClaimDetailsMetricsInjectionToken = getInjectionToken({ + id: "persistent-volume-claim-details-metrics-injection-token", +}); + +export const statefulSetDetailsMetricsInjectionToken = getInjectionToken({ + id: "stateful-set-details-metrics-injection-token", +}); + +export const namespaceDetailsMetricsInjectionToken = getInjectionToken({ + id: "namespace-details-metrics-injection-token", +}); + +export const jobDetailsMetricsInjectionToken = getInjectionToken({ + id: "job-details-metrics-injection-token", +}); + +export const daemonSetDetailsMetricsInjectionToken = getInjectionToken({ + id: "daemon-set-details-metrics-injection-token", +}); + +export const ingressDetailsMetricsInjectionToken = getInjectionToken({ + id: "ingress-details-metrics-injection-token", +}); + +export interface PodDetailsContainerMetricsComponentProps { + container: any; + pod: any; +} + +export interface PodDetailsContainerMetricsComponent { + id: string; + Component: React.ComponentType; +} + +export const podDetailsContainerMetricsInjectionToken = getInjectionToken({ + id: "pod-details-container-metrics-injection-token", +}); diff --git a/packages/metrics/jest.config.js b/packages/metrics/jest.config.js new file mode 100644 index 000000000000..38d54ab7b6c3 --- /dev/null +++ b/packages/metrics/jest.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact; diff --git a/packages/metrics/package.json b/packages/metrics/package.json new file mode 100644 index 000000000000..7016dc8b6df0 --- /dev/null +++ b/packages/metrics/package.json @@ -0,0 +1,43 @@ +{ + "name": "@k8slens/metrics", + "private": false, + "version": "6.5.0-alpha.1", + "description": "Injection tokens for implementing metrics for Lens", + "type": "commonjs", + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + }, + "files": [ + "dist" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/lensapp/lens.git" + }, + "main": "dist/index.js", + "types": "dist/index.d.ts", + "author": { + "name": "OpenLens Authors", + "email": "info@k8slens.dev" + }, + "license": "MIT", + "homepage": "https://github.com/lensapp/lens", + "scripts": { + "build": "webpack", + "clean": "rimraf dist/", + "dev": "webpack --mode=development --watch", + "test": "jest --coverage --runInBand", + "lint": "lens-lint", + "lint:fix": "lens-lint --fix" + }, + "peerDependencies": { + "@ogre-tools/injectable": "^15.1.2", + "react": "^17.0.2" + }, + "devDependencies": { + "@k8slens/eslint-config": "6.5.0-alpha.1", + "@k8slens/typescript": "6.5.0-alpha.1", + "@k8slens/jest": "6.5.0-alpha.1" + } + } diff --git a/packages/metrics/tsconfig.json b/packages/metrics/tsconfig.json new file mode 100644 index 000000000000..2b0f0e56032a --- /dev/null +++ b/packages/metrics/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@k8slens/typescript/config/base.json", + "include": ["**/*.ts"] + } diff --git a/packages/metrics/webpack.config.js b/packages/metrics/webpack.config.js new file mode 100644 index 000000000000..1cda407f5a9a --- /dev/null +++ b/packages/metrics/webpack.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/webpack").configForReact; diff --git a/packages/open-lens/src/renderer/index.ts b/packages/open-lens/src/renderer/index.ts index d14e817347eb..ce7ce7b2322a 100644 --- a/packages/open-lens/src/renderer/index.ts +++ b/packages/open-lens/src/renderer/index.ts @@ -4,6 +4,7 @@ import { rendererExtensionApi as Renderer, commonExtensionApi as Common, registerLensCore, + metricsFeature } from "@k8slens/core/renderer"; import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration"; import { registerFeature } from "@k8slens/feature-core"; @@ -32,7 +33,8 @@ runInAction(() => { applicationFeature, messagingFeatureForRenderer, keyboardShortcutsFeature, - reactApplicationFeature + reactApplicationFeature, + metricsFeature ); autoRegister({