[RDBMS] Hotfix: `az postgres flexible-server create` : Update VnetName to exclude servername and update default region for MySQL (#15295)

* hotfix chnages

* Remove - from password if thats the first character

* Style check fix and Mysql sku

* Remove MySQL SKU validator

* Remove MySQL SKu and tier validators
This commit is contained in:
arde0708 2020-09-27 20:35:09 -07:00 коммит произвёл GitHub
Родитель 39d334dddd
Коммит 23801a42fd
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
6 изменённых файлов: 49 добавлений и 38 удалений

Просмотреть файл

@ -14,7 +14,8 @@ from ._client_factory import resource_client_factory
logger = get_logger(__name__)
DEFAULT_LOCATION = 'eastus' # For testing: 'eastus2euap'
DEFAULT_LOCATION_PG = 'eastus' # For testing: 'eastus2euap'
DEFAULT_LOCATION_MySQL = 'westus2'
def resolve_poller(result, cli_ctx, name):
@ -29,10 +30,13 @@ def create_random_resource_name(prefix='azure', length=15):
return prefix + ''.join(digits)
def generate_missing_parameters(cmd, location, resource_group_name, server_name):
def generate_missing_parameters(cmd, location, resource_group_name, server_name, db_engine):
# if location is not passed as a parameter or is missing from local context
if location is None:
location = DEFAULT_LOCATION
if db_engine == 'postgres':
location = DEFAULT_LOCATION_PG
else:
location = DEFAULT_LOCATION_MySQL
# If resource group is there in local context, check for its existence.
resource_group_exists = True
@ -60,14 +64,14 @@ def generate_missing_parameters(cmd, location, resource_group_name, server_name)
def generate_password(administrator_login_password):
import secrets
import string
if administrator_login_password is None:
passwordLength = 16
special_character = random.choice('!@#,?;:$&*')
administrator_login_password = secrets.token_urlsafe(passwordLength)
random_position = random.randint(1, len(administrator_login_password) - 1)
administrator_login_password = administrator_login_password[
:random_position] + special_character + administrator_login_password[
random_position + 1:]
passwordlength = 16
administrator_login_password = secrets.token_urlsafe(passwordlength)
index = administrator_login_password.find("-")
if index != -1:
replaced_char = random.choice(string.ascii_letters)
administrator_login_password = administrator_login_password.replace("-", replaced_char)
return administrator_login_password

Просмотреть файл

@ -16,7 +16,7 @@ from azure.cli.core.commands.parameters import (
get_three_state_flag)
from azure.cli.command_modules.rdbms.validators import configuration_value_validator, validate_subnet, \
retention_validator, tls_validator, public_access_validator, pg_storage_validator, mysql_storage_validator, tier_validator, \
pg_sku_name_validator, mysql_sku_name_validator, pg_version_validator, mysql_version_validator, maintenance_window_validator, ip_address_validator
pg_sku_name_validator, pg_version_validator, mysql_version_validator, maintenance_window_validator, ip_address_validator
from azure.cli.core.commands.validators import get_default_location_from_resource_group
from azure.cli.core.local_context import LocalContextAttribute, LocalContextAction
@ -240,9 +240,9 @@ def load_arguments(self, _): # pylint: disable=too-many-statements
c.argument('zone', options_list=['--zone, -z'],
help='Availability zone into which to provision the resource.')
elif command_group == 'mysql':
c.argument('tier', default='Burstable', validator=tier_validator,
c.argument('tier', default='Burstable',
help='Compute tier of the server. Accepted values: Burstable, GeneralPurpose, Memory Optimized ')
c.argument('sku_name', default='Standard_B1ms', options_list=['--sku-name'], validator=mysql_sku_name_validator,
c.argument('sku_name', default='Standard_B1ms', options_list=['--sku-name'],
help='The name of the compute SKU. Follows the convention Standard_{VM name}. Examples: Standard_B1ms, Standard_D4s_v3 ')
c.argument('storage_mb', default='10', options_list=['--storage-size'], type=int, validator=mysql_storage_validator,
help='The storage capacity of the server. Minimum is 5 GiB and increases in 1 GiB increments. Max is 16 TiB.')
@ -290,8 +290,6 @@ def load_arguments(self, _): # pylint: disable=too-many-statements
with self.argument_context('{} flexible-server update'.format(command_group)) as c:
c.ignore('assign_identity')
c.argument('tier', options_list=['--tier'], validator=tier_validator,
help='Compute tier of the server. Accepted values: Burstable, GeneralPurpose, Memory Optimized ')
c.argument('backup_retention', type=int, options_list=['--backup-retention'],
help='The number of days a backup is retained. Range of 7 to 35 days. Default is 7 days.', validator=retention_validator)
c.argument('administrator_login_password', options_list=['--admin-password', '-p'],
@ -302,7 +300,9 @@ def load_arguments(self, _): # pylint: disable=too-many-statements
help='Period of time (UTC) designated for maintenance. Examples: "Sun:23:30" to schedule on Sunday, 11:30pm UTC. To set back to default pass in "Disabled".')
c.argument('tags', tags_type)
if command_group == 'mysql':
c.argument('sku_name', options_list=['--sku-name'], validator=mysql_sku_name_validator,
c.argument('tier', options_list=['--tier'],
help='Compute tier of the server. Accepted values: Burstable, GeneralPurpose, Memory Optimized ')
c.argument('sku_name', options_list=['--sku-name'],
help='The name of the compute SKU. Follows the convention Standard_{VM name}. Examples: Standard_B1ms, Standard_D4s_v3 ')
c.argument('storage_mb', options_list=['--storage-size'], type=int,
validator=mysql_storage_validator,
@ -317,6 +317,8 @@ def load_arguments(self, _): # pylint: disable=too-many-statements
c.argument('replication_role', options_list=['--replication-role'],
help='The replication role of the server.')
elif command_group == 'postgres':
c.argument('tier', options_list=['--tier'], validator=tier_validator,
help='Compute tier of the server. Accepted values: Burstable, GeneralPurpose, Memory Optimized ')
c.argument('sku_name', options_list=['--sku-name'], validator=pg_sku_name_validator,
help='The name of the compute SKU. Follows the convention Standard_{VM name}. Examples: Standard_D4s_v3 ')
c.argument('storage_mb', options_list=['--storage-size'], type=int,
@ -410,13 +412,15 @@ def load_arguments(self, _): # pylint: disable=too-many-statements
with self.argument_context('{} flexible-server replica create'.format(command_group)) as c:
c.argument('source_server', options_list=['--source-server'],
help='The name or resource ID of the source server to restore from.')
c.argument('tier', options_list=['--tier'], validator=tier_validator,
help='Compute tier of the server. Accepted values: Burstable, GeneralPurpose, Memory Optimized ')
if command_group == 'mysql':
c.argument('tier', options_list=['--tier'],
help='Compute tier of the server. Accepted values: Burstable, GeneralPurpose, Memory Optimized ')
c.argument('sku_name', options_list=['--sku-name'],
validator=mysql_sku_name_validator,
help='The name of the compute SKU. Follows the convention'
' Standard_{VM name}. Examples: Standard_B1ms, Standard_D4s_v3 ')
if command_group == 'postgres':
c.argument('tier', options_list=['--tier'], validator=tier_validator,
help='Compute tier of the server. Accepted values: Burstable, GeneralPurpose, Memory Optimized ')
with self.argument_context('{} flexible-server replica stop-replication'.format(command_group)) as c:
c.argument('server_name', options_list=['--name', '-s'], help='Name of the server.')

Просмотреть файл

@ -56,7 +56,8 @@ def flexible_server_create(cmd, client, resource_group_name=None, server_name=No
# Populate desired parameters
location, resource_group_name, server_name = generate_missing_parameters(cmd, location, resource_group_name,
server_name)
server_name, 'mysql')
server_name = server_name.lower()
# Handle Vnet scenario
if (subnet_arm_resource_id is not None) or (vnet_resource_id is not None):
@ -116,8 +117,8 @@ def flexible_server_create(cmd, client, resource_group_name=None, server_name=No
sku = server_result.sku.name
host = server_result.fully_qualified_domain_name
logger.warning('Make a note of your password. If you forget, you would have to reset your password with \
\'az mysql flexible-server update -n %s -g %s -p <new-password>\'.',
logger.warning('Make a note of your password. If you forget, you would have to '
'reset your password with \'az mysql flexible-server update -n %s -g %s -p <new-password>\'.',
server_name, resource_group_name)
_update_local_contexts(cmd, server_name, resource_group_name, location, user)

Просмотреть файл

@ -59,7 +59,8 @@ def flexible_server_create(cmd, client,
# Populate desired parameters
location, resource_group_name, server_name = generate_missing_parameters(cmd, location, resource_group_name,
server_name)
server_name, 'postgres')
server_name = server_name.lower()
# Handle Vnet scenario
if (subnet_arm_resource_id is not None) or (vnet_resource_id is not None):
@ -113,15 +114,15 @@ def flexible_server_create(cmd, client,
sku = server_result.sku.name
host = server_result.fully_qualified_domain_name
logger.warning('Make a note of your password. If you forget, you would have to \
reset your password with \'az postgres flexible-server update -n %s -g %s -p <new-password>\'.',
logger.warning('Make a note of your password. If you forget, you would have to '
'reset your password with \'az postgres flexible-server update -n %s -g %s -p <new-password>\'.',
server_name, resource_group_name)
_update_local_contexts(cmd, server_name, resource_group_name, location, user)
return _form_response(user, sku, loc, server_id, host, version,
administrator_login_password if administrator_login_password is not None else '*****',
_create_postgresql_connection_string(host, administrator_login_password), firewall_id,
_create_postgresql_connection_string(host, user, administrator_login_password), firewall_id,
subnet_id)
except Exception as ex: # pylint: disable=broad-except
logger.error(ex)
@ -329,7 +330,7 @@ def flexible_server_connection_string(
def _create_postgresql_connection_strings(host, user, password, database):
result = {
'psql_cmd': "psql --host={host} --port=5432 --username={user} --dbname=postgres",
'psql_cmd': "postgresql://{user}:{password}@{host}/postgres?sslmode=require",
'ado.net': "Server={host};Database=postgres;Port=5432;User Id={user};Password={password};",
'jdbc': "jdbc:postgresql://{host}:5432/postgres?user={user}&password={password}",
'jdbc Spring': "spring.datasource.url=jdbc:postgresql://{host}:5432/postgres "
@ -355,12 +356,13 @@ def _create_postgresql_connection_strings(host, user, password, database):
return result
def _create_postgresql_connection_string(host, password):
def _create_postgresql_connection_string(host, user, password):
connection_kwargs = {
'user': user,
'host': host,
'password': password if password is not None else '{password}'
}
return 'postgres://postgres:{password}@{host}/postgres?sslmode=require'.format(**connection_kwargs)
return 'postgresql://{user}:{password}@{host}/postgres?sslmode=require'.format(**connection_kwargs)
def _form_response(username, sku, location, server_id, host, version, password, connection_string, firewall_id=None,

Просмотреть файл

@ -59,7 +59,7 @@ def prepare_vnet(cmd, server_name, vnet, subnet, resource_group_name, loc, deleg
"The Subnet does not exist with the supplied subnet id. Checking the existence of the Vnet in the supplied Id...")
subnet_result = _create_vnet_subnet_delegation(nw_client, resource_group, vnet_name,
server_name + 'Subnet', location, server_name,
'Subnet' + server_name[6:], location, server_name,
delegation,
VirtualNetwork, Subnet, AddressSpace,
DEFAULT_VNET_ADDRESS_PREFIX, DEFAULT_SUBNET_PREFIX)
@ -77,13 +77,13 @@ def prepare_vnet(cmd, server_name, vnet, subnet, resource_group_name, loc, deleg
location = rg.location
validate_rg_loc_sub(resource_group, subscription, location, resource_group_name,
get_subscription_id(cmd.cli_ctx), loc)
subnet_result = _create_vnet_subnet_delegation(nw_client, resource_group, vnet_name, server_name + 'Subnet',
subnet_result = _create_vnet_subnet_delegation(nw_client, resource_group, vnet_name, 'Subnet' + server_name[6:],
location, server_name, delegation, VirtualNetwork, Subnet,
AddressSpace, DEFAULT_VNET_ADDRESS_PREFIX,
DEFAULT_SUBNET_PREFIX)
elif len(vnet.split('\\')) == 1:
logger.warning("You have supplied a Vnet Name. Verifying its existence...")
subnet_result = _create_vnet_subnet_delegation(nw_client, resource_group_name, vnet, server_name + 'Subnet',
subnet_result = _create_vnet_subnet_delegation(nw_client, resource_group_name, vnet, 'Subnet' + server_name[6:],
loc, server_name, delegation, VirtualNetwork, Subnet,
AddressSpace, DEFAULT_VNET_ADDRESS_PREFIX,
DEFAULT_SUBNET_PREFIX)
@ -210,7 +210,7 @@ def create_vnet(cmd, servername, location, resource_group_name, delegation_servi
'Delegation',
resource_type=ResourceType.MGMT_NETWORK)
client = network_client_factory(cmd.cli_ctx)
vnet_name, subnet_name, vnet_address_prefix, subnet_prefix = _create_vnet_metadata(servername)
vnet_name, subnet_name, vnet_address_prefix, subnet_prefix = _create_vnet_metadata(servername[6:])
logger.warning('Creating new vnet "%s" in resource group "%s"...', vnet_name, resource_group_name)
client.virtual_networks.create_or_update(resource_group_name, vnet_name,
@ -227,8 +227,8 @@ def create_vnet(cmd, servername, location, resource_group_name, delegation_servi
def _create_vnet_metadata(servername):
vnet_name = servername + 'VNET'
subnet_name = servername + 'Subnet'
vnet_name = 'VNET' + servername
subnet_name = 'Subnet' + servername
vnet_address_prefix = DEFAULT_VNET_ADDRESS_PREFIX
subnet_prefix = DEFAULT_SUBNET_PREFIX
return vnet_name, subnet_name, vnet_address_prefix, subnet_prefix

Просмотреть файл

@ -174,11 +174,11 @@ def mysql_sku_name_validator(ns):
'Examples: Standard_D4s_v3 Standard_E8s_v3 Standard_B1ms')
elif len(ns.sku_name.split('_')) == 3:
server_type, cpu, server_v3 = ns.sku_name.split('_')
if server_type != 'Standard' or server_v3 != 'v3':
if server_type != 'Standard' or server_v3 != 'v4':
raise CLIError('Incorrect value for --sku-name. Follow the convention Standard_{VM name}. '
'Examples: Standard_D4s_v3 Standard_B1ms')
if not re.match(r"^(D|E)\d+s$", cpu) or \
(re.match(r"^(D|E)\d+s$", cpu) and int(cpu[1:-1]) not in [2, 4, 8, 16, 32, 48, 64]):
if not re.match(r"^(D|E)\d+ds$", cpu) or \
(re.match(r"^(D|E)\d+ds$", cpu) and int(cpu[1:-1]) not in [2, 4, 8, 16, 32, 48, 64]):
raise CLIError('Incorrect value for --sku-name. Follow the convention Standard_{VM name}. '
'Examples: Standard_D4s_v3 Standard_E8s_v3 Standard_B1ms. '
'\nAllowed number of vCores: 2, 4, 8, 16, 32, 48, 64')