Exemplo n.º 1
0
def add_extension(source=None, extension_name=None, index_url=None, yes=None,  # pylint: disable=unused-argument
                  pip_extra_index_urls=None, pip_proxy=None):
    ext_sha256 = None
    if extension_name:
        ext = None
        try:
            ext = get_extension(extension_name)
        except ExtensionNotInstalledException:
            pass
        if ext:
            if isinstance(ext, WheelExtension):
                logger.warning("Extension '%s' is already installed.", extension_name)
                return
            else:
                logger.warning("Overriding development version of '%s' with production version.", extension_name)
        try:
            source, ext_sha256 = resolve_from_index(extension_name, index_url=index_url)
        except NoExtensionCandidatesError as err:
            logger.debug(err)
            raise CLIError("No matching extensions for '{}'. Use --debug for more information.".format(extension_name))
    _add_whl_ext(source, ext_sha256=ext_sha256, pip_extra_index_urls=pip_extra_index_urls, pip_proxy=pip_proxy)
    _augment_telemetry_with_ext_info(extension_name)
    try:
        if extension_name and get_extension(extension_name).preview:
            logger.warning("The installed extension '%s' is in preview.", extension_name)
    except ExtensionNotInstalledException:
        pass
Exemplo n.º 2
0
def start_shell(cmd, update=None, style=None):
    from importlib import import_module

    try:
        get_extension(INTERACTIVE_EXTENSION_NAME)

        if update:
            logger.warning(
                "Updating the Interactive extension to the latest available..."
            )
            update_extension(cmd, INTERACTIVE_EXTENSION_NAME)
            reload_extension(INTERACTIVE_EXTENSION_NAME)
    except ExtensionNotInstalledException:
        logger.warning("Installing the Interactive extension...")
        add_extension(cmd, extension_name=INTERACTIVE_EXTENSION_NAME)

    ext = get_extension(INTERACTIVE_EXTENSION_NAME)
    try:
        check_version_compatibility(ext.get_metadata())
    except CLIError:
        raise CLIError('Run `az interactive --update` and try again.')

    add_extension_to_path(INTERACTIVE_EXTENSION_NAME, ext_dir=ext.path)
    interactive_module = get_extension_modname(
        ext_name=INTERACTIVE_EXTENSION_NAME, ext_dir=ext.path)
    azext_interactive = import_module(interactive_module)
    azext_interactive.start_shell(cmd, style=style)
Exemplo n.º 3
0
def add_extension(cmd, source=None, extension_name=None, index_url=None, yes=None,  # pylint: disable=unused-argument
                  pip_extra_index_urls=None, pip_proxy=None):
    ext_sha256 = None
    if extension_name:
        import colorama
        colorama.init()  # Required for displaying the spinner correctly on windows issue #9140
        cmd.cli_ctx.get_progress_controller().add(message='Searching')
        colorama.deinit()
        ext = None
        try:
            ext = get_extension(extension_name)
        except ExtensionNotInstalledException:
            pass
        if ext:
            if isinstance(ext, WheelExtension):
                logger.warning("Extension '%s' is already installed.", extension_name)
                return
            logger.warning("Overriding development version of '%s' with production version.", extension_name)
        try:
            source, ext_sha256 = resolve_from_index(extension_name, index_url=index_url)
        except NoExtensionCandidatesError as err:
            logger.debug(err)
            raise CLIError("No matching extensions for '{}'. Use --debug for more information.".format(extension_name))
    _add_whl_ext(cmd=cmd, source=source, ext_sha256=ext_sha256, pip_extra_index_urls=pip_extra_index_urls,
                 pip_proxy=pip_proxy)
    _augment_telemetry_with_ext_info(extension_name)
    try:
        if extension_name and get_extension(extension_name).preview:
            logger.warning("The installed extension '%s' is in preview.", extension_name)
    except ExtensionNotInstalledException:
        pass
Exemplo n.º 4
0
def add_extension(cmd, source=None, extension_name=None, index_url=None, yes=None,  # pylint: disable=unused-argument
                  pip_extra_index_urls=None, pip_proxy=None, system=None):
    ext_sha256 = None
    if extension_name:
        cmd.cli_ctx.get_progress_controller().add(message='Searching')
        ext = None
        try:
            ext = get_extension(extension_name)
        except ExtensionNotInstalledException:
            pass
        if ext:
            if isinstance(ext, WheelExtension):
                logger.warning("Extension '%s' is already installed.", extension_name)
                return
            logger.warning("Overriding development version of '%s' with production version.", extension_name)
        try:
            source, ext_sha256 = resolve_from_index(extension_name, index_url=index_url)
        except NoExtensionCandidatesError as err:
            logger.debug(err)
            raise CLIError("No matching extensions for '{}'. Use --debug for more information.".format(extension_name))
    extension_name = _add_whl_ext(cmd=cmd, source=source, ext_sha256=ext_sha256,
                                  pip_extra_index_urls=pip_extra_index_urls, pip_proxy=pip_proxy, system=system)
    try:
        ext = get_extension(extension_name)
        _augment_telemetry_with_ext_info(extension_name, ext)
        if extension_name and ext.experimental:
            logger.warning("The installed extension '%s' is experimental and not covered by customer support. "
                           "Please use with discretion.", extension_name)
        elif extension_name and ext.preview:
            logger.warning("The installed extension '%s' is in preview.", extension_name)
    except ExtensionNotInstalledException:
        pass
Exemplo n.º 5
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)
Exemplo n.º 6
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)
Exemplo n.º 7
0
 def test_wheel_user_system_same_extension(self):
     _install_test_extension1()
     _install_test_extension1(system=True)
     self.assertNotEqual(build_extension_path(EXT_NAME), build_extension_path(EXT_NAME, system=True))
     actual = get_extension(EXT_NAME, ext_type=WheelExtension)
     self.assertEqual(actual.name, EXT_NAME)
     self.assertEqual(actual.path, build_extension_path(EXT_NAME))
     shutil.rmtree(self.ext_dir)
     actual = get_extension(EXT_NAME, ext_type=WheelExtension)
     self.assertEqual(actual.name, EXT_NAME)
     self.assertEqual(actual.path, build_extension_path(EXT_NAME, system=True))
