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

upcoming: [M3-8549] – BSE tooltip copy update & add "Encrypt Volume" checkbox in Attach Volume drawer #10909

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions packages/manager/.changeset/pr-10909-tests-1725903174019.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Tests
---

Add unit tests for AttachVolumeDrawer component ([#10909](https://github.com/linode/manager/pull/10909))
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Upcoming Features
---

Add 'Encrypt Volume' checkbox in Attach Volume drawer ([#10909](https://github.com/linode/manager/pull/10909))
2 changes: 1 addition & 1 deletion packages/manager/src/components/Encryption/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export const BLOCK_STORAGE_USER_SIDE_ENCRYPTION_CAVEAT =
'User-side encryption on top of encryption-enabled volumes is discouraged at this time, as it could severely impact your volume performance.';

export const BLOCK_STORAGE_ENCRYPTION_SETTING_IMMUTABLE_COPY =
'The encryption setting cannot be changed after creation.';
'The encryption setting cannot be modified after a volume has been created.';

export const BLOCK_STORAGE_CLONING_INHERITANCE_CAVEAT =
'Encryption is inherited from the source volume and cannot be changed when cloning volumes.';
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { waitFor } from '@testing-library/react';
import * as React from 'react';

import { accountFactory, volumeFactory } from 'src/factories';
import { HttpResponse, http, server } from 'src/mocks/testServer';
import { renderWithTheme } from 'src/utilities/testHelpers';

import { AttachVolumeDrawer } from './AttachVolumeDrawer';

const accountEndpoint = '*/v4/account';
const encryptionLabelText = 'Encrypt Volume';

describe('AttachVolumeDrawer', () => {
/* @TODO BSE: Remove feature flagging/conditionality once BSE is fully rolled out */

it('should display a disabled checkbox for volume encryption if the user has the account capability and the feature flag is on', async () => {
const volume = volumeFactory.build();

server.use(
http.get(accountEndpoint, () => {
return HttpResponse.json(
accountFactory.build({ capabilities: ['Block Storage Encryption'] })
);
})
);

const { getByLabelText } = renderWithTheme(
<AttachVolumeDrawer onClose={vi.fn} open volume={volume} />,
{
flags: { blockStorageEncryption: true },
}
);

await waitFor(() => {
expect(getByLabelText(encryptionLabelText)).not.toBeNull();
expect(getByLabelText(encryptionLabelText)).toBeDisabled();
});
});

it('should not display a checkbox for volume encryption if the user has the account capability but the feature flag is off', async () => {
const volume = volumeFactory.build();

server.use(
http.get(accountEndpoint, () => {
return HttpResponse.json(
accountFactory.build({ capabilities: ['Block Storage Encryption'] })
);
})
);

const { queryByRole } = renderWithTheme(
<AttachVolumeDrawer onClose={vi.fn} open volume={volume} />,
{
flags: { blockStorageEncryption: false },
}
);

await waitFor(() => {
expect(queryByRole('checkbox')).not.toBeInTheDocument();
});
});

it('should not display a checkbox for volume encryption if the feature flag is on but the user lacks the account capability', async () => {
const volume = volumeFactory.build();

server.use(
http.get(accountEndpoint, () => {
return HttpResponse.json(accountFactory.build({ capabilities: [] }));
})
);

const { queryByRole } = renderWithTheme(
<AttachVolumeDrawer onClose={vi.fn} open volume={volume} />,
{
flags: { blockStorageEncryption: true },
}
);

await waitFor(() => {
expect(queryByRole('checkbox')).not.toBeInTheDocument();
});
});
});
27 changes: 25 additions & 2 deletions packages/manager/src/features/Volumes/AttachVolumeDrawer.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { Volume } from '@linode/api-v4';
import { styled } from '@mui/material/styles';
import { useFormik } from 'formik';
import { useSnackbar } from 'notistack';
import * as React from 'react';
import { number, object } from 'yup';

import { ActionsPanel } from 'src/components/ActionsPanel/ActionsPanel';
import { Box } from 'src/components/Box';
import { Checkbox } from 'src/components/Checkbox';
import { Drawer } from 'src/components/Drawer';
import { BLOCK_STORAGE_ENCRYPTION_SETTING_IMMUTABLE_COPY } from 'src/components/Encryption/constants';
import { useIsBlockStorageEncryptionFeatureEnabled } from 'src/components/Encryption/utils';
import { FormHelperText } from 'src/components/FormHelperText';
import { Notice } from 'src/components/Notice/Notice';
import { LinodeSelect } from 'src/features/Linodes/LinodeSelect/LinodeSelect';
Expand All @@ -17,6 +20,8 @@ import { getAPIErrorFor } from 'src/utilities/getAPIErrorFor';

import { ConfigSelect } from './VolumeDrawer/ConfigSelect';

import type { Volume } from '@linode/api-v4';

interface Props {
onClose: () => void;
open: boolean;
Expand All @@ -43,6 +48,10 @@ export const AttachVolumeDrawer = React.memo((props: Props) => {

const { error, mutateAsync: attachVolume } = useAttachVolumeMutation();

const {
isBlockStorageEncryptionFeatureEnabled,
} = useIsBlockStorageEncryptionFeatureEnabled();

const formik = useFormik({
initialValues: { config_id: -1, linode_id: -1 },
async onSubmit(values) {
Expand Down Expand Up @@ -142,7 +151,21 @@ export const AttachVolumeDrawer = React.memo((props: Props) => {
onBlur={() => null}
value={formik.values.config_id}
/>

{isBlockStorageEncryptionFeatureEnabled && (
<Box
sx={{
marginLeft: '2px',
marginTop: '16px',
}}
>
<Checkbox
checked={volume?.encryption === 'enabled'}
disabled
text="Encrypt Volume"
toolTipText={BLOCK_STORAGE_ENCRYPTION_SETTING_IMMUTABLE_COPY}
/>
</Box>
)}
<ActionsPanel
primaryButtonProps={{
'data-testid': 'submit',
Expand Down
Loading