Skip to content

Commit

Permalink
upcoming: [M3-7986] - Fix & Improve Placement Groups feature restrict…
Browse files Browse the repository at this point in the history
…ion (linode#10372)

* Initial commit: save work

* Add coverage

* fix test

* Added changeset: Fix & Improve Placement Groups feature restriction

* Fix e2e
  • Loading branch information
abailly-akamai authored Apr 15, 2024
1 parent 391b846 commit 68f0add
Show file tree
Hide file tree
Showing 15 changed files with 173 additions and 48 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Upcoming Features
---

Fix & Improve Placement Groups feature restriction ([#10372](https://github.com/linode/manager/pull/10372))
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ import {
import { makeFeatureFlagData } from 'support/util/feature-flags';
import { mockGetPlacementGroups } from 'support/intercepts/vm-placement';
import { ui } from 'support/ui';
import { accountFactory } from 'src/factories';

import type { Flags } from 'src/featureFlags';
import { mockGetAccount } from 'support/intercepts/account';

const mockAccount = accountFactory.build();

describe('VM Placement landing page', () => {
// Mock the VM Placement Groups feature flag to be enabled for each test in this block.
Expand All @@ -18,6 +22,7 @@ describe('VM Placement landing page', () => {
}),
});
mockGetFeatureFlagClientstream();
mockGetAccount(mockAccount).as('getAccount');
});

/**
Expand Down
14 changes: 13 additions & 1 deletion packages/manager/src/GoTo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { makeStyles } from 'tss-react/mui';
import EnhancedSelect, { Item } from 'src/components/EnhancedSelect/Select';

import { useIsACLBEnabled } from './features/LoadBalancers/utils';
import { useIsPlacementGroupsEnabled } from './features/PlacementGroups/utils';
import { useAccountManagement } from './hooks/useAccountManagement';
import { useGlobalKeyboardListener } from './hooks/useGlobalKeyboardListener';

Expand Down Expand Up @@ -60,6 +61,7 @@ export const GoTo = React.memo(() => {
const { _hasAccountAccess, _isManagedAccount } = useAccountManagement();

const { isACLBEnabled } = useIsACLBEnabled();
const { isPlacementGroupsEnabled } = useIsPlacementGroupsEnabled();
const { goToOpen, setGoToOpen } = useGlobalKeyboardListener();

const onClose = () => {
Expand Down Expand Up @@ -113,6 +115,11 @@ export const GoTo = React.memo(() => {
display: 'Images',
href: '/images',
},
{
display: 'Placement Groups',
hide: !isPlacementGroupsEnabled,
href: '/placement-groups',
},
{
display: 'Domains',
href: '/domains',
Expand Down Expand Up @@ -149,7 +156,12 @@ export const GoTo = React.memo(() => {
href: '/profile/display',
},
],
[_hasAccountAccess, _isManagedAccount, isACLBEnabled]
[
_hasAccountAccess,
_isManagedAccount,
isACLBEnabled,
isPlacementGroupsEnabled,
]
);

const options: Item[] = React.useMemo(
Expand Down
16 changes: 10 additions & 6 deletions packages/manager/src/MainContent.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Grid from '@mui/material/Unstable_Grid2';
import { Theme } from '@mui/material/styles';
import Grid from '@mui/material/Unstable_Grid2';
import { isEmpty } from 'ramda';
import * as React from 'react';
import { Redirect, Route, Switch } from 'react-router-dom';
Expand All @@ -10,8 +10,8 @@ import { Box } from 'src/components/Box';
import { MainContentBanner } from 'src/components/MainContentBanner';
import { MaintenanceScreen } from 'src/components/MaintenanceScreen';
import { NotFound } from 'src/components/NotFound';
import { SIDEBAR_WIDTH } from 'src/components/PrimaryNav/SideMenu';
import { SideMenu } from 'src/components/PrimaryNav/SideMenu';
import { SIDEBAR_WIDTH } from 'src/components/PrimaryNav/SideMenu';
import { SuspenseLoader } from 'src/components/SuspenseLoader';
import { useDialogContext } from 'src/context/useDialogContext';
import { Footer } from 'src/features/Footer';
Expand All @@ -33,6 +33,7 @@ import { complianceUpdateContext } from './context/complianceUpdateContext';
import { switchAccountSessionContext } from './context/switchAccountSessionContext';
import { FlagSet } from './featureFlags';
import { useIsACLBEnabled } from './features/LoadBalancers/utils';
import { useIsPlacementGroupsEnabled } from './features/PlacementGroups/utils';
import { useGlobalErrors } from './hooks/useGlobalErrors';

const useStyles = makeStyles()((theme: Theme) => ({
Expand Down Expand Up @@ -226,6 +227,7 @@ export const MainContent = () => {
(checkRestrictedUser && !enginesLoading && !enginesError);

const { isACLBEnabled } = useIsACLBEnabled();
const { isPlacementGroupsEnabled } = useIsPlacementGroupsEnabled();

const defaultRoot = _isManagedAccount ? '/managed' : '/linodes';

Expand Down Expand Up @@ -337,10 +339,12 @@ export const MainContent = () => {
<React.Suspense fallback={<SuspenseLoader />}>
<Switch>
<Route component={LinodesRoutes} path="/linodes" />
<Route
component={PlacementGroups}
path="/placement-groups"
/>
{isPlacementGroupsEnabled && (
<Route
component={PlacementGroups}
path="/placement-groups"
/>
)}
<Route component={Volumes} path="/volumes" />
<Redirect path="/volumes*" to="/volumes" />
{isACLBEnabled && (
Expand Down
9 changes: 3 additions & 6 deletions packages/manager/src/components/DetailsPanel/DetailsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { TagsInput, TagsInputProps } from 'src/components/TagsInput/TagsInput';
import { TextField, TextFieldProps } from 'src/components/TextField';
import { Typography } from 'src/components/Typography';
import { PlacementGroupsDetailPanel } from 'src/features/PlacementGroups/PlacementGroupsDetailPanel';
import { useFlags } from 'src/hooks/useFlags';
import { useIsPlacementGroupsEnabled } from 'src/features/PlacementGroups/utils';

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

Expand All @@ -28,9 +28,7 @@ export const DetailsPanel = (props: DetailsPanelProps) => {
tagsInputProps,
} = props;
const theme = useTheme();
const flags = useFlags();

const showPlacementGroups = Boolean(flags.placementGroups?.enabled);
const { isPlacementGroupsEnabled } = useIsPlacementGroupsEnabled();

return (
<Paper
Expand Down Expand Up @@ -60,8 +58,7 @@ export const DetailsPanel = (props: DetailsPanelProps) => {
/>

{tagsInputProps && <TagsInput {...tagsInputProps} />}

{showPlacementGroups && (
{isPlacementGroupsEnabled && (
<PlacementGroupsDetailPanel
handlePlacementGroupChange={handlePlacementGroupChange}
selectedRegionId={selectedRegionId}
Expand Down
5 changes: 4 additions & 1 deletion packages/manager/src/components/PrimaryNav/PrimaryNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { BetaChip } from 'src/components/BetaChip/BetaChip';
import { Box } from 'src/components/Box';
import { Divider } from 'src/components/Divider';
import { useIsACLBEnabled } from 'src/features/LoadBalancers/utils';
import { useIsPlacementGroupsEnabled } from 'src/features/PlacementGroups/utils';
import { useAccountManagement } from 'src/hooks/useAccountManagement';
import { useFlags } from 'src/hooks/useFlags';
import { usePrefetch } from 'src/hooks/usePreFetch';
Expand Down Expand Up @@ -170,6 +171,7 @@ export const PrimaryNav = (props: PrimaryNavProps) => {
(checkRestrictedUser && !enginesLoading && !enginesError);

const { isACLBEnabled } = useIsACLBEnabled();
const { isPlacementGroupsEnabled } = useIsPlacementGroupsEnabled();

const prefetchObjectStorage = () => {
if (!enableObjectPrefetch) {
Expand Down Expand Up @@ -245,7 +247,7 @@ export const PrimaryNav = (props: PrimaryNavProps) => {
{
betaChipClassName: 'beta-chip-placement-groups',
display: 'Placement Groups',
hide: !flags.placementGroups?.enabled,
hide: !isPlacementGroupsEnabled,
href: '/placement-groups',
icon: <PlacementGroups />,
isBeta: flags.placementGroups?.beta,
Expand Down Expand Up @@ -322,6 +324,7 @@ export const PrimaryNav = (props: PrimaryNavProps) => {
allowMarketplacePrefetch,
flags.databaseBeta,
isACLBEnabled,
isPlacementGroupsEnabled,
flags.placementGroups,
]
);
Expand Down
1 change: 1 addition & 0 deletions packages/manager/src/factories/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export const accountFactory = Factory.Sync.makeFactory<Account>({
'LKE HA Control Planes',
'Machine Images',
'Managed Databases',
'Placement Group',
],
city: 'Colorado',
company: Factory.each((i) => `company-${i}`),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { waitFor } from '@testing-library/react';
import React from 'react';

import { profileFactory } from 'src/factories';
import { grantsFactory } from 'src/factories/grants';
import { grantsFactory, profileFactory } from 'src/factories';
import { HttpResponse, http, server } from 'src/mocks/testServer';
import { renderWithThemeAndHookFormContext } from 'src/utilities/testHelpers';

Expand Down Expand Up @@ -37,17 +36,19 @@ describe('Linode Create Details', () => {
expect(getByText('Type to choose or create a tag.')).toBeVisible();
});

it('renders an placement group details if the flag is on', () => {
it('renders an placement group details if the flag is on', async () => {
const { getByText } = renderWithThemeAndHookFormContext({
component: <Details />,
options: {
flags: { placementGroups: { beta: true, enabled: true } },
},
});

expect(
getByText('Select a region above to see available Placement Groups.')
).toBeVisible();
await waitFor(() => {
expect(
getByText('Select a region above to see available Placement Groups.')
).toBeVisible();
});
});

it('does not render the placement group select if the flag is off', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,14 @@ import { Paper } from 'src/components/Paper';
import { TagsInput } from 'src/components/TagsInput/TagsInput';
import { TextField } from 'src/components/TextField';
import { Typography } from 'src/components/Typography';
import { useFlags } from 'src/hooks/useFlags';
import { useIsPlacementGroupsEnabled } from 'src/features/PlacementGroups/utils';
import { useRestrictedGlobalGrantCheck } from 'src/hooks/useRestrictedGlobalGrantCheck';

import { PlacementGroupPanel } from './PlacementGroupPanel';

export const Details = () => {
const { control } = useFormContext<CreateLinodeRequest>();
const flags = useFlags();

const showPlacementGroups = Boolean(flags.placementGroups?.enabled);
const { isPlacementGroupsEnabled } = useIsPlacementGroupsEnabled();

const isCreateLinodeRestricted = useRestrictedGlobalGrantCheck({
globalGrantType: 'add_linodes',
Expand Down Expand Up @@ -51,7 +49,7 @@ export const Details = () => {
control={control}
name="tags"
/>
{showPlacementGroups && <PlacementGroupPanel />}
{isPlacementGroupsEnabled && <PlacementGroupPanel />}
</Paper>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -861,10 +861,7 @@ export class LinodeCreate extends React.PureComponent<
image: this.props.selectedImageID,
label: this.props.label,
placement_group:
this.props.flags.placementGroups?.enabled &&
placement_group_payload.id !== -1
? placement_group_payload
: undefined,
placement_group_payload.id !== -1 ? placement_group_payload : undefined,
private_ip: this.props.privateIPEnabled,
region: this.props.selectedRegionID ?? '',
root_pass: this.props.password,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { LandingHeader } from 'src/components/LandingHeader';
import { NotFound } from 'src/components/NotFound';
import { Notice } from 'src/components/Notice/Notice';
import { getRestrictedResourceText } from 'src/features/Account/utils';
import { useFlags } from 'src/hooks/useFlags';
import { useRestrictedGlobalGrantCheck } from 'src/hooks/useRestrictedGlobalGrantCheck';
import { useAllLinodesQuery } from 'src/queries/linodes/linodes';
import {
Expand All @@ -23,18 +22,14 @@ import { PlacementGroupsLinodes } from './PlacementGroupsLinodes/PlacementGroups
import { PlacementGroupsSummary } from './PlacementGroupsSummary/PlacementGroupsSummary';

export const PlacementGroupsDetail = () => {
const flags = useFlags();
const { id } = useParams<{ id: string }>();
const placementGroupId = +id;

const {
data: placementGroup,
error: placementGroupError,
isLoading,
} = usePlacementGroupQuery(
placementGroupId,
Boolean(flags.placementGroups?.enabled)
);
} = usePlacementGroupQuery(placementGroupId);
const { data: linodes, isFetching: isFetchingLinodes } = useAllLinodesQuery(
{},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { TextTooltip } from 'src/components/TextTooltip';
import { Typography } from 'src/components/Typography';
import { PlacementGroupsCreateDrawer } from 'src/features/PlacementGroups/PlacementGroupsCreateDrawer';
import { hasRegionReachedPlacementGroupCapacity } from 'src/features/PlacementGroups/utils';
import { useFlags } from 'src/hooks/useFlags';
import { useRestrictedGlobalGrantCheck } from 'src/hooks/useRestrictedGlobalGrantCheck';
import { useAllPlacementGroupsQuery } from 'src/queries/placementGroups';
import { useRegionsQuery } from 'src/queries/regions/regions';
Expand All @@ -26,7 +25,6 @@ interface Props {
}

export const PlacementGroupsDetailPanel = (props: Props) => {
const flags = useFlags();
const theme = useTheme();
const { handlePlacementGroupChange, selectedRegionId } = props;
const { data: allPlacementGroups } = useAllPlacementGroupsQuery();
Expand Down Expand Up @@ -151,16 +149,14 @@ export const PlacementGroupsDetailPanel = (props: Props) => {
</Button>
)}
</Box>
{flags.placementGroups?.enabled && (
<PlacementGroupsCreateDrawer
allPlacementGroups={allPlacementGroups || []}
disabledPlacementGroupCreateButton={isLinodeReadOnly}
onClose={() => setIsCreatePlacementGroupDrawerOpen(false)}
onPlacementGroupCreate={handlePlacementGroupCreated}
open={isCreatePlacementGroupDrawerOpen}
selectedRegionId={selectedRegionId}
/>
)}
<PlacementGroupsCreateDrawer
allPlacementGroups={allPlacementGroups || []}
disabledPlacementGroupCreateButton={isLinodeReadOnly}
onClose={() => setIsCreatePlacementGroupDrawerOpen(false)}
onPlacementGroupCreate={handlePlacementGroupCreated}
open={isCreatePlacementGroupDrawerOpen}
selectedRegionId={selectedRegionId}
/>
</>
);
};
Loading

0 comments on commit 68f0add

Please sign in to comment.