diff --git a/public/app/percona/add-instance/panel.types.ts b/public/app/percona/add-instance/panel.types.ts index 70cae7d02494b..649ffb124751e 100644 --- a/public/app/percona/add-instance/panel.types.ts +++ b/public/app/percona/add-instance/panel.types.ts @@ -50,6 +50,7 @@ export const INSTANCE_TYPES_LABELS = { [Databases.mariadb]: 'MariaDB', [Databases.mongodb]: 'MongoDB', [Databases.postgresql]: 'PostgreSQL', + [Databases.pgbouncer]: 'PGBouncer', [Databases.proxysql]: 'ProxySQL', [Databases.haproxy]: 'HAProxy', [InstanceTypesExtra.azure]: '', diff --git a/public/app/percona/dbaas/components/DBCluster/DBCluster.constants.ts b/public/app/percona/dbaas/components/DBCluster/DBCluster.constants.ts index 9b20169bb5727..081cd2fdc9340 100644 --- a/public/app/percona/dbaas/components/DBCluster/DBCluster.constants.ts +++ b/public/app/percona/dbaas/components/DBCluster/DBCluster.constants.ts @@ -1,7 +1,8 @@ -import { Databases, DATABASE_LABELS } from 'app/percona/shared/core'; +import { DATABASE_LABELS, Databases } from 'app/percona/shared/core'; import { DatabaseOperatorsMap, DBClusterServiceDatabasesMap } from './DBCluster.types'; import { Operators } from './EditDBClusterPage/DBClusterBasicOptions/DBClusterBasicOptions.types'; +import { PGService } from './PG.service'; import { PSMDBService } from './PSMDB.service'; import { XtraDBService } from './XtraDB.service'; @@ -16,11 +17,16 @@ export const DATABASE_OPTIONS = [ value: Databases.mongodb, label: DATABASE_LABELS.mongodb, }, + { + value: Databases.postgresql, + label: DATABASE_LABELS.postgresql, + }, ]; export const SERVICE_MAP: Partial = { [Databases.mysql]: new XtraDBService(), [Databases.mongodb]: new PSMDBService(), + [Databases.postgresql]: new PGService(), }; export const THOUSAND = 1000; @@ -30,6 +36,7 @@ export const RESOURCES_PRECISION = 2; export const DATABASE_OPERATORS: Partial = { [Operators.pxc]: Databases.mysql, [Operators.psmdb]: Databases.mongodb, + [Operators.pg]: Databases.postgresql, }; export const GET_CLUSTERS_CANCEL_TOKEN = 'getClusters'; diff --git a/public/app/percona/dbaas/components/DBCluster/DBCluster.types.ts b/public/app/percona/dbaas/components/DBCluster/DBCluster.types.ts index c65aa036d4c98..688d0e06e109a 100644 --- a/public/app/percona/dbaas/components/DBCluster/DBCluster.types.ts +++ b/public/app/percona/dbaas/components/DBCluster/DBCluster.types.ts @@ -13,6 +13,7 @@ export type ManageDBClusters = [DBCluster[], GetDBClustersAction, SetDBClustersL export enum DBClusterType { pxc = 'DB_CLUSTER_TYPE_PXC', psmdb = 'DB_CLUSTER_TYPE_PSMDB', + pg = 'DB_CLUSTER_TYPE_POSTGRESQL', } export const DatabaseToDBClusterTypeMapping: Partial> = { @@ -230,6 +231,8 @@ export interface DBClusterParamsAPI { image?: string; backup?: DBaaSBackupPayload; restore?: DBaaSRestorePayload; + instance?: DBClusterContainerAPI; + pgbouncer?: Omit; } interface DBClusterContainerAPI { @@ -329,6 +332,8 @@ export interface DBClusterMatrix { backup?: DBClusterComponent; operator?: DBClusterComponent; log_collector?: DBClusterComponent; + postgresql?: DBClusterComponent; + pgbouncer?: DBClusterComponent; } export interface DBClusterComponent { @@ -352,6 +357,8 @@ export interface DBClusterChangeComponentsAPI { pxc?: DBClusterChangeComponentAPI; haproxy?: DBClusterChangeComponentAPI; mongod?: DBClusterChangeComponentAPI; + postgresql?: DBClusterChangeComponentAPI; + pgbouncer?: DBClusterChangeComponentAPI; } export interface DBClusterChangeComponentAPI { @@ -368,6 +375,7 @@ export interface DBClusterChangeComponentVersionAPI { export interface DBClusterListResponse { pxc_clusters?: DBClusterResponse[]; psmdb_clusters?: DBClusterResponse[]; + postgresql_clusters?: DBClusterResponse[]; } export interface DBClusterSuspendResumeRequest { diff --git a/public/app/percona/dbaas/components/DBCluster/DBClusterActions/DBClusterActions.tsx b/public/app/percona/dbaas/components/DBCluster/DBClusterActions/DBClusterActions.tsx index c80d462822677..e72c12c30f9ee 100644 --- a/public/app/percona/dbaas/components/DBCluster/DBClusterActions/DBClusterActions.tsx +++ b/public/app/percona/dbaas/components/DBCluster/DBClusterActions/DBClusterActions.tsx @@ -4,6 +4,7 @@ import { useHistory } from 'react-router-dom'; import { Messages } from 'app/percona/dbaas/DBaaS.messages'; import { MultipleActions } from 'app/percona/dbaas/components/MultipleActions/MultipleActions'; +import { Databases } from 'app/percona/shared/core'; import { useDispatch } from 'app/types'; import { selectDBCluster } from '../../../../shared/core/reducers/dbaas/dbaas'; @@ -56,7 +57,10 @@ export const DBClusterActions: FC = ({ }, { content: Messages.dbcluster.table.actions.restartCluster, - disabled: isClusterChanging(dbCluster) || dbCluster.status === DBClusterStatus.suspended, + disabled: + isClusterChanging(dbCluster) || + dbCluster.status === DBClusterStatus.suspended || + dbCluster.databaseType === Databases.postgresql, action: async () => { try { const dbClusterService = newDBClusterService(dbCluster.databaseType); @@ -73,7 +77,9 @@ export const DBClusterActions: FC = ({ dbCluster.status === DBClusterStatus.ready ? Messages.dbcluster.table.actions.suspend : Messages.dbcluster.table.actions.resume, - disabled: dbCluster.status !== DBClusterStatus.ready && dbCluster.status !== DBClusterStatus.suspended, + disabled: + (dbCluster.status !== DBClusterStatus.ready && dbCluster.status !== DBClusterStatus.suspended) || + dbCluster.databaseType === Databases.postgresql, action: async () => { try { const dbClusterService = newDBClusterService(dbCluster.databaseType); diff --git a/public/app/percona/dbaas/components/DBCluster/DBClusterName/DBClusterName.constants.ts b/public/app/percona/dbaas/components/DBCluster/DBClusterName/DBClusterName.constants.ts index 1b44ab567dbbc..8d15082f32660 100644 --- a/public/app/percona/dbaas/components/DBCluster/DBClusterName/DBClusterName.constants.ts +++ b/public/app/percona/dbaas/components/DBCluster/DBClusterName/DBClusterName.constants.ts @@ -8,4 +8,6 @@ export const DASHBOARD_URL_MAP: DashboardURLMap = { `/graph/d/pxc-cluster-summary/pxc-galera-cluster-summary?var-cluster=${clusterName}-pxc`, [Databases.mongodb]: (clusterName: string) => `/graph/d/mongodb-cluster-summary/mongodb-cluster-summary?var-cluster=${clusterName}`, + //TODO (no dashboard for pg) + [Databases.postgresql]: (clusterName: string) => `${clusterName}`, }; diff --git a/public/app/percona/dbaas/components/DBCluster/DBClusterName/DBClusterName.tsx b/public/app/percona/dbaas/components/DBCluster/DBClusterName/DBClusterName.tsx index e6f8797696c59..cfa58beb8f290 100644 --- a/public/app/percona/dbaas/components/DBCluster/DBClusterName/DBClusterName.tsx +++ b/public/app/percona/dbaas/components/DBCluster/DBClusterName/DBClusterName.tsx @@ -2,6 +2,8 @@ import React, { FC } from 'react'; import { Icon, useStyles } from '@grafana/ui'; +import { Databases } from '../../../../shared/core'; + import { DASHBOARD_URL_MAP } from './DBClusterName.constants'; import { getStyles } from './DBClusterName.styles'; import { DBClusterNameProps } from './DBClusterName.types'; @@ -13,9 +15,16 @@ export const DBClusterName: FC = ({ dbCluster: { clusterName return (
{clusterName} - - - + {databaseType !== Databases.postgresql && ( + + + + )}
); }; diff --git a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/Configurations/Configurations.test.tsx b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/Configurations/Configurations.test.tsx index 6c33de909a63a..50685fdc5655f 100644 --- a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/Configurations/Configurations.test.tsx +++ b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/Configurations/Configurations.test.tsx @@ -21,11 +21,13 @@ describe('DBClusterAdvancedOptions Configurations::', () => { ) ); expect(screen.getByTestId('configurations').querySelector('legend')).toHaveTextContent( - Messages.fieldSets.commonConfiguration + Messages.fieldSets.configuration(Databases.haproxy) ); expect(screen.getByTestId('storageClass-field-label')).toHaveTextContent(Messages.labels.storageClass); expect(screen.getByTestId('storageClass-field-container').querySelector('input')).toBeTruthy(); - expect(screen.getByTestId('configuration-field-label')).toHaveTextContent(Messages.labels.commonConfiguration); + expect(screen.getByTestId('configuration-field-label')).toHaveTextContent( + Messages.labels.configuration(Databases.haproxy) + ); expect(screen.getByTestId('configuration-textarea-input')).toBeInTheDocument(); }); @@ -41,9 +43,11 @@ describe('DBClusterAdvancedOptions Configurations::', () => { ) ); expect(screen.getByTestId('configurations').querySelector('legend')).toHaveTextContent( - Messages.fieldSets.pxcConfiguration + Messages.fieldSets.configuration(Databases.mysql) + ); + expect(screen.getByTestId('configuration-field-label')).toHaveTextContent( + Messages.labels.configuration(Databases.mysql) ); - expect(screen.getByTestId('configuration-field-label')).toHaveTextContent(Messages.labels.pxcConfiguration); }); it('shows labels correctly for mongoDB', async () => { @@ -58,9 +62,11 @@ describe('DBClusterAdvancedOptions Configurations::', () => { ) ); expect(screen.getByTestId('configurations').querySelector('legend')).toHaveTextContent( - Messages.fieldSets.mongodbConfiguration + Messages.fieldSets.configuration(Databases.mongodb) + ); + expect(screen.getByTestId('configuration-field-label')).toHaveTextContent( + Messages.labels.configuration(Databases.mongodb) ); - expect(screen.getByTestId('configuration-field-label')).toHaveTextContent(Messages.labels.mongodbConfiguration); }); it('storageClass is disabled for edit mode', async () => { diff --git a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/Configurations/Configurations.tsx b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/Configurations/Configurations.tsx index dd336774dfed7..a9895ad46bc42 100644 --- a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/Configurations/Configurations.tsx +++ b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/Configurations/Configurations.tsx @@ -1,5 +1,5 @@ import { TextareaInputField, AsyncSelectField } from '@percona/platform-core'; -import React, { FC, useMemo } from 'react'; +import React, { FC } from 'react'; import FieldSet from '../../../../../../shared/components/Form/FieldSet/FieldSet'; import { Databases } from '../../../../../../shared/core'; @@ -9,24 +9,10 @@ import { ConfigurationService } from './Configurations.service'; import { ConfigurationFields, ConfigurationProps } from './Configurations.types'; export const Configurations: FC = ({ form, mode, databaseType, k8sClusterName }) => { - const label = useMemo( - () => - databaseType === Databases.mysql - ? Messages.labels.pxcConfiguration - : databaseType === Databases.mongodb - ? Messages.labels.mongodbConfiguration - : Messages.labels.commonConfiguration, - [databaseType] - ); - const fieldSetLabel = useMemo( - () => - databaseType === Databases.mysql - ? Messages.fieldSets.pxcConfiguration - : databaseType === Databases.mongodb - ? Messages.fieldSets.mongodbConfiguration - : Messages.fieldSets.commonConfiguration, - [databaseType] - ); + const label = databaseType ? Messages.labels.configuration(databaseType) : Messages.labels.commonConfiguration; + const fieldSetLabel = databaseType + ? Messages.fieldSets.configuration(databaseType) + : Messages.fieldSets.commonConfiguration; return (
@@ -38,15 +24,17 @@ export const Configurations: FC = ({ form, mode, databaseTyp label={Messages.labels.storageClass} disabled={mode === 'edit'} /> - { - form.mutators.trimConfiguration(event?.target?.value); - }, - }} - /> + {databaseType !== Databases.postgresql && ( + { + form.mutators.trimConfiguration(event?.target?.value); + }, + }} + /> + )}
); }; diff --git a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/DBClusterAdvancedOptions.messages.ts b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/DBClusterAdvancedOptions.messages.ts index 2826df809e016..5e0826498a3ad 100644 --- a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/DBClusterAdvancedOptions.messages.ts +++ b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/DBClusterAdvancedOptions.messages.ts @@ -1,9 +1,12 @@ +import { INSTANCE_TYPES_LABELS } from '../../../../../add-instance/panel.types'; +import { Databases } from '../../../../../shared/core'; + export const Messages = { fieldSets: { advancedSettings: 'Advanced Settings', - pxcConfiguration: 'MySQL Configurations', - mongodbConfiguration: 'MongoDB Configurations', commonConfiguration: 'Database Configurations', + configuration: (databaseType: Databases) => `${INSTANCE_TYPES_LABELS[databaseType]} Configurations`, + networkAndSecurity: 'Network and Security', }, labels: { nodes: 'Number of Nodes', @@ -12,9 +15,11 @@ export const Messages = { memory: 'Memory (GB)', disk: 'Disk (GB)', storageClass: 'Storage Class', - pxcConfiguration: 'MySQL Configuration', - mongodbConfiguration: 'MongoDB Configuration', commonConfiguration: 'Database Configuration', + configuration: (databaseType: Databases) => `${INSTANCE_TYPES_LABELS[databaseType]} Configuration`, + expose: 'Expose', + internetFacing: 'Internet Facing', + sourceRange: 'Source Range', }, resources: { small: 'Small', 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 627e1ce931d8b..72de699601b10 100644 --- a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/DBClusterAdvancedOptions.tsx +++ b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBClusterAdvancedOptions/DBClusterAdvancedOptions.tsx @@ -92,6 +92,11 @@ export const DBClusterAdvancedOptions: FC = ({ [allocatedResources, styles.resourcesBar, styles.resourcesBarEmpty] ); + const dbTypeValue = useMemo( + () => (selectedCluster ? selectedCluster.databaseType : databaseType?.value), + [selectedCluster, databaseType] + ); + const getAllocatedResources = async (triggerLoading = true) => { try { if (allocatedTimer) { @@ -155,8 +160,6 @@ export const DBClusterAdvancedOptions: FC = ({ useEffect(() => { const getExpectedResources = async () => { - const dbTypeValue = selectedCluster ? selectedCluster.databaseType : databaseType?.value; - try { const dbClusterService = newDBClusterService(dbTypeValue); setLoadingExpectedResources(true); @@ -193,23 +196,24 @@ export const DBClusterAdvancedOptions: FC = ({ } return () => clearTimeout(expectedTimer); - }, [memory, cpu, disk, kubernetesCluster, topology, nodes, single, databaseType]); + }, [memory, cpu, disk, kubernetesCluster, topology, nodes, single, dbTypeValue]); useEffect(() => { - const dbTypeValue = selectedCluster ? selectedCluster.databaseType : databaseType?.value; if (dbTypeValue === Databases.mongodb) { setShowUnsafeConfigurationWarning(nodes === 1); } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [databaseType, nodes]); + }, [nodes, dbTypeValue]); return (
<>{showUnsafeConfigurationWarning && } - + {dbTypeValue !== Databases.postgresql && ( + + )}
= ({
{ @@ -25,8 +25,8 @@ const KubernetesOption: FC = ({ DatabaseOperators[databaseType])} - disabledTags={disabledOperators.map((databaseType) => DatabaseOperators[databaseType])} + tags={availableOperators.map((databaseType) => DatabaseOperatorsLabels[databaseType])} + disabledTags={disabledOperators.map((databaseType) => DatabaseOperatorsLabels[databaseType])} dataTestId="kubernetes-option" /> ); @@ -36,9 +36,9 @@ export const getKubernetesOptions = (kubernetes: Kubernetes[]): KubernetesOption .map((kubernetesCluster) => { const { kubernetesClusterName, operators } = kubernetesCluster; - const availableOperators = OPERATORS.filter( - (databaseType) => operators[databaseType].status === KubernetesOperatorStatus.ok - ); + const availableOperators = OPERATORS.filter((databaseType) => { + return operators[databaseType].status === KubernetesOperatorStatus.ok; + }); const disabledOperators = OPERATORS.filter( (databaseType) => operators[databaseType].status !== KubernetesOperatorStatus.ok ); diff --git a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/EditDBClusterPage.test.tsx b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/EditDBClusterPage.test.tsx index 6c430ba6c2621..e9ff24e4fd7cd 100644 --- a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/EditDBClusterPage.test.tsx +++ b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/EditDBClusterPage.test.tsx @@ -38,6 +38,7 @@ describe('EditDBClusterPage::', () => { operators: { psmdb: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, pxc: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, + pg: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, }, }, ], @@ -87,6 +88,7 @@ describe('EditDBClusterPage::', () => { operators: { psmdb: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, pxc: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, + pg: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, }, }, ], @@ -130,6 +132,7 @@ describe('EditDBClusterPage::', () => { operators: { psmdb: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, pxc: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, + pg: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, }, }, ], diff --git a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/EditDBClusterPage.tsx b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/EditDBClusterPage.tsx index 3ef56109b314c..53fe841d65253 100644 --- a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/EditDBClusterPage.tsx +++ b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/EditDBClusterPage.tsx @@ -5,10 +5,13 @@ import { Form } from 'react-final-form'; import { Redirect, useHistory } from 'react-router-dom'; import { Spinner, useStyles2 } from '@grafana/ui/src'; +import NetworkAndSecurity from 'app/percona/dbaas/components/DBCluster/EditDBClusterPage/NetworkAndSecurity/NetworkAndSecurity'; +import Restore from 'app/percona/dbaas/components/DBCluster/EditDBClusterPage/Restore/Restore'; import { useShowPMMAddressWarning } from 'app/percona/shared/components/hooks/showPMMAddressWarning'; import { useSelector, useDispatch } from 'app/types'; import { FeatureLoader } from '../../../../shared/components/Elements/FeatureLoader'; +import { Databases } from '../../../../shared/core'; import { fetchStorageLocations } from '../../../../shared/core/reducers/backups/backupLocations'; import { resetAddDBClusterState } from '../../../../shared/core/reducers/dbaas/addDBCluster/addDBCluster'; import { resetDBCluster } from '../../../../shared/core/reducers/dbaas/dbaas'; @@ -33,8 +36,6 @@ import { Messages } from './EditDBClusterPage.messages'; import { getStyles } from './EditDBClusterPage.styles'; import { EditDBClusterPageProps } from './EditDBClusterPage.types'; import { generateUID } from './EditDBClusterPage.utils'; -import NetworkAndSecurity from './NetworkAndSecurity/NetworkAndSecurity'; -import Restore from './Restore/Restore'; import { useDefaultMode } from './hooks/useDefaultMode'; import { useEditDBClusterFormSubmit } from './hooks/useEditDBClusterFormSubmit'; import { useEditDBClusterPageDefaultValues } from './hooks/useEditDBClusterPageDefaultValues'; @@ -118,17 +119,20 @@ export const EditDBClusterPage: FC = () => {
{mode === 'create' && }
- {!!settings?.backupEnabled && } + {!!settings?.backupEnabled && + form.getState().values.databaseType.value !== Databases.postgresql && } - {!!settings?.backupEnabled && mode === 'create' && ( - - )} + {!!settings?.backupEnabled && + mode === 'create' && + form.getState().values.databaseType.value !== Databases.postgresql && ( + + )}
{ it('render items correctly for create and edit mode', () => { render(
} @@ -34,10 +40,14 @@ describe('DBClusterAdvancedOptions NetworkAndSecurity::', () => { expect(screen.getByTestId('sourceRanges[0].sourceRange-text-input')).toBeInTheDocument(); expect(screen.getByTestId('sourceRanges[0].sourceRange-text-input')).not.toBeDisabled(); }); + it('the delete button should not delete the first field', () => { render( } @@ -53,10 +63,14 @@ describe('DBClusterAdvancedOptions NetworkAndSecurity::', () => { fireEvent.click(deleteBtn); expect(screen.getByTestId('sourceRanges[0].sourceRange-text-input')).toBeInTheDocument(); }); + it('the delete button should delete field from the form if it is not the first one ', () => { render( } @@ -72,4 +86,23 @@ describe('DBClusterAdvancedOptions NetworkAndSecurity::', () => { fireEvent.click(deleteBtn); expect(screen.queryByTestId('sourceRanges[1].sourceRange-text-input')).not.toBeInTheDocument(); }); + it('source range field should be hidden whe database is postgreSQL ', () => { + render( + } + /> + ); + expect(screen.getByTestId('toggle-network-and-security')).toBeInTheDocument(); + const checkbox = screen.getByTestId('toggle-network-and-security'); + + fireEvent.click(checkbox); + + expect(screen.queryByTestId('source-ranges')).not.toBeInTheDocument(); + }); }); diff --git a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/NetworkAndSecurity/NetworkAndSecurity.tsx b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/NetworkAndSecurity/NetworkAndSecurity.tsx index f58b0b84835f8..9c0ed39da07c8 100644 --- a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/NetworkAndSecurity/NetworkAndSecurity.tsx +++ b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/NetworkAndSecurity/NetworkAndSecurity.tsx @@ -4,6 +4,7 @@ import { Field } from 'react-final-form'; import { FieldArray } from 'react-final-form-arrays'; import { Switch, useStyles, Button, Icon, Tooltip } from '@grafana/ui'; +import { Databases } from 'app/percona/shared/core'; import FieldSet from '../../../../../shared/components/Form/FieldSet/FieldSet'; @@ -13,7 +14,7 @@ import { NetworkAndSecurityFields, NetworkAndSecurityProps } from './NetworkAndS export const NetworkAndSecurity: FC = ({ form }) => { const styles = useStyles(getStyles); - const { expose } = form.getState().values; + const { expose, databaseType } = form.getState().values; return (
= ({ form }) => { tooltipIcon="info-circle" tooltipText={Messages.tooltips.internetFacing} /> - - {({ fields }) => ( -
- - {fields.map((name, index) => ( -
- -
- ))} -
- )} -
+ {databaseType.value !== Databases.postgresql && ( + + {({ fields }) => ( +
+ + {fields.map((name, index) => ( +
+ +
+ ))} +
+ )} +
+ )} ) : (
diff --git a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/hooks/DBClusterHooks.test.tsx b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/hooks/DBClusterHooks.test.tsx index fbeccb915a3f1..9b7bafa036068 100644 --- a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/hooks/DBClusterHooks.test.tsx +++ b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/hooks/DBClusterHooks.test.tsx @@ -25,6 +25,7 @@ const kubernetes: Kubernetes[] = [ operators: { psmdb: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, pxc: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, + pg: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, }, }, { @@ -33,6 +34,7 @@ const kubernetes: Kubernetes[] = [ operators: { psmdb: { status: KubernetesOperatorStatus.ok, version: '2', availableVersion: '2' }, pxc: { status: KubernetesOperatorStatus.ok, version: '2', availableVersion: '2' }, + pg: { status: KubernetesOperatorStatus.ok, version: '2', availableVersion: '2' }, }, }, ]; diff --git a/public/app/percona/dbaas/components/DBCluster/PG.service.ts b/public/app/percona/dbaas/components/DBCluster/PG.service.ts new file mode 100644 index 0000000000000..d3b219b8595e0 --- /dev/null +++ b/public/app/percona/dbaas/components/DBCluster/PG.service.ts @@ -0,0 +1,223 @@ +import { omit, pick } from 'lodash'; + +import { DBClusterService } from 'app/percona/dbaas/components/DBCluster/DBCluster.service'; +import { Databases } from 'app/percona/shared/core'; +import { apiManagement } from 'app/percona/shared/helpers/api'; + +import { + ManageComponentsVersionsRenderProps, + SupportedComponents, +} from '../Kubernetes/ManageComponentsVersionsModal/ManageComponentsVersionsModal.types'; + +import { BILLION, THOUSAND } from './DBCluster.constants'; +import { getComponentChange } from './DBCluster.service.utils'; +import { + DatabaseVersion, + CpuUnits, + DBCluster, + DBClusterActionAPI, + DBClusterComponents, + DBClusterConnectionAPI, + DBClusterExpectedResources, + DBClusterExpectedResourcesAPI, + DBClusterPayload, + ResourcesUnits, + DBClusterChangeComponentsAPI, + DBClusterType, + DBClusterStatus, + DBClusterSuspendResumeRequest, + DBClusterConfigurationAPI, +} from './DBCluster.types'; +import { Operators } from './EditDBClusterPage/DBClusterBasicOptions/DBClusterBasicOptions.types'; + +export class PGService extends DBClusterService { + addDBCluster(dbCluster: DBCluster): Promise { + return apiManagement.post('/DBaaS/PostgresqlCluster/Create', toAPI(dbCluster)); + } + + updateDBCluster(dbCluster: DBCluster): Promise { + return apiManagement.post('/DBaaS/PostgresqlCluster/Update', toAPI(dbCluster)); + } + + resumeDBCluster(dbCluster: DBCluster): Promise { + return apiManagement.post( + '/DBaaS/PostgresqlCluster/Update', + toResumeAPI(dbCluster) + ); + } + + suspendDBCluster(dbCluster: DBCluster): Promise { + return apiManagement.post( + '/DBaaS/PostgresqlCluster/Update', + toSuspendAPI(dbCluster) + ); + } + + deleteDBClusters(dbCluster: DBCluster): Promise { + const body = { + name: dbCluster.clusterName, + kubernetes_cluster_name: dbCluster.kubernetesClusterName, + cluster_type: DBClusterType.pg, + }; + + return apiManagement.post('/DBaaS/DBClusters/Delete', body); + } + + getDBClusterCredentials(dbCluster: DBCluster): Promise { + return apiManagement.post>( + '/DBaaS/PostgresqlCluster/GetCredentials', + omit(toAPI(dbCluster), ['params']) + ); + } + + restartDBCluster(dbCluster: DBCluster): Promise { + const body = { + name: dbCluster.clusterName, + kubernetes_cluster_name: dbCluster.kubernetesClusterName, + cluster_type: DBClusterType.pg, + }; + + return apiManagement.post('/DBaaS/DBClusters/Restart', body); + } + + getComponents(kubernetesClusterName: string): Promise { + return apiManagement.post('/DBaaS/Components/GetPG', { + kubernetes_cluster_name: kubernetesClusterName, + }); + } + + setComponents(kubernetesClusterName: string, componentsVersions: ManageComponentsVersionsRenderProps): Promise { + return apiManagement.post('/DBaaS/Components/ChangePG', { + kubernetes_cluster_name: kubernetesClusterName, + postgresql: getComponentChange(Operators.pg, SupportedComponents.postgresql, componentsVersions), + pgbouncer: getComponentChange(Operators.pg, SupportedComponents.pgbouncer, componentsVersions), + }); + } + + getDatabaseVersions(kubernetesClusterName: string): Promise { + return this.getComponents(kubernetesClusterName).then(({ versions }) => { + return Object.entries(versions[0].matrix.postgresql || {}).map(([version, component]) => ({ + value: component ? component.image_path : '', + label: version || '', + default: component.default || false, + disabled: component.disabled || false, + })); + }); + } + + getExpectedResources(dbCluster: DBCluster): Promise { + return apiManagement + .post>( + '/DBaaS/PostgresqlCluster/Resources/Get', + pick(toAPI(dbCluster), ['params']) + ) + .then(({ expected }: DBClusterExpectedResourcesAPI) => ({ + expected: { + cpu: { value: expected.cpu_m / THOUSAND, units: CpuUnits.MILLI, original: +expected.cpu_m }, + memory: { + value: expected.memory_bytes / BILLION, + units: ResourcesUnits.GB, + original: +expected.memory_bytes, + }, + disk: { value: expected.disk_size / BILLION, units: ResourcesUnits.GB, original: +expected.disk_size }, + }, + })); + } + + getClusterConfiguration(dbCluster: DBCluster): Promise { + return apiManagement + .post>('/DBaaS/DBClusters/Get', { + kubernetes_cluster_name: dbCluster.kubernetesClusterName, + name: dbCluster.clusterName, + }) + .then((result): DBClusterPayload => result?.psmdb_cluster); + } + + toModel(dbCluster: DBClusterPayload, kubernetesClusterName: string, databaseType: Databases): DBCluster { + return { + clusterName: dbCluster.name, + kubernetesClusterName, + databaseType, + clusterSize: dbCluster.params.cluster_size, + memory: (dbCluster.params.instance?.compute_resources?.memory_bytes || 0) / BILLION, + cpu: (dbCluster.params.instance?.compute_resources?.cpu_m || 0) / THOUSAND, + disk: (dbCluster.params.instance?.disk_size || 0) / BILLION, + status: dbCluster.state || DBClusterStatus.changing, + message: dbCluster.operation?.message, + finishedSteps: dbCluster.operation?.finished_steps || 0, + totalSteps: dbCluster.operation?.total_steps || 0, + expose: dbCluster.exposed, + installedImage: dbCluster.installed_image, + availableImage: dbCluster.available_image, + template: dbCluster.template, + sourceRanges: dbCluster.source_ranges, + }; + } +} + +const toAPI = (dbCluster: DBCluster): DBClusterPayload => ({ + kubernetes_cluster_name: dbCluster.kubernetesClusterName, + name: dbCluster.clusterName, + expose: dbCluster.expose, + internet_facing: dbCluster.internetFacing, + source_ranges: dbCluster.sourceRanges, + params: { + cluster_size: dbCluster.clusterSize, + instance: { + image: dbCluster.databaseImage, + compute_resources: { + cpu_m: dbCluster.cpu * THOUSAND, + memory_bytes: dbCluster.memory * BILLION, + }, + storage_class: dbCluster.storageClass, + disk_size: dbCluster.disk * BILLION, + configuration: dbCluster.configuration, + }, + + pgbouncer: { + compute_resources: { + cpu_m: dbCluster.cpu * THOUSAND, + memory_bytes: dbCluster.memory * BILLION, + }, + disk_size: dbCluster.disk * BILLION, + }, + + // ...(dbCluster.backup && { + // backup: { + // location_id: dbCluster.backup?.locationId, + // keep_copies: dbCluster.backup?.keepCopies, + // cron_expression: dbCluster.backup?.cronExpression, + // service_account: dbCluster.backup?.serviceAccount, + // }, + // }), + // ...(dbCluster.restore && { + // restore: { + // location_id: dbCluster.restore?.locationId, + // destination: dbCluster.restore?.destination, + // secrets_name: dbCluster.restore?.secretsName, + // }, + // }), + }, + // ...(dbCluster.template && { + // template: { + // name: dbCluster.template.name, + // kind: dbCluster.template.kind, + // }, + // }), +}); + +const toSuspendAPI = (dbCluster: DBCluster) => ({ + kubernetes_cluster_name: dbCluster.kubernetesClusterName, + name: dbCluster.clusterName, + params: { + suspend: true, + }, +}); + +const toResumeAPI = (dbCluster: DBCluster) => ({ + kubernetes_cluster_name: dbCluster.kubernetesClusterName, + name: dbCluster.clusterName, + params: { + resume: true, + }, +}); diff --git a/public/app/percona/dbaas/components/DBCluster/__mocks__/PG.service.ts b/public/app/percona/dbaas/components/DBCluster/__mocks__/PG.service.ts new file mode 100644 index 0000000000000..513b25ca87fee --- /dev/null +++ b/public/app/percona/dbaas/components/DBCluster/__mocks__/PG.service.ts @@ -0,0 +1,25 @@ +import { + dbClusterExpectedResourcesStub, + pgDBClusterConnectionStub, + pgComponentsVersionsStubs, +} from './dbClustersStubs'; + +export class PGService { + getDBClusterCredentials() { + return { connection_credentials: pgDBClusterConnectionStub }; + } + + restartDBCluster() {} + + getExpectedResources() { + return Promise.resolve(dbClusterExpectedResourcesStub); + } + + getComponents() { + return Promise.resolve(pgComponentsVersionsStubs); + } + + updateDBCluster() { + return Promise.resolve(); + } +} diff --git a/public/app/percona/dbaas/components/DBCluster/__mocks__/dbClustersStubs.ts b/public/app/percona/dbaas/components/DBCluster/__mocks__/dbClustersStubs.ts index 953bdc71c3de2..1a108cc9e46ec 100644 --- a/public/app/percona/dbaas/components/DBCluster/__mocks__/dbClustersStubs.ts +++ b/public/app/percona/dbaas/components/DBCluster/__mocks__/dbClustersStubs.ts @@ -145,6 +145,12 @@ export const mongoDBClusterConnectionStub: DBClusterConnection = { username: 'root', }; +export const pgDBClusterConnectionStub: DBClusterConnection = { + host: 'dbcluster-pg', + password: '1234', + port: 3000, + username: 'root', +}; export const getDBClustersActionStub = jest.fn(); export const dbClusterLogsAPI = { @@ -250,6 +256,19 @@ export const psmdbComponentsVersionsStubs = { ], }; +export const pgComponentsVersionsStubs = { + versions: [ + { + product: Operators.pg, + operator: '1', + matrix: { + postgresql: versionsStub, + pgbouncer: versionsStub, + }, + }, + ], +}; + export const resourcesA: ResourcesWithUnits = { value: 10, original: 10, diff --git a/public/app/percona/dbaas/components/Kubernetes/Kubernetes.constants.ts b/public/app/percona/dbaas/components/Kubernetes/Kubernetes.constants.ts index 3f292db73d38e..3ae5fccd85e62 100644 --- a/public/app/percona/dbaas/components/Kubernetes/Kubernetes.constants.ts +++ b/public/app/percona/dbaas/components/Kubernetes/Kubernetes.constants.ts @@ -7,11 +7,13 @@ import { ComponentToUpdate, DatabaseComponentToUpdateMap } from './Kubernetes.ty export const OPERATOR_COMPONENT_TO_UPDATE_MAP = { [Operators.pxc]: ComponentToUpdate.pxc, [Operators.psmdb]: ComponentToUpdate.psmdb, + [Operators.pg]: ComponentToUpdate.pg, }; export const DATABASE_COMPONENT_TO_UPDATE_MAP: DatabaseComponentToUpdateMap = { [Databases.mysql]: ComponentToUpdate.pxc, [Databases.mongodb]: ComponentToUpdate.psmdb, + [Databases.postgresql]: ComponentToUpdate.pg, }; export const GET_KUBERNETES_CANCEL_TOKEN = 'getKubernetes'; diff --git a/public/app/percona/dbaas/components/Kubernetes/Kubernetes.types.ts b/public/app/percona/dbaas/components/Kubernetes/Kubernetes.types.ts index 3edbf104fdb77..701a6bd38ea29 100644 --- a/public/app/percona/dbaas/components/Kubernetes/Kubernetes.types.ts +++ b/public/app/percona/dbaas/components/Kubernetes/Kubernetes.types.ts @@ -21,6 +21,7 @@ export interface OperatorToUpdate extends Operator { export interface OperatorsList { psmdb: Operator; pxc: Operator; + pg: Operator; } export interface KubernetesAPI { @@ -63,6 +64,7 @@ export interface ComponentToUpdateAPI { export interface OperatorToUpdateAPI { [ComponentToUpdate.psmdb]: ComponentVersionAPI; [ComponentToUpdate.pxc]: ComponentVersionAPI; + [ComponentToUpdate.pg]: ComponentVersionAPI; } export interface ComponentVersionAPI { @@ -72,6 +74,7 @@ export interface ComponentVersionAPI { export enum ComponentToUpdate { psmdb = 'psmdb-operator', pxc = 'pxc-operator', + pg = 'pg-operator', } export type DatabaseComponentToUpdateMap = { [key in Databases]?: ComponentToUpdate }; diff --git a/public/app/percona/dbaas/components/Kubernetes/Kubernetes.utils.test.ts b/public/app/percona/dbaas/components/Kubernetes/Kubernetes.utils.test.ts index 2045f67959a16..119ba3ecb795d 100644 --- a/public/app/percona/dbaas/components/Kubernetes/Kubernetes.utils.test.ts +++ b/public/app/percona/dbaas/components/Kubernetes/Kubernetes.utils.test.ts @@ -24,6 +24,7 @@ describe('Kubernetes.utils:: ', () => { operators: { psmdb: { status: KubernetesOperatorStatus.invalid }, pxc: { status: KubernetesOperatorStatus.unavailable }, + pg: { status: KubernetesOperatorStatus.unavailable }, }, }, { @@ -31,6 +32,7 @@ describe('Kubernetes.utils:: ', () => { operators: { psmdb: { status: KubernetesOperatorStatus.unsupported }, pxc: { status: KubernetesOperatorStatus.unavailable }, + pg: { status: KubernetesOperatorStatus.unavailable }, }, }, ]; @@ -40,17 +42,22 @@ describe('Kubernetes.utils:: ', () => { const kubernetes = [ { ...kubernetesStub[0], - operators: { psmdb: { status: KubernetesOperatorStatus.ok }, pxc: { status: KubernetesOperatorStatus.ok } }, + operators: { + psmdb: { status: KubernetesOperatorStatus.ok }, + pxc: { status: KubernetesOperatorStatus.ok }, + pg: { status: KubernetesOperatorStatus.ok }, + }, }, { ...kubernetesStub[1], operators: { psmdb: { status: KubernetesOperatorStatus.ok }, pxc: { status: KubernetesOperatorStatus.unavailable }, + pg: { status: KubernetesOperatorStatus.unavailable }, }, }, ]; - expect(getActiveOperators(kubernetes).length).toBe(2); + expect(getActiveOperators(kubernetes).length).toBe(3); }); it('should return list with one active operator', () => { const kubernetes = [ @@ -59,6 +66,7 @@ describe('Kubernetes.utils:: ', () => { operators: { psmdb: { status: KubernetesOperatorStatus.ok }, pxc: { status: KubernetesOperatorStatus.unavailable }, + pg: { status: KubernetesOperatorStatus.unavailable }, }, }, { @@ -66,6 +74,7 @@ describe('Kubernetes.utils:: ', () => { operators: { psmdb: { status: KubernetesOperatorStatus.unsupported }, pxc: { status: KubernetesOperatorStatus.unavailable }, + pg: { status: KubernetesOperatorStatus.unavailable }, }, }, ]; diff --git a/public/app/percona/dbaas/components/Kubernetes/KubernetesInventory.test.tsx b/public/app/percona/dbaas/components/Kubernetes/KubernetesInventory.test.tsx index 086541cb9bc6a..915d371af77ef 100644 --- a/public/app/percona/dbaas/components/Kubernetes/KubernetesInventory.test.tsx +++ b/public/app/percona/dbaas/components/Kubernetes/KubernetesInventory.test.tsx @@ -30,6 +30,7 @@ describe('KubernetesInventory::', () => { operators: { psmdb: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, pxc: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, + pg: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, }, }, { @@ -38,6 +39,7 @@ describe('KubernetesInventory::', () => { operators: { psmdb: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, pxc: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, + pg: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, }, }, ], diff --git a/public/app/percona/dbaas/components/Kubernetes/ManageComponentsVersionsModal/ManageComponentsVersions.hooks.test.ts b/public/app/percona/dbaas/components/Kubernetes/ManageComponentsVersionsModal/ManageComponentsVersions.hooks.test.ts index dea193992ed55..46be1951223b5 100644 --- a/public/app/percona/dbaas/components/Kubernetes/ManageComponentsVersionsModal/ManageComponentsVersions.hooks.test.ts +++ b/public/app/percona/dbaas/components/Kubernetes/ManageComponentsVersionsModal/ManageComponentsVersions.hooks.test.ts @@ -17,6 +17,7 @@ import { jest.mock('../../DBCluster/XtraDB.service'); jest.mock('../../DBCluster/PSMDB.service'); +jest.mock('../../DBCluster/PG.service'); describe('ManageComponentsVersions.hooks::', () => { it('returns operator components options, versions and initial values with two operators', async () => { @@ -41,7 +42,7 @@ describe('ManageComponentsVersions.hooks::', () => { expect(versionsFieldName).toEqual(versionsFieldNameStub); }); it('returns operator components options, versions and initial values with one operator', async () => { - const newOps = omit(kubernetesStub[0], 'operators.pxc'); + const newOps = omit(kubernetesStub[0], 'operators.pxc', 'operators.pg'); const wrapper = renderHook(() => useOperatorsComponentsVersions(newOps)); await wrapper.waitForNextUpdate(); @@ -55,9 +56,21 @@ describe('ManageComponentsVersions.hooks::', () => { ] = wrapper.result.current; expect(omit(initialValues, omitDefaultLabels)).toEqual( - omit(initialValuesStubs, ['pxcpxc', 'pxchaproxy', 'pxcpxcdefault', 'pxchaproxydefault'].concat(omitDefaultLabels)) + omit( + initialValuesStubs, + [ + 'pxcpxc', + 'pxchaproxy', + 'pxcpxcdefault', + 'pxchaproxydefault', + 'pgpostgresql', + 'pgpgbouncer', + 'pgpgbouncerdefault', + 'pgpostgresqldefault', + ].concat(omitDefaultLabels) + ) ); - expect(possibleComponentOptions).toEqual(omit(possibleComponentOptionsStubs, 'pxc')); + expect(possibleComponentOptions).toEqual(omit(possibleComponentOptionsStubs, 'pxc', 'pg')); expect(operatorsOptions).toEqual([operatorsOptionsStubs[0]]); expect(componentOptions).toEqual(psmdbComponentOptionsStubs); expect(versionsOptions).toEqual(versionsStubs); diff --git a/public/app/percona/dbaas/components/Kubernetes/ManageComponentsVersionsModal/ManageComponentsVersionsModal.messages.ts b/public/app/percona/dbaas/components/Kubernetes/ManageComponentsVersionsModal/ManageComponentsVersionsModal.messages.ts index 8a0dfafbf33a7..2d072575eea64 100644 --- a/public/app/percona/dbaas/components/Kubernetes/ManageComponentsVersionsModal/ManageComponentsVersionsModal.messages.ts +++ b/public/app/percona/dbaas/components/Kubernetes/ManageComponentsVersionsModal/ManageComponentsVersionsModal.messages.ts @@ -16,11 +16,14 @@ export const Messages = { operatorLabel: { [Operators.pxc]: (version: string) => `Percona Operator for MySQL ${version}`, [Operators.psmdb]: (version: string) => `Percona Operator for MongoDB ${version}`, + [Operators.pg]: (version: string) => `Percona Operator for PostgreSQL ${version}`, }, componentLabel: { pxc: 'Percona Operator for MySQL', haproxy: 'HAProxy', backup: 'Backup', mongod: 'Percona Operator for MongoDB', + postgresql: 'Percona Operator for PostgreSQL', + pgbouncer: 'PostgreSQL Bouncer', }, }; diff --git a/public/app/percona/dbaas/components/Kubernetes/ManageComponentsVersionsModal/ManageComponentsVersionsModal.types.ts b/public/app/percona/dbaas/components/Kubernetes/ManageComponentsVersionsModal/ManageComponentsVersionsModal.types.ts index bced4458ccfa5..7a71c9e245174 100644 --- a/public/app/percona/dbaas/components/Kubernetes/ManageComponentsVersionsModal/ManageComponentsVersionsModal.types.ts +++ b/public/app/percona/dbaas/components/Kubernetes/ManageComponentsVersionsModal/ManageComponentsVersionsModal.types.ts @@ -22,12 +22,15 @@ export interface ManageComponentsVersionsRenderProps { export interface PossibleComponentOptions { [Operators.pxc]?: SelectableValue[]; [Operators.psmdb]?: SelectableValue[]; + [Operators.pg]?: SelectableValue[]; } export enum SupportedComponents { pxc = 'pxc', haproxy = 'haproxy', mongod = 'mongod', + postgresql = 'postgresql', + pgbouncer = 'pgbouncer', } export enum ManageComponentVersionsFields { diff --git a/public/app/percona/dbaas/components/Kubernetes/ManageComponentsVersionsModal/__mocks__/componentsVersionsStubs.ts b/public/app/percona/dbaas/components/Kubernetes/ManageComponentsVersionsModal/__mocks__/componentsVersionsStubs.ts index 2328fbf4203df..407a720e79b72 100644 --- a/public/app/percona/dbaas/components/Kubernetes/ManageComponentsVersionsModal/__mocks__/componentsVersionsStubs.ts +++ b/public/app/percona/dbaas/components/Kubernetes/ManageComponentsVersionsModal/__mocks__/componentsVersionsStubs.ts @@ -11,14 +11,24 @@ export const initialValuesStubs = { psmdbmongod: versionsStubs, pxcpxc: versionsStubs, pxchaproxy: versionsStubs, + pgpostgresql: versionsStubs, + pgpgbouncer: versionsStubs, psmdbmongoddefault: versionsStubs[1], pxchaproxydefault: versionsStubs[1], pxcpxcdefault: versionsStubs[1], + pgpgbouncerdefault: versionsStubs[1], + pgpostgresqldefault: versionsStubs[1], }; // use to omit default labels form testing // due to parsing the label to a component to show the recommended option -export const omitDefaultLabels = ['psmdbmongoddefault.label', 'pxchaproxydefault.label', 'pxcpxcdefault.label']; +export const omitDefaultLabels = [ + 'psmdbmongoddefault.label', + 'pxchaproxydefault.label', + 'pxcpxcdefault.label', + 'pgpgbouncerdefault.label', + 'pgpostgresqldefault.label', +]; export const possibleComponentOptionsStubs = { psmdb: [{ name: 'mongod', value: 'mongod', label: 'Percona Operator for MongoDB' }], @@ -26,11 +36,16 @@ export const possibleComponentOptionsStubs = { { name: 'pxc', value: 'pxc', label: 'Percona Operator for MySQL' }, { name: 'haproxy', value: 'haproxy', label: 'HAProxy' }, ], + pg: [ + { name: 'postgresql', value: 'postgresql', label: 'Percona Operator for PostgreSQL' }, + { name: 'pgbouncer', value: 'pgbouncer', label: 'PostgreSQL Bouncer' }, + ], }; export const operatorsOptionsStubs = [ { name: 'psmdb', value: 'psmdb', label: 'Percona Operator for MongoDB 1' }, { name: 'pxc', value: 'pxc', label: 'Percona Operator for MySQL 1' }, + { name: 'pg', value: 'pg', label: 'Percona Operator for PostgreSQL 1' }, ]; export const psmdbComponentOptionsStubs = [{ name: 'mongod', value: 'mongod', label: 'Percona Operator for MongoDB' }]; diff --git a/public/app/percona/dbaas/components/Kubernetes/OperatorStatusItem/KubernetesOperatorStatus/OperatorStatus/OperatorStatus.constants.ts b/public/app/percona/dbaas/components/Kubernetes/OperatorStatusItem/KubernetesOperatorStatus/OperatorStatus/OperatorStatus.constants.ts index d87394ed805c9..da2068e9fbed6 100644 --- a/public/app/percona/dbaas/components/Kubernetes/OperatorStatusItem/KubernetesOperatorStatus/OperatorStatus/OperatorStatus.constants.ts +++ b/public/app/percona/dbaas/components/Kubernetes/OperatorStatusItem/KubernetesOperatorStatus/OperatorStatus/OperatorStatus.constants.ts @@ -9,6 +9,7 @@ export const OPERATORS_DOCS_URL = { [Databases.proxysql]: '', [Databases.mariadb]: '', [Databases.haproxy]: '', + [Databases.pgbouncer]: '', }; export const VERSION_PLACEHOLDER = ''; @@ -20,6 +21,7 @@ export const OPERATORS_RN_URL = { [Databases.proxysql]: '', [Databases.mariadb]: '', [Databases.haproxy]: '', + [Databases.pgbouncer]: '', }; export const STATUS_DATA_QA = { diff --git a/public/app/percona/dbaas/components/Kubernetes/OperatorStatusRow/OperatorStatusRow.test.tsx b/public/app/percona/dbaas/components/Kubernetes/OperatorStatusRow/OperatorStatusRow.test.tsx index 1576d03d8e0dd..8d40a5a82d611 100644 --- a/public/app/percona/dbaas/components/Kubernetes/OperatorStatusRow/OperatorStatusRow.test.tsx +++ b/public/app/percona/dbaas/components/Kubernetes/OperatorStatusRow/OperatorStatusRow.test.tsx @@ -17,6 +17,7 @@ describe('OperatorStatusRow::', () => { operators: { psmdb: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, pxc: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, + pg: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, }, }; render( @@ -47,6 +48,7 @@ describe('OperatorStatusRow::', () => { operators: { psmdb: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, pxc: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, + pg: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, }, }; render( @@ -76,6 +78,7 @@ describe('OperatorStatusRow::', () => { operators: { psmdb: { status: KubernetesOperatorStatus.invalid, version: '1', availableVersion: '1' }, pxc: { status: KubernetesOperatorStatus.unsupported, version: '1', availableVersion: '1' }, + pg: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, }, }; render( @@ -105,6 +108,7 @@ describe('OperatorStatusRow::', () => { operators: { psmdb: { status: KubernetesOperatorStatus.unavailable, version: '1', availableVersion: '1' }, pxc: { status: KubernetesOperatorStatus.invalid, version: '1', availableVersion: '1' }, + pg: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, }, }; render( @@ -134,6 +138,7 @@ describe('OperatorStatusRow::', () => { operators: { psmdb: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, pxc: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, + pg: { status: KubernetesOperatorStatus.ok, version: '1', availableVersion: '1' }, }, }; render( diff --git a/public/app/percona/dbaas/components/Kubernetes/OperatorStatusRow/OperatorStatusRow.tsx b/public/app/percona/dbaas/components/Kubernetes/OperatorStatusRow/OperatorStatusRow.tsx index 0666ee7f65b55..b25de3aa10e2f 100644 --- a/public/app/percona/dbaas/components/Kubernetes/OperatorStatusRow/OperatorStatusRow.tsx +++ b/public/app/percona/dbaas/components/Kubernetes/OperatorStatusRow/OperatorStatusRow.tsx @@ -42,25 +42,29 @@ export const OperatorStatusRow: FC = ({ [element] ); + const operators = useMemo( + () => [ + { databaseType: Databases.mysql, operator: element.operators.pxc }, + { databaseType: Databases.mongodb, operator: element.operators.psmdb }, + { databaseType: Databases.postgresql, operator: element.operators.pg }, + ], + [element] + ); + return (
- - + {operators.map((item) => ( + + ))}
{ pxc: { status: KubernetesOperatorStatus.ok, }, + pg: { + status: KubernetesOperatorStatus.ok, + }, }, status: KubernetesClusterStatus.ok, }); diff --git a/public/app/percona/shared/core/constants.ts b/public/app/percona/shared/core/constants.ts index a59ca235a56b2..db977c686645f 100644 --- a/public/app/percona/shared/core/constants.ts +++ b/public/app/percona/shared/core/constants.ts @@ -12,6 +12,7 @@ export const DATABASE_LABELS = { [Databases.proxysql]: 'ProxySQL', [Databases.mariadb]: 'MariaDB', [Databases.haproxy]: 'HAProxy', + [Databases.pgbouncer]: 'PGBouncer', }; export const OPERATOR_LABELS = { @@ -21,6 +22,7 @@ export const OPERATOR_LABELS = { [Databases.proxysql]: '', [Databases.mariadb]: '', [Databases.haproxy]: '', + [Databases.pgbouncer]: '', }; export const OPERATOR_FULL_LABELS = { @@ -30,6 +32,7 @@ export const OPERATOR_FULL_LABELS = { [Databases.proxysql]: '', [Databases.mariadb]: '', [Databases.haproxy]: '', + [Databases.pgbouncer]: '', }; export const PERCONA_CANCELLED_ERROR_NAME = 'percona-cancelled-request'; @@ -54,4 +57,5 @@ export const DATABASE_ICONS: Record = { [Databases.proxysql]: 'percona-database-proxysql', [Databases.mariadb]: 'percona-database-mysql', [Databases.haproxy]: 'percona-database-haproxy', + [Databases.pgbouncer]: 'percona-database-postgresql', }; diff --git a/public/app/percona/shared/core/reducers/dbaas/dbClusters/dbClusters.utils.ts b/public/app/percona/shared/core/reducers/dbaas/dbClusters/dbClusters.utils.ts index 0e66468995c7b..1fa0d42b6cc5a 100644 --- a/public/app/percona/shared/core/reducers/dbaas/dbClusters/dbClusters.utils.ts +++ b/public/app/percona/shared/core/reducers/dbaas/dbClusters/dbClusters.utils.ts @@ -16,9 +16,11 @@ export const formatDBClusters = (results: DBClusterListResponse[], kubernetes: K return results.reduce((acc: DBCluster[], r, index) => { const pxcClusters: DBClusterResponse[] = r.pxc_clusters ?? []; const psmdbClusters: DBClusterResponse[] = r.psmdb_clusters ?? []; + const pgClusters: DBClusterResponse[] = r.postgresql_clusters ?? []; const pxcClustersModel = clustersToModel(Databases.mysql, pxcClusters, kubernetes, index); const psmdbClustersModel = clustersToModel(Databases.mongodb, psmdbClusters, kubernetes, index); + const pgClusterModel = clustersToModel(Databases.postgresql, pgClusters, kubernetes, index); - return acc.concat([...pxcClustersModel, ...psmdbClustersModel]); + return acc.concat([...pxcClustersModel, ...psmdbClustersModel, ...pgClusterModel]); }, []); }; diff --git a/public/app/percona/shared/core/types.ts b/public/app/percona/shared/core/types.ts index 76e3f36cb6047..26e98fc9b6be8 100644 --- a/public/app/percona/shared/core/types.ts +++ b/public/app/percona/shared/core/types.ts @@ -5,6 +5,7 @@ export enum Databases { mariadb = 'mariadb', proxysql = 'proxysql', haproxy = 'haproxy', + pgbouncer = 'pgbouncer', } export enum ApiErrorCode { diff --git a/public/app/percona/ui-events/components/Telemetry.tsx b/public/app/percona/ui-events/components/Telemetry.tsx index 77dee75bccf40..3ccc0f8bb2f2b 100644 --- a/public/app/percona/ui-events/components/Telemetry.tsx +++ b/public/app/percona/ui-events/components/Telemetry.tsx @@ -1,9 +1,9 @@ import React, { FC, useEffect } from 'react'; -import { useSelector } from 'react-redux'; import { getPerconaSettings } from 'app/percona/shared/core/selectors'; import { EventStore } from 'app/percona/ui-events/EventStore'; import { UIEventsService } from 'app/percona/ui-events/UIEvents.service'; +import { useSelector } from 'app/types'; export interface UiEventsProps {}