/** * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ import "./hpa-details.scss"; import React from "react"; import { observer } from "mobx-react"; import { Link } from "react-router-dom"; import { DrawerItem, DrawerTitle } from "../drawer"; import { Badge } from "../badge"; import type { KubeObjectDetailsProps } from "../kube-object-details"; import { cssNames } from "../../utils"; import type { HorizontalPodAutoscalerMetricSpec, HorizontalPodAutoscalerMetricTarget } from "../../../common/k8s-api/endpoints/horizontal-pod-autoscaler.api"; 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"; import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable"; import getDetailsUrlInjectable from "../kube-detail-params/get-details-url.injectable"; export interface HpaDetailsProps extends KubeObjectDetailsProps { } interface Dependencies { apiManager: ApiManager; getDetailsUrl: GetDetailsUrl; } @observer class NonInjectedHpaDetails extends React.Component { private renderTargetLink(target: HorizontalPodAutoscalerMetricTarget | undefined) { if (!target) { return null; } const { object: hpa, apiManager, getDetailsUrl } = this.props; const { kind, name } = target; const objectUrl = getDetailsUrl(apiManager.lookupApiLink(target, hpa)); return ( <> on {`${kind}/${name}`} ); } renderMetrics() { const { object: hpa } = this.props; const renderName = (metric: HorizontalPodAutoscalerMetricSpec) => { switch (metric.type) { case HpaMetricType.ContainerResource: // fallthrough case HpaMetricType.Resource: { const metricSpec = metric.resource ?? metric.containerResource; const addition = metricSpec.targetAverageUtilization ? " (as a percentage of request)" : ""; return `Resource ${metricSpec.name} on Pods${addition}`; } case HpaMetricType.Pods: return `${metric.pods.metricName} on Pods`; case HpaMetricType.Object: { return ( <> {metric.object.metricName} {" "} {this.renderTargetLink(metric.object.target)} ); } case HpaMetricType.External: return `${metric.external.metricName} on ${JSON.stringify(metric.external.metricSelector)}`; } }; return ( Name Current / Target { hpa.getMetrics() .map((metric, index) => ( {renderName(metric)} {hpa.getMetricValues(metric)} )) }
); } render() { const { object: hpa, apiManager, getDetailsUrl } = this.props; if (!hpa) { return null; } if (!(hpa instanceof HorizontalPodAutoscaler)) { logger.error("[HpaDetails]: passed object that is not an instanceof HorizontalPodAutoscaler", hpa); return null; } const { scaleTargetRef } = hpa.spec; return (
{scaleTargetRef && ( {scaleTargetRef.kind} / {scaleTargetRef.name} )} {hpa.getMinPods()} {hpa.getMaxPods()} {hpa.getReplicas()} {hpa.getReadyConditions() .map(({ type, tooltip, isReady }) => ( ))} Metrics
{this.renderMetrics()}
); } } export const HpaDetails = withInjectables(NonInjectedHpaDetails, { getProps: (di, props) => ({ ...props, apiManager: di.inject(apiManagerInjectable), getDetailsUrl: di.inject(getDetailsUrlInjectable), }), });