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-8369] – Add "Encrypt Volume" checkbox in Edit Volume drawer #10787

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
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Upcoming Features
---

Add 'Encrypt Volume' checkbox in Edit Volume drawer ([#10787](https://github.com/linode/manager/pull/10787))
3 changes: 3 additions & 0 deletions packages/manager/src/components/Encryption/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,6 @@ export const BLOCK_STORAGE_ENCRYPTION_OVERHEAD_CAVEAT =

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.';
83 changes: 83 additions & 0 deletions packages/manager/src/features/Volumes/EditVolumeDrawer.test.tsx
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 { EditVolumeDrawer } from './EditVolumeDrawer';

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

describe('EditVolumeDrawer', () => {
/* @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(
<EditVolumeDrawer 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(
<EditVolumeDrawer 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(
<EditVolumeDrawer onClose={vi.fn} open volume={volume} />,
{
flags: { blockStorageEncryption: true },
}
);

await waitFor(() => {
expect(queryByRole('checkbox')).not.toBeInTheDocument();
});
});
});
26 changes: 25 additions & 1 deletion packages/manager/src/features/Volumes/EditVolumeDrawer.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { Volume } from '@linode/api-v4';
import { UpdateVolumeSchema } from '@linode/validation';
import { useFormik } from 'formik';
import React from 'react';

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 { Notice } from 'src/components/Notice/Notice';
import { TagsInput } from 'src/components/TagsInput/TagsInput';
import { TextField } from 'src/components/TextField';
Expand All @@ -15,6 +18,8 @@ import {
handleGeneralErrors,
} from 'src/utilities/formikErrorUtils';

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

interface Props {
onClose: () => void;
open: boolean;
Expand All @@ -28,6 +33,10 @@ export const EditVolumeDrawer = (props: Props) => {

const { mutateAsync: updateVolume } = useUpdateVolumeMutation();

const {
isBlockStorageEncryptionFeatureEnabled,
} = useIsBlockStorageEncryptionFeatureEnabled();

const isReadOnly =
grants !== undefined &&
grants.volume.find((grant) => grant.id === volume?.id)?.permissions ===
Expand Down Expand Up @@ -114,6 +123,21 @@ export const EditVolumeDrawer = (props: Props) => {
name="tags"
value={values.tags?.map((t) => ({ label: t, value: t })) ?? []}
/>
{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={{
disabled: isReadOnly || !dirty,
Expand Down
Loading