Update validate to use 2.11 ArgumentSpecValidator if available (#86)
Update validate to use 2.11 ArgumentSpecValidator if available SUMMARY fixes: #85 ISSUE TYPE Bugfix Pull Request COMPONENT NAME ADDITIONAL INFORMATION Reviewed-by: Bradley A. Thornton <bthornto@redhat.com> Reviewed-by: Ashwini Mhatre <mashu97@gmail.com> Reviewed-by: None <None>pull/91/head
parent
b95847245d
commit
61a826c997
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
bugfixes:
|
||||||
|
- Update validate to use 2.11 ArgumentSpecValidator if available.
|
|
@ -46,9 +46,7 @@ except ImportError:
|
||||||
# ansible-base 2.11 should expose argspec validation outside of the
|
# ansible-base 2.11 should expose argspec validation outside of the
|
||||||
# ansiblemodule class
|
# ansiblemodule class
|
||||||
try:
|
try:
|
||||||
from ansible.module_utils.somefile import ( # noqa: F401
|
from ansible.module_utils.common.arg_spec import ArgumentSpecValidator
|
||||||
FutureBaseArgspecValidator,
|
|
||||||
)
|
|
||||||
|
|
||||||
HAS_ANSIBLE_ARG_SPEC_VALIDATOR = True
|
HAS_ANSIBLE_ARG_SPEC_VALIDATOR = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -238,7 +236,35 @@ class AnsibleArgSpecValidator:
|
||||||
that is coming in 2.11, change the check according above
|
that is coming in 2.11, change the check according above
|
||||||
"""
|
"""
|
||||||
if HAS_ANSIBLE_ARG_SPEC_VALIDATOR:
|
if HAS_ANSIBLE_ARG_SPEC_VALIDATOR:
|
||||||
return self._validate()
|
if self._schema_format == "doc":
|
||||||
|
self._convert_doc_to_schema()
|
||||||
|
if self._schema_conditionals is not None:
|
||||||
|
self._schema = dict_merge(
|
||||||
|
self._schema, self._schema_conditionals
|
||||||
|
)
|
||||||
|
invalid_keys = [
|
||||||
|
k
|
||||||
|
for k in self._schema.keys()
|
||||||
|
if k not in VALID_ANSIBLEMODULE_ARGS
|
||||||
|
]
|
||||||
|
if invalid_keys:
|
||||||
|
valid = False
|
||||||
|
errors = [
|
||||||
|
"Invalid schema. Invalid keys found: {ikeys}".format(
|
||||||
|
ikeys=",".join(invalid_keys)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
updated_data = {}
|
||||||
|
return valid, errors, updated_data
|
||||||
|
else:
|
||||||
|
validator = ArgumentSpecValidator(**self._schema)
|
||||||
|
result = validator.validate(self._data)
|
||||||
|
valid = not bool(result.error_messages)
|
||||||
|
return (
|
||||||
|
valid,
|
||||||
|
result.error_messages,
|
||||||
|
result.validated_parameters,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
return self._validate()
|
return self._validate()
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,9 @@
|
||||||
|
|
||||||
- name: "{{ parser }} Check argspec fail"
|
- name: "{{ parser }} Check argspec fail"
|
||||||
assert:
|
assert:
|
||||||
that: "argfail['errors'] == 'parameters are mutually exclusive: command|template_path found in parser'"
|
that: "{{ msg in argfail.errors }}"
|
||||||
|
vars:
|
||||||
|
msg: "parameters are mutually exclusive: command|template_path found in parser"
|
||||||
|
|
||||||
- name: "{{ parser }} validate argspec"
|
- name: "{{ parser }} validate argspec"
|
||||||
ansible.utils.cli_parse:
|
ansible.utils.cli_parse:
|
||||||
|
@ -25,7 +27,9 @@
|
||||||
|
|
||||||
- name: "{{ parser }} Check argspec fail"
|
- name: "{{ parser }} Check argspec fail"
|
||||||
assert:
|
assert:
|
||||||
that: "argfail['errors'] == 'parameters are mutually exclusive: command|text'"
|
that: "{{ msg in argfail.errors }}"
|
||||||
|
vars:
|
||||||
|
msg: "parameters are mutually exclusive: command|text"
|
||||||
|
|
||||||
- name: "{{ parser }} validate argspec"
|
- name: "{{ parser }} validate argspec"
|
||||||
ansible.utils.cli_parse:
|
ansible.utils.cli_parse:
|
||||||
|
@ -37,7 +41,9 @@
|
||||||
|
|
||||||
- name: "{{ parser }} Check argspec fail"
|
- name: "{{ parser }} Check argspec fail"
|
||||||
assert:
|
assert:
|
||||||
that: "argfail['errors'] == 'one of the following is required: command, text'"
|
that: "{{ msg in argfail.errors }}"
|
||||||
|
vars:
|
||||||
|
msg: "one of the following is required: command, text"
|
||||||
|
|
||||||
|
|
||||||
- name: "{{ parser }} validate argspec"
|
- name: "{{ parser }} validate argspec"
|
||||||
|
@ -51,4 +57,6 @@
|
||||||
|
|
||||||
- name: "{{ parser }} Check arspec fail"
|
- name: "{{ parser }} Check arspec fail"
|
||||||
assert:
|
assert:
|
||||||
that: "argfail['msg'] == 'Parser name should be provided as a full name including collection'"
|
that: "{{ msg in argfail.msg }}"
|
||||||
|
vars:
|
||||||
|
msg: "Parser name should be provided as a full name including collection"
|
||||||
|
|
|
@ -12,6 +12,13 @@
|
||||||
- after
|
- after
|
||||||
loop_control:
|
loop_control:
|
||||||
loop_var: string
|
loop_var: string
|
||||||
|
when: "{{result.msg|type_debug != 'list'}}"
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that: "{{ msg in result.msg }}"
|
||||||
|
vars:
|
||||||
|
msg: "missing required arguments: after, before"
|
||||||
|
when: "{{result.msg|type_debug == 'list'}}"
|
||||||
|
|
||||||
- name: Check argspec validation, skip_lines must be a dict
|
- name: Check argspec validation, skip_lines must be a dict
|
||||||
ansible.utils.fact_diff:
|
ansible.utils.fact_diff:
|
||||||
|
@ -26,3 +33,8 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that: "{{ 'unable to convert to list' in result.msg }}"
|
that: "{{ 'unable to convert to list' in result.msg }}"
|
||||||
|
when: "{{result.msg|type_debug != 'list'}}"
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that: "{{ 'unable to convert to list' in result.msg[0] }}"
|
||||||
|
when: "{{result.msg|type_debug == 'list'}}"
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
register: result
|
register: result
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that: "{{ result.msg == msg }}"
|
that: "{{ msg in result.msg }}"
|
||||||
vars:
|
vars:
|
||||||
msg: "missing required arguments: path"
|
msg: "missing required arguments: path"
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,8 @@ class TestSortList(unittest.TestCase):
|
||||||
)
|
)
|
||||||
valid, errors, _updated_data = aav.validate()
|
valid, errors, _updated_data = aav.validate()
|
||||||
self.assertTrue(valid)
|
self.assertTrue(valid)
|
||||||
|
if not errors:
|
||||||
|
errors = None
|
||||||
self.assertEqual(errors, None)
|
self.assertEqual(errors, None)
|
||||||
|
|
||||||
def test_simple_defaults(self):
|
def test_simple_defaults(self):
|
||||||
|
@ -46,6 +48,8 @@ class TestSortList(unittest.TestCase):
|
||||||
}
|
}
|
||||||
valid, errors, updated_data = aav.validate()
|
valid, errors, updated_data = aav.validate()
|
||||||
self.assertTrue(valid)
|
self.assertTrue(valid)
|
||||||
|
if not errors:
|
||||||
|
errors = None
|
||||||
self.assertEqual(errors, None)
|
self.assertEqual(errors, None)
|
||||||
self.assertEqual(expected, updated_data)
|
self.assertEqual(expected, updated_data)
|
||||||
|
|
||||||
|
@ -84,6 +88,8 @@ class TestSortList(unittest.TestCase):
|
||||||
)
|
)
|
||||||
valid, errors, _updated_data = aav.validate()
|
valid, errors, _updated_data = aav.validate()
|
||||||
self.assertTrue(valid)
|
self.assertTrue(valid)
|
||||||
|
if not errors:
|
||||||
|
errors = None
|
||||||
self.assertEqual(errors, None)
|
self.assertEqual(errors, None)
|
||||||
|
|
||||||
def test_schema_conditional(self):
|
def test_schema_conditional(self):
|
||||||
|
@ -114,6 +120,12 @@ class TestSortList(unittest.TestCase):
|
||||||
)
|
)
|
||||||
valid, errors, _updated_data = aav.validate()
|
valid, errors, _updated_data = aav.validate()
|
||||||
self.assertFalse(valid)
|
self.assertFalse(valid)
|
||||||
|
if isinstance(errors, list):
|
||||||
|
# for ansibleargspecvalidator 2.11 its returning errors as list
|
||||||
|
self.assertIn(
|
||||||
|
"not_valid. Supported parameters include:", errors[0]
|
||||||
|
)
|
||||||
|
else:
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
"Unsupported parameters for 'test_action' module: not_valid",
|
"Unsupported parameters for 'test_action' module: not_valid",
|
||||||
errors,
|
errors,
|
||||||
|
@ -130,6 +142,8 @@ class TestSortList(unittest.TestCase):
|
||||||
)
|
)
|
||||||
valid, errors, _updated_data = aav.validate()
|
valid, errors, _updated_data = aav.validate()
|
||||||
self.assertTrue(valid)
|
self.assertTrue(valid)
|
||||||
|
if not errors:
|
||||||
|
errors = None
|
||||||
self.assertIsNone(errors)
|
self.assertIsNone(errors)
|
||||||
|
|
||||||
def test_invalid_spec(self):
|
def test_invalid_spec(self):
|
||||||
|
@ -143,4 +157,4 @@ class TestSortList(unittest.TestCase):
|
||||||
)
|
)
|
||||||
valid, errors, _updated_data = aav.validate()
|
valid, errors, _updated_data = aav.validate()
|
||||||
self.assertFalse(valid)
|
self.assertFalse(valid)
|
||||||
self.assertIn("Invalid keys found: not_valid", errors)
|
self.assertIn("Invalid schema. Invalid keys found: not_valid", errors)
|
||||||
|
|
|
@ -117,7 +117,7 @@ class TestCli_Parse(unittest.TestCase):
|
||||||
**kwargs
|
**kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertIn(
|
||||||
"one of the following is required: command, text", result["errors"]
|
"one of the following is required: command, text", result["errors"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ class TestCli_Parse(unittest.TestCase):
|
||||||
schema_conditionals=ARGSPEC_CONDITIONALS,
|
schema_conditionals=ARGSPEC_CONDITIONALS,
|
||||||
**kwargs
|
**kwargs
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertIn(
|
||||||
"missing required arguments: name found in parser",
|
"missing required arguments: name found in parser",
|
||||||
result["errors"],
|
result["errors"],
|
||||||
)
|
)
|
||||||
|
|
|
@ -144,9 +144,11 @@ class TestValidate(unittest.TestCase):
|
||||||
# missing required arguments
|
# missing required arguments
|
||||||
self._plugin._task.args = {"engine": "ansible.utils.jsonschema"}
|
self._plugin._task.args = {"engine": "ansible.utils.jsonschema"}
|
||||||
result = self._plugin.run(task_vars=None)
|
result = self._plugin.run(task_vars=None)
|
||||||
msg = "missing required arguments criteria data"
|
msg = "missing required arguments:"
|
||||||
for word in msg.split():
|
if isinstance(result["errors"], list):
|
||||||
self.assertIn(word, result["errors"])
|
self.assertIn(msg, result["errors"][0])
|
||||||
|
else:
|
||||||
|
self.assertIn(msg, result["errors"])
|
||||||
|
|
||||||
# invalid engine option value
|
# invalid engine option value
|
||||||
self._plugin._task.args = {
|
self._plugin._task.args = {
|
||||||
|
|
|
@ -112,9 +112,7 @@ class TestValidate(unittest.TestCase):
|
||||||
with self.assertRaises(AnsibleError) as error:
|
with self.assertRaises(AnsibleError) as error:
|
||||||
validate(*args, **kwargs)
|
validate(*args, **kwargs)
|
||||||
msg = "missing required arguments: criteria"
|
msg = "missing required arguments: criteria"
|
||||||
self.assertTrue(
|
self.assertIn(msg, str(error.exception))
|
||||||
set(str(error.exception).split()).issuperset(set(msg.split()))
|
|
||||||
)
|
|
||||||
|
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"criteria": CRITERIA_IN_RATE_CHECK,
|
"criteria": CRITERIA_IN_RATE_CHECK,
|
||||||
|
|
Loading…
Reference in New Issue