diff --git a/src/renderer/components/+config-resource-quotas/resource-quota-details.tsx b/src/renderer/components/+config-resource-quotas/resource-quota-details.tsx index 6a2665e741..9efed1807b 100644 --- a/src/renderer/components/+config-resource-quotas/resource-quota-details.tsx +++ b/src/renderer/components/+config-resource-quotas/resource-quota-details.tsx @@ -4,7 +4,7 @@ import kebabCase from "lodash/kebabCase"; import { observer } from "mobx-react"; import { Trans } from "@lingui/macro"; import { DrawerItem, DrawerTitle } from "../drawer"; -import { cpuUnitsToNumber, cssNames, unitsToBytes } from "../../utils"; +import { cpuUnitsToNumber, cssNames, unitsToBytes, compactedUnitsToNumber } from "../../utils"; import { KubeObjectDetailsProps } from "../kube-object"; import { ResourceQuota, resourceQuotaApi } from "../../api/endpoints/resource-quota.api"; import { LineProgress } from "../line-progress"; @@ -15,24 +15,34 @@ import { KubeObjectMeta } from "../kube-object/kube-object-meta"; interface Props extends KubeObjectDetailsProps { } -@observer -export class ResourceQuotaDetails extends React.Component { - renderQuotas = (quota: ResourceQuota) => { - const { hard, used } = quota.status - if (!hard || !used) return null - const transformUnit = (name: string, value: string) => { - if (name.includes("memory") || name.includes("storage")) { - return unitsToBytes(value) - } - if (name.includes("cpu")) { - return cpuUnitsToNumber(value) - } - return parseInt(value) - } - return Object.entries(hard).map(([name, value]) => { - if (!used[name]) return null +const onlyNumbers = /$[0-9]*^/g; + +function transformUnit(name: string, value: string): number { + if (name.includes("memory") || name.includes("storage")) { + return unitsToBytes(value) + } + + if (name.includes("cpu")) { + return cpuUnitsToNumber(value) + } + + if (onlyNumbers.test(value)) { + return parseInt(value); + } + + return compactedUnitsToNumber(value); +} + +function renderQuotas(quota: ResourceQuota): JSX.Element[] { + const { hard = {}, used = {} } = quota.status + + return Object.entries(hard) + .filter(([name]) => used[name]) + .map(([name, value]) => { const current = transformUnit(name, used[name]) const max = transformUnit(name, value) + const usage = max === 0 ? 100 : Math.ceil(current / max * 100); // special case 0 max as always 100% usage + return (
{name} @@ -41,14 +51,16 @@ export class ResourceQuotaDetails extends React.Component { max={max} value={current} tooltip={ -

Set: {value}. Used: {Math.ceil(current / max * 100) + "%"}

+

Set: {value}. Usage: {usage + "%"}

} />
) }) - } +} +@observer +export class ResourceQuotaDetails extends React.Component { render() { const { object: quota } = this.props; if (!quota) return null; @@ -57,7 +69,7 @@ export class ResourceQuotaDetails extends React.Component { Quotas} className="quota-list"> - {this.renderQuotas(quota)} + {renderQuotas(quota)} {quota.getScopeSelector().length > 0 && ( diff --git a/src/renderer/utils/compactedUnitsToNumber.ts b/src/renderer/utils/compactedUnitsToNumber.ts new file mode 100644 index 0000000000..e8de630f0e --- /dev/null +++ b/src/renderer/utils/compactedUnitsToNumber.ts @@ -0,0 +1,10 @@ +const base = 1000; +const suffixes = ["k", "m", "g", "t", "q"]; + +export function compactedUnitsToNumber(value: string): number { + const justLetters = value.toLowerCase().replace(/[0-9]\./g, '')[0]; + const index = suffixes.indexOf(justLetters); + return parseInt( + (parseFloat(value) * Math.pow(base, index + 1)).toFixed(1) + ) +} diff --git a/src/renderer/utils/convertCpu.ts b/src/renderer/utils/convertCpu.ts index 2e7c6b85c3..7b81a30cc3 100644 --- a/src/renderer/utils/convertCpu.ts +++ b/src/renderer/utils/convertCpu.ts @@ -1,10 +1,13 @@ // Helper to convert CPU K8S units to numbers +const thousand = 1000; +const million = thousand * thousand; +const shortBillion = thousand * million; + export function cpuUnitsToNumber(cpu: string) { const cpuNum = parseInt(cpu) - const billion = 1000000 * 1000 - if (cpu.includes("m")) return cpuNum / 1000 - if (cpu.includes("u")) return cpuNum / 1000000 - if (cpu.includes("n")) return cpuNum / billion + if (cpu.includes("m")) return cpuNum / thousand + if (cpu.includes("u")) return cpuNum / million + if (cpu.includes("n")) return cpuNum / shortBillion return parseFloat(cpu) -} \ No newline at end of file +} diff --git a/src/renderer/utils/convertMemory.ts b/src/renderer/utils/convertMemory.ts index faa89dd990..9d6ca95e62 100644 --- a/src/renderer/utils/convertMemory.ts +++ b/src/renderer/utils/convertMemory.ts @@ -7,6 +7,7 @@ export function unitsToBytes(value: string) { if (!suffixes.some(suffix => value.includes(suffix))) { return parseFloat(value) } + const index = suffixes.findIndex(suffix => suffix == value.replace(/[0-9]|i|\./g, '') ) diff --git a/src/renderer/utils/index.ts b/src/renderer/utils/index.ts index 8a3a263077..2c422c7867 100755 --- a/src/renderer/utils/index.ts +++ b/src/renderer/utils/index.ts @@ -20,3 +20,4 @@ export * from './formatDuration' export * from './isReactNode' export * from './convertMemory' export * from './convertCpu' +export * from './compactedUnitsToNumber'