def _install_or_update(component_name, version, link, private, upgrade=False): if not component_name: raise IncorrectUsageError('Specify a component name.') found = bool([dist for dist in pip.get_installed_distributions(local_only=True) if dist.key == COMPONENT_PREFIX + component_name]) if found and not upgrade: raise CLIError("Component already installed.") else: version_no = '==' + version if version else '' options = ['--quiet', '--isolated', '--disable-pip-version-check'] if upgrade: options.append('--upgrade') pkg_index_options = [] if link: pkg_index_options += ['--find-links', link] if private: if not PRIVATE_PYPI_URL: raise CLIError('{} environment variable not set.' .format(PRIVATE_PYPI_URL_ENV_NAME)) if not PRIVATE_PYPI_HOST: raise CLIError('{} environment variable not set.' .format(PRIVATE_PYPI_HOST_ENV_NAME)) pkg_index_options += ['--extra-index-url', PRIVATE_PYPI_URL, '--trusted-host', PRIVATE_PYPI_HOST] pip.main(['install'] + options + [COMPONENT_PREFIX + component_name+version_no] + pkg_index_options)
def move_resource(ids, destination_group, destination_subscription_id=None): '''Moves resources from one resource group to another(can be under different subscription) :param ids: the space separated resource ids to be moved :param destination_group: the destination resource group name :param destination_subscription_id: the destination subscription identifier ''' from azure.cli.commands.arm import parse_resource_id, is_valid_resource_id, resource_id #verify all resource ids are valid and under the same group resources = [] for i in ids: if is_valid_resource_id(i): resources.append(parse_resource_id(i)) else: raise CLIError('Invalid id "{}", as it has no group or subscription field'.format(i)) if len(set([r['subscription'] for r in resources])) > 1: raise CLIError('All resources should be under the same subscription') if len(set([r['resource_group'] for r in resources])) > 1: raise CLIError('All resources should be under the same group') rcf = _resource_client_factory() target = resource_id(subscription=(destination_subscription_id or rcf.config.subscription_id), resource_group=destination_group) return rcf.resources.move_resources(resources[0]['resource_group'], ids, target)
def set_up(self): _get_connection_string(self) self.cmd('storage share delete --name {}'.format(self.src_share)) self.cmd('storage share delete -n {}'.format(self.dest_share)) if self.cmd('storage share exists -n {}'.format(self.src_share)) == 'True': raise CLIError('Failed to delete pre-existing share {}. Unable to continue test.'.format(self.src_share)) if self.cmd('storage share exists -n {}'.format(self.dest_share)) == 'True': raise CLIError('Failed to delete pre-existing share {}. Unable to continue test.'.format(self.dest_share))
def update_self(private=False): pkg_index_options = [] if private: if not PRIVATE_PYPI_URL: raise CLIError('{} environment variable not set.' .format(PRIVATE_PYPI_URL_ENV_NAME)) if not PRIVATE_PYPI_HOST: raise CLIError('{} environment variable not set.' .format(PRIVATE_PYPI_HOST_ENV_NAME)) pkg_index_options += ['--extra-index-url', PRIVATE_PYPI_URL, '--trusted-host', PRIVATE_PYPI_HOST] pip.main(['install', '--quiet', '--isolated', '--disable-pip-version-check', '--upgrade'] + [CLI_PACKAGE_NAME] + pkg_index_options)
def handler(args): ordered_arguments = args.pop('ordered_arguments') try: client = factory() if factory else None except TypeError: client = factory(None) if factory else None getterargs = { key: val for key, val in args.items() if key in get_arguments } instance = getter(client, **getterargs) if client else getter( **getterargs) # Update properties for arg in ordered_arguments: arg_type, expressions = arg if arg_type == '--set': try: for expression in expressions: set_properties(instance, expression) except ValueError: raise CLIError('--set should be of the form:' ' --set property.property=<value>' ' property2.property=<value>') elif arg_type == '--add': try: add_properties(instance, expressions) except ValueError: raise CLIError( '--add should be of the form:' ' --add property.list key1=value1 key2=value2') elif arg_type == '--remove': try: remove_properties(instance, expressions) except ValueError: raise CLIError('--remove should be of the form: --remove' ' property.propertyToRemove or' ' --remove property.list <indexToRemove>') else: raise ValueError('Unsupported arg type {}'.format(arg_type)) # Done... update the instance! getterargs[setter_arg_name] = instance opres = setter(client, **getterargs) if client else setter( **getterargs) return opres.result() if isinstance(opres, AzureOperationPoller) else opres
def __call__(self, poller): print(self.start_msg, file=sys.stderr) logger.info( "Starting long running operation '%s' with polling interval %s ms", self.start_msg, self.poll_interval_ms) while not poller.done(): self._delay() logger.info("Long running operation '%s' polling now", self.start_msg) try: result = poller.result() except ClientException as client_exception: message = getattr(client_exception, 'message', client_exception) try: message = str(message) + ' ' + json.loads(client_exception.response.text) \ ['error']['details'][0]['message'] except: #pylint: disable=bare-except pass raise CLIError(message) logger.info("Long running operation '%s' completed with result %s", self.start_msg, result) return result
def __init__(self, test_file, test_name, run_live=False, debug=False, skip_setup=False, skip_teardown=False): super(VCRTestBase, self).__init__(test_name) self.test_name = test_name self.recording_dir = os.path.join(os.path.dirname(test_file), 'recordings') self.cassette_path = os.path.join(self.recording_dir, '{}.yaml'.format(test_name)) self.playback = os.path.isfile(self.cassette_path) self.run_live = run_live self.skip_setup = skip_setup self.skip_teardown = skip_teardown self.success = False self.exception = None self.track_commands = False self._debug = debug if not self.playback and ('--buffer' in sys.argv) and not run_live: self.exception = CLIError( 'No recorded result provided for {}.'.format(self.test_name)) self.my_vcr = vcr.VCR( cassette_library_dir=self.recording_dir, before_record_request=VCRTestBase._before_record_request, before_record_response=VCRTestBase._before_record_response, )
def export_group_as_template( resource_group_name, include_comments=False, include_parameter_default_value=False): '''Captures a resource group as a template. :param str resource_group_name:the name of the resoruce group. :param bool include_comments:export template with comments. :param bool include_parameter_default_value: export template parameter with default value. ''' rcf = _resource_client_factory() export_options = [] if include_comments: export_options.append('IncludeComments') if include_parameter_default_value: export_options.append('IncludeParameterDefaultValue') options = ','.join(export_options) if export_options else None result = rcf.resource_groups.export_template(resource_group_name, '*', options=options) #pylint: disable=no-member # On error, server still returns 200, with details in the error attribute if result.error: error = result.error if (hasattr(error, 'details') and error.details and hasattr(error.details[0], 'message')): error = error.details[0].message raise CLIError(error) print(json.dumps(result.template, indent=2))
def _generate_lb_id_list_from_names_or_ids(namespace, prop, child_type): raw = getattr(namespace, prop) if not raw: return raw = raw if isinstance(raw, list) else [raw] result = [] subscription = get_subscription_id() lb_name = namespace.load_balancer_name for item in raw: if is_valid_resource_id(item): result.append({'id': item}) else: if not lb_name: raise CLIError( 'Unable to process {}. Please supply a well-formed ID or ' '--lb-name.'.format(item)) else: result.append({ 'id': _generate_lb_subproperty_id( subscription=subscription, resource_group=namespace.resource_group_name, load_balancer_name=lb_name, child_type=child_type, child_name=item) }) setattr(namespace, prop, result)
def validate_subnet_name_or_id(namespace): """ Validates a subnet ID or, if a name is provided, formats it as an ID. """ if namespace.virtual_network_name is None and namespace.subnet is None: return if namespace.subnet == '': return # error if vnet-name is provided without subnet if namespace.virtual_network_name and not namespace.subnet: raise CLIError( 'You must specify --subnet name when using --vnet-name.') # determine if subnet is name or ID is_id = is_valid_resource_id(namespace.subnet) # error if vnet-name is provided along with a subnet ID if is_id and namespace.virtual_network_name: raise argparse.ArgumentError( None, 'Please omit --vnet-name when specifying a subnet ID') elif not is_id and not namespace.virtual_network_name: raise argparse.ArgumentError( None, 'Please specify --vnet-name when specifying a subnet name') if not is_id: namespace.subnet = resource_id( subscription=get_subscription_id(), resource_group=namespace.resource_group_name, namespace='Microsoft.Network', type='virtualNetworks', name=namespace.virtual_network_name, child_type='subnets', child_name=namespace.subnet)
def set_properties(instance, expression): key, value = expression.split('=', 1) try: value = json.loads(value) except: #pylint:disable=bare-except pass name, path = _get_name_path(key) root = instance instance = _find_property(instance, path) if instance is None: parent = _find_property(root, path[:-1]) set_properties(parent, '{}={{}}'.format(path[-1])) instance = _find_property(root, path) match = index_regex.match(name) index_value = int(match.group(1)) if match else None try: if index_value is not None: instance[index_value] = value elif isinstance(instance, dict): instance[name] = value else: setattr(instance, name, value) except IndexError: raise CLIError('index {} doesn\'t exist on {}'.format( index_value, _make_camel_case(name))) except (AttributeError, KeyError): show_options(instance, name, key.split('.'))
def __call__(self, parser, namespace, values, option_string=None): image = values match = re.match('([^:]*):([^:]*):([^:]*):([^:]*)', image) if image.lower().endswith('.vhd'): namespace.os_disk_type = 'custom' namespace.custom_os_disk_uri = image elif match: namespace.os_type = 'Custom' namespace.os_publisher = match.group(1) namespace.os_offer = match.group(2) namespace.os_sku = match.group(3) namespace.os_version = match.group(4) else: images = load_images_from_aliases_doc() matched = next( (x for x in images if x['urn alias'].lower() == image.lower()), None) if matched is None: raise CLIError('Invalid image "{}". Please pick one from {}' \ .format(image, [x['urn alias'] for x in images])) namespace.os_type = 'Custom' namespace.os_publisher = matched['publisher'] namespace.os_offer = matched['offer'] namespace.os_sku = matched['sku'] namespace.os_version = matched['version']
def load_images_from_aliases_doc(publisher=None, offer=None, sku=None): target_url = ( 'https://raw.githubusercontent.com/Azure/azure-rest-api-specs/' 'master/arm-compute/quickstart-templates/aliases.json') txt = urlopen(target_url).read() dic = json.loads(txt.decode()) try: all_images = [] result = (dic['outputs']['aliases']['value']) for v in result.values(): #loop around os for alias, vv in v.items(): #loop around distros all_images.append({ 'urn alias': alias, 'publisher': vv['publisher'], 'offer': vv['offer'], 'sku': vv['sku'], 'version': vv['version'] }) all_images = [ i for i in all_images if (_partial_matched(publisher, i['publisher']) and _partial_matched(offer, i['offer']) and _partial_matched(sku, i['sku'])) ] return all_images except KeyError: raise CLIError( 'Could not retrieve image list from {}'.format(target_url))
def get_one_of_subscription_locations(): result = get_subscription_locations() if result: return next((r.name for r in result if r.name.lower() == 'westus'), result[0].name) else: raise CLIError( 'Current subscription does not have valid location list')
def validate_address_pool_name_or_id(namespace): pool_name = namespace.backend_address_pool lb_name = namespace.load_balancer_name if is_valid_resource_id(pool_name): if lb_name: raise CLIError( 'Please omit --lb-name when specifying an address pool ID.') else: if not lb_name: raise CLIError( 'Please specify --lb-name when specifying an address pool name.' ) namespace.backend_address_pool = _generate_lb_subproperty_id( resource_group=namespace.resource_group_name, load_balancer_name=lb_name, child_type='backendAddressPools', child_name=pool_name)
def _handle_resource_not_exists(namespace): # TODO: hook up namespace._subscription_id once we support it ns, t = resource_type.split('/') if resource_exists(namespace.resource_group_name, namespace.name, ns, t): raise CLIError( 'Resource {} of type {} in group {} already exists.'.format( namespace.name, resource_type, namespace.resource_group_name))
def show_options(instance, part, path): options = instance.__dict__ if hasattr(instance, '__dict__') else instance options = options.keys() if isinstance(options, dict) else options options = [_make_camel_case(x) for x in options] raise CLIError( 'Couldn\'t find "{}" in "{}". Available options: {}'.format( _make_camel_case(part), _make_camel_case('.'.join(path[:-1]).replace('.[', '[')), sorted(list(options), key=str)))
def set_acl_policy(client, container_name, policy_name, start=None, expiry=None, permission=None): ''' Set a stored access policy on a containing object ''' from azure.storage.models import AccessPolicy if not (start or expiry or permission): raise CLIError( 'Must specify at least one property when updating an access policy.' ) acl = _get_acl(client, container_name) try: acl[policy_name] = AccessPolicy(permission, expiry, start) except KeyError: raise CLIError('ACL does not contain {}'.format(policy_name)) return _set_acl(client, container_name, acl)
def validate_inbound_nat_rule_name_or_id(namespace): rule_name = namespace.inbound_nat_rule lb_name = namespace.load_balancer_name if is_valid_resource_id(rule_name): if lb_name: raise CLIError( 'Please omit --lb-name when specifying an inbound NAT rule ID.' ) else: if not lb_name: raise CLIError( 'Please specify --lb-name when specifying an inbound NAT rule name.' ) namespace.inbound_nat_rule = _generate_lb_subproperty_id( resource_group=namespace.resource_group_name, load_balancer_name=lb_name, child_type='inboundNatRules', child_name=rule_name)
def reset_service_principal_credential(name, secret=None, years=1): '''reset credential, on expiration or you forget it. :param str name: the uri representing the name of the service principal :param str secret: the secret used to login. If missing, command will generate one. :param str years: Years the secret will be valid. ''' profile = Profile() cred, _, tenant = profile.get_login_credentials(for_graph_client=True) client = GraphRbacManagementClient(cred, tenant) #pylint: disable=no-member #look for the existing application query_exp = 'identifierUris/any(x:x eq \'{}\')'.format(name) aad_apps = list(client.applications.list(filter=query_exp)) if not aad_apps: raise CLIError( 'can\'t find a graph application matching \'{}\''.format(name)) #no need to check 2+ matches, as app id uri is unique app = aad_apps[0] #look for the existing service principal query_exp = 'servicePrincipalNames/any(x:x eq \'{}\')'.format(name) aad_sps = list(client.service_principals.list(filter=query_exp)) if not aad_sps: raise CLIError( 'can\'t find an service principal matching \'{}\''.format(name)) sp_object_id = aad_sps[0].object_id #build a new password credential and patch it secret = secret or str(uuid.uuid4()) start_date = datetime.datetime.now() end_date = start_date + relativedelta(years=years) key_id = str(uuid.uuid4()) app_cred = PasswordCredential(start_date, end_date, key_id, secret) app_create_param = ApplicationUpdateParameters( password_credentials=[app_cred]) client.applications.patch(app.object_id, app_create_param) _build_output_content(name, sp_object_id, secret, tenant)
def get_func(resource_group_name, resource_name, item_name): client = getattr(_network_client_factory(), resource) items = getattr(client.get(resource_group_name, resource_name), prop) result = next( (x for x in items if x.name.lower() == item_name.lower()), None) if not result: raise CLIError("Item '{}' does not exist on {} '{}'".format( item_name, resource, resource_name)) else: return result
def required_values_validator(namespace): errors = [ arg for arg in required_arguments 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'))
def signed_session(self): session = super(AdalAuthentication, self).signed_session() try: scheme, token = self._token_retriever() except adal.AdalError as err: raise CLIError(err) header = "{} {}".format(scheme, token) session.headers['Authorization'] = header return session
def check_component(component_name, private=False): found = bool([dist for dist in pip.get_installed_distributions(local_only=True) if dist.key == COMPONENT_PREFIX + component_name]) if not found: raise CLIError("Component not installed.") update_status = check_for_component_update(component_name, private) result = {} result['currentVersion'] = str(update_status['current_version']) result['latestVersion'] = str(update_status['latest_version']) result['updateAvailable'] = update_status['update_available'] return result
def create_role_assignment(role, assignee, resource_group_name=None, resource_id=None): ''' :param assignee: represent a user, group, or service principal. supported format: object id, user sign-in name, or service principal name :param resource_id: resource id ''' assignments_client = _auth_client_factory().role_assignments definitions_client = _auth_client_factory().role_definitions if resource_id: if resource_group_name: err = 'Resource group "{}" is redundant because resource id is supplied' raise CLIError(err.format(resource_group_name)) scope = resource_id else: scope = '/subscriptions/' + definitions_client.config.subscription_id if resource_group_name: scope = scope + '/resourceGroups/' + resource_group_name role_id = None try: uuid.UUID(role) role_id = role except ValueError: pass if not role_id: #retrieve role id role_defs = list(definitions_client.list(scope, "roleName eq '{}'".format(role))) if not role_defs: raise CLIError("Role '{}' doesn't exist.".format(role)) elif len(role_defs) > 1: ids = [r.id for r in role_defs] err = ("More than one role matches the given name '{}'. " "Set 'role' to one of the unique ids from {}'") raise CLIError(err.format(role, ids)) role_id = role_defs[0].id object_id = _get_object_id(assignee) properties = RoleAssignmentProperties(role_id, object_id) assignment_name = uuid.uuid4() return assignments_client.create(scope, assignment_name, properties)
def _handle_auth_types(**kwargs): if kwargs['command'] != 'vm create' and kwargs['command'] != 'vmss create': return args = kwargs['args'] is_windows = 'Windows' in args.os_offer \ and getattr(args, 'custom_os_disk_type', None) != 'linux' if not args.authentication_type: args.authentication_type = 'password' if is_windows else 'ssh' if args.authentication_type == 'password': if args.ssh_dest_key_path: raise CLIError( 'SSH parameters cannot be used with password authentication type' ) elif not args.admin_password: raise CLIError( 'Admin password is required with password authentication type') elif args.authentication_type == 'ssh': if args.admin_password: raise CLIError( 'Admin password cannot be used with SSH authentication type') ssh_key_file = os.path.join(os.path.expanduser('~'), '.ssh/id_rsa.pub') if not args.ssh_key_value: if os.path.isfile(ssh_key_file): with open(ssh_key_file) as f: args.ssh_key_value = f.read() else: raise CLIError( 'An RSA key file or key value must be supplied to SSH Key Value' ) if hasattr(args, 'network_security_group_type'): args.network_security_group_rule = 'RDP' if is_windows else 'SSH' if hasattr(args, 'nat_backend_port') and not args.nat_backend_port: args.nat_backend_port = '3389' if is_windows else '22'
def remove(component_name, force=False): prompt_for_delete = force is None found = bool([dist for dist in pip.get_installed_distributions(local_only=True) if dist.key == COMPONENT_PREFIX + component_name]) if found: if prompt_for_delete: ans = input("Really delete '{}'? [y/N] ".format(component_name)) if not ans or ans[0].lower() != 'y': return pip.main(['uninstall', '--quiet', '--isolated', '--yes', '--disable-pip-version-check', COMPONENT_PREFIX + component_name]) else: raise CLIError("Component not installed.")
def validate_address_prefixes(namespace): subnet_prefix_set = SPECIFIED_SENTINEL in namespace.subnet_address_prefix vnet_prefix_set = SPECIFIED_SENTINEL in namespace.vnet_address_prefix namespace.subnet_address_prefix = \ namespace.subnet_address_prefix.replace(SPECIFIED_SENTINEL, '') namespace.vnet_address_prefix = namespace.vnet_address_prefix.replace( SPECIFIED_SENTINEL, '') if namespace.subnet_type != 'new' and (subnet_prefix_set or vnet_prefix_set): raise CLIError( 'Existing subnet ({}) found. Cannot specify address prefixes when ' 'reusing an existing subnet.'.format(namespace.subnet))
def create_resource_group(resource_group_name, location, tags=None): ''' Create a new resource group. :param str resource_group_name:the desired resource group name :param str location:the resource group location :param str tags:tags in 'a=b;c' format ''' rcf = _resource_client_factory() if rcf.resource_groups.check_existence(resource_group_name): raise CLIError('resource group {} already exists'.format(resource_group_name)) parameters = ResourceGroup( location=location, tags=tags ) return rcf.resource_groups.create_or_update(resource_group_name, parameters)
def remove_nic_ip_config_inbound_nat_rule(resource_group_name, network_interface_name, ip_config_name, inbound_nat_rule, load_balancer_name=None): # pylint: disable=unused-argument client = _network_client_factory().network_interfaces nic = client.get(resource_group_name, network_interface_name) ip_config = next((x for x in nic.ip_configurations or [] if x.name.lower() == ip_config_name.lower()), None) if not ip_config: raise CLIError('IP configuration {} not found.'.format(ip_config_name)) keep_items = \ [x for x in ip_config.load_balancer_inbound_nat_rules if x.id != inbound_nat_rule] ip_config.load_balancer_inbound_nat_rules = keep_items return client.create_or_update(resource_group_name, network_interface_name, nic)