pgadmin4/web/pgadmin/misc/cloud/static/js/biganimal_schema.ui.js
2024-04-29 11:44:17 +05:30

505 lines
16 KiB
JavaScript

/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2024, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import gettext from 'sources/gettext';
import BaseUISchema from 'sources/SchemaView/base_schema.ui';
import { isEmptyString } from 'sources/validators';
import { CLOUD_PROVIDERS } from './cloud_constants';
class BigAnimalClusterTypeSchema extends BaseUISchema {
constructor(fieldOptions = {}, initValues = {}) {
super({
oid: undefined,
project: '',
cluster_type: '',
replicas: 0,
provider: '',
...initValues
});
this.fieldOptions = {
...fieldOptions,
};
this.initValues = initValues;
}
get idAttribute() {
return 'oid';
}
validate(data, setErrMsg) {
if (data.cluster_type == 'ha' && data.replicas == 0) {
setErrMsg('replicas', gettext('Please select number of stand by replicas.'));
return true;
}
return false;
}
get baseFields() {
return [
{ id: 'project',
label: gettext('Project'),
mode: ['create'],
noEmpty: true,
type: () => {
return {
type: 'select',
options: this.fieldOptions.projects
};
},
},
{
id: 'cluster_type', label: gettext('Cluster type'), noEmpty: true,
type: () => {
return {
type: 'toggle',
options: [
{'label': gettext('Single Node'), value: 'single'},
{'label': gettext('High Availability'), value: 'ha'},
{'label': gettext('Extreme High Availability'), value: 'eha'},
],
};
},
}, {
id: 'replicas', label: gettext('Number of standby replicas'), type: 'select',
mode: ['create'], deps: ['cluster_type'],
controlProps: { allowClear: false },
helpMessage: gettext('Adding standby replicas will increase your number of CPUs, as well as your cost.'),
options: [
{'label': gettext('1'), 'value': 1},
{'label': gettext('2'), 'value': 2},
],
disabled: (state) => {
return state.cluster_type != 'ha';
}
}, { id: 'provider', label: gettext('Cluster provider'), noEmpty: true,
deps:['project'],
type: (state) => {
return {
type: 'select',
options: state.project
? () => this.fieldOptions.providers(state.project)
: [],
optionsReloadBasis: state.project,
allowClear: false,
};
}
},
];
}
}
class BigAnimalInstanceSchema extends BaseUISchema {
constructor(fieldOptions = {}, initValues={}) {
super({
oid: undefined,
instance_type: '',
instance_series: '',
instance_size: '',
...initValues
});
this.fieldOptions = {
...fieldOptions,
};
this.initValues = initValues;
}
get idAttribute() {
return 'oid';
}
get baseFields() {
return [
{
id: 'instance_type', label: gettext('Instance type'),
mode: ['create'],
deps: [['region']],
type: (state) => {
return {
type: 'select',
options: ()=>this.fieldOptions.instance_types(state.region, state.provider),
optionsReloadBasis: state.region,
optionsLoaded: (options) => { state.instanceData = options; },
controlProps: {
allowClear: false,
filter: (options) => {
if (options.length == 0) return;
let _types = _.uniq(_.map(options, 'category')),
_options = [];
_.forEach(_types, (region) => {
_options.push({
'label': region,
'value': region
});
});
return _options;
},
}
};
},
noEmpty: true,
},{
id: 'instance_series', label: gettext('Instance series'),
mode: ['create'], deps: ['instance_type'],
type: (state) => {
return {
type: 'select',
options: state.instanceData,
optionsReloadBasis: state.instance_type,
controlProps: {
allowClear: false,
filter: (options) => {
if (options.length == 0) return;
let _types = _.filter(options, {'category': state.instance_type}),
_options = [];
_types = _.uniq(_.map(_types, 'familyName'));
_.forEach(_types, (value) => {
_options.push({
'label': value,
'value': value
});
});
return _options;
},
}
};
},
noEmpty: true,
},{
id: 'instance_size', label: gettext('Instance size'),
mode: ['create'], deps: ['instance_series'],
type: (state) => {
return {
type: 'select',
options: state.instanceData,
optionsReloadBasis: state.instance_series,
controlProps: {
allowClear: false,
filter: (options) => {
if (options.length == 0) return;
let _types = _.filter(options, {'familyName': state.instance_series}),
_options = [];
_.forEach(_types, (value) => {
_options.push({
'label': value.instanceTypeName + ' (' + value.cpu + 'vCPU, ' + value.ram + 'GB RAM)',
'value': value.instanceTypeName + ' (' + value.cpu + 'vCPU, ' + value.ram + 'GB RAM)' + '||' + value.instanceTypeId,
});
});
return _options;
},
}
};
}, noEmpty: true,
},
];
}
}
class BigAnimalVolumeSchema extends BaseUISchema {
constructor(fieldOptions = {}, initValues = {}) {
super({
oid: undefined,
volume_type: '',
volume_properties: '',
volume_size: 4,
volume_IOPS: '',
disk_throughput: 125,
...initValues
});
this.fieldOptions = {
...fieldOptions,
};
this.initValues = initValues;
this.volumeType = '';
}
get idAttribute() {
return 'oid';
}
validate(data, setErrMsg) {
if (!data.provider.includes(CLOUD_PROVIDERS.AWS) && isEmptyString(data.volume_properties)) {
setErrMsg('volume_properties', gettext('Please select volume properties.'));
return true;
}
if (data.provider.includes(CLOUD_PROVIDERS.AWS)) {
if (!isEmptyString(data.volume_size)) {
if( data.volume_type != 'io2' && (data.volume_size < 1 || data.volume_size > 16384)) {
setErrMsg('volume_size', gettext('Please enter the volume size in the range between 1 to 16384.'));
return true;
}
if (data.volume_type == 'io2' && (data.volume_size < 4 || data.volume_size > 16384)) {
setErrMsg('volume_size', gettext('Please enter the volume size in the range between 4 to 16384.'));
return true;
}
}
if (isEmptyString(data.volume_IOPS)) {
setErrMsg('volume_IOPS', gettext('Please enter volume IOPS.'));
return true;
}
else if (!isEmptyString(data.volume_IOPS)) {
if(data.volume_type == 'io2' && (data.volume_IOPS < 100 || data.volume_IOPS > Math.min(data.volume_size*500, 64000))) {
let errMsg = 'Please enter the volume IOPS in the range between 100 to ' + Math.min(data.volume_size*500, 64000) + '.';
setErrMsg('volume_IOPS', gettext(errMsg));
return true;
}
if(data.volume_type == 'gp3' && (data.volume_IOPS < 3000 || data.volume_IOPS > Math.min(Math.max(data.volume_size*500, 3000), 16000))) {
let errMsg = 'Please enter the volume IOPS in the range between 3000 to ' + Math.min(Math.max(data.volume_size*500, 3000), 16000) + '.';
setErrMsg('volume_IOPS', gettext(errMsg));
return true;
}
}
if ( data.volume_type === 'gp3' && !isEmptyString(data.disk_throughput) && (data.disk_throughput < 125 || data.disk_throughput > Math.min( ((data.volume_IOPS - 3000)/100*25 + 750) , 1000))) {
let errMsg = 'Please enter the Disk throughput in the range between 125 to ' + Math.min( ((data.volume_IOPS - 3000)/100*25+750) , 1000) + '.';
setErrMsg('disk_throughput', gettext(errMsg));
return true;
}
}
return false;
}
get baseFields() {
let obj = this;
return [
{
id: 'volume_type', label: gettext('Volume type'),
mode: ['create'], deps: [['region'], ['instance_series']],
type: (state) => {
return {
type: 'select',
options: ()=>this.fieldOptions.volume_types(state.region, state.provider),
optionsReloadBasis: state.region,
controlProps: {
allowClear: false,
filter: (options) => {
if (options.length == 0) return;
return options.filter((option) => {
return (option.supportedInstanceFamilyNames.includes(state.instance_series));
});
},
}
};
}, noEmpty: true,
},{
id: 'volume_properties', label: gettext('Volume properties'),
mode: ['create'], deps: ['volume_type', 'provider'],
type: (state) => {
return {
type: 'select',
options: ()=>this.fieldOptions.volume_properties(state.region, state.provider, state.volume_type),
optionsReloadBasis: state.volume_type,
};
},
visible: (state) => {
return state.provider === CLOUD_PROVIDERS.AZURE;
},
}, {
id: 'volume_size', label: gettext('Size'), type: 'text',
mode: ['create'], noEmpty: true, deps: ['volume_type'],
depChange: (state, source)=> {
obj.volumeType = state.volume_type;
if (source[0] !== 'volume_size') {
if(state.volume_type == 'io2') {
return {volume_size: 4};
} else {
return {volume_size: 1};
}
}
},
visible: (state) => {
return state.provider?.includes(CLOUD_PROVIDERS.AWS);
},
helpMessage: obj.volumeType == 'io2' ? gettext('Size (4-16,384 GiB)') : gettext('Size (1-16,384 GiB)')
}, {
id: 'volume_IOPS', label: gettext('IOPS'), type: 'text',
mode: ['create'],
visible: (state) => {
return state.provider?.includes(CLOUD_PROVIDERS.AWS);
}, deps: ['volume_type'],
depChange: (state, source) => {
obj.volumeType = state.volume_type;
if (source[0] !== 'volume_IOPS') {
if (state.provider.includes(CLOUD_PROVIDERS.AWS)) {
if(state.volume_type === 'io2') {
return {volume_IOPS: 100};
} else {
return {volume_IOPS: 3000};
}
} else {
return {volume_IOPS: 120};
}
}
},
},{
id: 'disk_throughput', label: gettext('Disk throughput'), type: 'text',
mode: ['create'],
deps : ['volume_type'],
visible: (state) => {
return state.provider?.includes(CLOUD_PROVIDERS.AWS) && state.volume_type === 'gp3';
}
}
];
}
}
class BigAnimalDatabaseSchema extends BaseUISchema {
constructor(fieldOptions = {}, initValues = {}) {
super({
oid: undefined,
password: '',
confirm_password: '',
database_type: '',
postgres_version: '',
high_availability: false,
replicas: 0,
...initValues
});
this.fieldOptions = {
...fieldOptions,
};
this.initValues = initValues;
}
validate(data, setErrMsg) {
if(!isEmptyString(data.password) && !isEmptyString(data.confirm_password)
&& data.password != data.confirm_password) {
setErrMsg('confirm_password', gettext('Passwords do not match.'));
return true;
}
if (!isEmptyString(data.confirm_password) && data.confirm_password.length < 12) {
setErrMsg('confirm_password', gettext('Password must be 12 characters or more.'));
return true;
}
if (data.high_availability && (isEmptyString(data.replicas) || data.replicas <= 0)) {
setErrMsg('replicas', gettext('Please select number of stand by replicas.'));
return true;
}
return false;
}
get idAttribute() {
return 'oid';
}
get baseFields() {
return [
{
id: 'gid', label: gettext('pgAdmin server group'), type: 'select',
options: this.fieldOptions.server_groups,
mode: ['create'],
controlProps: { allowClear: false },
noEmpty: true,
}, {
id: 'database_type', label: gettext('Database type'), mode: ['create'],
type: 'select',
options: this.fieldOptions.db_types,
noEmpty: true, orientation: 'vertical',
},{
id: 'postgres_version', label: gettext('Database version'),
mode: ['create'], noEmpty: true, deps: ['database_type'],
type: (state) => {
return {
type: 'select',
options: ()=>this.fieldOptions.db_versions(this.initValues.cluster_type, state.database_type),
optionsReloadBasis: state.database_type,
};
},
},{
id: 'password', label: gettext('Database password'), type: 'password',
mode: ['create'], noEmpty: true, controlProps: { autoComplete: 'new-password' }
},{
id: 'confirm_password', label: gettext('Confirm password'), type: 'password',
mode: ['create'], noEmpty: true,
},
];
}
}
class BigAnimalClusterSchema extends BaseUISchema {
constructor(fieldOptions = {}, initValues = {}) {
super({
oid: undefined,
name: '',
region: '',
cloud_type: 'public',
biganimal_public_ip: initValues.hostIP,
disk_throughput: 125,
...initValues
});
this.fieldOptions = {
...fieldOptions,
};
this.initValues = initValues;
this.instance_types = new BigAnimalInstanceSchema({
instance_types: this.fieldOptions.instance_types,
});
this.volume_types = new BigAnimalVolumeSchema({
volume_types: this.fieldOptions.volume_types,
volume_properties: this.fieldOptions.volume_properties
});
}
get idAttribute() {
return 'oid';
}
get baseFields() {
return [
{
id: 'name', label: gettext('Cluster name'), type: 'text',
mode: ['create'], noEmpty: true,
},{
id: 'region', label: gettext('Region'),
controlProps: { allowClear: false },
noEmpty: true,
mode: ['create'],
dep: [this.initValues.provider],
type: () => {
return {
type: 'select',
options: ()=>this.fieldOptions.regions()
};
},
},{
id: 'biganimal_public_ip', label: gettext('Public IP range'), type: 'text',
mode: ['create'],
helpMessage: gettext('IP address range for allowed inbound traffic, for example: 127.0.0.1/32. Add multiple IP addresses/ranges separated with commas. Leave blank for 0.0.0.0/0'),
},{
type: 'nested-fieldset', label: gettext('Instance Type'),
mode: ['create'], deps: ['region'],
schema: this.instance_types,
},{
type: 'nested-fieldset', label: gettext('Storage'),
mode: ['create'], deps: ['region'],
schema: this.volume_types,
}
];
}
}
export {
BigAnimalClusterSchema,
BigAnimalDatabaseSchema,
BigAnimalClusterTypeSchema
};