Exemplo n.º 8
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)
Exemplo n.º 9
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)
Exemplo n.º 10
0
def add_extension(cmd=None, source=None, extension_name=None, index_url=None, yes=None,  # pylint: disable=unused-argument, too-many-statements
                  pip_extra_index_urls=None, pip_proxy=None, system=None,
                  version=None, cli_ctx=None, upgrade=None):
    ext_sha256 = None

    version = None if version == 'latest' else version
    cmd_cli_ctx = cli_ctx or cmd.cli_ctx
    if extension_name:
        cmd_cli_ctx.get_progress_controller().add(message='Searching')
        ext = None
        set_extension_management_detail(extension_name, version)
        try:
            ext = get_extension(extension_name)
        except ExtensionNotInstalledException:
            pass
        if ext:
            if isinstance(ext, WheelExtension):
                if not upgrade:
                    logger.warning("Extension '%s' is already installed.", extension_name)
                    return
                logger.warning("Extension '%s' %s is already installed.", extension_name, ext.get_version())
                if version and version == ext.get_version():
                    return
                logger.warning("It will be overridden with version {}.".format(version) if version else "It will be updated if available.")
                update_extension(cmd=cmd, extension_name=extension_name, index_url=index_url, pip_extra_index_urls=pip_extra_index_urls, pip_proxy=pip_proxy, cli_ctx=cli_ctx, version=version)
                return
            logger.warning("Overriding development version of '%s' with production version.", extension_name)
        try:
            source, ext_sha256 = resolve_from_index(extension_name, index_url=index_url, target_version=version, cli_ctx=cmd_cli_ctx)
        except NoExtensionCandidatesError as err:
            logger.debug(err)

            if version:
                err = "No matching extensions for '{} ({})'. Use --debug for more information.".format(extension_name, version)
            else:
                err = "No matching extensions for '{}'. Use --debug for more information.".format(extension_name)
            raise CLIError(err)
    ext_name, ext_version = _get_extension_info_from_source(source)
    set_extension_management_detail(extension_name if extension_name else ext_name, ext_version)
    extension_name = _add_whl_ext(cli_ctx=cmd_cli_ctx, source=source, ext_sha256=ext_sha256,
                                  pip_extra_index_urls=pip_extra_index_urls, pip_proxy=pip_proxy, system=system)
    try:
        ext = get_extension(extension_name)
        if extension_name and ext.experimental:
            logger.warning("The installed extension '%s' is experimental and not covered by customer support. "
                           "Please use with discretion.", extension_name)
        elif extension_name and ext.preview:
            logger.warning("The installed extension '%s' is in preview.", extension_name)
        CommandIndex().invalidate()
    except ExtensionNotInstalledException:
        pass
Exemplo n.º 11
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)
Exemplo n.º 12
0
def start_shell(cmd, update=None, style=None):
    from importlib import import_module
    try:
        get_extension(INTERACTIVE_EXTENSION_NAME)
        if update:
            logger.warning("Updating the Interactive extension to the latest available..")
            update_extension(INTERACTIVE_EXTENSION_NAME)
            reload_extension(INTERACTIVE_EXTENSION_NAME)
    except ExtensionNotInstalledException:
        logger.warning("Installing the Interactive extension..")
        add_extension(extension_name=INTERACTIVE_EXTENSION_NAME)

    add_extension_to_path(INTERACTIVE_EXTENSION_NAME)
    interactive_module = get_extension_modname(ext_name=INTERACTIVE_EXTENSION_NAME)
    azext_interactive = import_module(interactive_module)
    azext_interactive.start_shell(cmd, style=style)
Exemplo n.º 13
0
def add_extension(
        source=None,
        extension_name=None,
        index_url=None,
        yes=None,  # pylint: disable=unused-argument
        pip_extra_index_urls=None,
        pip_proxy=None):
    ext_sha256 = None
    if extension_name:
        if extension_exists(extension_name):
            logger.warning("The extension '%s' already exists.",
                           extension_name)
            return
        try:
            source, ext_sha256 = resolve_from_index(extension_name,
                                                    index_url=index_url)
        except NoExtensionCandidatesError as err:
            logger.debug(err)
            raise CLIError(
                "No matching extensions for '{}'. Use --debug for more information."
                .format(extension_name))
    _add_whl_ext(source,
                 ext_sha256=ext_sha256,
                 pip_extra_index_urls=pip_extra_index_urls,
                 pip_proxy=pip_proxy)
    _augment_telemetry_with_ext_info(extension_name)
    try:
        if extension_name and get_extension(extension_name).preview:
            logger.warning("The installed extension '%s' is in preview.",
                           extension_name)
    except ExtensionNotInstalledException:
        pass
Exemplo n.º 14
0
def update_extension(extension_name, index_url=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)
            logger.debug('Deleting backup of old extension at %s', backup_dir)
            shutil.rmtree(backup_dir)
        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)
Exemplo n.º 15
0
def list_available_extensions(index_url=None, show_details=False):
    index_data = get_index_extensions(index_url=index_url)
    if show_details:
        return index_data
    installed_extensions = get_extensions(ext_type=WheelExtension)
    installed_extension_names = [e.name for e in installed_extensions]
    results = []
    for name, items in OrderedDict(sorted(index_data.items())).items():
        # exclude extensions/versions incompatible with current CLI version
        items = [item for item in items if ext_compat_with_cli(item['metadata'])[0]]
        if not items:
            continue

        latest = max(items, key=lambda c: parse_version(c['metadata']['version']))
        installed = False
        if name in installed_extension_names:
            installed = True
            ext_version = get_extension(name).version
            if ext_version and parse_version(latest['metadata']['version']) > parse_version(ext_version):
                installed = str(True) + ' (upgrade available)'
        results.append({
            'name': name,
            'version': latest['metadata']['version'],
            'summary': latest['metadata']['summary'],
            'preview': latest['metadata'].get(EXT_METADATA_ISPREVIEW, False),
            'experimental': latest['metadata'].get(EXT_METADATA_ISEXPERIMENTAL, False),
            'installed': installed
        })
    return results
Exemplo n.º 16
0
 def test_wheel_metadata2(self):
     _install_test_extension2()
     ext = get_extension(EXT_NAME)
     # There should be no exceptions and metadata should have some value
     self.assertTrue(ext.metadata)
     # We check that we can retrieve any one of the az extension metadata values
     self.assertTrue(ext.metadata.get(EXT_METADATA_MINCLICOREVERSION))
Exemplo n.º 17
0
def list_available_extensions(index_url=None, show_details=False):
    index_data = get_index_extensions(index_url=index_url)
    if show_details:
        return index_data
    installed_extensions = get_extensions()
    installed_extension_names = [e.name for e in installed_extensions]
    results = []
    for name, items in OrderedDict(sorted(index_data.items())).items():
        latest = sorted(items,
                        key=lambda c: parse_version(c['metadata']['version']),
                        reverse=True)[0]
        installed = False
        if name in installed_extension_names:
            installed = True
            ext_version = get_extension(name).version
            if ext_version and parse_version(latest['metadata']['version']
                                             ) > parse_version(ext_version):
                installed = str(True) + ' (upgrade available)'
        results.append({
            'name':
            name,
            'version':
            latest['metadata']['version'],
            'summary':
            latest['metadata']['summary'],
            'preview':
            latest['metadata'].get(EXT_METADATA_ISPREVIEW, False),
            'installed':
            installed
        })
    return results
