Example #1
0
def run_commands(args):
    from knack.cli import CLI
    from azure.cli.core import MainCommandsLoader, logger
    from azure.cli.core._config import GLOBAL_CONFIG_DIR, ENV_VAR_PREFIX
    from azure.cli.core.cloud import get_active_cloud

    class MockCLI(CLI):
        def __init__(self):
            super(MockCLI, self).__init__(cli_name='mock_cli',
                                          config_dir=GLOBAL_CONFIG_DIR,
                                          config_env_var_prefix=ENV_VAR_PREFIX)
            self.cloud = get_active_cloud(self)

    logger.addHandler(logging.NullHandler())

    loader = MainCommandsLoader(MockCLI())
    table = loader.load_command_table('')

    if args.prefix:
        table = dict((each, table[each]) for each in table
                     if each.startswith(args.prefix))

    if args.list_only:
        for each in sorted(table):
            if args.details:
                print_command_info(table[each])
            else:
                print(each)
        sys.exit(0)

    commands = ['az {} --help'.format(each) for each in table]
    results = []

    pool = multiprocessing.Pool(multiprocessing.cpu_count())
    for i, res in enumerate(
            pool.imap_unordered(run_single_command, commands, 10), 1):
        sys.stderr.write('{:.2f}% \n'.format(float(i) * 100 / len(commands)))
        sys.stderr.flush()
        results.append(res)
    pool.close()
    pool.join()

    if not all(results):
        sys.stderr.write('Error running --help on commands.\n')
        sys.exit(1)

    print('Done')
Example #2
0
def run_commands(args):
    from knack.cli import CLI
    from azure.cli.core import MainCommandsLoader, logger
    from azure.cli.core._config import GLOBAL_CONFIG_DIR, ENV_VAR_PREFIX
    from azure.cli.core.cloud import get_active_cloud

    class MockCLI(CLI):
        def __init__(self):
            super(MockCLI, self).__init__(
                cli_name='mock_cli',
                config_dir=GLOBAL_CONFIG_DIR,
                config_env_var_prefix=ENV_VAR_PREFIX)
            self.cloud = get_active_cloud(self)

    logger.addHandler(logging.NullHandler())

    loader = MainCommandsLoader(MockCLI())
    table = loader.load_command_table('')

    if args.prefix:
        table = dict((each, table[each]) for each in table if each.startswith(args.prefix))

    if args.list_only:
        for each in sorted(table):
            if args.details:
                print_command_info(table[each])
            else:
                print(each)
        sys.exit(0)

    commands = ['az {} --help'.format(each) for each in table]
    results = []

    pool = multiprocessing.Pool(multiprocessing.cpu_count())
    for i, res in enumerate(pool.imap_unordered(run_single_command, commands, 10), 1):
        sys.stderr.write('{:.2f}% \n'.format(float(i) * 100 / len(commands)))
        sys.stderr.flush()
        results.append(res)
    pool.close()
    pool.join()

    if not all(results):
        sys.stderr.write('Error running --help on commands.\n')
        sys.exit(1)

    print('Done')
Example #3
0
    def test_parser_error_spellchecker(self):
        cli = DummyCli()
        main_loader = MainCommandsLoader(cli)
        cli.loader = main_loader

        cli.loader.load_command_table(None)

        parser = cli.parser_cls(cli)
        parser.load_command_table(cli.loader)

        logger_msgs = []
        choice_lists = []
        original_get_close_matches = difflib.get_close_matches

        def mock_log_error(_, msg):
            logger_msgs.append(msg)

        def mock_get_close_matches(*args, **kwargs):
            choice_lists.append(original_get_close_matches(*args, **kwargs))

        # run multiple faulty commands and save error logs, as well as close matches
        with mock.patch('logging.Logger.error', mock_log_error), \
                mock.patch('difflib.get_close_matches', mock_get_close_matches):
            faulty_cmd_args = [
                'test module1 --opt enum_1',
                'test extension1 --opt enum_1',
                'test foo_bar --opt enum_3',
                'test module --opt enum_3',
                'test extension --opt enum_3'
            ]
            for text in faulty_cmd_args:
                with self.assertRaises(SystemExit):
                    parser.parse_args(text.split())
        parser.parse_args('test module --opt enum_1'.split())

        # assert the right type of error msg is logged for command vs argument parsing
        self.assertEqual(len(logger_msgs), 5)
        for msg in logger_msgs[:3]:
            self.assertIn("not in the", msg)
            self.assertIn("command group", msg)
        for msg in logger_msgs[3:]:
            self.assertIn("not a valid value for '--opt'.", msg)

        # assert the right choices are matched as "close".
        # If these don't hold, matching algorithm should be deemed flawed.
        for choices in choice_lists[:2]:
            self.assertEqual(len(choices), 1)
        self.assertEqual(len(choice_lists[2]), 0)
        for choices in choice_lists[3:]:
            self.assertEqual(len(choices), 2)
            for choice in ['enum_1', 'enum_2']:
                self.assertIn(choice, choices)
