def fzf_location(cmd, fzf_filter=None, no_default=False): """ Use fzf to quickly filter and select a default location. """ from azure.cli.core.commands.parameters import get_subscription_locations locations = get_subscription_locations(cmd.cli_ctx) if not locations: raise CLIError('No locations found.' 'If you are logged in, make sure a subscription exists' 'and you have access to it. If you are not logged' 'in, please run "az login" to access your account.') # Use tabulate to make a pretty table for fzf to display headers = ["Name", "Display Name", "Regional Display Name"] locations_sorted = sorted(locations, key=lambda i: i.name) locations_list = [[l.name, l.display_name, l.regional_display_name] for l in locations_sorted] result = _fzf(_fzf_table(locations_list, headers), header_lines=2, fzf_filter=fzf_filter) if result: location = result.split('|')[1].strip() if not no_default: cmd.cli_ctx.config.set_value( cmd.cli_ctx.config.defaults_section_name, 'location', location) return next((l for l in locations if l.name == location), None) return None
def _normalize_location(cmd, location): location = location.lower() locations = get_subscription_locations(cmd.cli_ctx) for loc in locations: if loc.display_name.lower() == location or loc.name.lower() == location: return loc.name return location
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 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 list_locations(cmd): from azure.cli.core.commands.parameters import get_subscription_locations return get_subscription_locations(cmd.cli_ctx)
def list_locations(): from azure.cli.core.commands.parameters import get_subscription_locations return get_subscription_locations()