Exemplo n.º 18
0
def list_available_extensions(index_url=None, show_details=False):
    index_data = get_index_extensions(index_url=index_url)
    if show_details:
        return index_data
    installed_extensions = get_extensions()
    installed_extension_names = [e.name for e in installed_extensions]
    results = []
    for name, items in OrderedDict(sorted(index_data.items())).items():
        # exclude extensions/versions incompatible with current CLI version
        items = [item for item in items if ext_compat_with_cli(item['metadata'])[0]]
        if not items:
            continue

        latest = max(items, key=lambda c: parse_version(c['metadata']['version']))
        installed = False
        if name in installed_extension_names:
            installed = True
            ext_version = get_extension(name).version
            if ext_version and parse_version(latest['metadata']['version']) > parse_version(ext_version):
                installed = str(True) + ' (upgrade available)'
        results.append({
            'name': name,
            'version': latest['metadata']['version'],
            'summary': latest['metadata']['summary'],
            'preview': latest['metadata'].get(EXT_METADATA_ISPREVIEW, False),
            'installed': installed
        })
    return results
Exemplo n.º 19
0
 def test_wheel_metadata2(self):
     _install_test_extension2(system=True)
     ext = get_extension(EXT_NAME)
     # There should be no exceptions and metadata should have some value
     self.assertTrue(ext.metadata)
     # We check that we can retrieve any one of the az extension metadata values
     self.assertTrue(ext.metadata.get(EXT_METADATA_MINCLICOREVERSION))
Exemplo n.º 20
0
def show_extension(extension_name):
    try:
        extension = get_extension(extension_name)
        return {OUT_KEY_NAME: extension.name,
                OUT_KEY_VERSION: extension.version,
                OUT_KEY_TYPE: extension.ext_type,
                OUT_KEY_METADATA: extension.metadata}
    except ExtensionNotInstalledException as e:
        raise CLIError(e)
Exemplo n.º 21
0
def show_extension(extension_name):
    try:
        extension = get_extension(extension_name)
        return {OUT_KEY_NAME: extension.name,
                OUT_KEY_VERSION: extension.version,
                OUT_KEY_TYPE: extension.ext_type,
                OUT_KEY_METADATA: extension.metadata}
    except ExtensionNotInstalledException as e:
        raise CLIError(e)
Exemplo n.º 22
0
def start_shell(cmd, update=None, style=None):
    from importlib import import_module
    try:
        get_extension(INTERACTIVE_EXTENSION_NAME)
        if update:
            logger.warning(
                "Updating the Interactive extension to the latest available..")
            update_extension(INTERACTIVE_EXTENSION_NAME)
            reload_extension(INTERACTIVE_EXTENSION_NAME)
    except ExtensionNotInstalledException:
        logger.warning("Installing the Interactive extension..")
        add_extension(extension_name=INTERACTIVE_EXTENSION_NAME)

    add_extension_to_path(INTERACTIVE_EXTENSION_NAME)
    interactive_module = get_extension_modname(
        ext_name=INTERACTIVE_EXTENSION_NAME)
    azext_interactive = import_module(interactive_module)
    azext_interactive.start_shell(cmd, style=style)
Exemplo n.º 23
0
def update_extension(cmd=None,
                     extension_name=None,
                     index_url=None,
                     pip_extra_index_urls=None,
                     pip_proxy=None,
                     cli_ctx=None,
                     version=None):
    try:
        cmd_cli_ctx = cli_ctx or cmd.cli_ctx
        ext = get_extension(extension_name, ext_type=WheelExtension)
        cur_version = ext.get_version()
        try:
            download_url, ext_sha256 = resolve_from_index(
                extension_name,
                cur_version=cur_version,
                index_url=index_url,
                target_version=version,
                cli_ctx=cmd_cli_ctx)
            _, ext_version = _get_extension_info_from_source(download_url)
            set_extension_management_detail(extension_name, ext_version)
        except NoExtensionCandidatesError as err:
            logger.debug(err)
            msg = "Extension {} with version {} not found.".format(
                extension_name, version
            ) if version else "No updates available for '{}'. Use --debug for more information.".format(
                extension_name)
            logger.warning(msg)
            return
        # 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 = ext.path
        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
        rmtree_with_retry(extension_path)
        # Install newer version
        try:
            _add_whl_ext(cli_ctx=cmd_cli_ctx,
                         source=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)
            rmtree_with_retry(backup_dir)
        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))
        CommandIndex().invalidate()
    except ExtensionNotInstalledException as e:
        raise CLIError(e)
Exemplo n.º 24
0
def _augment_telemetry_with_ext_info(extension_name, ext=None):
    # The extension must be available before calling this otherwise we can't get the version from metadata
    if not extension_name:
        return
    try:
        ext = ext or get_extension(extension_name)
        ext_version = ext.version
        set_extension_management_detail(extension_name, ext_version)
    except Exception:  # nopa pylint: disable=broad-except
        # Don't error on telemetry
        pass
Exemplo n.º 25
0
def _augment_telemetry_with_ext_info(extension_name):
    # The extension must be available before calling this otherwise we can't get the version from metadata
    if not extension_name:
        return
    try:
        ext = get_extension(extension_name)
        ext_version = ext.version
        set_extension_management_detail(extension_name, ext_version)
    except Exception:  # nopa pylint: disable=broad-except
        # Don't error on telemetry
        pass
Exemplo n.º 26
0
 def test_add_extension_to_path(self):
     add_extension(cmd=self.cmd, source=MY_EXT_SOURCE)
     num_exts = len(list_extensions())
     self.assertEqual(num_exts, 1)
     ext = get_extension('myfirstcliextension')
     old_path = sys.path[:]
     try:
         add_extension_to_path(ext.name)
         self.assertSequenceEqual(old_path, sys.path[:-1])
         self.assertEqual(ext.path, sys.path[-1])
     finally:
         sys.path[:] = old_path
Exemplo n.º 27
0
    def format_help(self):
        extension_version = None
        try:
            if self.command_source:
                extension_version = get_extension(self.command_source.extension_name).version
        except Exception:  # pylint: disable=broad-except
            pass

        telemetry.set_command_details(
            command=self.prog[3:],
            extension_name=self.command_source.extension_name if self.command_source else None,
            extension_version=extension_version)
        telemetry.set_success(summary='show help')
        super(AzCliCommandParser, self).format_help()
Exemplo n.º 28
0
def remove_extension(extension_name):
    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, ext)
        rmtree_with_retry(ext.path)
        CommandIndex().invalidate()
    except ExtensionNotInstalledException as e:
        raise CLIError(e)
Exemplo n.º 29
0
def teamcloud_update(cmd, version=None, prerelease=False):  # pylint: disable=too-many-statements, too-many-locals
    import os
    import tempfile
    import shutil
    from azure.cli.core import CommandIndex
    from azure.cli.core.extension import get_extension
    from azure.cli.core.extension.operations import _add_whl_ext, _augment_telemetry_with_ext_info
    from ._deploy_utils import get_github_release

    release = get_github_release(cmd.cli_ctx,
                                 'TeamCloud',
                                 version=version,
                                 prerelease=prerelease)
    asset = next((a for a in release['assets']
                  if 'py3-none-any.whl' in a['browser_download_url']), None)

    download_url = asset['browser_download_url'] if asset else None

    if not download_url:
        raise CLIError('Could not find extension .whl asset on release {}. '
                       'Specify a specific prerelease version with --version '
                       'or use latest prerelease with --pre'.format(
                           release['tag_name']))

    extension_name = 'tc'
    ext = get_extension(extension_name)
    cur_version = ext.get_version()
    # 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 = ext.path
    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(cli_ctx=cmd.cli_ctx, source=download_url)
        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))
    CommandIndex().invalidate()
