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

[UI] EVEREST-1210-edit-advanced-configuration-overview-page #771

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
5ca47f3
EVEREST-1210-edit-advanced-configuration-overview-page
solovevayaroslavna Oct 16, 2024
dbff109
EVEREST-1210-edit-advanced-configuration-overview-page
solovevayaroslavna Oct 18, 2024
8c29c89
Merge branch 'main' into EVEREST-1210-edit-advanced-configuration-ove…
solovevayaroslavna Oct 25, 2024
3168372
Merge branch 'main' into EVEREST-1210-edit-advanced-configuration-ove…
solovevayaroslavna Oct 25, 2024
8c28080
chore: lint/format
solovevayaroslavna Oct 25, 2024
54ac372
EVEREST-1210-edit-advanced-configuration-overview-page
solovevayaroslavna Oct 28, 2024
aa96416
Merge branch 'main' into EVEREST-1210-edit-advanced-configuration-ove…
solovevayaroslavna Oct 28, 2024
c5504b1
Merge branch 'EVEREST-1210-edit-advanced-configuration-overview-page'…
solovevayaroslavna Oct 29, 2024
f84096a
Merge branch 'main' into EVEREST-1210-edit-advanced-configuration-ove…
solovevayaroslavna Oct 29, 2024
12e4da7
Merge branch 'main' into EVEREST-1210-edit-advanced-configuration-ove…
fabio-silva Oct 31, 2024
9548e7f
Merge remote-tracking branch 'origin/main' into EVEREST-1210-edit-adv…
solovevayaroslavna Nov 11, 2024
25728fe
EVEREST-1210-edit-advanced-configuration-overview-page: fix after mer…
solovevayaroslavna Nov 11, 2024
414bf1e
Merge branch 'EVEREST-1210-edit-advanced-configuration-overview-page'…
solovevayaroslavna Nov 11, 2024
94c3b40
EVEREST-1210-edit-advanced-configuration-overview-page: removing inte…
solovevayaroslavna Nov 11, 2024
af7bf3f
EVEREST-1210-edit-advanced-configuration-overview-page: new line afte…
solovevayaroslavna Nov 11, 2024
820dcc3
EVEREST-1210-edit-advanced-configuration-overview-page: code-review fix
solovevayaroslavna Nov 11, 2024
7a14d12
Merge branch 'main' into EVEREST-1210-edit-advanced-configuration-ove…
solovevayaroslavna Nov 11, 2024
dc532fc
Merge branch 'main' into EVEREST-1210-edit-advanced-configuration-ove…
solovevayaroslavna Nov 11, 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
@@ -0,0 +1,50 @@
// everest
// Copyright (C) 2023 Percona LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import { z } from 'zod';
import { AdvancedConfigurationFields } from './advanced-configuration.types';
import { IP_REGEX } from 'consts';
import { Messages } from './messages';

export const advancedConfigurationsSchema = z
.object({
[AdvancedConfigurationFields.externalAccess]: z.boolean(),
[AdvancedConfigurationFields.sourceRanges]: z.array(
z.object({ sourceRange: z.string().optional() })
),
[AdvancedConfigurationFields.engineParametersEnabled]: z.boolean(),
[AdvancedConfigurationFields.engineParameters]: z.string().optional(),
})
.passthrough()
.superRefine(({ sourceRanges }, ctx) => {
sourceRanges.forEach(({ sourceRange }, index) => {
if (sourceRange && IP_REGEX.exec(sourceRange) === null) {
ctx.addIssue({
code: z.ZodIssueCode.invalid_string,
validation: 'ip',
path: [
AdvancedConfigurationFields.sourceRanges,
index,
'sourceRange',
],
message: Messages.errors.sourceRange.invalid,
});
}
});
});

export type AdvancedConfigurationFormType = z.infer<
typeof advancedConfigurationsSchema
>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// everest
// Copyright (C) 2023 Percona LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import { SwitchInput, TextArray, TextInput } from '@percona/ui-lib';
import { Messages } from './messages';
import { AdvancedConfigurationFields } from './advanced-configuration.types';
import { useFormContext } from 'react-hook-form';
import { DbType } from '@percona/types';
import { getParamsPlaceholderFromDbType } from './advanced-configuration.utils';
import { Stack } from '@mui/material';

interface AdvancedConfigurationFormProps {
dbType: DbType;
}

