mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2024-12-23 07:34:35 -06:00
Fixed following issues related to cloud deployment:
1) The Mumbai region issue has been resolved 2) Display name of regions has been modified appropriately 3) The password field has been validated the same way as AWS 4) Added support for a list of IP addresses in the public IP address range field.
This commit is contained in:
parent
dd4849070a
commit
ffc1c6c3b7
@ -137,17 +137,18 @@ class RdsProvider(AbsProvider):
|
||||
""" Create a new security group for the instance """
|
||||
ec2 = self._get_aws_client('ec2', args)
|
||||
ip = args.public_ip if args.public_ip else get_my_ip()
|
||||
ip = ip.split(',')
|
||||
|
||||
# Deploy the security group
|
||||
try:
|
||||
name = 'pgacloud_{}_{}_{}'.format(args.name,
|
||||
ip.replace('.', '-'),
|
||||
ip[0].replace('.', '-'),
|
||||
get_random_id())
|
||||
debug(args, 'Creating security group: {}...'.format(name))
|
||||
output({'Creating': 'Creating security group: {}...'.format(name)})
|
||||
response = ec2.create_security_group(
|
||||
Description='Inbound access for {} to RDS instance {}'.format(
|
||||
ip, args.name),
|
||||
ip[0], args.name),
|
||||
GroupName=name
|
||||
)
|
||||
except Exception as e:
|
||||
@ -158,9 +159,17 @@ class RdsProvider(AbsProvider):
|
||||
def _add_ingress_rule(self, args, security_group):
|
||||
""" Add a local -> PostgreSQL ingress rule to a security group """
|
||||
ec2 = self._get_aws_client('ec2', args)
|
||||
ip = args.public_ip if args.public_ip else '{}/32'.format(get_my_ip())
|
||||
ip = args.public_ip if args.public_ip else\
|
||||
'{}/32'.format(get_my_ip())
|
||||
port = args.db_port or 5432
|
||||
IpRanges = []
|
||||
|
||||
ip = ip.split(',')
|
||||
for i in ip:
|
||||
IpRanges.append({
|
||||
'CidrIp': i,
|
||||
'Description': 'pgcloud client {}'.format(i)
|
||||
})
|
||||
try:
|
||||
output({'Adding': 'Adding ingress rule for: {}...'.format(ip)})
|
||||
debug(args,
|
||||
@ -172,12 +181,7 @@ class RdsProvider(AbsProvider):
|
||||
'FromPort': port,
|
||||
'ToPort': port,
|
||||
'IpProtocol': 'tcp',
|
||||
'IpRanges': [
|
||||
{
|
||||
'CidrIp': ip,
|
||||
'Description': 'pgcloud client {}'.format(ip)
|
||||
},
|
||||
]
|
||||
'IpRanges': IpRanges
|
||||
},
|
||||
]
|
||||
)
|
||||
|
@ -25,6 +25,7 @@ from pgadmin.model import db, Server, Process
|
||||
from pgadmin.misc.cloud.utils.rds import RDS, verify_aws_credentials,\
|
||||
get_aws_db_instances, get_aws_db_versions, clear_aws_session,\
|
||||
get_aws_regions
|
||||
from pgadmin.misc.cloud.utils import get_my_ip
|
||||
|
||||
from config import root
|
||||
|
||||
@ -81,7 +82,8 @@ class CloudModule(PgAdminModule):
|
||||
'cloud.get_aws_db_instances',
|
||||
'cloud.update_cloud_server',
|
||||
'cloud.update_cloud_process',
|
||||
'cloud.get_aws_regions']
|
||||
'cloud.get_aws_regions',
|
||||
'cloud.get_host_ip']
|
||||
|
||||
|
||||
# Create blueprint for CloudModule class
|
||||
@ -108,6 +110,13 @@ def script():
|
||||
return res
|
||||
|
||||
|
||||
@blueprint.route('/get_host_ip/',
|
||||
methods=['GET'], endpoint='get_host_ip')
|
||||
@login_required
|
||||
def get_host_ip():
|
||||
return make_json_response(data=get_my_ip())
|
||||
|
||||
|
||||
@blueprint.route('/verify_credentials/',
|
||||
methods=['POST'], endpoint='verify_credentials')
|
||||
@login_required
|
||||
@ -285,7 +294,8 @@ def _create_server(data):
|
||||
maintenance_db=data.get('db'),
|
||||
username=data.get('username'),
|
||||
ssl_mode='prefer',
|
||||
cloud_status=data.get('cloud_status')
|
||||
cloud_status=data.get('cloud_status'),
|
||||
connect_timeout=30,
|
||||
)
|
||||
|
||||
db.session.add(server)
|
||||
|
@ -68,8 +68,22 @@ export default function CloudWizard({ nodeInfo, nodeData }) {
|
||||
const [cloudDBCred, setCloudDBCred] = React.useState({});
|
||||
const [cloudDBDetails, setCloudDBDetails] = React.useState({});
|
||||
const [callRDSAPI, setCallRDSAPI] = React.useState({});
|
||||
const [hostIP, setHostIP] = React.useState('127.0.0.1/32');
|
||||
const axiosApi = getApiInstance();
|
||||
|
||||
React.useEffect(() => {
|
||||
let _url = url_for('cloud.get_host_ip') ;
|
||||
axiosApi.get(_url)
|
||||
.then((res) => {
|
||||
if (res.data.data) {
|
||||
setHostIP(res.data.data);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
Alertify.error(gettext(`Error while getting the host ip: ${error.response.data.errormsg}`));
|
||||
});
|
||||
}, []);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (callRDSAPI == 2) {
|
||||
const cloudDBInstanceSchema = new CloudInstanceDetailsSchema({
|
||||
@ -111,6 +125,7 @@ export default function CloudWizard({ nodeInfo, nodeData }) {
|
||||
server_groups: ()=>getNodeListById(pgAdmin.Browser.Nodes['server_group'], nodeInfo, nodeData),
|
||||
}, {
|
||||
gid: nodeInfo['server_group']._id,
|
||||
hostIP: hostIP,
|
||||
});
|
||||
setCloudInstanceDetailsInstance(cloudDBInstanceSchema);
|
||||
}
|
||||
@ -151,7 +166,7 @@ export default function CloudWizard({ nodeInfo, nodeData }) {
|
||||
return isError;
|
||||
};
|
||||
|
||||
const validateCloudStep2 = (cloudInstanceDetails) => {
|
||||
const validateCloudStep2 = (cloudInstanceDetails, host_ip) => {
|
||||
let isError = false;
|
||||
if (isEmptyString(cloudInstanceDetails.aws_name) ||
|
||||
isEmptyString(cloudInstanceDetails.aws_db_version) || isEmptyString(cloudInstanceDetails.aws_instance_type) ||
|
||||
@ -162,7 +177,7 @@ export default function CloudWizard({ nodeInfo, nodeData }) {
|
||||
if(cloudInstanceDetails.aws_storage_type == 'io1' && isEmptyString(cloudInstanceDetails.aws_storage_IOPS)) {
|
||||
isError = true;
|
||||
}
|
||||
if (isEmptyString(cloudInstanceDetails.aws_public_ip)) cloudInstanceDetails.aws_public_ip = '127.0.0.1/32';
|
||||
if (isEmptyString(cloudInstanceDetails.aws_public_ip)) cloudInstanceDetails.aws_public_ip = host_ip;
|
||||
return isError;
|
||||
};
|
||||
|
||||
@ -222,7 +237,7 @@ export default function CloudWizard({ nodeInfo, nodeData }) {
|
||||
isError = validateCloudStep1(cloudDBCred);
|
||||
break;
|
||||
case 2:
|
||||
isError = validateCloudStep2(cloudInstanceDetails);
|
||||
isError = validateCloudStep2(cloudInstanceDetails, hostIP);
|
||||
break;
|
||||
case 3:
|
||||
isError = validateCloudStep3(cloudDBDetails);
|
||||
|
@ -27,6 +27,7 @@ define('pgadmin.misc.cloud', [
|
||||
return pgBrowser.Cloud;
|
||||
}
|
||||
|
||||
|
||||
// Create an Object Cloud of pgBrowser class
|
||||
pgBrowser.Cloud = {
|
||||
init: function() {
|
||||
|
@ -17,7 +17,7 @@ class CloudInstanceDetailsSchema extends BaseUISchema {
|
||||
super({
|
||||
oid: undefined,
|
||||
aws_name: '',
|
||||
aws_public_ip: '127.0.0.1/32',
|
||||
aws_public_ip: initValues.hostIP,
|
||||
...initValues
|
||||
});
|
||||
|
||||
@ -39,7 +39,7 @@ class CloudInstanceDetailsSchema extends BaseUISchema {
|
||||
}, {
|
||||
id: 'aws_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'),
|
||||
helpMessage: gettext('IP Address range for permitting the inbound traffic. Ex: 127.0.0.1/32, add multiple ip addresses/ranges by comma separated.'),
|
||||
}, {
|
||||
type: 'nested-fieldset', label: gettext('Version & Instance'),
|
||||
mode: ['create'],
|
||||
@ -127,9 +127,18 @@ class DatabaseSchema extends BaseUISchema {
|
||||
&& data.aws_db_password != data.aws_db_confirm_password) {
|
||||
setErrMsg('aws_db_confirm_password', gettext('Passwords do not match.'));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (!isEmptyString(data.aws_db_confirm_password) && data.aws_db_confirm_password.length < 8) {
|
||||
setErrMsg('aws_db_confirm_password', gettext('Password must be 8 characters or more.'));
|
||||
return true;
|
||||
}
|
||||
if (data.aws_db_confirm_password.includes('\'') || data.aws_db_confirm_password.includes('"') ||
|
||||
data.aws_db_confirm_password.includes('@') || data.aws_db_confirm_password.includes('/')) {
|
||||
setErrMsg('aws_db_confirm_password', gettext('Invalid passowrd.'));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
get idAttribute() {
|
||||
@ -152,6 +161,7 @@ class DatabaseSchema extends BaseUISchema {
|
||||
}, {
|
||||
id: 'aws_db_password', label: gettext('Password'), type: 'password',
|
||||
mode: ['create'], noEmpty: true,
|
||||
helpMessage: gettext('At least 8 printable ASCII characters. Can not contain any of the following: / \(slash\), \'\(single quote\), "\(double quote\) and @ \(at sign\).')
|
||||
}, {
|
||||
id: 'aws_db_confirm_password', label: gettext('Confirm password'),
|
||||
type: 'password',
|
||||
@ -202,6 +212,7 @@ export class InstanceSchema extends BaseUISchema {
|
||||
if (source[0] == 'aws_db_instance_class') {
|
||||
return {reload_instances: false};
|
||||
} else {
|
||||
state.instanceData = [];
|
||||
return {reload_instances: true};
|
||||
}
|
||||
},
|
||||
|
26
web/pgadmin/misc/cloud/utils/__init__.py
Normal file
26
web/pgadmin/misc/cloud/utils/__init__.py
Normal file
@ -0,0 +1,26 @@
|
||||
# ##########################################################################
|
||||
# #
|
||||
# # pgAdmin 4 - PostgreSQL Tools
|
||||
# #
|
||||
# # Copyright (C) 2013 - 2022, The pgAdmin Development Team
|
||||
# # This software is released under the PostgreSQL Licence
|
||||
# #
|
||||
# ##########################################################################
|
||||
|
||||
import urllib3
|
||||
|
||||
|
||||
def get_my_ip():
|
||||
""" Return the public IP of this host """
|
||||
http = urllib3.PoolManager()
|
||||
try:
|
||||
external_ip = http.request.urlopen(
|
||||
'https://ident.me').read().decode('utf8')
|
||||
except Exception:
|
||||
try:
|
||||
external_ip = http.request.urlopen(
|
||||
'https://ifconfig.me/ip').read().decode('utf8')
|
||||
except Exception:
|
||||
external_ip = '127.0.0.1'
|
||||
|
||||
return external_ip
|
@ -13,24 +13,28 @@
|
||||
AWS_REGIONS = {
|
||||
'us-gov-east-1': 'AWS GovCloud (US-East)',
|
||||
'us-gov-west-1': 'AWS GovCloud (US-West)',
|
||||
'af-south-1': 'Africa (Cape Town)',
|
||||
'ap-east-1': 'Asia Pacific (Hong Kong)',
|
||||
'ap-south-': 'Asia Pacific (Mumbai)',
|
||||
'ap-northeast-3': 'Asia Pacific (Osaka-Local)',
|
||||
'ap-south-1': 'Asia Pacific (Mumbai)',
|
||||
'ap-northeast-3': 'Asia Pacific (Osaka)',
|
||||
'ap-northeast-2': 'Asia Pacific (Seoul)',
|
||||
'ap-southeast-1': 'Asia Pacific (Singapore)',
|
||||
'ap-southeast-2': 'Asia Pacific (Sydney)',
|
||||
'ap-southeast-3': 'Asia Pacific (Jakarta)',
|
||||
'ap-northeast-1': 'Asia Pacific (Tokyo)',
|
||||
'ca-central-1': 'Canada (Central)',
|
||||
'cn-north-1': 'China (Beijing)',
|
||||
'cn-northwest-1': 'China (Ningxia)',
|
||||
'eu-central-1': 'EU (Frankfurt)',
|
||||
'eu-west-1': 'EU (Ireland)',
|
||||
'eu-west-2': 'EU (London)',
|
||||
'eu-west-3': 'EU (Paris)',
|
||||
'eu-north-1': 'EU (Stockholm)',
|
||||
'eu-central-1': 'Europe (Frankfurt)',
|
||||
'eu-west-1': 'Europe (Ireland)',
|
||||
'eu-west-2': 'Europe (London)',
|
||||
'eu-west-3': 'Europe (Paris)',
|
||||
'eu-north-1': 'Europe (Stockholm)',
|
||||
'eu-south-1': 'Europe (Milan)',
|
||||
'sa-east-1': 'South America (Sao Paulo)',
|
||||
'us-east-1': 'US East (N. Virginia)',
|
||||
'us-east-2': 'US East (Ohio)',
|
||||
'us-west-1': 'US West (N. California)',
|
||||
'us-west-2': 'US West (Oregon)',
|
||||
'me-south-1': 'Middle East (Bahrain)',
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user