diff --git a/README.md b/README.md index aa4e7d1..a4b529c 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ The Ansible ``ansible.utils`` collection includes a variety of plugins that aid This collection has been tested against following Ansible versions: **>=2.9.10**. -For collections that support Ansible 2.9, please ensure you update your `network_os` to use the -fully qualified collection name (for example, `cisco.ios.ios`). +For collections that support Ansible 2.9, please ensure you update your `network_os` to use the +fully qualified collection name (for example, `cisco.ios.ios`). Plugins and modules within a collection may be tested with only specific Ansible versions. A collection may contain metadata that identifies these versions. PEP440 is the schema used to describe the versions of Ansible. diff --git a/docs/ansible.utils.consolidate_filter.rst b/docs/ansible.utils.consolidate_filter.rst index 1b4eb22..0c75662 100644 --- a/docs/ansible.utils.consolidate_filter.rst +++ b/docs/ansible.utils.consolidate_filter.rst @@ -188,8 +188,242 @@ Examples .. code-block:: yaml - # Consolidated facts example - # -------------------------- + # Consolidated filter plugin example + # ---------------------------------- + + ##play.yml + tasks: + - name: Define some test data + ansible.builtin.set_fact: + values: + - name: a + value: 1 + - name: b + value: 2 + - name: c + value: 3 + colors: + - name: a + color: red + - name: b + color: green + - name: c + color: blue + + - name: Define some test data + ansible.builtin.set_fact: + base_data: + - data: "{{ values }}" + match_key: name + name: values + - data: "{{ colors }}" + match_key: name + name: colors + + - name: Consolidate the data source using the name key + ansible.builtin.set_fact: + consolidated: "{{ data_sources|ansible.utils.consolidate }}" + vars: + sizes: + - name: a + size: small + - name: b + size: medium + - name: c + size: large + additional_data_source: + - data: "{{ sizes }}" + match_key: name + name: sizes + data_sources: "{{ base_data + additional_data_source }}" + + ##Output + + # ok: [localhost] => { + # "ansible_facts": { + # "consolidated": { + # "a": { + # "colors": { + # "color": "red", + # "name": "a" + # }, + # "sizes": { + # "name": "a", + # "size": "small" + # }, + # "values": { + # "name": "a", + # "value": 1 + # } + # }, + # "b": { + # "colors": { + # "color": "green", + # "name": "b" + # }, + # "sizes": { + # "name": "b", + # "size": "medium" + # }, + # "values": { + # "name": "b", + # "value": 2 + # } + # }, + # "c": { + # "colors": { + # "color": "blue", + # "name": "c" + # }, + # "sizes": { + # "name": "c", + # "size": "large" + # }, + # "values": { + # "name": "c", + # "value": 3 + # } + # } + # } + # }, + # "changed": false + # } + + - name: Consolidate the data source using different keys + ansible.builtin.set_fact: + consolidated: "{{ data_sources|ansible.utils.consolidate }}" + vars: + sizes: + - title: a + size: small + - title: b + size: medium + - title: c + size: large + additional_data_source: + - data: "{{ sizes }}" + match_key: title + name: sizes + data_sources: "{{ base_data + additional_data_source }}" + + ##Output + + # ok: [localhost] => { + # "ansible_facts": { + # "consolidated": { + # "a": { + # "colors": { + # "color": "red", + # "name": "a" + # }, + # "sizes": { + # "size": "small", + # "title": "a" + # }, + # "values": { + # "name": "a", + # "value": 1 + # } + # }, + # "b": { + # "colors": { + # "color": "green", + # "name": "b" + # }, + # "sizes": { + # "size": "medium", + # "title": "b" + # }, + # "values": { + # "name": "b", + # "value": 2 + # } + # }, + # "c": { + # "colors": { + # "color": "blue", + # "name": "c" + # }, + # "sizes": { + # "size": "large", + # "title": "c" + # }, + # "values": { + # "name": "c", + # "value": 3 + # } + # } + # } + # }, + # "changed": false + # } + + - name: Consolidate the data source using the name key (fail_missing_match_key) + ansible.builtin.set_fact: + consolidated: "{{ data_sources|ansible.utils.consolidate(fail_missing_match_key=True) }}" + ignore_errors: true + vars: + vars: + sizes: + - size: small + - size: medium + - size: large + additional_data_source: + - data: "{{ sizes }}" + match_key: name + name: sizes + data_sources: "{{ base_data + additional_data_source }}" + + ##Output + + # fatal: [localhost]: FAILED! => { + # "msg": "Error when using plugin 'consolidate': 'fail_missing_match_key' + # reported missing match key 'name' in data source 3 in list entry 1, + # missing match key 'name' in data source 3 in list entry 2, + # missing match key 'name' in data source 3 in list entry 3" + # } + + - name: Consolidate the data source using the name key (fail_missing_match_value) + ansible.builtin.set_fact: + consolidated: "{{ data_sources|ansible.utils.consolidate(fail_missing_match_value=True) }}" + ignore_errors: true + vars: + sizes: + - name: a + size: small + - name: b + size: medium + additional_data_source: + - data: "{{ sizes }}" + match_key: name + name: sizes + data_sources: "{{ base_data + additional_data_source }}" + + # fatal: [localhost]: FAILED! => { + # "msg": "Error when using plugin 'consolidate': 'fail_missing_match_value' + # reported missing match value c in data source 3" + # } + + - name: Consolidate the data source using the name key (fail_duplicate) + ansible.builtin.set_fact: + consolidated: "{{ data_sources|ansible.utils.consolidate(fail_duplicate=True) }}" + ignore_errors: true + vars: + sizes: + - name: a + size: small + - name: a + size: small + additional_data_source: + - data: "{{ sizes }}" + match_key: name + name: sizes + data_sources: "{{ base_data + additional_data_source }}" + + # fatal: [localhost]: FAILED! => { + # "msg": "Error when using plugin 'consolidate': 'fail_duplicate' + # reported duplicate values in data source 3" + # } ##facts.yml diff --git a/plugins/filter/consolidate.py b/plugins/filter/consolidate.py index bd1ee83..d6f42ec 100644 --- a/plugins/filter/consolidate.py +++ b/plugins/filter/consolidate.py @@ -58,8 +58,242 @@ DOCUMENTATION = """ EXAMPLES = r""" -# Consolidated facts example -# -------------------------- +# Consolidated filter plugin example +# ---------------------------------- + +##play.yml +tasks: + - name: Define some test data + ansible.builtin.set_fact: + values: + - name: a + value: 1 + - name: b + value: 2 + - name: c + value: 3 + colors: + - name: a + color: red + - name: b + color: green + - name: c + color: blue + + - name: Define some test data + ansible.builtin.set_fact: + base_data: + - data: "{{ values }}" + match_key: name + name: values + - data: "{{ colors }}" + match_key: name + name: colors + + - name: Consolidate the data source using the name key + ansible.builtin.set_fact: + consolidated: "{{ data_sources|ansible.utils.consolidate }}" + vars: + sizes: + - name: a + size: small + - name: b + size: medium + - name: c + size: large + additional_data_source: + - data: "{{ sizes }}" + match_key: name + name: sizes + data_sources: "{{ base_data + additional_data_source }}" + +##Output + +# ok: [localhost] => { +# "ansible_facts": { +# "consolidated": { +# "a": { +# "colors": { +# "color": "red", +# "name": "a" +# }, +# "sizes": { +# "name": "a", +# "size": "small" +# }, +# "values": { +# "name": "a", +# "value": 1 +# } +# }, +# "b": { +# "colors": { +# "color": "green", +# "name": "b" +# }, +# "sizes": { +# "name": "b", +# "size": "medium" +# }, +# "values": { +# "name": "b", +# "value": 2 +# } +# }, +# "c": { +# "colors": { +# "color": "blue", +# "name": "c" +# }, +# "sizes": { +# "name": "c", +# "size": "large" +# }, +# "values": { +# "name": "c", +# "value": 3 +# } +# } +# } +# }, +# "changed": false +# } + +- name: Consolidate the data source using different keys + ansible.builtin.set_fact: + consolidated: "{{ data_sources|ansible.utils.consolidate }}" + vars: + sizes: + - title: a + size: small + - title: b + size: medium + - title: c + size: large + additional_data_source: + - data: "{{ sizes }}" + match_key: title + name: sizes + data_sources: "{{ base_data + additional_data_source }}" + +##Output + +# ok: [localhost] => { +# "ansible_facts": { +# "consolidated": { +# "a": { +# "colors": { +# "color": "red", +# "name": "a" +# }, +# "sizes": { +# "size": "small", +# "title": "a" +# }, +# "values": { +# "name": "a", +# "value": 1 +# } +# }, +# "b": { +# "colors": { +# "color": "green", +# "name": "b" +# }, +# "sizes": { +# "size": "medium", +# "title": "b" +# }, +# "values": { +# "name": "b", +# "value": 2 +# } +# }, +# "c": { +# "colors": { +# "color": "blue", +# "name": "c" +# }, +# "sizes": { +# "size": "large", +# "title": "c" +# }, +# "values": { +# "name": "c", +# "value": 3 +# } +# } +# } +# }, +# "changed": false +# } + +- name: Consolidate the data source using the name key (fail_missing_match_key) + ansible.builtin.set_fact: + consolidated: "{{ data_sources|ansible.utils.consolidate(fail_missing_match_key=True) }}" + ignore_errors: true + vars: + vars: + sizes: + - size: small + - size: medium + - size: large + additional_data_source: + - data: "{{ sizes }}" + match_key: name + name: sizes + data_sources: "{{ base_data + additional_data_source }}" + +##Output + +# fatal: [localhost]: FAILED! => { +# "msg": "Error when using plugin 'consolidate': 'fail_missing_match_key' +# reported missing match key 'name' in data source 3 in list entry 1, +# missing match key 'name' in data source 3 in list entry 2, +# missing match key 'name' in data source 3 in list entry 3" +# } + +- name: Consolidate the data source using the name key (fail_missing_match_value) + ansible.builtin.set_fact: + consolidated: "{{ data_sources|ansible.utils.consolidate(fail_missing_match_value=True) }}" + ignore_errors: true + vars: + sizes: + - name: a + size: small + - name: b + size: medium + additional_data_source: + - data: "{{ sizes }}" + match_key: name + name: sizes + data_sources: "{{ base_data + additional_data_source }}" + +# fatal: [localhost]: FAILED! => { +# "msg": "Error when using plugin 'consolidate': 'fail_missing_match_value' +# reported missing match value c in data source 3" +# } + +- name: Consolidate the data source using the name key (fail_duplicate) + ansible.builtin.set_fact: + consolidated: "{{ data_sources|ansible.utils.consolidate(fail_duplicate=True) }}" + ignore_errors: true + vars: + sizes: + - name: a + size: small + - name: a + size: small + additional_data_source: + - data: "{{ sizes }}" + match_key: name + name: sizes + data_sources: "{{ base_data + additional_data_source }}" + +# fatal: [localhost]: FAILED! => { +# "msg": "Error when using plugin 'consolidate': 'fail_duplicate' +# reported duplicate values in data source 3" +# } ##facts.yml @@ -1216,10 +1450,6 @@ from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_valid AnsibleArgSpecValidator, ) -# import debugpy - -# debugpy.listen(3000) -# debugpy.wait_for_client() try: from jinja2.filters import pass_environment except ImportError: diff --git a/plugins/plugin_utils/consolidate.py b/plugins/plugin_utils/consolidate.py index 2303c5a..242b2d4 100644 --- a/plugins/plugin_utils/consolidate.py +++ b/plugins/plugin_utils/consolidate.py @@ -55,7 +55,13 @@ def fail_on_filter(validator_func): any: Return value to the function call """ res, err = validator_func(*args, **kwargs) - if err: + if any( + [ + err.get("fail_missing_match_key"), + err.get("fail_duplicate"), + err.get("fail_missing_match_value"), + ] + ): _raise_error(err) return res diff --git a/tests/integration/inventory b/tests/integration/inventory new file mode 100644 index 0000000..646a212 --- /dev/null +++ b/tests/integration/inventory @@ -0,0 +1,2 @@ +[testgroup] +testhost ansible_connection="local" ansible_pipelining="yes" ansible_python_interpreter="/home/sagpaul/MyVnvs/dev39A212/bin/python" \ No newline at end of file diff --git a/tests/unit/plugins/filter/test_consolidate.py b/tests/unit/plugins/filter/test_consolidate.py index 222e729..8b7a4c8 100644 --- a/tests/unit/plugins/filter/test_consolidate.py +++ b/tests/unit/plugins/filter/test_consolidate.py @@ -379,7 +379,7 @@ class TestConsolidate(unittest.TestCase): with self.assertRaises(AnsibleFilterError) as error: _consolidate(*args) self.assertIn( - "Error when using plugin 'consolidate': 'fail_missing_match_key' reported Missing match key 'name' in data source 3 in list entry 1", + "Error when using plugin 'consolidate': 'fail_missing_match_key' reported missing match key 'name' in data source 3 in list entry 1", str(error.exception), ) @@ -516,6 +516,6 @@ class TestConsolidate(unittest.TestCase): with self.assertRaises(AnsibleFilterError) as error: _consolidate(*args) self.assertIn( - "Error when using plugin 'consolidate': 'fail_duplicate' reported Duplicate values in data source 3", + "Error when using plugin 'consolidate': 'fail_duplicate' reported duplicate values in data source 3", str(error.exception), )