示例#1
0
def update_extension(extension_name, index_url=None, pip_extra_index_urls=None, pip_proxy=None):
    try:
        ext = get_extension(extension_name)
        cur_version = ext.get_version()
        try:
            download_url, ext_sha256 = resolve_from_index(extension_name, cur_version=cur_version, index_url=index_url)
        except NoExtensionCandidatesError as err:
            logger.debug(err)
            raise CLIError("No updates available for '{}'. Use --debug for more information.".format(extension_name))
        # Copy current version of extension to tmp directory in case we need to restore it after a failed install.
        backup_dir = os.path.join(tempfile.mkdtemp(), extension_name)
        extension_path = get_extension_path(extension_name)
        logger.debug('Backing up the current extension: %s to %s', extension_path, backup_dir)
        shutil.copytree(extension_path, backup_dir)
        # Remove current version of the extension
        shutil.rmtree(extension_path)
        # Install newer version
        try:
            _add_whl_ext(download_url, ext_sha256=ext_sha256,
                         pip_extra_index_urls=pip_extra_index_urls, pip_proxy=pip_proxy)
            logger.debug('Deleting backup of old extension at %s', backup_dir)
            shutil.rmtree(backup_dir)
            # This gets the metadata for the extension *after* the update
            _augment_telemetry_with_ext_info(extension_name)
        except Exception as err:
            logger.error('An error occurred whilst updating.')
            logger.error(err)
            logger.debug('Copying %s to %s', backup_dir, extension_path)
            shutil.copytree(backup_dir, extension_path)
            raise CLIError('Failed to update. Rolled {} back to {}.'.format(extension_name, cur_version))
    except ExtensionNotInstalledException as e:
        raise CLIError(e)
示例#2
0
def remove_extension(extension_name):
    try:
        # Get the extension and it will raise an error if it doesn't exist
        get_extension(extension_name)
        # We call this just before we remove the extension so we can get the metadata before it is gone
        _augment_telemetry_with_ext_info(extension_name)
        shutil.rmtree(get_extension_path(extension_name))
    except ExtensionNotInstalledException as e:
        raise CLIError(e)
示例#3
0
def _add_whl_ext(source):  # pylint: disable=too-many-statements
    url_parse_result = urlparse(source)
    is_url = (url_parse_result.scheme == 'http' or url_parse_result.scheme == 'https')
    logger.debug('Extension source is url? %s', is_url)
    whl_filename = os.path.basename(url_parse_result.path) if is_url else os.path.basename(source)
    parsed_filename = WHEEL_INFO_RE(whl_filename)
    extension_name = parsed_filename.groupdict().get('name') if parsed_filename else None
    if not extension_name:
        raise CLIError('Unable to determine extension name from {}. Is the file name correct?'.format(source))
    if extension_exists(extension_name):
        raise CLIError('The extension {} already exists.'.format(extension_name))
    ext_file = None
    if is_url:
        # Download from URL
        tmp_dir = tempfile.mkdtemp()
        ext_file = os.path.join(tmp_dir, whl_filename)
        logger.debug('Downloading %s to %s', source, ext_file)
        try:
            _whl_download_from_url(url_parse_result, ext_file)
        except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError) as err:
            raise CLIError('Please ensure you have network connection. Error detail: {}'.format(str(err)))
        logger.debug('Downloaded to %s', ext_file)
    else:
        # Get file path
        ext_file = os.path.realpath(os.path.expanduser(source))
        if not os.path.isfile(ext_file):
            raise CLIError("File {} not found.".format(source))
    # Validate the extension
    logger.debug('Validating the extension {}'.format(ext_file))
    try:
        _validate_whl_extension(ext_file)
    except AssertionError:
        logger.debug(traceback.format_exc())
        raise CLIError('The extension is invalid. Use --debug for more information.')
    except CLIError as e:
        raise e
    logger.debug('Validation successful on {}'.format(ext_file))
    # Install with pip
    extension_path = get_extension_path(extension_name)
    pip_args = ['install', '--target', extension_path, ext_file]
    logger.debug('Executing pip with args: %s', pip_args)
    with HomebrewPipPatch():
        pip_status_code = _run_pip(pip_args)
    if pip_status_code > 0:
        logger.debug('Pip failed so deleting anything we might have installed at %s', extension_path)
        shutil.rmtree(extension_path, ignore_errors=True)
        raise CLIError('An error occurred. Pip failed with status code {}. '
                       'Use --debug for more information.'.format(pip_status_code))
    # Save the whl we used to install the extension in the extension dir.
    dst = os.path.join(extension_path, whl_filename)
    shutil.copyfile(ext_file, dst)
    logger.debug('Saved the whl to %s', dst)
