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

DRAFT (for 1.3): Everest 777 topology #616

Open
wants to merge 30 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
f5d573f
chore: move resources form to separate component
fabio-silva Aug 9, 2024
87a2342
chore: edit resources via overview
fabio-silva Aug 12, 2024
5d7c463
feat: submit custom number of nodes
fabio-silva Aug 13, 2024
0f9b461
chore: remove log
fabio-silva Aug 13, 2024
f59c303
chore: improve defaults logic
fabio-silva Aug 13, 2024
b3dcd28
feat: add accordions
fabio-silva Aug 14, 2024
180c96e
feat: show number of nodes/proxies next to accordion summary
fabio-silva Aug 14, 2024
8eb55ff
chore: add different names for proxies
fabio-silva Aug 14, 2024
b694cbc
chore: form validation
fabio-silva Aug 14, 2024
18271d4
feat: set proxies=nodes
fabio-silva Aug 14, 2024
87bc9af
feat: submit proxy resources
fabio-silva Aug 14, 2024
fc267a9
Merge branch 'main' into EVEREST-777-topology
fabio-silva Aug 19, 2024
2408edc
chore: remove disk from proxies
fabio-silva Aug 19, 2024
8b99dd9
Merge branch 'main' into EVEREST-777-topology
fabio-silva Aug 19, 2024
e6633a3
Merge branch 'main' into EVEREST-777-topology
fabio-silva Aug 20, 2024
00f9cf4
fix: unit tests
fabio-silva Aug 20, 2024
140a882
fix: bad import
fabio-silva Aug 20, 2024
837e593
fix: bad data-testid
fabio-silva Aug 20, 2024
5127f61
fix: e2e selectors
fabio-silva Aug 20, 2024
ee09d9d
fix: e2e test
fabio-silva Aug 20, 2024
3e31846
chore: e2e test proxy resouces
fabio-silva Aug 20, 2024
7f96a11
Merge branch 'main' into EVEREST-777-topology
fabio-silva Aug 21, 2024
39d62a2
Merge branch 'main' into EVEREST-777-topology
fabio-silva Aug 22, 2024
fbcbc79
Merge branch 'main' into EVEREST-777-topology
fabio-silva Aug 22, 2024
5c60071
Merge branch 'main' into EVEREST-777-topology
fabio-silva Aug 23, 2024
6c2a896
Merge branch 'main' into EVEREST-777-topology
solovevayaroslavna Aug 26, 2024
be4cac8
Merge branch 'main' into EVEREST-777-topology
solovevayaroslavna Aug 29, 2024
aee49eb
Merge branch 'main' into EVEREST-777-topology
fabio-silva Sep 24, 2024
e27efa3
Merge branch 'main' into EVEREST-777-topology
fabio-silva Sep 24, 2024
2eb5301
chore: change default shards
fabio-silva Sep 24, 2024
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
Expand Up @@ -139,6 +139,18 @@ test.describe('DB Cluster creation', () => {
await expect(page.getByText('Nº nodes: 3')).toBeVisible();

await resourcesStepCheck(page);

// Same number of proxies as nodes, as user hasn't changed it
await expect(page.getByText('Routers (3)')).toBeVisible();
await page.getByTestId('proxies-accordion').getByRole('button').click();
await page.getByTestId('toggle-button-routers-1').click();
await expect(page.getByText('Routers (1)')).toBeVisible();
await page.getByTestId('nodes-accordion').getByRole('button').click();
await page.getByTestId('toggle-button-nodes-1').click();
await page.getByTestId('toggle-button-nodes-3').click();
// After used changed the number of routers, it should no more follow the number of nodes
await expect(page.getByText('Routers (1)')).toBeVisible();

await moveForward(page);

await backupsStepCheck(page);
Expand All @@ -162,7 +174,10 @@ test.describe('DB Cluster creation', () => {
// Now we change the number of nodes
await page.getByTestId('button-edit-preview-resources').click();
await page.getByTestId('toggle-button-nodes-3').click();
await expect(page.getByText('PG Bouncers (3)')).toBeVisible();
await page.getByTestId('toggle-button-nodes-2').click();
// Since we changed DB type, the number of bouncers is reset and will follow the number of nodes
await expect(page.getByText('PG Bouncers (2)')).toBeVisible();
await page.getByTestId('button-edit-preview-basic-information').click();
// Because 2 nodes is not valid for MongoDB, the default will be picked
await page.getByTestId('mongodb-toggle-button').click();
Expand Down Expand Up @@ -261,7 +276,7 @@ test.describe('DB Cluster creation', () => {
).toBeVisible();

await page.getByTestId('toggle-button-nodes-3').click();
await page.getByTestId('toggle-button-large').click();
await page.getByTestId('node-resources-toggle-button-large').click();
await page.getByTestId('text-input-disk').fill('150');
await moveForward(page);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const resourcesStepCheck = async (page: Page) => {
await expect(page.getByTestId('step-header')).toBeVisible();
await expect(page.getByTestId('step-description')).toBeVisible();

await page.getByTestId('toggle-button-large').click();
await page.getByTestId('node-resources-toggle-button-large').click();
await page.getByTestId('text-input-cpu').fill('0.6');
await page.getByTestId('text-input-memory').fill('1');
await page.getByTestId('text-input-disk').fill('1');
Expand Down
2 changes: 1 addition & 1 deletion ui/apps/everest/.e2e/utils/db-wizard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export const populateResources = async (
await expect(page.getByTestId('step-header')).toBeVisible();
await expect(page.getByTestId('step-description')).toBeVisible();

await page.getByTestId('toggle-button-large').click();
await page.getByTestId('node-resources-toggle-button-large').click();
await page.getByTestId('text-input-cpu').fill(cpu.toString());
await page.getByTestId('text-input-memory').fill(memory.toString());
await page.getByTestId('text-input-disk').fill(disk.toString());
Expand Down
2 changes: 2 additions & 0 deletions ui/apps/everest/src/components/cluster-form/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './resources';
export { default as ResourcesForm } from './resources';
196 changes: 196 additions & 0 deletions ui/apps/everest/src/components/cluster-form/resources/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
import { DbType } from '@percona/types';
import { z } from 'zod';
import { Resources } from 'shared-types/dbCluster.types';
import { DbWizardFormFields } from 'consts';
import { memoryParser } from 'utils/k8ResourceParser';
import { Messages } from './messages';

const resourceToNumber = (minimum = 0) =>
z.union([z.string().min(1), z.number()]).pipe(
z.coerce
.number({
invalid_type_error: 'Please enter a valid number',
})
.min(minimum)
);

export const matchFieldsValueToResourceSize = (
resources?: Resources
): ResourceSize => {
if (!resources) {
return ResourceSize.custom;
}
const memory = memoryParser(resources.memory.toString());

const res = Object.values(DEFAULT_SIZES).findIndex(
(item) => item.cpu === Number(resources.cpu) && item.memory === memory.value
);
return res !== -1
? (Object.keys(DEFAULT_SIZES)[res] as ResourceSize)
: ResourceSize.custom;
};

export const NODES_DB_TYPE_MAP: Record<DbType, string[]> = {
[DbType.Mongo]: ['1', '3', '5'],
[DbType.Mysql]: ['1', '3', '5'],
[DbType.Postresql]: ['1', '2', '3'],
};

export enum ResourceSize {
small = 'small',
medium = 'medium',
large = 'large',
custom = 'custom',
}

export const humanizedResourceSizeMap: Record<ResourceSize, string> = {
[ResourceSize.small]: 'Small',
[ResourceSize.medium]: 'Medium',
[ResourceSize.large]: 'Large',
[ResourceSize.custom]: 'Custom',
};

export const DEFAULT_SIZES = {
[ResourceSize.small]: {
[DbWizardFormFields.cpu]: 1,
[DbWizardFormFields.memory]: 2,
[DbWizardFormFields.disk]: 25,
},
[ResourceSize.medium]: {
[DbWizardFormFields.cpu]: 4,
[DbWizardFormFields.memory]: 8,
[DbWizardFormFields.disk]: 100,
},
[ResourceSize.large]: {
[DbWizardFormFields.cpu]: 8,
[DbWizardFormFields.memory]: 32,
[DbWizardFormFields.disk]: 200,
},
};

export const SHARDING_DEFAULTS = {
[DbWizardFormFields.shardConfigServers]: {
min: '1',
max: '7',
},
[DbWizardFormFields.shardNr]: {
min: '1',
},
};

export const resourcesFormSchema = (passthrough?: boolean) => {
const objectShape = {
[DbWizardFormFields.shardNr]: z.string().optional(),
[DbWizardFormFields.shardConfigServers]: z.string().optional(),
[DbWizardFormFields.cpu]: resourceToNumber(0.6),
[DbWizardFormFields.memory]: resourceToNumber(0.512),
[DbWizardFormFields.disk]: resourceToNumber(1),
// we will never input this, but we need it and zod will let it pass
[DbWizardFormFields.diskUnit]: z.string(),
[DbWizardFormFields.resourceSizePerNode]: z.nativeEnum(ResourceSize),
[DbWizardFormFields.numberOfNodes]: z.string(),
[DbWizardFormFields.customNrOfNodes]: z.string().optional(),
[DbWizardFormFields.proxyCpu]: resourceToNumber(0.6),
[DbWizardFormFields.proxyMemory]: resourceToNumber(0.512),
[DbWizardFormFields.resourceSizePerProxy]: z.nativeEnum(ResourceSize),
[DbWizardFormFields.numberOfProxies]: z.string(),
[DbWizardFormFields.customNrOfProxies]: z.string().optional(),
};

const zObject = passthrough
? z.object(objectShape).passthrough()
: z.object(objectShape);

return zObject.superRefine(
(
{
sharding,
shardConfigServers,
shardNr,
numberOfNodes,
numberOfProxies,
customNrOfNodes = '',
customNrOfProxies = '',
},
ctx
) => {
[
[numberOfNodes, customNrOfNodes, DbWizardFormFields.customNrOfNodes],
[
numberOfProxies,
customNrOfProxies,
DbWizardFormFields.customNrOfProxies,
],
].forEach(([nr, customNr, path]) => {
if (nr === CUSTOM_NR_UNITS_INPUT_VALUE) {
const intNr = parseInt(customNr, 10);

if (Number.isNaN(intNr) || intNr < 1) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: 'Please enter a valid number',
path: [path],
});
}
}
});

if (sharding as boolean) {
const intShardNr = parseInt(shardNr || '', 10);
const intShardNrMin =
+SHARDING_DEFAULTS[DbWizardFormFields.shardNr].min;
const intShardConfigServers = parseInt(shardConfigServers || '', 10);
const intShardConfigServersMin =
+SHARDING_DEFAULTS[DbWizardFormFields.shardNr].min;
const intShardConfigServersMax =
+SHARDING_DEFAULTS[DbWizardFormFields.shardConfigServers].max;

if (Number.isNaN(intShardNr) || intShardNr < 0) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: Messages.sharding.invalid,
path: [DbWizardFormFields.shardNr],
});
} else {
if (intShardNr < intShardNrMin) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: Messages.sharding.min(intShardNrMin),
path: [DbWizardFormFields.shardNr],
});
}
}

if (Number.isNaN(intShardConfigServers) || intShardConfigServers <= 0) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: Messages.sharding.invalid,
path: [DbWizardFormFields.shardConfigServers],
});
} else {
if (intShardConfigServers < intShardConfigServersMin) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: Messages.sharding.min(intShardConfigServersMin),
path: [DbWizardFormFields.shardConfigServers],
});
} else if (!(intShardConfigServers % 2)) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: Messages.sharding.odd,
path: [DbWizardFormFields.shardConfigServers],
});
} else if (intShardConfigServers > intShardConfigServersMax) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: Messages.sharding.max(intShardConfigServersMax),
path: [DbWizardFormFields.shardConfigServers],
});
}
}
}
}
);
};

export const CUSTOM_NR_UNITS_INPUT_VALUE = 'custom-units-nr';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from './resources';
export * from './constants';
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const Messages = {
sharding: {
invalid: 'Please fill in valid values for sharding',
min: (val: number) => `The value cannot be less than ${val}`,
max: (val: number) => `The value cannot be more than ${val}`,
odd: 'The value cannot be even',
},
};
Loading
Loading