コード例 #1
0
ファイル: test_resolve.py プロジェクト: mevtorres/Azure-CLI
 def test_no_exts_in_index(self):
     name = 'myext'
     with IndexPatch(
         {}), self.assertRaises(NoExtensionCandidatesError) as err:
         resolve_from_index(name)
     self.assertEqual(str(err.exception),
                      "No extension found with name '{}'".format(name))
コード例 #2
0
ファイル: test_resolve.py プロジェクト: mevtorres/Azure-CLI
 def test_filter_platform_wrong_pyver(self):
     name = 'myext'
     # Should raise as not py2.py3
     with IndexPatch({
             'myext': [mock_ext('myext-0.0.1-py3-none-any.whl', '0.0.1')]
     }), self.assertRaises(NoExtensionCandidatesError):
         resolve_from_index(name)
コード例 #3
0
ファイル: test_resolve.py プロジェクト: mevtorres/Azure-CLI
 def test_filter_platform_wrong_platform(self):
     name = 'myext'
     # Should raise as we don't support platform specific whls in index
     with IndexPatch({
             'myext':
         [mock_ext('myext-0.0.1-py2.py3-none-x86_64.whl', '0.0.1')]
     }), self.assertRaises(NoExtensionCandidatesError):
         resolve_from_index(name)
コード例 #4
0
ファイル: test_resolve.py プロジェクト: mevtorres/Azure-CLI
 def test_ext_resolved(self):
     name = 'myext'
     index_data = {
         name: [mock_ext('myext-0.0.1-py2.py3-none-any.whl', '0.0.1')]
     }
     with IndexPatch(index_data):
         self.assertEqual(
             resolve_from_index(name)[0],
             index_data[name][0]['downloadUrl'])
コード例 #5
0
ファイル: test_resolve.py プロジェクト: mevtorres/Azure-CLI
 def test_filter_platform(self):
     name = 'myext'
     index_data = {
         'myext': [
             mock_ext('myext-0.0.1-py2.py3-none-any.whl', '0.0.1'),
             mock_ext('myext-0.0.2-py3-none-any.whl', '0.0.2')
         ]
     }
     with IndexPatch(index_data):
         # Should choose the first one as it's not a platform specific whl.
         self.assertEqual(
             resolve_from_index(name)[0],
             index_data[name][0]['downloadUrl'])
コード例 #6
0
ファイル: test_resolve.py プロジェクト: ymasaoka/azure-cli
 def test_filter_platform(self):
     name = 'myext'
     index_data = {
         'myext': [
             mock_ext('myext-0.0.1-py2.py3-none-any.whl', '0.0.1'),
             mock_ext('myext-0.0.2-py3-none-any.whl', '0.0.2')
         ]
     }
     with IndexPatch(index_data):
         # Should choose the second one as py version is not considered platform specific.
         self.assertEqual(
             resolve_from_index(name)[0],
             index_data[name][1]['downloadUrl'])
コード例 #7
0
    def test_filter_target_version(self):
        ext_name = 'hello'
        index_data = {
            ext_name: [
                mock_ext('hello-0.1.0-py3-none-any.whl', '0.1.0'),
                mock_ext('hello-0.2.0-py3-none-any.whl', '0.2.0')
            ]
        }

        # resolve okay
        with IndexPatch(index_data):
            self.assertEqual(
                resolve_from_index(ext_name, target_version='0.1.0')[0],
                index_data[ext_name][0]['downloadUrl'])
            self.assertEqual(
                resolve_from_index(ext_name, target_version='0.2.0')[0],
                index_data[ext_name][1]['downloadUrl'])

        with IndexPatch(index_data):
            with self.assertRaisesRegex(
                    NoExtensionCandidatesError,
                    'Extension with version 0.3.0 not found'):
                resolve_from_index(ext_name, target_version='0.3.0')