Example #4
0
    def test_parser_failure_recovery_recommendations(self):
        cli = DummyCli()
        main_loader = MainCommandsLoader(cli)
        cli.loader = main_loader

        cli.loader.load_command_table(None)

        parser = cli.parser_cls(cli)
        parser.load_command_table(cli.loader)

        recommendation_provider_parameters = []

        version = cli.get_cli_version()
        expected_recommendation_provider_parameters = [
            # version, command, parameters, extension
            ExpectedParameters(version, 'test module1', ['--opt'], False),
            ExpectedParameters(version, 'test extension1', ['--opt'], False),
            ExpectedParameters(version, 'foo_bar', ['--opt'], False),
            ExpectedParameters(version, 'test module', ['--opt'], False),
            ExpectedParameters(version, 'test extension', ['--opt'], True)
        ]

        def mock_recommendation_provider(*args):
            recommendation_provider_parameters.append(tuple(args))
            return []

        AzCliCommandParser.recommendation_provider = mock_recommendation_provider

        faulty_cmd_args = [
            'test module1 --opt enum_1', 'test extension1 --opt enum_1',
            'test foo_bar --opt enum_3', 'test module --opt enum_3',
            'test extension --opt enum_3'
        ]

        for text in faulty_cmd_args:
            with self.assertRaises(SystemExit):
                parser.parse_args(text.split())

        for i, parameters in enumerate(recommendation_provider_parameters):
            version, command, parameters, extension = parameters
            expected = expected_recommendation_provider_parameters[i]
            self.assertEqual(expected.version, version)
            self.assertIn(expected.command, command)
            self.assertEqual(expected.parameters, parameters)

            if expected.has_extension:
                self.assertIsNotNone(extension)
            else:
                self.assertIsNone(extension)
Example #5
0
    def test_register_command_from_extension(self):

        from azure.cli.core.commands import _load_command_loader
        cli = DummyCli()
        main_loader = MainCommandsLoader(cli)
        cli.loader = main_loader

        cmd_tbl = cli.loader.load_command_table(None)
        ext1 = cmd_tbl['hello noodle']
        ext2 = cmd_tbl['hello world']

        self.assertTrue(isinstance(ext1.command_source, ExtensionCommandSource))
        self.assertFalse(ext1.command_source.overrides_command)

        self.assertTrue(isinstance(ext2.command_source, ExtensionCommandSource))
        self.assertTrue(ext2.command_source.overrides_command)
