コード例 #1
0
    def test_command_index(self):

        from azure.cli.core._session import INDEX
        from azure.cli.core import CommandIndex, __version__

        cli = DummyCli()
        loader = cli.commands_loader
        command_index = CommandIndex(cli)

        expected_command_index = {
            'hello': [
                'azure.cli.command_modules.hello', 'azext_hello2',
                'azext_hello1'
            ],
            'extra': ['azure.cli.command_modules.extra']
        }
        expected_command_table = [
            'hello mod-only', 'hello overridden', 'extra unused',
            'hello ext-only'
        ]

        def _set_index(dict_):
            INDEX[CommandIndex._COMMAND_INDEX] = dict_

        def _check_index():
            self.assertEqual(INDEX[CommandIndex._COMMAND_INDEX_VERSION],
                             __version__)
            self.assertEqual(INDEX[CommandIndex._COMMAND_INDEX_CLOUD_PROFILE],
                             cli.cloud.profile)
            self.assertDictEqual(INDEX[CommandIndex._COMMAND_INDEX],
                                 expected_command_index)

        # Clear the command index
        _set_index({})
        self.assertFalse(INDEX[CommandIndex._COMMAND_INDEX])
        loader.load_command_table(None)
        # Test command index is built for None args
        _check_index()

        # Test command index is built when `args` is provided
        _set_index({})
        loader.load_command_table(["hello", "mod-only"])
        _check_index()

        # Test rebuild command index if no module found
        _set_index({"network": ["azure.cli.command_modules.network"]})
        loader.load_command_table(["hello", "mod-only"])
        _check_index()

        with mock.patch("azure.cli.core.__version__",
                        "2.7.0"), mock.patch.object(cli.cloud, "profile",
                                                    "2019-03-01-hybrid"):

            def update_and_check_index():
                loader.load_command_table(["hello", "mod-only"])
                self.assertEqual(INDEX[CommandIndex._COMMAND_INDEX_VERSION],
                                 "2.7.0")
                self.assertEqual(
                    INDEX[CommandIndex._COMMAND_INDEX_CLOUD_PROFILE],
                    "2019-03-01-hybrid")
                self.assertDictEqual(INDEX[CommandIndex._COMMAND_INDEX],
                                     expected_command_index)

            # Test rebuild command index if version is not present
            del INDEX[CommandIndex._COMMAND_INDEX_VERSION]
            del INDEX[CommandIndex._COMMAND_INDEX]
            update_and_check_index()

            # Test rebuild command index if version is not valid
            INDEX[CommandIndex._COMMAND_INDEX_VERSION] = ""
            _set_index({})
            update_and_check_index()

            # Test rebuild command index if version is outdated
            INDEX[CommandIndex._COMMAND_INDEX_VERSION] = "2.6.0"
            _set_index({})
            update_and_check_index()

            # Test rebuild command index if profile is outdated
            INDEX[CommandIndex.
                  _COMMAND_INDEX_CLOUD_PROFILE] = "2017-03-09-profile"
            _set_index({})
            update_and_check_index()

        # Test rebuild command index if modules are found but outdated
        # This only happens in dev environment. For users, the version check logic prevents it
        _set_index({"hello": ["azure.cli.command_modules.extra"]})
        loader.load_command_table(["hello", "mod-only"])
        _check_index()

        # Test irrelevant commands are not loaded
        _set_index(expected_command_index)
        cmd_tbl = loader.load_command_table(["hello", "mod-only"])
        self.assertEqual(
            ['hello mod-only', 'hello overridden', 'hello ext-only'],
            list(cmd_tbl.keys()))

        # Full scenario test 1: Installing an extension 'azext_hello1' that extends 'hello' group
        outdated_command_index = {
            'hello': ['azure.cli.command_modules.hello'],
            'extra': ['azure.cli.command_modules.extra']
        }
        _set_index(outdated_command_index)

        # Command for an outdated group
        cmd_tbl = loader.load_command_table(["hello", "-h"])
        # Index is not updated, and only built-in commands are loaded
        _set_index(outdated_command_index)
        self.assertListEqual(list(cmd_tbl),
                             ['hello mod-only', 'hello overridden'])

        # Command index is explicitly invalidated by azure.cli.core.extension.operations.add_extension
        command_index.invalidate()

        cmd_tbl = loader.load_command_table(["hello", "-h"])
        # Index is updated, and new commands are loaded
        _check_index()
        self.assertListEqual(list(cmd_tbl), expected_command_table)

        # Full scenario test 2: Installing extension 'azext_hello2' that overrides existing command 'hello overridden'
        outdated_command_index = {
            'hello': ['azure.cli.command_modules.hello', 'azext_hello1'],
            'extra': ['azure.cli.command_modules.extra']
        }
        _set_index(outdated_command_index)
        # Command for an overridden command
        cmd_tbl = loader.load_command_table(["hello", "overridden"])
        # Index is not updated
        self.assertEqual(INDEX[CommandIndex._COMMAND_INDEX],
                         outdated_command_index)
        # With the old command index, 'hello overridden' is loaded from the build-in module
        hello_overridden_cmd = cmd_tbl['hello overridden']
        self.assertEqual(hello_overridden_cmd.command_source, 'hello')
        self.assertListEqual(
            list(cmd_tbl),
            ['hello mod-only', 'hello overridden', 'hello ext-only'])

        # Command index is explicitly invalidated by azure.cli.core.extension.operations.add_extension
        command_index.invalidate()

        # Command index is updated, and 'hello overridden' is loaded from the new extension
        cmd_tbl = loader.load_command_table(["hello", "overridden"])
        hello_overridden_cmd = cmd_tbl['hello overridden']
        self.assertTrue(
            isinstance(hello_overridden_cmd.command_source,
                       ExtensionCommandSource))
        _check_index()
        self.assertListEqual(list(cmd_tbl), expected_command_table)

        # Call again with the new command index. Irrelevant commands are not loaded
        cmd_tbl = loader.load_command_table(["hello", "overridden"])
        hello_overridden_cmd = cmd_tbl['hello overridden']
        self.assertTrue(
            isinstance(hello_overridden_cmd.command_source,
                       ExtensionCommandSource))
        _check_index()
        self.assertListEqual(
            list(cmd_tbl),
            ['hello mod-only', 'hello overridden', 'hello ext-only'])

        del INDEX[CommandIndex._COMMAND_INDEX_VERSION]
        del INDEX[CommandIndex._COMMAND_INDEX_CLOUD_PROFILE]
        del INDEX[CommandIndex._COMMAND_INDEX]
コード例 #2
0
ファイル: operations.py プロジェクト: wonner/azure-cli
def add_extension(
        cmd=None,
        source=None,
        extension_name=None,
        index_url=None,
        yes=None,  # pylint: disable=unused-argument
        pip_extra_index_urls=None,
        pip_proxy=None,
        system=None,
        version=None,
        cli_ctx=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
        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,
                                                    target_version=version)
        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)

    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)
        _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)
        CommandIndex().invalidate()
    except ExtensionNotInstalledException:
        pass
コード例 #3
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 overriden 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