Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 22 additions & 16 deletions packages/api-v4/src/quotas/quotas.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,48 @@
import { BETA_API_ROOT } from '../constants';
import Request, { setMethod, setParams, setURL, setXFilter } from '../request';

import type { Quota, QuotaType, QuotaUsage } from './types';
import type { Quota, QuotaServiceType, QuotaUsage } from './types';
import type { Filter, ResourcePage as Page, Params } from 'src/types';

/**
* getQuota
*
* Returns the details for a single quota within a particular service specified by `type`.
*
* @param type { QuotaType } retrieve a quota within this service type.
* @param quotaService { QuotaServiceType } retrieve a quota within this service type.
* @param id { number } the quota ID to look up.
* @param collection { string } quota collection name (quotas/global-quotas).
* @param apiCollection { string } quota collection name (quotas/global-quotas).
*/
export const getQuota = (type: QuotaType, collection: string, id: number) =>
export const getQuota = (
quotaService: QuotaServiceType,
apiCollection: string,
id: number,
) =>
Request<Quota>(
setURL(`${BETA_API_ROOT}/${type}/${collection}/${id}`),
setURL(`${BETA_API_ROOT}/${quotaService}/${apiCollection}/${id}`),
setMethod('GET'),
);

/**
* getQuotas
*
* Returns a paginated list of quotas for a particular service specified by `type`.
* Returns a paginated list of quotas for a particular service specified by `quotaService`.
*
* This request can be filtered on `quota_name`, `service_name` and `scope`.
*
* @param type { QuotaType } retrieve quotas within this service type.
* @param collection { string } quota collection name (quotas/global-quotas).
* @param quotaService { QuotaServiceType } retrieve quotas within this service quotaService.
* @param apiCollection { string } quota API collection name (e.g. quotas, global-quotas, etc.).
* @param params { Params } query params to include in the request.
* @param filter { Filter } filters to include in the request.
*/
export const getQuotas = (
type: QuotaType,
collection: string,
quotaService: QuotaServiceType,
apiCollection: string,
params: Params = {},
filter: Filter = {},
) =>
Request<Page<Quota>>(
setURL(`${BETA_API_ROOT}/${type}/${collection}`),
setURL(`${BETA_API_ROOT}/${quotaService}/${apiCollection}`),
setMethod('GET'),
setXFilter(filter),
setParams(params),
Expand All @@ -47,16 +53,16 @@ export const getQuotas = (
*
* Returns the usage for a single quota within a particular service specified by `type`.
*
* @param type { QuotaType } retrieve a quota within this service type.
* @param collection { string } quota collection name (quotas/global-quotas).
* @param quotaService { QuotaServiceType } retrieve a quota within this service type.
* @param apiCollection { string } quota collection name (quotas/global-quotas).
* @param id { string } the quota ID to look up.
*/
export const getQuotaUsage = (
type: QuotaType,
collection: string,
quotaService: QuotaServiceType,
apiCollection: string,
id: string,
) =>
Request<QuotaUsage>(
setURL(`${BETA_API_ROOT}/${type}/${collection}/${id}/usage`),
setURL(`${BETA_API_ROOT}/${quotaService}/${apiCollection}/${id}/usage`),
setMethod('GET'),
);
113 changes: 71 additions & 42 deletions packages/api-v4/src/quotas/types.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,22 @@
import type { ObjectStorageEndpointTypes } from 'src/object-storage';
import type { Region } from 'src/regions';

export enum QuotaResourceMetrics {
BUCKET = 'bucket',
BYTE = 'byte',
BYTE_PER_SECOND = 'byte_per_second',
CLUSTER = 'cluster',
CPU = 'CPU',
GPU = 'GPU',
OBJECT = 'object',
REQUEST = 'request',
VPU = 'VPU',
}
export type LinodeQuotaResourceMetric = 'CPU' | 'GPU' | 'VPU';
export type LkeQuotaResourceMetric = 'cluster';
export type ObjectStorageEndpointQuotaResourceMetric =
| 'bucket'
| 'byte'
| 'byte_per_second'
| 'object'
| 'request';
export type ObjectStorageGlobalQuotaResourceMetric = 'key';

/**
* A Quota is a service used limit that is rated based on service metrics such
* as vCPUs used, instances or storage size.
*/
export interface Quota {
interface QuotaCommon<T> {
/**
* Longer explanatory description for the quota.
*/
description: string;

/**
* The OBJ endpoint type to which this limit applies.
*
* For OBJ limits only.
*/
endpoint_type?: ObjectStorageEndpointTypes;

/**
* Sets usage column to be n/a when value is false.
*/
has_usage?: boolean;

/**
* A unique identifier for the quota.
*/
Expand All @@ -52,31 +34,80 @@ export interface Quota {
quota_name: string;

/**
* Customer facing id describing the quota.
* The unit of measurement for this service limit.
*/
quota_type: string;
resource_metric: T;
}

interface QuotaCommonWithRegionApplied<T> extends QuotaCommon<T> {
/**
* The region slug to which this limit applies.
*
* OBJ limits are applied by endpoint, not region.
* This below really just is a `string` type but being verbose helps with reading comprehension.
*/
region_applied?: 'global' | Region['id'];
region_applied: 'global' | Region['id'];
}

interface QuotaCommonWithUsage<T> extends QuotaCommon<T> {
/**
* The unit of measurement for this service limit.
* Determines whether usage information is provided for this quota.
*/
has_usage: boolean;
}

export type LinodeQuota =
QuotaCommonWithRegionApplied<LinodeQuotaResourceMetric>;

export type LkeQuota = QuotaCommonWithRegionApplied<LkeQuotaResourceMetric>;

export interface ObjectStorageGlobalQuota
extends QuotaCommon<ObjectStorageGlobalQuotaResourceMetric> {
/**
* Represents the quota type.
*/
quota_type: 'keys';
}

export interface ObjectStorageEndpointQuota
extends QuotaCommonWithUsage<ObjectStorageEndpointQuotaResourceMetric> {
/**
* The OBJ endpoint type to which this limit applies.
*
*/
endpoint_type: ObjectStorageEndpointTypes;

/**
* Represents the quota type.
*/
resource_metric: QuotaResourceMetrics;
quota_type:
| 'obj-buckets'
| 'obj-bytes'
| 'obj-objects'
| 'obj-per-ip-concurrent-requests'
| 'obj-per-ip-egress-throughput'
| 'obj-per-ip-ingress-throughput'
| 'obj-total-concurrent-requests'
| 'obj-total-egress-throughput'
| 'obj-total-ingress-throughput';

/**
* The S3 endpoint URL to which this limit applies.
*
* For OBJ limits only.
*/
s3_endpoint?: string;
s3_endpoint: string;
}

/**
* A Quota is a service used limit that is rated based on service metrics such
* as vCPUs used, instances or storage size.
*/
export type Quota =
| LinodeQuota
| LkeQuota
| ObjectStorageEndpointQuota
| ObjectStorageGlobalQuota;

/**
* A usage limit for a given Quota based on service metrics such
* as vCPUs, instances or storage size.
Expand All @@ -97,10 +128,8 @@ export interface QuotaUsage {
usage: null | number;
}

export const quotaTypes = {
linode: 'Linodes',
lke: 'Kubernetes',
'object-storage': 'Object Storage',
} as const;

export type QuotaType = keyof typeof quotaTypes;
/**
* Represents the type of service for a given quota, e.g. Linodes, Object Storage, etc.
* The type must match the service part of the quota endpoint paths.
*/
export type QuotaServiceType = 'linode' | 'lke' | 'object-storage';
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { randomDomainName, randomLabel } from 'support/util/random';

import { supportTicketFactory } from 'src/factories';
import { objectStorageEndpointsFactory } from 'src/factories';
import { quotaFactory, quotaUsageFactory } from 'src/factories/quotas';
import { linodeQuotaFactory, quotaUsageFactory } from 'src/factories/quotas';
import { getQuotaIncreaseMessage } from 'src/features/Account/Quotas/utils';

import type { Quota } from '@linode/api-v4';
Expand Down Expand Up @@ -68,7 +68,7 @@ const mockSelectedEndpoint = mockEndpoints[1];
const selectedDomain = mockSelectedEndpoint.s3_endpoint || '';

const mockQuotas = [
quotaFactory.build({
linodeQuotaFactory.build({
quota_id: `obj-bytes-${selectedDomain}`,
quota_type: 'obj-bytes',
description: randomLabel(50),
Expand All @@ -78,7 +78,7 @@ const mockQuotas = [
resource_metric: QuotaResourceMetrics.BYTE,
s3_endpoint: selectedDomain,
}),
quotaFactory.build({
linodeQuotaFactory.build({
quota_id: `obj-buckets-${selectedDomain}`,
quota_type: 'obj-buckets',
description: randomLabel(50),
Expand All @@ -88,7 +88,7 @@ const mockQuotas = [
resource_metric: QuotaResourceMetrics.BUCKET,
s3_endpoint: selectedDomain,
}),
quotaFactory.build({
linodeQuotaFactory.build({
quota_id: `obj-objects-${selectedDomain}`,
quota_type: 'obj-objects',
description: randomLabel(50),
Expand Down Expand Up @@ -223,7 +223,7 @@ describe('Quota workflow tests', () => {
const updatedEndpoint = mockEndpoints[mockEndpoints.length - 1];
const updatedDomain = updatedEndpoint.s3_endpoint || '';
const updatedQuotas = [
quotaFactory.build({
linodeQuotaFactory.build({
quota_id: `obj-bytes-${updatedDomain}`,
quota_type: 'obj-bytes',
description: randomLabel(50),
Expand All @@ -233,7 +233,7 @@ describe('Quota workflow tests', () => {
resource_metric: QuotaResourceMetrics.BYTE,
s3_endpoint: updatedDomain,
}),
quotaFactory.build({
linodeQuotaFactory.build({
quota_id: `obj-buckets-${updatedDomain}`,
quota_type: 'obj-buckets',
description: randomLabel(50),
Expand All @@ -243,7 +243,7 @@ describe('Quota workflow tests', () => {
resource_metric: QuotaResourceMetrics.BUCKET,
s3_endpoint: updatedDomain,
}),
quotaFactory.build({
linodeQuotaFactory.build({
quota_id: `obj-objects-${updatedDomain}`,
quota_type: 'obj-objects',
description: randomLabel(50),
Expand Down Expand Up @@ -422,7 +422,7 @@ describe('Quota workflow tests', () => {
profile: mockProfile,
quantity: expectedResults[index].newQuotaLimit,
quota: mockQuota,
selectedService: {
service: {
label: 'Object Storage',
value: 'object-storage',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { ui } from 'support/ui';
import { randomDomainName, randomLabel } from 'support/util/random';

import { objectStorageEndpointsFactory } from 'src/factories';
import { quotaFactory, quotaUsageFactory } from 'src/factories/quotas';
import { linodeQuotaFactory, quotaUsageFactory } from 'src/factories/quotas';

const mockFeatureFlags = {
objSummaryPage: true,
Expand Down Expand Up @@ -52,7 +52,7 @@ const mockSelectedEndpoint = mockEndpoints[1];
const selectedDomain = mockSelectedEndpoint.s3_endpoint || '';

const mockQuotas = [
quotaFactory.build({
linodeQuotaFactory.build({
quota_id: `obj-bytes-${selectedDomain}`,
quota_type: 'obj-bytes',
description: randomLabel(50),
Expand All @@ -62,7 +62,7 @@ const mockQuotas = [
resource_metric: QuotaResourceMetrics.BYTE,
s3_endpoint: selectedDomain,
}),
quotaFactory.build({
linodeQuotaFactory.build({
quota_id: `obj-buckets-${selectedDomain}`,
quota_type: 'obj-buckets',
description: randomLabel(50),
Expand All @@ -72,7 +72,7 @@ const mockQuotas = [
resource_metric: QuotaResourceMetrics.BUCKET,
s3_endpoint: selectedDomain,
}),
quotaFactory.build({
linodeQuotaFactory.build({
quota_id: `obj-objects-${selectedDomain}`,
quota_type: 'obj-objects',
description: randomLabel(50),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { QuotaResourceMetrics } from '@linode/api-v4';
import React from 'react';

import { renderWithTheme } from 'src/utilities/testHelpers';
Expand Down Expand Up @@ -44,9 +43,9 @@
'should display correct byte quota usage text for $usage bytes used out of $limit bytes',
({ usage, limit, expectedText }) => {
const { getByText } = renderWithTheme(
<QuotaUsageBar

Check warning on line 46 in packages/manager/src/components/QuotaUsageBar/QuotaUsageBar.test.tsx

View workflow job for this annotation

GitHub Actions / ESLint Review (manager)

[eslint] reported by reviewdog 🐶 Replace `⏎··········limit={limit}⏎··········resourceMetric='byte'⏎··········usage={usage}⏎·······` with `·limit={limit}·resourceMetric="byte"·usage={usage}` Raw Output: {"ruleId":"prettier/prettier","severity":1,"message":"Replace `⏎··········limit={limit}⏎··········resourceMetric='byte'⏎··········usage={usage}⏎·······` with `·limit={limit}·resourceMetric=\"byte\"·usage={usage}`","line":46,"column":23,"nodeType":null,"messageId":"replace","endLine":50,"endColumn":8,"fix":{"range":[1270,1358],"text":" limit={limit} resourceMetric=\"byte\" usage={usage}"}}
limit={limit}
resourceMetric={QuotaResourceMetrics.BYTE}
resourceMetric='byte'
usage={usage}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import * as React from 'react';
import { BarPercent } from 'src/components/BarPercent';
import { convertResourceMetric } from 'src/features/Account/Quotas/utils';

import type { QuotaResourceMetrics } from '@linode/api-v4';
import type { Quota } from '@linode/api-v4';

interface Props {
limit: number;
resourceMetric: QuotaResourceMetrics;
resourceMetric: Quota['resource_metric'];
usage: number;
}

Expand Down
Loading
Loading