示例#4
0
def remove_extension(extension_name):
    def log_err(func, path, exc_info):
        logger.debug("Error occurred attempting to delete item from the extension '%s'.", extension_name)
        logger.debug("%s: %s - %s", func, path, exc_info)

    try:
        # Get the extension and it will raise an error if it doesn't exist
        get_extension(extension_name)
        # We call this just before we remove the extension so we can get the metadata before it is gone
        _augment_telemetry_with_ext_info(extension_name)
        shutil.rmtree(get_extension_path(extension_name), onerror=log_err)
    except ExtensionNotInstalledException as e:
        raise CLIError(e)
示例#5
0
def remove_extension(extension_name):
    def log_err(func, path, exc_info):
        logger.debug("Error occurred attempting to delete item from the extension '%s'.", extension_name)
        logger.debug("%s: %s - %s", func, path, exc_info)

    try:
        # Get the extension and it will raise an error if it doesn't exist
        get_extension(extension_name)
        # We call this just before we remove the extension so we can get the metadata before it is gone
        _augment_telemetry_with_ext_info(extension_name)
        shutil.rmtree(get_extension_path(extension_name), onerror=log_err)
    except ExtensionNotInstalledException as e:
        raise CLIError(e)
示例#6
0
def remove_extension(extension_name):
    def log_err(func, path, exc_info):
        logger.debug("Error occurred attempting to delete item from the extension '%s'.", extension_name)
        logger.debug("%s: %s - %s", func, path, exc_info)

    try:
        # Get the extension and it will raise an error if it doesn't exist
        ext = get_extension(extension_name)
        if ext and isinstance(ext, DevExtension):
            raise CLIError(
                "Extension '{name}' was installed in development mode. Remove using "
                "`azdev extension remove {name}`".format(name=extension_name))
        # We call this just before we remove the extension so we can get the metadata before it is gone
        _augment_telemetry_with_ext_info(extension_name)
        shutil.rmtree(get_extension_path(extension_name), onerror=log_err)
    except ExtensionNotInstalledException as e:
        raise CLIError(e)
示例#7
0
def remove_extension(extension_name):
    def log_err(func, path, exc_info):
        logger.warning("Error occurred attempting to delete item from the extension '%s'.", extension_name)
        logger.warning("%s: %s - %s", func, path, exc_info)

    try:
        # Get the extension and it will raise an error if it doesn't exist
        ext = get_extension(extension_name)
        if ext and isinstance(ext, DevExtension):
            raise CLIError(
                "Extension '{name}' was installed in development mode. Remove using "
                "`azdev extension remove {name}`".format(name=extension_name))
        # We call this just before we remove the extension so we can get the metadata before it is gone
        _augment_telemetry_with_ext_info(extension_name)
        shutil.rmtree(get_extension_path(extension_name), onerror=log_err)
    except ExtensionNotInstalledException as e:
        raise CLIError(e)