コード例 #8
0
def _check_value_in_extensions(cli_ctx, parser, args, no_prompt):  # pylint: disable=too-many-statements, too-many-locals
    """Check if the command args can be found in extension commands.
       Exit command if the error is caused by an extension not installed.
       Otherwise return.
    """
    # Check if the command is from an extension
    from azure.cli.core.util import roughly_parse_command
    from azure.cli.core.azclierror import NoTTYError
    exit_code = 2
    command_str = roughly_parse_command(args[1:])
    allow_prefix_match = args[-1] == '-h' or args[-1] == '--help'
    ext_name = _search_in_extension_commands(cli_ctx, command_str, allow_prefix_match=allow_prefix_match)
    # ext_name is a list if the input command matches the prefix of one or more extension commands,
    # for instance: `az blueprint` when running `az blueprint -h`
    # ext_name is a str if the input command matches a complete command of an extension,
    # for instance: `az blueprint create`
    if isinstance(ext_name, list):
        if len(ext_name) > 1:
            from knack.prompting import prompt_choice_list, NoTTYException
            prompt_msg = "The command requires the latest version of one of the following " \
                "extensions. You need to pick one to install:"
            try:
                choice_idx = prompt_choice_list(prompt_msg, ext_name)
                ext_name = ext_name[choice_idx]
                no_prompt = True
            except NoTTYException:
                tty_err_msg = "{}{}\nUnable to prompt for selection as no tty available. Please update or " \
                    "install the extension with 'az extension add --upgrade -n <extension-name>'." \
                    .format(prompt_msg, ext_name)
                az_error = NoTTYError(tty_err_msg)
                az_error.print_error()
                az_error.send_telemetry()
                parser.exit(exit_code)
        else:
            ext_name = ext_name[0]
    if not ext_name:
        return

    # If a valid command has parser error, it may be caused by CLI running on a profile that is
    # not 'latest' and the command is not supported in that profile. If this command exists in an extension,
    # CLI will try to download the extension and rerun the command. But the parser will fail again and try to
    # install the extension and rerun the command infinitely. So we need to check if the latest version of the
    # extension is already installed and return if yes as the error is not caused by extension not installed.
    from azure.cli.core.extension import get_extension, ExtensionNotInstalledException
    from azure.cli.core.extension._resolve import resolve_from_index, NoExtensionCandidatesError
    try:
        ext = get_extension(ext_name)
    except ExtensionNotInstalledException:
        pass
    else:
        try:
            resolve_from_index(ext_name, cur_version=ext.version, cli_ctx=cli_ctx)
        except NoExtensionCandidatesError:
            return

    telemetry.set_command_details(command_str,
                                  parameters=AzCliCommandInvoker._extract_parameter_names(args),  # pylint: disable=protected-access
                                  extension_name=ext_name)
    run_after_extension_installed = _get_extension_run_after_dynamic_install_config(cli_ctx)
    prompt_info = ""
    if no_prompt:
        logger.warning('The command requires the extension %s. It will be installed first.', ext_name)
        install_ext = True
    else:  # yes_prompt
        from knack.prompting import prompt_y_n, NoTTYException
        prompt_msg = 'The command requires the extension {}. Do you want to install it now?'.format(ext_name)
        if run_after_extension_installed:
            prompt_msg = '{} The command will continue to run after the extension is installed.' \
                .format(prompt_msg)
        NO_PROMPT_CONFIG_MSG = "Run 'az config set extension.use_dynamic_install=" \
            "yes_without_prompt' to allow installing extensions without prompt."
        try:
            install_ext = prompt_y_n(prompt_msg, default='y')
            if install_ext:
                prompt_info = " with prompt"
                logger.warning(NO_PROMPT_CONFIG_MSG)
        except NoTTYException:
            tty_err_msg = "The command requires the extension {}. " \
                          "Unable to prompt for extension install confirmation as no tty " \
                          "available. {}".format(ext_name, NO_PROMPT_CONFIG_MSG)
            az_error = NoTTYError(tty_err_msg)
            az_error.print_error()
            az_error.send_telemetry()
            parser.exit(exit_code)

    print_error = True
    if install_ext:
        from azure.cli.core.extension.operations import add_extension
        add_extension(cli_ctx=cli_ctx, extension_name=ext_name, upgrade=True)
        if run_after_extension_installed:
            import subprocess
            import platform
            exit_code = subprocess.call(args, shell=platform.system() == 'Windows')
            # In this case, error msg is for telemetry recording purpose only.
            # From UX perspective, the command will rerun in subprocess. Whether it succeeds or fails,
            # mesages will be shown from the subprocess and this process should not print more message to
            # interrupt that.
            print_error = False
            error_msg = ("Extension {} dynamically installed{} and commands will be "
                         "rerun automatically.").format(ext_name, prompt_info)
        else:
            error_msg = 'Extension {} installed{}. Please rerun your command.' \
                .format(ext_name, prompt_info)
    else:
        error_msg = "The command requires the latest version of extension {ext_name}. " \
            "To install, run 'az extension add --upgrade -n {ext_name}'.".format(
                ext_name=ext_name)
    az_error = CommandNotFoundError(error_msg)
    if print_error:
        az_error.print_error()
    az_error.send_telemetry()
    parser.exit(exit_code)