export const AdvancedConfigurationForm = ({
dbType,
}: AdvancedConfigurationFormProps) => {
const { watch } = useFormContext();
const [externalAccess, engineParametersEnabled] = watch([
AdvancedConfigurationFields.externalAccess,
AdvancedConfigurationFields.engineParametersEnabled,
]);

return (
<>
<SwitchInput
label={Messages.enableExternalAccess.title}
labelCaption={Messages.enableExternalAccess.caption}
name={AdvancedConfigurationFields.externalAccess}
/>
{externalAccess && (
<Stack sx={{ ml: 6 }}>
<TextArray
placeholder={Messages.sourceRangePlaceholder}
fieldName={AdvancedConfigurationFields.sourceRanges}
fieldKey="sourceRange"
label={Messages.sourceRange}
/>
</Stack>
)}
<SwitchInput
label={Messages.engineParameters.title}
labelCaption={Messages.engineParameters.caption}
name={AdvancedConfigurationFields.engineParametersEnabled}
formControlLabelProps={{
sx: {
mt: 1,
},
}}
/>
{engineParametersEnabled && (
<TextInput
name={AdvancedConfigurationFields.engineParameters}
textFieldProps={{
placeholder: getParamsPlaceholderFromDbType(dbType),
multiline: true,
minRows: 3,
sx: {
ml: 6,
},
}}
/>
)}
</>
);
};

export default AdvancedConfigurationForm;
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// everest
// Copyright (C) 2023 Percona LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

