diff --git a/public/app/percona/dbaas/components/DBCluster/DBCluster.service.ts b/public/app/percona/dbaas/components/DBCluster/DBCluster.service.ts index 82a6ce5b0ee65..6ba1571f0c426 100644 --- a/public/app/percona/dbaas/components/DBCluster/DBCluster.service.ts +++ b/public/app/percona/dbaas/components/DBCluster/DBCluster.service.ts @@ -22,9 +22,6 @@ import { DBClusterListResponse, DBClusterSecretsResponse, DBClusterSecretsRequest, - DBClusterTemplatesResponse, - DBClusterTemplatesRequest, - DBClusterType, DBClusterResponse, } from './DBCluster.types'; import { formatResources } from './DBCluster.utils'; @@ -112,14 +109,4 @@ export abstract class DBClusterService { }; }); } - static async getDBClusterTemplates( - kubernetesClusterName: string, - k8sClusterType: DBClusterType - ): Promise { - return apiManagement.post( - '/DBaaS/Templates/List', - { kubernetes_cluster_name: kubernetesClusterName, cluster_type: k8sClusterType }, - true - ); - } } diff --git a/public/app/percona/dbaas/components/DBCluster/DBCluster.types.ts b/public/app/percona/dbaas/components/DBCluster/DBCluster.types.ts index c65aa036d4c98..95dff17863227 100644 --- a/public/app/percona/dbaas/components/DBCluster/DBCluster.types.ts +++ b/public/app/percona/dbaas/components/DBCluster/DBCluster.types.ts @@ -3,6 +3,7 @@ import { BadgeColor } from '@grafana/ui'; import { Databases } from 'app/percona/shared/core'; import { DBClusterService } from './DBCluster.service'; +import { DBClusterTemplate } from './EditDBClusterPage/DBClusterAdvancedOptions/Templates/Templates.types'; import { Operators } from './EditDBClusterPage/DBClusterBasicOptions/DBClusterBasicOptions.types'; export type AddDBClusterAction = (dbCluster: DBCluster) => void; @@ -267,19 +268,6 @@ export interface DBClusterSecretsRequest { kubernetes_cluster_name: string; } -export interface DBClusterTemplate { - name: string; - kind: string; -} -export interface DBClusterTemplatesResponse { - templates: DBClusterTemplate[]; -} - -export interface DBClusterTemplatesRequest { - kubernetes_cluster_name: string; - cluster_type: DBClusterType; -} - export interface DBClusterSecret { name: string; } diff --git a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/DBClusterAdvancedOptions.tsx b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/DBClusterAdvancedOptions.tsx index b40b63ad25735..464358dfd479c 100644 --- a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/DBClusterAdvancedOptions.tsx +++ b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/DBClusterAdvancedOptions.tsx @@ -211,6 +211,7 @@ export const DBClusterAdvancedOptions: FC = ({
>> { - const dbClusterType = DatabaseToDBClusterTypeMapping[databaseType]; - const templatesResponse = - dbClusterType && (await DBClusterService.getDBClusterTemplates(k8sClusterName, dbClusterType)); - const templates = templatesResponse?.templates || []; - return templates.map((template) => ({ - label: template.name, - value: template.kind, - })); + getDBaaSTemplates(kubernetesClusterName: string, k8sClusterType: DBClusterType): Promise { + return apiManagement.post( + '/DBaaS/Templates/List', + { kubernetes_cluster_name: kubernetesClusterName, cluster_type: k8sClusterType }, + true + ); }, }; diff --git a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/Templates/Templates.tsx b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/Templates/Templates.tsx index a70ca8d73ad6d..36fae1e4f9596 100644 --- a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/Templates/Templates.tsx +++ b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/Templates/Templates.tsx @@ -1,20 +1,48 @@ -import React, { FC } from 'react'; +import React, { FC, useEffect, useMemo } from 'react'; +import { Field } from 'react-final-form'; -import { AsyncSelectFieldCore } from 'app/percona/shared/components/Form/AsyncSelectFieldCore'; +import { useDispatch, useSelector } from 'app/types'; +import { AsyncSelectFieldAdapter } from '../../../../../../shared/components/Form/FieldAdapters/FieldAdapters'; +import { fetchDBaaSTemplatesAction } from '../../../../../../shared/core/reducers'; +import { getDbaaSTemplates } from '../../../../../../shared/core/selectors'; +import { DatabaseToDBClusterTypeMapping } from '../../../DBCluster.types'; import { AdvancedOptionsFields } from '../DBClusterAdvancedOptions.types'; import { Messages } from './Templates.messages'; -import { TemplatesService } from './Templates.service'; import { TemplatesProps } from './Templates.types'; +import { getTemplatesOptions, notSelectedOption } from './Templates.utils'; + +export const Templates: FC = ({ k8sClusterName, databaseType, form }) => { + const dispatch = useDispatch(); + const { result, loading } = useSelector(getDbaaSTemplates); + + const templatesOptions = useMemo(() => getTemplatesOptions(result), [result]); + + useEffect(() => { + const dbClusterType = DatabaseToDBClusterTypeMapping[databaseType]; + if (dbClusterType) { + dispatch(fetchDBaaSTemplatesAction({ k8sClusterName, dbClusterType })); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [databaseType, dispatch, k8sClusterName]); + + useEffect(() => { + if (templatesOptions.length === 1) { + form.mutators.resetTemplate(notSelectedOption); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [templatesOptions]); -export const Templates: FC = ({ k8sClusterName, databaseType }) => { return ( - TemplatesService.loadTemplatesOptions(k8sClusterName, databaseType)} - defaultOptions + component={AsyncSelectFieldAdapter} + loading={loading} + options={templatesOptions} + defaultValue={notSelectedOption} /> ); }; diff --git a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/Templates/Templates.types.ts b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/Templates/Templates.types.ts index 0755f0b8631e3..d2538ba4ea472 100644 --- a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/Templates/Templates.types.ts +++ b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/Templates/Templates.types.ts @@ -1,6 +1,28 @@ +import { FormApi } from 'final-form'; + import { Databases } from '../../../../../../shared/core'; +import { DBClusterType } from '../../../DBCluster.types'; export interface TemplatesProps { k8sClusterName: string; databaseType: Databases; + form: FormApi, Partial>>; +} + +export interface DBClusterTemplate { + name: string; + kind: string; +} +export interface DBClusterTemplatesResponse { + templates: DBClusterTemplate[]; +} + +export interface DBClusterTemplatesRequest { + kubernetes_cluster_name: string; + cluster_type: DBClusterType; +} + +export interface DBClusterTemplate { + name: string; + kind: string; } diff --git a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/Templates/Templates.utils.ts b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/Templates/Templates.utils.ts new file mode 100644 index 0000000000000..fdf6b63546df0 --- /dev/null +++ b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/Templates/Templates.utils.ts @@ -0,0 +1,14 @@ +import { SelectableValue } from '@grafana/data'; + +import { DBClusterTemplatesResponse } from './Templates.types'; +export const notSelectedOption = { label: 'Not selected', value: '' }; +export const getTemplatesOptions = ( + templatesResponce: DBClusterTemplatesResponse | undefined +): Array> => { + const templates = templatesResponce?.templates || []; + const options = templates.map((template) => ({ + label: template.name, + value: template.kind, + })); + return options?.length ? [...options, notSelectedOption] : [notSelectedOption]; +}; diff --git a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/EditDBClusterPage.tsx b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/EditDBClusterPage.tsx index 3ef56109b314c..ffc1499580066 100644 --- a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/EditDBClusterPage.tsx +++ b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/EditDBClusterPage.tsx @@ -4,7 +4,9 @@ import React, { FC, useCallback, useEffect, useState } from 'react'; import { Form } from 'react-final-form'; import { Redirect, useHistory } from 'react-router-dom'; +import { SelectableValue } from '@grafana/data'; import { Spinner, useStyles2 } from '@grafana/ui/src'; +import { AdvancedOptionsFields } from 'app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/DBClusterAdvancedOptions.types'; import { useShowPMMAddressWarning } from 'app/percona/shared/components/hooks/showPMMAddressWarning'; import { useSelector, useDispatch } from 'app/types'; @@ -93,6 +95,9 @@ export const EditDBClusterPage: FC = () => { trimConfiguration: ([configuration]: string[], state, { changeValue }) => { changeValue(state, ConfigurationFields.configuration, () => configuration.trim()); }, + resetTemplate: (templateValue: SelectableValue, state, { changeValue }) => { + changeValue(state, AdvancedOptionsFields.template, () => templateValue); + }, ...arrayMutators, }} render={({ form, handleSubmit, valid, pristine, ...props }) => ( diff --git a/public/app/percona/dbaas/components/DBCluster/__mocks__/dbClustersStubs.ts b/public/app/percona/dbaas/components/DBCluster/__mocks__/dbClustersStubs.ts index 953bdc71c3de2..4de6b7c21a386 100644 --- a/public/app/percona/dbaas/components/DBCluster/__mocks__/dbClustersStubs.ts +++ b/public/app/percona/dbaas/components/DBCluster/__mocks__/dbClustersStubs.ts @@ -9,8 +9,8 @@ import { DBClusterComponentVersionStatus, DBClusterAllocatedResources, ResourcesWithUnits, - DBClusterTemplate, } from '../DBCluster.types'; +import { DBClusterTemplate } from '../EditDBClusterPage/DBClusterAdvancedOptions/Templates/Templates.types'; import { Operators } from '../EditDBClusterPage/DBClusterBasicOptions/DBClusterBasicOptions.types'; export const dbClustersStub: DBCluster[] = [ diff --git a/public/app/percona/shared/core/reducers/dbaas/addDBCluster/addDBCluster.ts b/public/app/percona/shared/core/reducers/dbaas/addDBCluster/addDBCluster.ts index 1e4f97e2fc05b..42e2d40710b9b 100644 --- a/public/app/percona/shared/core/reducers/dbaas/addDBCluster/addDBCluster.ts +++ b/public/app/percona/shared/core/reducers/dbaas/addDBCluster/addDBCluster.ts @@ -124,12 +124,13 @@ export const addDbClusterAction = createAsyncThunk( secretsName: secretsName?.value || '', }, }), - ...(template && { - template: { - name: template.label, - kind: template.value, - }, - }), + ...(template && + template.value && { + template: { + name: template.label, + kind: template.value, + }, + }), }), { successMessage: 'Cluster was successfully added', diff --git a/public/app/percona/shared/core/reducers/index.ts b/public/app/percona/shared/core/reducers/index.ts index a2e54109edd3b..aaf35be9d906f 100644 --- a/public/app/percona/shared/core/reducers/index.ts +++ b/public/app/percona/shared/core/reducers/index.ts @@ -3,6 +3,7 @@ import { combineReducers, createAsyncThunk, createSlice, PayloadAction } from '@ import { CancelToken } from 'axios'; import { createAsyncSlice, withAppEvents, withSerializedError } from 'app/features/alerting/unified/utils/redux'; +import { DBClusterTemplatesResponse } from 'app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/Templates/Templates.types'; import { KubernetesService } from 'app/percona/dbaas/components/Kubernetes/Kubernetes.service'; import { ComponentToUpdate, Kubernetes } from 'app/percona/dbaas/components/Kubernetes/Kubernetes.types'; import { AlertRuleTemplateService } from 'app/percona/integrated-alerting/components/AlertRuleTemplate/AlertRuleTemplate.service'; @@ -13,6 +14,8 @@ import { PlatformService } from 'app/percona/settings/components/Platform/Platfo import { api } from 'app/percona/shared/helpers/api'; import { uiEventsReducer } from 'app/percona/ui-events/reducer'; +import { DBClusterType } from '../../../dbaas/components/DBCluster/DBCluster.types'; +import { TemplatesService } from '../../../dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/Templates/Templates.service'; import { ServerInfo } from '../types'; import advisorsReducers from './advisors/advisors'; @@ -222,6 +225,12 @@ export const fetchTemplatesAction = createAsyncThunk( ) ); +export const fetchDBaaSTemplatesAction = createAsyncThunk( + 'percona/fetchDbaaSTemplates', + async (args: { k8sClusterName: string; dbClusterType: DBClusterType }): Promise => + withSerializedError(TemplatesService.getDBaaSTemplates(args?.k8sClusterName, args?.dbClusterType)) +); + const deleteKubernetesReducer = createAsyncSlice('deleteKubernetes', deleteKubernetesAction).reducer; const installKubernetesOperatorReducer = createAsyncSlice( 'instalKuberneteslOperator', @@ -230,6 +239,7 @@ const installKubernetesOperatorReducer = createAsyncSlice( const settingsReducer = createAsyncSlice('settings', fetchSettingsAction, initialSettingsState).reducer; const updateSettingsReducer = createAsyncSlice('updateSettings', updateSettingsAction).reducer; const templatesReducer = createAsyncSlice('templates', fetchTemplatesAction).reducer; +const dbaasTemplatesReducer = createAsyncSlice('dbaasTemplates', fetchDBaaSTemplatesAction).reducer; export default { percona: combineReducers({ @@ -237,6 +247,7 @@ export default { updateSettings: updateSettingsReducer, user: perconaUserReducers, dbaas: perconaDBaaSReducer, + dbaasTemplates: dbaasTemplatesReducer, kubernetes: perconaK8SClusterListReducer, deleteKubernetes: deleteKubernetesReducer, addKubernetes: perconaK8SCluster, diff --git a/public/app/percona/shared/core/selectors.ts b/public/app/percona/shared/core/selectors.ts index 6434c64595103..7694c53786175 100644 --- a/public/app/percona/shared/core/selectors.ts +++ b/public/app/percona/shared/core/selectors.ts @@ -10,6 +10,7 @@ export const getPerconaSettingFlag = (setting: keyof Settings) => (state: StoreS !!state.percona.settings.result?.[setting]; export const getPerconaUser = (state: StoreState) => state.percona.user; export const getDBaaS = (state: StoreState) => state.percona.dbaas; +export const getDbaaSTemplates = (state: StoreState) => state.percona.dbaasTemplates; export const getKubernetes = (state: StoreState) => state.percona.kubernetes; export const getDeleteKubernetes = (state: StoreState) => state.percona.deleteKubernetes; export const getAddKubernetes = (state: StoreState) => state.percona.addKubernetes;