diff --git a/web/pgacloud/providers/biganimal.py b/web/pgacloud/providers/biganimal.py index 53b0789f2..fb6afebb2 100644 --- a/web/pgacloud/providers/biganimal.py +++ b/web/pgacloud/providers/biganimal.py @@ -70,12 +70,17 @@ class BigAnimalProvider(AbsProvider): parser_create_instance.add_argument('--public-ip', default='', help='Public IP ' '(default: 127.0.0.1)') + parser_create_instance.add_argument('--high-availability', + required=True, + help='High Availability') def cmd_create_instance(self, args): """ Create a biganimal cluster """ try: private_network = True if args.private_network == '1' else False + high_availability = True if args.high_availability == '1' else\ + False ip = args.public_ip if args.public_ip else '0.0.0.0/0' IpRanges = [] @@ -102,7 +107,7 @@ class BigAnimalProvider(AbsProvider): 'replicas': 3, 'volumePropertiesId': args.volume_properties, 'volumeTypeId': args.volume_type, - 'zoneRedundantHa': False, + 'zoneRedundantHa': high_availability, 'pgConfigMap': [], } diff --git a/web/pgadmin/misc/cloud/biganimal/__init__.py b/web/pgadmin/misc/cloud/biganimal/__init__.py index 4b4d0b55b..b8a6a3f3b 100644 --- a/web/pgadmin/misc/cloud/biganimal/__init__.py +++ b/web/pgadmin/misc/cloud/biganimal/__init__.py @@ -366,6 +366,8 @@ def deploy_on_biganimal(data): _label = data['instance_details']['name'] _private_network = '1' if str(data['instance_details']['cloud_type'] ) == 'private' else '0' + _high_availability = '1' if data['db_details']['high_availability']\ + else '0' _instance_size = data['instance_details']['instance_size'].split('||')[1] args = [_cmd_script, @@ -386,7 +388,9 @@ def deploy_on_biganimal(data): '--instance-type', str(_instance_size), '--private-network', - _private_network + _private_network, + '--high-availability', + _high_availability ] if 'biganimal_public_ip' in data['instance_details']: diff --git a/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx b/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx index 7c191b95d..4aea8e6c8 100644 --- a/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx +++ b/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx @@ -230,17 +230,17 @@ export default function CloudWizard({ nodeInfo, nodeData }) { axiosApi.get(_url) .then((res) => { if (res.data && res.data.success == 1 ) { - setErrMsg([MESSAGE_TYPE.SUCCESS, 'Authentication completed successfully. Click the Next button to proceed.']); + setErrMsg([MESSAGE_TYPE.SUCCESS, gettext('Authentication completed successfully. Click the Next button to proceed.')]); setVerificationIntiated(true); clearInterval(myInterval); } else if (res.data && res.data.success == 0 && res.data.errormsg == 'access_denied') { - setErrMsg([MESSAGE_TYPE.INFO, 'Verification failed. Access Denied...']); + setErrMsg([MESSAGE_TYPE.INFO, gettext('Verification failed. Access Denied...')]); setVerificationIntiated(false); clearInterval(myInterval); } else if (res.data && res.data.success == 0 && res.data.errormsg == 'forbidden') { - setErrMsg([MESSAGE_TYPE.INFO, 'Authentication completed successfully but you do not have permission to create the cluster.']); + setErrMsg([MESSAGE_TYPE.INFO, gettext('Authentication completed successfully but you do not have permission to create the cluster.')]); setVerificationIntiated(false); clearInterval(myInterval); } diff --git a/web/pgadmin/misc/cloud/static/js/biganimal.js b/web/pgadmin/misc/cloud/static/js/biganimal.js index 39c60eae7..47096fb74 100644 --- a/web/pgadmin/misc/cloud/static/js/biganimal.js +++ b/web/pgadmin/misc/cloud/static/js/biganimal.js @@ -155,6 +155,9 @@ export function validateBigAnimal() { } function createData(name, value) { + if (typeof(value) == 'boolean') { + value = (value === true) ? 'True' : 'False'; + } return { name, value }; } @@ -184,6 +187,7 @@ export function getBigAnimalSummary(cloud, bigAnimalInstanceData, bigAnimalDatab createData('Password', 'xxxxxxx'), createData('Database Type', bigAnimalDatabaseData.database_type), createData('Database Version', bigAnimalDatabaseData.postgres_version), + createData('High Availability', bigAnimalDatabaseData.high_availability), ]; return [rows1, rows2, rows3, rows4]; @@ -194,8 +198,7 @@ export function validateBigAnimalStep2(cloudInstanceDetails) { if (isEmptyString(cloudInstanceDetails.name) || isEmptyString(cloudInstanceDetails.region) || isEmptyString(cloudInstanceDetails.instance_type) || isEmptyString(cloudInstanceDetails.instance_series)|| isEmptyString(cloudInstanceDetails.instance_size) || - isEmptyString(cloudInstanceDetails.volume_type)|| isEmptyString(cloudInstanceDetails.volume_properties) || - isEmptyString(cloudInstanceDetails.cloud_type)) { + isEmptyString(cloudInstanceDetails.volume_type)|| isEmptyString(cloudInstanceDetails.volume_properties)) { isError = true; } diff --git a/web/pgadmin/misc/cloud/static/js/cloud_db_details_schema.ui.js b/web/pgadmin/misc/cloud/static/js/cloud_db_details_schema.ui.js index 69768239a..28623a7dd 100644 --- a/web/pgadmin/misc/cloud/static/js/cloud_db_details_schema.ui.js +++ b/web/pgadmin/misc/cloud/static/js/cloud_db_details_schema.ui.js @@ -147,7 +147,7 @@ class DatabaseSchema extends BaseUISchema { get baseFields() { return [{ - id: 'gid', label: gettext('Server group'), type: 'select', + id: 'gid', label: gettext('pgAdmin server group'), type: 'select', options: this.fieldOptions.server_groups, mode: ['create'], controlProps: { allowClear: false }, @@ -458,59 +458,6 @@ class BigAnimalVolumeSchema extends BaseUISchema { } } - -class BigAnimalNetworkSchema extends BaseUISchema { - constructor(fieldOptions = {}, initValues = {}) { - super({ - oid: undefined, - cloud_type: '', - biganimal_public_ip: '', - ...initValues - }); - - this.fieldOptions = { - ...fieldOptions, - }; - this.initValues = initValues; - } - - get idAttribute() { - return 'oid'; - } - - get baseFields() { - var obj = this; - return [ - { - id: 'cloud_type', label: gettext('Cloud type'), type: 'toggle', - mode: ['create'], - options: [ - {'label': gettext('Private'), 'value': 'private'}, - {'label': gettext('Public'), 'value': 'public'}, - ], noEmpty: true, - helpMessage: gettext('Private networking allows only IP addresses within your private network to connect to your cluster.' - + ' Public means that any client can connect to your cluster’s public IP address over the internet.') - },{ - id: 'biganimal_public_ip', label: gettext('Public IP range'), type: 'text', - mode: ['create'], deps: ['cloud_type'], - disabled: (state) => { - if (state.cloud_type == 'public') return false; - return true; - }, - depChange: (state, source)=> { - if(source[0] == 'cloud_type') { - if (state.cloud_type == 'public') { - return {biganimal_public_ip: obj.initValues.hostIP}; - } else { - return {biganimal_public_ip: ''}; - } - } - }, - helpMessage: gettext('IP Address range for permitting the inbound traffic. Ex: 127.0.0.1/32, add multiple ip addresses/ranges by comma separated. Leave it blank for 0.0.0.0/0'), - }, - ]; - } -} class BigAnimalDatabaseSchema extends BaseUISchema { constructor(fieldOptions = {}, initValues = {}) { super({ @@ -550,7 +497,7 @@ class BigAnimalDatabaseSchema extends BaseUISchema { get baseFields() { return [ { - id: 'gid', label: gettext('Server group'), type: 'select', + id: 'gid', label: gettext('pgAdmin server group'), type: 'select', options: this.fieldOptions.server_groups, mode: ['create'], controlProps: { allowClear: false }, @@ -570,7 +517,12 @@ class BigAnimalDatabaseSchema extends BaseUISchema { },{ id: 'confirm_password', label: gettext('Confirm password'), type: 'password', mode: ['create'], noEmpty: true, + },{ + type: 'nested-fieldset', label: gettext('Availability'), + mode: ['create'], + schema: new BigAnimalHighAvailSchema(), }, + ]; } } @@ -581,7 +533,8 @@ class BigAnimalClusterSchema extends BaseUISchema { oid: undefined, name: '', region: '', - public_ip: initValues.hostIP, + cloud_type: 'public', + biganimal_public_ip: initValues.hostIP, ...initValues }); @@ -614,6 +567,10 @@ class BigAnimalClusterSchema extends BaseUISchema { controlProps: { allowClear: false }, noEmpty: true, mode: ['create'], + },{ + id: 'biganimal_public_ip', label: gettext('Public IP range'), type: 'text', + mode: ['create'], + helpMessage: gettext('IP Address range for permitting the inbound traffic. Ex: 127.0.0.1/32, add multiple ip addresses/ranges by comma separated. Leave it blank for 0.0.0.0/0'), },{ type: 'nested-fieldset', label: gettext('Instance Type'), mode: ['create'], deps: ['region'], @@ -622,16 +579,47 @@ class BigAnimalClusterSchema extends BaseUISchema { type: 'nested-fieldset', label: gettext('Storage'), mode: ['create'], deps: ['region'], schema: this.volume_types, - }, { - type: 'nested-fieldset', label: gettext('Network Connectivity'), - mode: ['create'], - schema: new BigAnimalNetworkSchema({}, this.initValues), } ]; } } + +class BigAnimalHighAvailSchema extends BaseUISchema { + constructor(fieldOptions = {}, initValues = {}) { + super({ + oid: undefined, + high_availability: '', + ...initValues + }); + + this.fieldOptions = { + ...fieldOptions, + }; + this.initValues = initValues; + } + + get idAttribute() { + return 'oid'; + } + + get baseFields() { + return [ + { + id: 'high_availability_note', type: 'note', + mode: ['create'], + text: gettext('High availability clusters are configured with one primary and two ' + + 'replicas with synchronous streaming replication. Clusters are configured across availability zones in regions with availability zones.'), + },{ + id: 'high_availability', label: gettext('High Availability'), type: 'switch', + mode: ['create'], + helpMessage: gettext('Turning on high availability means your number of CPUs will triple, as will your cost.'), + } + ]; + } +} + export { CloudInstanceDetailsSchema, CloudDBCredSchema, diff --git a/web/pgadmin/static/js/SchemaView/index.jsx b/web/pgadmin/static/js/SchemaView/index.jsx index ca8ed1f4b..9a8919f2f 100644 --- a/web/pgadmin/static/js/SchemaView/index.jsx +++ b/web/pgadmin/static/js/SchemaView/index.jsx @@ -485,6 +485,11 @@ function SchemaDialogView({ setDirty(isDataChanged); /* tell the callbacks the data has changed */ + if(viewHelperProps.mode !== 'edit') { + /* If new then merge the changed data with origData */ + changedData = _.assign({}, schema.origData, changedData); + } + props.onDataChange && props.onDataChange(isDataChanged, changedData); }, [sessData, formReady]); diff --git a/web/regression/javascript/SchemaView/SchemaView.spec.js b/web/regression/javascript/SchemaView/SchemaView.spec.js index 777b344ba..a66c67a68 100644 --- a/web/regression/javascript/SchemaView/SchemaView.spec.js +++ b/web/regression/javascript/SchemaView/SchemaView.spec.js @@ -294,11 +294,11 @@ describe('SchemaView', ()=>{ }, 0); }); - let onRestAction = (done)=> { + let onRestAction = (done, data)=> { ctrl.update(); expect(ctrl.find('DefaultButton[data-test="Reset"]').prop('disabled')).toBeTrue(); expect(ctrl.find('PrimaryButton[data-test="Save"]').prop('disabled')).toBeTrue(); - expect(onDataChange).toHaveBeenCalledWith(false, {}); + expect(onDataChange).toHaveBeenCalledWith(false, data); done(); }; @@ -313,7 +313,7 @@ describe('SchemaView', ()=>{ /* Press OK */ confirmSpy.calls.argsFor(0)[2](); setTimeout(()=>{ - onRestAction(done); + onRestAction(done, { id: undefined, field1: null, field2: null, fieldcoll: null }); }, 0); }, 0); }); @@ -351,7 +351,8 @@ describe('SchemaView', ()=>{ expect(confirmSpy).not.toHaveBeenCalled(); expect(ctrl.find('DefaultButton[data-test="Reset"]').prop('disabled')).toBeTrue(); expect(ctrl.find('PrimaryButton[data-test="Save"]').prop('disabled')).toBeTrue(); - expect(onDataChange).toHaveBeenCalledWith(false, {}); + // on reset, orig data will be considered + expect(onDataChange).toHaveBeenCalledWith(false, { id: undefined, field1: null, field2: null, fieldcoll: null }); done(); }, 0); }, 0); @@ -461,7 +462,7 @@ describe('SchemaView', ()=>{ /* Press OK */ confirmSpy.calls.argsFor(0)[2](); setTimeout(()=>{ - onRestAction(done); + onRestAction(done, {}); }, 0); }, 0); });