2023-01-09 01:02:26 -06:00
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
2024-01-01 02:43:48 -06:00
// Copyright (C) 2013 - 2024, The pgAdmin Development Team
2023-01-09 01:02:26 -06:00
// 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 ,
2023-03-24 05:37:02 -05:00
project : '' ,
2023-01-09 01:02:26 -06:00
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 [
2023-03-24 05:37:02 -05:00
{ id : 'project' ,
label : gettext ( 'Project' ) ,
mode : [ 'create' ] ,
noEmpty : true ,
type : ( ) => {
return {
type : 'select' ,
options : this . fieldOptions . projects
} ;
} ,
} ,
2023-01-09 01:02:26 -06:00
{
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 ,
2023-03-24 05:37:02 -05:00
deps : [ 'project' ] ,
type : ( state ) => {
return {
type : 'select' ,
options : state . project
? ( ) => this . fieldOptions . providers ( state . project )
: [ ] ,
optionsReloadBasis : state . project ,
allowClear : false ,
} ;
}
2023-01-09 01:02:26 -06:00
} ,
] ;
}
}
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 : '' ,
2023-07-10 00:52:24 -05:00
disk _throughput : 125 ,
2023-01-09 01:02:26 -06:00
... initValues
} ) ;
this . fieldOptions = {
... fieldOptions ,
} ;
this . initValues = initValues ;
this . volumeType = '' ;
}
get idAttribute ( ) {
return 'oid' ;
}
validate ( data , setErrMsg ) {
2023-07-10 00:52:24 -05:00
if ( ! data . provider . includes ( CLOUD _PROVIDERS . AWS ) && isEmptyString ( data . volume _properties ) ) {
setErrMsg ( 'volume_properties' , gettext ( 'Please select volume properties.' ) ) ;
2023-01-09 01:02:26 -06:00
return true ;
}
2023-07-10 00:52:24 -05:00
if ( data . provider . includes ( CLOUD _PROVIDERS . AWS ) ) {
2023-01-09 01:02:26 -06:00
if ( ! isEmptyString ( data . volume _size ) ) {
2023-07-10 00:52:24 -05:00
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.' ) ) ;
2023-01-09 01:02:26 -06:00
return true ;
}
2023-07-10 00:52:24 -05:00
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.' ) ) ;
2023-01-09 01:02:26 -06:00
return true ;
}
}
2023-07-10 00:52:24 -05:00
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 ) ) ;
2023-01-09 01:02:26 -06:00
return true ;
}
2023-07-10 00:52:24 -05:00
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 ) ) ;
2023-01-09 01:02:26 -06:00
return true ;
}
}
2023-07-10 00:52:24 -05:00
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 ;
}
2023-01-09 01:02:26 -06:00
}
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 ) => {
2023-07-10 00:52:24 -05:00
return state . provider === CLOUD _PROVIDERS . AZURE ;
2023-01-09 01:02:26 -06:00
} ,
} , {
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' ) {
2023-07-10 00:52:24 -05:00
if ( state . volume _type == 'io2' ) {
2023-01-09 01:02:26 -06:00
return { volume _size : 4 } ;
} else {
return { volume _size : 1 } ;
}
}
} ,
visible : ( state ) => {
2024-01-25 05:21:40 -06:00
return state . provider ? . includes ( CLOUD _PROVIDERS . AWS ) ;
2023-01-09 01:02:26 -06:00
} ,
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 ) => {
2024-01-25 05:21:40 -06:00
return state . provider ? . includes ( CLOUD _PROVIDERS . AWS ) ;
2023-01-09 01:02:26 -06:00
} , deps : [ 'volume_type' ] ,
depChange : ( state , source ) => {
obj . volumeType = state . volume _type ;
if ( source [ 0 ] !== 'volume_IOPS' ) {
2023-07-10 00:52:24 -05:00
if ( state . provider . includes ( CLOUD _PROVIDERS . AWS ) ) {
2023-01-09 01:02:26 -06:00
if ( state . volume _type === 'io2' ) {
return { volume _IOPS : 100 } ;
} else {
return { volume _IOPS : 3000 } ;
}
} else {
return { volume _IOPS : 120 } ;
}
}
} ,
2023-07-10 00:52:24 -05:00
} , {
id : 'disk_throughput' , label : gettext ( 'Disk throughput' ) , type : 'text' ,
mode : [ 'create' ] ,
deps : [ 'volume_type' ] ,
visible : ( state ) => {
2024-01-25 05:21:40 -06:00
return state . provider ? . includes ( CLOUD _PROVIDERS . AWS ) && state . volume _type === 'gp3' ;
2023-07-10 00:52:24 -05:00
}
}
2023-01-09 01:02:26 -06:00
] ;
}
}
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' ,
2023-03-24 05:37:02 -05:00
options : ( ) => this . fieldOptions . db _versions ( this . initValues . cluster _type , state . database _type ) ,
2023-01-09 01:02:26 -06:00
optionsReloadBasis : state . database _type ,
} ;
} ,
} , {
id : 'password' , label : gettext ( 'Database password' ) , type : 'password' ,
2024-04-29 01:14:17 -05:00
mode : [ 'create' ] , noEmpty : true , controlProps : { autoComplete : 'new-password' }
2023-01-09 01:02:26 -06:00
} , {
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 ,
2023-07-10 00:52:24 -05:00
disk _throughput : 125 ,
2023-01-09 01:02:26 -06:00
... 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' ,
2023-03-24 05:37:02 -05:00
options : ( ) => this . fieldOptions . regions ( )
2023-01-09 01:02:26 -06:00
} ;
} ,
} , {
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
} ;