Skip to content

Commit

Permalink
Merge branch 'develop' into M3-9420-nb-vpc-feature-flag
Browse files Browse the repository at this point in the history
  • Loading branch information
DevDW committed Feb 28, 2025
2 parents 654558b + 15dfc59 commit e878bb4
Show file tree
Hide file tree
Showing 32 changed files with 5,386 additions and 13,290 deletions.
9 changes: 5 additions & 4 deletions .github/workflows/e2e_schedule_and_push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version: "20.17"
cache: "pnpm"
- run: |
echo "CYPRESS_RECORD_KEY=${{ secrets.CYPRESS_RECORD_KEY }}" >> $GITHUB_ENV
echo "GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}" >> $GITHUB_ENV
Expand All @@ -54,16 +53,18 @@ jobs:
echo "REACT_APP_API_ROOT=${{ secrets.REACT_APP_API_ROOT }}" >> ./packages/manager/.env
echo "REACT_APP_APP_ROOT=${{ secrets.REACT_APP_APP_ROOT }}" >> ./packages/manager/.env
echo "REACT_APP_DISABLE_NEW_RELIC=1" >> ./packages/manager/.env
pnpm install:all
pnpm build
pnpm start:manager:ci &
- run: pnpm install --frozen-lockfile
- run: pnpm run --filter @linode/validation build
- run: pnpm run --filter @linode/api-v4 build
- name: Run tests
uses: cypress-io/github-action@v6
with:
working-directory: packages/manager
wait-on: "http://localhost:3000"
wait-on-timeout: 1000
install: false
build: pnpm run build
start: pnpm start:ci
browser: chrome
record: true
parallel: true
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"husky": "^9.1.6",
"concurrently": "9.1.0",
"typescript": "^5.7.3",
"vitest": "^3.0.5"
"vitest": "^3.0.7",
"@vitest/ui": "^3.0.7"
},
"scripts": {
"lint": "eslint . --quiet --ext .js,.ts,.tsx",
Expand Down Expand Up @@ -66,6 +67,8 @@
},
"dependencies": {},
"pnpm": {
"onlyBuiltDependencies": ["cypress"]
"onlyBuiltDependencies": [
"cypress"
]
}
}
5 changes: 5 additions & 0 deletions packages/manager/.changeset/pr-11683-changed-1739919225511.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Changed
---

