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

PMM-11773-Templates-select-issues: fix templates reloading #647

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
13 changes: 0 additions & 13 deletions public/app/percona/dbaas/components/DBCluster/DBCluster.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ import {
DBClusterListResponse,
DBClusterSecretsResponse,
DBClusterSecretsRequest,
DBClusterTemplatesResponse,
DBClusterTemplatesRequest,
DBClusterType,
DBClusterResponse,
} from './DBCluster.types';
import { formatResources } from './DBCluster.utils';
Expand Down Expand Up @@ -112,14 +109,4 @@ export abstract class DBClusterService {
};
});
}
static async getDBClusterTemplates(
kubernetesClusterName: string,
k8sClusterType: DBClusterType
): Promise<DBClusterTemplatesResponse> {
return apiManagement.post<DBClusterTemplatesResponse, DBClusterTemplatesRequest>(
'/DBaaS/Templates/List',
{ kubernetes_cluster_name: kubernetesClusterName, cluster_type: k8sClusterType },
true
);
}
}
14 changes: 1 addition & 13 deletions public/app/percona/dbaas/components/DBCluster/DBCluster.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ export const DBClusterAdvancedOptions: FC<DBClusterAdvancedOptionsProps> = ({
<Templates
k8sClusterName={selectedCluster ? selectedCluster.kubernetesClusterName : kubernetesCluster?.value}
databaseType={databaseType?.value}
form={form}
/>
<div className={styles.line}>
<NumberInputField
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import { SelectableValue } from '@grafana/data';
import { apiManagement } from 'app/percona/shared/helpers/api';

import { Databases } from '../../../../../../shared/core';
import { DBClusterService } from '../../../DBCluster.service';
import { DatabaseToDBClusterTypeMapping } from '../../../DBCluster.types';
import { DBClusterType } from '../../../DBCluster.types';

import { DBClusterTemplatesRequest, DBClusterTemplatesResponse } from './Templates.types';

export const TemplatesService = {
async loadTemplatesOptions(k8sClusterName: string, databaseType: Databases): Promise<Array<SelectableValue<string>>> {
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<DBClusterTemplatesResponse> {
return apiManagement.post<DBClusterTemplatesResponse, DBClusterTemplatesRequest>(
'/DBaaS/Templates/List',
{ kubernetes_cluster_name: kubernetesClusterName, cluster_type: k8sClusterType },
true
);
},
};
Original file line number Diff line number Diff line change
@@ -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<TemplatesProps> = ({ 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<TemplatesProps> = ({ k8sClusterName, databaseType }) => {
return (
<AsyncSelectFieldCore
<Field
dataTestId="templates-field"
name={AdvancedOptionsFields.template}
label={Messages.labels.templates}
loadOptions={() => TemplatesService.loadTemplatesOptions(k8sClusterName, databaseType)}
defaultOptions
component={AsyncSelectFieldAdapter}
loading={loading}
options={templatesOptions}
defaultValue={notSelectedOption}
/>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -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<Record<string, any>, Partial<Record<string, any>>>;
}

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;
}
Original file line number Diff line number Diff line change
@@ -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<SelectableValue<string>> => {
const templates = templatesResponce?.templates || [];
const options = templates.map((template) => ({
label: template.name,
value: template.kind,
}));
return options?.length ? [...options, notSelectedOption] : [notSelectedOption];
};
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -93,6 +95,9 @@ export const EditDBClusterPage: FC<EditDBClusterPageProps> = () => {
trimConfiguration: ([configuration]: string[], state, { changeValue }) => {
changeValue(state, ConfigurationFields.configuration, () => configuration.trim());
},
resetTemplate: (templateValue: SelectableValue<string>, state, { changeValue }) => {
changeValue(state, AdvancedOptionsFields.template, () => templateValue);
},
...arrayMutators,
}}
render={({ form, handleSubmit, valid, pristine, ...props }) => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
11 changes: 11 additions & 0 deletions public/app/percona/shared/core/reducers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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';
Expand Down Expand Up @@ -222,6 +225,12 @@ export const fetchTemplatesAction = createAsyncThunk(
)
);

export const fetchDBaaSTemplatesAction = createAsyncThunk(
'percona/fetchDbaaSTemplates',
async (args: { k8sClusterName: string; dbClusterType: DBClusterType }): Promise<DBClusterTemplatesResponse> =>
withSerializedError(TemplatesService.getDBaaSTemplates(args?.k8sClusterName, args?.dbClusterType))
);

const deleteKubernetesReducer = createAsyncSlice('deleteKubernetes', deleteKubernetesAction).reducer;
const installKubernetesOperatorReducer = createAsyncSlice(
'instalKuberneteslOperator',
Expand All @@ -230,13 +239,15 @@ 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({
settings: settingsReducer,
updateSettings: updateSettingsReducer,
user: perconaUserReducers,
dbaas: perconaDBaaSReducer,
dbaasTemplates: dbaasTemplatesReducer,
kubernetes: perconaK8SClusterListReducer,
deleteKubernetes: deleteKubernetesReducer,
addKubernetes: perconaK8SCluster,
Expand Down
1 change: 1 addition & 0 deletions public/app/percona/shared/core/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down