Skip to content

Commit 59bbd98

Browse files
authored
upcoming: [M3-10128] - Add types/endpoints/queries for Cloud NATs (linode#12379)
* Add Cloud NAT types * Update comment * Add endpoints / queries * Add CRUD mocking * Remove some unneeded comments * Use void instead of empty object for deleteCloudNAT param * Add schemas for POST and PUT reqs * Change to default_ports_per_interface * Change to default_ports_per_interface * Use ResourcePage instead of custom paginated res type * Add code review feedback * Add more code review feedback * Update queries to match VPC pattern with all/paginated structure * Use Request<{}> style format for return type * Add validation schema in api file
1 parent d194eb9 commit 59bbd98

File tree

19 files changed

+418
-0
lines changed

19 files changed

+418
-0
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { createCloudNATSchema } from '@linode/validation';
2+
3+
import { API_ROOT } from '../constants';
4+
import Request, {
5+
setData,
6+
setMethod,
7+
setParams,
8+
setURL,
9+
setXFilter,
10+
} from '../request';
11+
12+
import type { Filter, ResourcePage as Page, Params } from '../types';
13+
import type {
14+
CloudNAT,
15+
CreateCloudNATPayload,
16+
UpdateCloudNATPayload,
17+
} from './types';
18+
19+
export const getCloudNATs = (params?: Params, filter?: Filter) =>
20+
Request<Page<CloudNAT>>(
21+
setURL(`${API_ROOT}/networking/cloudnats`),
22+
setMethod('GET'),
23+
setParams(params),
24+
setXFilter(filter),
25+
);
26+
27+
export const getCloudNAT = (id: number) =>
28+
Request<CloudNAT>(
29+
setURL(`${API_ROOT}/networking/cloudnats/${id}`),
30+
setMethod('GET'),
31+
);
32+
33+
export const createCloudNAT = (data: CreateCloudNATPayload) =>
34+
Request<CloudNAT>(
35+
setURL(`${API_ROOT}/networking/cloudnats`),
36+
setMethod('POST'),
37+
setData(data, createCloudNATSchema),
38+
);
39+
40+
export const updateCloudNAT = (id: number, data: UpdateCloudNATPayload) =>
41+
Request<CloudNAT>(
42+
setURL(`${API_ROOT}/networking/cloudnats/${id}`),
43+
setMethod('PUT'),
44+
setData(data, createCloudNATSchema),
45+
);
46+
47+
export const deleteCloudNAT = (id: number) =>
48+
Request<{}>(
49+
setURL(`${API_ROOT}/networking/cloudnats/${id}`),
50+
setMethod('DELETE'),
51+
);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from './cloudnats';
2+
3+
export * from './types';
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
interface CloudNATIPAddress {
2+
address: string;
3+
}
4+
5+
export interface CloudNAT {
6+
addresses: CloudNATIPAddress[];
7+
id: number;
8+
label: string;
9+
port_prefix_default_len: number;
10+
region: string;
11+
}
12+
13+
export interface CreateCloudNATPayload {
14+
addresses?: CloudNATIPAddress[];
15+
label: string;
16+
port_prefix_default_len?: ValidPortSize;
17+
region: string;
18+
}
19+
20+
export interface UpdateCloudNATPayload {
21+
label?: string;
22+
}
23+
24+
export const VALID_PORT_SIZES = [
25+
64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384,
26+
] as const;
27+
28+
export type ValidPortSize = (typeof VALID_PORT_SIZES)[number];

packages/api-v4/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ export * from './account';
22

33
export * from './betas';
44

5+
export * from './cloudnat';
6+
57
export * from './cloudpulse';
68

79
export * from './databases';
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { Factory } from '@linode/utilities';
2+
3+
import type {
4+
CloudNAT,
5+
CreateCloudNATPayload,
6+
UpdateCloudNATPayload,
7+
} from '@linode/api-v4/lib/networking/types';
8+
9+
export const cloudNATFactory = Factory.Sync.makeFactory<CloudNAT>({
10+
id: Factory.each((id) => id),
11+
label: Factory.each((id) => `cloud-nat-mock-${id}`),
12+
region: 'us-east',
13+
addresses: Factory.each((id) => [{ address: `203.0.113.${id}` }]),
14+
port_prefix_default_len: 1024,
15+
});
16+
17+
export const createCloudNATPayloadFactory =
18+
Factory.Sync.makeFactory<CreateCloudNATPayload>({
19+
label: Factory.each((id) => `cloud-nat-mock-${id}`),
20+
region: 'us-east',
21+
});
22+
23+
export const updateCloudNATPayloadFactory =
24+
Factory.Sync.makeFactory<UpdateCloudNATPayload>({
25+
label: Factory.each((id) => `updated-cloud-nat-mock-${id}`),
26+
});

packages/manager/src/factories/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export * from './accountPayment';
77
export * from './accountSettings';
88
export * from './accountUsers';
99
export * from './billing';
10+
export * from './cloudnats';
1011
export * from './cloudpulse/alerts';
1112
export * from './cloudpulse/channels';
1213
export * from './cloudpulse/services';

packages/manager/src/mocks/mockState.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export const getStateSeederGroups = (
2222
};
2323

2424
export const emptyStore: MockState = {
25+
cloudnats: [],
2526
domainRecords: [],
2627
domains: [],
2728
eventQueue: [],

packages/manager/src/mocks/presets/baseline/crud.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
} from 'src/mocks/presets/crud/handlers/events';
55
import { linodeCrudPreset } from 'src/mocks/presets/crud/linodes';
66

7+
import { cloudNATCrudPreset } from '../crud/cloudnats';
78
import { domainCrudPreset } from '../crud/domains';
89
import { firewallCrudPreset } from '../crud/firewalls';
910
import { kubernetesCrudPreset } from '../crud/kubernetes';
@@ -19,6 +20,7 @@ import type { MockPresetBaseline } from 'src/mocks/types';
1920
export const baselineCrudPreset: MockPresetBaseline = {
2021
group: { id: 'General' },
2122
handlers: [
23+
...cloudNATCrudPreset.handlers,
2224
...domainCrudPreset.handlers,
2325
...firewallCrudPreset.handlers,
2426
...kubernetesCrudPreset.handlers,
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import {
2+
createCloudNAT,
3+
deleteCloudNAT,
4+
getCloudNATs,
5+
updateCloudNAT,
6+
} from 'src/mocks/presets/crud/handlers/cloudnats';
7+
8+
import type { MockPresetCrud } from 'src/mocks/types';
9+
10+
export const cloudNATCrudPreset: MockPresetCrud = {
11+
group: { id: 'CloudNATs' },
12+
handlers: [createCloudNAT, deleteCloudNAT, updateCloudNAT, getCloudNATs],
13+
id: 'cloudnats:crud',
14+
label: 'CloudNATs CRUD',
15+
};
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import { http } from 'msw';
2+
3+
import { cloudNATFactory } from 'src/factories';
4+
import { mswDB } from 'src/mocks/indexedDB';
5+
import {
6+
makeNotFoundResponse,
7+
makePaginatedResponse,
8+
makeResponse,
9+
} from 'src/mocks/utilities/response';
10+
11+
import type { CloudNAT } from '@linode/api-v4';
12+
import type { StrictResponse } from 'msw';
13+
import type { MockState } from 'src/mocks/types';
14+
import type {
15+
APIErrorResponse,
16+
APIPaginatedResponse,
17+
} from 'src/mocks/utilities/response';
18+
19+
export const getCloudNATs = () => [
20+
http.get(
21+
'*/v4/networking/cloudnats',
22+
async ({
23+
request,
24+
}): Promise<
25+
StrictResponse<APIErrorResponse | APIPaginatedResponse<CloudNAT>>
26+
> => {
27+
const cloudNATs = await mswDB.getAll('cloudnats');
28+
29+
return makePaginatedResponse({
30+
data: cloudNATs || [],
31+
request,
32+
});
33+
}
34+
),
35+
36+
http.get(
37+
'*/v4/networking/cloudnats/:id',
38+
async ({
39+
params,
40+
}): Promise<StrictResponse<APIErrorResponse | CloudNAT>> => {
41+
const id = Number(params.id);
42+
const cloudNAT = await mswDB.get('cloudnats', id);
43+
44+
if (!cloudNAT) {
45+
return makeNotFoundResponse();
46+
}
47+
48+
return makeResponse(cloudNAT);
49+
}
50+
),
51+
];
52+
53+
export const createCloudNAT = (mockState: MockState) => [
54+
http.post(
55+
'*/v4/networking/cloudnats',
56+
async ({
57+
request,
58+
}): Promise<StrictResponse<APIErrorResponse | CloudNAT>> => {
59+
const payload = await request.clone().json();
60+
61+
const cloudNAT = cloudNATFactory.build({
62+
...payload,
63+
addresses: ['203.0.113.100'],
64+
});
65+
66+
await mswDB.add('cloudnats', cloudNAT, mockState);
67+
68+
return makeResponse(cloudNAT);
69+
}
70+
),
71+
];
72+
73+
export const updateCloudNAT = (mockState: MockState) => [
74+
http.put(
75+
'*/v4/networking/cloudnats/:id',
76+
async ({
77+
params,
78+
request,
79+
}): Promise<StrictResponse<APIErrorResponse | CloudNAT>> => {
80+
const id = Number(params.id);
81+
const cloudNAT = await mswDB.get('cloudnats', id);
82+
83+
if (!cloudNAT) {
84+
return makeNotFoundResponse();
85+
}
86+
87+
const payload = await request.clone().json();
88+
const updatedCloudNAT = { ...cloudNAT, ...payload };
89+
90+
await mswDB.update('cloudnats', id, updatedCloudNAT, mockState);
91+
92+
return makeResponse(updatedCloudNAT);
93+
}
94+
),
95+
];
96+
97+
export const deleteCloudNAT = (mockState: MockState) => [
98+
http.delete(
99+
'*/v4/networking/cloudnats/:id',
100+
async ({ params }): Promise<StrictResponse<APIErrorResponse | {}>> => {
101+
const id = Number(params.id);
102+
const cloudNAT = await mswDB.get('cloudnats', id);
103+
104+
if (!cloudNAT) {
105+
return makeNotFoundResponse();
106+
}
107+
108+
await mswDB.delete('cloudnats', id, mockState);
109+
110+
return makeResponse({});
111+
}
112+
),
113+
];

0 commit comments

Comments
 (0)