1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-24 07:49:41 +02:00

chore(react): Convert cluster details to react CE (#466)

This commit is contained in:
James Player 2025-02-26 14:13:50 +13:00 committed by GitHub
parent dd98097897
commit 7759d762ab
24 changed files with 829 additions and 345 deletions

View file

@ -0,0 +1,45 @@
import { ResourceReservation } from '@/react/kubernetes/components/ResourceReservation';
import { ResourceQuotaFormValues } from './types';
import { useNamespaceResourceReservationData } from './useNamespaceResourceReservationData';
interface Props {
namespaceName: string;
environmentId: number;
resourceQuotaValues: ResourceQuotaFormValues;
}
export function NamespaceResourceReservation({
environmentId,
namespaceName,
resourceQuotaValues,
}: Props) {
const {
cpuLimit,
memoryLimit,
displayResourceUsage,
resourceUsage,
resourceReservation,
isLoading,
} = useNamespaceResourceReservationData(
environmentId,
namespaceName,
resourceQuotaValues
);
if (!resourceQuotaValues.enabled) {
return null;
}
return (
<ResourceReservation
displayResourceUsage={displayResourceUsage}
resourceReservation={resourceReservation}
resourceUsage={resourceUsage}
cpuLimit={cpuLimit}
memoryLimit={memoryLimit}
description="Resource reservation represents the total amount of resource assigned to all the applications deployed inside this namespace."
isLoading={isLoading}
/>
);
}

View file

@ -13,8 +13,8 @@ import { SliderWithInput } from '@@/form-components/Slider/SliderWithInput';
import { useClusterResourceLimitsQuery } from '../../../queries/useResourceLimitsQuery';
import { ResourceReservationUsage } from './ResourceReservationUsage';
import { ResourceQuotaFormValues } from './types';
import { NamespaceResourceReservation } from './NamespaceResourceReservation';
interface Props {
values: ResourceQuotaFormValues;
@ -128,7 +128,7 @@ export function ResourceQuotaFormSection({
</div>
)}
{namespaceName && isEdit && (
<ResourceReservationUsage
<NamespaceResourceReservation
namespaceName={namespaceName}
environmentId={environmentId}
resourceQuotaValues={values}

View file

@ -1,150 +0,0 @@
import { round } from 'lodash';
import { EnvironmentId } from '@/react/portainer/environments/types';
import { useMetricsForNamespace } from '@/react/kubernetes/metrics/queries/useMetricsForNamespace';
import { PodMetrics } from '@/react/kubernetes/metrics/types';
import { TextTip } from '@@/Tip/TextTip';
import { FormSectionTitle } from '@@/form-components/FormSectionTitle';
import { megaBytesValue, parseCPU } from '../../../resourceQuotaUtils';
import { ResourceUsageItem } from '../../ResourceUsageItem';
import { useResourceQuotaUsed } from './useResourceQuotaUsed';
import { ResourceQuotaFormValues } from './types';
export function ResourceReservationUsage({
namespaceName,
environmentId,
resourceQuotaValues,
}: {
namespaceName: string;
environmentId: EnvironmentId;
resourceQuotaValues: ResourceQuotaFormValues;
}) {
const namespaceMetricsQuery = useMetricsForNamespace(
environmentId,
namespaceName,
{
select: aggregatePodUsage,
}
);
const usedResourceQuotaQuery = useResourceQuotaUsed(
environmentId,
namespaceName
);
const { data: namespaceMetrics } = namespaceMetricsQuery;
const { data: usedResourceQuota } = usedResourceQuotaQuery;
const memoryQuota = Number(resourceQuotaValues.memory) ?? 0;
const cpuQuota = Number(resourceQuotaValues.cpu) ?? 0;
if (!resourceQuotaValues.enabled) {
return null;
}
return (
<>
<FormSectionTitle>Resource reservation</FormSectionTitle>
<TextTip color="blue" className="mb-2">
Resource reservation represents the total amount of resource assigned to
all the applications deployed inside this namespace.
</TextTip>
{!!usedResourceQuota && memoryQuota > 0 && (
<ResourceUsageItem
value={usedResourceQuota.memory}
total={getSafeValue(memoryQuota)}
label="Memory reservation"
annotation={`${usedResourceQuota.memory} / ${getSafeValue(
memoryQuota
)} MB ${getPercentageString(usedResourceQuota.memory, memoryQuota)}`}
/>
)}
{!!namespaceMetrics && memoryQuota > 0 && (
<ResourceUsageItem
value={namespaceMetrics.memory}
total={getSafeValue(memoryQuota)}
label="Memory used"
annotation={`${namespaceMetrics.memory} / ${getSafeValue(
memoryQuota
)} MB ${getPercentageString(namespaceMetrics.memory, memoryQuota)}`}
/>
)}
{!!usedResourceQuota && cpuQuota > 0 && (
<ResourceUsageItem
value={usedResourceQuota.cpu}
total={cpuQuota}
label="CPU reservation"
annotation={`${
usedResourceQuota.cpu
} / ${cpuQuota} ${getPercentageString(
usedResourceQuota.cpu,
cpuQuota
)}`}
/>
)}
{!!namespaceMetrics && cpuQuota > 0 && (
<ResourceUsageItem
value={namespaceMetrics.cpu}
total={cpuQuota}
label="CPU used"
annotation={`${
namespaceMetrics.cpu
} / ${cpuQuota} ${getPercentageString(
namespaceMetrics.cpu,
cpuQuota
)}`}
/>
)}
</>
);
}
function getSafeValue(value: number | string) {
const valueNumber = Number(value);
if (Number.isNaN(valueNumber)) {
return 0;
}
return valueNumber;
}
/**
* Returns the percentage of the value over the total.
* @param value - The value to calculate the percentage for.
* @param total - The total value to compare the percentage to.
* @returns The percentage of the value over the total, with the '- ' string prefixed, for example '- 50%'.
*/
function getPercentageString(value: number, total?: number | string) {
const totalNumber = Number(total);
if (
totalNumber === 0 ||
total === undefined ||
total === '' ||
Number.isNaN(totalNumber)
) {
return '';
}
if (value > totalNumber) {
return '- Exceeded';
}
return `- ${Math.round((value / totalNumber) * 100)}%`;
}
/**
* Aggregates the resource usage of all the containers in the namespace.
* @param podMetricsList - List of pod metrics
* @returns Aggregated resource usage. CPU cores are rounded to 3 decimal places. Memory is in MB.
*/
function aggregatePodUsage(podMetricsList: PodMetrics) {
const containerResourceUsageList = podMetricsList.items.flatMap((i) =>
i.containers.map((c) => c.usage)
);
const namespaceResourceUsage = containerResourceUsageList.reduce(
(total, usage) => ({
cpu: total.cpu + parseCPU(usage.cpu),
memory: total.memory + megaBytesValue(usage.memory),
}),
{ cpu: 0, memory: 0 }
);
namespaceResourceUsage.cpu = round(namespaceResourceUsage.cpu, 3);
return namespaceResourceUsage;
}

View file

@ -0,0 +1,65 @@
import { round } from 'lodash';
import { getSafeValue } from '@/react/kubernetes/utils';
import { PodMetrics } from '@/react/kubernetes/metrics/types';
import { useMetricsForNamespace } from '@/react/kubernetes/metrics/queries/useMetricsForNamespace';
import {
megaBytesValue,
parseCPU,
} from '@/react/kubernetes/namespaces/resourceQuotaUtils';
import { useResourceQuotaUsed } from './useResourceQuotaUsed';
import { ResourceQuotaFormValues } from './types';
export function useNamespaceResourceReservationData(
environmentId: number,
namespaceName: string,
resourceQuotaValues: ResourceQuotaFormValues
) {
const { data: quota, isLoading: isQuotaLoading } = useResourceQuotaUsed(
environmentId,
namespaceName
);
const { data: metrics, isLoading: isMetricsLoading } = useMetricsForNamespace(
environmentId,
namespaceName,
{
select: aggregatePodUsage,
}
);
return {
cpuLimit: Number(resourceQuotaValues.cpu) || 0,
memoryLimit: Number(resourceQuotaValues.memory) || 0,
displayResourceUsage: !!metrics,
resourceReservation: {
cpu: getSafeValue(quota?.cpu || 0),
memory: getSafeValue(quota?.memory || 0),
},
resourceUsage: {
cpu: getSafeValue(metrics?.cpu || 0),
memory: getSafeValue(metrics?.memory || 0),
},
isLoading: isQuotaLoading || isMetricsLoading,
};
}
/**
* Aggregates the resource usage of all the containers in the namespace.
* @param podMetricsList - List of pod metrics
* @returns Aggregated resource usage. CPU cores are rounded to 3 decimal places. Memory is in MB.
*/
function aggregatePodUsage(podMetricsList: PodMetrics) {
const containerResourceUsageList = podMetricsList.items.flatMap((i) =>
i.containers.map((c) => c.usage)
);
const namespaceResourceUsage = containerResourceUsageList.reduce(
(total, usage) => ({
cpu: total.cpu + parseCPU(usage.cpu),
memory: total.memory + megaBytesValue(usage.memory),
}),
{ cpu: 0, memory: 0 }
);
namespaceResourceUsage.cpu = round(namespaceResourceUsage.cpu, 3);
return namespaceResourceUsage;
}