diff --git a/packages/manager/src/features/ObjectStorage/BucketDetail/BucketAccess.tsx b/packages/manager/src/features/ObjectStorage/BucketDetail/BucketAccess.tsx
index 914262bf2da..af95b960e6c 100644
--- a/packages/manager/src/features/ObjectStorage/BucketDetail/BucketAccess.tsx
+++ b/packages/manager/src/features/ObjectStorage/BucketDetail/BucketAccess.tsx
@@ -6,8 +6,8 @@ import {
import { styled } from '@mui/material/styles';
import * as React from 'react';
-import { Typography } from 'src/components/Typography';
import { Paper } from 'src/components/Paper';
+import { Typography } from 'src/components/Typography';
import { AccessSelect } from './AccessSelect';
diff --git a/packages/manager/src/features/ObjectStorage/BucketLanding/BucketDetailsDrawer.tsx b/packages/manager/src/features/ObjectStorage/BucketLanding/BucketDetailsDrawer.tsx
index a9e01d542d9..4bb73143f48 100644
--- a/packages/manager/src/features/ObjectStorage/BucketLanding/BucketDetailsDrawer.tsx
+++ b/packages/manager/src/features/ObjectStorage/BucketLanding/BucketDetailsDrawer.tsx
@@ -60,7 +60,9 @@ export const BucketDetailsDrawer = React.memo(
);
// @TODO OBJ Multicluster: Once the feature is rolled out to production, we can clean this up by removing the useObjectStorageClusters and useRegionsQuery, which will not be required at that time.
- const { data: clusters } = useObjectStorageClusters();
+ const { data: clusters } = useObjectStorageClusters(
+ !isObjMultiClusterEnabled
+ );
const { data: regions } = useRegionsQuery();
const { data: profile } = useProfile();
const actualCluster = clusters?.find((c) => c.id === cluster);
diff --git a/packages/manager/src/features/ObjectStorage/BucketLanding/BucketLanding.tsx b/packages/manager/src/features/ObjectStorage/BucketLanding/BucketLanding.tsx
index 6dbf4a5bba9..fa13b3a6bb4 100644
--- a/packages/manager/src/features/ObjectStorage/BucketLanding/BucketLanding.tsx
+++ b/packages/manager/src/features/ObjectStorage/BucketLanding/BucketLanding.tsx
@@ -3,8 +3,8 @@ import {
ObjectStorageCluster,
} from '@linode/api-v4/lib/object-storage';
import { APIError } from '@linode/api-v4/lib/types';
-import Grid from '@mui/material/Unstable_Grid2';
import { Theme } from '@mui/material/styles';
+import Grid from '@mui/material/Unstable_Grid2';
import * as React from 'react';
import { makeStyles } from 'tss-react/mui';
@@ -17,6 +17,8 @@ import OrderBy from 'src/components/OrderBy';
import { TransferDisplay } from 'src/components/TransferDisplay/TransferDisplay';
import { TypeToConfirmDialog } from 'src/components/TypeToConfirmDialog/TypeToConfirmDialog';
import { Typography } from 'src/components/Typography';
+import { useAccountManagement } from 'src/hooks/useAccountManagement';
+import { useFlags } from 'src/hooks/useFlags';
import { useOpenClose } from 'src/hooks/useOpenClose';
import {
BucketError,
@@ -26,6 +28,7 @@ import {
} from 'src/queries/objectStorage';
import { useProfile } from 'src/queries/profile';
import { useRegionsQuery } from 'src/queries/regions/regions';
+import { isFeatureEnabled } from 'src/utilities/accountCapabilities';
import {
sendDeleteBucketEvent,
sendDeleteBucketFailedEvent,
@@ -48,17 +51,44 @@ export const BucketLanding = () => {
const isRestrictedUser = profile?.restricted;
+ const { account } = useAccountManagement();
+ const flags = useFlags();
+
+ const isObjMultiClusterEnabled = isFeatureEnabled(
+ 'Object Storage Access Key Regions',
+ Boolean(flags.objMultiCluster),
+ account?.capabilities ?? []
+ );
+
+ const { data: regions } = useRegionsQuery();
+
+ const regionsSupportingObjectStorage = regions?.filter((region) =>
+ region.capabilities.includes('Object Storage')
+ );
+
const {
data: objectStorageClusters,
error: clustersErrors,
isLoading: areClustersLoading,
- } = useObjectStorageClusters();
-
+ } = useObjectStorageClusters(!isObjMultiClusterEnabled);
+
+ /*
+ @TODO OBJ Multicluster:'region' will become required, and the
+ 'cluster' field will be deprecated once the feature is fully rolled out in production.
+ As part of the process of cleaning up after the 'objMultiCluster' feature flag, we will
+ remove 'cluster' and retain 'regions'.
+ */
const {
data: objectStorageBucketsResponse,
error: bucketsErrors,
isLoading: areBucketsLoading,
- } = useObjectStorageBuckets(objectStorageClusters);
+ } = useObjectStorageBuckets({
+ clusters: isObjMultiClusterEnabled ? undefined : objectStorageClusters,
+ isObjMultiClusterEnabled,
+ regions: isObjMultiClusterEnabled
+ ? regionsSupportingObjectStorage
+ : undefined,
+ });
const { mutateAsync: deleteBucket } = useDeleteBucketMutation();
diff --git a/packages/manager/src/features/ObjectStorage/BucketLanding/BucketRegions.test.tsx b/packages/manager/src/features/ObjectStorage/BucketLanding/BucketRegions.test.tsx
index 81062f8a955..005f1866dcf 100644
--- a/packages/manager/src/features/ObjectStorage/BucketLanding/BucketRegions.test.tsx
+++ b/packages/manager/src/features/ObjectStorage/BucketLanding/BucketRegions.test.tsx
@@ -26,7 +26,7 @@ const mockRegions = {
// Mock data as needed
error: null,
};
-vi.mock('src/queries/regions', () => ({
+vi.mock('src/queries/regions/regions', () => ({
useRegionsQuery: vi.fn(() => mockRegions),
}));
diff --git a/packages/manager/src/features/ObjectStorage/BucketLanding/BucketTableRow.tsx b/packages/manager/src/features/ObjectStorage/BucketLanding/BucketTableRow.tsx
index e5380629769..a8cf7a76563 100644
--- a/packages/manager/src/features/ObjectStorage/BucketLanding/BucketTableRow.tsx
+++ b/packages/manager/src/features/ObjectStorage/BucketLanding/BucketTableRow.tsx
@@ -42,7 +42,6 @@ export const BucketTableRow = (props: BucketTableRowProps) => {
size,
} = props;
- const { data: clusters } = useObjectStorageClusters();
const { data: regions } = useRegionsQuery();
const flags = useFlags();
@@ -54,6 +53,10 @@ export const BucketTableRow = (props: BucketTableRowProps) => {
account?.capabilities ?? []
);
+ const { data: clusters } = useObjectStorageClusters(
+ !isObjMultiClusterEnabled
+ );
+
const actualCluster = clusters?.find((c) => c.id === cluster);
const clusterRegion = regions?.find((r) => r.id === actualCluster?.region);
diff --git a/packages/manager/src/features/ObjectStorage/BucketLanding/CreateBucketDrawer.tsx b/packages/manager/src/features/ObjectStorage/BucketLanding/CreateBucketDrawer.tsx
index 9b0aed7ffc1..9b4997e76ed 100644
--- a/packages/manager/src/features/ObjectStorage/BucketLanding/CreateBucketDrawer.tsx
+++ b/packages/manager/src/features/ObjectStorage/BucketLanding/CreateBucketDrawer.tsx
@@ -7,6 +7,8 @@ import { Drawer } from 'src/components/Drawer';
import { Notice } from 'src/components/Notice/Notice';
import { TextField } from 'src/components/TextField';
import { EUAgreementCheckbox } from 'src/features/Account/Agreements/EUAgreementCheckbox';
+import { useAccountManagement } from 'src/hooks/useAccountManagement';
+import { useFlags } from 'src/hooks/useFlags';
import {
reportAgreementSigningError,
useAccountAgreements,
@@ -20,6 +22,7 @@ import {
} from 'src/queries/objectStorage';
import { useProfile } from 'src/queries/profile';
import { useRegionsQuery } from 'src/queries/regions/regions';
+import { isFeatureEnabled } from 'src/utilities/accountCapabilities';
import { sendCreateBucketEvent } from 'src/utilities/analytics';
import { getErrorMap } from 'src/utilities/errorUtils';
import { getGDPRDetails } from 'src/utilities/formatRegion';
@@ -37,9 +40,40 @@ export const CreateBucketDrawer = (props: Props) => {
const { data: profile } = useProfile();
const { isOpen, onClose } = props;
const isRestrictedUser = profile?.restricted;
+
+ const { account } = useAccountManagement();
+ const flags = useFlags();
+
+ const isObjMultiClusterEnabled = isFeatureEnabled(
+ 'Object Storage Access Key Regions',
+ Boolean(flags.objMultiCluster),
+ account?.capabilities ?? []
+ );
+
const { data: regions } = useRegionsQuery();
- const { data: clusters } = useObjectStorageClusters();
- const { data: buckets } = useObjectStorageBuckets(clusters);
+
+ const { data: clusters } = useObjectStorageClusters(
+ !isObjMultiClusterEnabled
+ );
+
+ const regionsSupportingObjectStorage = regions?.filter((region) =>
+ region.capabilities.includes('Object Storage')
+ );
+
+ /*
+ @TODO OBJ Multicluster:'region' will become required, and the
+ 'cluster' field will be deprecated once the feature is fully rolled out in production.
+ As part of the process of cleaning up after the 'objMultiCluster' feature flag, we will
+ remove 'cluster' and retain 'regions'.
+ */
+ const { data: buckets } = useObjectStorageBuckets({
+ clusters: isObjMultiClusterEnabled ? undefined : clusters,
+ isObjMultiClusterEnabled,
+ regions: isObjMultiClusterEnabled
+ ? regionsSupportingObjectStorage
+ : undefined,
+ });
+
const {
error,
isLoading,
diff --git a/packages/manager/src/features/ObjectStorage/BucketLanding/OMC_BucketLanding.tsx b/packages/manager/src/features/ObjectStorage/BucketLanding/OMC_BucketLanding.tsx
index 4c125d8e9b9..4696261d123 100644
--- a/packages/manager/src/features/ObjectStorage/BucketLanding/OMC_BucketLanding.tsx
+++ b/packages/manager/src/features/ObjectStorage/BucketLanding/OMC_BucketLanding.tsx
@@ -1,8 +1,8 @@
import { Region } from '@linode/api-v4';
import { ObjectStorageBucket } from '@linode/api-v4/lib/object-storage';
import { APIError } from '@linode/api-v4/lib/types';
-import Grid from '@mui/material/Unstable_Grid2';
import { Theme } from '@mui/material/styles';
+import Grid from '@mui/material/Unstable_Grid2';
import * as React from 'react';
import { makeStyles } from 'tss-react/mui';
@@ -15,14 +15,17 @@ import OrderBy from 'src/components/OrderBy';
import { TransferDisplay } from 'src/components/TransferDisplay/TransferDisplay';
import { TypeToConfirmDialog } from 'src/components/TypeToConfirmDialog/TypeToConfirmDialog';
import { Typography } from 'src/components/Typography';
+import { useAccountManagement } from 'src/hooks/useAccountManagement';
+import { useFlags } from 'src/hooks/useFlags';
import { useOpenClose } from 'src/hooks/useOpenClose';
import {
BucketError,
useDeleteBucketWithRegionMutation,
- useObjectStorageBucketsFromRegions,
+ useObjectStorageBuckets,
} from 'src/queries/objectStorage';
import { useProfile } from 'src/queries/profile';
import { useRegionsQuery } from 'src/queries/regions/regions';
+import { isFeatureEnabled } from 'src/utilities/accountCapabilities';
import {
sendDeleteBucketEvent,
sendDeleteBucketFailedEvent,
@@ -46,6 +49,15 @@ export const OMC_BucketLanding = () => {
const isRestrictedUser = profile?.restricted;
+ const { account } = useAccountManagement();
+ const flags = useFlags();
+
+ const isObjMultiClusterEnabled = isFeatureEnabled(
+ 'Object Storage Access Key Regions',
+ Boolean(flags.objMultiCluster),
+ account?.capabilities ?? []
+ );
+
const {
data: regions,
error: regionErrors,
@@ -54,7 +66,7 @@ export const OMC_BucketLanding = () => {
const regionsLookup = regions && getRegionsByRegionId(regions);
- const regionsSupportObjectStorage = regions?.filter((region) =>
+ const regionsSupportingObjectStorage = regions?.filter((region) =>
region.capabilities.includes('Object Storage')
);
@@ -62,7 +74,10 @@ export const OMC_BucketLanding = () => {
data: objectStorageBucketsResponse,
error: bucketsErrors,
isLoading: areBucketsLoading,
- } = useObjectStorageBucketsFromRegions(regionsSupportObjectStorage);
+ } = useObjectStorageBuckets({
+ isObjMultiClusterEnabled,
+ regions: regionsSupportingObjectStorage,
+ });
const { mutateAsync: deleteBucket } = useDeleteBucketWithRegionMutation();
diff --git a/packages/manager/src/features/ObjectStorage/BucketLanding/OMC_CreateBucketDrawer.tsx b/packages/manager/src/features/ObjectStorage/BucketLanding/OMC_CreateBucketDrawer.tsx
index 6816b48124b..55c17b9cb3e 100644
--- a/packages/manager/src/features/ObjectStorage/BucketLanding/OMC_CreateBucketDrawer.tsx
+++ b/packages/manager/src/features/ObjectStorage/BucketLanding/OMC_CreateBucketDrawer.tsx
@@ -5,6 +5,8 @@ import { ActionsPanel } from 'src/components/ActionsPanel/ActionsPanel';
import { Drawer } from 'src/components/Drawer';
import { Notice } from 'src/components/Notice/Notice';
import { TextField } from 'src/components/TextField';
+import { useAccountManagement } from 'src/hooks/useAccountManagement';
+import { useFlags } from 'src/hooks/useFlags';
import {
reportAgreementSigningError,
useAccountAgreements,
@@ -14,10 +16,10 @@ import { useAccountSettings } from 'src/queries/account/settings';
import {
useCreateBucketMutation,
useObjectStorageBuckets,
- useObjectStorageClusters,
} from 'src/queries/objectStorage';
import { useProfile } from 'src/queries/profile';
import { useRegionsQuery } from 'src/queries/regions/regions';
+import { isFeatureEnabled } from 'src/utilities/accountCapabilities';
import { sendCreateBucketEvent } from 'src/utilities/analytics';
import { getErrorMap } from 'src/utilities/errorUtils';
import { getGDPRDetails } from 'src/utilities/formatRegion';
@@ -36,10 +38,25 @@ export const OMC_CreateBucketDrawer = (props: Props) => {
const { data: profile } = useProfile();
const { isOpen, onClose } = props;
const isRestrictedUser = profile?.restricted;
+ const { account } = useAccountManagement();
+ const flags = useFlags();
+
+ const isObjMultiClusterEnabled = isFeatureEnabled(
+ 'Object Storage Access Key Regions',
+ Boolean(flags.objMultiCluster),
+ account?.capabilities ?? []
+ );
+
const { data: regions } = useRegionsQuery();
- // @TODO OBJ Multicluster - clusters will likely to be replaced with regions and will be taken care in future tickets.
- const { data: clusters } = useObjectStorageClusters();
- const { data: buckets } = useObjectStorageBuckets(clusters);
+
+ const regionsSupportingObjectStorage = regions?.filter((region) =>
+ region.capabilities.includes('Object Storage')
+ );
+
+ const { data: buckets } = useObjectStorageBuckets({
+ isObjMultiClusterEnabled,
+ regions: regionsSupportingObjectStorage,
+ });
const {
error,
diff --git a/packages/manager/src/features/ObjectStorage/ObjectStorageLanding.tsx b/packages/manager/src/features/ObjectStorage/ObjectStorageLanding.tsx
index 31ab0718237..fc383f3caac 100644
--- a/packages/manager/src/features/ObjectStorage/ObjectStorageLanding.tsx
+++ b/packages/manager/src/features/ObjectStorage/ObjectStorageLanding.tsx
@@ -22,6 +22,7 @@ import {
useObjectStorageBuckets,
useObjectStorageClusters,
} from 'src/queries/objectStorage';
+import { useRegionsQuery } from 'src/queries/regions/regions';
import { isFeatureEnabled } from 'src/utilities/accountCapabilities';
import { MODE } from './AccessKeyLanding/types';
@@ -53,12 +54,43 @@ export const ObjectStorageLanding = () => {
account,
accountSettings,
} = useAccountManagement();
- const { data: objectStorageClusters } = useObjectStorageClusters();
+
+ const flags = useFlags();
+
+ const isObjMultiClusterEnabled = isFeatureEnabled(
+ 'Object Storage Access Key Regions',
+ Boolean(flags.objMultiCluster),
+ account?.capabilities ?? []
+ );
+
+ const { data: objectStorageClusters } = useObjectStorageClusters(
+ !isObjMultiClusterEnabled
+ );
+
+ const { data: regionsData } = useRegionsQuery();
+
+ const regionsSupportingObjectStorage = regionsData?.filter((region) =>
+ region.capabilities.includes('Object Storage')
+ );
+
+ /*
+ @TODO OBJ Multicluster:'region' will become required, and the
+ 'cluster' field will be deprecated once the feature is fully rolled out in production.
+ As part of the process of cleaning up after the 'objMultiCluster' feature flag, we will
+ remove 'cluster' and retain 'regions'.
+ */
const {
data: objectStorageBucketsResponse,
error: bucketsErrors,
isLoading: areBucketsLoading,
- } = useObjectStorageBuckets(objectStorageClusters);
+ } = useObjectStorageBuckets({
+ clusters: isObjMultiClusterEnabled ? undefined : objectStorageClusters,
+ isObjMultiClusterEnabled,
+ regions: isObjMultiClusterEnabled
+ ? regionsSupportingObjectStorage
+ : undefined,
+ });
+
const userHasNoBucketCreated =
objectStorageBucketsResponse?.buckets.length === 0;
const createOrEditDrawer = useOpenClose();
@@ -85,14 +117,6 @@ export const ObjectStorageLanding = () => {
history.push(tabs[index].routeName);
};
- const flags = useFlags();
-
- const isObjMultiClusterEnabled = isFeatureEnabled(
- 'Object Storage Access Key Regions',
- Boolean(flags.objMultiCluster),
- account?.capabilities ?? []
- );
-
const objPromotionalOffers = (
flags.promotionalOffers ?? []
).filter((promotionalOffer) =>
diff --git a/packages/manager/src/features/PlacementGroups/PlacementGroupsAssignLinodesDrawer.test.tsx b/packages/manager/src/features/PlacementGroups/PlacementGroupsAssignLinodesDrawer.test.tsx
index 2c158d6bf19..9395d3b5e09 100644
--- a/packages/manager/src/features/PlacementGroups/PlacementGroupsAssignLinodesDrawer.test.tsx
+++ b/packages/manager/src/features/PlacementGroups/PlacementGroupsAssignLinodesDrawer.test.tsx
@@ -12,9 +12,8 @@ import { PlacementGroupsAssignLinodesDrawer } from './PlacementGroupsAssignLinod
const queryMocks = vi.hoisted(() => ({
useAllLinodesQuery: vi.fn().mockReturnValue({}),
- useAssignLinodesToPlacementGroup: vi.fn().mockReturnValue({}),
- useRegionsQuery: vi.fn().mockReturnValue({}),
useAllPlacementGroupsQuery: vi.fn().mockReturnValue({}),
+ useAssignLinodesToPlacementGroup: vi.fn().mockReturnValue({}),
}));
vi.mock('src/queries/linodes/linodes', async () => {
@@ -33,14 +32,6 @@ vi.mock('src/queries/placementGroups', async () => {
};
});
-vi.mock('src/queries/regions/regions', async () => {
- const actual = await vi.importActual('src/queries/regions/regions');
- return {
- ...actual,
- useRegionsQuery: queryMocks.useRegionsQuery,
- };
-});
-
vi.mock('src/queries/placementGroups', async () => {
const actual = await vi.importActual('src/queries/placementGroups');
return {
@@ -60,6 +51,7 @@ describe('PlacementGroupsAssignLinodesDrawer', () => {
);
@@ -75,7 +67,6 @@ describe('PlacementGroupsAssignLinodesDrawer', () => {
linodeFactory.build({ id: 11, label: 'Linode-11', region: 'us-east' }),
],
});
- queryMocks.useRegionsQuery.mockReturnValue(regionFactory.buildList(5));
queryMocks.useAllPlacementGroupsQuery.mockReturnValue({
data: placementGroupFactory.build(),
});
@@ -135,6 +126,7 @@ describe('PlacementGroupsAssignLinodesDrawer', () => {
})}
onClose={vi.fn()}
open={true}
+ region={regionFactory.build()}
/>
);
diff --git a/packages/manager/src/features/PlacementGroups/PlacementGroupsAssignLinodesDrawer.tsx b/packages/manager/src/features/PlacementGroups/PlacementGroupsAssignLinodesDrawer.tsx
index 821645bd3af..8b34fdf99d7 100644
--- a/packages/manager/src/features/PlacementGroups/PlacementGroupsAssignLinodesDrawer.tsx
+++ b/packages/manager/src/features/PlacementGroups/PlacementGroupsAssignLinodesDrawer.tsx
@@ -4,24 +4,25 @@ import * as React from 'react';
import { ActionsPanel } from 'src/components/ActionsPanel/ActionsPanel';
import { Box } from 'src/components/Box';
+import { DescriptionList } from 'src/components/DescriptionList/DescriptionList';
import { Divider } from 'src/components/Divider';
import { Drawer } from 'src/components/Drawer';
-import { Link } from 'src/components/Link';
import { Notice } from 'src/components/Notice/Notice';
import { Stack } from 'src/components/Stack';
import { TooltipIcon } from 'src/components/TooltipIcon';
import { Typography } from 'src/components/Typography';
-import { usePlacementGroupData } from 'src/hooks/usePlacementGroupsData';
import { useAllLinodesQuery } from 'src/queries/linodes/linodes';
import {
- useAssignLinodesToPlacementGroup,
useAllPlacementGroupsQuery,
+ useAssignLinodesToPlacementGroup,
} from 'src/queries/placementGroups';
+import { getErrorStringOrDefault } from 'src/utilities/errorUtils';
import { LinodeSelect } from '../Linodes/LinodeSelect/LinodeSelect';
import {
getAffinityTypeEnforcement,
getLinodesFromAllPlacementGroups,
+ hasPlacementGroupReachedCapacity,
} from './utils';
import type { PlacementGroupsAssignLinodesDrawerProps } from './types';
@@ -33,7 +34,7 @@ import type {
export const PlacementGroupsAssignLinodesDrawer = (
props: PlacementGroupsAssignLinodesDrawerProps
) => {
- const { onClose, open, selectedPlacementGroup } = props;
+ const { onClose, open, region, selectedPlacementGroup } = props;
const { data: allLinodesInRegion, error: linodesError } = useAllLinodesQuery(
{},
{
@@ -47,13 +48,15 @@ export const PlacementGroupsAssignLinodesDrawer = (
const { enqueueSnackbar } = useSnackbar();
// We display a notice and disable inputs in case the user reaches this drawer somehow
- // (not supposed to happen as the "Assign Linode to Placement Group" button should be disabled
- const { hasReachedCapacity, region } = usePlacementGroupData({
+ // (not supposed to happen as the "Assign Linode to Placement Group" button should be disabled)
+ const hasReachedCapacity = hasPlacementGroupReachedCapacity({
placementGroup: selectedPlacementGroup,
+ region,
});
- const { mutateAsync: assignLinodes } = useAssignLinodesToPlacementGroup(
- selectedPlacementGroup?.id ?? -1
- );
+ const {
+ isLoading,
+ mutateAsync: assignLinodes,
+ } = useAssignLinodesToPlacementGroup(selectedPlacementGroup?.id ?? -1);
const [selectedLinode, setSelectedLinode] = React.useState
(
null
);
@@ -93,16 +96,11 @@ export const PlacementGroupsAssignLinodesDrawer = (
return null;
}
- const { affinity_type, label } = selectedPlacementGroup;
+ const { affinity_type, is_strict, label } = selectedPlacementGroup;
const linodeSelectLabel = region
? `Linodes in ${region.label} (${region.id})`
: 'Linodes';
- const drawerTitle =
- label && affinity_type
- ? `Assign Linodes to Placement Group ${label} (${AFFINITY_TYPES[affinity_type]})`
- : 'Assign Linodes to Placement Group';
-
const handleAssignLinode = async (e: React.SyntheticEvent) => {
e.preventDefault();
setSelectedLinode(null);
@@ -124,24 +122,37 @@ export const PlacementGroupsAssignLinodesDrawer = (
variant: 'success',
});
handleDrawerClose();
- } catch (error) {
- setGeneralError(
- error?.[0]?.reason
- ? error[0].reason
- : 'An error occurred while adding the Linode to the group'
+ } catch (errorResponse) {
+ const error = getErrorStringOrDefault(
+ errorResponse,
+ 'An error occurred while adding the Linode to the group'
);
- enqueueSnackbar(error[0]?.reason, { variant: 'error' });
+ setGeneralError(error);
+ enqueueSnackbar(error, { variant: 'error' });
}
};
return (
-
+
{generalError ? : null}
-
- Affinity Enforcement:
- {getAffinityTypeEnforcement(selectedPlacementGroup.is_strict)}
-
-
+
+