Example #6
0
    def test_parser_error_spellchecker(self):
        cli = DummyCli()
        main_loader = MainCommandsLoader(cli)
        cli.loader = main_loader

        cli.loader.load_command_table(None)

        parser = cli.parser_cls(cli)
        parser.load_command_table(cli.loader)

        logger_msgs = []
        choice_lists = []
        original_get_close_matches = difflib.get_close_matches

        def mock_log_error(_, msg):
            logger_msgs.append(msg)

        def mock_get_close_matches(*args, **kwargs):
            choice_lists.append(original_get_close_matches(*args, **kwargs))

        def mock_ext_cmd_tree_load(*args, **kwargs):
            return {
                "test": {
                    "new-ext": {
                        "create": "new-ext-name",
                        "reset": "another-ext-name"
                    }
                }
            }

        def mock_add_extension(*args, **kwargs):
            pass

        # run multiple faulty commands and save error logs, as well as close matches
        with mock.patch('logging.Logger.error', mock_log_error), \
                mock.patch('difflib.get_close_matches', mock_get_close_matches):
            faulty_cmd_args = [
                'test module1 --opt enum_1', 'test extension1 --opt enum_1',
                'test foo_bar --opt enum_3', 'test module --opt enum_3',
                'test extension --opt enum_3'
            ]
            for text in faulty_cmd_args:
                with self.assertRaises(SystemExit):
                    parser.parse_args(text.split())
        parser.parse_args('test module --opt enum_1'.split())

        # assert the right type of error msg is logged for command vs argument parsing
        self.assertEqual(len(logger_msgs), 5)
        for msg in logger_msgs[:3]:
            self.assertIn("not in the", msg)
            self.assertIn("command group", msg)
        for msg in logger_msgs[3:]:
            self.assertIn("not a valid value for '--opt'.", msg)

        # assert the right choices are matched as "close".
        # If these don't hold, matching algorithm should be deemed flawed.
        for choices in choice_lists[:2]:
            self.assertEqual(len(choices), 1)
        self.assertEqual(len(choice_lists[2]), 0)
        for choices in choice_lists[3:]:
            self.assertEqual(len(choices), 2)
            for choice in ['enum_1', 'enum_2']:
                self.assertIn(choice, choices)

        # test dynamic extension install
        with mock.patch('logging.Logger.error', mock_log_error), \
                mock.patch('azure.cli.core.extension.operations.add_extension', mock_add_extension), \
                mock.patch('azure.cli.core.parser.AzCliCommandParser._get_extension_command_tree', mock_ext_cmd_tree_load), \
                mock.patch('azure.cli.core.parser.AzCliCommandParser._get_extension_use_dynamic_install_config', return_value='yes_without_prompt'):
            with self.assertRaises(SystemExit):
                parser.parse_args('test new-ext create --opt enum_2'.split())
            self.assertIn(
                "Extension new-ext-name installed. Please rerun your command.",
                logger_msgs[5])
            with self.assertRaises(SystemExit):
                parser.parse_args('test new-ext reset pos1 pos2'.split()
                                  )  # test positional args
            self.assertIn(
                "Extension another-ext-name installed. Please rerun your command.",
                logger_msgs[6])
Example #7
0
def build_command_table(cli_ctx):
    from azure.cli.core import MainCommandsLoader
    cmd_table = MainCommandsLoader(cli_ctx).load_command_table(None)
    for command in cmd_table:
        cmd_table[command].load_arguments()

    data = {}
    for command in cmd_table:
        com_descip = {}
        param_descrip = {}
        com_descip['short-summary'] = cmd_table[command].description() \
            if callable(cmd_table[command].description) \
            else cmd_table[command].description or ''
        com_descip['examples'] = ''

        for key in cmd_table[command].arguments:
            required = ''
            help_desc = ''
            if cmd_table[command].arguments[key].type.settings.get('required'):
                required = '[REQUIRED]'
            if cmd_table[command].arguments[key].type.settings.get('help'):
                help_desc = cmd_table[command].arguments[
                    key].type.settings.get('help')

            name_options = []
            for name in cmd_table[command].arguments[key].options_list:
                name_options.append(name)

            options = {
                'name': name_options,
                'required': required,
                'help': help_desc
            }
            param_descrip[
                cmd_table[command].arguments[key].options_list[0]] = options

        com_descip['parameters'] = param_descrip
        data[command] = com_descip

    for command in helps:
        diction_help = yaml.load(helps[command])
        if command not in data:
            data[command] = {
                'short-summary': diction_help.get('short-summary', ''),
                'long-summary': diction_help.get('long-summary', ''),
                'parameters': {}
            }
        else:
            data[command]['short-summary'] = diction_help.get(
                'short-summary', data[command].get('short-summary', ''))
            data[command]['long-summary'] = diction_help.get(
                "long-summary", '')
            data[command]['parameters'] = {}

        if 'parameters' in diction_help:
            for param in diction_help["parameters"]:
                if param['name'].split()[0] not in data[command]['parameters']:
                    options = {
                        'name': name_options,
                        'required': required,
                        'help': help_desc
                    }
                    data[command]['parameters'] = {
                        param["name"].split()[0]: options
                    }
                if 'short-summary' in param:
                    data[command]['parameters'][param['name'].split()[0]]['help'] \
                        = param['short-summary']
        if 'examples' in diction_help:
            string_example = ''
            for example in diction_help['examples']:
                string_example += example.get('name', '') + '\n' + example.get(
                    'text', '') + '\n'
            data[command]['examples'] = string_example

    return data