Exemplo n.º 30
0
    def format_help(self):
        extension_version = None
        try:
            if self.command_source:
                extension_version = get_extension(self.command_source.extension_name).version
        except Exception:  # pylint: disable=broad-except
            pass

        telemetry.set_command_details(
            command=self.prog[3:],
            extension_name=self.command_source.extension_name if self.command_source else None,
            extension_version=extension_version)
        telemetry.set_success(summary='show help')
        super(AzCliCommandParser, self).format_help()
Exemplo n.º 31
0
def list_versions(extension_name, index_url=None):
    index_data = get_index_extensions(index_url=index_url)

    try:
        exts = index_data[extension_name]
    except Exception:
        raise CLIError('Extension {} not found.'.format(extension_name))

    try:
        installed_ext = get_extension(extension_name, ext_type=WheelExtension)
    except ExtensionNotInstalledException:
        installed_ext = None

    results = []
    latest_compatible_version = None

    for ext in sorted(exts,
                      key=lambda c: parse_version(c['metadata']['version']),
                      reverse=True):
        compatible = ext_compat_with_cli(ext['metadata'])[0]
        ext_version = ext['metadata']['version']
        if latest_compatible_version is None and compatible:
            latest_compatible_version = ext_version
        installed = ext_version == installed_ext.version if installed_ext else False
        if installed and parse_version(
                latest_compatible_version) > parse_version(
                    installed_ext.version):
            installed = str(True) + ' (upgrade available)'
        version = ext['metadata']['version']
        if latest_compatible_version == ext_version:
            version = version + ' (max compatible version)'
        results.append({
            'name':
            extension_name,
            'version':
            version,
            'preview':
            ext['metadata'].get(EXT_METADATA_ISPREVIEW, False),
            'experimental':
            ext['metadata'].get(EXT_METADATA_ISEXPERIMENTAL, False),
            'installed':
            installed,
            'compatible':
            compatible
        })
    results.reverse()
    return results
Exemplo n.º 32
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, ext)
        shutil.rmtree(ext.path, onerror=log_err)
    except ExtensionNotInstalledException as e:
        raise CLIError(e)
Exemplo n.º 33
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)
Exemplo n.º 34
0
def update_extension(cmd,
                     extension_name,
                     index_url=None,
                     pip_extra_index_urls=None,
                     pip_proxy=None):
    try:
        ext = get_extension(extension_name, ext_type=WheelExtension)
        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 = ext.path
        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(cmd=cmd,
                         source=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))
        CommandIndex().invalidate()
    except ExtensionNotInstalledException as e:
        raise CLIError(e)
Exemplo n.º 35
0
def add_extension(source=None, extension_name=None, index_url=None, yes=None,  # pylint: disable=unused-argument
                  pip_extra_index_urls=None, pip_proxy=None):
    ext_sha256 = None
    if extension_name:
        if extension_exists(extension_name):
            raise CLIError('The extension {} already exists.'.format(extension_name))
        try:
            source, ext_sha256 = resolve_from_index(extension_name, index_url=index_url)
        except NoExtensionCandidatesError as err:
            logger.debug(err)
            raise CLIError("No matching extensions for '{}'. Use --debug for more information.".format(extension_name))
    _add_whl_ext(source, ext_sha256=ext_sha256, pip_extra_index_urls=pip_extra_index_urls, pip_proxy=pip_proxy)
    _augment_telemetry_with_ext_info(extension_name)
    try:
        if extension_name and get_extension(extension_name).preview:
            logger.warning("The installed extension '%s' is in preview.", extension_name)
    except ExtensionNotInstalledException:
        pass
Exemplo n.º 36
0
def add_extension_to_path(extension_name, ext_dir=None):
    ext_dir = ext_dir or get_extension(extension_name).path
    sys.path.append(ext_dir)
    # If this path update should have made a new "azure" module available,
    # extend the existing module with its path. This allows extensions to
    # include (or depend on) Azure SDK modules that are not yet part of
    # the CLI. This applies to both the "azure" and "azure.mgmt" namespaces,
    # but ensures that modules installed by the CLI take priority.
    azure_dir = os.path.join(ext_dir, "azure")
    if os.path.isdir(azure_dir):
        import azure
        azure.__path__.append(azure_dir)
        azure_mgmt_dir = os.path.join(azure_dir, "mgmt")
        if os.path.isdir(azure_mgmt_dir):
            try:
                # Should have been imported already, so this will be quick
                import azure.mgmt
            except ImportError:
                pass
            else:
                azure.mgmt.__path__.append(azure_mgmt_dir)
Exemplo n.º 37
0
def list_available_extensions(index_url=None, show_details=False):
    index_data = get_index_extensions(index_url=index_url)
    if show_details:
        return index_data
    installed_extensions = get_extensions()
    installed_extension_names = [e.name for e in installed_extensions]
    results = []
    for name, items in OrderedDict(sorted(index_data.items())).items():
        latest = sorted(items, key=lambda c: parse_version(c['metadata']['version']), reverse=True)[0]
        installed = False
        if name in installed_extension_names:
            installed = True
            ext_version = get_extension(name).version
            if ext_version and parse_version(latest['metadata']['version']) > parse_version(ext_version):
                installed = str(True) + ' (upgrade available)'
        results.append({
            'name': name,
            'version': latest['metadata']['version'],
            'summary': latest['metadata']['summary'],
            'preview': latest['metadata'].get(EXT_METADATA_ISPREVIEW, False),
            'installed': installed
        })
    return results
Exemplo n.º 38
0
    def test_add_extension_azure_to_path(self):
        import azure
        import azure.mgmt
        old_path_0 = list(sys.path)
        old_path_1 = list(azure.__path__)
        old_path_2 = list(azure.mgmt.__path__)

        add_extension(cmd=self.cmd, source=MY_EXT_SOURCE)
        ext = get_extension('myfirstcliextension')
        azure_dir = os.path.join(ext.path, "azure")
        azure_mgmt_dir = os.path.join(azure_dir, "mgmt")
        os.mkdir(azure_dir)
        os.mkdir(azure_mgmt_dir)

        try:
            add_extension_to_path(ext.name)
            new_path_1 = list(azure.__path__)
            new_path_2 = list(azure.mgmt.__path__)
        finally:
            sys.path.remove(ext.path)
            remove_extension(ext.name)
            if isinstance(azure.__path__, list):
                azure.__path__[:] = old_path_1
            else:
                list(azure.__path__)
            if isinstance(azure.mgmt.__path__, list):
                azure.mgmt.__path__[:] = old_path_2
            else:
                list(azure.mgmt.__path__)
        self.assertSequenceEqual(old_path_1, new_path_1[:-1])
        self.assertSequenceEqual(old_path_2, new_path_2[:-1])
        self.assertEqual(azure_dir, new_path_1[-1])
        self.assertEqual(azure_mgmt_dir, new_path_2[-1])
        self.assertSequenceEqual(old_path_0, list(sys.path))
        self.assertSequenceEqual(old_path_1, list(azure.__path__))
        self.assertSequenceEqual(old_path_2, list(azure.mgmt.__path__))