示例#8
0
        def _update_command_table_from_extensions(ext_suppressions):

            def _handle_extension_suppressions(extensions):
                filtered_extensions = []
                for ext in extensions:
                    should_include = True
                    for suppression in ext_suppressions:
                        if should_include and suppression.handle_suppress(ext):
                            should_include = False
                    if should_include:
                        filtered_extensions.append(ext)
                return filtered_extensions

            extensions = get_extensions()
            if extensions:
                logger.debug("Found %s extensions: %s", len(extensions), [e.name for e in extensions])
                allowed_extensions = _handle_extension_suppressions(extensions)
                module_commands = set(self.command_table.keys())
                for ext in allowed_extensions:
                    ext_name = ext.name
                    ext_dir = ext.path or get_extension_path(ext_name)
                    sys.path.append(ext_dir)
                    try:
                        ext_mod = get_extension_modname(ext_name, ext_dir=ext_dir)
                        # Add to the map. This needs to happen before we load commands as registering a command
                        # from an extension requires this map to be up-to-date.
                        # self._mod_to_ext_map[ext_mod] = ext_name
                        start_time = timeit.default_timer()
                        extension_command_table, extension_group_table = \
                            _load_extension_command_loader(self, args, ext_mod)

                        for cmd_name, cmd in extension_command_table.items():
                            cmd.command_source = ExtensionCommandSource(
                                extension_name=ext_name,
                                overrides_command=cmd_name in module_commands,
                                preview=ext.preview)

                        self.command_table.update(extension_command_table)
                        self.command_group_table.update(extension_group_table)
                        elapsed_time = timeit.default_timer() - start_time
                        logger.debug("Loaded extension '%s' in %.3f seconds.", ext_name, elapsed_time)
                    except Exception:  # pylint: disable=broad-except
                        self.cli_ctx.raise_event(EVENT_FAILED_EXTENSION_LOAD, extension_name=ext_name)
                        logger.warning("Unable to load extension '%s'. Use --debug for more information.", ext_name)
                        logger.debug(traceback.format_exc())
示例#9
0
def get_extension_modules():
    from importlib import import_module
    import pkgutil
    from azure.cli.core.extension import get_extensions, get_extension_path, get_extension_modname
    extension_whls = get_extensions()
    ext_modules = []
    if extension_whls:
        for ext_name in [e.name for e in extension_whls]:
            ext_dir = get_extension_path(ext_name)
            sys.path.append(ext_dir)
            try:
                ext_mod = get_extension_modname(ext_name, ext_dir=ext_dir)
                module = import_module(ext_mod)
                setattr(module, 'path', module.__path__[0])
                ext_modules.append((module, ext_mod))
            except Exception as ex:
                display("Error importing '{}' extension: {}".format(ext_mod, ex))
    return ext_modules
示例#10
0
def _get_command_table_from_extensions():
    extensions = get_extension_names()
    if extensions:
        logger.debug("Found {} extensions: {}".format(len(extensions), extensions))
        for ext_name in extensions:
            ext_dir = get_extension_path(ext_name)
            sys.path.append(ext_dir)
            try:
                ext_mod = get_extension_modname(ext_dir=ext_dir)
                # Add to the map. This needs to happen before we load commands as registering a command
                # from an extension requires this map to be up-to-date.
                mod_to_ext_map[ext_mod] = ext_name
                start_time = timeit.default_timer()
                import_module(ext_mod).load_commands()
                elapsed_time = timeit.default_timer() - start_time
                logger.debug("Loaded extension '%s' in %.3f seconds.", ext_name, elapsed_time)
            except Exception:  # pylint: disable=broad-except
                logger.warning("Unable to load extension '%s'. Use --debug for more information.", ext_name)
                logger.debug(traceback.format_exc())
def update_cmd_tree(ext_name):
    print(f"Processing {ext_name}")

    ext_dir = get_extension_path(ext_name)
    ext_mod = get_extension_modname(ext_name, ext_dir=ext_dir)

    invoker = az_cli.invocation_cls(
        cli_ctx=az_cli,
        commands_loader_cls=az_cli.commands_loader_cls,
        parser_cls=az_cli.parser_cls,
        help_cls=az_cli.help_cls)
    az_cli.invocation = invoker

    sys.path.append(ext_dir)
    extension_command_table, _ = _load_extension_command_loader(
        invoker.commands_loader, None, ext_mod)

    EXT_CMD_TREE_TO_UPLOAD = Session()
    EXT_CMD_TREE_TO_UPLOAD.load(
        os.path.expanduser(os.path.join('~', '.azure', file_name)))
    root = {}
    for cmd_name, ext_cmd in extension_command_table.items():
        try:
            # do not include hidden deprecated command
            if ext_cmd.deprecate_info.hide:
                print(f"Skip hidden deprecated command: {cmd_name}")
                continue
        except AttributeError:
            pass
        parts = cmd_name.split()
        parent = root
        for i, part in enumerate(parts):
            if part in parent:
                pass
            elif i == len(parts) - 1:
                parent[part] = ext_name
            else:
                parent[part] = {}
            parent = parent[part]
    print(root)
    for k, v in root.items():
        merge(EXT_CMD_TREE_TO_UPLOAD.data, k, v)
    EXT_CMD_TREE_TO_UPLOAD.save_with_retry()
