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

Extract pod container metrics to its own injection token.

Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
This commit is contained in:
Juho Heikka 2023-04-04 21:36:00 +03:00
parent be0028cc5e
commit 03a87f9549
8 changed files with 177 additions and 63 deletions

View File

@ -3,10 +3,11 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getFeature } from "@k8slens/feature-core"; import { getFeature } from "@k8slens/feature-core";
import { clusterOverviewUIBlockInjectionToken, podDetailsMetricsInjectionToken } from "@k8slens/metrics"; import { clusterOverviewUIBlockInjectionToken, podDetailsContainerMetricsInjectionToken, podDetailsMetricsInjectionToken } from "@k8slens/metrics";
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { ClusterMetrics } from "../../renderer/components/+cluster/cluster-metrics"; import { ClusterMetrics } from "../../renderer/components/+cluster/cluster-metrics";
import { ClusterPieCharts } from "../../renderer/components/+cluster/cluster-pie-charts"; import { ClusterPieCharts } from "../../renderer/components/+cluster/cluster-pie-charts";
import { PodDetailsContainerMetrics } from "../../renderer/components/+workloads-pods/pod-details-container-metrics";
import PodMetricsDetailsComponent from "../../renderer/components/+workloads-pods/pod-metrics-details-component"; import PodMetricsDetailsComponent from "../../renderer/components/+workloads-pods/pod-metrics-details-component";
const clusterPieChartsClusterOverviewInjectable = getInjectable({ const clusterPieChartsClusterOverviewInjectable = getInjectable({
@ -33,15 +34,21 @@ const clusterMetricsOverviewBlockInjectable = getInjectable({
injectionToken: clusterOverviewUIBlockInjectionToken, injectionToken: clusterOverviewUIBlockInjectionToken,
}); });
const podMetricsDetailsComponentInjectable = getInjectable({ const podDetailsMetricsInjectable = getInjectable({
id: "pod-metrics-details-component-injectable", id: "pod-details-metrics-injectable",
instantiate: () => ({ instantiate: () => PodMetricsDetailsComponent,
id: "pod-metrics-details-component-injectable",
Component: PodMetricsDetailsComponent,
}),
injectionToken: podDetailsMetricsInjectionToken, injectionToken: podDetailsMetricsInjectionToken,
}); });
const podDetailsContainerMetricsInjectable = getInjectable({
id: "pod-details-container-metrics-injectable",
instantiate: () => ({
id: "pod-details-container-metrics",
Component: PodDetailsContainerMetrics,
}),
injectionToken: podDetailsContainerMetricsInjectionToken,
});
export const metricsFeature = getFeature({ export const metricsFeature = getFeature({
id: "core-metrics-feature", id: "core-metrics-feature",
@ -49,6 +56,7 @@ export const metricsFeature = getFeature({
di.register(clusterPieChartsClusterOverviewInjectable); di.register(clusterPieChartsClusterOverviewInjectable);
di.register(clusterMetricsOverviewBlockInjectable); di.register(clusterMetricsOverviewBlockInjectable);
di.register(podMetricsDetailsComponentInjectable); di.register(podDetailsMetricsInjectable);
di.register(podDetailsContainerMetricsInjectable);
}, },
}); });

View File

@ -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 (
<>
<DrawerTitle>Containers</DrawerTitle>
{containers.map(container => (
<PodDetailsContainer
key={container.name}
pod={pod}
container={container}
/>
))}
</>
);
});
export { PodDetailsContainers };

View File