Exemplo n.º 39
0
    def execute(self, args):
        from knack.events import (EVENT_INVOKER_PRE_CMD_TBL_CREATE,
                                  EVENT_INVOKER_POST_CMD_TBL_CREATE,
                                  EVENT_INVOKER_CMD_TBL_LOADED,
                                  EVENT_INVOKER_PRE_PARSE_ARGS,
                                  EVENT_INVOKER_POST_PARSE_ARGS,
                                  EVENT_INVOKER_FILTER_RESULT)
        from azure.cli.core.commands.events import EVENT_INVOKER_PRE_CMD_TBL_TRUNCATE

        # TODO: Can't simply be invoked as an event because args are transformed
        args = _pre_command_table_create(self.cli_ctx, args)

        self.cli_ctx.raise_event(EVENT_INVOKER_PRE_CMD_TBL_CREATE, args=args)
        self.commands_loader.load_command_table(args)
        self.cli_ctx.raise_event(
            EVENT_INVOKER_PRE_CMD_TBL_TRUNCATE,
            load_cmd_tbl_func=self.commands_loader.load_command_table,
            args=args)
        command = self._rudimentary_get_command(args)
        self.cli_ctx.invocation.data['command_string'] = command
        telemetry.set_raw_command_name(command)

        try:
            self.commands_loader.command_table = {
                command: self.commands_loader.command_table[command]
            }
        except KeyError:
            # Trim down the command table to reduce the number of subparsers required to optimize the performance.
            #
            # When given a command table like this:
            #
            # network application-gateway create
            # network application-gateway delete
            # network list-usages
            # storage account create
            # storage account list
            #
            # input:  az
            # output: network application-gateway create
            #         storage account create
            #
            # input:  az network
            # output: network application-gateway create
            #         network list-usages

            cmd_table = {}
            group_names = set()
            for cmd_name, cmd in self.commands_loader.command_table.items():
                if command and not cmd_name.startswith(command):
                    continue

                cmd_stub = cmd_name[len(command):].strip()
                group_name = cmd_stub.split(' ', 1)[0]
                if group_name not in group_names:
                    cmd_table[cmd_name] = cmd
                    group_names.add(group_name)
                self.commands_loader.command_table = cmd_table

        self.commands_loader.command_table = self.commands_loader.command_table  # update with the truncated table
        self.commands_loader.command_name = command
        self.commands_loader.load_arguments(command)
        self.cli_ctx.raise_event(EVENT_INVOKER_POST_CMD_TBL_CREATE,
                                 commands_loader=self.commands_loader)
        self.parser.cli_ctx = self.cli_ctx
        self.parser.load_command_table(self.commands_loader)

        self.cli_ctx.raise_event(EVENT_INVOKER_CMD_TBL_LOADED,
                                 cmd_tbl=self.commands_loader.command_table,
                                 parser=self.parser)

        arg_check = [a for a in args if a not in ['--debug', '--verbose']]
        if not arg_check:
            self.parser.enable_autocomplete()
            subparser = self.parser.subparsers[tuple()]
            self.help.show_welcome(subparser)

            # TODO: No event in base with which to target
            telemetry.set_command_details('az')
            telemetry.set_success(summary='welcome')
            return CommandResultItem(None, exit_code=0)

        if args[0].lower() == 'help':
            args[0] = '--help'

        self.parser.enable_autocomplete()

        self.cli_ctx.raise_event(EVENT_INVOKER_PRE_PARSE_ARGS, args=args)
        parsed_args = self.parser.parse_args(args)
        self.cli_ctx.raise_event(EVENT_INVOKER_POST_PARSE_ARGS,
                                 command=parsed_args.command,
                                 args=parsed_args)

        # TODO: This fundamentally alters the way Knack.invocation works here. Cannot be customized
        # with an event. Would need to be customized via inheritance.

        cmd = parsed_args.func
        self.cli_ctx.data['command'] = parsed_args.command

        self.cli_ctx.data[
            'safe_params'] = AzCliCommandInvoker._extract_parameter_names(args)

        command_source = self.commands_loader.command_table[
            command].command_source

        extension_version = None
        extension_name = None
        try:
            if isinstance(command_source, ExtensionCommandSource):
                extension_name = command_source.extension_name
                extension_version = get_extension(
                    command_source.extension_name).version
        except Exception:  # pylint: disable=broad-except
            pass
        telemetry.set_command_details(self.cli_ctx.data['command'],
                                      self.data['output'],
                                      self.cli_ctx.data['safe_params'],
                                      extension_name=extension_name,
                                      extension_version=extension_version)
        if extension_name:
            self.data['command_extension_name'] = extension_name

        self.resolve_warnings(cmd, parsed_args)
        self.resolve_confirmation(cmd, parsed_args)

        jobs = []
        for expanded_arg in _explode_list_args(parsed_args):
            cmd_copy = copy.copy(cmd)
            cmd_copy.cli_ctx = copy.copy(cmd.cli_ctx)
            cmd_copy.cli_ctx.data = copy.deepcopy(cmd.cli_ctx.data)
            expanded_arg.cmd = cmd_copy

            if hasattr(expanded_arg, '_subscription'):
                cmd_copy.cli_ctx.data[
                    'subscription_id'] = expanded_arg._subscription  # pylint: disable=protected-access

            self._validation(expanded_arg)
            jobs.append((expanded_arg, cmd_copy))

        ids = getattr(parsed_args, '_ids', None) or [None] * len(jobs)
        if self.cli_ctx.config.getboolean('core', 'disable_concurrent_ids',
                                          False) or len(ids) < 2:
            results, exceptions = self._run_jobs_serially(jobs, ids)
        else:
            results, exceptions = self._run_jobs_concurrently(jobs, ids)

        # handle exceptions
        if len(exceptions) == 1 and not results:
            ex, id_arg = exceptions[0]
            raise ex
        elif exceptions:
            for exception, id_arg in exceptions:
                logger.warning('%s: "%s"', id_arg, str(exception))
            if not results:
                return CommandResultItem(
                    None,
                    exit_code=1,
                    error=CLIError('Encountered more than one exception.'))
            else:
                logger.warning('Encountered more than one exception.')

        if results and len(results) == 1:
            results = results[0]

        event_data = {'result': results}
        self.cli_ctx.raise_event(EVENT_INVOKER_FILTER_RESULT,
                                 event_data=event_data)

        return CommandResultItem(
            event_data['result'],
            table_transformer=self.commands_loader.command_table[
                parsed_args.command].table_transformer,
            is_query_active=self.data['query_active'])