示例#12
0
def _get_command_table_from_extensions():
    extensions = get_extension_names()
    if extensions:
        logger.debug("Found {} extensions: {}".format(len(extensions), extensions))
        for ext_name in extensions:
            ext_dir = get_extension_path(ext_name)
            sys.path.append(ext_dir)
            try:
                ext_mod = get_extension_modname(ext_dir=ext_dir)
                # Add to the map. This needs to happen before we load commands as registering a command
                # from an extension requires this map to be up-to-date.
                mod_to_ext_map[ext_mod] = ext_name
                start_time = timeit.default_timer()
                import_module(ext_mod).load_commands()
                elapsed_time = timeit.default_timer() - start_time
                logger.debug("Loaded extension '%s' in %.3f seconds.", ext_name, elapsed_time)
            except Exception:  # pylint: disable=broad-except
                logger.warning("Unable to load extension '%s'. Use --debug for more information.", ext_name)
                logger.debug(traceback.format_exc())
示例#13
0
def ensure_azure_namespace_path():
    """
    Run prior to importing azure namespace packages (azure.*) to ensure the
    extension root path is configured for package import.
    """
    from azure.cli.core.extension import get_extension_path
    from azext_iot.constants import EXTENSION_NAME

    ext_path = get_extension_path(EXTENSION_NAME)

    ext_azure_dir = os.path.join(ext_path, "azure")
    if os.path.isdir(ext_azure_dir):
        import azure

        if getattr(azure, "__path__", None) and ext_azure_dir not in azure.__path__:
            azure.__path__.append(ext_azure_dir)  # _NamespacePath /w PEP420

    if sys.path and sys.path[0] != ext_path:
        sys.path.insert(0, ext_path)

    return
示例#14
0
def install(package, exact_version=None, compatible_version=None):
    if not extension_exists(EXTENSION_NAME):
        raise RuntimeError('iot extension is misconfigured')
    ext_path = get_extension_path(EXTENSION_NAME)
    cmd = [sys.executable, '-m', 'pip', '--disable-pip-version-check', '--no-cache-dir', 'install', '-U', '--target', ext_path]
    cmd_suffix = None

    if exact_version:
        cmd_suffix = '{}=={}'.format(package, exact_version)
    elif compatible_version:
        cmd_suffix = '{}~={}'.format(package, compatible_version)
    else:
        cmd_suffix = package

    cmd.append(cmd_suffix)
    logger.info(cmd)
    try:
        log_output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, universal_newlines=True)
        logger.debug(log_output)
        return True
    except subprocess.CalledProcessError as e:
        logger.debug(e.output)
        logger.debug(e)
        return False