Improve error handling for kubeconfig download during cluster provisioning ([#11683](https://github.com/linode/manager/pull/11683))
5 changes: 5 additions & 0 deletions packages/manager/.changeset/pr-11736-added-1740581762216.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Added
---

Link to Linode's Firewall in Linode Entity Details ([#11736](https://github.com/linode/manager/pull/11736))
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Upcoming Features
---

Add Interface type to Linode Entity Detail ([#11736](https://github.com/linode/manager/pull/11736))
5 changes: 5 additions & 0 deletions packages/manager/.changeset/pr-11755-changed-1740752072171.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Changed
---

Move @vitest/ui to monorepo root dependency ([#11755](https://github.com/linode/manager/pull/11755))
5 changes: 5 additions & 0 deletions packages/manager/.changeset/pr-11755-changed-1740752328523.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Changed
---

Upgrade vitest and @vitest/ui to 3.0.7 ([#11755](https://github.com/linode/manager/pull/11755))
5 changes: 5 additions & 0 deletions packages/manager/.changeset/pr-11758-changed-1740751964030.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Changed
---

Update react-vnc to 3.0.7 ([#11758](https://github.com/linode/manager/pull/11758))
6 changes: 6 additions & 0 deletions packages/manager/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ 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/).

## [2025-02-27] - v1.137.2

### Fixed:

- Disk Encryption logic preventing Linode deployment in distributed regions ([#11760](https://github.com/linode/manager/pull/11760)

## [2025-02-25] - v1.137.1

### Fixed:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
import { ui } from 'support/ui';
import { accountFactory, regionFactory } from '@src/factories';
import { mockGetRegions } from 'support/intercepts/regions';
import {
linodeFactory,
accountFactory,
linodeTypeFactory,
regionFactory,
} from '@src/factories';
import {
mockGetRegionAvailability,
mockGetRegions,
} from 'support/intercepts/regions';
import { mockGetAccount } from 'support/intercepts/account';
import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags';
import { makeFeatureFlagData } from 'support/util/feature-flags';
import {
checkboxTestId,
headerTestId,
} from 'src/components/Encryption/constants';
import { extendRegion } from 'support/util/regions';
import { linodeCreatePage } from 'support/ui/pages';
import {
mockCreateLinode,
mockGetLinodeTypes,
} from 'support/intercepts/linodes';
import { randomLabel, randomString } from 'support/util/random';
import type { Region } from '@linode/api-v4';

describe('Create Linode with Disk Encryption', () => {
it('should not have a "Disk Encryption" section visible if the feature flag is off and user does not have capability', () => {
Expand Down Expand Up @@ -77,4 +93,123 @@ describe('Create Linode with Disk Encryption', () => {

cy.get(`[data-testid="${checkboxTestId}"]`).should('be.enabled');
});

// Confirm Linode Disk Encryption features when using Distributed Regions.
describe('Distributed regions', () => {
const encryptionTooltipMessage =
'Distributed Compute Instances are encrypted. This setting can not be changed.';

const mockDistributedRegionWithoutCapability = regionFactory.build({
capabilities: [
'Linodes',
'Cloud Firewall',
'Distributed Plans',
'Placement Group',
],
site_type: 'distributed',
});

const mockDistributedRegionWithCapability = regionFactory.build({
capabilities: [
'Linodes',
'Cloud Firewall',
'Distributed Plans',
'Placement Group',
'Disk Encryption',
],
site_type: 'distributed',
});

const mockDistributedRegions: Region[] = [
mockDistributedRegionWithCapability,
mockDistributedRegionWithoutCapability,
];

const mockLinodeType = linodeTypeFactory.build({
id: 'nanode-edge-1',
label: 'Nanode 1GB',
class: 'nanode',
});

/*
* Right now there's some ambiguity over the 'Disk Encryption' capability
* and whether it's expected to be present for Distributed Regions. We'll
* test Cloud against both scenarios -- when distributed regions do and do
* not have the capability -- and confirm that the Linode Create flow works
* as expected in both cases.
*/
mockDistributedRegions.forEach((distributedRegion) => {
const suffix = distributedRegion.capabilities.includes('Disk Encryption')
? '(with region capability)'
: '(without region capability)';

/*
* - Confirms that disk encryption works as expected for distributed regions. Specifically:
* - Encrypted checkbox is always checked, is disabled, and therefore cannot be changed.
* - Outgoing Linode create API request payload does NOT contain encryption property.
*/
it(`creates a Linode with Disk Encryption in a distributed region ${suffix}`, () => {
const mockRegions = [distributedRegion];
const mockLinode = linodeFactory.build({
label: randomLabel(),
region: distributedRegion.id,
});

mockAppendFeatureFlags({
gecko2: {
enabled: true,
},
});

mockGetRegions(mockRegions);
mockGetLinodeTypes([mockLinodeType]);
mockGetRegionAvailability(distributedRegion.id, []);
mockCreateLinode(mockLinode).as('createLinode');
cy.visitWithLogin('/linodes/create');

cy.get('[data-qa-linode-region]').within(() => {
ui.tabList.find().within(() => {
cy.findByText('Distributed').click();
});

cy.findByLabelText('Region').type(distributedRegion.label);
ui.regionSelect
.findItemByRegionLabel(
extendRegion(distributedRegion).label,
mockRegions
)
.click();
});

linodeCreatePage.setLabel(mockLinode.label);
linodeCreatePage.setRootPassword(randomString(32));

// Select mock Nanode plan type.
cy.get('[data-qa-plan-row="Nanode 1 GB"]').click();

cy.findByLabelText('Encrypt Disk')
.should('be.disabled')
.should('be.checked');

cy.findByLabelText(encryptionTooltipMessage).click();
ui.tooltip.findByText(encryptionTooltipMessage).should('be.visible');

// Click "Create Linode" and confirm outgoing API request payload.
ui.button
.findByTitle('Create Linode')
.should('be.visible')
.should('be.enabled')
.click();

// Submit form to create Linode and confirm that outgoing API request
// contains expected user data.
cy.wait('@createLinode').then((xhr) => {
const requestPayload = xhr.request.body;
const regionId = requestPayload['region'];
expect(regionId).to.equal(mockLinode.region);
expect(requestPayload['disk_encryption']).to.be.undefined;
});
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ describe('Firewalls', () => {
cy.wait('@getLinodeFirewalls');

// Verify the firewall shows up in the table
cy.findByText(firewallToAttach.label)
cy.findAllByText(firewallToAttach.label)
.should('be.visible')
.closest('tr')
.within(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import { routes } from 'support/ui/constants';
import { apiMatcher } from 'support/util/intercepts';
import { chooseRegion, getRegionById } from 'support/util/regions';
import { authenticate } from 'support/api/authentication';
import { mockGetLinodes } from 'support/intercepts/linodes';
import {
mockGetLinodes,
mockGetLinodeFirewalls,
} from 'support/intercepts/linodes';
import { userPreferencesFactory, profileFactory } from '@src/factories';
import { accountUserFactory } from '@src/factories/accountUsers';
import { grantsFactory } from '@src/factories/grants';
Expand All @@ -22,6 +25,7 @@ import {
import { randomLabel } from 'support/util/random';
import * as commonLocators from 'support/ui/locators/common-locators';
import * as linodeLocators from 'support/ui/locators/linode-locators';
import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags';

const mockLinodes = new Array(5).fill(null).map(
(_item: null, index: number): Linode => {
Expand Down Expand Up @@ -392,6 +396,10 @@ describe('linode landing checks', () => {
});

it('checks summary view for linode table', () => {
mockAppendFeatureFlags({
linodeInterfaces: { enabled: false },
});

const mockPreferencesListView = userPreferencesFactory.build();

const mockPreferencesSummaryView = {
Expand All @@ -405,6 +413,10 @@ describe('linode landing checks', () => {
'updateUserPreferences'
);

mockLinodes.forEach((linode) => {
mockGetLinodeFirewalls(linode.id, []);
});

cy.visitWithLogin('/linodes');
cy.wait(['@getLinodes', '@getUserPreferences']);

Expand Down
7 changes: 3 additions & 4 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.137.1",
"version": "1.137.2",
"private": true,
"type": "module",
"bugs": {
Expand Down Expand Up @@ -77,7 +77,7 @@
"react-redux": "~7.1.3",
"react-router-dom": "~5.3.4",
"react-router-hash-link": "^2.3.1",
"react-vnc": "^2.0.2",
"react-vnc": "^3.0.7",
"react-waypoint": "^10.3.0",
"recharts": "^2.14.1",
"recompose": "^0.30.0",
Expand Down Expand Up @@ -172,8 +172,7 @@
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"@vitejs/plugin-react-swc": "^3.7.2",
"@vitest/coverage-v8": "^3.0.3",
"@vitest/ui": "^3.0.3",
"@vitest/coverage-v8": "^3.0.7",
"axe-core": "^4.10.2",
"chai-string": "^1.5.0",
"concurrently": "^9.1.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,16 +156,36 @@ export const KubeConfigDisplay = (props: Props) => {

const downloadKubeConfig = async () => {
try {
const { data } = await getKubeConfig();
const queryResult = await getKubeConfig();

if (
Array.isArray(queryResult.error) &&
queryResult.error[0]?.reason?.includes(
'kubeconfig is not yet available'
)
) {
enqueueSnackbar(
'Your cluster is still provisioning. Please try again in a few minutes.',
{ variant: 'error' }
);
return;
}

if (data) {
downloadFile(`${clusterLabel}-kubeconfig.yaml`, data);
if (queryResult.isError) {
throw queryResult.error;
}

if (!queryResult.data) {
throw new Error('No kubeconfig data available');
}

downloadFile(`${clusterLabel}-kubeconfig.yaml`, queryResult.data);
} catch (error) {
const errorText = getAPIErrorOrDefault(
error,
'Unable to download your kubeconfig'
)[0].reason;
const errorText =
error instanceof Error
? error.message
: getAPIErrorOrDefault(error, 'Unable to download your kubeconfig')[0]
.reason;

enqueueSnackbar(errorText, { variant: 'error' });
}
Expand Down
Loading

0 comments on commit e878bb4

Please sign in to comment.