diff --git a/src/common/k8s-api/endpoints/horizontal-pod-autoscaler.api.ts b/src/common/k8s-api/endpoints/horizontal-pod-autoscaler.api.ts index 50f7c19aea..1a5cd80662 100644 --- a/src/common/k8s-api/endpoints/horizontal-pod-autoscaler.api.ts +++ b/src/common/k8s-api/endpoints/horizontal-pod-autoscaler.api.ts @@ -3,11 +3,11 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { BaseKubeObjectCondition, LabelSelector, NamespaceScopedMetadata } from "../kube-object"; -import { KubeObject } from "../kube-object"; +import type { OptionVarient } from "../../utils"; import type { DerivedKubeApiOptions, KubeApiDependencies } from "../kube-api"; import { KubeApi } from "../kube-api"; -import type { OptionVarient } from "../../utils"; +import type { BaseKubeObjectCondition, LabelSelector, NamespaceScopedMetadata } from "../kube-object"; +import { KubeObject } from "../kube-object"; export enum HpaMetricType { Resource = "Resource", @@ -28,10 +28,9 @@ export interface ContainerResourceMetricSource { name: string; targetAverageUtilization?: number; targetAverageValue?: string; - - // autscaling/v2 target?: { averageUtilization?: number; + averageValue?: string; type?: string; } } @@ -41,8 +40,6 @@ export interface ExternalMetricSource { metricSelector?: LabelSelector; targetAverageValue?: string; targetValue?: string; - - // autoscaling/v2 metric?: { name?: string; selector?: LabelSelector; @@ -59,24 +56,21 @@ export interface ObjectMetricSource { metricName?: string; selector?: LabelSelector; targetValue?: string; - - // autoscaling/v2 metric?: { name?: string; }, - target: { + target?: { type?: string; value?: string; + averageValue?: string; }; - describedObject?: CrossVersionObjectReference; + describedObject?: CrossVersionObjectReference } export interface PodsMetricSource { metricName?: string; selector?: LabelSelector; targetAverageValue?: string; - - // autoscaling/v2 metric?: { name?: string; } @@ -90,8 +84,6 @@ export interface ResourceMetricSource { name: string; targetAverageUtilization?: number; targetAverageValue?: string; - - // autoscaling/v2 target?: { averageUtilization?: number; averageValue?: string; @@ -136,17 +128,29 @@ interface HPAScalingPolicy { type HPAScalingPolicyType = string; export interface ContainerResourceMetricStatus { - container: string; + container?: string; currentAverageUtilization?: number; - currentAverageValue: string; + currentAverageValue?: string; name: string; + current?: { + averageUtilization?: number; + averageValue?: string; + } } export interface ExternalMetricStatus { currentAverageValue?: string; - currentValue: string; - metricName: string; + currentValue?: string; + metricName?: string; metricSelector?: LabelSelector; + metric?: { + name?: string; + selector?: LabelSelector; + }, + current?: { + averageValue?: string; + value?: string; + } } export interface ObjectMetricStatus { @@ -154,30 +158,34 @@ export interface ObjectMetricStatus { currentValue?: string; metricName?: string; selector?: LabelSelector; - - // autoscaling/v2 metric?: { name?: string; + selector?: LabelSelector; }, - current: { + current?: { type?: string; value?: string; + averageValue?: string; }; describedObject?: CrossVersionObjectReference; } export interface PodsMetricStatus { - currentAverageValue: string; - metricName: string; + currentAverageValue?: string; + metricName?: string; selector?: LabelSelector; + metric?: { + name?: string; + } + current?: { + averageValue?: string; + } } export interface ResourceMetricStatus { currentAverageUtilization?: number; currentAverageValue?: string; name: string; - - // autoscaling/v2 current?: { averageUtilization?: number; averageValue?: string; @@ -220,11 +228,6 @@ export interface HorizontalPodAutoscalerStatus { currentMetrics?: HorizontalPodAutoscalerMetricStatus[]; } -interface MetricCurrentTarget { - current?: string; - target?: string; -} - export class HorizontalPodAutoscaler extends KubeObject< NamespaceScopedMetadata, HorizontalPodAutoscalerStatus, @@ -263,48 +266,12 @@ export class HorizontalPodAutoscaler extends KubeObject< } getMetrics() { - // console.log(this.spec) return this.spec.metrics ?? []; } getCurrentMetrics() { - // console.log(this.status) return this.status?.currentMetrics ?? []; } - - getMetricValues(metric: HorizontalPodAutoscalerMetricSpec): string { - const { - current = "unknown", - target = "unknown", - } = this.getMetricsCurrentAndTarget(metric); - - return `${current} / ${target}`; - } - - getMetricsCurrentAndTarget(spec: HorizontalPodAutoscalerMetricSpec): MetricCurrentTarget { - const currentMetrics = this.getCurrentMetrics(); - const currentMetric = currentMetrics.find(m => ( - m.type === spec.type - && getMetricName(m) === getMetricName(spec) - )); - - console.log(spec, currentMetrics) - - switch (spec.type) { - case HpaMetricType.Resource: - return getResourceMetricValue(currentMetric?.resource, spec.resource); - case HpaMetricType.Pods: - return getPodsMetricValue(currentMetric?.pods, spec.pods); - case HpaMetricType.Object: - return getObjectMetricValue(currentMetric?.object, spec.object); - case HpaMetricType.External: - return getExternalMetricValue(currentMetric?.external, spec.external); - case HpaMetricType.ContainerResource: - return getContainerResourceMetricValue(currentMetric?.containerResource, spec.containerResource); - default: - return {}; - } - } } export class HorizontalPodAutoscalerApi extends KubeApi { @@ -322,92 +289,3 @@ export class HorizontalPodAutoscalerApi extends KubeApi }); } } - -function getMetricName(metric: HorizontalPodAutoscalerMetricSpec | HorizontalPodAutoscalerMetricStatus): string | undefined { - switch (metric.type) { - case HpaMetricType.Resource: - return metric.resource.name; - case HpaMetricType.Pods: - return metric.pods.metricName; - case HpaMetricType.Object: - return metric.object.metricName; - case HpaMetricType.External: - return metric.external.metricName; - case HpaMetricType.ContainerResource: - return metric.containerResource.name; - default: - return undefined; - } -} - -function getResourceMetricValue(currentMetric: ResourceMetricStatus | undefined, targetMetric: ResourceMetricSource): MetricCurrentTarget { - return { - current: ( - typeof currentMetric?.current?.averageUtilization === "number" - ? `${currentMetric.current?.averageUtilization}%` - : currentMetric?.current?.averageValue - ), - target: typeof targetMetric?.target?.averageUtilization === "number" - ? `${targetMetric.target.averageUtilization}%` - : targetMetric?.target?.averageValue ?? "unknown" - }; -} - -function getPodsMetricValue(currentMetric: PodsMetricStatus | undefined, targetMetric: PodsMetricSource): MetricCurrentTarget { - return { - current: currentMetric?.currentAverageValue, - target: targetMetric?.target?.averageValue, - } - - // v1 - // return { - // current: currentMetric?.currentAverageValue, - // target: targetMetric?.targetAverageValue, - // }; -} - -function getObjectMetricValue(currentMetric: ObjectMetricStatus | undefined, targetMetric: ObjectMetricSource): MetricCurrentTarget { - return { - current: ( - currentMetric?.currentValue - ?? currentMetric?.averageValue - ), - target: targetMetric?.target?.value - }; -} - -function getExternalMetricValue(currentMetric: ExternalMetricStatus | undefined, targetMetric: ExternalMetricSource): MetricCurrentTarget { - return { - current: ( - currentMetric?.currentValue - ?? currentMetric?.currentAverageValue - ), - target: ( - targetMetric?.target?.value - ?? `${targetMetric?.target?.averageValue} (avg)` - ), - }; -} - -function getContainerResourceMetricValue(currentMetric: ContainerResourceMetricStatus | undefined, targetMetric: ContainerResourceMetricSource): MetricCurrentTarget { - let target = "unknown"; - - if (targetMetric.target) { - // v2 - target = targetMetric.target.averageUtilization ? `${targetMetric.target.averageUtilization}%` : "unknown"; - } else { - target = typeof targetMetric?.targetAverageUtilization === "number" - ? `${targetMetric.targetAverageUtilization}%` - : targetMetric?.targetAverageValue ?? "unknown"; - } - - return { - current: ( - typeof currentMetric?.currentAverageUtilization === "number" - ? `${currentMetric.currentAverageUtilization}%` - : currentMetric?.currentAverageValue - ), - target, - }; -} - diff --git a/src/renderer/components/+config-autoscalers/get-hpa-metrics.injectable.ts b/src/renderer/components/+config-autoscalers/get-hpa-metrics.injectable.ts new file mode 100644 index 0000000000..3111149570 --- /dev/null +++ b/src/renderer/components/+config-autoscalers/get-hpa-metrics.injectable.ts @@ -0,0 +1,61 @@ +import { getInjectable } from "@ogre-tools/injectable"; +import { HorizontalPodAutoscaler, HorizontalPodAutoscalerMetricSpec, HorizontalPodAutoscalerMetricStatus, HpaMetricType } from "../../../common/k8s-api/endpoints"; +import type { HorizontalPodAutoscalerV2MetricParser } from "./hpa-v2-metric-parser"; +import horizonalPodAutoscalerV2MetricParser from "./hpa-v2-metric-parser.injectable"; + +const getHorizontalPodAutoscalerMetrics = getInjectable({ + id: "get-horizontal-pod-autoscaler-metrics", + instantiate: (di) => (hpa: HorizontalPodAutoscaler) => { + const hpaV2Parser = di.inject(horizonalPodAutoscalerV2MetricParser); + const metrics = hpa.spec?.metrics ?? []; + const currentMetrics = hpa.status?.currentMetrics ?? []; + + return metrics.map((metric) => { + const currentMetric = currentMetrics.find(current => + current.type === metric.type + && getMetricName(current) === getMetricName(metric) + ); + const parser = hpa.apiVersion.includes("v2") ? hpaV2Parser : hpaV2Parser; + + const values = getMetricValues(parser, currentMetric, metric); + + return `${values.current ?? "unknown"} / ${values.target ?? "unknown"}`; + }); + }, +}) + +function getMetricValues(parser: HorizontalPodAutoscalerV2MetricParser, current: HorizontalPodAutoscalerMetricStatus | undefined, target: HorizontalPodAutoscalerMetricSpec) { + switch (target.type) { + case HpaMetricType.Resource: + return parser.getResource({ current: current?.resource, target: target.resource}); + case HpaMetricType.Pods: + return parser.getPods({ current: current?.pods, target: target.pods }); + case HpaMetricType.Object: + return parser.getObject({ current: current?.object, target: target.object }); + case HpaMetricType.External: + return parser.getExternal({ current: current?.external, target: target.external }); + case HpaMetricType.ContainerResource: + return parser.getContainerResource({ current: current?.containerResource, target: target.containerResource }); + default: + return {}; + } +} + +function getMetricName(metric: HorizontalPodAutoscalerMetricSpec | HorizontalPodAutoscalerMetricStatus): string | undefined { + switch (metric.type) { + case HpaMetricType.Resource: + return metric.resource.name; + case HpaMetricType.Pods: + return metric.pods.metricName || metric.pods.metric?.name; + case HpaMetricType.Object: + return metric.object.metricName || metric.object.metric?.name; + case HpaMetricType.External: + return metric.external.metricName || metric.external.metric?.name; + case HpaMetricType.ContainerResource: + return metric.containerResource.name; + default: + return undefined; + } +} + +export default getHorizontalPodAutoscalerMetrics; \ No newline at end of file