Exemplo n.º 40
0
def add_extension_to_path(extension_name, ext_dir=None):
    ext_dir = ext_dir or get_extension(extension_name).path
    sys.path.append(ext_dir)
Exemplo n.º 41
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)
Exemplo n.º 42
0
    def execute(self, args):
        from knack.events import (
            EVENT_INVOKER_PRE_CMD_TBL_CREATE,
            EVENT_INVOKER_POST_CMD_TBL_CREATE, EVENT_INVOKER_CMD_TBL_LOADED,
            EVENT_INVOKER_PRE_PARSE_ARGS, EVENT_INVOKER_POST_PARSE_ARGS,
            EVENT_INVOKER_TRANSFORM_RESULT, EVENT_INVOKER_FILTER_RESULT)
        from knack.util import CommandResultItem, todict
        from azure.cli.core.commands.events import EVENT_INVOKER_PRE_CMD_TBL_TRUNCATE

        # TODO: Can't simply be invoked as an event because args are transformed
        args = _pre_command_table_create(self.cli_ctx, args)

        self.cli_ctx.raise_event(EVENT_INVOKER_PRE_CMD_TBL_CREATE, args=args)
        self.commands_loader.load_command_table(args)
        self.cli_ctx.raise_event(
            EVENT_INVOKER_PRE_CMD_TBL_TRUNCATE,
            load_cmd_tbl_func=self.commands_loader.load_command_table,
            args=args)
        command = self._rudimentary_get_command(args)
        telemetry.set_raw_command_name(command)

        try:
            self.commands_loader.command_table = {
                command: self.commands_loader.command_table[command]
            }
        except KeyError:
            # Trim down the command table to reduce the number of subparsers required to optimize the performance.
            #
            # When given a command table like this:
            #
            # network application-gateway create
            # network application-gateway delete
            # network list-usages
            # storage account create
            # storage account list
            #
            # input:  az
            # output: network application-gateway create
            #         storage account create
            #
            # input:  az network
            # output: network application-gateway create
            #         network list-usages

            cmd_table = {}
            group_names = set()
            for cmd_name, cmd in self.commands_loader.command_table.items():
                if command and not cmd_name.startswith(command):
                    continue

                cmd_stub = cmd_name[len(command):].strip()
                group_name = cmd_stub.split(' ', 1)[0]
                if group_name not in group_names:
                    cmd_table[cmd_name] = cmd
                    group_names.add(group_name)
                self.commands_loader.command_table = cmd_table

        self.commands_loader.command_table = self.commands_loader.command_table  # update with the truncated table
        self.commands_loader.command_name = command
        self.commands_loader.load_arguments(command)
        self.cli_ctx.raise_event(EVENT_INVOKER_POST_CMD_TBL_CREATE,
                                 cmd_tbl=self.commands_loader.command_table)
        self.parser.cli_ctx = self.cli_ctx
        self.parser.load_command_table(self.commands_loader.command_table)

        self.cli_ctx.raise_event(EVENT_INVOKER_CMD_TBL_LOADED,
                                 cmd_tbl=self.commands_loader.command_table,
                                 parser=self.parser)

        if not args:
            self.cli_ctx.completion.enable_autocomplete(self.parser)
            subparser = self.parser.subparsers[tuple()]
            self.help.show_welcome(subparser)

            # TODO: No event in base with which to target
            telemetry.set_command_details('az')
            telemetry.set_success(summary='welcome')
            return None

        if args[0].lower() == 'help':
            args[0] = '--help'

        self.cli_ctx.completion.enable_autocomplete(self.parser)

        self.cli_ctx.raise_event(EVENT_INVOKER_PRE_PARSE_ARGS, args=args)
        parsed_args = self.parser.parse_args(args)
        self.cli_ctx.raise_event(EVENT_INVOKER_POST_PARSE_ARGS,
                                 command=parsed_args.command,
                                 args=parsed_args)

        # TODO: This fundamentally alters the way Knack.invocation works here. Cannot be customized
        # with an event. Would need to be customized via inheritance.
        results = []
        for expanded_arg in _explode_list_args(parsed_args):
            cmd = expanded_arg.func
            if hasattr(expanded_arg, 'cmd'):
                expanded_arg.cmd = cmd

            self.cli_ctx.data['command'] = expanded_arg.command

            self._validation(expanded_arg)

            params = self._filter_params(expanded_arg)

            command_source = self.commands_loader.command_table[
                command].command_source

            extension_version = None
            try:
                if command_source:
                    extension_version = get_extension(
                        command_source.extension_name).version
            except Exception:  # pylint: disable=broad-except
                pass

            telemetry.set_command_details(
                self.cli_ctx.data['command'],
                self.data['output'],
                [(p.split('=', 1)[0] if p.startswith('--') else p[:2])
                 for p in args if (p.startswith('-') and len(p) > 1)],
                extension_name=command_source.extension_name
                if command_source else None,
                extension_version=extension_version)
            if command_source:
                self.data[
                    'command_extension_name'] = command_source.extension_name

            try:
                result = cmd(params)
                if cmd.supports_no_wait and getattr(expanded_arg, 'no_wait',
                                                    False):
                    result = None
                elif cmd.no_wait_param and getattr(expanded_arg,
                                                   cmd.no_wait_param, False):
                    result = None

                # TODO: Not sure how to make this actually work with the TRANSFORM event...
                transform_op = cmd.command_kwargs.get('transform', None)
                if transform_op:
                    result = transform_op(result)

                if _is_poller(result):
                    result = LongRunningOperation(
                        self.cli_ctx, 'Starting {}'.format(cmd.name))(result)
                elif _is_paged(result):
                    result = list(result)

                result = todict(result)
                event_data = {'result': result}
                self.cli_ctx.raise_event(EVENT_INVOKER_TRANSFORM_RESULT,
                                         event_data=event_data)
                self.cli_ctx.raise_event(EVENT_INVOKER_FILTER_RESULT,
                                         event_data=event_data)
                result = event_data['result']
                results.append(result)

            except Exception as ex:  # pylint: disable=broad-except
                if cmd.exception_handler:
                    cmd.exception_handler(ex)
                    return None
                else:
                    six.reraise(*sys.exc_info())

        if results and len(results) == 1:
            results = results[0]

        return CommandResultItem(
            results,
            table_transformer=self.commands_loader.command_table[
                parsed_args.command].table_transformer,
            is_query_active=self.data['query_active'])
Exemplo n.º 43
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)
Exemplo n.º 44
0
 def test_wheel_metadata1(self):
     _install_test_extension1(system=True)
     ext = get_extension(EXT_NAME)
     # There should be no exceptions and metadata should have some value
     self.assertTrue(ext.metadata)
Exemplo n.º 45
0
 def test_wheel_version(self):
     _install_test_extension1()
     ext = get_extension(EXT_NAME)
     self.assertEqual(ext.version, EXT_VERSION)
Exemplo n.º 46
0
 def test_wheel_metadata1(self):
     _install_test_extension1()
     ext = get_extension(EXT_NAME)
     # There should be no exceptions and metadata should have some value
     self.assertTrue(ext.metadata)