@ -0,0 +1,40 @@
/**
* 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 NonInjectedPodDetailsInitContainers = observer(({ pod }: PodDetailsContainersProps) => {
const initContainers = pod.getInitContainers();
if (initContainers.length === 0) {
return null;
}
return (
<>
<DrawerTitle>Init Containers</DrawerTitle>
{initContainers.map(container => (
<PodDetailsContainer
key={container.name}
pod={pod}
container={container}
/>
))}
</>
);
});
const PodDetailsInitContainers = NonInjectedPodDetailsInitContainers;
export { PodDetailsInitContainers };

View File

@ -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<PodMetricData>;
}
const NonInjectedPodDetailsContainerMetrics = observer(({ pod, container, podContainerMetrics }: ContainerMetricsProps & Dependencies) => {
const metrics = getItemMetrics(toJS(podContainerMetrics.value.get()), container.name);
if (!metrics) {
return null;
}
return (
<ResourceMetrics
object={pod}
tabs={[
"CPU",
"Memory",
"Filesystem",
]}
metrics={metrics}
>
<ContainerCharts />
</ResourceMetrics>
);
});
export const PodDetailsContainerMetrics = withInjectables<Dependencies, ContainerMetricsProps>(NonInjectedPodDetailsContainerMetrics, {
getProps: (di, props) => ({
...props,
podContainerMetrics: di.inject(podContainerMetricsInjectable, props.pod),
}),
});

View File

@ -13,9 +13,6 @@ import { StatusBrick } from "../status-brick";
import { Badge } from "../badge"; import { Badge } from "../badge";
import { ContainerEnvironment } from "./pod-container-env"; import { ContainerEnvironment } from "./pod-container-env";
import { PodContainerPort } from "./pod-container-port"; 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 { LocaleDate } from "../locale-date";
import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import { ClusterMetricsResourceType } from "../../../common/cluster-types";
import type { PortForwardStore } from "../../port-forward"; 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 portForwardStoreInjectable from "../../port-forward/port-forward-store/port-forward-store.injectable";
import type { IComputedValue } from "mobx"; import type { IComputedValue } from "mobx";
import enabledMetricsInjectable from "../../api/catalog/entity/metrics-enabled.injectable"; import enabledMetricsInjectable from "../../api/catalog/entity/metrics-enabled.injectable";
import type { PodDetailsContainerMetricsComponent } from "@k8slens/metrics";
import { podDetailsContainerMetricsInjectionToken } from "@k8slens/metrics";
export interface PodDetailsContainerProps { export interface PodDetailsContainerProps {
pod: Pod; pod: Pod;
container: Container; container: Container;
metrics?: Partial<Record<string, MetricData>>;
} }
interface Dependencies { interface Dependencies {
portForwardStore: PortForwardStore; portForwardStore: PortForwardStore;
containerMetricsVisible: IComputedValue<boolean>; containerMetricsVisible: IComputedValue<boolean>;
containerMetrics: PodDetailsContainerMetricsComponent[];
} }
@observer @observer
@ -84,7 +83,7 @@ class NonInjectedPodDetailsContainer extends React.Component<PodDetailsContainer
} }
render() { render() {
const { pod, container, metrics, containerMetricsVisible } = this.props; const { pod, container, containerMetricsVisible, containerMetrics } = this.props;
if (!pod || !container) return null; if (!pod || !container) return null;
const { name, image, imagePullPolicy, ports, volumeMounts, command, args } = container; const { name, image, imagePullPolicy, ports, volumeMounts, command, args } = container;
@ -105,18 +104,15 @@ class NonInjectedPodDetailsContainer extends React.Component<PodDetailsContainer
<StatusBrick className={cssNames(state, { ready })}/> <StatusBrick className={cssNames(state, { ready })}/>
{name} {name}
</div> </div>
{(isMetricVisible && !isInitContainer && metrics) && ( {(isMetricVisible && !isInitContainer) && (
<ResourceMetrics <>
object={pod} {containerMetrics.map(ContainerMetrics => (
tabs={[ <ContainerMetrics.Component
"CPU", key={ContainerMetrics.id}
"Memory", container={container}
"Filesystem", pod={pod}/>
]} ))}
metrics={metrics} </>
>
<ContainerCharts/>
</ResourceMetrics>
)} )}
{status && ( {status && (
<DrawerItem name="Status"> <DrawerItem name="Status">
@ -218,5 +214,6 @@ export const PodDetailsContainer = withInjectables<Dependencies, PodDetailsConta
...props, ...props,
portForwardStore: di.inject(portForwardStoreInjectable), portForwardStore: di.inject(portForwardStoreInjectable),
containerMetricsVisible: di.inject(enabledMetricsInjectable, ClusterMetricsResourceType.Container), containerMetricsVisible: di.inject(enabledMetricsInjectable, ClusterMetricsResourceType.Container),
containerMetrics: di.injectMany(podDetailsContainerMetricsInjectionToken),
}), }),
}); });

View File

@ -11,18 +11,15 @@ import { observer } from "mobx-react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { Pod } from "../../../common/k8s-api/endpoints"; import { Pod } from "../../../common/k8s-api/endpoints";
import type { NodeApi, PriorityClassApi, RuntimeClassApi, ServiceAccountApi } from "../../../common/k8s-api/endpoints"; import type { NodeApi, PriorityClassApi, RuntimeClassApi, ServiceAccountApi } from "../../../common/k8s-api/endpoints";
import { DrawerItem, DrawerTitle } from "../drawer"; import { DrawerItem } from "../drawer";
import { Badge } from "../badge"; import { Badge } from "../badge";
import { cssNames, stopPropagation } from "@k8slens/utilities"; import { cssNames, stopPropagation } from "@k8slens/utilities";
import { PodDetailsContainer } from "./pod-details-container";
import { PodDetailsAffinities } from "./pod-details-affinities"; import { PodDetailsAffinities } from "./pod-details-affinities";
import { PodDetailsTolerations } from "./pod-details-tolerations"; import { PodDetailsTolerations } from "./pod-details-tolerations";
import { PodDetailsSecrets } from "./pod-details-secrets"; import { PodDetailsSecrets } from "./pod-details-secrets";
import type { KubeObjectDetailsProps } from "../kube-object-details"; import type { KubeObjectDetailsProps } from "../kube-object-details";
import { getItemMetrics } from "../../../common/k8s-api/endpoints/metrics.api";
import type { Logger } from "../../../common/logger"; import type { Logger } from "../../../common/logger";
import { PodVolumes } from "./details/volumes/view"; import { PodVolumes } from "./details/volumes/view";
import type { IAsyncComputed } from "@ogre-tools/injectable-react";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { GetDetailsUrl } from "../kube-detail-params/get-details-url.injectable"; import type { GetDetailsUrl } from "../kube-detail-params/get-details-url.injectable";
import getDetailsUrlInjectable from "../kube-detail-params/get-details-url.injectable"; import getDetailsUrlInjectable from "../kube-detail-params/get-details-url.injectable";
@ -31,9 +28,8 @@ import runtimeClassApiInjectable from "../../../common/k8s-api/endpoints/runtime
import serviceAccountApiInjectable from "../../../common/k8s-api/endpoints/service-account.api.injectable"; import serviceAccountApiInjectable from "../../../common/k8s-api/endpoints/service-account.api.injectable";
import priorityClassApiInjectable from "../../../common/k8s-api/endpoints/priority-class.api.injectable"; import priorityClassApiInjectable from "../../../common/k8s-api/endpoints/priority-class.api.injectable";
import loggerInjectable from "../../../common/logger.injectable"; import loggerInjectable from "../../../common/logger.injectable";
import type { PodMetricData } from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics.injectable"; import { PodDetailsContainers } from "./details/containers/pod-details-containers";
import podContainerMetricsInjectable from "./container-metrics.injectable"; import { PodDetailsInitContainers } from "./details/containers/pod-details-init-containers";
import { toJS } from "../../../common/utils";
export interface PodDetailsProps extends KubeObjectDetailsProps<Pod> { export interface PodDetailsProps extends KubeObjectDetailsProps<Pod> {
} }
@ -45,13 +41,12 @@ interface Dependencies {
runtimeClassApi: RuntimeClassApi; runtimeClassApi: RuntimeClassApi;
serviceAccountApi: ServiceAccountApi; serviceAccountApi: ServiceAccountApi;
logger: Logger; logger: Logger;
containerMetrics: IAsyncComputed<PodMetricData>;
} }
@observer @observer
class NonInjectedPodDetails extends React.Component<PodDetailsProps & Dependencies> { class NonInjectedPodDetails extends React.Component<PodDetailsProps & Dependencies> {
render() { render() {
const { object: pod, getDetailsUrl, nodeApi, logger, containerMetrics } = this.props; const { object: pod, getDetailsUrl, nodeApi, logger } = this.props;
if (!pod) { if (!pod) {
return null; return null;
@ -68,8 +63,6 @@ class NonInjectedPodDetails extends React.Component<PodDetailsProps & Dependenci
const podIPs = pod.getIPs(); const podIPs = pod.getIPs();
const { nodeName } = spec ?? {}; const { nodeName } = spec ?? {};
const nodeSelector = pod.getNodeSelectors(); const nodeSelector = pod.getNodeSelectors();
const initContainers = pod.getInitContainers();
const containers = pod.getContainers();
const namespace = pod.getNs(); const namespace = pod.getNs();
const priorityClassName = pod.getPriorityClassName(); const priorityClassName = pod.getPriorityClassName();
@ -169,28 +162,9 @@ class NonInjectedPodDetails extends React.Component<PodDetailsProps & Dependenci
<PodDetailsSecrets pod={pod} /> <PodDetailsSecrets pod={pod} />
</DrawerItem> </DrawerItem>
{initContainers.length > 0 && ( <PodDetailsInitContainers pod={pod} />
<>
<DrawerTitle>Init Containers</DrawerTitle>
{initContainers.map(container => (
<PodDetailsContainer
key={container.name}
pod={pod}
container={container}
/>
))}
</>
)}
<DrawerTitle>Containers</DrawerTitle> <PodDetailsContainers pod={pod} />
{containers.map(container => (
<PodDetailsContainer
key={container.name}
pod={pod}
container={container}
metrics={getItemMetrics(toJS(containerMetrics.value.get()), container.name)}
/>
))}
<PodVolumes pod={pod} /> <PodVolumes pod={pod} />
</div> </div>
@ -207,6 +181,5 @@ export const PodDetails = withInjectables<Dependencies, PodDetailsProps>(NonInje
runtimeClassApi: di.inject(runtimeClassApiInjectable), runtimeClassApi: di.inject(runtimeClassApiInjectable),
serviceAccountApi: di.inject(serviceAccountApiInjectable), serviceAccountApi: di.inject(serviceAccountApiInjectable),
logger: di.inject(loggerInjectable), logger: di.inject(loggerInjectable),
containerMetrics: di.inject(podContainerMetricsInjectable, props.object),
}), }),
}); });

View File

@ -17,7 +17,7 @@ const podMetricsInjectable = getInjectable({
const podMetrics = di.injectMany(podDetailsMetricsInjectionToken); const podMetrics = di.injectMany(podDetailsMetricsInjectionToken);
const first = podMetrics[0]; const first = podMetrics[0];
const Component = first?.Component ?? Empty; const Component = first ?? Empty;
return { return {
Component, Component,

View File

@ -16,11 +16,22 @@ export const clusterOverviewUIBlockInjectionToken = getInjectionToken<ClusterOve
id: "cluster-overview-ui-block-injection-token", id: "cluster-overview-ui-block-injection-token",
}); });
export type KubeObjectDetailMetrics = { export type KubeObjectDetailMetrics = React.ElementType;
id: string;
Component: React.ElementType;
};
export const podDetailsMetricsInjectionToken = getInjectionToken<KubeObjectDetailMetrics>({ export const podDetailsMetricsInjectionToken = getInjectionToken<KubeObjectDetailMetrics>({
id: "pod-details-metrics-injection-token", id: "pod-details-metrics-injection-token",
}); });
export interface PodDetailsContainerMetricsComponentProps {
container: any;
pod: any;
}
export interface PodDetailsContainerMetricsComponent {
id: string;
Component: React.ComponentType<PodDetailsContainerMetricsComponentProps>;
}
export const podDetailsContainerMetricsInjectionToken =
getInjectionToken<PodDetailsContainerMetricsComponent>({
id: "pod-details-container-metrics-injection-token",
});