Example #1
0
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
Example #2
0
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
Example #3
0
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)
Example #4
0
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
Example #5
0
def list_locations(cmd):
    from azure.cli.core.commands.parameters import get_subscription_locations
    return get_subscription_locations(cmd.cli_ctx)
Example #6
0
def list_locations():
    from azure.cli.core.commands.parameters import get_subscription_locations
    return get_subscription_locations()