mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Refactor kube detail components and add KubeEvents automatically to all custom resources (#6468)
* Support Events on CustomResourece details panel Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove unnecessary check Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove legacy KubeObjectMeta use from non-metrics details Signed-off-by: Sebastian Malton <sebastian@malton.name> * Change orderNumber of default KubeMetaDetails Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove last use of legacy global getActiveClusterEntity Signed-off-by: Sebastian Malton <sebastian@malton.name> * Refactor ResourceMetrics to use IAsyncComputed - Introduce first use for namespace metrics Signed-off-by: Sebastian Malton <sebastian@malton.name> * Introduce metrics details item for Ingress Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove legacyStore for nodes Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove legacyStore for ingresses Signed-off-by: Sebastian Malton <sebastian@malton.name> * Replace NodeMetrics in details with injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Change namespace metrics details to use more injectables Signed-off-by: Sebastian Malton <sebastian@malton.name> * Change ingress metrics details to use more injectables Signed-off-by: Sebastian Malton <sebastian@malton.name> * Change PersistentVolumeClaim metrics to be injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Change DaemonSet metrics to be injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Change Deployment metrics to be injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Change Job metrics to be injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Convert Pod metrics to be injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Make ReplicaSet metrics details injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Make StatefulSet metrics component injectable Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove dead code Signed-off-by: Sebastian Malton <sebastian@malton.name> * Introduce fix for metrics components visible on all details Signed-off-by: Sebastian Malton <sebastian@malton.name> * Use the new and correct enabled check Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove legacy global for daemonSetStore Signed-off-by: Sebastian Malton <sebastian@malton.name> * Switch components to be static to help with React performance Signed-off-by: Sebastian Malton <sebastian@malton.name> * Remove legacy store of CronJobs Signed-off-by: Sebastian Malton <sebastian@malton.name> * Make DeploymentReplicaSets injectable to fix build error Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix up remove dead code Signed-off-by: Sebastian Malton <sebastian@malton.name> * Allow use of ResourceMetrics without IAsyncComputed Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix metrics not updating correctly Signed-off-by: Sebastian Malton <sebastian@malton.name> * Update snapshots because moving KubeObjectMeta out of CustomResourceDetails Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Update more snapshots Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix test failures due to newer dep versions Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix type errors from new asyncComputed Signed-off-by: Sebastian Malton <sebastian@malton.name> Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
d05189d008
commit
83d2b12cca
@ -24,7 +24,7 @@ const requestPodMetricsForJobsInjectable = getInjectable({
|
||||
instantiate: (di): RequestPodMetricsForJobs => {
|
||||
const requestMetrics = di.inject(requestMetricsInjectable);
|
||||
|
||||
return (jobs, namespace, selector) => {
|
||||
return (jobs, namespace, selector = "") => {
|
||||
const podSelector = jobs.map(job => `${job.getName()}-[[:alnum:]]{5}`).join("|");
|
||||
const opts = { category: "pods", pods: podSelector, namespace, selector };
|
||||
|
||||
|
||||
16
src/common/utils/sort-function.ts
Normal file
16
src/common/utils/sort-function.ts
Normal file
@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get an ordering function based on the function getter
|
||||
*/
|
||||
export function byValue<T>(getOrderValue: (src: T) => number): (left: T, right: T) => number {
|
||||
return (left, right) => {
|
||||
const leftValue = getOrderValue(left);
|
||||
const rightValue = getOrderValue(right);
|
||||
|
||||
return leftValue - rightValue;
|
||||
};
|
||||
}
|
||||
@ -302,11 +302,63 @@ exports[`disable kube object detail items when cluster is not relevant given ext
|
||||
<div
|
||||
class="drawer-content flex column box grow"
|
||||
>
|
||||
<div
|
||||
class="DrawerItem"
|
||||
>
|
||||
<span
|
||||
class="name"
|
||||
>
|
||||
Created
|
||||
</span>
|
||||
<span
|
||||
class="value"
|
||||
>
|
||||
<unknown>
|
||||
ago
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="DrawerItem"
|
||||
>
|
||||
<span
|
||||
class="name"
|
||||
>
|
||||
Name
|
||||
</span>
|
||||
<span
|
||||
class="value"
|
||||
>
|
||||
some-name
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="DrawerItem"
|
||||
>
|
||||
<span
|
||||
class="name"
|
||||
>
|
||||
Namespace
|
||||
</span>
|
||||
<span
|
||||
class="value"
|
||||
>
|
||||
some-namespace
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
data-testid="some-kube-object-detail-item"
|
||||
>
|
||||
Some detail
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
class="DrawerTitle flex gaps align-center title"
|
||||
>
|
||||
<span>
|
||||
Events
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@ -792,6 +844,15 @@ exports[`disable kube object detail items when cluster is not relevant given ext
|
||||
some-namespace
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
class="DrawerTitle flex gaps align-center title"
|
||||
>
|
||||
<span>
|
||||
Events
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@ -1277,6 +1338,15 @@ exports[`disable kube object detail items when cluster is not relevant given not
|
||||
some-namespace
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
class="DrawerTitle flex gaps align-center title"
|
||||
>
|
||||
<span>
|
||||
Events
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
||||
@ -19,6 +19,7 @@ import extensionShouldBeEnabledForClusterFrameInjectable from "../../../../rende
|
||||
import apiManagerInjectable from "../../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import { KubeObjectDetails } from "../../../../renderer/components/kube-object-details";
|
||||
import type { ApiManager } from "../../../../common/k8s-api/api-manager";
|
||||
import type { KubeObjectStore } from "../../../../common/k8s-api/kube-object.store";
|
||||
|
||||
describe("disable kube object detail items when cluster is not relevant", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
@ -32,16 +33,11 @@ describe("disable kube object detail items when cluster is not relevant", () =>
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(
|
||||
apiManagerInjectable,
|
||||
() =>
|
||||
({
|
||||
windowDi.override(apiManagerInjectable, () => ({
|
||||
getStore: () => ({
|
||||
getByPath: () =>
|
||||
getKubeObjectStub("some-kind", "some-api-version"),
|
||||
}),
|
||||
} as unknown as ApiManager),
|
||||
);
|
||||
loadFromPath: async () => getKubeObjectStub("some-kind", "some-api-version"),
|
||||
}) as Partial<KubeObjectStore> as KubeObjectStore,
|
||||
}) as Partial<ApiManager> as ApiManager);
|
||||
|
||||
windowDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable);
|
||||
|
||||
|
||||
@ -16,6 +16,7 @@ import { KubeObject } from "../../../../common/k8s-api/kube-object";
|
||||
import apiManagerInjectable from "../../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import { KubeObjectDetails } from "../../../../renderer/components/kube-object-details";
|
||||
import type { ApiManager } from "../../../../common/k8s-api/api-manager";
|
||||
import type { KubeObjectStore } from "../../../../common/k8s-api/kube-object.store";
|
||||
|
||||
describe("reactively hide kube object detail item", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
@ -28,16 +29,11 @@ describe("reactively hide kube object detail item", () => {
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(
|
||||
apiManagerInjectable,
|
||||
() =>
|
||||
({
|
||||
windowDi.override(apiManagerInjectable, () => ({
|
||||
getStore: () => ({
|
||||
getByPath: () =>
|
||||
getKubeObjectStub("some-kind", "some-api-version"),
|
||||
}),
|
||||
} as unknown as ApiManager),
|
||||
);
|
||||
loadFromPath: async () => getKubeObjectStub("some-kind", "some-api-version"),
|
||||
}) as Partial<KubeObjectStore> as KubeObjectStore,
|
||||
}) as Partial<ApiManager> as ApiManager);
|
||||
|
||||
runInAction(() => {
|
||||
windowDi.register(testRouteInjectable, testRouteComponentInjectable);
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { asLegacyGlobalFunctionForExtensionApi } from "../../../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-function-for-extension-api";
|
||||
import getActiveClusterEntityInjectable from "./get-active-cluster-entity.injectable";
|
||||
|
||||
/**
|
||||
* @deprecated use `di.inject(getActiveClusterEntityInjectable)` instead
|
||||
*/
|
||||
export const getActiveClusterEntity = asLegacyGlobalFunctionForExtensionApi(getActiveClusterEntityInjectable);
|
||||
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import { computed } from "mobx";
|
||||
import type { ClusterMetricsResourceType } from "../../../../common/cluster-types";
|
||||
import currentKubeObjectInDetailsInjectable from "../../../components/kube-object-details/current-kube-object-in-details.injectable";
|
||||
import enabledMetricsInjectable from "./metrics-enabled.injectable";
|
||||
|
||||
const metricsDetailsComponentEnabledInjectable = getInjectable({
|
||||
id: "metrics-details-component-enabled",
|
||||
instantiate: (di, kind) => {
|
||||
const metricsEnabled = di.inject(enabledMetricsInjectable, kind);
|
||||
const currentKubeObjectInDetails = di.inject(currentKubeObjectInDetailsInjectable);
|
||||
|
||||
return computed(() => {
|
||||
const current = currentKubeObjectInDetails.value.get();
|
||||
|
||||
if (!current?.object) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return current.object.kind == kind && metricsEnabled.get();
|
||||
});
|
||||
},
|
||||
lifecycle: lifecycleEnum.keyedSingleton({
|
||||
getInstanceKey: (di, kind: ClusterMetricsResourceType) => kind,
|
||||
}),
|
||||
});
|
||||
|
||||
export default metricsDetailsComponentEnabledInjectable;
|
||||
@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import { computed } from "mobx";
|
||||
import type { ClusterMetricsResourceType } from "../../../../common/cluster-types";
|
||||
import getActiveClusterEntityInjectable from "./get-active-cluster-entity.injectable";
|
||||
|
||||
const enabledMetricsInjectable = getInjectable({
|
||||
id: "enabled-metrics",
|
||||
instantiate: (di, kind) => {
|
||||
const getActiveClusterEntity = di.inject(getActiveClusterEntityInjectable);
|
||||
|
||||
return computed(() => !getActiveClusterEntity()?.isMetricHidden(kind));
|
||||
},
|
||||
lifecycle: lifecycleEnum.keyedSingleton({
|
||||
getInstanceKey: (di, kind: ClusterMetricsResourceType) => kind,
|
||||
}),
|
||||
});
|
||||
|
||||
export default enabledMetricsInjectable;
|
||||
@ -16,7 +16,6 @@ import type { HorizontalPodAutoscalerMetricSpec, HorizontalPodAutoscalerMetricTa
|
||||
import { HorizontalPodAutoscaler, HpaMetricType } from "../../../common/k8s-api/endpoints/horizontal-pod-autoscaler.api";
|
||||
import { Table, TableCell, TableHead, TableRow } from "../table";
|
||||
import type { ApiManager } from "../../../common/k8s-api/api-manager";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import logger from "../../../common/logger";
|
||||
import type { GetDetailsUrl } from "../kube-detail-params/get-details-url.injectable";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
@ -121,8 +120,6 @@ class NonInjectedHpaDetails extends React.Component<HpaDetailsProps & Dependenci
|
||||
|
||||
return (
|
||||
<div className="HpaDetails">
|
||||
<KubeObjectMeta object={hpa}/>
|
||||
|
||||
<DrawerItem name="Reference">
|
||||
{scaleTargetRef && (
|
||||
<Link to={getDetailsUrl(apiManager.lookupApiLink(scaleTargetRef, hpa))}>
|
||||
|
||||
@ -9,7 +9,6 @@ import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { DrawerItem } from "../drawer";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import type { Lease } from "../../../common/k8s-api/endpoints";
|
||||
|
||||
export interface LeaseDetailsProps extends KubeObjectDetailsProps<Lease> {
|
||||
@ -23,8 +22,6 @@ export class LeaseDetails extends React.Component<LeaseDetailsProps> {
|
||||
|
||||
return (
|
||||
<div className="LeaseDetails">
|
||||
<KubeObjectMeta object={lease} />
|
||||
|
||||
<DrawerItem name="Holder Identity">
|
||||
{lease.getHolderIdentity()}
|
||||
</DrawerItem>
|
||||
|
||||
@ -10,7 +10,6 @@ import { observer } from "mobx-react";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import type { LimitRangeItem } from "../../../common/k8s-api/endpoints/limit-range.api";
|
||||
import { LimitPart, LimitRange, Resource } from "../../../common/k8s-api/endpoints/limit-range.api";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import { DrawerItem } from "../drawer/drawer-item";
|
||||
import { Badge } from "../badge";
|
||||
import logger from "../../../common/logger";
|
||||
@ -73,8 +72,6 @@ export class LimitRangeDetails extends React.Component<LimitRangeDetailsProps> {
|
||||
|
||||
return (
|
||||
<div className="LimitRangeDetails">
|
||||
<KubeObjectMeta object={limitRange}/>
|
||||
|
||||
{containerLimits.length > 0 && (
|
||||
<DrawerItem name="Container Limits" labelsOnly>
|
||||
{
|
||||
|
||||
@ -14,7 +14,6 @@ import { Input } from "../input";
|
||||
import { Button } from "../button";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { ConfigMap } from "../../../common/k8s-api/endpoints";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import type { ConfigMapStore } from "./store";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
@ -95,7 +94,6 @@ class NonInjectedConfigMapDetails extends React.Component<ConfigMapDetailsProps
|
||||
|
||||
return (
|
||||
<div className="ConfigMapDetails">
|
||||
<KubeObjectMeta object={configMap}/>
|
||||
{
|
||||
data.length > 0 && (
|
||||
<>
|
||||
|
||||
@ -11,7 +11,6 @@ import { DrawerItem } from "../drawer";
|
||||
import { Badge } from "../badge";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { PodDisruptionBudget } from "../../../common/k8s-api/endpoints";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import logger from "../../../common/logger";
|
||||
|
||||
export interface PodDisruptionBudgetDetailsProps extends KubeObjectDetailsProps<PodDisruptionBudget> {
|
||||
@ -37,8 +36,6 @@ export class PodDisruptionBudgetDetails extends React.Component<PodDisruptionBud
|
||||
|
||||
return (
|
||||
<div className="PdbDetails">
|
||||
<KubeObjectMeta object={pdb}/>
|
||||
|
||||
{selectors.length > 0 && (
|
||||
<DrawerItem name="Selector" labelsOnly>
|
||||
{
|
||||
|
||||
@ -10,7 +10,6 @@ import { observer } from "mobx-react";
|
||||
import { DrawerItem } from "../drawer";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import type { PriorityClass } from "../../../common/k8s-api/endpoints";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
|
||||
export interface PriorityClassesDetailsProps extends KubeObjectDetailsProps<PriorityClass> {
|
||||
}
|
||||
@ -23,8 +22,6 @@ export class PriorityClassesDetails extends React.Component<PriorityClassesDetai
|
||||
|
||||
return (
|
||||
<div className="PriorityClassesDetails">
|
||||
<KubeObjectMeta object={pc} />
|
||||
|
||||
<DrawerItem name="Description">
|
||||
{pc.getDescription()}
|
||||
</DrawerItem>
|
||||
|
||||
@ -13,7 +13,6 @@ import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { ResourceQuota } from "../../../common/k8s-api/endpoints/resource-quota.api";
|
||||
import { LineProgress } from "../line-progress";
|
||||
import { Table, TableCell, TableHead, TableRow } from "../table";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import logger from "../../../common/logger";
|
||||
|
||||
export interface ResourceQuotaDetailsProps extends KubeObjectDetailsProps<ResourceQuota> {
|
||||
@ -93,8 +92,6 @@ export class ResourceQuotaDetails extends React.Component<ResourceQuotaDetailsPr
|
||||
|
||||
return (
|
||||
<div className="ResourceQuotaDetails">
|
||||
<KubeObjectMeta object={quota}/>
|
||||
|
||||
<DrawerItem name="Quotas" className="quota-list">
|
||||
{renderQuotas(quota)}
|
||||
</DrawerItem>
|
||||
|
||||
@ -10,7 +10,6 @@ import { observer } from "mobx-react";
|
||||
import { DrawerItem } from "../drawer";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import type { RuntimeClass } from "../../../common/k8s-api/endpoints";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import { Badge } from "../badge";
|
||||
import { RuntimeClassDetailsTolerations } from "./runtime-classes-details-tolerations";
|
||||
|
||||
@ -26,8 +25,6 @@ export class RuntimeClassesDetails extends React.Component<RuntimeClassesDetails
|
||||
|
||||
return (
|
||||
<div className="RuntimeClassesDetails">
|
||||
<KubeObjectMeta object={rc} />
|
||||
|
||||
<DrawerItem name="Handler">
|
||||
{rc.getHandler()}
|
||||
</DrawerItem>
|
||||
|
||||
@ -16,7 +16,6 @@ import { base64, toggle } from "../../utils";
|
||||
import { Icon } from "../icon";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { Secret } from "../../../common/k8s-api/endpoints";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import type { SecretStore } from "./store";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
@ -161,7 +160,6 @@ class NonInjectedSecretDetails extends React.Component<SecretDetailsProps & Depe
|
||||
|
||||
return (
|
||||
<div className="SecretDetails">
|
||||
<KubeObjectMeta object={secret}/>
|
||||
<DrawerItem name="Type">
|
||||
{secret.type}
|
||||
</DrawerItem>
|
||||
|
||||
@ -5,35 +5,6 @@ exports[`<CustomResourceDetails /> with a CRD with a boolean field should displa
|
||||
<div
|
||||
class="CrdResourceDetails MyCrd"
|
||||
>
|
||||
<div
|
||||
class="DrawerItem"
|
||||
>
|
||||
<span
|
||||
class="name"
|
||||
>
|
||||
Created
|
||||
</span>
|
||||
<span
|
||||
class="value"
|
||||
>
|
||||
<unknown>
|
||||
ago
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="DrawerItem"
|
||||
>
|
||||
<span
|
||||
class="name"
|
||||
>
|
||||
Name
|
||||
</span>
|
||||
<span
|
||||
class="value"
|
||||
>
|
||||
first-crd
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="DrawerItem"
|
||||
>
|
||||
@ -57,35 +28,6 @@ exports[`<CustomResourceDetails /> with a CRD with a boolean field should displa
|
||||
<div
|
||||
class="CrdResourceDetails MyCrd"
|
||||
>
|
||||
<div
|
||||
class="DrawerItem"
|
||||
>
|
||||
<span
|
||||
class="name"
|
||||
>
|
||||
Created
|
||||
</span>
|
||||
<span
|
||||
class="value"
|
||||
>
|
||||
<unknown>
|
||||
ago
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="DrawerItem"
|
||||
>
|
||||
<span
|
||||
class="name"
|
||||
>
|
||||
Name
|
||||
</span>
|
||||
<span
|
||||
class="value"
|
||||
>
|
||||
first-crd
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="DrawerItem"
|
||||
>
|
||||
@ -109,35 +51,6 @@ exports[`<CustomResourceDetails /> with a CRD with a number field should display
|
||||
<div
|
||||
class="CrdResourceDetails MyCrd"
|
||||
>
|
||||
<div
|
||||
class="DrawerItem"
|
||||
>
|
||||
<span
|
||||
class="name"
|
||||
>
|
||||
Created
|
||||
</span>
|
||||
<span
|
||||
class="value"
|
||||
>
|
||||
<unknown>
|
||||
ago
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="DrawerItem"
|
||||
>
|
||||
<span
|
||||
class="name"
|
||||
>
|
||||
Name
|
||||
</span>
|
||||
<span
|
||||
class="value"
|
||||
>
|
||||
first-crd
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="DrawerItem"
|
||||
>
|
||||
@ -161,35 +74,6 @@ exports[`<CustomResourceDetails /> with a CRD with a number field should display
|
||||
<div
|
||||
class="CrdResourceDetails MyCrd"
|
||||
>
|
||||
<div
|
||||
class="DrawerItem"
|
||||
>
|
||||
<span
|
||||
class="name"
|
||||
>
|
||||
Created
|
||||
</span>
|
||||
<span
|
||||
class="value"
|
||||
>
|
||||
<unknown>
|
||||
ago
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="DrawerItem"
|
||||
>
|
||||
<span
|
||||
class="name"
|
||||
>
|
||||
Name
|
||||
</span>
|
||||
<span
|
||||
class="value"
|
||||
>
|
||||
first-crd
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="DrawerItem"
|
||||
>
|
||||
|
||||
@ -14,7 +14,6 @@ import { DrawerItem, DrawerTitle } from "../drawer";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { Table, TableCell, TableHead, TableRow } from "../table";
|
||||
import { Input } from "../input";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import { MonacoEditor } from "../monaco-editor";
|
||||
import logger from "../../../common/logger";
|
||||
|
||||
@ -42,8 +41,6 @@ export class CRDDetails extends React.Component<CRDDetailsProps> {
|
||||
|
||||
return (
|
||||
<div className="CRDDetails">
|
||||
<KubeObjectMeta object={crd}/>
|
||||
|
||||
<DrawerItem name="Group">
|
||||
{crd.getGroup()}
|
||||
</DrawerItem>
|
||||
|
||||
@ -11,7 +11,6 @@ import { cssNames } from "../../utils";
|
||||
import { Badge } from "../badge";
|
||||
import { DrawerItem } from "../drawer";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import { Input } from "../input";
|
||||
import type { AdditionalPrinterColumnsV1 } from "../../../common/k8s-api/endpoints/custom-resource-definition.api";
|
||||
import { CustomResourceDefinition } from "../../../common/k8s-api/endpoints/custom-resource-definition.api";
|
||||
@ -21,7 +20,7 @@ import { KubeObject } from "../../../common/k8s-api/kube-object";
|
||||
import logger from "../../../common/logger";
|
||||
|
||||
export interface CustomResourceDetailsProps extends KubeObjectDetailsProps<KubeObject> {
|
||||
crd: CustomResourceDefinition;
|
||||
crd?: CustomResourceDefinition;
|
||||
}
|
||||
|
||||
function convertSpecValue(value: unknown): React.ReactNode {
|
||||
@ -129,7 +128,6 @@ export class CustomResourceDetails extends React.Component<CustomResourceDetails
|
||||
|
||||
return (
|
||||
<div className={cssNames("CrdResourceDetails", crd.getResourceKind())}>
|
||||
<KubeObjectMeta object={object} />
|
||||
{this.renderAdditionalColumns(object, extraColumns)}
|
||||
{this.renderStatus(object, extraColumns)}
|
||||
</div>
|
||||
|
||||
@ -58,7 +58,6 @@ export class CustomResourceDefinitionStore extends KubeObjectStore<CustomResourc
|
||||
}
|
||||
|
||||
getByObject(obj: KubeObject) {
|
||||
if (!obj) return null;
|
||||
const { kind, apiVersion } = obj;
|
||||
|
||||
return this.items.find(crd => (
|
||||
|
||||
@ -12,7 +12,6 @@ import { Link } from "react-router-dom";
|
||||
import { observer } from "mobx-react";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { KubeEvent } from "../../../common/k8s-api/endpoints/events.api";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import { Table, TableCell, TableHead, TableRow } from "../table";
|
||||
import type { ApiManager } from "../../../common/k8s-api/api-manager";
|
||||
import logger from "../../../common/logger";
|
||||
@ -52,8 +51,6 @@ const NonInjectedEventDetails = observer(({
|
||||
|
||||
return (
|
||||
<div className={cssNames("EventDetails", className)}>
|
||||
<KubeObjectMeta object={event}/>
|
||||
|
||||
<DrawerItem name="Message">
|
||||
{message}
|
||||
</DrawerItem>
|
||||
|
||||
@ -13,13 +13,13 @@ import type { KubeObject } from "../../../common/k8s-api/kube-object";
|
||||
import { Pod } from "../../../common/k8s-api/endpoints/pod.api";
|
||||
import type { GetPodById } from "../+workloads-pods/get-pod-by-id.injectable";
|
||||
|
||||
export interface EventStoreDependencies {
|
||||
interface Dependencies {
|
||||
getPodById: GetPodById;
|
||||
}
|
||||
|
||||
export class EventStore extends KubeObjectStore<KubeEvent, KubeEventApi> {
|
||||
constructor(
|
||||
protected readonly dependencies: EventStoreDependencies,
|
||||
protected readonly dependencies: Dependencies,
|
||||
api: KubeEventApi,
|
||||
opts: KubeObjectStoreOptions = {},
|
||||
) {
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* 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";
|
||||
|
||||
interface Dependencies {
|
||||
metrics: IAsyncComputed<PodMetricInNamespaceData>;
|
||||
}
|
||||
|
||||
const NonInjectedNamespaceMetricsDetailsComponent = ({
|
||||
object,
|
||||
metrics,
|
||||
}: KubeObjectDetailsProps<Namespace> & Dependencies) => (
|
||||
<ResourceMetrics
|
||||
tabs={podMetricTabs}
|
||||
object={object}
|
||||
metrics={metrics}
|
||||
>
|
||||
<PodCharts />
|
||||
</ResourceMetrics>
|
||||
);
|
||||
|
||||
const NamespaceMetricsDetailsComponent = withInjectables<Dependencies, KubeObjectDetailsProps<Namespace>>(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;
|
||||
29
src/renderer/components/+namespaces/metrics.injectable.ts
Normal file
29
src/renderer/components/+namespaces/metrics.injectable.ts
Normal file
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import { asyncComputed } from "@ogre-tools/injectable-react";
|
||||
import { now } from "mobx-utils";
|
||||
import type { Namespace } from "../../../common/k8s-api/endpoints";
|
||||
import requestPodMetricsInNamespaceInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-in-namespace.injectable";
|
||||
|
||||
const namespaceMetricsInjectable = getInjectable({
|
||||
id: "namespace-metrics",
|
||||
instantiate: (di, namespace) => {
|
||||
const requestPodMetricsInNamespace = di.inject(requestPodMetricsInNamespaceInjectable);
|
||||
|
||||
return asyncComputed({
|
||||
getValueFromObservedPromise: async () => {
|
||||
now(60 * 1000); // Update every minute
|
||||
|
||||
return requestPodMetricsInNamespace(namespace.getName());
|
||||
},
|
||||
});
|
||||
},
|
||||
lifecycle: lifecycleEnum.keyedSingleton({
|
||||
getInstanceKey: (di, namespace: Namespace) => namespace.getId(),
|
||||
}),
|
||||
});
|
||||
|
||||
export default namespaceMetricsInjectable;
|
||||
@ -6,7 +6,7 @@
|
||||
import "./namespace-details.scss";
|
||||
|
||||
import React from "react";
|
||||
import { computed, makeObservable, observable, reaction } from "mobx";
|
||||
import { computed, makeObservable } from "mobx";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { DrawerItem } from "../drawer";
|
||||
import { cssNames } from "../../utils";
|
||||
@ -14,42 +14,32 @@ import { Namespace } from "../../../common/k8s-api/endpoints";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Spinner } from "../spinner";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import { ResourceMetrics } from "../resource-metrics";
|
||||
import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts";
|
||||
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||
import logger from "../../../common/logger";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
|
||||
import type { SubscribeStores } from "../../kube-watch-api/kube-watch-api";
|
||||
import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable";
|
||||
import type { GetActiveClusterEntity } from "../../api/catalog/entity/get-active-cluster-entity.injectable";
|
||||
import type { GetDetailsUrl } from "../kube-detail-params/get-details-url.injectable";
|
||||
import type { ResourceQuotaStore } from "../+config-resource-quotas/store";
|
||||
import type { LimitRangeStore } from "../+config-limit-ranges/store";
|
||||
import getActiveClusterEntityInjectable from "../../api/catalog/entity/get-active-cluster-entity.injectable";
|
||||
import getDetailsUrlInjectable from "../kube-detail-params/get-details-url.injectable";
|
||||
import limitRangeStoreInjectable from "../+config-limit-ranges/store.injectable";
|
||||
import resourceQuotaStoreInjectable from "../+config-resource-quotas/store.injectable";
|
||||
import type { PodMetricInNamespaceData, RequestPodMetricsInNamespace } from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-in-namespace.injectable";
|
||||
import requestPodMetricsInNamespaceInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-in-namespace.injectable";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface NamespaceDetailsProps extends KubeObjectDetailsProps<Namespace> {
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
subscribeStores: SubscribeStores;
|
||||
getActiveClusterEntity: GetActiveClusterEntity;
|
||||
getDetailsUrl: GetDetailsUrl;
|
||||
resourceQuotaStore: ResourceQuotaStore;
|
||||
limitRangeStore: LimitRangeStore;
|
||||
requestPodMetricsInNamespace: RequestPodMetricsInNamespace;
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
@observer
|
||||
class NonInjectedNamespaceDetails extends React.Component<NamespaceDetailsProps & Dependencies> {
|
||||
@observable metrics: PodMetricInNamespaceData | null = null;
|
||||
|
||||
constructor(props: NamespaceDetailsProps & Dependencies) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
@ -57,10 +47,6 @@ class NonInjectedNamespaceDetails extends React.Component<NamespaceDetailsProps
|
||||
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
}),
|
||||
|
||||
this.props.subscribeStores([
|
||||
this.props.resourceQuotaStore,
|
||||
this.props.limitRangeStore,
|
||||
@ -80,40 +66,23 @@ class NonInjectedNamespaceDetails extends React.Component<NamespaceDetailsProps
|
||||
return this.props.limitRangeStore.getAllByNs(namespace);
|
||||
}
|
||||
|
||||
loadMetrics = async () => {
|
||||
this.metrics = await this.props.requestPodMetricsInNamespace(this.props.object.getName());
|
||||
};
|
||||
|
||||
render() {
|
||||
const { object: namespace, getActiveClusterEntity, resourceQuotaStore, getDetailsUrl, limitRangeStore } = this.props;
|
||||
const { object: namespace, resourceQuotaStore, getDetailsUrl, limitRangeStore } = this.props;
|
||||
|
||||
if (!namespace) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!(namespace instanceof Namespace)) {
|
||||
logger.error("[NamespaceDetails]: passed object that is not an instanceof Namespace", namespace);
|
||||
this.props.logger.error("[NamespaceDetails]: passed object that is not an instanceof Namespace", namespace);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
const status = namespace.getStatus();
|
||||
const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Namespace);
|
||||
|
||||
return (
|
||||
<div className="NamespaceDetails">
|
||||
{!isMetricHidden && (
|
||||
<ResourceMetrics
|
||||
loader={this.loadMetrics}
|
||||
tabs={podMetricTabs}
|
||||
object={namespace}
|
||||
metrics={this.metrics}
|
||||
>
|
||||
<PodCharts />
|
||||
</ResourceMetrics>
|
||||
)}
|
||||
<KubeObjectMeta object={namespace}/>
|
||||
|
||||
<DrawerItem name="Status">
|
||||
<span className={cssNames("status", status.toLowerCase())}>{status}</span>
|
||||
</DrawerItem>
|
||||
@ -143,11 +112,10 @@ export const NamespaceDetails = withInjectables<Dependencies, NamespaceDetailsPr
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
subscribeStores: di.inject(subscribeStoresInjectable),
|
||||
getActiveClusterEntity: di.inject(getActiveClusterEntityInjectable),
|
||||
getDetailsUrl: di.inject(getDetailsUrlInjectable),
|
||||
limitRangeStore: di.inject(limitRangeStoreInjectable),
|
||||
resourceQuotaStore: di.inject(resourceQuotaStoreInjectable),
|
||||
requestPodMetricsInNamespace: di.inject(requestPodMetricsInNamespaceInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@ -10,7 +10,6 @@ import { observer } from "mobx-react";
|
||||
import { DrawerTitle } from "../drawer";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { Endpoints } from "../../../common/k8s-api/endpoints";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import { EndpointSubsetList } from "./endpoint-subset-list";
|
||||
import logger from "../../../common/logger";
|
||||
|
||||
@ -34,7 +33,6 @@ export class EndpointsDetails extends React.Component<EndpointsDetailsProps> {
|
||||
|
||||
return (
|
||||
<div className="EndpointDetails">
|
||||
<KubeObjectMeta object={endpoint}/>
|
||||
<DrawerTitle>Subsets</DrawerTitle>
|
||||
{
|
||||
endpoint.getEndpointSubsets().map((subset) => (
|
||||
|
||||
@ -6,54 +6,26 @@
|
||||
import "./ingress-details.scss";
|
||||
|
||||
import React from "react";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { makeObservable, observable, reaction } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import { DrawerItem, DrawerTitle } from "../drawer";
|
||||
import type { ILoadBalancerIngress } from "../../../common/k8s-api/endpoints";
|
||||
import { Ingress } from "../../../common/k8s-api/endpoints";
|
||||
import { Table, TableCell, TableHead, TableRow } from "../table";
|
||||
import { ResourceMetrics } from "../resource-metrics";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { IngressCharts } from "./ingress-charts";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import { computeRuleDeclarations } from "../../../common/k8s-api/endpoints/ingress.api";
|
||||
import { getActiveClusterEntity } from "../../api/catalog/entity/legacy-globals";
|
||||
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||
import logger from "../../../common/logger";
|
||||
import type { IngressMetricData, RequestIngressMetrics } from "../../../common/k8s-api/endpoints/metrics.api/request-ingress-metrics.injectable";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import requestIngressMetricsInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-ingress-metrics.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface IngressDetailsProps extends KubeObjectDetailsProps<Ingress> {
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
requestIngressMetrics: RequestIngressMetrics;
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
@observer
|
||||
class NonInjectedIngressDetails extends React.Component<IngressDetailsProps & Dependencies> {
|
||||
@observable metrics: IngressMetricData | null = null;
|
||||
|
||||
constructor(props: IngressDetailsProps & Dependencies) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
loadMetrics = async () => {
|
||||
const { object: ingress, requestIngressMetrics } = this.props;
|
||||
|
||||
this.metrics = await requestIngressMetrics(ingress.getName(), ingress.getNs());
|
||||
};
|
||||
|
||||
renderPaths(ingress: Ingress) {
|
||||
return ingress.getRules()
|
||||
.map((rule, index) => (
|
||||
@ -124,7 +96,7 @@ class NonInjectedIngressDetails extends React.Component<IngressDetailsProps & De
|
||||
}
|
||||
|
||||
render() {
|
||||
const { object: ingress } = this.props;
|
||||
const { object: ingress, logger } = this.props;
|
||||
|
||||
if (!ingress) {
|
||||
return null;
|
||||
@ -136,25 +108,10 @@ class NonInjectedIngressDetails extends React.Component<IngressDetailsProps & De
|
||||
return null;
|
||||
}
|
||||
|
||||
const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Ingress);
|
||||
const port = ingress.getServiceNamePort();
|
||||
|
||||
return (
|
||||
<div className="IngressDetails">
|
||||
{!isMetricHidden && (
|
||||
<ResourceMetrics
|
||||
loader={this.loadMetrics}
|
||||
tabs={[
|
||||
"Network",
|
||||
"Duration",
|
||||
]}
|
||||
object={ingress}
|
||||
metrics={this.metrics}
|
||||
>
|
||||
<IngressCharts/>
|
||||
</ResourceMetrics>
|
||||
)}
|
||||
<KubeObjectMeta object={ingress}/>
|
||||
<DrawerItem name="Ports">
|
||||
{ingress.getPorts()}
|
||||
</DrawerItem>
|
||||
@ -181,6 +138,6 @@ class NonInjectedIngressDetails extends React.Component<IngressDetailsProps & De
|
||||
export const IngressDetails = withInjectables<Dependencies, IngressDetailsProps>(NonInjectedIngressDetails, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
requestIngressMetrics: di.inject(requestIngressMetricsInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
@ -32,85 +32,86 @@ interface Dependencies {
|
||||
filterByNamespace: FilterByNamespace;
|
||||
}
|
||||
|
||||
@observer
|
||||
class NonInjectedIngresses extends React.Component<Dependencies> {
|
||||
render() {
|
||||
const NonInjectedIngresses = observer((props: Dependencies) => {
|
||||
const {
|
||||
ingressStore,
|
||||
filterByNamespace,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<SiblingsInTabLayout>
|
||||
<KubeObjectListLayout
|
||||
isConfigurable
|
||||
tableId="network_ingresses"
|
||||
className="Ingresses"
|
||||
store={this.props.ingressStore}
|
||||
sortingCallbacks={{
|
||||
store={ ingressStore }
|
||||
sortingCallbacks={ {
|
||||
[columnId.name]: ingress => ingress.getName(),
|
||||
[columnId.namespace]: ingress => ingress.getNs(),
|
||||
[columnId.age]: ingress => -ingress.getCreationTimestamp(),
|
||||
}}
|
||||
searchFilters={[
|
||||
} }
|
||||
searchFilters={ [
|
||||
ingress => ingress.getSearchFields(),
|
||||
ingress => ingress.getPorts(),
|
||||
]}
|
||||
] }
|
||||
renderHeaderTitle="Ingresses"
|
||||
renderTableHeader={[
|
||||
renderTableHeader={ [
|
||||
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||
{ className: "warning", showWithColumn: columnId.name },
|
||||
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
|
||||
{ title: "LoadBalancers", className: "loadbalancers", id: columnId.loadBalancers },
|
||||
{ title: "Rules", className: "rules", id: columnId.rules },
|
||||
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||
]}
|
||||
renderTableContents={ingress => [
|
||||
] }
|
||||
renderTableContents={ ingress => [
|
||||
ingress.getName(),
|
||||
<KubeObjectStatusIcon key="icon" object={ingress} />,
|
||||
<KubeObjectStatusIcon key="icon" object={ ingress } />,
|
||||
<a
|
||||
key="namespace"
|
||||
className="filterNamespace"
|
||||
onClick={prevDefault(() => this.props.filterByNamespace(ingress.getNs()))}
|
||||
onClick={prevDefault(() => filterByNamespace(ingress.getNs()))}
|
||||
>
|
||||
{ingress.getNs()}
|
||||
</a>,
|
||||
ingress.getLoadBalancers().map(lb => <p key={lb}>{lb}</p>),
|
||||
ingress.getLoadBalancers().map(lb => <p key={ lb }>{ lb }</p>),
|
||||
computeRouteDeclarations(ingress).map(decl => (
|
||||
decl.displayAsLink
|
||||
? (
|
||||
<div key={decl.url} className="ingressRule">
|
||||
<div key={ decl.url } className="ingressRule">
|
||||
<a
|
||||
href={decl.url}
|
||||
href={ decl.url }
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
onClick={e => e.stopPropagation()}
|
||||
onClick={ e => e.stopPropagation() }
|
||||
>
|
||||
{decl.url}
|
||||
{ decl.url }
|
||||
</a>
|
||||
{` ⇢ ${decl.service}`}
|
||||
{ ` ⇢ ${decl.service}` }
|
||||
</div>
|
||||
)
|
||||
: (
|
||||
<div key={decl.url} className="ingressRule">
|
||||
{`${decl.url} ⇢ ${decl.service}`}
|
||||
<div key={ decl.url } className="ingressRule">
|
||||
{ `${decl.url} ⇢ ${decl.service}` }
|
||||
</div>
|
||||
)
|
||||
)),
|
||||
<KubeObjectAge key="age" object={ingress} />,
|
||||
]}
|
||||
tableProps={{
|
||||
<KubeObjectAge key="age" object={ ingress } />,
|
||||
] }
|
||||
tableProps={ {
|
||||
customRowHeights: (item, lineHeight, paddings) => {
|
||||
const lines = item.getRoutes().length || 1;
|
||||
|
||||
return lines * lineHeight + paddings;
|
||||
},
|
||||
}}
|
||||
/>
|
||||
} } />
|
||||
</SiblingsInTabLayout>
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export const Ingresses = withInjectables<Dependencies>(NonInjectedIngresses, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
filterByNamespace: di.inject(filterByNamespaceInjectable),
|
||||
ingressStore: di.inject(ingressStoreInjectable),
|
||||
filterByNamespace: di.inject(filterByNamespaceInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* 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";
|
||||
|
||||
interface Dependencies {
|
||||
metrics: IAsyncComputed<IngressMetricData>;
|
||||
}
|
||||
|
||||
const NonInjectedIngressMetricsDetailsComponent = ({
|
||||
object,
|
||||
metrics,
|
||||
}: KubeObjectDetailsProps<Ingress> & Dependencies) => (
|
||||
<ResourceMetrics
|
||||
tabs={[
|
||||
"Network",
|
||||
"Duration",
|
||||
]}
|
||||
object={object}
|
||||
metrics={metrics}
|
||||
>
|
||||
<IngressCharts />
|
||||
</ResourceMetrics>
|
||||
);
|
||||
|
||||
const IngressMetricsDetailsComponent = withInjectables<Dependencies, KubeObjectDetailsProps<Ingress>>(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;
|
||||
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import { asyncComputed } from "@ogre-tools/injectable-react";
|
||||
import { now } from "mobx-utils";
|
||||
import type { Ingress } from "../../../common/k8s-api/endpoints";
|
||||
import requestIngressMetricsInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-ingress-metrics.injectable";
|
||||
|
||||
const ingressMetricsInjectable = getInjectable({
|
||||
id: "ingress-metrics",
|
||||
instantiate: (di, ingress) => {
|
||||
const requestIngressMetrics = di.inject(requestIngressMetricsInjectable);
|
||||
|
||||
return asyncComputed({
|
||||
getValueFromObservedPromise: async () => {
|
||||
now(60 * 1000); // Update every minute
|
||||
|
||||
return requestIngressMetrics(ingress.getName(), ingress.getNs());
|
||||
},
|
||||
});
|
||||
},
|
||||
lifecycle: lifecycleEnum.keyedSingleton({
|
||||
getInstanceKey: (di, ingress: Ingress) => ingress.getId(),
|
||||
}),
|
||||
});
|
||||
|
||||
export default ingressMetricsInjectable;
|
||||
@ -13,7 +13,6 @@ import { Badge } from "../badge";
|
||||
import { SubTitle } from "../layout/sub-title";
|
||||
import { observer } from "mobx-react";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import logger from "../../../common/logger";
|
||||
import type { LabelMatchExpression, LabelSelector } from "../../../common/k8s-api/kube-object";
|
||||
import { isEmpty } from "lodash";
|
||||
@ -170,8 +169,6 @@ export class NetworkPolicyDetails extends React.Component<NetworkPolicyDetailsPr
|
||||
|
||||
return (
|
||||
<div className={styles.NetworkPolicyDetails}>
|
||||
<KubeObjectMeta object={policy}/>
|
||||
|
||||
<DrawerItem name="Pod Selector" labelsOnly={selector.length > 0}>
|
||||
{
|
||||
selector.length > 0
|
||||
|
||||
@ -11,7 +11,6 @@ import { DrawerItem, DrawerTitle } from "../drawer";
|
||||
import { Badge } from "../badge";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { Service } from "../../../common/k8s-api/endpoints";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import { ServicePortComponent } from "./service-port-component";
|
||||
import type { EndpointsStore } from "../+network-endpoints/store";
|
||||
import { ServiceDetailsEndpoint } from "./service-details-endpoint";
|
||||
@ -75,8 +74,6 @@ class NonInjectedServiceDetails extends React.Component<ServiceDetailsProps & De
|
||||
|
||||
return (
|
||||
<div className="ServicesDetails">
|
||||
<KubeObjectMeta object={service}/>
|
||||
|
||||
<DrawerItem name="Selector" labelsOnly>
|
||||
{service.getSelector().map(selector => <Badge key={selector} label={selector}/>)}
|
||||
</DrawerItem>
|
||||
|
||||
@ -11,26 +11,18 @@ import kebabCase from "lodash/kebabCase";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { DrawerItem, DrawerItemLabels } from "../drawer";
|
||||
import { Badge } from "../badge";
|
||||
import { ResourceMetrics } from "../resource-metrics";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { formatNodeTaint, Node } from "../../../common/k8s-api/endpoints";
|
||||
import { NodeCharts } from "./node-charts";
|
||||
import { makeObservable, observable, reaction } from "mobx";
|
||||
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||
import { NodeDetailsResources } from "./details-resources";
|
||||
import { DrawerTitle } from "../drawer/drawer-title";
|
||||
import logger from "../../../common/logger";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import type { SubscribeStores } from "../../kube-watch-api/kube-watch-api";
|
||||
import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable";
|
||||
import type { PodStore } from "../+workloads-pods/store";
|
||||
import podStoreInjectable from "../+workloads-pods/store.injectable";
|
||||
import type { GetActiveClusterEntity } from "../../api/catalog/entity/get-active-cluster-entity.injectable";
|
||||
import getActiveClusterEntityInjectable from "../../api/catalog/entity/get-active-cluster-entity.injectable";
|
||||
import type { ClusterMetricData, RequestClusterMetricsByNodeNames } from "../../../common/k8s-api/endpoints/metrics.api/request-cluster-metrics-by-node-names.injectable";
|
||||
import requestClusterMetricsByNodeNamesInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-cluster-metrics-by-node-names.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface NodeDetailsProps extends KubeObjectDetailsProps<Node> {
|
||||
}
|
||||
@ -38,39 +30,21 @@ export interface NodeDetailsProps extends KubeObjectDetailsProps<Node> {
|
||||
interface Dependencies {
|
||||
subscribeStores: SubscribeStores;
|
||||
podStore: PodStore;
|
||||
getActiveClusterEntity: GetActiveClusterEntity;
|
||||
requestClusterMetricsByNodeNames: RequestClusterMetricsByNodeNames;
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
@observer
|
||||
class NonInjectedNodeDetails extends React.Component<NodeDetailsProps & Dependencies> {
|
||||
@observable metrics: ClusterMetricData | null = null;
|
||||
|
||||
constructor(props: NodeDetailsProps & Dependencies) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.props.object.getName(), () => {
|
||||
this.metrics = null;
|
||||
}),
|
||||
|
||||
this.props.subscribeStores([
|
||||
this.props.podStore,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
loadMetrics = async () => {
|
||||
const { object: node, requestClusterMetricsByNodeNames } = this.props;
|
||||
|
||||
this.metrics = await requestClusterMetricsByNodeNames([node.getName()]);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { object: node, podStore, getActiveClusterEntity } = this.props;
|
||||
const { object: node, podStore, logger } = this.props;
|
||||
|
||||
if (!node) {
|
||||
return null;
|
||||
@ -86,27 +60,9 @@ class NonInjectedNodeDetails extends React.Component<NodeDetailsProps & Dependen
|
||||
const conditions = node.getActiveConditions();
|
||||
const taints = node.getTaints();
|
||||
const childPods = podStore.getPodsByNode(node.getName());
|
||||
const { metrics } = this;
|
||||
const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Node);
|
||||
|
||||
return (
|
||||
<div className="NodeDetails">
|
||||
{!isMetricHidden && podStore.isLoaded && (
|
||||
<ResourceMetrics
|
||||
loader={this.loadMetrics}
|
||||
tabs={[
|
||||
"CPU",
|
||||
"Memory",
|
||||
"Disk",
|
||||
"Pods",
|
||||
]}
|
||||
object={node}
|
||||
metrics={metrics}
|
||||
>
|
||||
<NodeCharts/>
|
||||
</ResourceMetrics>
|
||||
)}
|
||||
<KubeObjectMeta object={node} hideFields={["labels", "annotations", "uid", "resourceVersion", "selfLink"]}/>
|
||||
{addresses && (
|
||||
<DrawerItem name="Addresses">
|
||||
{
|
||||
@ -197,8 +153,7 @@ export const NodeDetails = withInjectables<Dependencies, NodeDetailsProps>(NonIn
|
||||
...props,
|
||||
subscribeStores: di.inject(subscribeStoresInjectable),
|
||||
podStore: di.inject(podStoreInjectable),
|
||||
getActiveClusterEntity: di.inject(getActiveClusterEntityInjectable),
|
||||
requestClusterMetricsByNodeNames: di.inject(requestClusterMetricsByNodeNamesInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { asLegacyGlobalForExtensionApi } from "../../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api";
|
||||
import nodeStoreInjectable from "./store.injectable";
|
||||
|
||||
/**
|
||||
* @deprecated use `di.inject(nodeStoreInjectable)` instead
|
||||
*/
|
||||
export const nodeStore = asLegacyGlobalForExtensionApi(nodeStoreInjectable);
|
||||
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* 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";
|
||||
|
||||
interface Dependencies {
|
||||
metrics: IAsyncComputed<ClusterMetricData>;
|
||||
}
|
||||
|
||||
const NonInjectedNodeMetricsDetailsComponent = ({
|
||||
object,
|
||||
metrics,
|
||||
}: KubeObjectDetailsProps<Node> & Dependencies) => (
|
||||
<ResourceMetrics
|
||||
tabs={[
|
||||
"CPU",
|
||||
"Memory",
|
||||
"Disk",
|
||||
"Pods",
|
||||
]}
|
||||
object={object}
|
||||
metrics={metrics}
|
||||
>
|
||||
<NodeCharts />
|
||||
</ResourceMetrics>
|
||||
);
|
||||
|
||||
const NodeMetricsDetailsComponent = withInjectables<Dependencies, KubeObjectDetailsProps<Node>>(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;
|
||||
29
src/renderer/components/+nodes/metrics.injectable.ts
Normal file
29
src/renderer/components/+nodes/metrics.injectable.ts
Normal file
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import { asyncComputed } from "@ogre-tools/injectable-react";
|
||||
import { now } from "mobx-utils";
|
||||
import type { Node } from "../../../common/k8s-api/endpoints";
|
||||
import requestClusterMetricsByNodeNamesInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-cluster-metrics-by-node-names.injectable";
|
||||
|
||||
const nodeMetricsInjectable = getInjectable({
|
||||
id: "node-metrics",
|
||||
instantiate: (di, node) => {
|
||||
const requestClusterMetricsByNodeNames = di.inject(requestClusterMetricsByNodeNamesInjectable);
|
||||
|
||||
return asyncComputed({
|
||||
getValueFromObservedPromise: () => {
|
||||
now(60 * 1000);
|
||||
|
||||
return requestClusterMetricsByNodeNames([node.getName()]);
|
||||
},
|
||||
});
|
||||
},
|
||||
lifecycle: lifecycleEnum.keyedSingleton({
|
||||
getInstanceKey: (di, node: Node) => node.getId(),
|
||||
}),
|
||||
});
|
||||
|
||||
export default nodeMetricsInjectable;
|
||||
@ -12,7 +12,6 @@ import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { PodSecurityPolicy } from "../../../common/k8s-api/endpoints";
|
||||
import { Badge } from "../badge";
|
||||
import { Table, TableCell, TableHead, TableRow } from "../table";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import logger from "../../../common/logger";
|
||||
|
||||
export interface PodSecurityPolicyDetailsProps extends KubeObjectDetailsProps<PodSecurityPolicy> {
|
||||
@ -74,8 +73,6 @@ export class PodSecurityPolicyDetails extends React.Component<PodSecurityPolicyD
|
||||
|
||||
return (
|
||||
<div className="PodSecurityPolicyDetails">
|
||||
<KubeObjectMeta object={psp}/>
|
||||
|
||||
{allowedCapabilities && (
|
||||
<DrawerItem name="Allowed Capabilities">
|
||||
{allowedCapabilities.join(", ")}
|
||||
|
||||
@ -12,7 +12,6 @@ import { Badge } from "../badge";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { StorageClass } from "../../../common/k8s-api/endpoints";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import type { StorageClassStore } from "./store";
|
||||
import { VolumeDetailsList } from "../+storage-volumes/volume-details-list";
|
||||
import type { PersistentVolumeStore } from "../+storage-volumes/store";
|
||||
@ -60,8 +59,6 @@ class NonInjectedStorageClassDetails extends React.Component<StorageClassDetails
|
||||
|
||||
return (
|
||||
<div className="StorageClassDetails">
|
||||
<KubeObjectMeta object={storageClass}/>
|
||||
|
||||
{provisioner && (
|
||||
<DrawerItem name="Provisioner" labelsOnly>
|
||||
<Badge label={provisioner}/>
|
||||
|
||||
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* 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";
|
||||
|
||||
interface Dependencies {
|
||||
metrics: IAsyncComputed<PersistentVolumeClaimMetricData>;
|
||||
}
|
||||
|
||||
const NonInjectedPersistentVolumeClaimMetricsDetailsComponent = ({
|
||||
object,
|
||||
metrics,
|
||||
}: KubeObjectDetailsProps<PersistentVolumeClaim> & Dependencies) => (
|
||||
<ResourceMetrics
|
||||
tabs={[
|
||||
"Disk",
|
||||
]}
|
||||
object={object}
|
||||
metrics={metrics}
|
||||
>
|
||||
<VolumeClaimDiskChart />
|
||||
</ResourceMetrics>
|
||||
);
|
||||
|
||||
const PersistentVolumeClaimMetricsDetailsComponent = withInjectables<Dependencies, KubeObjectDetailsProps<PersistentVolumeClaim>>(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;
|
||||
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import { asyncComputed } from "@ogre-tools/injectable-react";
|
||||
import { now } from "mobx-utils";
|
||||
import type { PersistentVolumeClaim } from "../../../common/k8s-api/endpoints";
|
||||
import requestPersistentVolumeClaimMetricsInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-persistent-volume-claim-metrics.injectable";
|
||||
|
||||
const persistentVolumeClaimMetricsInjectable = getInjectable({
|
||||
id: "persistent-volume-claim-metrics",
|
||||
instantiate: (di, persistentVolumeClaim) => {
|
||||
const requestPersistentVolumeClaimMetrics = di.inject(requestPersistentVolumeClaimMetricsInjectable);
|
||||
|
||||
return asyncComputed({
|
||||
getValueFromObservedPromise: () => {
|
||||
now(60 * 1000); // update every minute
|
||||
|
||||
return requestPersistentVolumeClaimMetrics(persistentVolumeClaim);
|
||||
},
|
||||
});
|
||||
},
|
||||
lifecycle: lifecycleEnum.keyedSingleton({
|
||||
getInstanceKey: (di, persistentVolumeClaim: PersistentVolumeClaim) => persistentVolumeClaim.getId(),
|
||||
}),
|
||||
});
|
||||
|
||||
export default persistentVolumeClaimMetricsInjectable;
|
||||
@ -6,64 +6,37 @@
|
||||
import "./volume-claim-details.scss";
|
||||
|
||||
import React, { Fragment } from "react";
|
||||
import { makeObservable, observable, reaction } from "mobx";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { observer } from "mobx-react";
|
||||
import { DrawerItem, DrawerTitle } from "../drawer";
|
||||
import { Badge } from "../badge";
|
||||
import { Link } from "react-router-dom";
|
||||
import { ResourceMetrics } from "../resource-metrics";
|
||||
import { VolumeClaimDiskChart } from "./volume-claim-disk-chart";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { PersistentVolumeClaim, storageClassApi } from "../../../common/k8s-api/endpoints";
|
||||
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import logger from "../../../common/logger";
|
||||
import type { PersistentVolumeClaimMetricData, RequestPersistentVolumeClaimMetrics } from "../../../common/k8s-api/endpoints/metrics.api/request-persistent-volume-claim-metrics.injectable";
|
||||
import type { StorageClassApi } from "../../../common/k8s-api/endpoints";
|
||||
import { PersistentVolumeClaim } from "../../../common/k8s-api/endpoints";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import requestPersistentVolumeClaimMetricsInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-persistent-volume-claim-metrics.injectable";
|
||||
import type { GetActiveClusterEntity } from "../../api/catalog/entity/get-active-cluster-entity.injectable";
|
||||
import type { GetDetailsUrl } from "../kube-detail-params/get-details-url.injectable";
|
||||
import type { PodStore } from "../+workloads-pods/store";
|
||||
import getActiveClusterEntityInjectable from "../../api/catalog/entity/get-active-cluster-entity.injectable";
|
||||
import getDetailsUrlInjectable from "../kube-detail-params/get-details-url.injectable";
|
||||
import podStoreInjectable from "../+workloads-pods/store.injectable";
|
||||
import { stopPropagation } from "../../../renderer/utils";
|
||||
import storageClassApiInjectable from "../../../common/k8s-api/endpoints/storage-class.api.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface PersistentVolumeClaimDetailsProps extends KubeObjectDetailsProps<PersistentVolumeClaim> {
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
requestPersistentVolumeClaimMetrics: RequestPersistentVolumeClaimMetrics;
|
||||
getActiveClusterEntity: GetActiveClusterEntity;
|
||||
getDetailsUrl: GetDetailsUrl;
|
||||
podStore: PodStore;
|
||||
storageClassApi: StorageClassApi;
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
@observer
|
||||
class NonInjectedPersistentVolumeClaimDetails extends React.Component<PersistentVolumeClaimDetailsProps & Dependencies> {
|
||||
@observable metrics: PersistentVolumeClaimMetricData | null = null;
|
||||
|
||||
constructor(props: PersistentVolumeClaimDetailsProps & Dependencies) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
loadMetrics = async () => {
|
||||
const { object: volumeClaim, requestPersistentVolumeClaimMetrics } = this.props;
|
||||
|
||||
this.metrics = await requestPersistentVolumeClaimMetrics(volumeClaim);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { object: volumeClaim, getActiveClusterEntity, podStore, getDetailsUrl } = this.props;
|
||||
const { object: volumeClaim, podStore, getDetailsUrl, storageClassApi, logger } = this.props;
|
||||
|
||||
if (!volumeClaim) {
|
||||
return null;
|
||||
@ -77,27 +50,13 @@ class NonInjectedPersistentVolumeClaimDetails extends React.Component<Persistent
|
||||
|
||||
const { storageClassName, accessModes } = volumeClaim.spec;
|
||||
const pods = volumeClaim.getPods(podStore.items);
|
||||
const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.VolumeClaim);
|
||||
|
||||
const storageClassDetailsUrl = getDetailsUrl(storageClassApi.getUrl({
|
||||
const storageClassDetailsUrl = getDetailsUrl(storageClassApi.formatUrlForNotListing({
|
||||
name: storageClassName,
|
||||
}));
|
||||
|
||||
return (
|
||||
<div className="PersistentVolumeClaimDetails">
|
||||
{!isMetricHidden && (
|
||||
<ResourceMetrics
|
||||
loader={this.loadMetrics}
|
||||
tabs={[
|
||||
"Disk",
|
||||
]}
|
||||
object={volumeClaim}
|
||||
metrics={this.metrics}
|
||||
>
|
||||
<VolumeClaimDiskChart />
|
||||
</ResourceMetrics>
|
||||
)}
|
||||
<KubeObjectMeta object={volumeClaim} />
|
||||
<DrawerItem name="Access Modes">
|
||||
{accessModes?.join(", ")}
|
||||
</DrawerItem>
|
||||
@ -147,9 +106,9 @@ class NonInjectedPersistentVolumeClaimDetails extends React.Component<Persistent
|
||||
export const PersistentVolumeClaimDetails = withInjectables<Dependencies, PersistentVolumeClaimDetailsProps>(NonInjectedPersistentVolumeClaimDetails, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
requestPersistentVolumeClaimMetrics: di.inject(requestPersistentVolumeClaimMetricsInjectable),
|
||||
getActiveClusterEntity: di.inject(getActiveClusterEntityInjectable),
|
||||
getDetailsUrl: di.inject(getDetailsUrlInjectable),
|
||||
podStore: di.inject(podStoreInjectable),
|
||||
storageClassApi: di.inject(storageClassApiInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
@ -13,7 +13,6 @@ import { DrawerItem, DrawerTitle } from "../drawer";
|
||||
import { Badge } from "../badge";
|
||||
import { PersistentVolume, persistentVolumeClaimApi, storageClassApi } from "../../../common/k8s-api/endpoints";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import { getDetailsUrl } from "../kube-detail-params";
|
||||
import logger from "../../../common/logger";
|
||||
import { stopPropagation } from "../../../renderer/utils";
|
||||
@ -44,7 +43,6 @@ export class PersistentVolumeDetails extends React.Component<PersistentVolumeDet
|
||||
|
||||
return (
|
||||
<div className="PersistentVolumeDetails">
|
||||
<KubeObjectMeta object={volume} />
|
||||
<DrawerItem name="Capacity">
|
||||
{capacity?.storage}
|
||||
</DrawerItem>
|
||||
|
||||
@ -14,7 +14,6 @@ import { autoBind, ObservableHashSet, prevDefault } from "../../../utils";
|
||||
import { AddRemoveButtons } from "../../add-remove-buttons";
|
||||
import { DrawerTitle } from "../../drawer";
|
||||
import type { KubeObjectDetailsProps } from "../../kube-object-details";
|
||||
import { KubeObjectMeta } from "../../kube-object-meta";
|
||||
import { Table, TableCell, TableHead, TableRow } from "../../table";
|
||||
import { ClusterRoleBindingDialog } from "./dialog";
|
||||
import { clusterRoleBindingStore } from "./legacy-store";
|
||||
@ -76,8 +75,6 @@ class NonInjectedClusterRoleBindingDetails extends React.Component<ClusterRoleBi
|
||||
|
||||
return (
|
||||
<div className="ClusterRoleBindingDetails">
|
||||
<KubeObjectMeta object={clusterRoleBinding} />
|
||||
|
||||
<DrawerTitle>Reference</DrawerTitle>
|
||||
<Table>
|
||||
<TableHead>
|
||||
|
||||
@ -10,7 +10,6 @@ import React from "react";
|
||||
|
||||
import { DrawerTitle } from "../../drawer";
|
||||
import type { KubeObjectDetailsProps } from "../../kube-object-details";
|
||||
import { KubeObjectMeta } from "../../kube-object-meta";
|
||||
import type { ClusterRole } from "../../../../common/k8s-api/endpoints";
|
||||
|
||||
export interface ClusterRoleDetailsProps extends KubeObjectDetailsProps<ClusterRole> {
|
||||
@ -26,8 +25,6 @@ export class ClusterRoleDetails extends React.Component<ClusterRoleDetailsProps>
|
||||
|
||||
return (
|
||||
<div className="ClusterRoleDetails">
|
||||
<KubeObjectMeta object={clusterRole}/>
|
||||
|
||||
<DrawerTitle>Rules</DrawerTitle>
|
||||
{rules.map(({ resourceNames, apiGroups, resources, verbs }, index) => {
|
||||
return (
|
||||
|
||||
@ -13,7 +13,6 @@ import { prevDefault } from "../../../utils";
|
||||
import { AddRemoveButtons } from "../../add-remove-buttons";
|
||||
import { DrawerTitle } from "../../drawer";
|
||||
import type { KubeObjectDetailsProps } from "../../kube-object-details";
|
||||
import { KubeObjectMeta } from "../../kube-object-meta";
|
||||
import { Table, TableCell, TableHead, TableRow } from "../../table";
|
||||
import { RoleBindingDialog } from "./dialog";
|
||||
import { roleBindingStore } from "./legacy-store";
|
||||
@ -71,8 +70,6 @@ class NonInjectedRoleBindingDetails extends React.Component<RoleBindingDetailsPr
|
||||
|
||||
return (
|
||||
<div className="RoleBindingDetails">
|
||||
<KubeObjectMeta object={roleBinding} />
|
||||
|
||||
<DrawerTitle>Reference</DrawerTitle>
|
||||
<Table>
|
||||
<TableHead>
|
||||
|
||||
@ -11,7 +11,6 @@ import React from "react";
|
||||
import type { Role } from "../../../../common/k8s-api/endpoints";
|
||||
import { DrawerTitle } from "../../drawer";
|
||||
import type { KubeObjectDetailsProps } from "../../kube-object-details";
|
||||
import { KubeObjectMeta } from "../../kube-object-meta";
|
||||
|
||||
export interface RoleDetailsProps extends KubeObjectDetailsProps<Role> {
|
||||
}
|
||||
@ -26,7 +25,6 @@ export class RoleDetails extends React.Component<RoleDetailsProps> {
|
||||
|
||||
return (
|
||||
<div className="RoleDetails">
|
||||
<KubeObjectMeta object={role}/>
|
||||
<DrawerTitle>Rules</DrawerTitle>
|
||||
{rules.map(({ resourceNames, apiGroups, resources, verbs }, index) => {
|
||||
return (
|
||||
|
||||
@ -14,7 +14,6 @@ import type { Secret, ServiceAccount } from "../../../../common/k8s-api/endpoint
|
||||
import { DrawerItem, DrawerTitle } from "../../drawer";
|
||||
import { Icon } from "../../icon";
|
||||
import type { KubeObjectDetailsProps } from "../../kube-object-details";
|
||||
import { KubeObjectMeta } from "../../kube-object-meta";
|
||||
import { Spinner } from "../../spinner";
|
||||
import { ServiceAccountsSecret } from "./secret";
|
||||
import type { SecretStore } from "../../+config-secrets/store";
|
||||
@ -137,8 +136,6 @@ class NonInjectedServiceAccountsDetails extends React.Component<ServiceAccountsD
|
||||
|
||||
return (
|
||||
<div className="ServiceAccountsDetails">
|
||||
<KubeObjectMeta object={serviceAccount}/>
|
||||
|
||||
{tokens.length > 0 && (
|
||||
<DrawerItem name="Tokens" className="links">
|
||||
{this.renderSecretLinks(tokens)}
|
||||
|
||||
@ -17,7 +17,6 @@ import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { getDetailsUrl } from "../kube-detail-params";
|
||||
import type { Job } from "../../../common/k8s-api/endpoints";
|
||||
import { CronJob } from "../../../common/k8s-api/endpoints";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import logger from "../../../common/logger";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import type { SubscribeStores } from "../../kube-watch-api/kube-watch-api";
|
||||
@ -61,7 +60,6 @@ class NonInjectedCronJobDetails extends React.Component<CronJobDetailsProps & De
|
||||
|
||||
return (
|
||||
<div className="CronJobDetails">
|
||||
<KubeObjectMeta object={cronJob}/>
|
||||
<DrawerItem name="Schedule">
|
||||
{
|
||||
cronJob.isNeverRun()
|
||||
|
||||
@ -13,11 +13,9 @@ import moment from "moment";
|
||||
import { SiblingsInTabLayout } from "../layout/siblings-in-tab-layout";
|
||||
import { KubeObjectAge } from "../kube-object/age";
|
||||
import type { CronJobStore } from "./store";
|
||||
import type { JobStore } from "../+workloads-jobs/store";
|
||||
import type { EventStore } from "../+events/store";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import cronJobStoreInjectable from "./store.injectable";
|
||||
import jobStoreInjectable from "../+workloads-jobs/store.injectable";
|
||||
import eventStoreInjectable from "../+events/store.injectable";
|
||||
import { prevDefault } from "../../utils";
|
||||
import type { FilterByNamespace } from "../+namespaces/namespace-select-filter-model/filter-by-namespace.injectable";
|
||||
@ -35,20 +33,16 @@ enum columnId {
|
||||
|
||||
interface Dependencies {
|
||||
cronJobStore: CronJobStore;
|
||||
jobStore: JobStore;
|
||||
eventStore: EventStore;
|
||||
filterByNamespace: FilterByNamespace;
|
||||
}
|
||||
|
||||
@observer
|
||||
class NonInjectedCronJobs extends React.Component<Dependencies>{
|
||||
render() {
|
||||
const NonInjectedCronJobs = observer((props: Dependencies) => {
|
||||
const {
|
||||
cronJobStore,
|
||||
eventStore,
|
||||
jobStore,
|
||||
filterByNamespace,
|
||||
} = this.props;
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<SiblingsInTabLayout>
|
||||
@ -57,7 +51,7 @@ class NonInjectedCronJobs extends React.Component<Dependencies>{
|
||||
tableId="workload_cronjobs"
|
||||
className="CronJobs"
|
||||
store={cronJobStore}
|
||||
dependentStores={[jobStore, eventStore]}
|
||||
dependentStores={[eventStore]}
|
||||
sortingCallbacks={{
|
||||
[columnId.name]: cronJob => cronJob.getName(),
|
||||
[columnId.namespace]: cronJob => cronJob.getNs(),
|
||||
@ -104,15 +98,13 @@ class NonInjectedCronJobs extends React.Component<Dependencies>{
|
||||
/>
|
||||
</SiblingsInTabLayout>
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export const CronJobs = withInjectables<Dependencies>(NonInjectedCronJobs, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
cronJobStore: di.inject(cronJobStoreInjectable),
|
||||
eventStore: di.inject(eventStoreInjectable),
|
||||
jobStore: di.inject(jobStoreInjectable),
|
||||
filterByNamespace: di.inject(filterByNamespaceInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
@ -16,22 +16,16 @@ import type { DaemonSetStore } from "./store";
|
||||
import type { PodStore } from "../+workloads-pods/store";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { DaemonSet } from "../../../common/k8s-api/endpoints";
|
||||
import { ResourceMetrics, ResourceMetricsText } from "../resource-metrics";
|
||||
import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts";
|
||||
import { makeObservable, observable, reaction } from "mobx";
|
||||
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||
import logger from "../../../common/logger";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import type { SubscribeStores } from "../../kube-watch-api/kube-watch-api";
|
||||
import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable";
|
||||
import daemonSetStoreInjectable from "./store.injectable";
|
||||
import podStoreInjectable from "../+workloads-pods/store.injectable";
|
||||
import type { GetActiveClusterEntity } from "../../api/catalog/entity/get-active-cluster-entity.injectable";
|
||||
import getActiveClusterEntityInjectable from "../../api/catalog/entity/get-active-cluster-entity.injectable";
|
||||
import type { DaemonSetPodMetricData, RequestPodMetricsForDaemonSets } from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-for-daemon-sets.injectable";
|
||||
import requestPodMetricsForDaemonSetsInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-for-daemon-sets.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface DaemonSetDetailsProps extends KubeObjectDetailsProps<DaemonSet> {
|
||||
}
|
||||
@ -40,38 +34,21 @@ interface Dependencies {
|
||||
subscribeStores: SubscribeStores;
|
||||
daemonSetStore: DaemonSetStore;
|
||||
podStore: PodStore;
|
||||
getActiveClusterEntity: GetActiveClusterEntity;
|
||||
requestPodMetricsForDaemonSets: RequestPodMetricsForDaemonSets;
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
@observer
|
||||
class NonInjectedDaemonSetDetails extends React.Component<DaemonSetDetailsProps & Dependencies> {
|
||||
@observable metrics: DaemonSetPodMetricData | null = null;
|
||||
|
||||
constructor(props: DaemonSetDetailsProps & Dependencies) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
}),
|
||||
this.props.subscribeStores([
|
||||
this.props.podStore,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
loadMetrics = async () => {
|
||||
const { object: daemonSet, requestPodMetricsForDaemonSets } = this.props;
|
||||
|
||||
this.metrics = await requestPodMetricsForDaemonSets([daemonSet], daemonSet.getNs());
|
||||
};
|
||||
|
||||
render() {
|
||||
const { object: daemonSet, daemonSetStore, podStore, getActiveClusterEntity } = this.props;
|
||||
const { object: daemonSet, daemonSetStore, logger } = this.props;
|
||||
|
||||
if (!daemonSet) {
|
||||
return null;
|
||||
@ -88,21 +65,9 @@ class NonInjectedDaemonSetDetails extends React.Component<DaemonSetDetailsProps
|
||||
const images = daemonSet.getImages();
|
||||
const nodeSelector = daemonSet.getNodeSelectors();
|
||||
const childPods = daemonSetStore.getChildPods(daemonSet);
|
||||
const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.DaemonSet);
|
||||
|
||||
return (
|
||||
<div className="DaemonSetDetails">
|
||||
{!isMetricHidden && podStore.isLoaded && (
|
||||
<ResourceMetrics
|
||||
loader={this.loadMetrics}
|
||||
tabs={podMetricTabs}
|
||||
object={daemonSet}
|
||||
metrics={this.metrics}
|
||||
>
|
||||
<PodCharts/>
|
||||
</ResourceMetrics>
|
||||
)}
|
||||
<KubeObjectMeta object={daemonSet}/>
|
||||
{selectors.length > 0 && (
|
||||
<DrawerItem name="Selector" labelsOnly>
|
||||
{
|
||||
@ -132,7 +97,6 @@ class NonInjectedDaemonSetDetails extends React.Component<DaemonSetDetailsProps
|
||||
<DrawerItem name="Pod Status" className="pod-status">
|
||||
<PodDetailsStatuses pods={childPods}/>
|
||||
</DrawerItem>
|
||||
<ResourceMetricsText metrics={this.metrics}/>
|
||||
<PodDetailsList pods={childPods} owner={daemonSet}/>
|
||||
</div>
|
||||
);
|
||||
@ -147,5 +111,6 @@ export const DaemonSetDetails = withInjectables<Dependencies, DaemonSetDetailsPr
|
||||
podStore: di.inject(podStoreInjectable),
|
||||
getActiveClusterEntity: di.inject(getActiveClusterEntityInjectable),
|
||||
requestPodMetricsForDaemonSets: di.inject(requestPodMetricsForDaemonSetsInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
@ -14,7 +14,6 @@ import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||
import { SiblingsInTabLayout } from "../layout/siblings-in-tab-layout";
|
||||
import { KubeObjectAge } from "../kube-object/age";
|
||||
import type { DaemonSetStore } from "./store";
|
||||
import type { PodStore } from "../+workloads-pods/store";
|
||||
import type { EventStore } from "../+events/store";
|
||||
import { prevDefault } from "../../utils";
|
||||
import type { FilterByNamespace } from "../+namespaces/namespace-select-filter-model/filter-by-namespace.injectable";
|
||||
@ -22,7 +21,6 @@ import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import daemonSetStoreInjectable from "./store.injectable";
|
||||
import eventStoreInjectable from "../+events/store.injectable";
|
||||
import filterByNamespaceInjectable from "../+namespaces/namespace-select-filter-model/filter-by-namespace.injectable";
|
||||
import podStoreInjectable from "../+workloads-pods/store.injectable";
|
||||
|
||||
enum columnId {
|
||||
name = "name",
|
||||
@ -34,24 +32,18 @@ enum columnId {
|
||||
|
||||
interface Dependencies {
|
||||
daemonSetStore: DaemonSetStore;
|
||||
podStore: PodStore;
|
||||
eventStore: EventStore;
|
||||
filterByNamespace: FilterByNamespace;
|
||||
}
|
||||
|
||||
@observer
|
||||
class NonInjectedDaemonSets extends React.Component<Dependencies> {
|
||||
getPodsLength(daemonSet: DaemonSet) {
|
||||
return this.props.daemonSetStore.getChildPods(daemonSet).length;
|
||||
}
|
||||
|
||||
render() {
|
||||
const NonInjectedDaemonSets = observer((props: Dependencies) => {
|
||||
const {
|
||||
daemonSetStore,
|
||||
eventStore,
|
||||
filterByNamespace,
|
||||
podStore,
|
||||
} = this.props;
|
||||
} = props;
|
||||
|
||||
const getPodsLength = (daemonSet: DaemonSet) => daemonSetStore.getChildPods(daemonSet).length;
|
||||
|
||||
return (
|
||||
<SiblingsInTabLayout>
|
||||
@ -60,11 +52,11 @@ class NonInjectedDaemonSets extends React.Component<Dependencies> {
|
||||
tableId="workload_daemonsets"
|
||||
className="DaemonSets"
|
||||
store={daemonSetStore}
|
||||
dependentStores={[podStore, eventStore]} // status icon component uses event store
|
||||
dependentStores={[eventStore]} // status icon component uses event store
|
||||
sortingCallbacks={{
|
||||
[columnId.name]: daemonSet => daemonSet.getName(),
|
||||
[columnId.namespace]: daemonSet => daemonSet.getNs(),
|
||||
[columnId.pods]: daemonSet => this.getPodsLength(daemonSet),
|
||||
[columnId.pods]: daemonSet => getPodsLength(daemonSet),
|
||||
[columnId.age]: daemonSet => -daemonSet.getCreationTimestamp(),
|
||||
}}
|
||||
searchFilters={[
|
||||
@ -89,7 +81,7 @@ class NonInjectedDaemonSets extends React.Component<Dependencies> {
|
||||
>
|
||||
{daemonSet.getNs()}
|
||||
</a>,
|
||||
this.getPodsLength(daemonSet),
|
||||
getPodsLength(daemonSet),
|
||||
<KubeObjectStatusIcon key="icon" object={daemonSet} />,
|
||||
daemonSet.getNodeSelectors().map(selector => (
|
||||
<Badge
|
||||
@ -103,8 +95,7 @@ class NonInjectedDaemonSets extends React.Component<Dependencies> {
|
||||
/>
|
||||
</SiblingsInTabLayout>
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export const DaemonSets = withInjectables<Dependencies>(NonInjectedDaemonSets, {
|
||||
getProps: (di, props) => ({
|
||||
@ -112,6 +103,5 @@ export const DaemonSets = withInjectables<Dependencies>(NonInjectedDaemonSets, {
|
||||
daemonSetStore: di.inject(daemonSetStoreInjectable),
|
||||
eventStore: di.inject(eventStoreInjectable),
|
||||
filterByNamespace: di.inject(filterByNamespaceInjectable),
|
||||
podStore: di.inject(podStoreInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* 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";
|
||||
|
||||
interface Dependencies {
|
||||
metrics: IAsyncComputed<DaemonSetPodMetricData>;
|
||||
}
|
||||
|
||||
const NonInjectedDaemonSetMetricsDetailsComponent = ({
|
||||
object,
|
||||
metrics,
|
||||
}: KubeObjectDetailsProps<DaemonSet> & Dependencies) => (
|
||||
<ResourceMetrics
|
||||
tabs={podMetricTabs}
|
||||
object={object}
|
||||
metrics={metrics}
|
||||
>
|
||||
<PodCharts />
|
||||
</ResourceMetrics>
|
||||
);
|
||||
|
||||
const DaemonSetMetricsDetailsComponent = withInjectables<Dependencies, KubeObjectDetailsProps<DaemonSet>>(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;
|
||||
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import { asyncComputed } from "@ogre-tools/injectable-react";
|
||||
import { now } from "mobx-utils";
|
||||
import type { DaemonSet } from "../../../common/k8s-api/endpoints";
|
||||
import requestPodMetricsForDaemonSetsInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-for-daemon-sets.injectable";
|
||||
|
||||
const daemonSetMetricsInjectable = getInjectable({
|
||||
id: "daemon-set-metrics",
|
||||
instantiate: (di, daemonSet) => {
|
||||
const requestPodMetricsForDaemonSets = di.inject(requestPodMetricsForDaemonSetsInjectable);
|
||||
|
||||
return asyncComputed({
|
||||
getValueFromObservedPromise: () => {
|
||||
now(60 * 1000); // update every minute
|
||||
|
||||
return requestPodMetricsForDaemonSets([daemonSet], daemonSet.getNs());
|
||||
},
|
||||
});
|
||||
},
|
||||
lifecycle: lifecycleEnum.keyedSingleton({
|
||||
getInstanceKey: (di, daemonSet: DaemonSet) => daemonSet.getId(),
|
||||
}),
|
||||
});
|
||||
|
||||
export default daemonSetMetricsInjectable;
|
||||
@ -14,70 +14,40 @@ import { Deployment } from "../../../common/k8s-api/endpoints";
|
||||
import { PodDetailsTolerations } from "../+workloads-pods/pod-details-tolerations";
|
||||
import { PodDetailsAffinities } from "../+workloads-pods/pod-details-affinities";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { ResourceMetrics, ResourceMetricsText } from "../resource-metrics";
|
||||
import type { DeploymentStore } from "./store";
|
||||
import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts";
|
||||
import { makeObservable, observable, reaction } from "mobx";
|
||||
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import type { ReplicaSetStore } from "../+workloads-replicasets/store";
|
||||
import { DeploymentReplicaSets } from "./deployment-replicasets";
|
||||
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||
import logger from "../../../common/logger";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import type { SubscribeStores } from "../../kube-watch-api/kube-watch-api";
|
||||
import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable";
|
||||
import type { PodStore } from "../+workloads-pods/store";
|
||||
import podStoreInjectable from "../+workloads-pods/store.injectable";
|
||||
import replicaSetStoreInjectable from "../+workloads-replicasets/store.injectable";
|
||||
import deploymentStoreInjectable from "./store.injectable";
|
||||
import type { GetActiveClusterEntity } from "../../api/catalog/entity/get-active-cluster-entity.injectable";
|
||||
import getActiveClusterEntityInjectable from "../../api/catalog/entity/get-active-cluster-entity.injectable";
|
||||
import type { DeploymentPodMetricData, RequestPodMetricsForDeployments } from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-for-deployments.injectable";
|
||||
import requestPodMetricsForDeploymentsInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-for-deployments.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface DeploymentDetailsProps extends KubeObjectDetailsProps<Deployment> {
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
subscribeStores: SubscribeStores;
|
||||
podStore: PodStore;
|
||||
replicaSetStore: ReplicaSetStore;
|
||||
deploymentStore: DeploymentStore;
|
||||
getActiveClusterEntity: GetActiveClusterEntity;
|
||||
requestPodMetricsForDeployments: RequestPodMetricsForDeployments;
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
@observer
|
||||
class NonInjectedDeploymentDetails extends React.Component<DeploymentDetailsProps & Dependencies> {
|
||||
@observable metrics: DeploymentPodMetricData | null = null;
|
||||
|
||||
constructor(props: DeploymentDetailsProps & Dependencies) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
}),
|
||||
|
||||
this.props.subscribeStores([
|
||||
this.props.podStore,
|
||||
this.props.replicaSetStore,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
loadMetrics = async () => {
|
||||
const { object: deployment, requestPodMetricsForDeployments } = this.props;
|
||||
|
||||
this.metrics = await requestPodMetricsForDeployments([deployment], deployment.getNs());
|
||||
};
|
||||
|
||||
render() {
|
||||
const { object: deployment, podStore, replicaSetStore, deploymentStore, getActiveClusterEntity } = this.props;
|
||||
const { object: deployment, replicaSetStore, deploymentStore, logger } = this.props;
|
||||
|
||||
if (!deployment) {
|
||||
return null;
|
||||
@ -94,21 +64,9 @@ class NonInjectedDeploymentDetails extends React.Component<DeploymentDetailsProp
|
||||
const selectors = deployment.getSelectors();
|
||||
const childPods = deploymentStore.getChildPods(deployment);
|
||||
const replicaSets = replicaSetStore.getReplicaSetsByOwner(deployment);
|
||||
const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Deployment);
|
||||
|
||||
return (
|
||||
<div className="DeploymentDetails">
|
||||
{!isMetricHidden && podStore.isLoaded && (
|
||||
<ResourceMetrics
|
||||
loader={this.loadMetrics}
|
||||
tabs={podMetricTabs}
|
||||
object={deployment}
|
||||
metrics={this.metrics}
|
||||
>
|
||||
<PodCharts/>
|
||||
</ResourceMetrics>
|
||||
)}
|
||||
<KubeObjectMeta object={deployment}/>
|
||||
<DrawerItem name="Replicas">
|
||||
{`${spec.replicas} desired, ${status?.updatedReplicas ?? 0} updated, `}
|
||||
{`${status?.replicas ?? 0} total, ${status?.availableReplicas ?? 0} available, `}
|
||||
@ -159,7 +117,6 @@ class NonInjectedDeploymentDetails extends React.Component<DeploymentDetailsProp
|
||||
</DrawerItem>
|
||||
<PodDetailsTolerations workload={deployment}/>
|
||||
<PodDetailsAffinities workload={deployment}/>
|
||||
<ResourceMetricsText metrics={this.metrics}/>
|
||||
<DeploymentReplicaSets replicaSets={replicaSets}/>
|
||||
<PodDetailsList pods={childPods} owner={deployment}/>
|
||||
</div>
|
||||
@ -171,11 +128,9 @@ export const DeploymentDetails = withInjectables<Dependencies, DeploymentDetails
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
subscribeStores: di.inject(subscribeStoresInjectable),
|
||||
podStore: di.inject(podStoreInjectable),
|
||||
replicaSetStore: di.inject(replicaSetStoreInjectable),
|
||||
deploymentStore: di.inject(deploymentStoreInjectable),
|
||||
getActiveClusterEntity: di.inject(getActiveClusterEntityInjectable),
|
||||
requestPodMetricsForDeployments: di.inject(requestPodMetricsForDeploymentsInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@ -8,7 +8,6 @@ import "./deployment-replicasets.scss";
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import type { ReplicaSet } from "../../../common/k8s-api/endpoints";
|
||||
import type { KubeObjectMenuProps } from "../kube-object-menu";
|
||||
import { KubeObjectMenu } from "../kube-object-menu";
|
||||
import { Spinner } from "../spinner";
|
||||
import { prevDefault, stopPropagation } from "../../utils";
|
||||
@ -30,6 +29,11 @@ enum sortBy {
|
||||
age = "age",
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
replicaSetStore: ReplicaSetStore;
|
||||
showDetails: ShowDetails;
|
||||
}
|
||||
|
||||
export interface DeploymentReplicaSetsProps {
|
||||
replicaSets: ReplicaSet[];
|
||||
}
|
||||
@ -96,7 +100,7 @@ class NonInjectedDeploymentReplicaSets extends React.Component<DeploymentReplica
|
||||
<TableCell className="pods">{this.getPodsLength(replica)}</TableCell>
|
||||
<TableCell className="age"><KubeObjectAge key="age" object={replica} /></TableCell>
|
||||
<TableCell className="actions" onClick={stopPropagation}>
|
||||
<ReplicaSetMenu object={replica} />
|
||||
<KubeObjectMenu object={replica} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))
|
||||
@ -114,9 +118,3 @@ export const DeploymentReplicaSets = withInjectables<Dependencies, DeploymentRep
|
||||
showDetails: di.inject(showDetailsInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
export function ReplicaSetMenu(props: KubeObjectMenuProps<ReplicaSet>) {
|
||||
return (
|
||||
<KubeObjectMenu {...props}/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* 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";
|
||||
|
||||
interface Dependencies {
|
||||
metrics: IAsyncComputed<DeploymentPodMetricData>;
|
||||
}
|
||||
|
||||
const NonInjectedDeploymentMetricsDetailsComponent = ({
|
||||
object,
|
||||
metrics,
|
||||
}: KubeObjectDetailsProps<Deployment> & Dependencies) => (
|
||||
<ResourceMetrics
|
||||
tabs={podMetricTabs}
|
||||
object={object}
|
||||
metrics={metrics}
|
||||
>
|
||||
<PodCharts />
|
||||
</ResourceMetrics>
|
||||
);
|
||||
|
||||
const DeploymentMetricsDetailsComponent = withInjectables<Dependencies, KubeObjectDetailsProps<Deployment>>(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;
|
||||
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import { asyncComputed } from "@ogre-tools/injectable-react";
|
||||
import { now } from "mobx-utils";
|
||||
import type { Deployment } from "../../../common/k8s-api/endpoints";
|
||||
import requestPodMetricsForDeploymentsInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-for-deployments.injectable";
|
||||
|
||||
const deploymentMetricsInjectable = getInjectable({
|
||||
id: "deployment-metrics",
|
||||
instantiate: (di, deployment) => {
|
||||
const requestPodMetricsForDeployments = di.inject(requestPodMetricsForDeploymentsInjectable);
|
||||
|
||||
return asyncComputed({
|
||||
getValueFromObservedPromise: () => {
|
||||
now(60 * 1000);
|
||||
|
||||
return requestPodMetricsForDeployments([deployment], deployment.getNs());
|
||||
},
|
||||
});
|
||||
},
|
||||
lifecycle: lifecycleEnum.keyedSingleton({
|
||||
getInstanceKey: (di, deployment: Deployment) => deployment.getId(),
|
||||
}),
|
||||
});
|
||||
|
||||
export default deploymentMetricsInjectable;
|
||||
@ -17,22 +17,14 @@ import type { JobStore } from "./store";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { Job } from "../../../common/k8s-api/endpoints";
|
||||
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import { makeObservable, observable, reaction } from "mobx";
|
||||
import { podMetricTabs, PodCharts } from "../+workloads-pods/pod-charts";
|
||||
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||
import { ResourceMetrics } from "../resource-metrics";
|
||||
import logger from "../../../common/logger";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import type { SubscribeStores } from "../../kube-watch-api/kube-watch-api";
|
||||
import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable";
|
||||
import type { PodStore } from "../+workloads-pods/store";
|
||||
import podStoreInjectable from "../+workloads-pods/store.injectable";
|
||||
import jobStoreInjectable from "./store.injectable";
|
||||
import type { GetActiveClusterEntity } from "../../api/catalog/entity/get-active-cluster-entity.injectable";
|
||||
import getActiveClusterEntityInjectable from "../../api/catalog/entity/get-active-cluster-entity.injectable";
|
||||
import type { JobPodMetricData, RequestPodMetricsForJobs } from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-for-jobs.injectable";
|
||||
import requestPodMetricsForJobsInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-for-jobs.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface JobDetailsProps extends KubeObjectDetailsProps<Job> {
|
||||
}
|
||||
@ -41,38 +33,21 @@ interface Dependencies {
|
||||
subscribeStores: SubscribeStores;
|
||||
podStore: PodStore;
|
||||
jobStore: JobStore;
|
||||
getActiveClusterEntity: GetActiveClusterEntity;
|
||||
requestPodMetricsForJobs: RequestPodMetricsForJobs;
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
@observer
|
||||
class NonInjectedJobDetails extends React.Component<JobDetailsProps & Dependencies> {
|
||||
@observable metrics: JobPodMetricData | null = null;
|
||||
|
||||
constructor(props: JobDetailsProps & Dependencies) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
}),
|
||||
this.props.subscribeStores([
|
||||
this.props.podStore,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
loadMetrics = async () => {
|
||||
const { object: job, requestPodMetricsForJobs } = this.props;
|
||||
|
||||
this.metrics = await requestPodMetricsForJobs([job], job.getNs(), "");
|
||||
};
|
||||
|
||||
render() {
|
||||
const { object: job, jobStore, getActiveClusterEntity } = this.props;
|
||||
const { object: job, jobStore, logger } = this.props;
|
||||
|
||||
if (!job) {
|
||||
return null;
|
||||
@ -89,21 +64,9 @@ class NonInjectedJobDetails extends React.Component<JobDetailsProps & Dependenci
|
||||
const images = job.getImages();
|
||||
const childPods = jobStore.getChildPods(job);
|
||||
const condition = job.getCondition();
|
||||
const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Job);
|
||||
|
||||
return (
|
||||
<div className="JobDetails">
|
||||
{!isMetricHidden && (
|
||||
<ResourceMetrics
|
||||
loader={this.loadMetrics}
|
||||
tabs={podMetricTabs}
|
||||
object={job}
|
||||
metrics={this.metrics}
|
||||
>
|
||||
<PodCharts />
|
||||
</ResourceMetrics>
|
||||
)}
|
||||
<KubeObjectMeta object={job}/>
|
||||
<DrawerItem name="Selector" labelsOnly>
|
||||
{
|
||||
Object.keys(selectors).map(label => <Badge key={label} label={label}/>)
|
||||
@ -161,8 +124,7 @@ export const JobDetails = withInjectables<Dependencies, JobDetailsProps>(NonInje
|
||||
subscribeStores: di.inject(subscribeStoresInjectable),
|
||||
podStore: di.inject(podStoreInjectable),
|
||||
jobStore: di.inject(jobStoreInjectable),
|
||||
getActiveClusterEntity: di.inject(getActiveClusterEntityInjectable),
|
||||
requestPodMetricsForJobs: di.inject(requestPodMetricsForJobsInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@ -35,14 +35,12 @@ interface Dependencies {
|
||||
filterByNamespace: FilterByNamespace;
|
||||
}
|
||||
|
||||
@observer
|
||||
class NonInjectedJobs extends React.Component<Dependencies> {
|
||||
render() {
|
||||
const NonInjectedJobs = observer((props: Dependencies) => {
|
||||
const {
|
||||
eventStore,
|
||||
filterByNamespace,
|
||||
jobStore,
|
||||
} = this.props;
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<SiblingsInTabLayout>
|
||||
@ -94,8 +92,7 @@ class NonInjectedJobs extends React.Component<Dependencies> {
|
||||
/>
|
||||
</SiblingsInTabLayout>
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export const Jobs = withInjectables<Dependencies>(NonInjectedJobs, {
|
||||
getProps: (di, props) => ({
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* 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";
|
||||
|
||||
interface Dependencies {
|
||||
metrics: IAsyncComputed<JobPodMetricData>;
|
||||
}
|
||||
|
||||
const NonInjectedJobMetricsDetailsComponent = ({
|
||||
object,
|
||||
metrics,
|
||||
}: KubeObjectDetailsProps<Job> & Dependencies) => (
|
||||
<ResourceMetrics
|
||||
tabs={podMetricTabs}
|
||||
object={object}
|
||||
metrics={metrics}
|
||||
>
|
||||
<PodCharts />
|
||||
</ResourceMetrics>
|
||||
);
|
||||
|
||||
const JobMetricsDetailsComponent = withInjectables<Dependencies, KubeObjectDetailsProps<Job>>(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;
|
||||
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import { asyncComputed } from "@ogre-tools/injectable-react";
|
||||
import { now } from "mobx-utils";
|
||||
import type { Job } from "../../../common/k8s-api/endpoints";
|
||||
import requestPodMetricsForJobsInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-for-jobs.injectable";
|
||||
|
||||
const jobMetricsInjectable = getInjectable({
|
||||
id: "job-metrics",
|
||||
instantiate: (di, job) => {
|
||||
const requestPodMetricsForJobs = di.inject(requestPodMetricsForJobsInjectable);
|
||||
|
||||
return asyncComputed({
|
||||
getValueFromObservedPromise: () => {
|
||||
now(60 * 1000);
|
||||
|
||||
return requestPodMetricsForJobs([job], job.getNs());
|
||||
},
|
||||
});
|
||||
},
|
||||
lifecycle: lifecycleEnum.keyedSingleton({
|
||||
getInstanceKey: (di, job: Job) => job.getId(),
|
||||
}),
|
||||
});
|
||||
|
||||
export default jobMetricsInjectable;
|
||||
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import { asyncComputed } from "@ogre-tools/injectable-react";
|
||||
import { now } from "mobx-utils";
|
||||
import type { Pod } from "../../../common/k8s-api/endpoints";
|
||||
import requestPodMetricsInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics.injectable";
|
||||
|
||||
const podContainerMetricsInjectable = getInjectable({
|
||||
id: "pod-container-metrics",
|
||||
instantiate: (di, pod) => {
|
||||
const requestPodMetrics = di.inject(requestPodMetricsInjectable);
|
||||
|
||||
return asyncComputed({
|
||||
getValueFromObservedPromise: () => {
|
||||
now(60 * 1000);
|
||||
|
||||
return requestPodMetrics([pod], pod.getNs(), "container, namespace");
|
||||
},
|
||||
});
|
||||
},
|
||||
lifecycle: lifecycleEnum.keyedSingleton({
|
||||
getInstanceKey: (di, pod: Pod) => pod.getId(),
|
||||
}),
|
||||
});
|
||||
|
||||
export default podContainerMetricsInjectable;
|
||||
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* 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";
|
||||
|
||||
interface Dependencies {
|
||||
metrics: IAsyncComputed<PodMetricData>;
|
||||
}
|
||||
|
||||
const NonInjectedPodMetricsDetailsComponent = ({
|
||||
object,
|
||||
metrics,
|
||||
}: KubeObjectDetailsProps<Pod> & Dependencies) => (
|
||||
<ResourceMetrics
|
||||
tabs={podMetricTabs}
|
||||
object={object}
|
||||
metrics={metrics}
|
||||
>
|
||||
<PodCharts />
|
||||
</ResourceMetrics>
|
||||
);
|
||||
|
||||
const PodMetricsDetailsComponent = withInjectables<Dependencies, KubeObjectDetailsProps<Pod>>(NonInjectedPodMetricsDetailsComponent, {
|
||||
getProps: (di, props) => ({
|
||||
metrics: di.inject(podMetricsInjectable, props.object),
|
||||
...props,
|
||||
}),
|
||||
});
|
||||
|
||||
const podMetricsDetailsComponentInjectable = getInjectable({
|
||||
id: "pod-metrics-details-container",
|
||||
instantiate: (di) => ({
|
||||
Component: PodMetricsDetailsComponent,
|
||||
enabled: di.inject(metricsDetailsComponentEnabledInjectable, ClusterMetricsResourceType.Pod),
|
||||
orderNumber: -1,
|
||||
}),
|
||||
injectionToken: kubeObjectDetailItemInjectionToken,
|
||||
});
|
||||
|
||||
export default podMetricsDetailsComponentInjectable;
|
||||
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import { asyncComputed } from "@ogre-tools/injectable-react";
|
||||
import { now } from "mobx-utils";
|
||||
import type { Pod } from "../../../common/k8s-api/endpoints";
|
||||
import requestPodMetricsInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics.injectable";
|
||||
|
||||
const podMetricsInjectable = getInjectable({
|
||||
id: "pod-metrics",
|
||||
instantiate: (di, pod) => {
|
||||
const requestPodMetrics = di.inject(requestPodMetricsInjectable);
|
||||
|
||||
return asyncComputed({
|
||||
getValueFromObservedPromise: () => {
|
||||
now(60 * 1000);
|
||||
|
||||
return requestPodMetrics([pod], pod.getNs());
|
||||
},
|
||||
});
|
||||
},
|
||||
lifecycle: lifecycleEnum.keyedSingleton({
|
||||
getInstanceKey: (di, pod: Pod) => pod.getId(),
|
||||
}),
|
||||
});
|
||||
|
||||
export default podMetricsInjectable;
|
||||
@ -7,9 +7,8 @@ import "./pod-details.scss";
|
||||
|
||||
import React from "react";
|
||||
import kebabCase from "lodash/kebabCase";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { observable, reaction, makeObservable } from "mobx";
|
||||
import { Pod } from "../../../common/k8s-api/endpoints";
|
||||
import type { NodeApi, PriorityClassApi, RuntimeClassApi, ServiceAccountApi } from "../../../common/k8s-api/endpoints";
|
||||
import { DrawerItem, DrawerTitle } from "../drawer";
|
||||
@ -19,67 +18,39 @@ import { PodDetailsContainer } from "./pod-details-container";
|
||||
import { PodDetailsAffinities } from "./pod-details-affinities";
|
||||
import { PodDetailsTolerations } from "./pod-details-tolerations";
|
||||
import { PodDetailsSecrets } from "./pod-details-secrets";
|
||||
import { ResourceMetrics } from "../resource-metrics";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { getItemMetrics } from "../../../common/k8s-api/endpoints/metrics.api";
|
||||
import { PodCharts, podMetricTabs } from "./pod-charts";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||
import logger from "../../../common/logger";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import { PodVolumes } from "./details/volumes/view";
|
||||
import type { PodMetricData, RequestPodMetrics } from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics.injectable";
|
||||
import type { IAsyncComputed } from "@ogre-tools/injectable-react";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import requestPodMetricsInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics.injectable";
|
||||
import type { GetActiveClusterEntity } from "../../api/catalog/entity/get-active-cluster-entity.injectable";
|
||||
import type { GetDetailsUrl } from "../kube-detail-params/get-details-url.injectable";
|
||||
import getActiveClusterEntityInjectable from "../../api/catalog/entity/get-active-cluster-entity.injectable";
|
||||
import getDetailsUrlInjectable from "../kube-detail-params/get-details-url.injectable";
|
||||
import nodeApiInjectable from "../../../common/k8s-api/endpoints/node.api.injectable";
|
||||
import runtimeClassApiInjectable from "../../../common/k8s-api/endpoints/runtime-class.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 loggerInjectable from "../../../common/logger.injectable";
|
||||
import type { PodMetricData } from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics.injectable";
|
||||
import podContainerMetricsInjectable from "./container-metrics.injectable";
|
||||
|
||||
export interface PodDetailsProps extends KubeObjectDetailsProps<Pod> {
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
requestPodMetrics: RequestPodMetrics;
|
||||
getActiveClusterEntity: GetActiveClusterEntity;
|
||||
getDetailsUrl: GetDetailsUrl;
|
||||
nodeApi: NodeApi;
|
||||
priorityClassApi: PriorityClassApi;
|
||||
runtimeClassApi: RuntimeClassApi;
|
||||
serviceAccountApi: ServiceAccountApi;
|
||||
logger: Logger;
|
||||
containerMetrics: IAsyncComputed<PodMetricData>;
|
||||
}
|
||||
|
||||
@observer
|
||||
class NonInjectedPodDetails extends React.Component<PodDetailsProps & Dependencies> {
|
||||
@observable metrics: PodMetricData | null = null;
|
||||
@observable containerMetrics: PodMetricData | null = null;
|
||||
|
||||
constructor(props: PodDetailsProps & Dependencies) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
this.containerMetrics = null;
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
loadMetrics = async () => {
|
||||
const { object: pod, requestPodMetrics } = this.props;
|
||||
|
||||
this.metrics = await requestPodMetrics([pod], pod.getNs());
|
||||
this.containerMetrics = await requestPodMetrics([pod], pod.getNs(), "container, namespace");
|
||||
};
|
||||
|
||||
render() {
|
||||
const { object: pod, getActiveClusterEntity, getDetailsUrl, nodeApi } = this.props;
|
||||
const { object: pod, getDetailsUrl, nodeApi, logger, containerMetrics } = this.props;
|
||||
|
||||
if (!pod) {
|
||||
return null;
|
||||
@ -96,7 +67,6 @@ class NonInjectedPodDetails extends React.Component<PodDetailsProps & Dependenci
|
||||
const podIPs = pod.getIPs();
|
||||
const { nodeName } = spec ?? {};
|
||||
const nodeSelector = pod.getNodeSelectors();
|
||||
const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Pod);
|
||||
const initContainers = pod.getInitContainers();
|
||||
const containers = pod.getContainers();
|
||||
|
||||
@ -105,39 +75,26 @@ class NonInjectedPodDetails extends React.Component<PodDetailsProps & Dependenci
|
||||
const runtimeClassName = pod.getRuntimeClassName();
|
||||
const serviceAccountName = pod.getServiceAccountName();
|
||||
|
||||
const priorityClassDetailsUrl = getDetailsUrl(this.props.priorityClassApi.getUrl({
|
||||
const priorityClassDetailsUrl = getDetailsUrl(this.props.priorityClassApi.formatUrlForNotListing({
|
||||
name: priorityClassName,
|
||||
}));
|
||||
const runtimeClassDetailsUrl = getDetailsUrl(this.props.runtimeClassApi.getUrl({
|
||||
const runtimeClassDetailsUrl = getDetailsUrl(this.props.runtimeClassApi.formatUrlForNotListing({
|
||||
name: runtimeClassName,
|
||||
}));
|
||||
const serviceAccountDetailsUrl = getDetailsUrl(this.props.serviceAccountApi.getUrl({
|
||||
const serviceAccountDetailsUrl = getDetailsUrl(this.props.serviceAccountApi.formatUrlForNotListing({
|
||||
name: serviceAccountName,
|
||||
namespace,
|
||||
}));
|
||||
|
||||
return (
|
||||
<div className="PodDetails">
|
||||
{!isMetricHidden && (
|
||||
<ResourceMetrics
|
||||
loader={this.loadMetrics}
|
||||
tabs={podMetricTabs}
|
||||
object={pod}
|
||||
metrics={this.metrics}
|
||||
>
|
||||
<PodCharts />
|
||||
</ResourceMetrics>
|
||||
)}
|
||||
|
||||
<KubeObjectMeta object={pod} />
|
||||
|
||||
<DrawerItem name="Status">
|
||||
<span className={cssNames("status", kebabCase(pod.getStatusMessage()))}>
|
||||
{pod.getStatusMessage()}
|
||||
</span>
|
||||
</DrawerItem>
|
||||
<DrawerItem name="Node" hidden={!nodeName}>
|
||||
<Link to={getDetailsUrl(nodeApi.getUrl({ name: nodeName }))}>
|
||||
<Link to={getDetailsUrl(nodeApi.formatUrlForNotListing({ name: nodeName }))}>
|
||||
{nodeName}
|
||||
</Link>
|
||||
</DrawerItem>
|
||||
@ -230,7 +187,7 @@ class NonInjectedPodDetails extends React.Component<PodDetailsProps & Dependenci
|
||||
key={container.name}
|
||||
pod={pod}
|
||||
container={container}
|
||||
metrics={getItemMetrics(toJS(this.containerMetrics), container.name)}
|
||||
metrics={getItemMetrics(toJS(containerMetrics.value.get()), container.name)}
|
||||
/>
|
||||
))}
|
||||
|
||||
@ -243,12 +200,12 @@ class NonInjectedPodDetails extends React.Component<PodDetailsProps & Dependenci
|
||||
export const PodDetails = withInjectables<Dependencies, PodDetailsProps>(NonInjectedPodDetails, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
requestPodMetrics: di.inject(requestPodMetricsInjectable),
|
||||
getActiveClusterEntity: di.inject(getActiveClusterEntityInjectable),
|
||||
getDetailsUrl: di.inject(getDetailsUrlInjectable),
|
||||
nodeApi: di.inject(nodeApiInjectable),
|
||||
priorityClassApi: di.inject(priorityClassApiInjectable),
|
||||
runtimeClassApi: di.inject(runtimeClassApiInjectable),
|
||||
serviceAccountApi: di.inject(serviceAccountApiInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
containerMetrics: di.inject(podContainerMetricsInjectable, props.object),
|
||||
}),
|
||||
});
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* 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";
|
||||
|
||||
interface Dependencies {
|
||||
metrics: IAsyncComputed<ReplicaSetPodMetricData>;
|
||||
}
|
||||
|
||||
const NonInjectedReplicaSetMetricsDetailsComponent = ({
|
||||
object,
|
||||
metrics,
|
||||
}: KubeObjectDetailsProps<ReplicaSet> & Dependencies) => (
|
||||
<ResourceMetrics
|
||||
tabs={podMetricTabs}
|
||||
object={object}
|
||||
metrics={metrics}
|
||||
>
|
||||
<PodCharts />
|
||||
</ResourceMetrics>
|
||||
);
|
||||
|
||||
const ReplicaSetMetricsDetailsComponent = withInjectables<Dependencies, KubeObjectDetailsProps<ReplicaSet>>(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;
|
||||
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import { asyncComputed } from "@ogre-tools/injectable-react";
|
||||
import { now } from "mobx-utils";
|
||||
import type { ReplicaSet } from "../../../common/k8s-api/endpoints";
|
||||
import requestPodMetricsForReplicaSetsInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-for-replica-sets.injectable";
|
||||
|
||||
const replicaSetMetricsInjectable = getInjectable({
|
||||
id: "replica-set-metrics",
|
||||
instantiate: (di, replicaSet) => {
|
||||
const requestPodMetricsForReplicaSets = di.inject(requestPodMetricsForReplicaSetsInjectable);
|
||||
|
||||
return asyncComputed({
|
||||
getValueFromObservedPromise: async () => {
|
||||
now(60 * 1000); // update every minute
|
||||
|
||||
return requestPodMetricsForReplicaSets([replicaSet], replicaSet.getNs());
|
||||
},
|
||||
});
|
||||
},
|
||||
lifecycle: lifecycleEnum.keyedSingleton({
|
||||
getInstanceKey: (di, replicaSet: ReplicaSet) => replicaSet.getId(),
|
||||
}),
|
||||
});
|
||||
|
||||
export default replicaSetMetricsInjectable;
|
||||
@ -5,7 +5,6 @@
|
||||
|
||||
import "./replicaset-details.scss";
|
||||
import React from "react";
|
||||
import { makeObservable, observable, reaction } from "mobx";
|
||||
import { DrawerItem } from "../drawer";
|
||||
import { Badge } from "../badge";
|
||||
import { PodDetailsStatuses } from "../+workloads-pods/pod-details-statuses";
|
||||
@ -14,12 +13,8 @@ import { PodDetailsAffinities } from "../+workloads-pods/pod-details-affinities"
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { ReplicaSet } from "../../../common/k8s-api/endpoints";
|
||||
import { ResourceMetrics, ResourceMetricsText } from "../resource-metrics";
|
||||
import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts";
|
||||
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||
import logger from "../../../common/logger";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import type { SubscribeStores } from "../../kube-watch-api/kube-watch-api";
|
||||
import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable";
|
||||
@ -27,10 +22,7 @@ import type { PodStore } from "../+workloads-pods/store";
|
||||
import podStoreInjectable from "../+workloads-pods/store.injectable";
|
||||
import type { ReplicaSetStore } from "./store";
|
||||
import replicaSetStoreInjectable from "./store.injectable";
|
||||
import type { GetActiveClusterEntity } from "../../api/catalog/entity/get-active-cluster-entity.injectable";
|
||||
import getActiveClusterEntityInjectable from "../../api/catalog/entity/get-active-cluster-entity.injectable";
|
||||
import type { ReplicaSetPodMetricData, RequestPodMetricsForReplicaSets } from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-for-replica-sets.injectable";
|
||||
import requestPodMetricsForReplicaSetsInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-for-replica-sets.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface ReplicaSetDetailsProps extends KubeObjectDetailsProps<ReplicaSet> {
|
||||
}
|
||||
@ -39,39 +31,20 @@ interface Dependencies {
|
||||
subscribeStores: SubscribeStores;
|
||||
podStore: PodStore;
|
||||
replicaSetStore: ReplicaSetStore;
|
||||
getActiveClusterEntity: GetActiveClusterEntity;
|
||||
requestPodMetricsForReplicaSets: RequestPodMetricsForReplicaSets;
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
@observer
|
||||
class NonInjectedReplicaSetDetails extends React.Component<ReplicaSetDetailsProps & Dependencies> {
|
||||
@observable metrics: ReplicaSetPodMetricData | null = null;
|
||||
|
||||
constructor(props: ReplicaSetDetailsProps & Dependencies) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
}),
|
||||
|
||||
this.props.subscribeStores([
|
||||
this.props.podStore,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
loadMetrics = async () => {
|
||||
const { object: replicaSet, requestPodMetricsForReplicaSets } = this.props;
|
||||
|
||||
this.metrics = await requestPodMetricsForReplicaSets([replicaSet], replicaSet.getNs());
|
||||
};
|
||||
|
||||
render() {
|
||||
const { object: replicaSet, podStore, replicaSetStore, getActiveClusterEntity } = this.props;
|
||||
const { object: replicaSet, replicaSetStore, logger } = this.props;
|
||||
|
||||
if (!replicaSet) {
|
||||
return null;
|
||||
@ -88,21 +61,9 @@ class NonInjectedReplicaSetDetails extends React.Component<ReplicaSetDetailsProp
|
||||
const nodeSelector = replicaSet.getNodeSelectors();
|
||||
const images = replicaSet.getImages();
|
||||
const childPods = replicaSetStore.getChildPods(replicaSet);
|
||||
const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.ReplicaSet);
|
||||
|
||||
return (
|
||||
<div className="ReplicaSetDetails">
|
||||
{!isMetricHidden && podStore.isLoaded && (
|
||||
<ResourceMetrics
|
||||
loader={this.loadMetrics}
|
||||
tabs={podMetricTabs}
|
||||
object={replicaSet}
|
||||
metrics={this.metrics}
|
||||
>
|
||||
<PodCharts/>
|
||||
</ResourceMetrics>
|
||||
)}
|
||||
<KubeObjectMeta object={replicaSet}/>
|
||||
{selectors.length > 0 && (
|
||||
<DrawerItem name="Selector" labelsOnly>
|
||||
{
|
||||
@ -132,7 +93,6 @@ class NonInjectedReplicaSetDetails extends React.Component<ReplicaSetDetailsProp
|
||||
<DrawerItem name="Pod Status" className="pod-status">
|
||||
<PodDetailsStatuses pods={childPods}/>
|
||||
</DrawerItem>
|
||||
<ResourceMetricsText metrics={this.metrics}/>
|
||||
<PodDetailsList pods={childPods} owner={replicaSet}/>
|
||||
</div>
|
||||
);
|
||||
@ -145,7 +105,6 @@ export const ReplicaSetDetails = withInjectables<Dependencies, ReplicaSetDetails
|
||||
subscribeStores: di.inject(subscribeStoresInjectable),
|
||||
podStore: di.inject(podStoreInjectable),
|
||||
replicaSetStore: di.inject(replicaSetStoreInjectable),
|
||||
getActiveClusterEntity: di.inject(getActiveClusterEntityInjectable),
|
||||
requestPodMetricsForReplicaSets: di.inject(requestPodMetricsForReplicaSetsInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
@ -35,14 +35,12 @@ interface Dependencies {
|
||||
filterByNamespace: FilterByNamespace;
|
||||
}
|
||||
|
||||
@observer
|
||||
class NonInjectedReplicaSets extends React.Component<Dependencies> {
|
||||
render() {
|
||||
const NonInjectedReplicaSets = observer((props: Dependencies) => {
|
||||
const {
|
||||
eventStore,
|
||||
filterByNamespace,
|
||||
replicaSetStore,
|
||||
} = this.props;
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<SiblingsInTabLayout>
|
||||
@ -91,8 +89,7 @@ class NonInjectedReplicaSets extends React.Component<Dependencies> {
|
||||
/>
|
||||
</SiblingsInTabLayout>
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export const ReplicaSets = withInjectables<Dependencies>(NonInjectedReplicaSets, {
|
||||
getProps: (di, props) => ({
|
||||
|
||||
@ -9,12 +9,12 @@ import { PodStatusPhase } from "../../../common/k8s-api/endpoints/pod.api";
|
||||
import type { KubeObjectStoreOptions } from "../../../common/k8s-api/kube-object.store";
|
||||
import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store";
|
||||
|
||||
export interface ReplicaSetStoreDependencies {
|
||||
interface Dependencies {
|
||||
getPodsByOwnerId: GetPodsByOwnerId;
|
||||
}
|
||||
|
||||
export class ReplicaSetStore extends KubeObjectStore<ReplicaSet, ReplicaSetApi> {
|
||||
constructor(protected readonly dependencies: ReplicaSetStoreDependencies, api: ReplicaSetApi, opts?: KubeObjectStoreOptions) {
|
||||
constructor(protected readonly dependencies: Dependencies, api: ReplicaSetApi, opts?: KubeObjectStoreOptions) {
|
||||
super(api, opts);
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* 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";
|
||||
|
||||
interface Dependencies {
|
||||
metrics: IAsyncComputed<StatefulSetPodMetricData>;
|
||||
}
|
||||
|
||||
const NonInjectedStatefulSetMetricsDetailsComponent = ({
|
||||
object,
|
||||
metrics,
|
||||
}: KubeObjectDetailsProps<StatefulSet> & Dependencies) => (
|
||||
<ResourceMetrics
|
||||
tabs={podMetricTabs}
|
||||
object={object}
|
||||
metrics={metrics}
|
||||
>
|
||||
<PodCharts />
|
||||
</ResourceMetrics>
|
||||
);
|
||||
|
||||
const StatefulSetMetricsDetailsComponent = withInjectables<Dependencies, KubeObjectDetailsProps<StatefulSet>>(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;
|
||||
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import { asyncComputed } from "@ogre-tools/injectable-react";
|
||||
import { now } from "mobx-utils";
|
||||
import type { StatefulSet } from "../../../common/k8s-api/endpoints";
|
||||
import requestPodMetricsForStatefulSetsInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-for-stateful-sets.injectable";
|
||||
|
||||
const statefulSetMetricsInjectable = getInjectable({
|
||||
id: "stateful-set-metrics",
|
||||
instantiate: (di, statefulSet) => {
|
||||
const requestPodMetricsForStatefulSets = di.inject(requestPodMetricsForStatefulSetsInjectable);
|
||||
|
||||
return asyncComputed({
|
||||
getValueFromObservedPromise: async () => {
|
||||
now(60 * 1000);
|
||||
|
||||
return requestPodMetricsForStatefulSets([statefulSet], statefulSet.getNs());
|
||||
},
|
||||
});
|
||||
},
|
||||
lifecycle: lifecycleEnum.keyedSingleton({
|
||||
getInstanceKey: (di, statefulSet: StatefulSet) => statefulSet.getId(),
|
||||
}),
|
||||
});
|
||||
|
||||
export default statefulSetMetricsInjectable;
|
||||
@ -7,7 +7,6 @@ import "./statefulset-details.scss";
|
||||
|
||||
import React from "react";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { makeObservable, observable, reaction } from "mobx";
|
||||
import { Badge } from "../badge";
|
||||
import { DrawerItem } from "../drawer";
|
||||
import { PodDetailsStatuses } from "../+workloads-pods/pod-details-statuses";
|
||||
@ -16,22 +15,15 @@ import { PodDetailsAffinities } from "../+workloads-pods/pod-details-affinities"
|
||||
import type { StatefulSetStore } from "./store";
|
||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||
import { StatefulSet } from "../../../common/k8s-api/endpoints";
|
||||
import { ResourceMetrics, ResourceMetricsText } from "../resource-metrics";
|
||||
import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts";
|
||||
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||
import logger from "../../../common/logger";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import type { SubscribeStores } from "../../kube-watch-api/kube-watch-api";
|
||||
import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable";
|
||||
import type { PodStore } from "../+workloads-pods/store";
|
||||
import podStoreInjectable from "../+workloads-pods/store.injectable";
|
||||
import statefulSetStoreInjectable from "./store.injectable";
|
||||
import type { GetActiveClusterEntity } from "../../api/catalog/entity/get-active-cluster-entity.injectable";
|
||||
import getActiveClusterEntityInjectable from "../../api/catalog/entity/get-active-cluster-entity.injectable";
|
||||
import type { RequestPodMetricsForStatefulSets, StatefulSetPodMetricData } from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-for-stateful-sets.injectable";
|
||||
import requestPodMetricsForStatefulSetsInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-for-stateful-sets.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
|
||||
export interface StatefulSetDetailsProps extends KubeObjectDetailsProps<StatefulSet> {
|
||||
}
|
||||
@ -40,39 +32,21 @@ interface Dependencies {
|
||||
subscribeStores: SubscribeStores;
|
||||
podStore: PodStore;
|
||||
statefulSetStore: StatefulSetStore;
|
||||
getActiveClusterEntity: GetActiveClusterEntity;
|
||||
requestPodMetricsForStatefulSets: RequestPodMetricsForStatefulSets;
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
@observer
|
||||
class NonInjectedStatefulSetDetails extends React.Component<StatefulSetDetailsProps & Dependencies> {
|
||||
@observable metrics: StatefulSetPodMetricData | null = null;
|
||||
|
||||
constructor(props: StatefulSetDetailsProps & Dependencies) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.props.object, () => {
|
||||
this.metrics = null;
|
||||
}),
|
||||
|
||||
this.props.subscribeStores([
|
||||
this.props.podStore,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
loadMetrics = async () => {
|
||||
const { object: statefulSet, requestPodMetricsForStatefulSets } = this.props;
|
||||
|
||||
this.metrics = await requestPodMetricsForStatefulSets([statefulSet], statefulSet.getNs());
|
||||
};
|
||||
|
||||
render() {
|
||||
const { object: statefulSet, podStore, statefulSetStore, getActiveClusterEntity } = this.props;
|
||||
const { object: statefulSet, statefulSetStore, logger } = this.props;
|
||||
|
||||
if (!statefulSet) {
|
||||
return null;
|
||||
@ -88,21 +62,9 @@ class NonInjectedStatefulSetDetails extends React.Component<StatefulSetDetailsPr
|
||||
const selectors = statefulSet.getSelectors();
|
||||
const nodeSelector = statefulSet.getNodeSelectors();
|
||||
const childPods = statefulSetStore.getChildPods(statefulSet);
|
||||
const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.StatefulSet);
|
||||
|
||||
return (
|
||||
<div className="StatefulSetDetails">
|
||||
{!isMetricHidden && podStore.isLoaded && (
|
||||
<ResourceMetrics
|
||||
loader={this.loadMetrics}
|
||||
tabs={podMetricTabs}
|
||||
object={statefulSet}
|
||||
metrics={this.metrics}
|
||||
>
|
||||
<PodCharts/>
|
||||
</ResourceMetrics>
|
||||
)}
|
||||
<KubeObjectMeta object={statefulSet}/>
|
||||
{selectors.length && (
|
||||
<DrawerItem name="Selector" labelsOnly>
|
||||
{
|
||||
@ -131,7 +93,6 @@ class NonInjectedStatefulSetDetails extends React.Component<StatefulSetDetailsPr
|
||||
<DrawerItem name="Pod Status" className="pod-status">
|
||||
<PodDetailsStatuses pods={childPods}/>
|
||||
</DrawerItem>
|
||||
<ResourceMetricsText metrics={this.metrics}/>
|
||||
<PodDetailsList pods={childPods} owner={statefulSet}/>
|
||||
</div>
|
||||
);
|
||||
@ -144,8 +105,7 @@ export const StatefulSetDetails = withInjectables<Dependencies, StatefulSetDetai
|
||||
subscribeStores: di.inject(subscribeStoresInjectable),
|
||||
podStore: di.inject(podStoreInjectable),
|
||||
statefulSetStore: di.inject(statefulSetStoreInjectable),
|
||||
getActiveClusterEntity: di.inject(getActiveClusterEntityInjectable),
|
||||
requestPodMetricsForStatefulSets: di.inject(requestPodMetricsForStatefulSetsInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@ -13,13 +13,11 @@ import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||
import { SiblingsInTabLayout } from "../layout/siblings-in-tab-layout";
|
||||
import { KubeObjectAge } from "../kube-object/age";
|
||||
import type { StatefulSetStore } from "./store";
|
||||
import type { PodStore } from "../+workloads-pods/store";
|
||||
import type { EventStore } from "../+events/store";
|
||||
import type { FilterByNamespace } from "../+namespaces/namespace-select-filter-model/filter-by-namespace.injectable";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import eventStoreInjectable from "../+events/store.injectable";
|
||||
import filterByNamespaceInjectable from "../+namespaces/namespace-select-filter-model/filter-by-namespace.injectable";
|
||||
import podStoreInjectable from "../+workloads-pods/store.injectable";
|
||||
import statefulSetStoreInjectable from "./store.injectable";
|
||||
import { prevDefault } from "../../utils";
|
||||
|
||||
@ -33,26 +31,22 @@ enum columnId {
|
||||
|
||||
interface Dependencies {
|
||||
statefulSetStore: StatefulSetStore;
|
||||
podStore: PodStore;
|
||||
eventStore: EventStore;
|
||||
filterByNamespace: FilterByNamespace;
|
||||
}
|
||||
|
||||
@observer
|
||||
class NonInjectedStatefulSets extends React.Component<Dependencies> {
|
||||
renderPods(statefulSet: StatefulSet) {
|
||||
const renderPodCounts = (statefulSet: StatefulSet) => {
|
||||
const { readyReplicas, currentReplicas } = statefulSet.status ?? {};
|
||||
|
||||
return `${readyReplicas || 0}/${currentReplicas || 0}`;
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const NonInjectedStatefulSets = observer((props: Dependencies) => {
|
||||
const {
|
||||
eventStore,
|
||||
filterByNamespace,
|
||||
podStore,
|
||||
statefulSetStore,
|
||||
} = this.props;
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<SiblingsInTabLayout>
|
||||
@ -61,7 +55,7 @@ class NonInjectedStatefulSets extends React.Component<Dependencies> {
|
||||
tableId="workload_statefulsets"
|
||||
className="StatefulSets"
|
||||
store={statefulSetStore}
|
||||
dependentStores={[podStore, eventStore]} // status icon component uses event store, details component uses podStore
|
||||
dependentStores={[eventStore]}
|
||||
sortingCallbacks={{
|
||||
[columnId.name]: statefulSet => statefulSet.getName(),
|
||||
[columnId.namespace]: statefulSet => statefulSet.getNs(),
|
||||
@ -89,7 +83,7 @@ class NonInjectedStatefulSets extends React.Component<Dependencies> {
|
||||
>
|
||||
{statefulSet.getNs()}
|
||||
</a>,
|
||||
this.renderPods(statefulSet),
|
||||
renderPodCounts(statefulSet),
|
||||
statefulSet.getReplicas(),
|
||||
<KubeObjectStatusIcon key="icon" object={statefulSet} />,
|
||||
<KubeObjectAge key="age" object={statefulSet} />,
|
||||
@ -97,15 +91,13 @@ class NonInjectedStatefulSets extends React.Component<Dependencies> {
|
||||
/>
|
||||
</SiblingsInTabLayout>
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export const StatefulSets = withInjectables<Dependencies>(NonInjectedStatefulSets, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
eventStore: di.inject(eventStoreInjectable),
|
||||
filterByNamespace: di.inject(filterByNamespaceInjectable),
|
||||
podStore: di.inject(podStoreInjectable),
|
||||
statefulSetStore: di.inject(statefulSetStoreInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
@ -3,10 +3,15 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { computed } from "mobx";
|
||||
import kubeDetailsUrlParamInjectable from "../kube-detail-params/kube-details-url.injectable";
|
||||
import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import { asyncComputed } from "@ogre-tools/injectable-react";
|
||||
import type { KubeObject } from "../../../common/k8s-api/kube-object";
|
||||
|
||||
export type CurrentKubeObject =
|
||||
| undefined
|
||||
| { object: KubeObject; error?: undefined }
|
||||
| { object?: undefined; error: string };
|
||||
|
||||
const currentKubeObjectInDetailsInjectable = getInjectable({
|
||||
id: "current-kube-object-in-details",
|
||||
@ -14,20 +19,24 @@ const currentKubeObjectInDetailsInjectable = getInjectable({
|
||||
instantiate: (di) => {
|
||||
const urlParam = di.inject(kubeDetailsUrlParamInjectable);
|
||||
const apiManager = di.inject(apiManagerInjectable);
|
||||
const logger = di.inject(loggerInjectable);
|
||||
|
||||
return computed(() => {
|
||||
return asyncComputed({
|
||||
getValueFromObservedPromise: async (): Promise<CurrentKubeObject> => {
|
||||
const path = urlParam.get();
|
||||
const store = apiManager.getStore(path);
|
||||
|
||||
try {
|
||||
return apiManager.getStore(path)?.getByPath(path);
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`[KUBE-OBJECT-DETAILS]: failed to get store or object ${path}: ${error}`,
|
||||
);
|
||||
|
||||
if (!store) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
try {
|
||||
const object = await store.loadFromPath(path);
|
||||
|
||||
return { object };
|
||||
} catch (error) {
|
||||
return { error: String(error) };
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* 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 { computed } from "mobx";
|
||||
import React from "react";
|
||||
import { CustomResourceDetails } from "../+custom-resources";
|
||||
import customResourceDefinitionStoreInjectable from "../+custom-resources/definition.store.injectable";
|
||||
import currentKubeObjectInDetailsInjectable from "./current-kube-object-in-details.injectable";
|
||||
import { kubeObjectDetailItemInjectionToken } from "./kube-object-detail-items/kube-object-detail-item-injection-token";
|
||||
|
||||
const customResourceDetailItemInjectable = getInjectable({
|
||||
id: "custom-resource-detail-item",
|
||||
instantiate: (di) => {
|
||||
const customResourceDefinitionStore = di.inject(customResourceDefinitionStoreInjectable);
|
||||
const currentKubeObjectInDetails = di.inject(currentKubeObjectInDetailsInjectable);
|
||||
const currentCustomResourceDefinition = computed(() => {
|
||||
const { object } = currentKubeObjectInDetails.value.get() ?? {};
|
||||
|
||||
if (!object) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return customResourceDefinitionStore.getByObject(object);
|
||||
});
|
||||
|
||||
return {
|
||||
Component: ({ object }) => <CustomResourceDetails object={object} crd={currentCustomResourceDefinition.get()} />,
|
||||
enabled: computed(() => Boolean(currentCustomResourceDefinition.get())),
|
||||
orderNumber: 100,
|
||||
};
|
||||
},
|
||||
injectionToken: kubeObjectDetailItemInjectionToken,
|
||||
});
|
||||
|
||||
export default customResourceDetailItemInjectable;
|
||||
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* 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 { computed } from "mobx";
|
||||
import { KubeObjectMeta } from "../kube-object-meta";
|
||||
import { kubeObjectDetailItemInjectionToken } from "./kube-object-detail-items/kube-object-detail-item-injection-token";
|
||||
|
||||
const defaultKubeObjectMetaDetailsItemInjectable = getInjectable({
|
||||
id: "default-kube-object-meta-details-item",
|
||||
instantiate: () => ({
|
||||
Component: KubeObjectMeta,
|
||||
enabled: computed(() => true),
|
||||
orderNumber: 0,
|
||||
}),
|
||||
injectionToken: kubeObjectDetailItemInjectionToken,
|
||||
});
|
||||
|
||||
export default defaultKubeObjectMetaDetailsItemInjectable;
|
||||
@ -17,7 +17,7 @@ const clusterRoleBindingDetailItemInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
Component: ClusterRoleBindingDetails,
|
||||
enabled: computed(() => isClusterRoleBinding(kubeObject.get())),
|
||||
enabled: computed(() => isClusterRoleBinding(kubeObject.value.get()?.object)),
|
||||
orderNumber: 10,
|
||||
};
|
||||
},
|
||||
|
||||
@ -17,7 +17,7 @@ const clusterRoleDetailItemInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
Component: ClusterRoleDetails,
|
||||
enabled: computed(() => isClusterRole(kubeObject.get())),
|
||||
enabled: computed(() => isClusterRole(kubeObject.value.get()?.object)),
|
||||
orderNumber: 10,
|
||||
};
|
||||
},
|
||||
|
||||
@ -17,7 +17,7 @@ const configMapDetailItemInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
Component: ConfigMapDetails,
|
||||
enabled: computed(() => isConfigMap(kubeObject.get())),
|
||||
enabled: computed(() => isConfigMap(kubeObject.value.get()?.object)),
|
||||
orderNumber: 10,
|
||||
};
|
||||
},
|
||||
|
||||
@ -17,7 +17,7 @@ const cronJobDetailItemInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
Component: CronJobDetails,
|
||||
enabled: computed(() => isCronJob(kubeObject.get())),
|
||||
enabled: computed(() => isCronJob(kubeObject.value.get()?.object)),
|
||||
orderNumber: 10,
|
||||
};
|
||||
},
|
||||
|
||||
@ -17,7 +17,7 @@ const customResourceDefinitionsDetailItemInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
Component: CRDDetails,
|
||||
enabled: computed(() => isCustomResourceDefinition(kubeObject.get())),
|
||||
enabled: computed(() => isCustomResourceDefinition(kubeObject.value.get()?.object)),
|
||||
orderNumber: 10,
|
||||
};
|
||||
},
|
||||
|
||||
@ -17,7 +17,7 @@ const daemonSetDetailItemInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
Component: DaemonSetDetails,
|
||||
enabled: computed(() => isDaemonSet(kubeObject.get())),
|
||||
enabled: computed(() => isDaemonSet(kubeObject.value.get()?.object)),
|
||||
orderNumber: 10,
|
||||
};
|
||||
},
|
||||
|
||||
@ -17,7 +17,7 @@ const deploymentDetailItemInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
Component: DeploymentDetails,
|
||||
enabled: computed(() => isDeployment(kubeObject.get())),
|
||||
enabled: computed(() => isDeployment(kubeObject.value.get()?.object)),
|
||||
orderNumber: 10,
|
||||
};
|
||||
},
|
||||
|
||||
@ -17,7 +17,7 @@ const endpointsDetailItemInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
Component: EndpointsDetails,
|
||||
enabled: computed(() => isEndpoint(kubeObject.get())),
|
||||
enabled: computed(() => isEndpoint(kubeObject.value.get()?.object)),
|
||||
orderNumber: 10,
|
||||
};
|
||||
},
|
||||
|
||||
@ -17,7 +17,7 @@ const eventsDetailItemInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
Component: EventDetails,
|
||||
enabled: computed(() => isEvent(kubeObject.get())),
|
||||
enabled: computed(() => isEvent(kubeObject.value.get()?.object)),
|
||||
orderNumber: 10,
|
||||
};
|
||||
},
|
||||
|
||||
@ -17,7 +17,7 @@ const horizontalPodAutoscalerDetailItemInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
Component: HpaDetails,
|
||||
enabled: computed(() => isHorizontalPodAutoscaler(kubeObject.get())),
|
||||
enabled: computed(() => isHorizontalPodAutoscaler(kubeObject.value.get()?.object)),
|
||||
orderNumber: 10,
|
||||
};
|
||||
},
|
||||
|
||||
@ -17,7 +17,7 @@ const ingressDetailItemInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
Component: IngressDetails,
|
||||
enabled: computed(() => isIngress(kubeObject.get())),
|
||||
enabled: computed(() => isIngress(kubeObject.value.get()?.object)),
|
||||
orderNumber: 10,
|
||||
};
|
||||
},
|
||||
|
||||
@ -17,7 +17,7 @@ const jobDetailItemInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
Component: JobDetails,
|
||||
enabled: computed(() => isJob(kubeObject.get())),
|
||||
enabled: computed(() => isJob(kubeObject.value.get()?.object)),
|
||||
orderNumber: 10,
|
||||
};
|
||||
},
|
||||
|
||||
@ -6,78 +6,16 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { computed } from "mobx";
|
||||
import { kubeObjectDetailItemInjectionToken } from "../kube-object-detail-item-injection-token";
|
||||
import { KubeEventDetails } from "../../../+events/kube-event-details";
|
||||
import currentKubeObjectInDetailsInjectable from "../../current-kube-object-in-details.injectable";
|
||||
import { isClusterRole } from "./cluster-role-detail-item.injectable";
|
||||
import { isClusterRoleBinding } from "./cluster-role-binding-detail-item.injectable";
|
||||
import { isCronJob } from "./cron-job-detail-item.injectable";
|
||||
import { isDaemonSet } from "./daemon-set-detail-item.injectable";
|
||||
import { isDeployment } from "./deployment-detail-item.injectable";
|
||||
import { isEndpoint } from "./endpoints-detail-item.injectable";
|
||||
import { isHorizontalPodAutoscaler } from "./horizontal-pod-autoscaler-detail-item.injectable";
|
||||
import { isIngress } from "./ingress-detail-item.injectable";
|
||||
import { isJob } from "./job-detail-item.injectable";
|
||||
import { isNetworkPolicy } from "./network-policy-detail-item.injectable";
|
||||
import { isPersistentVolume } from "./persistent-volume-detail-item.injectable";
|
||||
import { isPersistentVolumeClaim } from "./persistent-volume-claim-detail-item.injectable";
|
||||
import { isNode } from "./node-detail-item.injectable";
|
||||
import { isPod } from "./pod-detail-item.injectable";
|
||||
import { isReplicaSet } from "./replica-set-detail-item.injectable";
|
||||
import { isRole } from "./role-detail-item.injectable";
|
||||
import { isRoleBinding } from "./role-binding-detail-item.injectable";
|
||||
import { isService } from "./service-detail-item.injectable";
|
||||
import { isServiceAccount } from "./service-account-detail-item.injectable";
|
||||
import { isStatefulSet } from "./stateful-set-detail-item.injectable";
|
||||
import { isStorageClass } from "./storage-class-detail-item.injectable";
|
||||
|
||||
const kubeEventDetailItemInjectable = getInjectable({
|
||||
id: "kube-event-detail-item",
|
||||
|
||||
instantiate: (di) => {
|
||||
const currentKubeObjectInDetails = di.inject(
|
||||
currentKubeObjectInDetailsInjectable,
|
||||
);
|
||||
|
||||
return {
|
||||
instantiate: () => ({
|
||||
Component: KubeEventDetails,
|
||||
|
||||
enabled: computed(() => {
|
||||
const kubeObject = currentKubeObjectInDetails.get();
|
||||
|
||||
if (!kubeObject) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const predicates = [
|
||||
isClusterRole,
|
||||
isClusterRoleBinding,
|
||||
isCronJob,
|
||||
isDaemonSet,
|
||||
isDeployment,
|
||||
isEndpoint,
|
||||
isHorizontalPodAutoscaler,
|
||||
isIngress,
|
||||
isJob,
|
||||
isNetworkPolicy,
|
||||
isNode,
|
||||
isPersistentVolume,
|
||||
isPersistentVolumeClaim,
|
||||
isPod,
|
||||
isReplicaSet,
|
||||
isRole,
|
||||
isRoleBinding,
|
||||
isService,
|
||||
isServiceAccount,
|
||||
isStatefulSet,
|
||||
isStorageClass,
|
||||
];
|
||||
|
||||
return predicates.some((predicate) => predicate(kubeObject));
|
||||
enabled: computed(() => true),
|
||||
orderNumber: Infinity,
|
||||
}),
|
||||
|
||||
orderNumber: 355,
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: kubeObjectDetailItemInjectionToken,
|
||||
});
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ const leaseDetailItemInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
Component: LeaseDetails,
|
||||
enabled: computed(() => isLease(kubeObject.get())),
|
||||
enabled: computed(() => isLease(kubeObject.value.get()?.object)),
|
||||
orderNumber: 10,
|
||||
};
|
||||
},
|
||||
|
||||
@ -17,7 +17,7 @@ const limitRangeDetailItemInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
Component: LimitRangeDetails,
|
||||
enabled: computed(() => isLimitRange(kubeObject.get())),
|
||||
enabled: computed(() => isLimitRange(kubeObject.value.get()?.object)),
|
||||
orderNumber: 10,
|
||||
};
|
||||
},
|
||||
|
||||
@ -17,7 +17,7 @@ const namespacesDetailItemInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
Component: NamespaceDetails,
|
||||
enabled: computed(() => isNamespace(kubeObject.get())),
|
||||
enabled: computed(() => isNamespace(kubeObject.value.get()?.object)),
|
||||
orderNumber: 10,
|
||||
};
|
||||
},
|
||||
|
||||
@ -17,7 +17,7 @@ const networkPolicyDetailItemInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
Component: NetworkPolicyDetails,
|
||||
enabled: computed(() => isNetworkPolicy(kubeObject.get())),
|
||||
enabled: computed(() => isNetworkPolicy(kubeObject.value.get()?.object)),
|
||||
orderNumber: 10,
|
||||
};
|
||||
},
|
||||
|
||||
@ -17,7 +17,7 @@ const nodeDetailItemInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
Component: NodeDetails,
|
||||
enabled: computed(() => isNode(kubeObject.get())),
|
||||
enabled: computed(() => isNode(kubeObject.value.get()?.object)),
|
||||
orderNumber: 10,
|
||||
};
|
||||
},
|
||||
|
||||
@ -17,7 +17,7 @@ const persistentVolumeClaimDetailItemInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
Component: PersistentVolumeClaimDetails,
|
||||
enabled: computed(() => isPersistentVolumeClaim(kubeObject.get())),
|
||||
enabled: computed(() => isPersistentVolumeClaim(kubeObject.value.get()?.object)),
|
||||
orderNumber: 10,
|
||||
};
|
||||
},
|
||||
|
||||
@ -17,7 +17,7 @@ const persistentVolumeDetailItemInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
Component: PersistentVolumeDetails,
|
||||
enabled: computed(() => isPersistentVolume(kubeObject.get())),
|
||||
enabled: computed(() => isPersistentVolume(kubeObject.value.get()?.object)),
|
||||
orderNumber: 10,
|
||||
};
|
||||
},
|
||||
|
||||
@ -17,7 +17,7 @@ const podDetailItemInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
Component: PodDetails,
|
||||
enabled: computed(() => isPod(kubeObject.get())),
|
||||
enabled: computed(() => isPod(kubeObject.value.get()?.object)),
|
||||
orderNumber: 10,
|
||||
};
|
||||
},
|
||||
|
||||
@ -17,7 +17,7 @@ const podDisruptionBudgetDetailItemInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
Component: PodDisruptionBudgetDetails,
|
||||
enabled: computed(() => isPodDisruptionBudget(kubeObject.get())),
|
||||
enabled: computed(() => isPodDisruptionBudget(kubeObject.value.get()?.object)),
|
||||
orderNumber: 10,
|
||||
};
|
||||
},
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user