export enum AdvancedConfigurationFields {
externalAccess = 'externalAccess',
sourceRanges = 'sourceRanges',
engineParametersEnabled = 'engineParametersEnabled',
engineParameters = 'engineParameters',
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// everest
// Copyright (C) 2023 Percona LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import { DbType } from '@percona/types';
import { DbCluster, ProxyExposeType } from 'shared-types/dbCluster.types';
import { AdvancedConfigurationFields } from './advanced-configuration.types';
import { AdvancedConfigurationFormType } from './advanced-configuration-schema';
import { isProxy } from 'utils/db';

export const getParamsPlaceholderFromDbType = (dbType: DbType) => {
let dynamicText = '';

switch (dbType) {
case DbType.Mongo:
dynamicText = 'operationProfiling:\nmode: slowOp\nslowOpThresholdMs: 200';
break;
case DbType.Mysql:
dynamicText =
'[mysqld]\nkey_buffer_size=16M\nmax_allowed_packet=128M\nmax_connections=250';
break;
case DbType.Postresql:
default:
dynamicText =
'log_connections = yes\nsearch_path = \'"$user", public\'\nshared_buffers = 128MB';
break;
}

return dynamicText;
};

export const advancedConfigurationModalDefaultValues = (
dbCluster: DbCluster
): AdvancedConfigurationFormType => {
const sourceRangesSource = isProxy(dbCluster?.spec?.proxy)
? dbCluster?.spec?.proxy?.expose.ipSourceRanges
: dbCluster?.spec?.proxy.ipSourceRanges;

return {
[AdvancedConfigurationFields.externalAccess]: isProxy(
dbCluster?.spec?.proxy
)
? dbCluster?.spec?.proxy?.expose?.type === ProxyExposeType.external
: dbCluster?.spec?.proxy.type === ProxyExposeType.external,
[AdvancedConfigurationFields.engineParametersEnabled]:
!!dbCluster?.spec?.engine?.config,
[AdvancedConfigurationFields.engineParameters]:
dbCluster?.spec?.engine?.config,
[AdvancedConfigurationFields.sourceRanges]: sourceRangesSource
? sourceRangesSource.map((sourceRange) => ({ sourceRange }))
: [{ sourceRange: '' }],
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// everest
// Copyright (C) 2023 Percona LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

export { default } from './advanced-configuration';
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// everest
// Copyright (C) 2023 Percona LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import { INVALID_SOURCE_RANGE_ERROR, SOURCE_RANGE_PLACEHOLDER } from 'consts';

export const Messages = {
enableExternalAccess: {
title: 'Enable External Access',
caption: `
Enable this to make this database available outside of the Kubernetes cluster network.
Exposing your database to remote access poses severe risks, including unauthorized access, data breaches and compliance violations.
`,
},
sourceRange: 'Source Range',
sourceRangePlaceholder: SOURCE_RANGE_PLACEHOLDER,
engineParameters: {
title: 'Set database engine parameters',
caption:
'Set your database engine configuration to adjust your database system to your workload and performance needs. For configuration format and specific parameters, check your database type documentation.',
},
errors: {
sourceRange: {
invalid: INVALID_SOURCE_RANGE_ERROR,
},
engineParameters: {
invalid: 'Invalid',
},
},
};
12 changes: 5 additions & 7 deletions ui/apps/everest/src/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and

import { AdvancedConfigurationFields } from 'components/cluster-form/advanced-configuration/advanced-configuration.types';
import { DBVersionFields } from 'components/cluster-form/db-version/db-version.types';
import { BackupStatus } from 'shared-types/backups.types';

// limitations under the License.
Expand All @@ -20,7 +22,7 @@ export const IP_REGEX =

export const INVALID_SOURCE_RANGE_ERROR = 'Invalid IP address range';
export const SOURCE_RANGE_PLACEHOLDER =
'Please enter the single IP address or range using netmask (e.g. 192.168.1.1/24)';
'Enter IP with netmask (e.g. 192.168.1.1/24)';
export const DATE_FORMAT = "dd'/'MM'/'yyyy 'at' hh':'mm' 'a";
export const PITR_DATE_FORMAT = "dd'/'MM'/'yyyy 'at' hh':'mm':'ss' 'a";

Expand Down Expand Up @@ -49,7 +51,6 @@ export enum DbWizardForm {
dbType = 'dbType',
k8sNamespace = 'k8sNamespace',
dbEnvironment = 'dbEnvironment',
dbVersion = 'dbVersion',
storageClass = 'storageClass',
cpu = 'cpu',
proxyCpu = 'proxyCpu',
Expand All @@ -68,11 +69,6 @@ export enum DbWizardForm {
schedules = 'schedules',
pitrEnabled = 'pitrEnabled',
pitrStorageLocation = 'pitrStorageLocation',
externalAccess = 'externalAccess',
internetFacing = 'internetFacing',
sourceRanges = 'sourceRanges',
engineParametersEnabled = 'engineParametersEnabled',
engineParameters = 'engineParameters',
monitoring = 'monitoring',
monitoringInstance = 'monitoringInstance',
endpoint = 'endpoint',
Expand All @@ -83,4 +79,6 @@ export enum DbWizardForm {

export const DbWizardFormFields = {
...DbWizardForm,
...DBVersionFields,
...AdvancedConfigurationFields,
};
50 changes: 49 additions & 1 deletion ui/apps/everest/src/hooks/api/db-cluster/useUpdateDbCluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@

import { UseMutationOptions, useMutation } from '@tanstack/react-query';
import { updateDbClusterFn } from 'api/dbClusterApi';
import { DbCluster, Proxy } from 'shared-types/dbCluster.types';
import {
DbCluster,
ProxyExposeType,
Proxy,
} from 'shared-types/dbCluster.types';
import { DbWizardType } from 'pages/database-form/database-form-schema.ts';
import cronConverter from 'utils/cron-converter';
import {
Expand Down Expand Up @@ -171,6 +175,50 @@ export const useUpdateDbClusterCrd = () =>
},
}),
});
export const useUpdateDbClusterAdvancedConfiguration = () =>
useMutation({
mutationFn: ({
clusterName,
namespace,
dbCluster,
externalAccess,
sourceRanges,
engineParametersEnabled,
engineParameters,
}: {
clusterName: string;
namespace: string;
dbCluster: DbCluster;
externalAccess: boolean;
sourceRanges: Array<{ sourceRange?: string }>;
engineParametersEnabled: boolean;
engineParameters: string | undefined;
}) =>
updateDbClusterFn(clusterName, namespace, {
...dbCluster,
spec: {
...dbCluster.spec,
engine: {
...dbCluster.spec.engine,
config: engineParametersEnabled ? engineParameters : '',
},
proxy: {
...dbCluster.spec.proxy,
expose: {
type: externalAccess
? ProxyExposeType.external
: ProxyExposeType.internal,
...(!!externalAccess &&
sourceRanges && {
ipSourceRanges: sourceRanges.flatMap((source) =>
source.sourceRange ? [source.sourceRange] : []
),
}),
},
} as Proxy,
},
}),
});

export const useUpdateDbClusterVersion = () =>
useMutation({
Expand Down
Loading
Loading