Exemplo n.º 47
0
 def test_wheel_type(self):
     _install_test_extension1()
     ext = get_extension(EXT_NAME)
     self.assertEqual(ext.ext_type, 'whl')
Exemplo n.º 48
0
 def test_get_extension(self):
     _install_test_extension1()
     actual = get_extension(EXT_NAME)
     self.assertEqual(actual.name, EXT_NAME)
Exemplo n.º 49
0
 def test_get_extension_not_installed(self):
     with self.assertRaises(ExtensionNotInstalledException):
         get_extension(EXT_NAME)
Exemplo n.º 50
0
    def execute(self, args):
        from knack.events import (EVENT_INVOKER_PRE_CMD_TBL_CREATE, EVENT_INVOKER_POST_CMD_TBL_CREATE,
                                  EVENT_INVOKER_CMD_TBL_LOADED, EVENT_INVOKER_PRE_PARSE_ARGS,
                                  EVENT_INVOKER_POST_PARSE_ARGS, EVENT_INVOKER_TRANSFORM_RESULT,
                                  EVENT_INVOKER_FILTER_RESULT)
        from knack.util import CommandResultItem, todict
        from azure.cli.core.commands.events import EVENT_INVOKER_PRE_CMD_TBL_TRUNCATE

        # TODO: Can't simply be invoked as an event because args are transformed
        args = _pre_command_table_create(self.cli_ctx, args)

        self.cli_ctx.raise_event(EVENT_INVOKER_PRE_CMD_TBL_CREATE, args=args)
        self.commands_loader.load_command_table(args)
        self.cli_ctx.raise_event(EVENT_INVOKER_PRE_CMD_TBL_TRUNCATE,
                                 load_cmd_tbl_func=self.commands_loader.load_command_table, args=args)
        command = self._rudimentary_get_command(args)
        telemetry.set_raw_command_name(command)

        try:
            self.commands_loader.command_table = {command: self.commands_loader.command_table[command]}
        except KeyError:
            # Trim down the command table to reduce the number of subparsers required to optimize the performance.
            #
            # When given a command table like this:
            #
            # network application-gateway create
            # network application-gateway delete
            # network list-usages
            # storage account create
            # storage account list
            #
            # input:  az
            # output: network application-gateway create
            #         storage account create
            #
            # input:  az network
            # output: network application-gateway create
            #         network list-usages

            cmd_table = {}
            group_names = set()
            for cmd_name, cmd in self.commands_loader.command_table.items():
                if command and not cmd_name.startswith(command):
                    continue

                cmd_stub = cmd_name[len(command):].strip()
                group_name = cmd_stub.split(' ', 1)[0]
                if group_name not in group_names:
                    cmd_table[cmd_name] = cmd
                    group_names.add(group_name)
                self.commands_loader.command_table = cmd_table

        self.commands_loader.command_table = self.commands_loader.command_table  # update with the truncated table
        self.commands_loader.command_name = command
        self.commands_loader.load_arguments(command)
        self.cli_ctx.raise_event(EVENT_INVOKER_POST_CMD_TBL_CREATE, commands_loader=self.commands_loader)
        self.parser.cli_ctx = self.cli_ctx
        self.parser.load_command_table(self.commands_loader)

        self.cli_ctx.raise_event(EVENT_INVOKER_CMD_TBL_LOADED, cmd_tbl=self.commands_loader.command_table,
                                 parser=self.parser)

        if not args:
            self.parser.enable_autocomplete()
            subparser = self.parser.subparsers[tuple()]
            self.help.show_welcome(subparser)

            # TODO: No event in base with which to target
            telemetry.set_command_details('az')
            telemetry.set_success(summary='welcome')
            return None

        if args[0].lower() == 'help':
            args[0] = '--help'

        self.parser.enable_autocomplete()

        self.cli_ctx.raise_event(EVENT_INVOKER_PRE_PARSE_ARGS, args=args)
        parsed_args = self.parser.parse_args(args)
        self.cli_ctx.raise_event(EVENT_INVOKER_POST_PARSE_ARGS, command=parsed_args.command, args=parsed_args)

        # TODO: This fundamentally alters the way Knack.invocation works here. Cannot be customized
        # with an event. Would need to be customized via inheritance.
        results = []
        for expanded_arg in _explode_list_args(parsed_args):
            cmd = expanded_arg.func
            if hasattr(expanded_arg, 'cmd'):
                expanded_arg.cmd = cmd

            self.cli_ctx.data['command'] = expanded_arg.command

            self._validation(expanded_arg)

            params = self._filter_params(expanded_arg)

            command_source = self.commands_loader.command_table[command].command_source

            extension_version = None
            extension_name = None
            try:
                if isinstance(command_source, ExtensionCommandSource):
                    extension_name = command_source.extension_name
                    extension_version = get_extension(command_source.extension_name).version
            except Exception:  # pylint: disable=broad-except
                pass

            telemetry.set_command_details(self.cli_ctx.data['command'], self.data['output'],
                                          [(p.split('=', 1)[0] if p.startswith('--') else p[:2]) for p in args if
                                           (p.startswith('-') and len(p) > 1)],
                                          extension_name=extension_name, extension_version=extension_version)
            if extension_name:
                self.data['command_extension_name'] = extension_name

            deprecations = [] + getattr(expanded_arg, '_argument_deprecations', [])
            if cmd.deprecate_info:
                deprecations.append(cmd.deprecate_info)

            # search for implicit deprecation
            path_comps = cmd.name.split()[:-1]
            implicit_deprecate_info = None
            while path_comps and not implicit_deprecate_info:
                implicit_deprecate_info = resolve_deprecate_info(self.cli_ctx, ' '.join(path_comps))
                del path_comps[-1]

            if implicit_deprecate_info:
                deprecate_kwargs = implicit_deprecate_info.__dict__.copy()
                deprecate_kwargs['object_type'] = 'command'
                del deprecate_kwargs['_get_tag']
                del deprecate_kwargs['_get_message']
                deprecations.append(ImplicitDeprecated(**deprecate_kwargs))

            for d in deprecations:
                logger.warning(d.message)

            try:
                result = cmd(params)
                if cmd.supports_no_wait and getattr(expanded_arg, 'no_wait', False):
                    result = None
                elif cmd.no_wait_param and getattr(expanded_arg, cmd.no_wait_param, False):
                    result = None

                transform_op = cmd.command_kwargs.get('transform', None)
                if transform_op:
                    result = transform_op(result)

                if _is_poller(result):
                    result = LongRunningOperation(self.cli_ctx, 'Starting {}'.format(cmd.name))(result)
                elif _is_paged(result):
                    result = list(result)

                result = todict(result, AzCliCommandInvoker.remove_additional_prop_layer)
                event_data = {'result': result}
                self.cli_ctx.raise_event(EVENT_INVOKER_TRANSFORM_RESULT, event_data=event_data)
                result = event_data['result']
                results.append(result)

            except Exception as ex:  # pylint: disable=broad-except
                if cmd.exception_handler:
                    cmd.exception_handler(ex)
                    return None
                else:
                    six.reraise(*sys.exc_info())

        if results and len(results) == 1:
            results = results[0]

        event_data = {'result': results}
        self.cli_ctx.raise_event(EVENT_INVOKER_FILTER_RESULT, event_data=event_data)

        return CommandResultItem(
            event_data['result'],
            table_transformer=self.commands_loader.command_table[parsed_args.command].table_transformer,
            is_query_active=self.data['query_active'])
