def process_route_table_create_namespace(namespace): from azure.mgmt.network.models import RouteTable namespace.parameters = RouteTable() validate_location(namespace) validate_tags(namespace) if hasattr(namespace, 'tags'): namespace.parameters.tags = namespace.tags
def validate_vnet_integration(cmd, namespace): validate_tags(namespace) if namespace.subnet or namespace.vnet: if not namespace.subnet: raise ArgumentUsageError("Cannot use --vnet without --subnet") if not is_valid_resource_id(namespace.subnet) and not namespace.vnet: raise ArgumentUsageError( "Must either specify subnet by resource ID or include --vnet argument" ) client = web_client_factory(cmd.cli_ctx) if is_valid_resource_id(namespace.plan): parse_result = parse_resource_id(namespace.plan) plan_info = client.app_service_plans.get( parse_result['resource_group'], parse_result['name']) else: plan_info = client.app_service_plans.get( name=namespace.plan, resource_group_name=namespace.resource_group_name) sku_name = plan_info.sku.name disallowed_skus = { 'FREE', 'SHARED', 'BASIC', 'ElasticPremium', 'PremiumContainer', 'Isolated', 'IsolatedV2' } if get_sku_tier(sku_name) in disallowed_skus: raise ArgumentUsageError( "App Service Plan has invalid sku for vnet integration: {}." "Plan sku cannot be one of: {}. " "Please run 'az appservice plan create -h' " "to see all available App Service Plan SKUs ".format( sku_name, disallowed_skus))
def process_lb_create_namespace(cmd, namespace): get_default_location_from_resource_group(cmd, namespace) validate_tags(namespace) if namespace.subnet and namespace.public_ip_address: raise ValueError( 'incorrect usage: --subnet NAME --vnet-name NAME | ' '--subnet ID | --public-ip NAME_OR_ID') if namespace.subnet: # validation for an internal load balancer get_subnet_validator( has_type_field=True, allow_new=True, allow_none=True, default_none=True)(cmd, namespace) namespace.public_ip_address_type = None namespace.public_ip_address = None else: # validation for internet facing load balancer get_public_ip_validator(has_type_field=True, allow_none=True, allow_new=True)(cmd, namespace) if namespace.public_ip_dns_name and namespace.public_ip_address_type != 'new': raise CLIError( 'specify --public-ip-dns-name only if creating a new public IP address.') namespace.subnet_type = None namespace.subnet = None namespace.virtual_network_name = None
def process_nw_cm_create_namespace(cmd, namespace): from msrestazure.tools import is_valid_resource_id, resource_id, parse_resource_id validate_tags(namespace) compute_client = get_mgmt_service_client(cmd.cli_ctx, ResourceType.MGMT_COMPUTE).virtual_machines vm_name = parse_resource_id(namespace.source_resource)['name'] rg = namespace.resource_group_name or parse_resource_id(namespace.source_resource).get('resource_group', None) if not rg: raise CLIError('usage error: --source-resource ID | --source-resource NAME --resource-group NAME') vm = compute_client.get(rg, vm_name) namespace.location = vm.location # pylint: disable=no-member get_network_watcher_from_location()(cmd, namespace) if namespace.source_resource and not is_valid_resource_id(namespace.source_resource): namespace.source_resource = resource_id( subscription=get_subscription_id(cmd.cli_ctx), resource_group=rg, namespace='Microsoft.Compute', type='virtualMachines', name=namespace.source_resource) if namespace.dest_resource and not is_valid_resource_id(namespace.dest_resource): namespace.dest_resource = resource_id( subscription=get_subscription_id(cmd.cli_ctx), resource_group=namespace.resource_group_name, namespace='Microsoft.Compute', type='virtualMachines', name=namespace.dest_resource)
def process_secret_set_namespace(cmd, namespace): validate_tags(namespace) content = namespace.value file_path = namespace.file_path encoding = namespace.encoding tags = namespace.tags or {} use_error = CLIError("incorrect usage: [Required] --value VALUE | --file PATH") if (content and file_path) or (not content and not file_path): raise use_error from azure.cli.core.profiles import ResourceType SecretAttributes = cmd.get_models('SecretAttributes', resource_type=ResourceType.DATA_KEYVAULT) namespace.secret_attributes = SecretAttributes() if namespace.expires: namespace.secret_attributes.expires = namespace.expires if namespace.disabled: namespace.secret_attributes.enabled = not namespace.disabled if namespace.not_before: namespace.secret_attributes.not_before = namespace.not_before encoding = encoding or 'utf-8' if file_path: if encoding in secret_text_encoding_values: with open(file_path, 'r') as f: try: content = f.read() except UnicodeDecodeError: raise CLIError("Unable to decode file '{}' with '{}' encoding.".format( file_path, encoding)) encoded_str = content encoded = content.encode(encoding) decoded = encoded.decode(encoding) elif encoding == 'base64': with open(file_path, 'rb') as f: content = f.read() try: encoded = base64.encodebytes(content) except AttributeError: encoded = base64.encodestring(content) # pylint: disable=deprecated-method encoded_str = encoded.decode('utf-8') decoded = base64.b64decode(encoded_str) elif encoding == 'hex': with open(file_path, 'rb') as f: content = f.read() encoded = binascii.b2a_hex(content) encoded_str = encoded.decode('utf-8') decoded = binascii.unhexlify(encoded_str) if content != decoded: raise CLIError("invalid encoding '{}'".format(encoding)) content = encoded_str tags.update({'file-encoding': encoding}) namespace.tags = tags namespace.value = content
def tc_deploy_validator(cmd, ns): if ns.principal_name is not None: if ns.principal_password is None: raise CLIError( 'usage error: --principal-password must be have a value if --principal-name is specified' ) if ns.principal_password is not None: if ns.principal_name is None: raise CLIError( 'usage error: --principal-name must be have a value if --principal-password is specified' ) if sum(1 for ct in [ns.version, ns.prerelease, ns.index_url] if ct) > 1: raise CLIError( 'usage error: can only use one of --index-url | --version/-v | --pre' ) if ns.version: ns.version = ns.version.lower() if ns.version[:1].isdigit(): ns.version = 'v' + ns.version if not _is_valid_version(ns.version): raise CLIError( '--version/-v should be in format v0.0.0 do not include -pre suffix' ) from ._deploy_utils import github_release_version_exists if not github_release_version_exists(cmd.cli_ctx, ns.version, 'TeamCloud'): raise CLIError('--version/-v {} does not exist'.format(ns.version)) if ns.tags: from azure.cli.core.commands.validators import validate_tags validate_tags(ns) if ns.index_url: if not _is_valid_url(ns.index_url): raise CLIError('--index-url should be a valid url') if ns.name is not None: name_clean = '' for n in ns.name.lower(): if n.isalpha() or n.isdigit() or n == '-': name_clean += n ns.name = name_clean if ns.skip_name_validation: logger.warning( 'IMPORTANT: --skip-name-validation prevented unique name validation.' ) else: from ._client_factory import web_client_factory web_client = web_client_factory(cmd.cli_ctx) availability = web_client.check_name_availability(ns.name, 'Site') if not availability.name_available: raise CLIError('--name/-n {}'.format(availability.message))
def validate_asp_create(namespace): validate_tags(namespace) sku = _normalize_sku(namespace.sku) _validate_asp_sku(sku, namespace.app_service_environment, namespace.zone_redundant) if namespace.is_linux and namespace.hyper_v: raise MutuallyExclusiveArgumentError( 'Usage error: --is-linux and --hyper-v cannot be used together.')
def process_autoscale_create_namespace(cmd, namespace): from msrestazure.tools import parse_resource_id validate_tags(namespace) get_target_resource_validator('resource', required=True, preserve_resource_group_parameter=True)(cmd, namespace) if not namespace.resource_group_name: namespace.resource_group_name = parse_resource_id(namespace.resource).get('resource_group', None) get_default_location_from_resource_group(cmd, namespace)
def process_local_gateway_create_namespace(cmd, namespace): ns = namespace get_default_location_from_resource_group(cmd, ns) validate_tags(ns) use_bgp_settings = any([ns.asn or ns.bgp_peering_address or ns.peer_weight]) if use_bgp_settings and (not ns.asn or not ns.bgp_peering_address): raise ValueError( 'incorrect usage: --bgp-peering-address IP --asn ASN [--peer-weight WEIGHT]')
def process_vnet_gateway_update_namespace(cmd, namespace): ns = namespace get_virtual_network_validator()(cmd, ns) get_public_ip_validator()(cmd, ns) validate_tags(ns) public_ip_count = len(ns.public_ip_address or []) if public_ip_count > 2: raise CLIError('Specify a single public IP to create an active-standby gateway or two ' 'public IPs to create an active-active gateway.')
def process_img_tmpl_output_add_namespace(cmd, namespace): from azure.cli.core.commands.parameters import get_subscription_locations outputs = [output for output in [namespace.managed_image, namespace.gallery_image_definition, namespace.is_vhd] if output] # pylint:disable=line-too-long if len(outputs) != 1: err = "Supplied outputs: {}".format(outputs) logger.debug(err) raise CLIError("Usage error: must supply exactly one destination type to add. Supplied {}".format(len(outputs))) if namespace.managed_image: if not is_valid_resource_id(namespace.managed_image): namespace.managed_image = resource_id( subscription=get_subscription_id(cmd.cli_ctx), resource_group=namespace.resource_group_name, namespace='Microsoft.Compute', type='images', name=namespace.managed_image ) if namespace.gallery_image_definition: if not is_valid_resource_id(namespace.gallery_image_definition): if not namespace.gallery_name: raise CLIError("Usage error: gallery image definition is a name and not an ID.") namespace.gallery_image_definition = resource_id( subscription=get_subscription_id(cmd.cli_ctx), resource_group=namespace.resource_group_name, namespace='Microsoft.Compute', type='galleries', name=namespace.gallery_name, child_type_1='images', child_name_1=namespace.gallery_image_definition ) if namespace.is_vhd and not namespace.output_name: raise CLIError("Usage error: If --is-vhd is used, a run output name must be provided via --output-name.") subscription_locations = get_subscription_locations(cmd.cli_ctx) location_names = [l.name for l in subscription_locations] location_display_names = [l.display_name for l in subscription_locations] if namespace.managed_image_location: namespace.managed_image_location = _validate_location(namespace.managed_image_location, location_names, location_display_names) if namespace.gallery_replication_regions: processed_regions = [] for loc in namespace.gallery_replication_regions: processed_regions.append(_validate_location(loc, location_names, location_display_names)) namespace.gallery_replication_regions = processed_regions # get default location from resource group if not any([namespace.managed_image_location, namespace.gallery_replication_regions]) and hasattr(namespace, 'location'): # pylint: disable=line-too-long # store location in namespace.location for use in custom method. get_default_location_from_resource_group(cmd, namespace) # validate tags. validate_tags(namespace)
def _final_validator_impl(cmd, namespace): # do additional creation validation verb = cmd.name.rsplit(' ', 1)[1] if verb == 'create': password_validator(namespace) get_default_location_from_resource_group(cmd, namespace) validate_tags(namespace) for validator in validators: validator(namespace)
def validate_functionapp_asp_create(namespace): validate_tags(namespace) sku = _normalize_sku(namespace.sku) tier = get_sku_tier(sku) _validate_asp_sku(sku=sku, app_service_environment=None, zone_redundant=namespace.zone_redundant) if namespace.max_burst is not None: if tier.lower() != "elasticpremium": raise ArgumentUsageError( "--max-burst is only supported for Elastic Premium (EP) plans")
def _final_validator_impl(cmd, namespace): # do additional creation validation verbs = cmd.name.rsplit(' ', 2) if verbs[1] == 'server' and verbs[2] == 'create': password_validator(namespace) get_default_location_from_resource_group(cmd, namespace) validate_tags(namespace) for validator in validators: validator(namespace)
def process_vpn_connection_create_namespace(cmd, namespace): from msrestazure.tools import is_valid_resource_id, resource_id get_default_location_from_resource_group(cmd, namespace) validate_tags(namespace) args = [ a for a in [ namespace.express_route_circuit2, namespace.local_gateway2, namespace.vnet_gateway2 ] if a ] if len(args) != 1: raise ValueError( 'usage error: --vnet-gateway2 NAME_OR_ID | --local-gateway2 NAME_OR_ID ' '| --express-route-circuit2 NAME_OR_ID') def _validate_name_or_id(value, resource_type): if not is_valid_resource_id(value): subscription = getattr(namespace, 'subscription', get_subscription_id(cmd.cli_ctx)) return resource_id(subscription=subscription, resource_group=namespace.resource_group_name, namespace='Microsoft.Network', type=resource_type, name=value) return value if (namespace.local_gateway2 or namespace.vnet_gateway2) and not namespace.shared_key: raise CLIError( '--shared-key is required for VNET-to-VNET or Site-to-Site connections.' ) if namespace.express_route_circuit2 and namespace.shared_key: raise CLIError( '--shared-key cannot be used with an ExpressRoute connection.') namespace.vnet_gateway1 = \ _validate_name_or_id(namespace.vnet_gateway1, 'virtualNetworkGateways') if namespace.express_route_circuit2: namespace.express_route_circuit2 = \ _validate_name_or_id( namespace.express_route_circuit2, 'expressRouteCircuits') namespace.connection_type = 'ExpressRoute' elif namespace.local_gateway2: namespace.local_gateway2 = \ _validate_name_or_id(namespace.local_gateway2, 'localNetworkGateways') namespace.connection_type = 'IPSec' elif namespace.vnet_gateway2: namespace.vnet_gateway2 = \ _validate_name_or_id(namespace.vnet_gateway2, 'virtualNetworkGateways') namespace.connection_type = 'Vnet2Vnet'
def _final_validator_impl(cmd, namespace): # do additional creation validation verbs = cmd.name.rsplit(' ', 2) if verbs[1] == 'server' and verbs[2] == 'create': storage_validator(namespace) password_validator(namespace) get_default_location_from_resource_group(cmd, namespace) validate_tags(namespace) for validator in validators: validator(namespace)
def process_nic_create_namespace(cmd, namespace): get_default_location_from_resource_group(cmd, namespace) validate_tags(namespace) validate_address_pool_id_list(cmd, namespace) validate_inbound_nat_rule_id_list(cmd, namespace) get_asg_validator(cmd.loader, 'application_security_groups')(cmd, namespace) # process folded parameters get_subnet_validator(has_type_field=False)(cmd, namespace) get_public_ip_validator(has_type_field=False, allow_none=True, default_none=True)(cmd, namespace) get_nsg_validator(has_type_field=False, allow_none=True, default_none=True)(cmd, namespace)
def _final_validator_impl(cmd, namespace): # do additional creation validation verb = cmd.name.rsplit(' ', 1)[1] if verb == 'create': storage_validator(namespace) password_validator(namespace) get_default_location_from_resource_group(cmd, namespace) validate_tags(namespace) for validator in validators: validator(namespace)
def process_secret_set_namespace(namespace): validate_tags(namespace) content = namespace.value file_path = namespace.file_path encoding = namespace.encoding tags = namespace.tags or {} use_error = CLIError( "incorrect usage: [Required] --value VALUE | --file PATH") if (content and file_path) or (not content and not file_path): raise use_error encoding = encoding or 'utf-8' if file_path: if encoding in secret_text_encoding_values: with open(file_path, 'r') as f: try: content = f.read() except UnicodeDecodeError: raise CLIError( "Unable to decode file '{}' with '{}' encoding.". format(file_path, encoding)) encoded_str = content encoded = content.encode(encoding) decoded = encoded.decode(encoding) elif encoding == 'base64': with open(file_path, 'rb') as f: content = f.read() try: encoded = base64.encodebytes(content) except AttributeError: encoded = base64.encodestring(content) # pylint: disable=deprecated-method encoded_str = encoded.decode('utf-8') decoded = base64.b64decode(encoded_str) elif encoding == 'hex': with open(file_path, 'rb') as f: content = f.read() encoded = binascii.b2a_hex(content) encoded_str = encoded.decode('utf-8') decoded = binascii.unhexlify(encoded_str) if content != decoded: raise CLIError("invalid encoding '{}'".format(encoding)) content = encoded_str tags.update({'file-encoding': encoding}) namespace.tags = tags namespace.value = content
def process_secret_set_namespace(namespace): validate_tags(namespace) content = namespace.value file_path = namespace.file_path encoding = namespace.encoding tags = namespace.tags or {} use_error = CLIError("incorrect usage: [Required] --value VALUE | --file PATH") if (content and file_path) or (not content and not file_path): raise use_error encoding = encoding or 'utf-8' if file_path: if encoding in secret_text_encoding_values: with open(file_path, 'r') as f: try: content = f.read() except UnicodeDecodeError: raise CLIError("Unable to decode file '{}' with '{}' encoding.".format( file_path, encoding)) encoded_str = content encoded = content.encode(encoding) decoded = encoded.decode(encoding) elif encoding == 'base64': with open(file_path, 'rb') as f: content = f.read() try: encoded = base64.encodebytes(content) except AttributeError: encoded = base64.encodestring(content) # pylint: disable=deprecated-method encoded_str = encoded.decode('utf-8') decoded = base64.b64decode(encoded_str) elif encoding == 'hex': with open(file_path, 'rb') as f: content = f.read() encoded = binascii.b2a_hex(content) encoded_str = encoded.decode('utf-8') decoded = binascii.unhexlify(encoded_str) if content != decoded: raise CLIError("invalid encoding '{}'".format(encoding)) content = encoded_str tags.update({'file-encoding': encoding}) namespace.tags = tags namespace.value = content
def process_route_table_create_namespace(namespace): from azure.mgmt.network.models import RouteTable namespace.parameters = RouteTable() if namespace.location: namespace.parameters.location = namespace.location else: resource_group = resource_client_factory().resource_groups.get( namespace.resource_group_name) namespace.parameters.location = resource_group.location # pylint: disable=no-member validate_tags(namespace) if hasattr(namespace, 'tags'): namespace.parameters.tags = namespace.tags
def process_vnet_create_namespace(cmd, namespace): get_default_location_from_resource_group(cmd, namespace) validate_tags(namespace) if namespace.subnet_prefix and not namespace.subnet_name: raise ValueError('incorrect usage: --subnet-name NAME [--subnet-prefix PREFIX]') if namespace.subnet_name and not namespace.subnet_prefix: if isinstance(namespace.vnet_prefixes, str): namespace.vnet_prefixes = [namespace.vnet_prefixes] prefix_components = namespace.vnet_prefixes[0].split('/', 1) address = prefix_components[0] bit_mask = int(prefix_components[1]) subnet_mask = 24 if bit_mask < 24 else bit_mask namespace.subnet_prefix = '{}/{}'.format(address, subnet_mask)
def process_vnet_create_namespace(cmd, namespace): get_default_location_from_resource_group(cmd, namespace) validate_ddos_name_or_id(cmd, namespace) validate_tags(namespace) if namespace.subnet_prefix and not namespace.subnet_name: raise ValueError('incorrect usage: --subnet-name NAME [--subnet-prefix PREFIX]') if namespace.subnet_name and not namespace.subnet_prefix: if isinstance(namespace.vnet_prefixes, str): namespace.vnet_prefixes = [namespace.vnet_prefixes] prefix_components = namespace.vnet_prefixes[0].split('/', 1) address = prefix_components[0] bit_mask = int(prefix_components[1]) subnet_mask = 24 if bit_mask < 24 else bit_mask namespace.subnet_prefix = '{}/{}'.format(address, subnet_mask)
def _final_valiator_impl(namespace): # do additional creation validation if namespace.subcommand == 'create': storage_validator(namespace) password_validator(namespace) get_default_location_from_resource_group(namespace) validate_tags(namespace) for validator in validators: validator(namespace) if namespace.sku.tier or namespace.sku.capacity: namespace.sku.name = 'SkuName' else: namespace.parameters.sku = None
def process_vpn_connection_create_namespace(cmd, namespace): from msrestazure.tools import is_valid_resource_id, resource_id get_default_location_from_resource_group(cmd, namespace) validate_tags(namespace) args = [a for a in [namespace.express_route_circuit2, namespace.local_gateway2, namespace.vnet_gateway2] if a] if len(args) != 1: raise ValueError('usage error: --vnet-gateway2 NAME_OR_ID | --local-gateway2 NAME_OR_ID ' '| --express-route-circuit2 NAME_OR_ID') def _validate_name_or_id(value, resource_type): if not is_valid_resource_id(value): subscription = getattr(namespace, 'subscription', get_subscription_id(cmd.cli_ctx)) return resource_id( subscription=subscription, resource_group=namespace.resource_group_name, namespace='Microsoft.Network', type=resource_type, name=value) return value if (namespace.local_gateway2 or namespace.vnet_gateway2) and not namespace.shared_key: raise CLIError('--shared-key is required for VNET-to-VNET or Site-to-Site connections.') if namespace.express_route_circuit2 and namespace.shared_key: raise CLIError('--shared-key cannot be used with an ExpressRoute connection.') namespace.vnet_gateway1 = \ _validate_name_or_id(namespace.vnet_gateway1, 'virtualNetworkGateways') if namespace.express_route_circuit2: namespace.express_route_circuit2 = \ _validate_name_or_id( namespace.express_route_circuit2, 'expressRouteCircuits') namespace.connection_type = 'ExpressRoute' elif namespace.local_gateway2: namespace.local_gateway2 = \ _validate_name_or_id(namespace.local_gateway2, 'localNetworkGateways') namespace.connection_type = 'IPSec' elif namespace.vnet_gateway2: namespace.vnet_gateway2 = \ _validate_name_or_id(namespace.vnet_gateway2, 'virtualNetworkGateways') namespace.connection_type = 'Vnet2Vnet'
def process_vnet_gateway_create_namespace(cmd, namespace): ns = namespace get_default_location_from_resource_group(cmd, ns) validate_tags(ns) get_virtual_network_validator()(cmd, ns) get_public_ip_validator()(cmd, ns) public_ip_count = len(ns.public_ip_address or []) if public_ip_count > 2: raise CLIError('Specify a single public IP to create an active-standby gateway or two ' 'public IPs to create an active-active gateway.') enable_bgp = any([ns.asn, ns.bgp_peering_address, ns.peer_weight]) if enable_bgp and not ns.asn: raise ValueError( 'incorrect usage: --asn ASN [--peer-weight WEIGHT --bgp-peering-address IP ]')
def _final_validator_impl(cmd, namespace): # do additional creation validation verb = cmd.name.rsplit(' ', 1)[1] if verb == 'create': storage_validator(namespace) password_validator(namespace) get_default_location_from_resource_group(cmd, namespace) validate_tags(namespace) for validator in validators: validator(namespace) if namespace.sku.tier or namespace.sku.capacity: namespace.sku.name = 'SkuName' else: namespace.parameters.sku = None
def process_ag_create_namespace(cmd, namespace): get_default_location_from_resource_group(cmd, namespace) get_servers_validator(camel_case=True)(namespace) # process folded parameters if namespace.subnet or namespace.virtual_network_name: get_subnet_validator(has_type_field=True, allow_new=True)(cmd, namespace) validate_address_prefixes(namespace) if namespace.public_ip_address: get_public_ip_validator( has_type_field=True, allow_none=True, allow_new=True, default_none=True)(cmd, namespace) validate_cert(namespace) validate_tags(namespace)
def test_tags_invalid(self): the_input = argparse.Namespace() the_input.tags = [] validate_tags(the_input) self.assertEqual(the_input.tags, {})
def test_tags_valid(self): the_input = argparse.Namespace() the_input.tags = ['a=b', 'c=d', 'e'] validate_tags(the_input) expected = {'a': 'b', 'c': 'd', 'e': ''} self.assertEqual(the_input.tags, expected)
def process_route_table_create_namespace(namespace): from azure.mgmt.network.models import RouteTable get_default_location_from_resource_group(namespace) validate_tags(namespace) namespace.parameters = RouteTable(location=namespace.location, tags=namespace.tags)
def process_route_table_create_namespace(namespace): RouteTable = get_sdk(ResourceType.MGMT_NETWORK, 'RouteTable', mod='models') get_default_location_from_resource_group(namespace) validate_tags(namespace) namespace.parameters = RouteTable(location=namespace.location, tags=namespace.tags)
def process_image_template_create_namespace(cmd, namespace): # pylint: disable=too-many-locals, too-many-branches, too-many-statements from azure.cli.core.commands.parameters import get_subscription_locations source = None scripts = [] # default location to RG location. if not namespace.location: get_default_location_from_resource_group(cmd, namespace) # validate tags. validate_tags(namespace) # Validate and parse scripts if namespace.scripts: for ns_script in namespace.scripts: scripts.append(_parse_script(ns_script)) # Validate and parse destination and locations destinations = [] subscription_locations = get_subscription_locations(cmd.cli_ctx) location_names = [l.name for l in subscription_locations] location_display_names = [l.display_name for l in subscription_locations] if namespace.managed_image_destinations: for dest in namespace.managed_image_destinations: rid, location = _parse_image_destination(cmd, namespace.resource_group_name, dest, is_shared_image=False) location = _validate_location(location, location_names, location_display_names) destinations.append((_DestType.MANAGED_IMAGE, rid, location)) if namespace.shared_image_destinations: for dest in namespace.shared_image_destinations: rid, locations = _parse_image_destination(cmd, namespace.resource_group_name, dest, is_shared_image=True) locations = [_validate_location(l, location_names, location_display_names) for l in locations] destinations.append((_DestType.SHARED_IMAGE_GALLERY, rid, locations)) # Validate and parse source image # 1 - check if source is a URN. A urn e.g "Canonical:UbuntuServer:18.04-LTS:latest" urn_match = re.match('([^:]*):([^:]*):([^:]*):([^:]*)', namespace.source) if urn_match: # if platform image urn source = { 'publisher': urn_match.group(1), 'offer': urn_match.group(2), 'sku': urn_match.group(3), 'version': urn_match.group(4), 'type': _SourceType.PLATFORM_IMAGE } likely_linux = bool("windows" not in source["offer"].lower() and "windows" not in source["sku"].lower()) logger.info("%s looks like a platform image URN", namespace.source) # 2 - check if a fully-qualified ID (assumes it is an image ID) elif is_valid_resource_id(namespace.source): parsed = parse_resource_id(namespace.source) image_type = parsed.get('type') image_resource_type = parsed.get('type') if not image_type: pass elif image_type.lower() == 'images': source = { 'image_id': namespace.source, 'type': _SourceType.MANAGED_IMAGE } logger.info("%s looks like a managed image id.", namespace.source) elif image_type == "galleries" and image_resource_type: source = { 'image_version_id': namespace.source, 'type': _SourceType.SIG_VERSION } logger.info("%s looks like a shared image version id.", namespace.source) # 3 - check if source is a Redhat iso uri. If so a checksum must be provided. elif urlparse(namespace.source).scheme and "://" in namespace.source and ".iso" in namespace.source.lower(): if not namespace.checksum: raise CLIError("Must provide a checksum for source uri: {}".format(namespace.source)) source = { 'source_uri': namespace.source, 'sha256_checksum': namespace.checksum, 'type': _SourceType.ISO_URI } likely_linux = True logger.info("%s looks like a RedHat iso uri.", namespace.source) # 4 - check if source is a urn alias from the vmImageAliasDoc endpoint. See "az cloud show" if not source: from azure.cli.command_modules.vm._actions import load_images_from_aliases_doc images = load_images_from_aliases_doc(cmd.cli_ctx) matched = next((x for x in images if x['urnAlias'].lower() == namespace.source.lower()), None) if matched: source = { 'publisher': matched['publisher'], 'offer': matched['offer'], 'sku': matched['sku'], 'version': matched['version'], 'type': _SourceType.PLATFORM_IMAGE } if "windows" not in source["offer"].lower() and "windows" not in source["sku"].lower(): likely_linux = True logger.info("%s looks like a platform image alias.", namespace.source) # 5 - check if source is an existing managed disk image resource if not source: compute_client = _compute_client_factory(cmd.cli_ctx) try: image_name = namespace.source compute_client.images.get(namespace.resource_group_name, namespace.source) namespace.source = _get_resource_id(cmd.cli_ctx, namespace.source, namespace.resource_group_name, 'images', 'Microsoft.Compute') source = { 'image_id': namespace.source, 'type': _SourceType.MANAGED_IMAGE } logger.info("%s, looks like a managed image name. Using resource ID: %s", image_name, namespace.source) # pylint: disable=line-too-long except CloudError: pass if not source: err = 'Invalid image "{}". Use a valid image URN, managed image name or ID, ISO URI, ' \ 'or pick a platform image alias from {}.\nSee vm create -h for more information on specifying an image.'\ .format(namespace.source, ", ".join([x['urnAlias'] for x in images])) raise CLIError(err) for script in scripts: if script["type"] is None: try: script["type"] = ScriptType.SHELL if likely_linux else ScriptType.POWERSHELL logger.info("For script %s, likely linux is %s.", script["script"], likely_linux) except NameError: raise CLIError("Unable to infer the type of script {}.".format(script["script"])) namespace.source_dict = source namespace.scripts_list = scripts namespace.destinations_lists = destinations
def process_public_ip_create_namespace(cmd, namespace): get_default_location_from_resource_group(cmd, namespace) validate_tags(namespace)
def process_route_table_create_namespace(namespace): from azure.mgmt.network.models import RouteTable validate_location(namespace) validate_tags(namespace) namespace.parameters = RouteTable(location=namespace.location, tags=namespace.tags)
def process_route_table_create_namespace(cmd, namespace): get_default_location_from_resource_group(cmd, namespace) validate_tags(namespace)
def process_msi_namespace(cmd, namespace): get_default_location_from_resource_group(cmd, namespace) validate_tags(namespace)