diff --git a/ui/apps/everest/src/components/cluster-form/advanced-configuration/advanced-configuration-schema.ts b/ui/apps/everest/src/components/cluster-form/advanced-configuration/advanced-configuration-schema.ts new file mode 100644 index 000000000..11713745b --- /dev/null +++ b/ui/apps/everest/src/components/cluster-form/advanced-configuration/advanced-configuration-schema.ts @@ -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 +>; diff --git a/ui/apps/everest/src/components/cluster-form/advanced-configuration/advanced-configuration.tsx b/ui/apps/everest/src/components/cluster-form/advanced-configuration/advanced-configuration.tsx new file mode 100644 index 000000000..5bc4a815c --- /dev/null +++ b/ui/apps/everest/src/components/cluster-form/advanced-configuration/advanced-configuration.tsx @@ -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 ( + <> + + {externalAccess && ( + + + + )} + + {engineParametersEnabled && ( + + )} + + ); +}; + +export default AdvancedConfigurationForm; diff --git a/ui/apps/everest/src/components/cluster-form/advanced-configuration/advanced-configuration.types.ts b/ui/apps/everest/src/components/cluster-form/advanced-configuration/advanced-configuration.types.ts new file mode 100644 index 000000000..b6a491c9f --- /dev/null +++ b/ui/apps/everest/src/components/cluster-form/advanced-configuration/advanced-configuration.types.ts @@ -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', +} diff --git a/ui/apps/everest/src/components/cluster-form/advanced-configuration/advanced-configuration.utils.ts b/ui/apps/everest/src/components/cluster-form/advanced-configuration/advanced-configuration.utils.ts new file mode 100644 index 000000000..3c9d4cbb2 --- /dev/null +++ b/ui/apps/everest/src/components/cluster-form/advanced-configuration/advanced-configuration.utils.ts @@ -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: '' }], + }; +}; diff --git a/ui/apps/everest/src/components/cluster-form/advanced-configuration/index.ts b/ui/apps/everest/src/components/cluster-form/advanced-configuration/index.ts new file mode 100644 index 000000000..15cc75140 --- /dev/null +++ b/ui/apps/everest/src/components/cluster-form/advanced-configuration/index.ts @@ -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'; diff --git a/ui/apps/everest/src/components/cluster-form/advanced-configuration/messages.ts b/ui/apps/everest/src/components/cluster-form/advanced-configuration/messages.ts new file mode 100644 index 000000000..712f996d7 --- /dev/null +++ b/ui/apps/everest/src/components/cluster-form/advanced-configuration/messages.ts @@ -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', + }, + }, +}; diff --git a/ui/apps/everest/src/consts.ts b/ui/apps/everest/src/consts.ts index fe99f8495..0ac305fe4 100644 --- a/ui/apps/everest/src/consts.ts +++ b/ui/apps/everest/src/consts.ts @@ -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. @@ -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"; @@ -49,7 +51,6 @@ export enum DbWizardForm { dbType = 'dbType', k8sNamespace = 'k8sNamespace', dbEnvironment = 'dbEnvironment', - dbVersion = 'dbVersion', storageClass = 'storageClass', cpu = 'cpu', proxyCpu = 'proxyCpu', @@ -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', @@ -83,4 +79,6 @@ export enum DbWizardForm { export const DbWizardFormFields = { ...DbWizardForm, + ...DBVersionFields, + ...AdvancedConfigurationFields, }; diff --git a/ui/apps/everest/src/hooks/api/db-cluster/useUpdateDbCluster.ts b/ui/apps/everest/src/hooks/api/db-cluster/useUpdateDbCluster.ts index 37296f75c..563f03e8c 100644 --- a/ui/apps/everest/src/hooks/api/db-cluster/useUpdateDbCluster.ts +++ b/ui/apps/everest/src/hooks/api/db-cluster/useUpdateDbCluster.ts @@ -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 { @@ -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({ diff --git a/ui/apps/everest/src/pages/database-form/database-form-body/steps/advanced-configurations/advanced-configurations.messages.ts b/ui/apps/everest/src/pages/database-form/database-form-body/steps/advanced-configurations/advanced-configurations.messages.ts index 6a2e128cd..a57d7a720 100644 --- a/ui/apps/everest/src/pages/database-form/database-form-body/steps/advanced-configurations/advanced-configurations.messages.ts +++ b/ui/apps/everest/src/pages/database-form/database-form-body/steps/advanced-configurations/advanced-configurations.messages.ts @@ -11,10 +11,8 @@ // 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 - -import { SOURCE_RANGE_PLACEHOLDER } from 'consts'; - // limitations under the License. + export const Messages = { advanced: 'Advanced Configurations', caption: ` @@ -22,19 +20,4 @@ export const Messages = { theft of sensitive information, data manipulation, compliance violations, legal consequences, and reputational damage. Secure your database with strong controls, encryption, and firewalls. Use secure remote access, regularly back up data, and conduct security audits. `, - 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. - `, - }, - internetFacing: 'Internet Facing', - 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.', - }, }; diff --git a/ui/apps/everest/src/pages/database-form/database-form-body/steps/advanced-configurations/advanced-configurations.test.tsx b/ui/apps/everest/src/pages/database-form/database-form-body/steps/advanced-configurations/advanced-configurations.test.tsx index 99cdcccaf..b83ce02d9 100644 --- a/ui/apps/everest/src/pages/database-form/database-form-body/steps/advanced-configurations/advanced-configurations.test.tsx +++ b/ui/apps/everest/src/pages/database-form/database-form-body/steps/advanced-configurations/advanced-configurations.test.tsx @@ -9,7 +9,6 @@ const FormProviderWrapper = ({ children }: { children: React.ReactNode }) => { defaultValues: { externalAccess: false, engineParametersEnabled: false, - // internetFacing: false, sourceRanges: [ { sourgeRange: '192.168.1.1', diff --git a/ui/apps/everest/src/pages/database-form/database-form-body/steps/advanced-configurations/advanced-configurations.tsx b/ui/apps/everest/src/pages/database-form/database-form-body/steps/advanced-configurations/advanced-configurations.tsx index 52f3520ac..6cc2a15be 100644 --- a/ui/apps/everest/src/pages/database-form/database-form-body/steps/advanced-configurations/advanced-configurations.tsx +++ b/ui/apps/everest/src/pages/database-form/database-form-body/steps/advanced-configurations/advanced-configurations.tsx @@ -13,65 +13,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { FormGroup, Stack } from '@mui/material'; -import { SwitchInput, TextInput, TextArray } from '@percona/ui-lib'; import { useFormContext } from 'react-hook-form'; import { Messages } from './advanced-configurations.messages.ts'; -import { getParamsPlaceholderFromDbType } from './advanced-configurations.utils.ts'; import { DbWizardFormFields } from 'consts.ts'; import { StepHeader } from '../step-header/step-header.tsx'; +import AdvancedConfigurationForm from 'components/cluster-form/advanced-configuration/advanced-configuration.tsx'; +import { FormGroup } from '@mui/material'; export const AdvancedConfigurations = () => { - const methods = useFormContext(); - const [externalAccess, engineParametersEnabled, dbType] = methods.watch([ - DbWizardFormFields.externalAccess, - DbWizardFormFields.engineParametersEnabled, - DbWizardFormFields.dbType, - ]); + const { watch } = useFormContext(); + const dbType = watch(DbWizardFormFields.dbType); return ( <> - - {externalAccess && ( - - - - )} - - {engineParametersEnabled && ( - - )} + ); diff --git a/ui/apps/everest/src/pages/database-form/database-form-body/steps/advanced-configurations/advanced-configurations.utils.ts b/ui/apps/everest/src/pages/database-form/database-form-body/steps/advanced-configurations/advanced-configurations.utils.ts deleted file mode 100644 index ba9ba9ffb..000000000 --- a/ui/apps/everest/src/pages/database-form/database-form-body/steps/advanced-configurations/advanced-configurations.utils.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { DbType } from '@percona/types'; - -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 && `${dynamicText}`; -}; diff --git a/ui/apps/everest/src/pages/database-form/database-form-schema.ts b/ui/apps/everest/src/pages/database-form/database-form-schema.ts index e9664743d..26bfda3bd 100644 --- a/ui/apps/everest/src/pages/database-form/database-form-schema.ts +++ b/ui/apps/everest/src/pages/database-form/database-form-schema.ts @@ -1,12 +1,13 @@ import { z } from 'zod'; import { DbType } from '@percona/types'; -import { IP_REGEX, MAX_DB_CLUSTER_NAME_LENGTH } from '../../consts.ts'; +import { MAX_DB_CLUSTER_NAME_LENGTH } from '../../consts.ts'; import { Messages } from './database-form.messages.ts'; import { DbWizardFormFields } from 'consts.ts'; import { rfc_123_schema } from 'utils/common-validation.ts'; import { Messages as ScheduleFormMessages } from 'components/schedule-form-dialog/schedule-form/schedule-form.messages.ts'; import { resourcesFormSchema } from 'components/cluster-form'; import { dbVersionSchemaObject } from 'components/cluster-form/db-version/db-version-schema'; +import { advancedConfigurationsSchema } from 'components/cluster-form/advanced-configuration/advanced-configuration-schema.ts'; const basicInfoSchema = z .object({ @@ -69,30 +70,6 @@ const backupsStepSchema = z } }); -const advancedConfigurationsSchema = z - .object({ - [DbWizardFormFields.externalAccess]: z.boolean(), - // internetFacing: z.boolean(), - [DbWizardFormFields.sourceRanges]: z.array( - z.object({ sourceRange: z.string().optional() }) - ), - [DbWizardFormFields.engineParametersEnabled]: z.boolean(), - [DbWizardFormFields.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: [DbWizardFormFields.sourceRanges, index, 'sourceRange'], - message: Messages.errors.sourceRange.invalid, - }); - } - }); - }); - const stepFiveSchema = z .object({ monitoring: z.boolean(), diff --git a/ui/apps/everest/src/pages/database-form/database-form.constants.ts b/ui/apps/everest/src/pages/database-form/database-form.constants.ts index fc70bbb04..86c498e6a 100644 --- a/ui/apps/everest/src/pages/database-form/database-form.constants.ts +++ b/ui/apps/everest/src/pages/database-form/database-form.constants.ts @@ -35,7 +35,6 @@ export const DB_WIZARD_DEFAULTS: DbWizardType = { [DbWizardFormFields.storageClass]: '', [DbWizardFormFields.k8sNamespace]: null, [DbWizardFormFields.externalAccess]: false, - // [DbWizardFormFields.internetFacing]: true, [DbWizardFormFields.sourceRanges]: [{ sourceRange: '' }], [DbWizardFormFields.engineParametersEnabled]: false, [DbWizardFormFields.engineParameters]: '', diff --git a/ui/apps/everest/src/pages/database-form/database-form.messages.ts b/ui/apps/everest/src/pages/database-form/database-form.messages.ts index 406df04ad..56f795ae7 100644 --- a/ui/apps/everest/src/pages/database-form/database-form.messages.ts +++ b/ui/apps/everest/src/pages/database-form/database-form.messages.ts @@ -13,7 +13,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { INVALID_SOURCE_RANGE_ERROR } from '../../consts'; import { errorMessages } from 'utils/common-validation'; export const Messages = { @@ -30,12 +29,6 @@ export const Messages = { accept: 'Yes, cancel', }, errors: { - sourceRange: { - invalid: INVALID_SOURCE_RANGE_ERROR, - }, - engineParameters: { - invalid: 'Invalid', - }, endpoint: { invalid: 'Invalid URL', }, diff --git a/ui/apps/everest/src/pages/database-form/database-form.utils.ts b/ui/apps/everest/src/pages/database-form/database-form.utils.ts index 2b767f5ca..b138f5eb8 100644 --- a/ui/apps/everest/src/pages/database-form/database-form.utils.ts +++ b/ui/apps/everest/src/pages/database-form/database-form.utils.ts @@ -14,7 +14,7 @@ // limitations under the License. import { DbEngineType, DbType } from '@percona/types'; -import { DbCluster, ProxyExposeType } from 'shared-types/dbCluster.types'; +import { DbCluster } from 'shared-types/dbCluster.types'; import { DbWizardMode } from './database-form.types'; import { DbWizardFormFields } from 'consts.ts'; import { dbEngineToDbType } from '@percona/utils'; @@ -34,6 +34,7 @@ import { PROXIES_DEFAULT_SIZES, } from 'components/cluster-form'; import { isProxy } from 'utils/db.tsx'; +import { advancedConfigurationModalDefaultValues } from 'components/cluster-form/advanced-configuration/advanced-configuration.utils.ts'; const replicasToNodes = (replicas: string, dbType: DbType): string => { const nodeOptions = NODES_DB_TYPE_MAP[dbType]; @@ -65,9 +66,6 @@ export const DbClusterPayloadToFormValues = ( replicas, dbEngineToDbType(dbCluster?.spec?.engine?.type) ); - const sourceRangesSource = isProxy(dbCluster?.spec?.proxy) - ? dbCluster?.spec?.proxy?.expose.ipSourceRanges - : dbCluster?.spec?.proxy.ipSourceRanges; return { //basic info @@ -84,20 +82,8 @@ export const DbClusterPayloadToFormValues = ( ) : dbCluster?.metadata?.name, [DbWizardFormFields.dbVersion]: dbCluster?.spec?.engine?.version || '', - [DbWizardFormFields.externalAccess]: isProxy(dbCluster?.spec?.proxy) - ? dbCluster?.spec?.proxy?.expose?.type === ProxyExposeType.external - : dbCluster?.spec?.proxy.type === ProxyExposeType.external, - // [DbWizardFormFields.internetFacing]: true, - [DbWizardFormFields.engineParametersEnabled]: - !!dbCluster?.spec?.engine?.config, - [DbWizardFormFields.engineParameters]: dbCluster?.spec?.engine?.config, - [DbWizardFormFields.sourceRanges]: sourceRangesSource - ? sourceRangesSource.map((sourceRange) => ({ sourceRange })) - : [{ sourceRange: '' }], - [DbWizardFormFields.monitoring]: - !!dbCluster?.spec?.monitoring?.monitoringConfigName, - [DbWizardFormFields.monitoringInstance]: - dbCluster?.spec?.monitoring?.monitoringConfigName || '', + + //resources [DbWizardFormFields.numberOfNodes]: numberOfNodes, [DbWizardFormFields.numberOfProxies]: replicasToNodes( proxies, @@ -159,5 +145,14 @@ export const DbClusterPayloadToFormValues = ( ? backup?.pitr?.backupStorageName || null : DB_WIZARD_DEFAULTS[DbWizardFormFields.pitrStorageLocation], [DbWizardFormFields.schedules]: backup?.schedules || [], + + //advanced configuration + ...advancedConfigurationModalDefaultValues(dbCluster), + + //monitoring + [DbWizardFormFields.monitoring]: + !!dbCluster?.spec?.monitoring?.monitoringConfigName, + [DbWizardFormFields.monitoringInstance]: + dbCluster?.spec?.monitoring?.monitoringConfigName || '', }; }; diff --git a/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cards/db-details/advanced-configuration.tsx b/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cards/db-details/advanced-configuration.tsx deleted file mode 100644 index 4bb076ecb..000000000 --- a/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cards/db-details/advanced-configuration.tsx +++ /dev/null @@ -1,47 +0,0 @@ -// 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 { Messages } from '../../cluster-overview.messages'; -import OverviewSection from '../../overview-section'; -import { AdvancedConfigurationOverviewCardProps } from '../card.types'; -import OverviewSectionRow from '../../overview-section-row'; - -export const AdvancedConfiguration = ({ - loading, - externalAccess, - // parameters, -}: AdvancedConfigurationOverviewCardProps) => { - return ( - - - {/**/} - {/*//TODO 1210 waits https://perconacorp.slack.com/archives/C0545J2BEJX/p1721309559055999*/} - - ); -}; diff --git a/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cards/db-details/advanced-configuration/advanced-configuration.tsx b/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cards/db-details/advanced-configuration/advanced-configuration.tsx new file mode 100644 index 000000000..2599e1375 --- /dev/null +++ b/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cards/db-details/advanced-configuration/advanced-configuration.tsx @@ -0,0 +1,115 @@ +// 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 { Messages } from '../../../cluster-overview.messages'; +import OverviewSection from '../../../overview-section'; +import { AdvancedConfigurationOverviewCardProps } from '../../card.types'; +import OverviewSectionRow from '../../../overview-section-row'; +import { DbClusterContext } from 'pages/db-cluster-details/dbCluster.context'; +import { useContext, useState } from 'react'; +import { AdvancedConfigurationEditModal } from './edit-advanced-configuration'; +import { useUpdateDbClusterAdvancedConfiguration } from 'hooks'; +import { AdvancedConfigurationFormType } from 'components/cluster-form/advanced-configuration/advanced-configuration-schema'; + +export const AdvancedConfiguration = ({ + loading, + externalAccess, + parameters, +}: AdvancedConfigurationOverviewCardProps) => { + const { + canUpdateDb, + dbCluster, + queryResult: { refetch }, + } = useContext(DbClusterContext); + const [openEditModal, setOpenEditModal] = useState(false); + const [updating, setUpdating] = useState(false); + const { mutate: updateDbClusterAdvancedConfiguration } = + useUpdateDbClusterAdvancedConfiguration(); + const handleCloseModal = () => { + setOpenEditModal(false); + }; + + const handleSubmit = async ({ + externalAccess, + sourceRanges, + engineParametersEnabled, + engineParameters, + }: AdvancedConfigurationFormType) => { + setUpdating(true); + updateDbClusterAdvancedConfiguration( + { + clusterName: dbCluster!.metadata?.name, + namespace: dbCluster!.metadata?.namespace, + dbCluster: dbCluster!, + externalAccess: externalAccess, + sourceRanges: sourceRanges, + engineParametersEnabled: engineParametersEnabled, + engineParameters: engineParameters, + }, + { + onSuccess: async () => { + await refetch(); + handleCloseModal(); + setUpdating(false); + }, + onError: () => { + setUpdating(false); + }, + } + ); + }; + + return ( + { + setOpenEditModal(true); + }, + children: Messages.actions.edit, + }, + } + : undefined)} + > + + + + {openEditModal && dbCluster && ( + + )} + + ); +}; diff --git a/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cards/db-details/advanced-configuration/edit-advanced-configuration/edit-advanced-configuration.messages.ts b/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cards/db-details/advanced-configuration/edit-advanced-configuration/edit-advanced-configuration.messages.ts new file mode 100644 index 000000000..8937c95e2 --- /dev/null +++ b/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cards/db-details/advanced-configuration/edit-advanced-configuration/edit-advanced-configuration.messages.ts @@ -0,0 +1,19 @@ +// 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 const Messages = { + formDialogHeader: 'Edit advanced configuration', + save: 'Save', +}; diff --git a/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cards/db-details/advanced-configuration/edit-advanced-configuration/edit-advanced-configuration.tsx b/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cards/db-details/advanced-configuration/edit-advanced-configuration/edit-advanced-configuration.tsx new file mode 100644 index 000000000..eed152dba --- /dev/null +++ b/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cards/db-details/advanced-configuration/edit-advanced-configuration/edit-advanced-configuration.tsx @@ -0,0 +1,66 @@ +// 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 { FormDialog } from 'components/form-dialog/form-dialog'; +import { SubmitHandler } from 'react-hook-form'; +import AdvancedConfigurationForm from 'components/cluster-form/advanced-configuration'; +import { AdvancedConfigurationModalProps } from './edit-advanced-configuration.types'; +import { + AdvancedConfigurationFormType, + advancedConfigurationsSchema, +} from 'components/cluster-form/advanced-configuration/advanced-configuration-schema'; +import { Messages } from './edit-advanced-configuration.messages'; +import { dbEngineToDbType } from '@percona/utils'; +import { advancedConfigurationModalDefaultValues } from 'components/cluster-form/advanced-configuration/advanced-configuration.utils'; + +export const AdvancedConfigurationEditModal = ({ + open, + handleCloseModal, + handleSubmitModal, + dbCluster, + submitting, +}: AdvancedConfigurationModalProps) => { + const onSubmit: SubmitHandler = ({ + externalAccess, + engineParametersEnabled, + engineParameters, + sourceRanges, + }) => { + handleSubmitModal({ + externalAccess, + engineParametersEnabled, + engineParameters, + sourceRanges, + }); + }; + + return ( + + + + ); +}; diff --git a/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cards/db-details/advanced-configuration/edit-advanced-configuration/edit-advanced-configuration.types.ts b/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cards/db-details/advanced-configuration/edit-advanced-configuration/edit-advanced-configuration.types.ts new file mode 100644 index 000000000..430859bf2 --- /dev/null +++ b/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cards/db-details/advanced-configuration/edit-advanced-configuration/edit-advanced-configuration.types.ts @@ -0,0 +1,25 @@ +// 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 { AdvancedConfigurationFormType } from 'components/cluster-form/advanced-configuration/advanced-configuration-schema'; +import { DbCluster } from 'shared-types/dbCluster.types'; + +export interface AdvancedConfigurationModalProps { + open: boolean; + handleCloseModal: () => void; + handleSubmitModal: (props: AdvancedConfigurationFormType) => void; + dbCluster: DbCluster; + submitting: boolean; +} diff --git a/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cards/db-details/advanced-configuration/edit-advanced-configuration/index.ts b/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cards/db-details/advanced-configuration/edit-advanced-configuration/index.ts new file mode 100644 index 000000000..3255c9f5a --- /dev/null +++ b/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cards/db-details/advanced-configuration/edit-advanced-configuration/index.ts @@ -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 { AdvancedConfigurationEditModal } from './edit-advanced-configuration'; diff --git a/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cards/db-details/advanced-configuration/index.ts b/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cards/db-details/advanced-configuration/index.ts new file mode 100644 index 000000000..104f2fbd9 --- /dev/null +++ b/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cards/db-details/advanced-configuration/index.ts @@ -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 { AdvancedConfiguration } from './advanced-configuration'; diff --git a/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cluster-overview.tsx b/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cluster-overview.tsx index 7a875bf0a..294cc8ec0 100644 --- a/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cluster-overview.tsx +++ b/ui/apps/everest/src/pages/db-cluster-details/cluster-overview/cluster-overview.tsx @@ -96,7 +96,7 @@ export const ClusterOverview = () => { dbCluster.spec.proxy.expose.type === ProxyExposeType.external } monitoring={dbCluster?.spec.monitoring.monitoringConfigName} - parameters={!!dbCluster?.spec.engine.config} //TODO EVEREST-1210 waits https://perconacorp.slack.com/archives/C0545J2BEJX/p1721309559055999 + parameters={!!dbCluster?.spec.engine.config} />