Exemplo n.º 51
0
def add_extension_to_path(extension_name, ext_dir=None):
    ext_dir = ext_dir or get_extension(extension_name).path
    sys.path.append(ext_dir)
Exemplo n.º 52
0
    def execute(self, args):
        from knack.events import (EVENT_INVOKER_PRE_CMD_TBL_CREATE, EVENT_INVOKER_POST_CMD_TBL_CREATE,
                                  EVENT_INVOKER_CMD_TBL_LOADED, EVENT_INVOKER_PRE_PARSE_ARGS,
                                  EVENT_INVOKER_POST_PARSE_ARGS,
                                  EVENT_INVOKER_FILTER_RESULT)
        from azure.cli.core.commands.events import EVENT_INVOKER_PRE_CMD_TBL_TRUNCATE

        # TODO: Can't simply be invoked as an event because args are transformed
        args = _pre_command_table_create(self.cli_ctx, args)

        self.cli_ctx.raise_event(EVENT_INVOKER_PRE_CMD_TBL_CREATE, args=args)
        self.commands_loader.load_command_table(args)
        self.cli_ctx.raise_event(EVENT_INVOKER_PRE_CMD_TBL_TRUNCATE,
                                 load_cmd_tbl_func=self.commands_loader.load_command_table, args=args)
        command = self._rudimentary_get_command(args)
        self.cli_ctx.invocation.data['command_string'] = command
        telemetry.set_raw_command_name(command)

        try:
            self.commands_loader.command_table = {command: self.commands_loader.command_table[command]}
        except KeyError:
            # Trim down the command table to reduce the number of subparsers required to optimize the performance.
            #
            # When given a command table like this:
            #
            # network application-gateway create
            # network application-gateway delete
            # network list-usages
            # storage account create
            # storage account list
            #
            # input:  az
            # output: network application-gateway create
            #         storage account create
            #
            # input:  az network
            # output: network application-gateway create
            #         network list-usages

            cmd_table = {}
            group_names = set()
            for cmd_name, cmd in self.commands_loader.command_table.items():
                if command and not cmd_name.startswith(command):
                    continue

                cmd_stub = cmd_name[len(command):].strip()
                group_name = cmd_stub.split(' ', 1)[0]
                if group_name not in group_names:
                    cmd_table[cmd_name] = cmd
                    group_names.add(group_name)
                self.commands_loader.command_table = cmd_table

        self.commands_loader.command_table = self.commands_loader.command_table  # update with the truncated table
        self.commands_loader.command_name = command
        self.commands_loader.load_arguments(command)
        self.cli_ctx.raise_event(EVENT_INVOKER_POST_CMD_TBL_CREATE, commands_loader=self.commands_loader)
        self.parser.cli_ctx = self.cli_ctx
        self.parser.load_command_table(self.commands_loader)

        self.cli_ctx.raise_event(EVENT_INVOKER_CMD_TBL_LOADED, cmd_tbl=self.commands_loader.command_table,
                                 parser=self.parser)

        arg_check = [a for a in args if a not in ['--debug', '--verbose']]
        if not arg_check:
            self.parser.enable_autocomplete()
            subparser = self.parser.subparsers[tuple()]
            self.help.show_welcome(subparser)

            # TODO: No event in base with which to target
            telemetry.set_command_details('az')
            telemetry.set_success(summary='welcome')
            return CommandResultItem(None, exit_code=0)

        if args[0].lower() == 'help':
            args[0] = '--help'

        self.parser.enable_autocomplete()

        self.cli_ctx.raise_event(EVENT_INVOKER_PRE_PARSE_ARGS, args=args)
        parsed_args = self.parser.parse_args(args)
        self.cli_ctx.raise_event(EVENT_INVOKER_POST_PARSE_ARGS, command=parsed_args.command, args=parsed_args)

        # TODO: This fundamentally alters the way Knack.invocation works here. Cannot be customized
        # with an event. Would need to be customized via inheritance.

        cmd = parsed_args.func
        self.cli_ctx.data['command'] = parsed_args.command

        self.cli_ctx.data['safe_params'] = AzCliCommandInvoker._extract_parameter_names(args)

        command_source = self.commands_loader.command_table[command].command_source

        extension_version = None
        extension_name = None
        try:
            if isinstance(command_source, ExtensionCommandSource):
                extension_name = command_source.extension_name
                extension_version = get_extension(command_source.extension_name).version
        except Exception:  # pylint: disable=broad-except
            pass
        telemetry.set_command_details(self.cli_ctx.data['command'], self.data['output'],
                                      self.cli_ctx.data['safe_params'],
                                      extension_name=extension_name, extension_version=extension_version)
        if extension_name:
            self.data['command_extension_name'] = extension_name

        self.resolve_warnings(cmd, parsed_args)
        self.resolve_confirmation(cmd, parsed_args)

        jobs = []
        for expanded_arg in _explode_list_args(parsed_args):
            cmd_copy = copy.copy(cmd)
            cmd_copy.cli_ctx = copy.copy(cmd.cli_ctx)
            cmd_copy.cli_ctx.data = copy.deepcopy(cmd.cli_ctx.data)
            expanded_arg.cmd = expanded_arg._cmd = cmd_copy

            if hasattr(expanded_arg, '_subscription'):
                cmd_copy.cli_ctx.data['subscription_id'] = expanded_arg._subscription  # pylint: disable=protected-access

            self._validation(expanded_arg)
            jobs.append((expanded_arg, cmd_copy))

        ids = getattr(parsed_args, '_ids', None) or [None] * len(jobs)
        if self.cli_ctx.config.getboolean('core', 'disable_concurrent_ids', False) or len(ids) < 2:
            results, exceptions = self._run_jobs_serially(jobs, ids)
        else:
            results, exceptions = self._run_jobs_concurrently(jobs, ids)

        # handle exceptions
        if len(exceptions) == 1 and not results:
            ex, id_arg = exceptions[0]
            raise ex
        elif exceptions:
            for exception, id_arg in exceptions:
                logger.warning('%s: "%s"', id_arg, str(exception))
            if not results:
                return CommandResultItem(None, exit_code=1, error=CLIError('Encountered more than one exception.'))
            logger.warning('Encountered more than one exception.')

        if results and len(results) == 1:
            results = results[0]

        event_data = {'result': results}
        self.cli_ctx.raise_event(EVENT_INVOKER_FILTER_RESULT, event_data=event_data)

        return CommandResultItem(
            event_data['result'],
            table_transformer=self.commands_loader.command_table[parsed_args.command].table_transformer,
            is_query_active=self.data['query_active'])