Skip to content

Commit b39d3e7

Browse files
change: [UIE-8228] - DBaaS Resize GA: Enable Downsizing, update node presentation (linode#11311)
* change: [UIE-8228] - DBaaS Resize GA: Enable Downsizing, update node presentation * Added changeset: DBaaS Resize GA: Enable Downsizing (horizontal and vertical), enable 'Shared' tab, updated node presentation * clean up unit test * try to fix flake * revert changes --------- Co-authored-by: Banks Nussman <[email protected]>
1 parent 8c11b28 commit b39d3e7

File tree

10 files changed

+68
-102
lines changed

10 files changed

+68
-102
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@linode/manager": Changed
3+
---
4+
5+
DBaaS Resize GA: Enable Downsizing (horizontal and vertical), enable 'Shared' tab, updated node presentation ([#11311](https://github.com/linode/manager/pull/11311))

packages/manager/src/features/Databases/DatabaseCreate/DatabaseNodeSelector.tsx

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import type {
1414
DatabasePriceObject,
1515
Engine,
1616
} from '@linode/api-v4/lib/databases/types';
17-
import type { Theme } from '@mui/material';
1817
import type {
1918
PlanSelectionType,
2019
PlanSelectionWithDatabaseType,
@@ -36,9 +35,6 @@ interface Props {
3635
selectedPlan: PlanSelectionWithDatabaseType | undefined;
3736
selectedTab: number;
3837
}
39-
const typographyBaseStyles = (theme: Theme) => ({
40-
color: theme.palette.mode === 'dark' ? theme.color.grey6 : theme.color.grey1,
41-
});
4238

4339
export const DatabaseNodeSelector = (props: Props) => {
4440
const {
@@ -87,17 +83,10 @@ export const DatabaseNodeSelector = (props: Props) => {
8783
/>
8884
);
8985

90-
const isDisabled = (nodeSize: ClusterSize) => {
91-
return currentClusterSize && nodeSize < currentClusterSize;
92-
};
93-
9486
const options = [
9587
{
9688
label: (
97-
<Typography
98-
component="div"
99-
sx={isDisabled(1) ? typographyBaseStyles : undefined}
100-
>
89+
<Typography component="div">
10190
<span>1 Node {` `}</span>
10291
{currentClusterSize === 1 && currentChip}
10392
<br />
@@ -115,10 +104,7 @@ export const DatabaseNodeSelector = (props: Props) => {
115104
if (hasDedicated && selectedTab === 0 && isDatabasesV2Enabled) {
116105
options.push({
117106
label: (
118-
<Typography
119-
component="div"
120-
sx={isDisabled(2) ? typographyBaseStyles : undefined}
121-
>
107+
<Typography component="div">
122108
<span>2 Nodes - High Availability</span>
123109
{currentClusterSize === 2 && currentChip}
124110
<br />
@@ -135,10 +121,7 @@ export const DatabaseNodeSelector = (props: Props) => {
135121

136122
options.push({
137123
label: (
138-
<Typography
139-
component="div"
140-
sx={isDisabled(3) ? typographyBaseStyles : undefined}
141-
>
124+
<Typography component="div">
142125
<span>3 Nodes - High Availability (recommended)</span>
143126
{currentClusterSize === 3 && currentChip}
144127
<br />
@@ -186,9 +169,6 @@ export const DatabaseNodeSelector = (props: Props) => {
186169
>
187170
{nodeOptions.map((nodeOption) => (
188171
<FormControlLabel
189-
disabled={
190-
currentClusterSize && nodeOption.value < currentClusterSize
191-
}
192172
control={<Radio />}
193173
data-qa-radio={nodeOption.label}
194174
data-testid={`database-node-${nodeOption.value}`}

packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResize.test.tsx

Lines changed: 9 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -270,17 +270,6 @@ describe('database resize', () => {
270270
expect(selectedNodeRadioButton).toBeChecked();
271271
});
272272

273-
it('should disable visible lower node selections', async () => {
274-
const { getByTestId } = renderWithTheme(
275-
<DatabaseResize database={mockDatabase} />,
276-
{ flags }
277-
);
278-
await waitForElementToBeRemoved(getByTestId(loadingTestId));
279-
const selectedNodeRadioButton = getByTestId('database-node-1').children[0]
280-
.children[0] as HTMLInputElement;
281-
expect(selectedNodeRadioButton).toBeDisabled();
282-
});
283-
284273
it('should set price, enable resize button, and update resize summary when a new number of nodes is selected', async () => {
285274
const mockDatabase = databaseFactory.build({
286275
cluster_size: 1,
@@ -395,52 +384,21 @@ describe('database resize', () => {
395384
},
396385
};
397386

398-
const { findByTestId } = renderWithTheme(
387+
const { getByRole, getByTestId } = renderWithTheme(
399388
<DatabaseResize database={mockDatabase} />,
400389
{ flags }
401390
);
391+
expect(getByTestId(loadingTestId)).toBeInTheDocument();
392+
await waitForElementToBeRemoved(getByTestId(loadingTestId));
402393

403-
expect(await findByTestId('database-nodes')).toBeDefined();
404-
expect(await findByTestId('database-node-1')).toBeDefined();
405-
expect(await findByTestId('database-node-2')).toBeDefined();
406-
expect(await findByTestId('database-node-3')).toBeDefined();
407-
});
408-
409-
it('should disable lower node selections', async () => {
410-
const mockDatabase = databaseFactory.build({
411-
cluster_size: 3,
412-
platform: 'rdbms-default',
413-
type: 'g6-dedicated-2',
414-
});
415-
416-
const flags = {
417-
dbaasV2: {
418-
beta: false,
419-
enabled: true,
420-
},
421-
};
394+
const dedicatedTab = getByRole('tab', { name: 'Dedicated CPU' });
422395

423-
// Mock route history so the Plan Selection table displays prices without requiring a region in the DB resize flow.
424-
const history = createMemoryHistory();
425-
history.push(`databases/${database.engine}/${database.id}/resize`);
396+
await userEvent.click(dedicatedTab);
426397

427-
const { getByTestId } = renderWithTheme(
428-
<Router history={history}>
429-
<DatabaseResize database={mockDatabase} />
430-
</Router>,
431-
{ flags }
432-
);
433-
expect(getByTestId(loadingTestId)).toBeInTheDocument();
434-
await waitForElementToBeRemoved(getByTestId(loadingTestId));
435-
expect(
436-
getByTestId('database-node-1').children[0].children[0]
437-
).toBeDisabled();
438-
expect(
439-
getByTestId('database-node-2').children[0].children[0]
440-
).toBeDisabled();
441-
expect(
442-
getByTestId('database-node-3').children[0].children[0]
443-
).toBeEnabled();
398+
expect(getByTestId('database-nodes')).toBeDefined();
399+
expect(getByTestId('database-node-1')).toBeDefined();
400+
expect(getByTestId('database-node-2')).toBeDefined();
401+
expect(getByTestId('database-node-3')).toBeDefined();
444402
});
445403
});
446404

packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResize.tsx

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ import { DatabaseSummarySection } from 'src/features/Databases/DatabaseCreate/Da
1818
import { DatabaseResizeCurrentConfiguration } from 'src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration';
1919
import { useIsDatabasesEnabled } from 'src/features/Databases/utilities';
2020
import { typeLabelDetails } from 'src/features/Linodes/presentation';
21-
import { useDatabaseMutation } from 'src/queries/databases/databases';
2221
import { useDatabaseTypesQuery } from 'src/queries/databases/databases';
22+
import { useDatabaseMutation } from 'src/queries/databases/databases';
2323
import { formatStorageUnits } from 'src/utilities/formatStorageUnits';
24+
import { convertMegabytesTo } from 'src/utilities/unitConversions';
2425

2526
import {
2627
StyledGrid,
@@ -81,7 +82,7 @@ export const DatabaseResize = ({ database, disabled = false }: Props) => {
8182
const onResize = () => {
8283
const payload: UpdateDatabasePayload = {};
8384

84-
if (clusterSize && clusterSize > database.cluster_size && isDatabasesV2GA) {
85+
if (clusterSize && isDatabasesV2GA) {
8586
payload.cluster_size = clusterSize;
8687
}
8788

@@ -110,8 +111,7 @@ export const DatabaseResize = ({ database, disabled = false }: Props) => {
110111
const selectedEngine = database.engine.split('/')[0] as Engine;
111112

112113
const summaryText = React.useMemo(() => {
113-
const nodeSelected = clusterSize && clusterSize > database.cluster_size;
114-
114+
const nodeSelected = clusterSize && clusterSize !== database.cluster_size;
115115
const isSamePlanSelected = selectedPlanId === database.type;
116116
if (!dbTypes) {
117117
return undefined;
@@ -173,13 +173,19 @@ export const DatabaseResize = ({ database, disabled = false }: Props) => {
173173
if (!dbTypes) {
174174
return [];
175175
}
176+
176177
return dbTypes.map((type: DatabaseType) => {
177178
const { label } = type;
178179
const formattedLabel = formatStorageUnits(label);
179-
const nodePricing = type.engines[selectedEngine].find(
180-
(cluster: DatabaseClusterSizeObject) =>
181-
cluster.quantity === database.cluster_size
180+
181+
const nodePricing = type.engines[
182+
selectedEngine
183+
].find((cluster: DatabaseClusterSizeObject) =>
184+
selectedTab === 1 && database.cluster_size === 2
185+
? cluster.quantity === 3
186+
: cluster.quantity === clusterSize
182187
);
188+
183189
const price = nodePricing?.price ?? {
184190
hourly: null,
185191
monthly: null,
@@ -196,7 +202,7 @@ export const DatabaseResize = ({ database, disabled = false }: Props) => {
196202
subHeadings,
197203
};
198204
});
199-
}, [database.cluster_size, dbTypes, selectedEngine]);
205+
}, [database.cluster_size, dbTypes, selectedEngine, selectedTab]);
200206

201207
const currentPlan = displayTypes?.find((type) => type.id === database.type);
202208

@@ -207,14 +213,23 @@ export const DatabaseResize = ({ database, disabled = false }: Props) => {
207213
currentPlan?.heading
208214
);
209215
setSelectedTab(initialTab);
210-
}, [database.type, displayTypes]);
216+
}, []);
211217

212218
const currentPlanDisk = currentPlan ? currentPlan.disk : 0;
213-
const disabledPlans = displayTypes?.filter((type) =>
214-
type.class === 'dedicated'
215-
? type.disk < currentPlanDisk
216-
: type.disk <= currentPlanDisk
217-
);
219+
const disabledPlans = !isNewDatabaseGA
220+
? displayTypes?.filter((type) =>
221+
type.class === 'dedicated'
222+
? type.disk < currentPlanDisk
223+
: type.disk <= currentPlanDisk
224+
)
225+
: displayTypes?.filter(
226+
(type) =>
227+
database?.used_disk_size_gb &&
228+
database.used_disk_size_gb >
229+
+convertMegabytesTo(type.disk, true)
230+
.split(/(GB|MB|KB)/i)[0]
231+
.trim()
232+
);
218233
const isDisabledSharedTab = database.cluster_size === 2;
219234

220235
const shouldSubmitBeDisabled = React.useMemo(() => {
@@ -249,7 +264,7 @@ export const DatabaseResize = ({ database, disabled = false }: Props) => {
249264
setSelectedPlanId(database.type);
250265
setClusterSize(database.cluster_size);
251266
} else {
252-
setClusterSize(undefined);
267+
setClusterSize(3);
253268
setSelectedPlanId(undefined);
254269
}
255270
}
@@ -274,11 +289,13 @@ export const DatabaseResize = ({ database, disabled = false }: Props) => {
274289
</Paper>
275290
<Paper sx={{ marginTop: 2 }}>
276291
<StyledPlansPanel
292+
disabledTabs={
293+
!isNewDatabaseGA && isDisabledSharedTab ? ['shared'] : []
294+
}
277295
currentPlanHeading={currentPlan?.heading}
278296
data-qa-select-plan
279297
disabled={disabled}
280298
disabledSmallerPlans={disabledPlans}
281-
disabledTabs={isDisabledSharedTab ? ['shared'] : []}
282299
handleTabChange={handleTabChange}
283300
header="Choose a Plan"
284301
onSelect={(selected: string) => setSelectedPlanId(selected)}

packages/manager/src/features/Databases/DatabaseDetail/DatabaseResize/DatabaseResizeCurrentConfiguration.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,10 @@ export const DatabaseResizeCurrentConfiguration = ({ database }: Props) => {
5757

5858
const configuration =
5959
database.cluster_size === 1
60-
? 'Primary'
61-
: `Primary +${database.cluster_size - 1} replicas`;
60+
? 'Primary (1 Node)'
61+
: database.cluster_size > 2
62+
? `Primary (+${database.cluster_size - 1} Nodes)`
63+
: `Primary (+${database.cluster_size - 1} Node)`;
6264

6365
const sxTooltipIcon = {
6466
marginLeft: 0.5,

packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummary.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import { DatabaseSummary } from './DatabaseSummary';
1111
import type { Database } from '@linode/api-v4';
1212

1313
const CLUSTER_CONFIGURATION = 'Cluster Configuration';
14-
const THREE_NODE = 'Primary +2 replicas';
15-
const TWO_NODE = 'Primary +1 replicas';
14+
const THREE_NODE = 'Primary (+2 Nodes)';
15+
const TWO_NODE = 'Primary (+1 Node)';
1616
const VERSION = 'Version';
1717

1818
const CONNECTION_DETAILS = 'Connection Details';

packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import type { Database, DatabaseStatus } from '@linode/api-v4/lib/databases';
1111

1212
const STATUS_VALUE = 'Active';
1313
const PLAN_VALUE = 'New DBaaS - Dedicated 8 GB';
14-
const NODES_VALUE = 'Primary +1 replicas';
14+
const NODES_VALUE = 'Primary (+1 Node)';
1515
const REGION_ID = 'us-east';
1616
const REGION_LABEL = 'Newark, NJ';
1717

@@ -150,7 +150,7 @@ describe('DatabaseSummaryClusterConfiguration', () => {
150150
expect(queryAllByText('Nanode 1 GB')).toHaveLength(1);
151151

152152
expect(queryAllByText('Nodes')).toHaveLength(1);
153-
expect(queryAllByText('Primary')).toHaveLength(1);
153+
expect(queryAllByText('Primary (1 Node)')).toHaveLength(1);
154154

155155
expect(queryAllByText('CPUs')).toHaveLength(1);
156156
expect(queryAllByText(1)).toHaveLength(1);

packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,10 @@ export const DatabaseSummaryClusterConfiguration = (props: Props) => {
5555

5656
const configuration =
5757
database.cluster_size === 1
58-
? 'Primary'
59-
: `Primary +${database.cluster_size - 1} replicas`;
58+
? 'Primary (1 Node)'
59+
: database.cluster_size > 2
60+
? `Primary (+${database.cluster_size - 1} Nodes)`
61+
: `Primary (+${database.cluster_size - 1} Node)`;
6062

6163
const sxTooltipIcon = {
6264
marginLeft: '4px',

packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/legacy/DatabaseSummaryClusterConfigurationLegacy.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,10 @@ export const DatabaseSummaryClusterConfigurationLegacy = (props: Props) => {
6767

6868
const configuration =
6969
database.cluster_size === 1
70-
? 'Primary'
71-
: `Primary +${database.cluster_size - 1} replicas`;
70+
? 'Primary (1 Node)'
71+
: database.cluster_size > 2
72+
? `Primary (+${database.cluster_size - 1} Nodes)`
73+
: `Primary (+${database.cluster_size - 1} Node)`;
7274

7375
const sxTooltipIcon = {
7476
marginLeft: '4px',

packages/manager/src/features/components/PlansPanel/PlanSelection.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export const PlanSelection = (props: PlanSelectionProps) => {
8282
)}/mo ($${price?.hourly ?? UNKNOWN_PRICE}/hr)`;
8383

8484
const rowIsDisabled =
85-
isSamePlan ||
85+
(!isDatabaseFlow && isSamePlan) ||
8686
planIsTooSmall ||
8787
planBelongsToDisabledClass ||
8888
planIsDisabled512Gb ||
@@ -125,7 +125,7 @@ export const PlanSelection = (props: PlanSelectionProps) => {
125125
onClick={() => (!rowIsDisabled ? onSelect(plan.id) : undefined)}
126126
>
127127
<StyledRadioCell>
128-
{!isSamePlan && (
128+
{(!isSamePlan || (isDatabaseFlow && isSamePlan)) && (
129129
<FormControlLabel
130130
aria-label={`${plan.heading} ${
131131
rowIsDisabled ? `- ${disabledPlanReasonCopy}` : ''

0 commit comments

Comments
 (0)