diff options
Diffstat (limited to 'test/integration/targets/roles_arg_spec/test_complex_role_fails.yml')
-rw-r--r-- | test/integration/targets/roles_arg_spec/test_complex_role_fails.yml | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/test/integration/targets/roles_arg_spec/test_complex_role_fails.yml b/test/integration/targets/roles_arg_spec/test_complex_role_fails.yml new file mode 100644 index 0000000..81abdaa --- /dev/null +++ b/test/integration/targets/roles_arg_spec/test_complex_role_fails.yml @@ -0,0 +1,197 @@ +--- +- name: "Running include_role test1" + hosts: localhost + gather_facts: false + vars: + ansible_unicode_type_match: "<type 'ansible.parsing.yaml.objects.AnsibleUnicode'>" + unicode_type_match: "<type 'unicode'>" + string_type_match: "<type 'str'>" + float_type_match: "<type 'float'>" + list_type_match: "<type 'list'>" + ansible_list_type_match: "<type 'ansible.parsing.yaml.objects.AnsibleSequence'>" + dict_type_match: "<type 'dict'>" + ansible_dict_type_match: "<type 'ansible.parsing.yaml.objects.AnsibleMapping'>" + ansible_unicode_class_match: "<class 'ansible.parsing.yaml.objects.AnsibleUnicode'>" + unicode_class_match: "<class 'unicode'>" + string_class_match: "<class 'str'>" + bytes_class_match: "<class 'bytes'>" + float_class_match: "<class 'float'>" + list_class_match: "<class 'list'>" + ansible_list_class_match: "<class 'ansible.parsing.yaml.objects.AnsibleSequence'>" + dict_class_match: "<class 'dict'>" + ansible_dict_class_match: "<class 'ansible.parsing.yaml.objects.AnsibleMapping'>" + expected: + test1_1: + argument_errors: [ + "argument 'tidy_expected' is of type <class 'ansible.parsing.yaml.objects.AnsibleMapping'> and we were unable to convert to list: <class 'ansible.parsing.yaml.objects.AnsibleMapping'> cannot be converted to a list", + "argument 'bust_some_stuff' is of type <class 'str'> and we were unable to convert to int: <class 'str'> cannot be converted to an int", + "argument 'some_list' is of type <class 'ansible.parsing.yaml.objects.AnsibleMapping'> and we were unable to convert to list: <class 'ansible.parsing.yaml.objects.AnsibleMapping'> cannot be converted to a list", + "argument 'some_dict' is of type <class 'ansible.parsing.yaml.objects.AnsibleSequence'> and we were unable to convert to dict: <class 'ansible.parsing.yaml.objects.AnsibleSequence'> cannot be converted to a dict", + "argument 'some_int' is of type <class 'float'> and we were unable to convert to int: <class 'float'> cannot be converted to an int", + "argument 'some_float' is of type <class 'str'> and we were unable to convert to float: <class 'str'> cannot be converted to a float", + "argument 'some_bytes' is of type <class 'bytes'> and we were unable to convert to bytes: <class 'bytes'> cannot be converted to a Byte value", + "argument 'some_bits' is of type <class 'str'> and we were unable to convert to bits: <class 'str'> cannot be converted to a Bit value", + "value of test1_choices must be one of: this paddle game, the astray, this remote control, the chair, got: My dog", + "value of some_choices must be one of: choice1, choice2, got: choice4", + "argument 'some_second_level' is of type <class 'ansible.parsing.yaml.objects.AnsibleUnicode'> found in 'some_dict_options'. and we were unable to convert to bool: The value 'not-a-bool' is not a valid boolean. ", + "argument 'third_level' is of type <class 'ansible.parsing.yaml.objects.AnsibleUnicode'> found in 'multi_level_option -> second_level'. and we were unable to convert to int: <class 'ansible.parsing.yaml.objects.AnsibleUnicode'> cannot be converted to an int", + "argument 'some_more_dict_options' is of type <class 'ansible.parsing.yaml.objects.AnsibleUnicode'> and we were unable to convert to dict: dictionary requested, could not parse JSON or key=value", + "value of 'some_more_dict_options' must be of type dict or list of dicts", + "dictionary requested, could not parse JSON or key=value", + ] + + tasks: + - name: include_role test1 since it has a arg_spec.yml + block: + - include_role: + name: test1 + vars: + tidy_expected: + some_key: some_value + test1_var1: 37.4 + test1_choices: "My dog" + bust_some_stuff: "some_string_that_is_not_an_int" + some_choices: "choice4" + some_str: 37.5 + some_list: {'a': false} + some_dict: + - "foo" + - "bar" + some_int: 37. + some_float: "notafloatisit" + some_path: "anything_is_a_valid_path" + some_raw: {"anything_can_be": "a_raw_type"} + # not sure what would be an invalid jsonarg + # some_jsonarg: "not sure what this does yet" + some_json: | + '{[1, 3, 3] 345345|45v<#!}' + some_jsonarg: | + {"foo": [1, 3, 3]} + # not sure we can load binary in safe_load + some_bytes: !!binary | + R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5 + OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+ + +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC + AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs= + some_bits: "foo" + # some_str_nicknames: [] + # some_str_akas: {} + some_str_removed_in: "foo" + some_dict_options: + some_second_level: "not-a-bool" + some_more_dict_options: "not-a-dict" + multi_level_option: + second_level: + third_level: "should_be_int" + + - fail: + msg: "Should not get here" + + rescue: + - debug: + var: ansible_failed_result + + - name: replace py version specific types with generic names so tests work on py2 and py3 + set_fact: + # We want to compare if the actual failure messages and the expected failure messages + # are the same. But to compare and do set differences, we have to handle some + # differences between py2/py3. + # The validation failure messages include python type and class reprs, which are + # different between py2 and py3. For ex, "<type 'str'>" vs "<class 'str'>". Plus + # the usual py2/py3 unicode/str/bytes type shenanigans. The 'THE_FLOAT_REPR' is + # because py3 quotes the value in the error while py2 does not, so we just ignore + # the rest of the line. + actual_generic: "{{ ansible_failed_result.argument_errors| + map('replace', ansible_unicode_type_match, 'STR')| + map('replace', unicode_type_match, 'STR')| + map('replace', string_type_match, 'STR')| + map('replace', float_type_match, 'FLOAT')| + map('replace', list_type_match, 'LIST')| + map('replace', ansible_list_type_match, 'LIST')| + map('replace', dict_type_match, 'DICT')| + map('replace', ansible_dict_type_match, 'DICT')| + map('replace', ansible_unicode_class_match, 'STR')| + map('replace', unicode_class_match, 'STR')| + map('replace', string_class_match, 'STR')| + map('replace', bytes_class_match, 'STR')| + map('replace', float_class_match, 'FLOAT')| + map('replace', list_class_match, 'LIST')| + map('replace', ansible_list_class_match, 'LIST')| + map('replace', dict_class_match, 'DICT')| + map('replace', ansible_dict_class_match, 'DICT')| + map('regex_replace', '''float:.*$''', 'THE_FLOAT_REPR')| + map('regex_replace', 'Valid booleans include.*$', '')| + list }}" + expected_generic: "{{ expected.test1_1.argument_errors| + map('replace', ansible_unicode_type_match, 'STR')| + map('replace', unicode_type_match, 'STR')| + map('replace', string_type_match, 'STR')| + map('replace', float_type_match, 'FLOAT')| + map('replace', list_type_match, 'LIST')| + map('replace', ansible_list_type_match, 'LIST')| + map('replace', dict_type_match, 'DICT')| + map('replace', ansible_dict_type_match, 'DICT')| + map('replace', ansible_unicode_class_match, 'STR')| + map('replace', unicode_class_match, 'STR')| + map('replace', string_class_match, 'STR')| + map('replace', bytes_class_match, 'STR')| + map('replace', float_class_match, 'FLOAT')| + map('replace', list_class_match, 'LIST')| + map('replace', ansible_list_class_match, 'LIST')| + map('replace', dict_class_match, 'DICT')| + map('replace', ansible_dict_class_match, 'DICT')| + map('regex_replace', '''float:.*$''', 'THE_FLOAT_REPR')| + map('regex_replace', 'Valid booleans include.*$', '')| + list }}" + + - name: figure out the difference between expected and actual validate_argument_spec failures + set_fact: + actual_not_in_expected: "{{ actual_generic| difference(expected_generic) | sort() }}" + expected_not_in_actual: "{{ expected_generic | difference(actual_generic) | sort() }}" + + - name: assert that all actual validate_argument_spec failures were in expected + assert: + that: + - actual_not_in_expected | length == 0 + msg: "Actual validate_argument_spec failures that were not expected: {{ actual_not_in_expected }}" + + - name: assert that all expected validate_argument_spec failures were in expected + assert: + that: + - expected_not_in_actual | length == 0 + msg: "Expected validate_argument_spec failures that were not in actual results: {{ expected_not_in_actual }}" + + - name: assert that `validate_args_context` return value has what we expect + assert: + that: + - ansible_failed_result.validate_args_context.argument_spec_name == "main" + - ansible_failed_result.validate_args_context.name == "test1" + - ansible_failed_result.validate_args_context.type == "role" + - "ansible_failed_result.validate_args_context.path is search('roles_arg_spec/roles/test1')" + + - name: test message for missing required parameters and invalid suboptions + block: + - include_role: + name: test1 + vars: + some_json: '{}' + some_jsonarg: '{}' + multi_level_option: + second_level: + not_a_supported_suboption: true + + - fail: + msg: "Should not get here" + + rescue: + - debug: + var: ansible_failed_result + + - assert: + that: + - ansible_failed_result.argument_errors | length == 2 + - missing_required in ansible_failed_result.argument_errors + - got_unexpected in ansible_failed_result.argument_errors + vars: + missing_required: "missing required arguments: third_level found in multi_level_option -> second_level" + got_unexpected: "multi_level_option.second_level.not_a_supported_suboption. Supported parameters include: third_level." |