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

Release v1.112.0 - stagingmaster #10180

Merged
merged 18 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
b897726
feat: [M3-7644] - Add VPC IPv4 address and range to Linode IP Address…
hana-akamai Jan 26, 2024
f35b249
feat: [M3-7641] – Support IPv4 ranges in VPC "Assign Linodes" drawer …
dwiley-akamai Jan 26, 2024
d1649a5
feat: [M3-7642] – Support IPv4 Ranges data in "Unassign Linodes" draw…
dwiley-akamai Jan 29, 2024
2d5eca9
feat: [M3-7643] – Support VPC IPv4 Ranges in Linode Create flow (#10116)
dwiley-akamai Jan 29, 2024
7c26b52
Bump versions and changelog
jaalah Jan 29, 2024
37e2a4a
Update test text field label from "Linodes" to "Linode"
Jan 29, 2024
6bd2f42
Fix IP ranges table spacing and unassign CSV download wording
jaalah Jan 29, 2024
bad64b1
Merge branch 'staging-off-release' of https://github.com/linode/manag…
jaalah Jan 29, 2024
92cbef9
Update version numbers
jaalah Feb 12, 2024
0abd0a8
Fix merge conflicts
jaalah Feb 12, 2024
9d5fad5
fix: [M3-7739, M3-7741, M3-7746, M3-7747] - Cherry pick zero price fi…
jdamore-linode Feb 12, 2024
5510eed
Cloud version 1.112.0
cpathipa Feb 12, 2024
9178a45
feat: [M3-7645] – Support VPC IPv4 Ranges in Add/Edit Linode Config d…
dwiley-akamai Feb 12, 2024
58346c2
Bump validation/package.json
cpathipa Feb 12, 2024
47870ab
Merge pull request #10178 from linode/staging-off-release
cpathipa Feb 12, 2024
24bc50f
Merge branch 'master' into staging
cpathipa Feb 12, 2024
4f33509
change: [M3-7755] – Update IPv4 range "Learn more" docs link (#10181)
dwiley-akamai Feb 12, 2024
a9d02f1
Update release dates in Manager and Validation changelogs
DevDW Feb 12, 2024
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
17 changes: 17 additions & 0 deletions packages/manager/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).

## [2024-02-12] - v1.112.0

### Added:

- Support for IPv4 Ranges in VPC 'Assign Linodes to subnet' drawer ([#10089](https://github.com/linode/manager/pull/10089))
- VPC IPv4 address and range to Linode IP Address Table ([#10108](https://github.com/linode/manager/pull/10108))
- Support for VPC IPv4 Ranges data in Unassign Linodes drawer ([#10114](https://github.com/linode/manager/pull/10114))
- Support for VPC IPv4 Ranges in Linode Create flow and 'VPC IPv4 Ranges' column to inner Subnets table on VPC Detail page ([#10116](https://github.com/linode/manager/pull/10116))
- Support VPC IPv4 Ranges in Add/Edit Linode Config dialog ([#10170](https://github.com/linode/manager/pull/10170))

### Fixed:

- Error when enabling backups for Linodes in regions with $0 pricing ([#10153](https://github.com/linode/manager/pull/10153))
- Error notices for $0 regions in LKE Resize and Add Node Pools drawers ([#10157](https://github.com/linode/manager/pull/10157))
- Error in Enable All Backups drawer when one or more Linode is in a $0 region ([#10161](https://github.com/linode/manager/pull/10161))
- Display $0.00 prices in Linode Migration dialog ([#10166](https://github.com/linode/manager/pull/10166))

## [2024-02-05] - v1.111.0
### Changed:

Expand Down
225 changes: 225 additions & 0 deletions packages/manager/cypress/e2e/core/kubernetes/lke-update.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1011,4 +1011,229 @@ describe('LKE cluster updates for DC-specific prices', () => {
// Confirm total price updates in Kube Specs: $14.40/mo existing pool + $28.80/mo new pool.
cy.findByText('$43.20/month').should('be.visible');
});

/*
* - Confirms node pool resize UI flow using mocked API responses.
* - Confirms that pool size can be changed.
* - Confirms that drawer reflects $0 pricing.
* - Confirms that details page still shows $0 pricing after resizing.
*/
it('can resize pools with region prices of $0', () => {
const dcSpecificPricingRegion = getRegionById('us-southeast');

const mockCluster = kubernetesClusterFactory.build({
k8s_version: latestKubernetesVersion,
region: dcSpecificPricingRegion.id,
control_plane: {
high_availability: false,
},
});

const mockNodePoolResized = nodePoolFactory.build({
count: 3,
type: dcPricingMockLinodeTypes[2].id,
nodes: kubeLinodeFactory.buildList(3),
});

const mockNodePoolInitial = {
...mockNodePoolResized,
count: 1,
nodes: [mockNodePoolResized.nodes[0]],
};

const mockLinodes: Linode[] = mockNodePoolResized.nodes.map(
(node: PoolNodeResponse): Linode => {
return linodeFactory.build({
id: node.instance_id ?? undefined,
ipv4: [randomIp()],
region: dcSpecificPricingRegion.id,
type: dcPricingMockLinodeTypes[2].id,
});
}
);

const mockNodePoolDrawerTitle = 'Resize Pool: Linode 2 GB Plan';

mockGetCluster(mockCluster).as('getCluster');
mockGetClusterPools(mockCluster.id, [mockNodePoolInitial]).as(
'getNodePools'
);
mockGetLinodes(mockLinodes).as('getLinodes');
mockGetLinodeType(dcPricingMockLinodeTypes[2]).as('getLinodeType');
mockGetKubernetesVersions().as('getVersions');
mockGetDashboardUrl(mockCluster.id);
mockGetApiEndpoints(mockCluster.id);

cy.visitWithLogin(`/kubernetes/clusters/${mockCluster.id}`);
cy.wait([
'@getCluster',
'@getNodePools',
'@getLinodes',
'@getVersions',
'@getLinodeType',
]);

// Confirm that nodes are visible.
mockNodePoolInitial.nodes.forEach((node: PoolNodeResponse) => {
cy.get(`tr[data-qa-node-row="${node.id}"]`)
.should('be.visible')
.within(() => {
const nodeLinode = mockLinodes.find(
(linode: Linode) => linode.id === node.instance_id
);
if (nodeLinode) {
cy.findByText(nodeLinode.label).should('be.visible');
}
});
});

// Confirm total price is listed in Kube Specs.
cy.findByText('$0.00/month').should('be.visible');

// Click "Resize Pool" and increase size to 4 nodes.
ui.button
.findByTitle('Resize Pool')
.should('be.visible')
.should('be.enabled')
.click();

mockUpdateNodePool(mockCluster.id, mockNodePoolResized).as(
'resizeNodePool'
);
mockGetClusterPools(mockCluster.id, [mockNodePoolResized]).as(
'getNodePools'
);

ui.drawer
.findByTitle(mockNodePoolDrawerTitle)
.should('be.visible')
.within(() => {
ui.button
.findByTitle('Save Changes')
.should('be.visible')
.should('be.disabled');

cy.findByText('Current pool: $0/month (1 node at $0/month)').should(
'be.visible'
);
cy.findByText('Resized pool: $0/month (1 node at $0/month)').should(
'be.visible'
);

cy.findByLabelText('Add 1')
.should('be.visible')
.should('be.enabled')
.click()
.click()
.click();

cy.findByLabelText('Edit Quantity').should('have.value', '4');
cy.findByText('Current pool: $0/month (1 node at $0/month)').should(
'be.visible'
);
cy.findByText('Resized pool: $0/month (4 nodes at $0/month)').should(
'be.visible'
);

ui.button
.findByTitle('Save Changes')
.should('be.visible')
.should('be.enabled')
.click();
});

cy.wait(['@resizeNodePool', '@getNodePools']);

// Confirm total price is still $0 in Kube Specs.
cy.findByText('$0.00/month').should('be.visible');
});

/*
* - Confirms UI flow when adding node pools using mocked API responses.
* - Confirms that drawer reflects $0 prices.
* - Confirms that details page still shows $0 pricing after adding node pool.
*/
it('can add node pools with region prices of $0', () => {
const dcSpecificPricingRegion = getRegionById('us-southeast');

const mockCluster = kubernetesClusterFactory.build({
k8s_version: latestKubernetesVersion,
region: dcSpecificPricingRegion.id,
control_plane: {
high_availability: false,
},
});

const mockNewNodePool = nodePoolFactory.build({
count: 2,
type: dcPricingMockLinodeTypes[2].id,
nodes: kubeLinodeFactory.buildList(2),
});

const mockNodePool = nodePoolFactory.build({
count: 1,
type: dcPricingMockLinodeTypes[2].id,
nodes: kubeLinodeFactory.buildList(1),
});

mockGetCluster(mockCluster).as('getCluster');
mockGetClusterPools(mockCluster.id, [mockNodePool]).as('getNodePools');
mockGetKubernetesVersions().as('getVersions');
mockAddNodePool(mockCluster.id, mockNewNodePool).as('addNodePool');
mockGetLinodeType(dcPricingMockLinodeTypes[2]).as('getLinodeType');
mockGetLinodeTypes(dcPricingMockLinodeTypes);
mockGetDashboardUrl(mockCluster.id);
mockGetApiEndpoints(mockCluster.id);

cy.visitWithLogin(`/kubernetes/clusters/${mockCluster.id}`);
cy.wait(['@getCluster', '@getNodePools', '@getVersions', '@getLinodeType']);

// Assert that initial node pool is shown on the page.
cy.findByText('Linode 2 GB', { selector: 'h2' }).should('be.visible');

// Confirm total price of $0 is listed in Kube Specs.
cy.findByText('$0.00/month').should('be.visible');

// Add a new node pool, select plan, submit form in drawer.
ui.button
.findByTitle('Add a Node Pool')
.should('be.visible')
.should('be.enabled')
.click();

mockGetClusterPools(mockCluster.id, [mockNodePool, mockNewNodePool]).as(
'getNodePools'
);

ui.drawer
.findByTitle(`Add a Node Pool: ${mockCluster.label}`)
.should('be.visible')
.within(() => {
cy.findByText('Linode 2 GB')
.should('be.visible')
.closest('tr')
.within(() => {
// Assert that $0 prices are displayed the plan table, then add a node pool with 2 linodes.
cy.findAllByText('$0').should('have.length', 2);
cy.findByLabelText('Add 1').should('be.visible').click().click();
});

// Assert that $0 prices are displayed as helper text.
cy.contains(
'This pool will add $0/month (2 nodes at $0/month) to this cluster.'
).should('be.visible');

ui.button
.findByTitle('Add pool')
.should('be.visible')
.should('be.enabled')
.click();
});

// Wait for API responses.
cy.wait(['@addNodePool', '@getNodePools']);

// Confirm total price is still $0 in Kube Specs.
cy.findByText('$0.00/month').should('be.visible');
});
});
19 changes: 15 additions & 4 deletions packages/manager/cypress/e2e/core/linodes/backup-linode.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,16 +270,22 @@ describe('"Enable Linode Backups" banner', () => {
// See `dcPricingMockLinodeTypes` exported from `support/constants/dc-specific-pricing.ts`.
linodeFactory.build({
label: randomLabel(),
region: 'us-east',
region: 'us-ord',
backups: { enabled: false },
type: dcPricingMockLinodeTypesForBackups[0].id,
}),
linodeFactory.build({
label: randomLabel(),
region: 'us-west',
region: 'us-east',
backups: { enabled: false },
type: dcPricingMockLinodeTypesForBackups[1].id,
}),
linodeFactory.build({
label: randomLabel(),
region: 'us-west',
backups: { enabled: false },
type: dcPricingMockLinodeTypesForBackups[2].id,
}),
linodeFactory.build({
label: randomLabel(),
region: 'us-central',
Expand Down Expand Up @@ -317,6 +323,7 @@ describe('"Enable Linode Backups" banner', () => {

// The expected backup price for each Linode, as shown in backups drawer table.
const expectedPrices = [
'$0.00/mo', // us-ord mocked price.
'$3.57/mo', // us-east mocked price.
'$4.17/mo', // us-west mocked price.
'$2.00/mo', // regular price.
Expand Down Expand Up @@ -358,7 +365,7 @@ describe('"Enable Linode Backups" banner', () => {
);

// Confirm that expected total cost is shown.
cy.contains(`Total for 3 Linodes: ${expectedTotal}`).should(
cy.contains(`Total for 4 Linodes: ${expectedTotal}`).should(
'be.visible'
);

Expand All @@ -377,6 +384,10 @@ describe('"Enable Linode Backups" banner', () => {
.closest('tr')
.within(() => {
cy.findByText(expectedPrice).should('be.visible');
// Confirm no error indicator appears for $0.00 prices.
cy.findByLabelText(
'There was an error loading the price.'
).should('not.exist');
});
});

Expand All @@ -398,7 +409,7 @@ describe('"Enable Linode Backups" banner', () => {
cy.wait([...enableBackupAliases, '@updateAccountSettings']);

ui.toast.assertMessage(
'3 Linodes have been enrolled in automatic backups, and all new Linodes will automatically be backed up.'
'4 Linodes have been enrolled in automatic backups, and all new Linodes will automatically be backed up.'
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ describe('VPC assign/unassign flows', () => {
mockGetLinodeConfigs(mockLinode.id, [mockConfig]).as(
'getLinodeConfigs'
);
cy.findByLabelText('Linodes')
cy.findByLabelText('Linode')
.should('be.visible')
.click()
.type(mockLinode.label)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,10 @@ export const dcPricingMockLinodeTypes = linodeTypeFactory.buildList(3, {
monthly: 12.2,
},
{
hourly: 0.006,
// Mock a DC with $0 region prices, which is possible in some circumstances (e.g. Limited Availability).
hourly: 0.0,
id: 'us-southeast',
monthly: 4.67,
monthly: 0.0,
},
],
});
Expand All @@ -92,6 +93,11 @@ export const dcPricingMockLinodeTypesForBackups = linodeTypeFactory.buildList(
monthly: 2.0,
},
region_prices: [
{
hourly: 0,
id: 'us-ord',
monthly: 0,
},
{
hourly: 0.0048,
id: 'us-east',
Expand Down
4 changes: 2 additions & 2 deletions packages/manager/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "linode-manager",
"author": "Linode",
"description": "The Linode Manager website",
"version": "1.111.0",
"version": "1.112.0",
"private": true,
"type": "module",
"bugs": {
Expand Down Expand Up @@ -215,4 +215,4 @@
"Firefox ESR",
"not ie < 9"
]
}
}
Loading
Loading