diff --git a/packages/core/src/renderer/components/+config-autoscalers/__snapshots__/hpa-details.test.tsx.snap b/packages/core/src/renderer/components/+config-autoscalers/__snapshots__/hpa-details.test.tsx.snap
new file mode 100644
index 0000000000..a32a798b8b
--- /dev/null
+++ b/packages/core/src/renderer/components/+config-autoscalers/__snapshots__/hpa-details.test.tsx.snap
@@ -0,0 +1,326 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` renders 1`] = `
+
+
+
+
+
+ Reference
+
+
+ Deployment
+ /
+ hpav2deployment
+
+
+
+
+ Min Pods
+
+
+ 0
+
+
+
+
+ Max Pods
+
+
+ 10
+
+
+
+
+ Replicas
+
+
+ 0
+
+
+
+
+ Status
+
+
+
+
+
+
+`;
+
+exports[` shows unknown metrics with lack of metric type 1`] = `
+
+
+
+
+
+ Reference
+
+
+ Deployment
+ /
+ hpav2deployment
+
+
+
+
+ Min Pods
+
+
+ 0
+
+
+
+
+ Max Pods
+
+
+ 10
+
+
+
+
+ Replicas
+
+
+ 0
+
+
+
+
+ Status
+
+
+
+
+ Metrics
+
+
+
+
+
+`;
+
+exports[` shows unknown metrics with with unusual type 1`] = `
+
+
+
+
+
+ Reference
+
+
+ Deployment
+ /
+ hpav2deployment
+
+
+
+
+ Min Pods
+
+
+ 0
+
+
+
+
+ Max Pods
+
+
+ 10
+
+
+
+
+ Replicas
+
+
+ 0
+
+
+
+
+ Status
+
+
+
+
+ Metrics
+
+
+
+
+
+`;
diff --git a/packages/core/src/renderer/components/+config-autoscalers/get-hpa-metric-name.ts b/packages/core/src/renderer/components/+config-autoscalers/get-hpa-metric-name.ts
index f92b249909..d45db05ec0 100644
--- a/packages/core/src/renderer/components/+config-autoscalers/get-hpa-metric-name.ts
+++ b/packages/core/src/renderer/components/+config-autoscalers/get-hpa-metric-name.ts
@@ -19,8 +19,8 @@ interface Metric extends MetricNames {
type: HpaMetricType;
}
-export function getMetricName(metric: Metric): string | undefined {
- switch (metric.type) {
+export function getMetricName(metric: Metric | undefined): string | undefined {
+ switch (metric?.type) {
case HpaMetricType.Resource:
return metric.resource?.name;
case HpaMetricType.Pods:
diff --git a/packages/core/src/renderer/components/+config-autoscalers/hpa-details.test.tsx b/packages/core/src/renderer/components/+config-autoscalers/hpa-details.test.tsx
new file mode 100644
index 0000000000..017b719841
--- /dev/null
+++ b/packages/core/src/renderer/components/+config-autoscalers/hpa-details.test.tsx
@@ -0,0 +1,392 @@
+/**
+ * Copyright (c) OpenLens Authors. All rights reserved.
+ * Licensed under MIT License. See LICENSE in root directory for more information.
+ */
+import type { RenderResult } from "@testing-library/react";
+import React from "react";
+import { HorizontalPodAutoscaler, HpaMetricType } from "../../../common/k8s-api/endpoints";
+import { getDiForUnitTesting } from "../../getDiForUnitTesting";
+import type { DiRender } from "../test-utils/renderFor";
+import { renderFor } from "../test-utils/renderFor";
+import { HpaDetails } from "./hpa-details";
+
+jest.mock("react-router-dom", () => ({
+ Link: ({ children }: { children: React.ReactNode }) => children,
+}));
+
+const hpaV2 = {
+ apiVersion: "autoscaling/v2",
+ kind: "HorizontalPodAutoscaler",
+ metadata: {
+ name: "hpav2",
+ resourceVersion: "1",
+ uid: "hpav2",
+ namespace: "default",
+ selfLink: "/apis/autoscaling/v2/namespaces/default/horizontalpodautoscalers/hpav2",
+ },
+ spec: {
+ maxReplicas: 10,
+ scaleTargetRef: {
+ kind: "Deployment",
+ name: "hpav2deployment",
+ apiVersion: "apps/v1",
+ },
+ },
+};
+
+describe("", () => {
+ let result: RenderResult;
+ let render: DiRender;
+
+ beforeEach(() => {
+ const di = getDiForUnitTesting({ doGeneralOverrides: true });
+
+ render = renderFor(di);
+ });
+
+ it("renders", () => {
+ const hpa = new HorizontalPodAutoscaler(hpaV2);
+
+ result = render(
+ ,
+ );
+
+ expect(result.baseElement).toMatchSnapshot();
+ });
+
+ it("does not show metrics table if no metrics found", () => {
+ const hpa = new HorizontalPodAutoscaler(hpaV2);
+
+ result = render(
+ ,
+ );
+
+ expect(result.queryByTestId("hpa-metrics")).toBeNull();
+ });
+
+ it("shows proper metric name for autoscaling/v1", () => {
+ const hpa = new HorizontalPodAutoscaler({
+ apiVersion: "autoscaling/v1",
+ kind: "HorizontalPodAutoscaler",
+ metadata: {
+ name: "hpav1",
+ resourceVersion: "1",
+ uid: "hpav1",
+ namespace: "default",
+ selfLink: "/apis/autoscaling/v1/namespaces/default/horizontalpodautoscalers/hpav1",
+ },
+ spec: {
+ maxReplicas: 10,
+ scaleTargetRef: {
+ kind: "Deployment",
+ name: "hpav1deployment",
+ apiVersion: "apps/v1",
+ },
+ targetCPUUtilizationPercentage: 80,
+ },
+ });
+
+ result = render(
+ ,
+ );
+
+ expect(result.getByText("CPU Utilization percentage")).toBeInTheDocument();
+ });
+
+ it("shows proper metric name for container resource metrics", () => {
+ const hpa = new HorizontalPodAutoscaler(
+ {
+ ...hpaV2,
+ spec: {
+ ...hpaV2.spec,
+ metrics: [
+ {
+ type: HpaMetricType.ContainerResource,
+ containerResource: {
+ name: "cpu",
+ container: "nginx",
+ target: {
+ type: "Utilization",
+ averageUtilization: 60,
+ },
+ },
+ },
+ ],
+ },
+ },
+ );
+
+ result = render(
+ ,
+ );
+
+ expect(result.getByText("Resource cpu on Pods")).toBeInTheDocument();
+ });
+
+ it("shows proper metric name for resource metrics", () => {
+ const hpa = new HorizontalPodAutoscaler(
+ {
+ ...hpaV2,
+ spec: {
+ ...hpaV2.spec,
+ metrics: [
+ {
+ type: HpaMetricType.Resource,
+ resource: {
+ name: "cpu",
+ target: {
+ type: "Utilization",
+ averageUtilization: 50,
+ },
+ },
+ },
+ ],
+ },
+ },
+ );
+
+ result = render(
+ ,
+ );
+
+ expect(result.getByText("Resource cpu on Pods")).toBeInTheDocument();
+ });
+
+ it("shows proper metric name for pod metrics for hpa v2", () => {
+ const hpa = new HorizontalPodAutoscaler(
+ {
+ ...hpaV2,
+ spec: {
+ ...hpaV2.spec,
+ metrics: [
+ {
+ type: HpaMetricType.Pods,
+ pods: {
+ metric: {
+ name: "packets-per-second",
+ },
+ target: {
+ type: "AverageValue",
+ averageValue: "1k",
+ },
+ },
+ },
+ ],
+ },
+ },
+ );
+
+ result = render(
+ ,
+ );
+
+ expect(result.getByText("packets-per-second on Pods")).toBeInTheDocument();
+ });
+
+ it("shows proper metric name for pod metrics for hpa v2beta1", () => {
+ const hpa = new HorizontalPodAutoscaler(
+ {
+ ...hpaV2,
+ spec: {
+ ...hpaV2.spec,
+ metrics: [
+ {
+ type: HpaMetricType.Pods,
+ pods: {
+ metricName: "packets-per-second",
+ },
+ },
+ ],
+ },
+ },
+ );
+
+ result = render(
+ ,
+ );
+
+ expect(result.getByText("packets-per-second on Pods")).toBeInTheDocument();
+ });
+
+ it("shows proper metric name for object metrics for hpa v2", () => {
+ const hpa = new HorizontalPodAutoscaler(
+ {
+ ...hpaV2,
+ spec: {
+ ...hpaV2.spec,
+ metrics: [
+ {
+ type: HpaMetricType.Object,
+ object: {
+ metric: {
+ name: "requests-per-second",
+ },
+ target: {
+ type: "Value",
+ value: "10k",
+ },
+ describedObject: {
+ kind: "Service",
+ name: "nginx",
+ apiVersion: "v1",
+ },
+ },
+ },
+ ],
+ },
+ },
+ );
+
+ result = render(
+ ,
+ );
+
+ expect(result.getByText(/requests-per-second/)).toHaveTextContent("requests-per-second onService/nginx");
+ });
+
+ it("shows proper metric name for object metrics for hpa v2beta1", () => {
+ const hpa = new HorizontalPodAutoscaler(
+ {
+ ...hpaV2,
+ spec: {
+ ...hpaV2.spec,
+ metrics: [
+ {
+ type: HpaMetricType.Object,
+ object: {
+ metricName: "requests-per-second",
+ },
+ },
+ ],
+ },
+ },
+ );
+
+ result = render(
+ ,
+ );
+
+ expect(result.getByText("requests-per-second")).toBeInTheDocument();
+ });
+
+ it("shows proper metric name for external metrics for hpa v2", () => {
+ const hpa = new HorizontalPodAutoscaler(
+ {
+ ...hpaV2,
+ spec: {
+ ...hpaV2.spec,
+ metrics: [
+ {
+ type: HpaMetricType.External,
+ external: {
+ metric: {
+ name: "queue_messages_ready",
+ selector: {
+ matchLabels: { queue: "worker_tasks" },
+ },
+ },
+ target: {
+ type: "AverageValue",
+ averageValue: "30",
+ },
+ },
+ },
+ ],
+ },
+ },
+ );
+
+ result = render(
+ ,
+ );
+
+ expect(result.getByText("queue_messages_ready on {\"matchLabels\":{\"queue\":\"worker_tasks\"}}")).toBeInTheDocument();
+ });
+
+ it("shows proper metric name for external metrics for hpa v2beta1", () => {
+ const hpa = new HorizontalPodAutoscaler(
+ {
+ ...hpaV2,
+ spec: {
+ ...hpaV2.spec,
+ metrics: [
+ {
+ type: HpaMetricType.External,
+ external: {
+ metricName: "queue_messages_ready",
+ metricSelector: {
+ matchLabels: { queue: "worker_tasks" },
+ },
+ },
+ },
+ ],
+ },
+ },
+ );
+
+ result = render(
+ ,
+ );
+
+ expect(result.getByText("queue_messages_ready on {\"matchLabels\":{\"queue\":\"worker_tasks\"}}")).toBeInTheDocument();
+ });
+
+ it("shows unknown metrics with lack of metric type", () => {
+ const hpa = new HorizontalPodAutoscaler(
+ {
+ ...hpaV2,
+ spec: {
+ ...hpaV2.spec,
+ metrics: [
+ // @ts-ignore
+ {
+ resource: {
+ name: "cpu",
+ target: {
+ type: "Utilization",
+ averageUtilization: 50,
+ },
+ },
+ },
+ ],
+ },
+ },
+ );
+
+ result = render(
+ ,
+ );
+
+ expect(result.baseElement).toMatchSnapshot();
+ });
+
+ it("shows unknown metrics with with unusual type", () => {
+ const hpa = new HorizontalPodAutoscaler(
+ {
+ ...hpaV2,
+ spec: {
+ ...hpaV2.spec,
+ metrics: [
+ {
+ // @ts-ignore
+ type: "Unusual",
+ resource: {
+ name: "cpu",
+ target: {
+ type: "Utilization",
+ averageUtilization: 50,
+ },
+ },
+ },
+ ],
+ },
+ },
+ );
+
+ result = render(
+ ,
+ );
+
+ expect(result.baseElement).toMatchSnapshot();
+ });
+});
diff --git a/packages/core/src/renderer/components/+config-autoscalers/hpa-details.tsx b/packages/core/src/renderer/components/+config-autoscalers/hpa-details.tsx
index 96c1a7e20b..49130991a5 100644
--- a/packages/core/src/renderer/components/+config-autoscalers/hpa-details.tsx
+++ b/packages/core/src/renderer/components/+config-autoscalers/hpa-details.tsx
@@ -62,7 +62,7 @@ class NonInjectedHpaDetails extends React.Component {
const metricName = getMetricName(metric);
- switch (metric.type) {
+ switch (metric?.type) {
case HpaMetricType.ContainerResource:
// fallthrough
@@ -85,11 +85,13 @@ class NonInjectedHpaDetails extends React.Component
+
Name
Current / Target
@@ -162,10 +164,14 @@ class NonInjectedHpaDetails extends React.Component
- Metrics
-
- {this.renderMetrics()}
-
+ {(hpa.getMetrics().length !== 0 || hpa.spec?.targetCPUUtilizationPercentage) && (
+ <>
+ Metrics
+
+ {this.renderMetrics()}
+
+ >
+ )}
);
}