def _validate_name_or_id(cli_ctx, resource_group_name, property_value, property_type, parent_value, parent_type): from azure.cli.core.commands.client_factory import get_subscription_id from azure.mgmt.core.tools import parse_resource_id, is_valid_resource_id has_parent = parent_type is not None if is_valid_resource_id(property_value): resource_id_parts = parse_resource_id(property_value) value_supplied_was_id = True elif has_parent: resource_id_parts = dict(name=parent_value, resource_group=resource_group_name, namespace=parent_type.split('/')[0], type=parent_type.split('/')[1], subscription=get_subscription_id(cli_ctx), child_name_1=property_value, child_type_1=property_type) value_supplied_was_id = False else: resource_id_parts = dict(name=property_value, resource_group=resource_group_name, namespace=property_type.split('/')[0], type=property_type.split('/')[1], subscription=get_subscription_id(cli_ctx)) value_supplied_was_id = False return (resource_id_parts, value_supplied_was_id)
def _parse_item_resource_id(addon, key, secondary): resource_id = (addon.get(key, None) or addon.get(secondary, {})).get('resourceId', None) if not resource_id: return None resource_dict = parse_resource_id(resource_id) return resource_dict.get('resource_name', '')
def internal_validate_lock_parameters(namespace, resource_group, resource_provider_namespace, parent_resource_path, resource_type, resource_name): if resource_group is None: if resource_name is not None: from msrestazure.tools import parse_resource_id, is_valid_resource_id if not is_valid_resource_id(resource_name): raise CLIError( '--resource is not a valid resource ID. ' '--resource as a resource name is ignored if --resource-group is not given.' ) # resource-name is an ID, populate namespace id_dict = parse_resource_id(resource_name) for id_part in [ 'resource_name', 'resource_type', 'resource_group' ]: setattr(namespace, id_part, id_dict.get(id_part)) setattr(namespace, 'resource_provider_namespace', id_dict.get('resource_namespace')) setattr(namespace, 'parent_resource_path', id_dict.get('resource_parent').strip('/')) if resource_type is not None: raise CLIError( '--resource-type is ignored if --resource-group is not given.') if resource_provider_namespace is not None: raise CLIError( '--namespace is ignored if --resource-group is not given.') if parent_resource_path is not None: raise CLIError( '--parent is ignored if --resource-group is not given.') return if resource_name is None: if resource_type is not None: raise CLIError( '--resource-type is ignored if --resource is not given.') if resource_provider_namespace is not None: raise CLIError( '--namespace is ignored if --resource is not given.') if parent_resource_path is not None: raise CLIError('--parent is ignored if --resource is not given.') return if not resource_type: raise CLIError( '--resource-type is required if the name, --resource, is present') parts = resource_type.split('/') if resource_provider_namespace is None: if len(parts) == 1: raise CLIError( 'A resource namespace is required if the name, --resource, is present.' 'Expected <namespace>/<type> or --namespace=<namespace>') elif len(parts) != 1: raise CLIError( 'Resource namespace specified in both --resource-type and --namespace' )
def parse_one_scope_with_action(scope, operation_on_scope): result = parse_resource_id(scope) if 'namespace' in result and 'resource_type' in result: operation_on_scope(result['namespace'], result['resource_type'], 'resource') elif 'resource_group' in result: # It's a resource group. operation_on_scope('', '', 'resource_group') elif 'subscription' in result: # It's a subscription. operation_on_scope('', '', 'subscription') else: raise CLIError('Scope must be a valid resource id.')
def validate_vnet(cmd, namespace): if not namespace.vnet and not namespace.app_subnet and \ not namespace.service_runtime_subnet and not namespace.reserved_cidr_range: return validate_vnet_required_parameters(namespace) vnet_id = '' if namespace.vnet: vnet_id = namespace.vnet # format the app_subnet and service_runtime_subnet if not is_valid_resource_id(vnet_id): if vnet_id.count('/') > 0: raise InvalidArgumentValueError('--vnet {0} is not a valid name or resource ID'.format(vnet_id)) vnet_id = resource_id( subscription=get_subscription_id(cmd.cli_ctx), resource_group=namespace.resource_group, namespace='Microsoft.Network', type='virtualNetworks', name=vnet_id ) else: vnet = parse_resource_id(vnet_id) if vnet['namespace'].lower() != 'microsoft.network' or vnet['type'].lower() != 'virtualnetworks': raise InvalidArgumentValueError('--vnet {0} is not a valid VirtualNetwork resource ID'.format(vnet_id)) namespace.app_subnet = _construct_subnet_id(vnet_id, namespace.app_subnet) namespace.service_runtime_subnet = _construct_subnet_id(vnet_id, namespace.service_runtime_subnet) else: app_vnet_id = _parse_vnet_id_from_subnet(namespace.app_subnet) service_runtime_vnet_id = _parse_vnet_id_from_subnet(namespace.service_runtime_subnet) if app_vnet_id.lower() != service_runtime_vnet_id.lower(): raise InvalidArgumentValueError('--app-subnet and --service-runtime-subnet should be in the same Virtual Networks.') vnet_id = app_vnet_id if namespace.app_subnet.lower() == namespace.service_runtime_subnet.lower(): raise InvalidArgumentValueError('--app-subnet and --service-runtime-subnet should not be the same.') vnet_obj = _get_vnet(cmd, vnet_id) instance_location = namespace.location if instance_location is None: instance_location = _get_rg_location(cmd.cli_ctx, namespace.resource_group) else: instance_location_slice = instance_location.split(" ") instance_location = "".join([piece.lower() for piece in instance_location_slice]) if vnet_obj.location.lower() != instance_location.lower(): raise InvalidArgumentValueError('--vnet and Azure Spring Apps instance should be in the same location.') for subnet in vnet_obj.subnets: _validate_subnet(namespace, subnet) _validate_route_table(namespace, vnet_obj) if namespace.reserved_cidr_range: _validate_cidr_range(namespace) else: namespace.reserved_cidr_range = _set_default_cidr_range(vnet_obj.address_space.address_prefixes) if \ vnet_obj and vnet_obj.address_space and vnet_obj.address_space.address_prefixes \ else '10.234.0.0/16,10.244.0.0/16,172.17.0.1/16'
def get_resource_name_and_rg(resource_group_name, name_or_id): if is_valid_resource_id(name_or_id): id_parts = parse_resource_id(name_or_id) name = id_parts.get('name') resource_group = id_parts.get('resource_group') if name is None or resource_group is None: raise InvalidArgumentValueError( "Please provide a valid resource id.") else: name = name_or_id resource_group = resource_group_name return name, resource_group
def _parse_vnet_id_from_subnet(subnet_id): if not is_valid_resource_id(subnet_id): raise InvalidArgumentValueError( '{0} is not a valid subnet resource ID'.format(subnet_id)) subnet = parse_resource_id(subnet_id) if subnet['namespace'].lower() != 'microsoft.network' or \ subnet['type'].lower() != 'virtualnetworks' or \ 'resource_type' not in subnet or subnet['resource_type'].lower() != 'subnets': raise InvalidArgumentValueError( '{0} is not a valid subnet resource ID'.format(subnet_id)) return resource_id(subscription=subnet['subscription'], resource_group=subnet['resource_group'], namespace=subnet['namespace'], type=subnet['type'], name=subnet['name'])
def parse_one_scope_with_action(scope, operation_on_scope): result = parse_resource_id(scope) if 'namespace' in result and 'resource_type' in result: resource_types = [result['type']] child_idx = 1 while 'child_type_{}'.format(child_idx) in result: resource_types.append(result['child_type_{}'.format(child_idx)]) child_idx += 1 operation_on_scope(result['namespace'], '/'.join(resource_types), 'resource') elif 'resource_group' in result: # It's a resource group. operation_on_scope('', '', 'resource_group') elif 'subscription' in result: # It's a subscription. operation_on_scope('', '', 'subscription') else: raise InvalidArgumentValueError('Scope must be a valid resource id.')
def _validate_deployment_name_with_template_specs(namespace): # If missing,try come out with a name associated with the template name if namespace.deployment_name is None: template_filename = None if namespace.template_file and os.path.isfile(namespace.template_file): template_filename = namespace.template_file if namespace.template_uri and urlparse(namespace.template_uri).scheme: template_filename = urlsplit(namespace.template_uri).path if namespace.template_spec: from azure.mgmt.core.tools import parse_resource_id, is_valid_resource_id namespace.template_spec = namespace.template_spec.strip("\"") if not is_valid_resource_id(namespace.template_spec): raise CLIError('--template-spec is not a valid resource ID.') if namespace.template_spec.__contains__("versions") is False: raise CLIError('Please enter a valid template spec version ID.') template_filename = parse_resource_id(namespace.template_spec).get('resource_name') if template_filename: template_filename = os.path.basename(template_filename) namespace.deployment_name = os.path.splitext(template_filename)[0] else: namespace.deployment_name = 'deployment1'
def _get_vnet(cmd, vnet_id): vnet = parse_resource_id(vnet_id) network_client = _get_network_client(cmd.cli_ctx, subscription_id=vnet['subscription']) return network_client.virtual_networks.get(vnet['resource_group'], vnet['resource_name'])
def get_arm_resource_by_id(cli_ctx, arm_id, api_version=None): from msrestazure.tools import parse_resource_id, is_valid_resource_id if not is_valid_resource_id(arm_id): raise CLIError("'{}' is not a valid ID.".format(arm_id)) client = get_mgmt_service_client(cli_ctx, ResourceType.MGMT_RESOURCE_RESOURCES) if not api_version: parts = parse_resource_id(arm_id) # to retrieve the provider, we need to know the namespace namespaces = {k: v for k, v in parts.items() if 'namespace' in k} # every ARM ID has at least one namespace, so start with that namespace = namespaces.pop('namespace') namespaces.pop('resource_namespace') # find the most specific child namespace (if any) and use that value instead highest_child = 0 for k, v in namespaces.items(): child_number = int(k.split('_')[2]) if child_number > highest_child: namespace = v highest_child = child_number # retrieve provider info for the namespace provider = client.providers.get(namespace) # assemble the resource type key used by the provider list operation. type1/type2/type3/... resource_type_str = '' if not highest_child: resource_type_str = parts['resource_type'] else: types = { int(k.split('_')[2]): v for k, v in parts.items() if k.startswith('child_type') } for k in sorted(types.keys()): if k < highest_child: continue resource_type_str = '{}{}/'.format( resource_type_str, parts['child_type_{}'.format(k)]) resource_type_str = resource_type_str.rstrip('/') api_version = None rt = next((t for t in provider.resource_types if t.resource_type.lower() == resource_type_str.lower()), None) if not rt: from azure.cli.core.parser import IncorrectUsageError raise IncorrectUsageError( 'Resource type {} not found.'.format(resource_type_str)) try: # Use the most recent non-preview API version unless there is only a # single API version. API versions are returned by the service in a sorted list. api_version = next( (x for x in rt.api_versions if not x.endswith('preview')), rt.api_versions[0]) except AttributeError: err = "No API versions found for resource type '{}'." raise CLIError(err.format(resource_type_str)) return client.resources.get_by_id(arm_id, api_version)
def parse_ids_arguments(_, command, args): namespace = args cmd = namespace._cmd # pylint: disable=protected-access # some commands have custom IDs and parsing. This will not work for that. if not ids_metadata.get(command, None): return ids = getattr(namespace, 'ids', getattr(namespace, '_ids', None)) required_args = [ cmd.arguments[x] for x in ids_metadata[command]['required'] ] optional_args = [ cmd.arguments[x] for x in ids_metadata[command]['optional'] ] combined_args = required_args + optional_args if not ids: # ensure the required parameters are provided if --ids is not errors = [ arg for arg in required_args if getattr(namespace, arg.name, None) is None ] if errors: missing_required = ' '.join( (arg.options_list[0] for arg in errors)) raise CLIError('({} | {}) are required'.format( missing_required, '--ids')) return # show warning if names are used in conjunction with --ids other_values = { arg.name: { 'arg': arg, 'value': getattr(namespace, arg.name, None) } for arg in combined_args } for _, data in other_values.items(): if data['value'] and not getattr(data['value'], 'is_default', None): logger.warning( "option '%s' will be ignored due to use of '--ids'.", data['arg'].type.settings['options_list'][0]) # create the empty lists, overwriting any values that may already be there for arg in combined_args: setattr(namespace, arg.name, IterateValue()) def assemble_json(ids): lcount = 0 lind = None for i, line in enumerate(ids): if line == '[': if lcount == 0: lind = i lcount += 1 elif line == ']': lcount -= 1 # final closed set of matching brackets if lcount == 0: left = lind right = i + 1 l_comp = ids[:left] m_comp = [''.join(ids[left:right])] r_comp = ids[right:] ids = l_comp + m_comp + r_comp return assemble_json(ids) # base case--no more merging required return ids # reassemble JSON strings from bash ids = assemble_json(ids) # expand the IDs into the relevant fields full_id_list = [] for val in ids: try: # support piping values from JSON. Does not require use of --query json_vals = json.loads(val) if not isinstance(json_vals, list): json_vals = [json_vals] for json_val in json_vals: if isinstance(json_val, dict) and 'id' in json_val: full_id_list += [json_val['id']] except ValueError: # supports piping of --ids to the command when using TSV. Requires use of --query full_id_list = full_id_list + val.splitlines() if full_id_list: setattr(namespace, '_ids', full_id_list) from azure.mgmt.core.tools import parse_resource_id, is_valid_resource_id for val in full_id_list: if not is_valid_resource_id(val): raise CLIError('invalid resource ID: {}'.format(val)) # place the ID parts into the correct property lists parts = parse_resource_id(val) for arg in combined_args: id_part = arg.type.settings.get('id_part') id_value = parts.get(id_part, None) if id_value is None: argument_name = arg.type.settings.get('options_list')[0] raise CLIError( "Argument {arg_name} cannot be derived from ID {id}. " "Please provide a complete resource ID " "containing all information of '{group_name}' " "arguments. ".format(id=val, arg_name=argument_name, group_name=arg.arg_group)) getattr(namespace, arg.name).append(id_value) # support deprecating --ids deprecate_info = cmd.arguments['ids'].type.settings.get( 'deprecate_info') if deprecate_info: if not hasattr(namespace, '_argument_deprecations'): setattr(namespace, '_argument_deprecations', [deprecate_info]) else: namespace._argument_deprecations.append(deprecate_info) # pylint: disable=protected-access
def test_resource_parse(self): """ Tests resource id parsing, reforming, and validation. """ tests = [{ 'resource_id': '/subscriptions/fakesub/resourcegroups/testgroup/providers' '/Microsoft.Storage/storageAccounts/foo/providers' '/Microsoft.Authorization/locks/bar', 'expected': { 'name': 'foo', 'type': 'storageAccounts', 'namespace': 'Microsoft.Storage', 'child_name_1': 'bar', 'child_namespace_1': 'Microsoft.Authorization', 'child_type_1': 'locks', 'child_parent_1': 'storageAccounts/foo/providers/Microsoft.Authorization/', 'resource_group': 'testgroup', 'subscription': 'fakesub', } }, { 'resource_id': '/subscriptions/fakesub/resourcegroups/testgroup/providers' '/Microsoft.Storage/storageAccounts/foo' '/locks/bar', 'expected': { 'name': 'foo', 'type': 'storageAccounts', 'namespace': 'Microsoft.Storage', 'child_name_1': 'bar', 'child_type_1': 'locks', 'child_parent_1': 'storageAccounts/foo/', 'resource_group': 'testgroup', 'subscription': 'fakesub', } }, { 'resource_id': '/subscriptions/fakesub/resourcegroups/testgroup/providers' '/Microsoft.Storage/storageAccounts/foo/providers' '/Microsoft.Authorization/locks/bar/providers/Microsoft.Network/' 'nets/gc', 'expected': { 'name': 'foo', 'type': 'storageAccounts', 'namespace': 'Microsoft.Storage', 'child_name_1': 'bar', 'child_namespace_1': 'Microsoft.Authorization', 'child_type_1': 'locks', 'child_parent_1': 'storageAccounts/foo/providers/Microsoft.Authorization/', 'child_name_2': 'gc', 'child_namespace_2': 'Microsoft.Network', 'child_type_2': 'nets', 'child_parent_2': 'storageAccounts/foo/providers/Microsoft.Authorization/' 'locks/bar/providers/Microsoft.Network/', 'resource_group': 'testgroup', 'subscription': 'fakesub', } }, { 'resource_id': '/subscriptions/fakesub/resourcegroups/testgroup/providers' '/Microsoft.Storage/storageAccounts/foo' '/locks/bar/nets/gc', 'expected': { 'name': 'foo', 'type': 'storageAccounts', 'namespace': 'Microsoft.Storage', 'child_name_1': 'bar', 'child_type_1': 'locks', 'child_parent_1': 'storageAccounts/foo/', 'child_name_2': 'gc', 'child_type_2': 'nets', 'child_parent_2': 'storageAccounts/foo/locks/bar/', 'resource_group': 'testgroup', 'subscription': 'fakesub', } }, { 'resource_id': '/subscriptions/mySub/resourceGroups/myRg/providers/' 'Microsoft.Provider1/resourceType1/name1', 'expected': { 'subscription': 'mySub', 'resource_group': 'myRg', 'namespace': 'Microsoft.Provider1', 'type': 'resourceType1', 'name': 'name1', 'resource_parent': '', 'resource_namespace': 'Microsoft.Provider1', 'resource_type': 'resourceType1', 'resource_name': 'name1' } }, { 'resource_id': '/subscriptions/mySub/resourceGroups/myRg/providers/' 'Microsoft.Provider1/resourceType1/name1/resourceType2/name2', 'expected': { 'subscription': 'mySub', 'resource_group': 'myRg', 'namespace': 'Microsoft.Provider1', 'type': 'resourceType1', 'name': 'name1', 'child_namespace_1': None, 'child_type_1': 'resourceType2', 'child_name_1': 'name2', 'child_parent_1': 'resourceType1/name1/', 'resource_parent': 'resourceType1/name1/', 'resource_namespace': 'Microsoft.Provider1', 'resource_type': 'resourceType2', 'resource_name': 'name2' } }, { 'resource_id': '/subscriptions/00000/resourceGroups/myRg/providers/' 'Microsoft.RecoveryServices/vaults/vault_name/backupFabrics/' 'fabric_name/protectionContainers/container_name/' 'protectedItems/item_name/recoveryPoint/recovery_point_guid', 'expected': { 'subscription': '00000', 'resource_group': 'myRg', 'namespace': 'Microsoft.RecoveryServices', 'type': 'vaults', 'name': 'vault_name', 'child_type_1': 'backupFabrics', 'child_name_1': 'fabric_name', 'child_parent_1': 'vaults/vault_name/', 'child_type_2': 'protectionContainers', 'child_name_2': 'container_name', 'child_parent_2': 'vaults/vault_name/backupFabrics/fabric_name/', 'child_type_3': 'protectedItems', 'child_name_3': 'item_name', 'child_parent_3': 'vaults/vault_name/backupFabrics/fabric_name/' 'protectionContainers/container_name/', 'child_type_4': 'recoveryPoint', 'child_name_4': 'recovery_point_guid', 'child_parent_4': 'vaults/vault_name/backupFabrics/fabric_name/' 'protectionContainers/container_name/protectedItems/' 'item_name/', 'resource_parent': 'vaults/vault_name/backupFabrics/fabric_name/' 'protectionContainers/container_name/protectedItems/' 'item_name/', 'resource_namespace': 'Microsoft.RecoveryServices', 'resource_type': 'recoveryPoint', 'resource_name': 'recovery_point_guid' } }, { 'resource_id': '/subscriptions/mySub/resourceGroups/myRg/providers/' 'Microsoft.Provider1/resourceType1/name1/resourceType2/name2/' 'providers/Microsoft.Provider3/resourceType3/name3', 'expected': { 'subscription': 'mySub', 'resource_group': 'myRg', 'namespace': 'Microsoft.Provider1', 'type': 'resourceType1', 'name': 'name1', 'child_namespace_1': None, 'child_type_1': 'resourceType2', 'child_name_1': 'name2', 'child_parent_1': 'resourceType1/name1/', 'child_namespace_2': 'Microsoft.Provider3', 'child_type_2': 'resourceType3', 'child_name_2': 'name3', 'child_parent_2': 'resourceType1/name1/resourceType2/name2/' 'providers/Microsoft.Provider3/', 'resource_parent': 'resourceType1/name1/resourceType2/name2/' 'providers/Microsoft.Provider3/', 'resource_namespace': 'Microsoft.Provider1', 'resource_type': 'resourceType3', 'resource_name': 'name3' } }, { 'resource_id': '/subscriptions/fakesub/providers/Microsoft.Authorization' '/locks/foo', 'expected': { 'name': 'foo', 'type': 'locks', 'namespace': 'Microsoft.Authorization', 'subscription': 'fakesub', } }, { 'resource_id': '/Subscriptions/fakesub/providers/Microsoft.Authorization' '/locks/foo', 'expected': { 'name': 'foo', 'type': 'locks', 'namespace': 'Microsoft.Authorization', 'subscription': 'fakesub', } }, { 'resource_id': '/subscriptions/mySub/resourceGroups/myRg', 'expected': { 'subscription': 'mySub', 'resource_group': 'myRg' } }] for test in tests: self.assertTrue(is_valid_resource_id(test['resource_id'])) kwargs = parse_resource_id(test['resource_id']) for key in test['expected']: try: self.assertEqual(kwargs[key], test['expected'][key]) except KeyError: self.assertTrue(key not in kwargs and test['expected'][key] is None) invalid_ids = [ '/subscriptions/fakesub/resourceGroups/myRg/type1/name1', '/subscriptions/fakesub/resourceGroups/myRg/providers/Microsoft.Provider/foo', '/subscriptions/fakesub/resourceGroups/myRg/providers/namespace/type/name/type1' ] for invalid_id in invalid_ids: self.assertFalse(is_valid_resource_id(invalid_id)) tests = [{ 'resource_id': '/subscriptions/fakesub/resourcegroups/testgroup/providers' '/Microsoft.Storage/storageAccounts/foo/providers' '/Microsoft.Authorization/locks/bar', 'id_args': { 'name': 'foo', 'type': 'storageAccounts', 'namespace': 'Microsoft.Storage', 'child_name_1': 'bar', 'child_namespace_1': 'Microsoft.Authorization', 'child_type_1': 'locks', 'resource_group': 'testgroup', 'subscription': 'fakesub', } }, { 'resource_id': '/subscriptions/fakesub/resourcegroups/testgroup/providers' '/Microsoft.Storage/storageAccounts/foo' '/locks/bar', 'id_args': { 'name': 'foo', 'type': 'storageAccounts', 'namespace': 'Microsoft.Storage', 'child_name_1': 'bar', 'child_type_1': 'locks', 'resource_group': 'testgroup', 'subscription': 'fakesub', } }, { 'resource_id': '/subscriptions/mySub/resourceGroups/myRg/providers/' 'Microsoft.Provider1/resourceType1/name1/resourceType2/name2/' 'providers/Microsoft.Provider3/resourceType3/name3', 'id_args': { 'subscription': 'mySub', 'resource_group': 'myRg', 'namespace': 'Microsoft.Provider1', 'type': 'resourceType1', 'name': 'name1', 'child_type_1': 'resourceType2', 'child_name_1': 'name2', 'child_namespace_2': 'Microsoft.Provider3', 'child_type_2': 'resourceType3', 'child_name_2': 'name3' } }, { 'resource_id': '/subscriptions/mySub/resourceGroups/myRg/' 'providers/Microsoft.Provider1', 'id_args': { 'subscription': 'mySub', 'resource_group': 'myRg', 'namespace': 'Microsoft.Provider1' } }, { 'resource_id': '/subscriptions/mySub/resourceGroups/myRg', 'id_args': { 'subscription': 'mySub', 'resource_group': 'myRg' } }, { 'resource_id': '/subscriptions/mySub/resourceGroups/myRg/' 'providers/Microsoft.Provider1/resourceType1/name1/resourceType2/' 'name2/providers/Microsoft.Provider3', 'id_args': { 'subscription': 'mySub', 'resource_group': 'myRg', 'namespace': 'Microsoft.Provider1', 'type': 'resourceType1', 'name': 'name1', 'child_type_1': 'resourceType2', 'child_name_1': 'name2', 'child_namespace_2': 'Microsoft.Provider3' } }, { 'resource_id': '/subscriptions/mySub/resourceGroups/myRg/' 'providers/Microsoft.Provider1/resourceType1/name1', 'id_args': { 'subscription': 'mySub', 'resource_group': 'myRg', 'namespace': 'Microsoft.Provider1', 'type': 'resourceType1', 'name': 'name1', 'child_type_1': None, 'child_name_1': 'name2', 'child_namespace_2': 'Microsoft.Provider3' } }, { 'resource_id': '/subscriptions/mySub/resourceGroups/myRg', 'id_args': { 'subscription': 'mySub', 'resource_group': 'myRg' } }] for test in tests: rsrc_id = resource_id(**test['id_args']) self.assertEqual(rsrc_id.lower(), test['resource_id'].lower())
def validate_dest_account(namespace): if is_valid_resource_id(namespace.dest_account): parsed_storage = parse_resource_id(namespace.dest_account) storage_name = parsed_storage['resource_name'] namespace.dest_account = storage_name
def validate_app_service(namespace): if namespace.app_service and is_valid_resource_id(namespace.app_service): namespace.app_service = parse_resource_id( namespace.app_service)['name']