示例#15
0
def _add_whl_ext(source, ext_sha256=None, pip_extra_index_urls=None, pip_proxy=None):  # pylint: disable=too-many-statements
    if not source.endswith('.whl'):
        raise ValueError('Unknown extension type. Only Python wheels are supported.')
    url_parse_result = urlparse(source)
    is_url = (url_parse_result.scheme == 'http' or url_parse_result.scheme == 'https')
    logger.debug('Extension source is url? %s', is_url)
    whl_filename = os.path.basename(url_parse_result.path) if is_url else os.path.basename(source)
    parsed_filename = WHEEL_INFO_RE(whl_filename)
    # Extension names can have - but .whl format changes it to _ (PEP 0427). Undo this.
    extension_name = parsed_filename.groupdict().get('name').replace('_', '-') if parsed_filename else None
    if not extension_name:
        raise CLIError('Unable to determine extension name from {}. Is the file name correct?'.format(source))
    if extension_exists(extension_name):
        raise CLIError('The extension {} already exists.'.format(extension_name))
    ext_file = None
    if is_url:
        # Download from URL
        tmp_dir = tempfile.mkdtemp()
        ext_file = os.path.join(tmp_dir, whl_filename)
        logger.debug('Downloading %s to %s', source, ext_file)
        try:
            _whl_download_from_url(url_parse_result, ext_file)
        except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError) as err:
            raise CLIError('Please ensure you have network connection. Error detail: {}'.format(str(err)))
        logger.debug('Downloaded to %s', ext_file)
    else:
        # Get file path
        ext_file = os.path.realpath(os.path.expanduser(source))
        if not os.path.isfile(ext_file):
            raise CLIError("File {} not found.".format(source))
    # Validate the extension
    logger.debug('Validating the extension %s', ext_file)
    if ext_sha256:
        valid_checksum, computed_checksum = is_valid_sha256sum(ext_file, ext_sha256)
        if valid_checksum:
            logger.debug("Checksum of %s is OK", ext_file)
        else:
            logger.debug("Invalid checksum for %s. Expected '%s', computed '%s'.",
                         ext_file, ext_sha256, computed_checksum)
            raise CLIError("The checksum of the extension does not match the expected value. "
                           "Use --debug for more information.")
    try:
        _validate_whl_extension(ext_file)
    except AssertionError:
        logger.debug(traceback.format_exc())
        raise CLIError('The extension is invalid. Use --debug for more information.')
    except CLIError as e:
        raise e
    logger.debug('Validation successful on %s', ext_file)
    # Check for distro consistency
    check_distro_consistency()
    # Install with pip
    extension_path = get_extension_path(extension_name)
    pip_args = ['install', '--target', extension_path, ext_file]

    if pip_proxy:
        pip_args = pip_args + ['--proxy', pip_proxy]
    if pip_extra_index_urls:
        for extra_index_url in pip_extra_index_urls:
            pip_args = pip_args + ['--extra-index-url', extra_index_url]

    logger.debug('Executing pip with args: %s', pip_args)
    with HomebrewPipPatch():
        pip_status_code = _run_pip(pip_args)
    if pip_status_code > 0:
        logger.debug('Pip failed so deleting anything we might have installed at %s', extension_path)
        shutil.rmtree(extension_path, ignore_errors=True)
        raise CLIError('An error occurred. Pip failed with status code {}. '
                       'Use --debug for more information.'.format(pip_status_code))
    # Save the whl we used to install the extension in the extension dir.
    dst = os.path.join(extension_path, whl_filename)
    shutil.copyfile(ext_file, dst)
    logger.debug('Saved the whl to %s', dst)
示例#16
0
def remove_extension(extension_name):
    try:
        get_extension(extension_name)
        shutil.rmtree(get_extension_path(extension_name))
    except ExtensionNotInstalledException as e:
        raise CLIError(e)
示例#17
0
def _install_test_extension2():  # pylint: disable=no-self-use
    # We extract the extension into place as we aren't testing install here
    zip_file = _get_test_data_file('myfirstcliextension_az_extmetadata.zip')
    zip_ref = zipfile.ZipFile(zip_file, 'r')
    zip_ref.extractall(get_extension_path(EXT_NAME))
    zip_ref.close()
示例#18
0
def _install_test_extension1():  # pylint: disable=no-self-use
    # We extract the extension into place as we aren't testing install here
    zip_file = _get_test_data_file('{}.zip'.format(EXT_NAME))
    zip_ref = zipfile.ZipFile(zip_file, 'r')
    zip_ref.extractall(get_extension_path(EXT_NAME))
    zip_ref.close()
示例#19
0
def add_extension_to_path(extension_name):
    ext_dir = get_extension_path(extension_name)
    sys.path.append(ext_dir)