Skip to content

Commit bf4087d

Browse files
reactor: STORIF-285 - Quota resource metric converted into an enum.
1 parent 7bf9ed9 commit bf4087d

13 files changed

Lines changed: 101 additions & 91 deletions

File tree

packages/api-v4/src/quotas/types.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
import type { ObjectStorageEndpointTypes } from 'src/object-storage';
22
import type { Region } from 'src/regions';
3+
4+
export enum QuotaResourceMetrics {
5+
BUCKET = 'bucket',
6+
BYTE = 'byte',
7+
BYTE_PER_SECOND = 'byte_per_second',
8+
CLUSTER = 'cluster',
9+
CPU = 'CPU',
10+
GPU = 'GPU',
11+
OBJECT = 'object',
12+
REQUEST = 'request',
13+
VPU = 'VPU',
14+
}
15+
316
/**
417
* A Quota is a service used limit that is rated based on service metrics such
518
* as vCPUs used, instances or storage size.
@@ -54,7 +67,7 @@ export interface Quota {
5467
/**
5568
* The unit of measurement for this service limit.
5669
*/
57-
resource_metric: string;
70+
resource_metric: QuotaResourceMetrics;
5871

5972
/**
6073
* The S3 endpoint URL to which this limit applies.

packages/manager/cypress/e2e/core/account/quotas-storage.spec.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { QuotaResourceMetrics } from '@linode/api-v4';
12
import { regionFactory } from '@linode/utilities';
23
import { profileFactory } from '@linode/utilities';
34
import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags';
@@ -74,7 +75,7 @@ const mockQuotas = [
7475
endpoint_type: mockSelectedEndpoint.endpoint_type,
7576
quota_limit: 10,
7677
quota_name: randomLabel(15),
77-
resource_metric: 'byte',
78+
resource_metric: QuotaResourceMetrics.BYTE,
7879
s3_endpoint: selectedDomain,
7980
}),
8081
quotaFactory.build({
@@ -84,7 +85,7 @@ const mockQuotas = [
8485
endpoint_type: mockSelectedEndpoint.endpoint_type,
8586
quota_limit: 78,
8687
quota_name: randomLabel(15),
87-
resource_metric: 'bucket',
88+
resource_metric: QuotaResourceMetrics.BUCKET,
8889
s3_endpoint: selectedDomain,
8990
}),
9091
quotaFactory.build({
@@ -94,7 +95,7 @@ const mockQuotas = [
9495
endpoint_type: mockSelectedEndpoint.endpoint_type,
9596
quota_limit: 400,
9697
quota_name: randomLabel(15),
97-
resource_metric: 'object',
98+
resource_metric: QuotaResourceMetrics.OBJECT,
9899
s3_endpoint: selectedDomain,
99100
}),
100101
];
@@ -229,7 +230,7 @@ describe('Quota workflow tests', () => {
229230
endpoint_type: updatedEndpoint.endpoint_type,
230231
quota_limit: 20,
231232
quota_name: randomLabel(15),
232-
resource_metric: 'byte',
233+
resource_metric: QuotaResourceMetrics.BYTE,
233234
s3_endpoint: updatedDomain,
234235
}),
235236
quotaFactory.build({
@@ -239,7 +240,7 @@ describe('Quota workflow tests', () => {
239240
endpoint_type: updatedEndpoint.endpoint_type,
240241
quota_limit: 122,
241242
quota_name: randomLabel(15),
242-
resource_metric: 'bucket',
243+
resource_metric: QuotaResourceMetrics.BUCKET,
243244
s3_endpoint: updatedDomain,
244245
}),
245246
quotaFactory.build({
@@ -249,7 +250,7 @@ describe('Quota workflow tests', () => {
249250
endpoint_type: updatedEndpoint.endpoint_type,
250251
quota_limit: 450,
251252
quota_name: randomLabel(15),
252-
resource_metric: 'object',
253+
resource_metric: QuotaResourceMetrics.OBJECT,
253254
s3_endpoint: updatedDomain,
254255
}),
255256
];

packages/manager/cypress/e2e/core/objectStorage/object-storage-summary-page.spec.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { QuotaResourceMetrics } from '@linode/api-v4';
12
import { regionFactory } from '@linode/utilities';
23
import { authenticate } from 'support/api/authentication';
34
import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags';
@@ -58,7 +59,7 @@ const mockQuotas = [
5859
endpoint_type: mockSelectedEndpoint.endpoint_type,
5960
quota_limit: 10,
6061
quota_name: 'Total Capacity',
61-
resource_metric: 'byte',
62+
resource_metric: QuotaResourceMetrics.BYTE,
6263
s3_endpoint: selectedDomain,
6364
}),
6465
quotaFactory.build({
@@ -68,7 +69,7 @@ const mockQuotas = [
6869
endpoint_type: mockSelectedEndpoint.endpoint_type,
6970
quota_limit: 78,
7071
quota_name: 'Number of Objects',
71-
resource_metric: 'bucket',
72+
resource_metric: QuotaResourceMetrics.BUCKET,
7273
s3_endpoint: selectedDomain,
7374
}),
7475
quotaFactory.build({
@@ -78,7 +79,7 @@ const mockQuotas = [
7879
endpoint_type: mockSelectedEndpoint.endpoint_type,
7980
quota_limit: 400,
8081
quota_name: 'Number of Buckets',
81-
resource_metric: 'object',
82+
resource_metric: QuotaResourceMetrics.OBJECT,
8283
s3_endpoint: selectedDomain,
8384
}),
8485
];

packages/manager/src/components/QuotaUsageBar/QuotaUsageBar.test.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { QuotaResourceMetrics } from '@linode/api-v4';
12
import React from 'react';
23

34
import { renderWithTheme } from 'src/utilities/testHelpers';
@@ -43,7 +44,11 @@ describe('QuotaUsageBanner', () => {
4344
'should display correct byte quota usage text for $usage bytes used out of $limit bytes',
4445
({ usage, limit, expectedText }) => {
4546
const { getByText } = renderWithTheme(
46-
<QuotaUsageBar limit={limit} resourceMetric="byte" usage={usage} />
47+
<QuotaUsageBar
48+
limit={limit}
49+
resourceMetric={QuotaResourceMetrics.BYTE}
50+
usage={usage}
51+
/>
4752
);
4853
const quotaUsageText = getByText(expectedText);
4954
expect(quotaUsageText).toBeVisible();

packages/manager/src/components/QuotaUsageBar/QuotaUsageBar.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@ import { Typography, useTheme } from '@linode/ui';
22
import * as React from 'react';
33

44
import { BarPercent } from 'src/components/BarPercent';
5-
import {
6-
convertResourceMetric,
7-
pluralizeMetric,
8-
} from 'src/features/Account/Quotas/utils';
5+
import { convertResourceMetric } from 'src/features/Account/Quotas/utils';
6+
7+
import type { QuotaResourceMetrics } from '@linode/api-v4';
98

109
interface Props {
1110
limit: number;
12-
resourceMetric: string;
11+
resourceMetric: QuotaResourceMetrics;
1312
usage: number;
1413
}
1514

@@ -18,7 +17,7 @@ export const QuotaUsageBar = ({ limit, usage, resourceMetric }: Props) => {
1817

1918
const { convertedUsage, convertedLimit, convertedResourceMetric } =
2019
convertResourceMetric({
21-
initialResourceMetric: pluralizeMetric(limit, resourceMetric),
20+
initialResourceMetric: resourceMetric,
2221
initialUsage: usage,
2322
initialLimit: limit,
2423
});

packages/manager/src/factories/quotas.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { QuotaResourceMetrics } from '@linode/api-v4/lib/quotas/types';
12
import { Factory } from '@linode/utilities';
23

34
import type { Quota, QuotaUsage } from '@linode/api-v4/lib/quotas/types';
@@ -9,7 +10,7 @@ export const quotaFactory = Factory.Sync.makeFactory<Quota>({
910
quota_name: 'Linode Dedicated vCPUs',
1011
quota_type: 'linode-dedicated-cpus',
1112
region_applied: 'us-east',
12-
resource_metric: 'CPU',
13+
resource_metric: QuotaResourceMetrics.CPU,
1314
has_usage: true,
1415
});
1516

packages/manager/src/features/Account/Quotas/QuotasTable/QuotasTable.test.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { QuotaResourceMetrics } from '@linode/api-v4';
12
import { waitFor } from '@testing-library/react';
23
import * as React from 'react';
34

@@ -131,7 +132,7 @@ describe('QuotasTable', () => {
131132
'Current total ingress bandwidth per account, per endpoint',
132133
quota_limit: 1250000000,
133134
quota_type: 'obj-total-ingress-throughput',
134-
resource_metric: 'byte_per_second',
135+
resource_metric: QuotaResourceMetrics.BYTE_PER_SECOND,
135136
has_usage: false,
136137
}),
137138
],

packages/manager/src/features/Account/Quotas/QuotasTable/QuotasTableRow.tsx

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,7 @@ import { TableRow } from 'src/components/TableRow/TableRow';
99
import { useFlags } from 'src/hooks/useFlags';
1010
import { useIsAkamaiAccount } from 'src/hooks/useIsAkamaiAccount';
1111

12-
import {
13-
convertResourceMetric,
14-
getQuotaError,
15-
pluralizeMetric,
16-
} from '../utils';
12+
import { convertResourceMetric, getQuotaError } from '../utils';
1713

1814
import type { QuotaWithUsage } from '../utils';
1915
import type { Quota, QuotaUsage } from '@linode/api-v4';
@@ -58,10 +54,7 @@ export const QuotasTableRow = (props: QuotasTableRowProps) => {
5854
isAkamaiAccount);
5955

6056
const { convertedLimit, convertedResourceMetric } = convertResourceMetric({
61-
initialResourceMetric: pluralizeMetric(
62-
quota.quota_limit,
63-
quota.resource_metric
64-
),
57+
initialResourceMetric: quota.resource_metric,
6558
initialUsage: quota.usage?.usage ?? 0,
6659
initialLimit: quota.quota_limit,
6760
});

packages/manager/src/features/Account/Quotas/utils.test.tsx

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { QuotaResourceMetrics } from '@linode/api-v4';
12
import { profileFactory } from '@linode/utilities';
23
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
34
import { renderHook } from '@testing-library/react';
@@ -133,7 +134,7 @@ describe('useGetLocationsForQuotaService', () => {
133134

134135
describe('convertResourceMetric', () => {
135136
it('should convert the resource metric to a human readable format', () => {
136-
const resourceMetric = 'byte';
137+
const resourceMetric = QuotaResourceMetrics.BYTE;
137138
const usage = 1e6;
138139
const limit = 1e8;
139140

@@ -154,25 +155,16 @@ describe('convertResourceMetric', () => {
154155
describe('pluralizeMetric', () => {
155156
it('should not pluralize if the value is 1', () => {
156157
const value = 1;
157-
const unit = 'CPU';
158+
const unit = QuotaResourceMetrics.CPU;
158159

159160
const result = pluralizeMetric(value, unit);
160161

161162
expect(result).toEqual('CPU');
162163
});
163164

164-
it('should not pluralize the resource metric if the unit is byte', () => {
165+
it('should pluralize the resource metric if the value is greater than 1', () => {
165166
const value = 100;
166-
const unit = 'byte';
167-
168-
const result = pluralizeMetric(value, unit);
169-
170-
expect(result).toEqual('byte');
171-
});
172-
173-
it('should pluralize the resource metric if the unit is not byte', () => {
174-
const value = 100;
175-
const unit = 'CPU';
167+
const unit = QuotaResourceMetrics.CPU;
176168

177169
const result = pluralizeMetric(value, unit);
178170

packages/manager/src/features/Account/Quotas/utils.ts

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { QuotaResourceMetrics } from '@linode/api-v4';
12
import { useRegionsQuery } from '@linode/queries';
23
import { capitalize, readableBytes } from '@linode/utilities';
34
import { object, string } from 'yup';
@@ -217,7 +218,7 @@ export const getQuotaIncreaseMessage = ({
217218

218219
interface ConvertResourceMetricProps {
219220
initialLimit: number;
220-
initialResourceMetric: string;
221+
initialResourceMetric: QuotaResourceMetrics;
221222
initialUsage: number;
222223
}
223224

@@ -233,34 +234,38 @@ export const convertResourceMetric = ({
233234
convertedResourceMetric: string;
234235
convertedUsage: number;
235236
} => {
236-
if (initialResourceMetric === 'byte') {
237-
const limitReadable = readableBytes(initialLimit);
237+
switch (initialResourceMetric) {
238+
case QuotaResourceMetrics.BYTE: {
239+
const limitReadable = readableBytes(initialLimit);
238240

239-
return {
240-
convertedUsage: readableBytes(initialUsage, {
241-
unit: limitReadable.unit,
242-
}).value,
243-
convertedResourceMetric: capitalize(limitReadable.unit),
244-
convertedLimit: limitReadable.value,
245-
};
246-
}
247-
248-
if (initialResourceMetric === 'byte_per_second') {
249-
return {
250-
convertedUsage: 0,
251-
convertedResourceMetric: 'Gbps',
252-
convertedLimit: readableBytes(initialLimit * 8, {
253-
unit: 'GB',
254-
base10: true,
255-
}).value,
256-
};
241+
return {
242+
convertedUsage: readableBytes(initialUsage, {
243+
unit: limitReadable.unit,
244+
}).value,
245+
convertedLimit: limitReadable.value,
246+
convertedResourceMetric: capitalize(limitReadable.unit),
247+
};
248+
}
249+
case QuotaResourceMetrics.BYTE_PER_SECOND: {
250+
return {
251+
convertedUsage: 0,
252+
convertedResourceMetric: 'Gbps',
253+
convertedLimit: readableBytes(initialLimit * 8, {
254+
unit: 'GB',
255+
base10: true,
256+
}).value,
257+
};
258+
}
259+
default: {
260+
return {
261+
convertedUsage: initialUsage,
262+
convertedLimit: initialLimit,
263+
convertedResourceMetric: capitalize(
264+
pluralizeMetric(initialLimit, initialResourceMetric)
265+
),
266+
};
267+
}
257268
}
258-
259-
return {
260-
convertedUsage: initialUsage,
261-
convertedLimit: initialLimit,
262-
convertedResourceMetric: capitalize(initialResourceMetric),
263-
};
264269
};
265270

266271
/**
@@ -270,16 +275,11 @@ export const convertResourceMetric = ({
270275
*
271276
* Note: the value should be the raw values in bytes, not an existing conversion
272277
*/
273-
export const pluralizeMetric = (value: number, unit: string) => {
274-
if (unit === 'byte_per_second') {
275-
return unit;
276-
}
277-
278-
if (unit !== 'byte') {
279-
return value > 1 ? `${unit}s` : unit;
280-
}
281-
282-
return unit;
278+
export const pluralizeMetric = (
279+
value: number,
280+
unit: QuotaResourceMetrics
281+
): string => {
282+
return value > 1 ? `${unit}s` : unit;
283283
};
284284

285285
export const getQuotaIncreaseFormSchema = (currentLimit: number) =>

0 commit comments

Comments
 (0)