diff --git a/web/pgAdmin4.py b/web/pgAdmin4.py
index 10aabe8a9..939c67f8f 100644
--- a/web/pgAdmin4.py
+++ b/web/pgAdmin4.py
@@ -16,6 +16,9 @@ import sys
if sys.version_info < (3, 4):
raise RuntimeError('This application must be run under Python 3.4 '
'or later.')
+# Due to https://github.com/eventlet/eventlet/issues/670
+if sys.version_info <= (3, 9):
+ import select
import builtins
import os
diff --git a/web/pgadmin/misc/cloud/google/__init__.py b/web/pgadmin/misc/cloud/google/__init__.py
index 162f58d46..5d0cf3420 100644
--- a/web/pgadmin/misc/cloud/google/__init__.py
+++ b/web/pgadmin/misc/cloud/google/__init__.py
@@ -71,7 +71,7 @@ def verify_credentials():
data = json.loads(request.data)
client_secret_path = data['secret']['client_secret_file'] if \
'client_secret_file' in data['secret'] else None
- status = True
+ status = False
error = None
res_data = {}
@@ -91,15 +91,14 @@ def verify_credentials():
# get auth url
auth_url, error_msg = _google.get_auth_url(request.host_url)
if error_msg:
- status = False
error = error_msg
else:
+ status = True
res_data = {'auth_url': auth_url}
# save google object
- session['google']['client_config'] = client_config
- session['google']['google_obj'] = pickle.dumps(_google, -1)
+ session['google']['client_config'] = client_config
+ session['google']['google_obj'] = pickle.dumps(_google, -1)
else:
- status = False
error = 'Client secret path not found'
return make_json_response(success=status, errormsg=error, data=res_data)
diff --git a/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx b/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx
index 452cdd984..95921ea43 100644
--- a/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx
+++ b/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx
@@ -271,6 +271,10 @@ export default function CloudWizard({ nodeInfo, nodeData, onClose, cloudPanel})
if(activeStep == 3 && (cloudProvider == CLOUD_PROVIDERS.AWS || cloudProvider == CLOUD_PROVIDERS.AZURE || cloudProvider == CLOUD_PROVIDERS.GOOGLE)) {
resolve(true);
}
+ else if(activeStep == 1 && (cloudProvider == CLOUD_PROVIDERS.AWS || cloudProvider == CLOUD_PROVIDERS.AZURE || cloudProvider == CLOUD_PROVIDERS.GOOGLE)) {
+ setVerificationIntiated(false);
+ }
+ setErrMsg(['', '']);
resolve();
});
};
diff --git a/web/pgadmin/misc/cloud/static/js/google.js b/web/pgadmin/misc/cloud/static/js/google.js
index 2a14ce610..6cfcf8257 100644
--- a/web/pgadmin/misc/cloud/static/js/google.js
+++ b/web/pgadmin/misc/cloud/static/js/google.js
@@ -83,7 +83,7 @@ export function GoogleCredentials(props) {
child.close();
}
resolve();
- } else if (res.data && res.data.success == 0 && (res.data.errormsg == 'Invalid state parameter.' || res.data.errormsg == 'Access denied.' || res.data.errormsg == 'Authentication is failed.')){
+ } else if (res.data && res.data.success == 0 && res.data.errormsg ){
_eventBus.fireEvent('SET_ERROR_MESSAGE_FOR_CLOUD_WIZARD',[MESSAGE_TYPE.ERROR, res.data.errormsg]);
_eventBus.fireEvent('SET_CRED_VERIFICATION_INITIATED',false);
clearInterval(interval);
@@ -242,9 +242,12 @@ GoogleDatabaseDetails.propTypes = {
// Validation functions
export function validateGoogleStep2(cloudInstanceDetails) {
let isError = false;
- if (isEmptyString(cloudInstanceDetails.name) ||
- isEmptyString(cloudInstanceDetails.db_version) || isEmptyString(cloudInstanceDetails.instance_type) ||
- isEmptyString(cloudInstanceDetails.region)|| isEmptyString(cloudInstanceDetails.storage_size) || isEmptyString(cloudInstanceDetails.public_ips)) {
+ if ((isEmptyString(cloudInstanceDetails.name) || isEmptyString(cloudInstanceDetails.project) ||
+ isEmptyString(cloudInstanceDetails.region) || isEmptyString(cloudInstanceDetails.availability_zone) ||
+ isEmptyString(cloudInstanceDetails.db_version) || isEmptyString(cloudInstanceDetails.instance_type) ||
+ isEmptyString(cloudInstanceDetails.instance_class) || isEmptyString(cloudInstanceDetails.storage_type)||
+ isEmptyString(cloudInstanceDetails.storage_size) || isEmptyString(cloudInstanceDetails.public_ips)) ||
+ (cloudInstanceDetails.high_availability && isEmptyString(cloudInstanceDetails.secondary_availability_zone))) {
isError = true;
}
return isError;
@@ -274,9 +277,17 @@ function createData(name, value) {
// Summary section
export function getGoogleSummary(cloud, cloudInstanceDetails, cloudDBDetails) {
- let dbVersion = cloudInstanceDetails.db_version;
- dbVersion = dbVersion.charAt(0) + dbVersion.slice(1,7).toLowerCase() + 'SQL ' + dbVersion.split('_')[1];
+ let db_version = cloudInstanceDetails.db_version;
+ db_version = db_version.charAt(0) + db_version.slice(1,7).toLowerCase() + 'SQL ' + db_version.split('_')[1];
let storageType = cloudInstanceDetails.storage_type.split('_')[1];
+ let instance_class = cloudInstanceDetails.instance_class.charAt(0).toUpperCase() + cloudInstanceDetails.instance_class.slice(1);
+ let instance_type = cloudInstanceDetails.instance_type;
+ if (instance_class =='Standard' || instance_class =='Highmem' ){
+ instance_type = instance_type.split('-')[2] + ' vCPU ' + Math.round((parseInt(instance_type.split('-')[3]))/1024) + ' GB';
+ }else{
+ const instance_type_mapping = {'db-f1-micro':'1 vCPU, 0.6 GB', 'db-g1-small': '1 vCPU, 1.7 GB'};
+ instance_type = instance_type_mapping[instance_type];
+ }
const rows1 = [
createData(gettext('Cloud'), cloud),
@@ -287,8 +298,9 @@ export function getGoogleSummary(cloud, cloudInstanceDetails, cloudDBDetails) {
];
const rows2 = [
- createData(gettext('PostgreSQL version'), dbVersion),
- createData(gettext('Instance type'), cloudInstanceDetails.instance_type),
+ createData(gettext('PostgreSQL version'), db_version),
+ createData(gettext('Instance class'), instance_class),
+ createData(gettext('Instance type'), instance_type),
];
const rows3 = [
diff --git a/web/pgadmin/misc/cloud/static/js/google_schema.ui.js b/web/pgadmin/misc/cloud/static/js/google_schema.ui.js
index 1f9182e2d..2d4e35a5f 100644
--- a/web/pgadmin/misc/cloud/static/js/google_schema.ui.js
+++ b/web/pgadmin/misc/cloud/static/js/google_schema.ui.js
@@ -38,7 +38,7 @@ class GoogleCredSchema extends BaseUISchema{
id: 'client_secret_file',
label: gettext('Client secret file'),
type: 'file',
- helpMessage: gettext('Select a client secrets file containing the client ID, client secret, and other OAuth 2.0 parameters for google authentication. Refer link for creating client secret.'),
+ helpMessage: gettext('Select a client secrets file containing the client ID, client secret, and other OAuth 2.0 parameters for google authentication. Refer link for creating client secret.'),
controlProps: {
dialogType: 'select_file',
supportedTypes: ['json'],
@@ -65,6 +65,7 @@ class GoogleCredSchema extends BaseUISchema{
obj.fieldOptions.authenticateGoogle(state.client_secret_file)
.then(()=>{
resolve(()=>({
+ is_authenticating: false,
}));
})
.catch((err)=>{
@@ -81,7 +82,7 @@ class GoogleCredSchema extends BaseUISchema{
deps:['auth_btn'],
deferredDepChange: (state, source)=>{
return new Promise((resolve, reject)=>{
- if(source == 'auth_btn' && state.is_authenticating ) {
+ if(source == 'auth_btn' && state.is_authenticating ) {
obj.fieldOptions.verification_ack()
.then(()=>{
resolve();
@@ -261,7 +262,7 @@ class GoogleStorageSchema extends BaseUISchema {
{
id: 'storage_size',
label: gettext('Storage capacity'),
- type: 'text',
+ type: 'int',
mode: ['create'],
noEmpty: true,
deps: ['storage_type'],
@@ -272,7 +273,7 @@ class GoogleStorageSchema extends BaseUISchema {
validate(data, setErrMsg) {
if (data.storage_size && (data.storage_size < 9 || data.storage_size > 65536)) {
- setErrMsg('storage_size', gettext('Please enter value betwwen 10 and 65,536.'));
+ setErrMsg('storage_size', gettext('Please enter the value between 10 and 65,536.'));
return true;
}
return false;
@@ -350,8 +351,8 @@ class GoogleHighAvailabilitySchema extends BaseUISchema {
}
validate(data, setErrMsg) {
- if (data.high_availability && (isEmptyString(data.secondary_availability_zone))) {
- setErrMsg('secondary_availability_zone', gettext('Please select Secondary availability zone.'));
+ if (data.high_availability && (isEmptyString(data.secondary_availability_zone)) || (data.secondary_availability_zone == data.availability_zone)) {
+ setErrMsg('secondary_availability_zone', gettext('Please select Secondary availability zone different than primary.'));
return true;
}
return false;
@@ -519,6 +520,14 @@ class GoogleClusterSchema extends BaseUISchema {
},
];
}
+
+ validate(data, setErr) {
+ if ( !isEmptyString(data.name) && (!/^(?=[a-z])[a-z0-9\-]*$/.test(data.name) || data.name.length > 97)) {
+ setErr('name',gettext('Name must only contain lowercase letters, numbers, and hyphens. Start with a letter.'));
+ return true;
+ }
+ return false;
+ }
}
-export {GoogleCredSchema, GoogleClusterSchema, GoogleDatabaseSchema};
\ No newline at end of file
+export {GoogleCredSchema, GoogleClusterSchema, GoogleDatabaseSchema};