Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change: [M3-7227] - Update VPC-related API types in accordance with new API changes #9824

Merged
merged 10 commits into from
Oct 24, 2023
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/api-v4": Upcoming Features
---

Update the `Subnet` and `Interface` objects to match new API spec ([#9824](https://github.com/linode/manager/pull/9824))
coliu-akamai marked this conversation as resolved.
Show resolved Hide resolved
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: SubnetLinodeInformation[];
created: string;
updated: string;
}

export interface ModifySubnetPayload {
label: string;
}

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

export interface SubnetLinodeInformation {
id: number;
interfaces: SubnetInterfaceInformation[];
coliu-akamai marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Upcoming Features
---

Fix type errors relating to newly updated API spec ([#9824](https://github.com/linode/manager/pull/9824))
coliu-akamai marked this conversation as resolved.
Show resolved Hide resolved
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: true,
coliu-akamai marked this conversation as resolved.
Show resolved Hide resolved
id: Factory.each((i) => i),
ipam_address: '10.0.0.1/24',
label: Factory.each((i) => `interface-${i}`),
Expand All @@ -15,6 +16,7 @@ export const LinodeConfigInterfaceFactoryWithVPC = Factory.Sync.makeFactory<Inte
id: Factory.each((i) => i),
ipam_address: '10.0.0.1/24',
label: Factory.each((i) => `interface-${i}`),
active: true,
purpose: 'vpc',
ipv4: {
vpc: '10.0.0.0',
Expand Down
20 changes: 18 additions & 2 deletions packages/manager/src/factories/subnets.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
import { Subnet } from '@linode/api-v4/lib/vpcs/types';
import { Subnet, SubnetLinodeInformation } from '@linode/api-v4/lib/vpcs/types';
import * as Factory from 'factory.ts';

export const subnetLinodeInformationFactory = Factory.Sync.makeFactory<SubnetLinodeInformation>(
{
id: Factory.each((i) => i),
interfaces: Factory.each((i) =>
Array.from({ length: i }, () => ({
active: 'true',
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))
Array.from({ length: i }, () =>
subnetLinodeInformationFactory.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 @@ -6,6 +6,7 @@ import {
accountFactory,
linodeFactory,
subnetFactory,
subnetLinodeInformationFactory,
vpcFactory,
} from 'src/factories';
import { makeResourcePage } from 'src/mocks/serverHandlers';
Expand Down Expand Up @@ -40,7 +41,7 @@ describe('Linode Entity Detail', () => {

const subnet = subnetFactory.build({
id: 2,
linodes: [5],
linodes: [subnetLinodeInformationFactory.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: [subnetLinodeInformationFactory.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: [subnetLinodeInformationFactory.build({ id: linode.id })],
});

const _vpcs = vpcFactory.buildList(3);
Expand Down
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 {
subnetFactory,
subnetLinodeInformationFactory,
} 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: [
subnetLinodeInformationFactory.build({ id: 1 }),
subnetLinodeInformationFactory.build({ id: 2 }),
subnetLinodeInformationFactory.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: [subnetLinodeInformationFactory.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
40 changes: 32 additions & 8 deletions packages/manager/src/features/VPCs/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,52 @@
import { LinodeConfigInterfaceFactoryWithVPC } from 'src/factories/linodeConfigInterfaceFactory';
import { linodeConfigFactory } from 'src/factories/linodeConfigs';
import { subnetFactory } from 'src/factories/subnets';
import {
subnetFactory,
subnetLinodeInformationFactory,
} from 'src/factories/subnets';

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

const subnetLinodeInfoList1 = subnetLinodeInformationFactory.buildList(4);
const subnetLinodeInfoId1 = subnetLinodeInformationFactory.build({ id: 1 });
const subnetLinodeInfoId3 = subnetLinodeInformationFactory.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: [
subnetLinodeInformationFactory.build({ id: 6 }),
subnetLinodeInformationFactory.build({ id: 7 }),
subnetLinodeInformationFactory.build({ id: 8 }),
subnetLinodeInformationFactory.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);
expect(getUniqueLinodesFromSubnets(subnets3)).toBe(8);
});
});

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
Loading