Skip to content

Commit 53998f4

Browse files
authored
test: [M3-10465, M3-10466] - Add Cypress test coverage for LKE-E Phase 2 (VPC, IP Stack) create flow (linode#12709)
* Move shared constants out to constants/lke.ts file * Add new test file with LKE-E phase 2 networking config coverage WIP * Clean up request mocking and assertions * Correctly mock VPCs in the region capability, fixing BYO test case failures * Add changeset * Clean up for error message * Correct success test cases; punt failure validation to separate ticket/case
1 parent 3ffc985 commit 53998f4

File tree

4 files changed

+328
-73
lines changed

4 files changed

+328
-73
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@linode/manager": Tests
3+
---
4+
5+
Add `lke-enterprise-create` Cypress spec to test LKE-E Phase 2 (VPC + IP Stack) coverage ([#12709](https://github.com/linode/manager/pull/12709))

packages/manager/cypress/e2e/core/kubernetes/lke-create.spec.ts

Lines changed: 9 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,15 @@ import {
1717
dcPricingPlanPlaceholder,
1818
} from 'support/constants/dc-specific-pricing';
1919
import {
20+
clusterPlans,
21+
dedicatedNodeCount,
22+
dedicatedType,
2023
latestEnterpriseTierKubernetesVersion,
2124
latestKubernetesVersion,
25+
mockedLKEClusterTypes,
26+
mockedLKEEnterprisePrices,
27+
nanodeNodeCount,
28+
nanodeType,
2229
} from 'support/constants/lke';
2330
import { mockGetAccount } from 'support/intercepts/account';
2431
import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags';
@@ -50,8 +57,6 @@ import {
5057
kubernetesClusterFactory,
5158
kubernetesControlPlaneACLFactory,
5259
kubernetesControlPlaneACLOptionsFactory,
53-
lkeEnterpriseTypeFactory,
54-
lkeHighAvailabilityTypeFactory,
5560
nodePoolFactory,
5661
} from 'src/factories';
5762
import {
@@ -62,12 +67,8 @@ import { getTotalClusterMemoryCPUAndStorage } from 'src/features/Kubernetes/kube
6267
import { getTotalClusterPrice } from 'src/utilities/pricing/kubernetes';
6368

6469
import type { PriceType } from '@linode/api-v4/lib/types';
65-
import type { ExtendedType } from 'src/utilities/extendType';
6670
import type { LkePlanDescription } from 'support/api/lke';
6771

68-
const dedicatedNodeCount = 4;
69-
const nanodeNodeCount = 3;
70-
7172
const clusterRegion = chooseRegion({
7273
capabilities: ['Kubernetes'],
7374
exclude: ['au-mel', 'eu-west'], // Unavailable regions
@@ -82,46 +83,7 @@ const nanodeMemoryPool = nodePoolFactory.build({
8283
nodes: kubeLinodeFactory.buildList(nanodeNodeCount),
8384
type: 'g6-standard-1',
8485
});
85-
const dedicatedType = dedicatedTypeFactory.build({
86-
disk: 81920,
87-
id: 'g6-dedicated-2',
88-
label: 'Dedicated 4 GB',
89-
memory: 4096,
90-
price: {
91-
hourly: 0.054,
92-
monthly: 36.0,
93-
},
94-
region_prices: dcPricingMockLinodeTypes.find(
95-
(type) => type.id === 'g6-dedicated-2'
96-
)?.region_prices,
97-
vcpus: 2,
98-
}) as ExtendedType;
99-
const nanodeType = linodeTypeFactory.build({
100-
disk: 51200,
101-
id: 'g6-standard-1',
102-
label: 'Linode 2 GB',
103-
memory: 2048,
104-
price: {
105-
hourly: 0.0095,
106-
monthly: 12.0,
107-
},
108-
region_prices: dcPricingMockLinodeTypes.find(
109-
(type) => type.id === 'g6-standard-1'
110-
)?.region_prices,
111-
vcpus: 1,
112-
}) as ExtendedType;
113-
const gpuType = linodeTypeFactory.build({
114-
class: 'gpu',
115-
id: 'g2-gpu-1',
116-
}) as ExtendedType;
117-
const highMemType = linodeTypeFactory.build({
118-
class: 'highmem',
119-
id: 'g7-highmem-1',
120-
}) as ExtendedType;
121-
const premiumType = linodeTypeFactory.build({
122-
class: 'premium',
123-
id: 'g7-premium-1',
124-
}) as ExtendedType;
86+
12587
const mockedLKEClusterPrices: PriceType[] = [
12688
{
12789
id: 'lke-sa',
@@ -146,33 +108,7 @@ const mockedLKEHAClusterPrices: PriceType[] = [
146108
transfer: 0,
147109
},
148110
];
149-
const mockedLKEEnterprisePrices = [
150-
lkeHighAvailabilityTypeFactory.build(),
151-
lkeEnterpriseTypeFactory.build(),
152-
];
153-
const clusterPlans: LkePlanDescription[] = [
154-
{
155-
nodeCount: dedicatedNodeCount,
156-
planName: 'Dedicated 4 GB',
157-
size: 4,
158-
tab: 'Dedicated CPU',
159-
type: 'dedicated',
160-
},
161-
{
162-
nodeCount: nanodeNodeCount,
163-
planName: 'Linode 2 GB',
164-
size: 24,
165-
tab: 'Shared CPU',
166-
type: 'standard',
167-
},
168-
];
169-
const mockedLKEClusterTypes = [
170-
dedicatedType,
171-
nanodeType,
172-
gpuType,
173-
highMemType,
174-
premiumType,
175-
];
111+
176112
const validEnterprisePlanTabs = [
177113
'Dedicated CPU',
178114
'Shared CPU',
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
/**
2+
* Confirms create operations on LKE-Enterprise clusters.
3+
*/
4+
5+
import { regionFactory } from '@linode/utilities';
6+
import {
7+
clusterPlans,
8+
latestEnterpriseTierKubernetesVersion,
9+
latestKubernetesVersion,
10+
mockedLKEClusterTypes,
11+
mockedLKEEnterprisePrices,
12+
} from 'support/constants/lke';
13+
import { mockGetAccount } from 'support/intercepts/account';
14+
import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags';
15+
import { mockGetLinodeTypes } from 'support/intercepts/linodes';
16+
import {
17+
mockCreateCluster,
18+
mockGetKubernetesVersions,
19+
mockGetLKEClusterTypes,
20+
mockGetTieredKubernetesVersions,
21+
} from 'support/intercepts/lke';
22+
import { mockGetRegions } from 'support/intercepts/regions';
23+
import { mockGetVPCs } from 'support/intercepts/vpc';
24+
import { ui } from 'support/ui';
25+
import { randomLabel } from 'support/util/random';
26+
27+
import {
28+
accountFactory,
29+
kubernetesClusterFactory,
30+
subnetFactory,
31+
vpcFactory,
32+
} from 'src/factories';
33+
34+
describe('LKE Cluster Creation with LKE-E', () => {
35+
describe('LKE-E Phase 2 Networking Configurations', () => {
36+
const clusterLabel = randomLabel();
37+
const selectedVpcId = 1;
38+
const selectedSubnetId = 1;
39+
40+
const mockEnterpriseCluster = kubernetesClusterFactory.build({
41+
k8s_version: latestEnterpriseTierKubernetesVersion.id,
42+
label: clusterLabel,
43+
region: 'us-iad',
44+
tier: 'enterprise',
45+
});
46+
47+
const mockVpcs = [
48+
{
49+
...vpcFactory.build(),
50+
id: selectedVpcId,
51+
label: 'test-vpc',
52+
region: 'us-iad',
53+
subnets: [
54+
subnetFactory.build({
55+
id: selectedSubnetId,
56+
label: 'subnet-a',
57+
ipv4: '10.0.0.0/13',
58+
}),
59+
],
60+
},
61+
];
62+
63+
// Accounts for the different combination of IP Networking and VPC/Subnet radio selections
64+
const possibleNetworkingConfigurations = [
65+
{
66+
description:
67+
'Successfully creates cluster with auto-generated dual-stack VPC and IPv4+IPv6 stack',
68+
isUsingOwnVPC: false,
69+
stackType: 'ipv4-ipv6',
70+
},
71+
{
72+
description:
73+
'Successfully creates cluster with auto-generated dual-stack VPC and IPv4 stack',
74+
isUsingOwnVPC: false,
75+
stackType: 'ipv4',
76+
},
77+
{
78+
description:
79+
'Successfully creates cluster with existing (BYO) dual-stack VPC and IPv4+IPv6 stack',
80+
isUsingOwnVPC: true,
81+
stackType: 'ipv4-ipv6',
82+
},
83+
{
84+
description:
85+
'Successfully creates cluster with existing (BYO) dual-stack VPC and IPv4 stack',
86+
isUsingOwnVPC: true,
87+
stackType: 'ipv4',
88+
},
89+
];
90+
91+
beforeEach(() => {
92+
// TODO LKE-E: Remove feature flag mocks once we're in GA
93+
mockAppendFeatureFlags({
94+
lkeEnterprise: {
95+
enabled: true,
96+
la: true,
97+
postLa: false,
98+
phase2Mtc: true,
99+
},
100+
}).as('getFeatureFlags');
101+
mockGetAccount(
102+
accountFactory.build({
103+
capabilities: ['Kubernetes Enterprise'],
104+
})
105+
).as('getAccount');
106+
107+
mockGetTieredKubernetesVersions('enterprise', [
108+
latestEnterpriseTierKubernetesVersion,
109+
]).as('getTieredKubernetesVersions');
110+
mockGetKubernetesVersions([latestKubernetesVersion]).as(
111+
'getKubernetesVersions'
112+
);
113+
114+
mockGetLinodeTypes(mockedLKEClusterTypes).as('getLinodeTypes');
115+
mockGetLKEClusterTypes(mockedLKEEnterprisePrices).as(
116+
'getLKEEnterpriseClusterTypes'
117+
);
118+
mockCreateCluster(mockEnterpriseCluster).as('createCluster');
119+
120+
mockGetRegions([
121+
regionFactory.build({
122+
capabilities: [
123+
'Linodes',
124+
'Kubernetes',
125+
'Kubernetes Enterprise',
126+
'VPCs',
127+
],
128+
id: 'us-iad',
129+
label: 'Washington, DC',
130+
}),
131+
]).as('getRegions');
132+
133+
mockGetVPCs(mockVpcs).as('getVPCs');
134+
135+
cy.visitWithLogin('/kubernetes/clusters');
136+
cy.wait(['@getAccount']);
137+
138+
ui.button.findByTitle('Create Cluster').click();
139+
cy.url().should('endWith', '/kubernetes/create');
140+
cy.wait([
141+
'@getKubernetesVersions',
142+
'@getTieredKubernetesVersions',
143+
'@getLinodeTypes',
144+
]);
145+
});
146+
147+
possibleNetworkingConfigurations.forEach(
148+
({ description, isUsingOwnVPC, stackType }) => {
149+
it(`${description}`, () => {
150+
// Select the enterprise tier and available region
151+
cy.findByLabelText('Cluster Label').type(clusterLabel);
152+
cy.findByText('LKE Enterprise').click();
153+
154+
cy.wait(['@getLKEEnterpriseClusterTypes', '@getRegions']);
155+
156+
ui.regionSelect.find().clear().type('Washington, DC{enter}');
157+
cy.wait('@getVPCs');
158+
159+
// Select either the autogenerated or existing (BYO) VPC radio button
160+
if (isUsingOwnVPC) {
161+
cy.findByTestId('isUsingOwnVpc').within(() => {
162+
cy.findByLabelText('Use an existing VPC').click();
163+
});
164+
165+
// Select the existing VPC and Subnet to use
166+
ui.autocomplete.findByLabel('VPC').click();
167+
cy.findByText('test-vpc').click();
168+
ui.autocomplete.findByLabel('Subnet').click();
169+
cy.findByText(/subnet-a/).click();
170+
}
171+
172+
// Select either the IPv4 or IPv4 + IPv6 (dual-stack) IP Networking radio button
173+
cy.findByLabelText(
174+
stackType === 'ipv4' ? 'IPv4' : 'IPv4 + IPv6'
175+
).click();
176+
177+
// Select a plan and add nodes
178+
cy.findByText(clusterPlans[0].tab).should('be.visible').click();
179+
cy.findByText(clusterPlans[0].planName)
180+
.should('be.visible')
181+
.closest('tr')
182+
.within(() => {
183+
cy.get('[name="Quantity"]').should('be.visible').click();
184+
cy.focused().type(`{selectall}${clusterPlans[0].nodeCount}`);
185+
186+
ui.button
187+
.findByTitle('Add')
188+
.should('be.visible')
189+
.should('be.enabled')
190+
.click();
191+
});
192+
193+
// Bypass ACL validation error
194+
cy.get('input[name="acl-acknowledgement"]').check();
195+
196+
// Create LKE-E cluster
197+
cy.get('[data-testid="kube-checkout-bar"]')
198+
.should('be.visible')
199+
.within(() => {
200+
ui.button
201+
.findByTitle('Create Cluster')
202+
.should('be.visible')
203+
.should('be.enabled')
204+
.click();
205+
});
206+
207+
// Confirm request payload
208+
cy.wait('@createCluster').then((intercept) => {
209+
const payload = intercept.request.body;
210+
211+
expect(payload.stack_type).to.eq(stackType);
212+
// Confirm existing (BYO) VPC selection passes the vpc_id and subnet_id;
213+
// else, confirm undefined is passed for an autogenerated VPC
214+
if (isUsingOwnVPC) {
215+
expect(payload.vpc_id).to.eq(selectedVpcId);
216+
expect(payload.subnet_id).to.eq(selectedSubnetId);
217+
} else {
218+
expect(payload.vpc_id).to.be.undefined;
219+
expect(payload.subnet_id).to.be.undefined;
220+
}
221+
});
222+
});
223+
}
224+
);
225+
});
226+
});

0 commit comments

Comments
 (0)