mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-05-22 08:59:08 -07:00
Migrate command line parsing to argparse (#50610)
* Start of migration to argparse * various fixes and improvements * Linting fixes * Test fixes * Fix vault_password_files * Add PrependAction for argparse * A bunch of additional tweak/fixes * Fix ansible-config tests * Fix man page generation * linting fix * More adhoc pattern fixes * Add changelog fragment * Add support for argcomplete * Enable argcomplete global completion * Rename PrependAction to PrependListAction to better describe what it does * Add documentation for installing and configuring argcomplete * Address rebase issues * Fix display encoding for vault * Fix line length * Address rebase issues * Handle rebase issues * Use mutually exclusive group instead of handling manually * Fix rebase issues * Address rebase issue * Update version added for argcomplete support * -e must be given a value * ci_complete
This commit is contained in:
parent
7ee6c136fd
commit
db6cc60352
28 changed files with 930 additions and 914 deletions
|
@ -8,10 +8,10 @@ ansible --help
|
|||
ansible testhost -i ../../inventory -m ping "$@"
|
||||
ansible testhost -i ../../inventory -m setup "$@"
|
||||
|
||||
ansible-config -c ./ansible-testé.cfg view | grep 'remote_user = admin'
|
||||
ansible-config -c ./ansible-testé.cfg dump | grep 'DEFAULT_REMOTE_USER([^)]*) = admin\>'
|
||||
ansible-config view -c ./ansible-testé.cfg | grep 'remote_user = admin'
|
||||
ansible-config dump -c ./ansible-testé.cfg | grep 'DEFAULT_REMOTE_USER([^)]*) = admin\>'
|
||||
ANSIBLE_REMOTE_USER=administrator ansible-config dump| grep 'DEFAULT_REMOTE_USER([^)]*) = administrator\>'
|
||||
ansible-config list | grep 'DEFAULT_REMOTE_USER'
|
||||
|
||||
# 'view' command must fail when config file is missing
|
||||
ansible-config -c ./ansible-non-existent.cfg view && exit 1 || echo 'Failure is expected'
|
||||
ansible-config view -c ./ansible-non-existent.cfg && exit 1 || echo 'Failure is expected'
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
|
||||
set -eux
|
||||
|
||||
ansible-playbook main.yml -i inventory -e "$@"
|
||||
ansible-playbook main.yml -i inventory "$@"
|
||||
|
|
|
@ -79,7 +79,7 @@ if [ -x "$(command -v setsid)" ]; then
|
|||
echo "rc was $WRONG_RC (0 is expected)"
|
||||
[ $WRONG_RC -eq 0 ]
|
||||
|
||||
setsid sh -c 'tty; ansible-vault --ask-vault-pass -vvvvv view test_vault.yml' < /dev/null > log 2>&1 && :
|
||||
setsid sh -c 'tty; ansible-vault view --ask-vault-pass -vvvvv test_vault.yml' < /dev/null > log 2>&1 && :
|
||||
WRONG_RC=$?
|
||||
echo "rc was $WRONG_RC (1 is expected)"
|
||||
[ $WRONG_RC -eq 1 ]
|
||||
|
@ -103,7 +103,7 @@ if [ -x "$(command -v setsid)" ]; then
|
|||
echo $?
|
||||
cat log
|
||||
|
||||
setsid sh -c 'tty; echo test-vault-password|ansible-vault --ask-vault-pass -vvvvv view vaulted.inventory' < /dev/null > log 2>&1
|
||||
setsid sh -c 'tty; echo test-vault-password|ansible-vault view --ask-vault-pass -vvvvv vaulted.inventory' < /dev/null > log 2>&1
|
||||
echo $?
|
||||
cat log
|
||||
fi
|
||||
|
|
|
@ -8,7 +8,7 @@ __metaclass__ = type
|
|||
|
||||
import pytest
|
||||
|
||||
from ansible.cli.arguments import optparse_helpers as opt_help
|
||||
from ansible.cli.arguments import option_helpers as opt_help
|
||||
|
||||
|
||||
class TestOptparseHelpersVersion:
|
||||
|
|
|
@ -14,28 +14,19 @@ from ansible.errors import AnsibleOptionsError
|
|||
def test_parse():
|
||||
""" Test adhoc parse"""
|
||||
adhoc_cli = AdHocCLI([])
|
||||
with pytest.raises(AnsibleOptionsError) as exec_info:
|
||||
with pytest.raises(SystemExit) as exec_info:
|
||||
adhoc_cli.parse()
|
||||
assert "Missing target hosts" == str(exec_info.value)
|
||||
|
||||
|
||||
def test_with_command():
|
||||
""" Test simple adhoc command"""
|
||||
module_name = 'command'
|
||||
adhoc_cli = AdHocCLI(args=['-m', module_name, '-vv'])
|
||||
adhoc_cli = AdHocCLI(args=['ansible', '-m', module_name, '-vv', 'localhost'])
|
||||
adhoc_cli.parse()
|
||||
assert context.CLIARGS['module_name'] == module_name
|
||||
assert display.verbosity == 2
|
||||
|
||||
|
||||
def test_with_extra_parameters():
|
||||
""" Test extra parameters"""
|
||||
adhoc_cli = AdHocCLI(args=['-m', 'command', 'extra_parameters'])
|
||||
with pytest.raises(AnsibleOptionsError) as exec_info:
|
||||
adhoc_cli.parse()
|
||||
assert "Extraneous options or arguments" == str(exec_info.value)
|
||||
|
||||
|
||||
def test_simple_command():
|
||||
""" Test valid command and its run"""
|
||||
adhoc_cli = AdHocCLI(['/bin/ansible', '-m', 'command', 'localhost', '-a', 'echo "hi"'])
|
||||
|
@ -89,3 +80,10 @@ def test_run_import_playbook():
|
|||
adhoc_cli.run()
|
||||
assert context.CLIARGS['module_name'] == import_playbook
|
||||
assert "'%s' is not a valid action for ad-hoc commands" % import_playbook == str(exec_info.value)
|
||||
|
||||
|
||||
def test_run_no_extra_vars():
|
||||
adhoc_cli = AdHocCLI(args=['/bin/ansible', 'localhost', '-e'])
|
||||
with pytest.raises(SystemExit) as exec_info:
|
||||
adhoc_cli.parse()
|
||||
assert exec_info.value.code == 2
|
||||
|
|
|
@ -27,7 +27,7 @@ import tempfile
|
|||
import yaml
|
||||
|
||||
from ansible import context
|
||||
from ansible.cli.arguments import optparse_helpers as opt_help
|
||||
from ansible.cli.arguments import option_helpers as opt_help
|
||||
from ansible.cli.galaxy import GalaxyCLI
|
||||
from ansible.errors import AnsibleError, AnsibleOptionsError
|
||||
from ansible.module_utils.six import PY3
|
||||
|
@ -128,14 +128,13 @@ class TestGalaxy(unittest.TestCase):
|
|||
def test_run(self):
|
||||
''' verifies that the GalaxyCLI object's api is created and that execute() is called. '''
|
||||
gc = GalaxyCLI(args=["ansible-galaxy", "install", "--ignore-errors", "imaginary_role"])
|
||||
with patch.object(ansible.cli.CLI, "execute", return_value=None) as mock_ex:
|
||||
with patch.object(ansible.cli.CLI, "run", return_value=None) as mock_run:
|
||||
gc.run()
|
||||
# testing
|
||||
self.assertIsInstance(gc.galaxy, ansible.galaxy.Galaxy)
|
||||
self.assertEqual(mock_run.call_count, 1)
|
||||
self.assertTrue(isinstance(gc.api, ansible.galaxy.api.GalaxyAPI))
|
||||
self.assertEqual(mock_ex.call_count, 1)
|
||||
gc.parse()
|
||||
with patch.object(ansible.cli.CLI, "run", return_value=None) as mock_run:
|
||||
gc.run()
|
||||
# testing
|
||||
self.assertIsInstance(gc.galaxy, ansible.galaxy.Galaxy)
|
||||
self.assertEqual(mock_run.call_count, 1)
|
||||
self.assertTrue(isinstance(gc.api, ansible.galaxy.api.GalaxyAPI))
|
||||
|
||||
def test_execute_remove(self):
|
||||
# installing role
|
||||
|
@ -172,51 +171,26 @@ class TestGalaxy(unittest.TestCase):
|
|||
gc.run()
|
||||
self.assertTrue(mocked_display.called_once_with("- downloading role 'fake_role_name', owned by "))
|
||||
|
||||
def run_parse_common(self, galaxycli_obj, action):
|
||||
with patch.object(opt_help.SortedOptParser, "set_usage") as mocked_usage:
|
||||
galaxycli_obj.parse()
|
||||
|
||||
# checking that the common results of parse() for all possible actions have been created/called
|
||||
self.assertIsInstance(galaxycli_obj.parser, opt_help.SortedOptParser)
|
||||
formatted_call = {
|
||||
'import': 'usage: %prog import [options] github_user github_repo',
|
||||
'delete': 'usage: %prog delete [options] github_user github_repo',
|
||||
'info': 'usage: %prog info [options] role_name[,version]',
|
||||
'init': 'usage: %prog init [options] role_name',
|
||||
'install': 'usage: %prog install [options] [-r FILE | role_name(s)[,version] | scm+role_repo_url[,version] | tar_file(s)]',
|
||||
'list': 'usage: %prog list [role_name]',
|
||||
'login': 'usage: %prog login [options]',
|
||||
'remove': 'usage: %prog remove role1 role2 ...',
|
||||
'search': ('usage: %prog search [searchterm1 searchterm2] [--galaxy-tags galaxy_tag1,galaxy_tag2] [--platforms platform1,platform2] '
|
||||
'[--author username]'),
|
||||
'setup': 'usage: %prog setup [options] source github_user github_repo secret',
|
||||
}
|
||||
|
||||
first_call = 'usage: %prog [delete|import|info|init|install|list|login|remove|search|setup] [--help] [options] ...'
|
||||
second_call = formatted_call[action]
|
||||
calls = [call(first_call), call(second_call)]
|
||||
mocked_usage.assert_has_calls(calls)
|
||||
|
||||
def test_parse_no_action(self):
|
||||
''' testing the options parser when no action is given '''
|
||||
gc = GalaxyCLI(args=["ansible-galaxy", ""])
|
||||
self.assertRaises(AnsibleOptionsError, gc.parse)
|
||||
self.assertRaises(SystemExit, gc.parse)
|
||||
|
||||
def test_parse_invalid_action(self):
|
||||
''' testing the options parser when an invalid action is given '''
|
||||
gc = GalaxyCLI(args=["ansible-galaxy", "NOT_ACTION"])
|
||||
self.assertRaises(AnsibleOptionsError, gc.parse)
|
||||
self.assertRaises(SystemExit, gc.parse)
|
||||
|
||||
def test_parse_delete(self):
|
||||
''' testing the options parser when the action 'delete' is given '''
|
||||
gc = GalaxyCLI(args=["ansible-galaxy", "delete"])
|
||||
self.run_parse_common(gc, "delete")
|
||||
gc = GalaxyCLI(args=["ansible-galaxy", "delete", "foo", "bar"])
|
||||
gc.parse()
|
||||
self.assertEqual(context.CLIARGS['verbosity'], 0)
|
||||
|
||||
def test_parse_import(self):
|
||||
''' testing the options parser when the action 'import' is given '''
|
||||
gc = GalaxyCLI(args=["ansible-galaxy", "import"])
|
||||
self.run_parse_common(gc, "import")
|
||||
gc = GalaxyCLI(args=["ansible-galaxy", "import", "foo", "bar"])
|
||||
gc.parse()
|
||||
self.assertEqual(context.CLIARGS['wait'], True)
|
||||
self.assertEqual(context.CLIARGS['reference'], None)
|
||||
self.assertEqual(context.CLIARGS['check_status'], False)
|
||||
|
@ -224,21 +198,21 @@ class TestGalaxy(unittest.TestCase):
|
|||
|
||||
def test_parse_info(self):
|
||||
''' testing the options parser when the action 'info' is given '''
|
||||
gc = GalaxyCLI(args=["ansible-galaxy", "info"])
|
||||
self.run_parse_common(gc, "info")
|
||||
gc = GalaxyCLI(args=["ansible-galaxy", "info", "foo", "bar"])
|
||||
gc.parse()
|
||||
self.assertEqual(context.CLIARGS['offline'], False)
|
||||
|
||||
def test_parse_init(self):
|
||||
''' testing the options parser when the action 'init' is given '''
|
||||
gc = GalaxyCLI(args=["ansible-galaxy", "init"])
|
||||
self.run_parse_common(gc, "init")
|
||||
gc = GalaxyCLI(args=["ansible-galaxy", "init", "foo"])
|
||||
gc.parse()
|
||||
self.assertEqual(context.CLIARGS['offline'], False)
|
||||
self.assertEqual(context.CLIARGS['force'], False)
|
||||
|
||||
def test_parse_install(self):
|
||||
''' testing the options parser when the action 'install' is given '''
|
||||
gc = GalaxyCLI(args=["ansible-galaxy", "install"])
|
||||
self.run_parse_common(gc, "install")
|
||||
gc.parse()
|
||||
self.assertEqual(context.CLIARGS['ignore_errors'], False)
|
||||
self.assertEqual(context.CLIARGS['no_deps'], False)
|
||||
self.assertEqual(context.CLIARGS['role_file'], None)
|
||||
|
@ -247,35 +221,34 @@ class TestGalaxy(unittest.TestCase):
|
|||
def test_parse_list(self):
|
||||
''' testing the options parser when the action 'list' is given '''
|
||||
gc = GalaxyCLI(args=["ansible-galaxy", "list"])
|
||||
self.run_parse_common(gc, "list")
|
||||
gc.parse()
|
||||
self.assertEqual(context.CLIARGS['verbosity'], 0)
|
||||
|
||||
def test_parse_login(self):
|
||||
''' testing the options parser when the action 'login' is given '''
|
||||
gc = GalaxyCLI(args=["ansible-galaxy", "login"])
|
||||
self.run_parse_common(gc, "login")
|
||||
gc.parse()
|
||||
self.assertEqual(context.CLIARGS['verbosity'], 0)
|
||||
self.assertEqual(context.CLIARGS['token'], None)
|
||||
|
||||
def test_parse_remove(self):
|
||||
''' testing the options parser when the action 'remove' is given '''
|
||||
gc = GalaxyCLI(args=["ansible-galaxy", "remove"])
|
||||
self.run_parse_common(gc, "remove")
|
||||
gc = GalaxyCLI(args=["ansible-galaxy", "remove", "foo"])
|
||||
gc.parse()
|
||||
self.assertEqual(context.CLIARGS['verbosity'], 0)
|
||||
|
||||
def test_parse_search(self):
|
||||
''' testing the options parswer when the action 'search' is given '''
|
||||
gc = GalaxyCLI(args=["ansible-galaxy", "search"])
|
||||
self.run_parse_common(gc, "search")
|
||||
gc.parse()
|
||||
self.assertEqual(context.CLIARGS['platforms'], None)
|
||||
self.assertEqual(context.CLIARGS['galaxy_tags'], None)
|
||||
self.assertEqual(context.CLIARGS['author'], None)
|
||||
|
||||
def test_parse_setup(self):
|
||||
''' testing the options parser when the action 'setup' is given '''
|
||||
gc = GalaxyCLI(args=["ansible-galaxy", "setup"])
|
||||
self.run_parse_common(gc, "setup")
|
||||
|
||||
gc = GalaxyCLI(args=["ansible-galaxy", "setup", "source", "github_user", "github_repo", "secret"])
|
||||
gc.parse()
|
||||
self.assertEqual(context.CLIARGS['verbosity'], 0)
|
||||
self.assertEqual(context.CLIARGS['remove_id'], None)
|
||||
self.assertEqual(context.CLIARGS['setup_list'], False)
|
||||
|
|
|
@ -41,9 +41,8 @@ class TestVaultCli(unittest.TestCase):
|
|||
|
||||
def test_parse_empty(self):
|
||||
cli = VaultCLI([])
|
||||
self.assertRaisesRegexp(errors.AnsibleOptionsError,
|
||||
'.*Missing required action.*',
|
||||
cli.parse)
|
||||
self.assertRaises(SystemExit,
|
||||
cli.parse)
|
||||
|
||||
# FIXME: something weird seems to be afoot when parsing actions
|
||||
# cli = VaultCLI(args=['view', '/dev/null/foo', 'mysecret3'])
|
||||
|
|
|
@ -12,7 +12,7 @@ import pytest
|
|||
|
||||
from ansible import constants as C
|
||||
from ansible import context
|
||||
from ansible.cli.arguments import optparse_helpers as opt_help
|
||||
from ansible.cli.arguments import option_helpers as opt_help
|
||||
from ansible.errors import AnsibleError
|
||||
from ansible.playbook.play_context import PlayContext
|
||||
from ansible.playbook.play import Play
|
||||
|
@ -45,8 +45,7 @@ def reset_cli_args():
|
|||
|
||||
|
||||
def test_play_context(mocker, parser, reset_cli_args):
|
||||
(options, args) = parser.parse_args(['-vv', '--check'])
|
||||
options.args = args
|
||||
options = parser.parse_args(['-vv', '--check'])
|
||||
context._init_global_context(options)
|
||||
play = Play.load({})
|
||||
play_context = PlayContext(play=play)
|
||||
|
@ -97,8 +96,7 @@ def test_play_context(mocker, parser, reset_cli_args):
|
|||
|
||||
|
||||
def test_play_context_make_become_cmd(mocker, parser, reset_cli_args):
|
||||
(options, args) = parser.parse_args([])
|
||||
options.args = args
|
||||
options = parser.parse_args([])
|
||||
context._init_global_context(options)
|
||||
play_context = PlayContext()
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue