Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

basic: allow one or more when param list having choices #34537

Merged
merged 4 commits into from Feb 8, 2018
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 12 additions & 3 deletions lib/ansible/module_utils/basic.py
Expand Up @@ -157,7 +157,7 @@
except ImportError:
pass

from ansible.module_utils.pycompat24 import get_exception, literal_eval
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this change might be the cause of all the import sanity test failures

from ansible.module_utils.pycompat24 import literal_eval
from ansible.module_utils.six import (
PY2,
PY3,
Expand All @@ -170,7 +170,7 @@
)
from ansible.module_utils.six.moves import map, reduce, shlex_quote
from ansible.module_utils._text import to_native, to_bytes, to_text
from ansible.module_utils.parsing.convert_bool import BOOLEANS, BOOLEANS_FALSE, BOOLEANS_TRUE, boolean
from ansible.module_utils.parsing.convert_bool import BOOLEANS_FALSE, BOOLEANS_TRUE, boolean


PASSWORD_MATCH = re.compile(r'^(?:.+[-_\s])?pass(?:[-_\s]?(?:word|phrase|wrd|wd)?)(?:[-_\s].+)?$', re.I)
Expand Down Expand Up @@ -1778,7 +1778,16 @@ def _check_argument_values(self, spec=None, param=None):
continue
if isinstance(choices, SEQUENCETYPE) and not isinstance(choices, (binary_type, text_type)):
if k in param:
if param[k] not in choices:
# Allow one or more when type='list' param with choices
if isinstance(param[k], list):
diff_list = ", ".join([item for item in param[k] if item not in choices])
if diff_list:
choices_str = ", ".join([to_native(c) for c in choices])
msg = "value of %s must be one or more of: %s. Got no match for: %s" % (k, choices_str, diff_list)
if self._options_context:
msg += " found in %s" % " -> ".join(self._options_context)
self.fail_json(msg=msg)
elif param[k] not in choices:
# PyYaml converts certain strings to bools. If we can unambiguously convert back, do so before checking
# the value. If we can't figure this out, module author is responsible.
lowered_choices = None
Expand Down
20 changes: 20 additions & 0 deletions test/units/module_utils/basic/test_argument_spec.py
Expand Up @@ -71,6 +71,7 @@ def complex_argspec():
baz=dict(fallback=(basic.env_fallback, ['BAZ'])),
bar1=dict(type='bool'),
zardoz=dict(choices=['one', 'two']),
zardoz2=dict(type='list', choices=['one', 'two', 'three']),
)
mut_ex = (('bar', 'bam'),)
req_to = (('bam', 'baz'),)
Expand Down Expand Up @@ -254,6 +255,25 @@ def test_fail_required_together_and_fallback(self, capfd, mocker, stdin, complex
assert results['failed']
assert results['msg'] == "parameters are required together: bam, baz"

@pytest.mark.parametrize('stdin', [{'foo': 'hello', 'zardoz2': ['one', 'four', 'five']}], indirect=['stdin'])
def test_fail_list_with_choices(self, capfd, mocker, stdin, complex_argspec):
"""Fail because one of the items is not in the choice"""
with pytest.raises(SystemExit):
basic.AnsibleModule(**complex_argspec)

out, err = capfd.readouterr()
results = json.loads(out)

assert results['failed']
assert results['msg'] == "value of zardoz2 must be one or more of: one, two, three. Got no match for: four, five"

@pytest.mark.parametrize('stdin', [{'foo': 'hello', 'zardoz2': ['one', 'three']}], indirect=['stdin'])
def test_list_with_choices(self, capfd, mocker, stdin, complex_argspec):
"""Test choices with list"""
am = basic.AnsibleModule(**complex_argspec)
assert isinstance(am.params['zardoz2'], list)
assert am.params['zardoz2'] == ['one', 'three']


class TestComplexOptions:
"""Test arg spec options"""
Expand Down