Skip to content

Commit 9a313ac

Browse files
reactor: STORIF-285 - Quota resource metric converted into an enum.
1 parent 573ad61 commit 9a313ac

13 files changed

Lines changed: 107 additions & 92 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 & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { type Quota, 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';
@@ -22,8 +23,6 @@ import { objectStorageEndpointsFactory } from 'src/factories';
2223
import { quotaFactory, quotaUsageFactory } from 'src/factories/quotas';
2324
import { getQuotaIncreaseMessage } from 'src/features/Account/Quotas/utils';
2425

25-
import type { Quota } from '@linode/api-v4';
26-
2726
const mockFeatureFlags = {
2827
limitsEvolution: {
2928
enabled: true,
@@ -74,7 +73,7 @@ const mockQuotas = [
7473
endpoint_type: mockSelectedEndpoint.endpoint_type,
7574
quota_limit: 10,
7675
quota_name: randomLabel(15),
77-
resource_metric: 'byte',
76+
resource_metric: QuotaResourceMetrics.BYTE,
7877
s3_endpoint: selectedDomain,
7978
}),
8079
quotaFactory.build({
@@ -84,7 +83,7 @@ const mockQuotas = [
8483
endpoint_type: mockSelectedEndpoint.endpoint_type,
8584
quota_limit: 78,
8685
quota_name: randomLabel(15),
87-
resource_metric: 'bucket',
86+
resource_metric: QuotaResourceMetrics.BUCKET,
8887
s3_endpoint: selectedDomain,
8988
}),
9089
quotaFactory.build({
@@ -94,7 +93,7 @@ const mockQuotas = [
9493
endpoint_type: mockSelectedEndpoint.endpoint_type,
9594
quota_limit: 400,
9695
quota_name: randomLabel(15),
97-
resource_metric: 'object',
96+
resource_metric: QuotaResourceMetrics.OBJECT,
9897
s3_endpoint: selectedDomain,
9998
}),
10099
];
@@ -229,7 +228,7 @@ describe('Quota workflow tests', () => {
229228
endpoint_type: updatedEndpoint.endpoint_type,
230229
quota_limit: 20,
231230
quota_name: randomLabel(15),
232-
resource_metric: 'byte',
231+
resource_metric: QuotaResourceMetrics.BYTE,
233232
s3_endpoint: updatedDomain,
234233
}),
235234
quotaFactory.build({
@@ -239,7 +238,7 @@ describe('Quota workflow tests', () => {
239238
endpoint_type: updatedEndpoint.endpoint_type,
240239
quota_limit: 122,
241240
quota_name: randomLabel(15),
242-
resource_metric: 'bucket',
241+
resource_metric: QuotaResourceMetrics.BUCKET,
243242
s3_endpoint: updatedDomain,
244243
}),
245244
quotaFactory.build({
@@ -249,7 +248,7 @@ describe('Quota workflow tests', () => {
249248
endpoint_type: updatedEndpoint.endpoint_type,
250249
quota_limit: 450,
251250
quota_name: randomLabel(15),
252-
resource_metric: 'object',
251+
resource_metric: QuotaResourceMetrics.OBJECT,
253252
s3_endpoint: updatedDomain,
254253
}),
255254
];

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: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1+
import {
2+
type Quota,
3+
QuotaResourceMetrics,
4+
type QuotaUsage,
5+
} from '@linode/api-v4/lib/quotas/types';
16
import { Factory } from '@linode/utilities';
27

3-
import type { Quota, QuotaUsage } from '@linode/api-v4/lib/quotas/types';
4-
58
export const quotaFactory = Factory.Sync.makeFactory<Quota>({
69
description: 'Maximimum number of vCPUs allowed',
710
quota_id: Factory.each((id) => id.toString()),
811
quota_limit: 50,
912
quota_name: 'Linode Dedicated vCPUs',
1013
quota_type: 'linode-dedicated-cpus',
1114
region_applied: 'us-east',
12-
resource_metric: 'CPU',
15+
resource_metric: QuotaResourceMetrics.CPU,
1316
has_usage: true,
1417
});
1518

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 & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { QuotaResourceMetrics, type QuotaUsage } 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';
@@ -13,7 +14,6 @@ import {
1314
useGetLocationsForQuotaService,
1415
} from './utils';
1516

16-
import type { QuotaUsage } from '@linode/api-v4';
1717
import type { UseQueryResult } from '@tanstack/react-query';
1818

1919
const queryMocks = vi.hoisted(() => ({
@@ -133,7 +133,7 @@ describe('useGetLocationsForQuotaService', () => {
133133

134134
describe('convertResourceMetric', () => {
135135
it('should convert the resource metric to a human readable format', () => {
136-
const resourceMetric = 'byte';
136+
const resourceMetric = QuotaResourceMetrics.BYTE;
137137
const usage = 1e6;
138138
const limit = 1e8;
139139

@@ -154,7 +154,7 @@ describe('convertResourceMetric', () => {
154154
describe('pluralizeMetric', () => {
155155
it('should not pluralize if the value is 1', () => {
156156
const value = 1;
157-
const unit = 'CPU';
157+
const unit = QuotaResourceMetrics.CPU;
158158

159159
const result = pluralizeMetric(value, unit);
160160

@@ -163,7 +163,7 @@ describe('pluralizeMetric', () => {
163163

164164
it('should not pluralize the resource metric if the unit is byte', () => {
165165
const value = 100;
166-
const unit = 'byte';
166+
const unit = QuotaResourceMetrics.BYTE;
167167

168168
const result = pluralizeMetric(value, unit);
169169

@@ -172,7 +172,7 @@ describe('pluralizeMetric', () => {
172172

173173
it('should pluralize the resource metric if the unit is not byte', () => {
174174
const value = 100;
175-
const unit = 'CPU';
175+
const unit = QuotaResourceMetrics.CPU;
176176

177177
const result = pluralizeMetric(value, unit);
178178

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

Lines changed: 13 additions & 15 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,19 +234,19 @@ export const convertResourceMetric = ({
233234
convertedResourceMetric: string;
234235
convertedUsage: number;
235236
} => {
236-
if (initialResourceMetric === 'byte') {
237+
if (initialResourceMetric === QuotaResourceMetrics.BYTE) {
237238
const limitReadable = readableBytes(initialLimit);
238239

239240
return {
240241
convertedUsage: readableBytes(initialUsage, {
241242
unit: limitReadable.unit,
242243
}).value,
243-
convertedResourceMetric: capitalize(limitReadable.unit),
244244
convertedLimit: limitReadable.value,
245+
convertedResourceMetric: capitalize(limitReadable.unit),
245246
};
246247
}
247248

248-
if (initialResourceMetric === 'byte_per_second') {
249+
if (initialResourceMetric === QuotaResourceMetrics.BYTE_PER_SECOND) {
249250
return {
250251
convertedUsage: 0,
251252
convertedResourceMetric: 'Gbps',
@@ -259,7 +260,9 @@ export const convertResourceMetric = ({
259260
return {
260261
convertedUsage: initialUsage,
261262
convertedLimit: initialLimit,
262-
convertedResourceMetric: capitalize(initialResourceMetric),
263+
convertedResourceMetric: capitalize(
264+
pluralizeMetric(initialLimit, initialResourceMetric)
265+
),
263266
};
264267
};
265268

@@ -270,16 +273,11 @@ export const convertResourceMetric = ({
270273
*
271274
* Note: the value should be the raw values in bytes, not an existing conversion
272275
*/
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;
276+
export const pluralizeMetric = (
277+
value: number,
278+
unit: QuotaResourceMetrics
279+
): string => {
280+
return value > 1 ? `${unit}s` : unit;
283281
};
284282

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

0 commit comments

Comments
 (0)