Skip to content

Commit

Permalink
change: [M3-7227] - Update VPC-related API types in accordance with n…
Browse files Browse the repository at this point in the history
…ew API changes (#9824)

* update api types and fix resulting errors

* add changesets

* increase timeout of specific test?

* Update packages/manager/.changeset/pr-9824-upcoming-features-1697827056392.md

Co-authored-by: Dajahi Wiley <114682940+dwiley-akamai@users.noreply.github.com>

* Update packages/api-v4/.changeset/pr-9824-upcoming-features-1697827003419.md

Co-authored-by: Dajahi Wiley <114682940+dwiley-akamai@users.noreply.github.com>

* address feedback for factories

* fix array size for subnet factories, update naming

* remove extra timeout

* fix cypress test: make mock subnet start with 0 linodes

---------

Co-authored-by: Dajahi Wiley <114682940+dwiley-akamai@users.noreply.github.com>
  • Loading branch information
coliu-akamai and dwiley-akamai authored Oct 24, 2023
1 parent cc8a9af commit f0b17fe
Show file tree
Hide file tree
Showing 15 changed files with 121 additions and 34 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/api-v4": Upcoming Features
---

Update the `Subnet` and `Interface` interfaces to match new API spec ([#9824](https://github.com/linode/manager/pull/9824))
3 changes: 2 additions & 1 deletion packages/api-v4/src/linodes/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,14 +165,15 @@ export interface Interface {
purpose: InterfacePurpose;
ipam_address: string | null;
primary?: boolean;
active: boolean;
subnet_id?: number | null;
vpc_id?: number | null;
ipv4?: ConfigInterfaceIPv4;
ipv6?: ConfigInterfaceIPv6;
ip_ranges?: string[];
}

export type InterfacePayload = Omit<Interface, 'id'>;
export type InterfacePayload = Omit<Interface, 'id' | 'active'>;

export interface ConfigInterfaceOrderPayload {
ids: number[];
Expand Down
11 changes: 10 additions & 1 deletion packages/api-v4/src/vpcs/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Interface } from 'src/linodes';

export interface VPC {
id: number;
label: string;
Expand Down Expand Up @@ -28,11 +30,18 @@ export interface CreateSubnetPayload {

export interface Subnet extends CreateSubnetPayload {
id: number;
linodes: number[];
linodes: SubnetAssignedLinodeData[];
created: string;
updated: string;
}

export interface ModifySubnetPayload {
label: string;
}

export type SubnetLinodeInterfaceData = Pick<Interface, 'active' | 'id'>;

export interface SubnetAssignedLinodeData {
id: number;
interfaces: SubnetLinodeInterfaceData[];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Upcoming Features
---

Properly support new shapes of `Subnet` and `Interface` return objects ([#9824](https://github.com/linode/manager/pull/9824))
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ describe('VPC details page', () => {
const mockSubnet = subnetFactory.build({
id: randomNumber(),
label: randomLabel(),
linodes: [],
});
const mockVPC = vpcFactory.build({
id: randomNumber(),
Expand Down
12 changes: 7 additions & 5 deletions packages/manager/src/factories/linodeConfigInterfaceFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as Factory from 'factory.ts';

export const LinodeConfigInterfaceFactory = Factory.Sync.makeFactory<Interface>(
{
active: false,
id: Factory.each((i) => i),
ipam_address: '10.0.0.1/24',
label: Factory.each((i) => `interface-${i}`),
Expand All @@ -12,19 +13,20 @@ export const LinodeConfigInterfaceFactory = Factory.Sync.makeFactory<Interface>(

export const LinodeConfigInterfaceFactoryWithVPC = Factory.Sync.makeFactory<Interface>(
{
active: false,
id: Factory.each((i) => i),
ip_ranges: ['192.0.2.0/24'],
ipam_address: '10.0.0.1/24',
label: Factory.each((i) => `interface-${i}`),
purpose: 'vpc',
ipv4: {
vpc: '10.0.0.0',
nat_1_1: 'some nat',
vpc: '10.0.0.0',
},
ipv6: {
vpc: '2001:0db8:85a3:0000:0000:8a2e:0370:7334',
},
ip_ranges: ['192.0.2.0/24'],
vpc_id: Factory.each((i) => i + 1),
label: Factory.each((i) => `interface-${i}`),
purpose: 'vpc',
subnet_id: Factory.each((i) => i),
vpc_id: Factory.each((i) => i + 1),
}
);
24 changes: 21 additions & 3 deletions packages/manager/src/factories/subnets.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
import { Subnet } from '@linode/api-v4/lib/vpcs/types';
import {
Subnet,
SubnetAssignedLinodeData,
} from '@linode/api-v4/lib/vpcs/types';
import * as Factory from 'factory.ts';

// NOTE: Changing to fixed array length for the interfaces and linodes fields of the
// subnetAssignedLinodeDataFactory and subnetFactory respectively -- see [M3-7227] for more details

export const subnetAssignedLinodeDataFactory = Factory.Sync.makeFactory<SubnetAssignedLinodeData>(
{
id: Factory.each((i) => i),
interfaces: Array.from({ length: 5 }, () => ({
active: false,
id: Math.floor(Math.random() * 100),
})),
}
);

export const subnetFactory = Factory.Sync.makeFactory<Subnet>({
created: '2023-07-12T16:08:53',
id: Factory.each((i) => i),
ipv4: '0.0.0.0/0',
label: Factory.each((i) => `subnet-${i}`),
linodes: Factory.each((i) =>
Array.from({ length: i }, () => Math.floor(Math.random() * 100))
linodes: Array.from({ length: 5 }, () =>
subnetAssignedLinodeDataFactory.build({
id: Math.floor(Math.random() * 100),
})
),
updated: '2023-07-12T16:08:53',
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as React from 'react';
import {
accountFactory,
linodeFactory,
subnetAssignedLinodeDataFactory,
subnetFactory,
vpcFactory,
} from 'src/factories';
Expand Down Expand Up @@ -40,7 +41,7 @@ describe('Linode Entity Detail', () => {

const subnet = subnetFactory.build({
id: 2,
linodes: [5],
linodes: [subnetAssignedLinodeDataFactory.build({ id: 5 })],
});

const vpc = vpcFactory.build({
Expand Down Expand Up @@ -81,7 +82,7 @@ describe('Linode Entity Detail', () => {

const subnet = subnetFactory.build({
id: 4,
linodes: [85],
linodes: [subnetAssignedLinodeDataFactory.build({ id: 85 })],
});

const vpc = vpcFactory.build({
Expand Down Expand Up @@ -116,7 +117,7 @@ describe('Linode Entity Detail', () => {
const subnet = subnetFactory.build({
id: 4,
label: '1st-subnet',
linodes: [linode.id],
linodes: [subnetAssignedLinodeDataFactory.build({ id: linode.id })],
});

const _vpcs = vpcFactory.buildList(3);
Expand Down
6 changes: 5 additions & 1 deletion packages/manager/src/features/Linodes/LinodeEntityDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,11 @@ export const Body = React.memo((props: BodyProps) => {
const vpcLinodeIsAssignedTo = vpcsList.find((vpc) => {
const subnets = vpc.subnets;

return Boolean(subnets.find((subnet) => subnet.linodes.includes(linodeId)));
return Boolean(
subnets.find((subnet) =>
subnet.linodes.some((linodeInfo) => linodeInfo.id === linodeId)
)
);
});

const { data: configs } = useAllLinodeConfigsQuery(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export const SubnetAssignLinodesDrawer = (
// assigned to this subnet
const findUnassignedLinodes = React.useCallback(() => {
return linodes?.filter((linode) => {
return !subnet?.linodes.includes(linode.id);
return !subnet?.linodes.some((linodeInfo) => linodeInfo.id === linode.id);
});
}, [subnet, linodes]);

Expand Down Expand Up @@ -232,7 +232,9 @@ export const SubnetAssignLinodesDrawer = (
// Check if the selected Linode is already assigned to the subnet
if (
values.selectedLinode &&
subnet?.linodes.includes(values.selectedLinode.id)
subnet?.linodes.some(
(linodeInfo) => linodeInfo.id === values.selectedLinode?.id
)
) {
const configId = getConfigId(linodeConfigs, values.selectedConfig);

Expand Down Expand Up @@ -280,7 +282,9 @@ export const SubnetAssignLinodesDrawer = (
// we want to remove it from assignedLinodesAndConfigData
const isLinodeToRemoveValid =
removedLinodeId.current !== -1 &&
!subnet?.linodes.includes(removedLinodeId.current) &&
!subnet?.linodes.some(
(linodeInfo) => linodeInfo.id === removedLinodeId.current
) &&
!!assignedLinodesAndConfigData.find(
(data) => data.id === removedLinodeId.current
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ export const SubnetUnassignLinodesDrawer = React.memo(
// 2. We need to filter only the linodes that are assigned to the subnet.
const findAssignedLinodes = React.useCallback(() => {
return linodes?.filter((linode) => {
return subnetLinodeIds?.includes(linode.id);
return subnetLinodeIds?.some(
(linodeInfo) => linodeInfo.id === linode.id
);
});
}, [linodes, subnetLinodeIds]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { waitForElementToBeRemoved } from '@testing-library/react';
import * as React from 'react';
import { QueryClient } from 'react-query';

import { subnetFactory } from 'src/factories/subnets';
import {
subnetAssignedLinodeDataFactory,
subnetFactory,
} from 'src/factories/subnets';
import { makeResourcePage } from 'src/mocks/serverHandlers';
import { rest, server } from 'src/mocks/testServer';
import { mockMatchMedia, renderWithTheme } from 'src/utilities/testHelpers';
Expand All @@ -21,7 +24,13 @@ const loadingTestId = 'circle-progress';

describe('VPC Subnets table', () => {
it('should display filter input, subnet label, id, ip range, number of linodes, and action menu', async () => {
const subnet = subnetFactory.build({ linodes: [1, 2, 3] });
const subnet = subnetFactory.build({
linodes: [
subnetAssignedLinodeDataFactory.build({ id: 1 }),
subnetAssignedLinodeDataFactory.build({ id: 2 }),
subnetAssignedLinodeDataFactory.build({ id: 3 }),
],
});
server.use(
rest.get('*/vpcs/:vpcId/subnets', (req, res, ctx) => {
return res(ctx.json(makeResourcePage([subnet])));
Expand Down Expand Up @@ -81,7 +90,9 @@ describe('VPC Subnets table', () => {
});

it('should show linode table head data when table is expanded', async () => {
const subnet = subnetFactory.build({ linodes: [1] });
const subnet = subnetFactory.build({
linodes: [subnetAssignedLinodeDataFactory.build({ id: 1 })],
});
server.use(
rest.get('*/vpcs/:vpcId/subnets', (req, res, ctx) => {
return res(ctx.json(makeResourcePage([subnet])));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,11 +230,11 @@ export const VPCSubnetsTable = (props: Props) => {
</TableHead>
<TableBody>
{subnet.linodes.length > 0 ? (
subnet.linodes.map((linodeId) => (
subnet.linodes.map((linodeInfo) => (
<SubnetLinodeRow
handleUnassignLinode={handleSubnetUnassignLinode}
key={linodeId}
linodeId={linodeId}
key={linodeInfo.id}
linodeId={linodeInfo.id}
subnet={subnet}
subnetId={subnet.id}
/>
Expand Down
38 changes: 31 additions & 7 deletions packages/manager/src/features/VPCs/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,50 @@
import { LinodeConfigInterfaceFactoryWithVPC } from 'src/factories/linodeConfigInterfaceFactory';
import { linodeConfigFactory } from 'src/factories/linodeConfigs';
import { subnetFactory } from 'src/factories/subnets';
import {
subnetAssignedLinodeDataFactory,
subnetFactory,
} from 'src/factories/subnets';

import {
getSubnetInterfaceFromConfigs,
getUniqueLinodesFromSubnets,
} from './utils';

const subnetLinodeInfoList1 = subnetAssignedLinodeDataFactory.buildList(4);
const subnetLinodeInfoId1 = subnetAssignedLinodeDataFactory.build({ id: 1 });
const subnetLinodeInfoId3 = subnetAssignedLinodeDataFactory.build({ id: 3 });

describe('getUniqueLinodesFromSubnets', () => {
it(`returns the number of unique linodes within a VPC's subnets`, () => {
const subnets0 = [subnetFactory.build({ linodes: [] })];
const subnets1 = [subnetFactory.build({ linodes: [1, 2, 3] })];
const subnets2 = [subnetFactory.build({ linodes: [1, 1, 3, 3] })];
const subnets1 = [subnetFactory.build({ linodes: subnetLinodeInfoList1 })];
const subnets2 = [
subnetFactory.build({
linodes: [
subnetLinodeInfoId1,
subnetLinodeInfoId1,
subnetLinodeInfoId3,
subnetLinodeInfoId3,
],
}),
];
const subnets3 = [
subnetFactory.build({ linodes: [1, 2, 3] }),
subnetFactory.build({ linodes: subnetLinodeInfoList1 }),
subnetFactory.build({ linodes: [] }),
subnetFactory.build({ linodes: [3] }),
subnetFactory.build({ linodes: [6, 7, 8, 9, 1] }),
subnetFactory.build({ linodes: [subnetLinodeInfoId3] }),
subnetFactory.build({
linodes: [
subnetAssignedLinodeDataFactory.build({ id: 6 }),
subnetAssignedLinodeDataFactory.build({ id: 7 }),
subnetAssignedLinodeDataFactory.build({ id: 8 }),
subnetAssignedLinodeDataFactory.build({ id: 9 }),
subnetLinodeInfoId1,
],
}),
];

expect(getUniqueLinodesFromSubnets(subnets0)).toBe(0);
expect(getUniqueLinodesFromSubnets(subnets1)).toBe(3);
expect(getUniqueLinodesFromSubnets(subnets1)).toBe(4);
expect(getUniqueLinodesFromSubnets(subnets2)).toBe(2);
expect(getUniqueLinodesFromSubnets(subnets3)).toBe(7);
});
Expand Down
6 changes: 3 additions & 3 deletions packages/manager/src/features/VPCs/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import type { Config, Subnet } from '@linode/api-v4';
export const getUniqueLinodesFromSubnets = (subnets: Subnet[]) => {
const linodes: number[] = [];
for (const subnet of subnets) {
subnet.linodes.forEach((linodeId) => {
if (!linodes.includes(linodeId)) {
linodes.push(linodeId);
subnet.linodes.forEach((linodeInfo) => {
if (!linodes.includes(linodeInfo.id)) {
linodes.push(linodeInfo.id);
}
});
}
Expand Down

0 comments on commit f0b17fe

Please sign in to comment.