diff --git a/README.md b/README.md index 3e8338d..0c1a552 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/changelogs/fragments/bugfix_ipaddr_filter.yaml b/changelogs/fragments/bugfix_ipaddr_filter.yaml new file mode 100644 index 0000000..4db67b7 --- /dev/null +++ b/changelogs/fragments/bugfix_ipaddr_filter.yaml @@ -0,0 +1,5 @@ +--- +bugfixes: + - Fix issue in ipaddr,ipv4,ipv6,ipwrap filters.(https://github.com/ansible-collections/ansible.utils/issues/148). + - ipaddr - Fix issue of breaking ipaddr filter with netcommon 2.6.0(https://github.com/ansible-collections/ansible.netcommon/issues/375). + - ipaddr - Add valid network for link-local (https://github.com/ansible-collections/ansible.netcommon/issues/350). diff --git a/docs/ansible.utils.cidr_merge_filter.rst b/docs/ansible.utils.cidr_merge_filter.rst index c13daa7..fbd8988 100644 --- a/docs/ansible.utils.cidr_merge_filter.rst +++ b/docs/ansible.utils.cidr_merge_filter.rst @@ -159,7 +159,7 @@ Common return values are documented `here data
- - + raw
diff --git a/docs/ansible.utils.ipaddr_filter.rst b/docs/ansible.utils.ipaddr_filter.rst index 69b7934..0e55624 100644 --- a/docs/ansible.utils.ipaddr_filter.rst +++ b/docs/ansible.utils.ipaddr_filter.rst @@ -78,8 +78,7 @@ Parameters value
- list - / elements=string + raw / required
@@ -302,13 +301,12 @@ Common return values are documented `here data
- list - / elements=string + raw
-
Returns list with values valid for a particular query.
+
Returns values valid for a particular query.

diff --git a/docs/ansible.utils.ipmath_filter.rst b/docs/ansible.utils.ipmath_filter.rst index 468ac6b..3bc10df 100644 --- a/docs/ansible.utils.ipmath_filter.rst +++ b/docs/ansible.utils.ipmath_filter.rst @@ -166,13 +166,12 @@ Common return values are documented `here data
- list - / elements=string + string
-
Returns list with values valid for a particular query.
+
Returns result of IP math/arithmetic.

diff --git a/docs/ansible.utils.ipsubnet_filter.rst b/docs/ansible.utils.ipsubnet_filter.rst index a790bf6..12422ca 100644 --- a/docs/ansible.utils.ipsubnet_filter.rst +++ b/docs/ansible.utils.ipsubnet_filter.rst @@ -280,13 +280,12 @@ Common return values are documented `here data
- list - / elements=string + raw
-
Returns list with values valid for a particular query.
+
Returns values valid for a particular query.

diff --git a/docs/ansible.utils.ipv4_filter.rst b/docs/ansible.utils.ipv4_filter.rst index 8f490b2..158be32 100644 --- a/docs/ansible.utils.ipv4_filter.rst +++ b/docs/ansible.utils.ipv4_filter.rst @@ -59,8 +59,7 @@ Parameters value
- list - / elements=string + raw / required
@@ -156,13 +155,12 @@ Common return values are documented `here data
- list - / elements=string + raw
-
Returns list with values valid for a particular query.
+
Returns values valid for a particular query.

diff --git a/docs/ansible.utils.ipv6_filter.rst b/docs/ansible.utils.ipv6_filter.rst index eda4835..a82f327 100644 --- a/docs/ansible.utils.ipv6_filter.rst +++ b/docs/ansible.utils.ipv6_filter.rst @@ -59,8 +59,7 @@ Parameters value
- list - / elements=string + raw / required
@@ -172,13 +171,12 @@ Common return values are documented `here data
- list - / elements=string + raw
-
Returns list with values valid for a particular query.
+
Returns values valid for a particular query.

diff --git a/docs/ansible.utils.ipwrap_filter.rst b/docs/ansible.utils.ipwrap_filter.rst index 8e4771e..dbf1619 100644 --- a/docs/ansible.utils.ipwrap_filter.rst +++ b/docs/ansible.utils.ipwrap_filter.rst @@ -60,8 +60,7 @@ Parameters value
- list - / elements=string + raw / required
@@ -170,13 +169,12 @@ Common return values are documented `here data
- list - / elements=string + raw
-
Returns list with values valid for a particular query.
+
Returns values valid for a particular query.

diff --git a/docs/ansible.utils.next_nth_usable_filter.rst b/docs/ansible.utils.next_nth_usable_filter.rst index 7d28be1..5e7616f 100644 --- a/docs/ansible.utils.next_nth_usable_filter.rst +++ b/docs/ansible.utils.next_nth_usable_filter.rst @@ -126,13 +126,12 @@ Common return values are documented `here data
- list - / elements=string + string
-
Returns list with values valid for a particular query.
+
Returns the next nth usable ip within a network described by value.

diff --git a/docs/ansible.utils.previous_nth_usable_filter.rst b/docs/ansible.utils.previous_nth_usable_filter.rst index ac2e267..3de1af9 100644 --- a/docs/ansible.utils.previous_nth_usable_filter.rst +++ b/docs/ansible.utils.previous_nth_usable_filter.rst @@ -125,13 +125,12 @@ Common return values are documented `here data
- list - / elements=string + string
-
Returns list with values valid for a particular query.
+
Returns the previous nth usable ip within a network described by value.

diff --git a/docs/ansible.utils.slaac_filter.rst b/docs/ansible.utils.slaac_filter.rst index 5f16c45..b5a0574 100644 --- a/docs/ansible.utils.slaac_filter.rst +++ b/docs/ansible.utils.slaac_filter.rst @@ -118,7 +118,7 @@ Common return values are documented `here -
Returns nth host from network
+
Returns the SLAAC address within a network for a given HW/MAC address.

diff --git a/plugins/filter/cidr_merge.py b/plugins/filter/cidr_merge.py index 29c68d6..ef4dc74 100644 --- a/plugins/filter/cidr_merge.py +++ b/plugins/filter/cidr_merge.py @@ -120,6 +120,7 @@ EXAMPLES = r""" RETURN = """ data: + type: raw description: - Returns a minified list of subnets or a single subnet that spans all of the inputs. """ diff --git a/plugins/filter/ipaddr.py b/plugins/filter/ipaddr.py index 60a9cc6..178170f 100644 --- a/plugins/filter/ipaddr.py +++ b/plugins/filter/ipaddr.py @@ -13,6 +13,7 @@ from ansible_collections.ansible.utils.plugins.plugin_utils.base.ipaddr_utils im _need_netaddr, ) from ansible.errors import AnsibleFilterError +from ansible.errors import AnsibleError from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( AnsibleArgSpecValidator, ) @@ -51,8 +52,7 @@ DOCUMENTATION = """ value: description: - list of subnets or individual address or any other values input for ipaddr plugin - type: list - elements: str + type: raw required: True query: description: @@ -240,10 +240,9 @@ EXAMPLES = r""" RETURN = """ data: - type: list - elements: str + type: raw description: - - Returns list with values valid for a particular query. + - Returns values valid for a particular query. """ @@ -253,6 +252,25 @@ def _ipaddr(*args, **kwargs): keys = ["value", "query", "version", "alias"] data = dict(zip(keys, args[1:])) data.update(kwargs) + try: + if isinstance(data["value"], str): + pass + elif isinstance(data["value"], list): + pass + else: + raise AnsibleError( + "Unrecognized type <{0}> for ipaddr filter <{1}>".format( + type(data["value"]), "value" + ) + ) + + except (TypeError, ValueError): + raise AnsibleError( + "Unrecognized type <{0}> for ipaddr filter <{1}>".format( + type(data["value"]), "value" + ) + ) + aav = AnsibleArgSpecValidator( data=data, schema=DOCUMENTATION, name="ipaddr" ) diff --git a/plugins/filter/ipmath.py b/plugins/filter/ipmath.py index 3cf50d3..a62a833 100644 --- a/plugins/filter/ipmath.py +++ b/plugins/filter/ipmath.py @@ -127,10 +127,9 @@ EXAMPLES = r""" RETURN = """ data: - type: list - elements: str + type: str description: - - Returns list with values valid for a particular query. + - Returns result of IP math/arithmetic. """ diff --git a/plugins/filter/ipsubnet.py b/plugins/filter/ipsubnet.py index 815277a..69c4170 100644 --- a/plugins/filter/ipsubnet.py +++ b/plugins/filter/ipsubnet.py @@ -231,10 +231,9 @@ tasks: RETURN = """ data: - type: list - elements: str + type: raw description: - - Returns list with values valid for a particular query. + - Returns values valid for a particular query. """ diff --git a/plugins/filter/ipv4.py b/plugins/filter/ipv4.py index 930eaf5..dff3f70 100644 --- a/plugins/filter/ipv4.py +++ b/plugins/filter/ipv4.py @@ -13,6 +13,7 @@ from ansible_collections.ansible.utils.plugins.plugin_utils.base.ipaddr_utils im _need_netaddr, ) from ansible.errors import AnsibleFilterError +from ansible.errors import AnsibleError from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( AnsibleArgSpecValidator, ) @@ -48,8 +49,7 @@ DOCUMENTATION = """ value: description: - list of subnets or individual address or any other values input for ipv4 plugin - type: list - elements: str + type: raw required: True query: description: @@ -118,10 +118,9 @@ EXAMPLES = r""" RETURN = """ data: - type: list - elements: str + type: raw description: - - Returns list with values valid for a particular query. + - Returns values valid for a particular query. """ @@ -131,6 +130,24 @@ def _ipv4(*args, **kwargs): keys = ["value", "query"] data = dict(zip(keys, args[1:])) data.update(kwargs) + try: + if isinstance(data["value"], str): + pass + elif isinstance(data["value"], list): + pass + else: + raise AnsibleError( + "Unrecognized type <{0}> for ipv4 filter <{1}>".format( + type(data["value"]), "value" + ) + ) + + except (TypeError, ValueError): + raise AnsibleError( + "Unrecognized type <{0}> for ipv4 filter <{1}>".format( + type(data["value"]), "value" + ) + ) aav = AnsibleArgSpecValidator(data=data, schema=DOCUMENTATION, name="ipv4") valid, errors, updated_data = aav.validate() if not valid: diff --git a/plugins/filter/ipv6.py b/plugins/filter/ipv6.py index b7eb206..3bf1156 100644 --- a/plugins/filter/ipv6.py +++ b/plugins/filter/ipv6.py @@ -13,6 +13,7 @@ from ansible_collections.ansible.utils.plugins.plugin_utils.base.ipaddr_utils im _need_netaddr, ) from ansible.errors import AnsibleFilterError +from ansible.errors import AnsibleError from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( AnsibleArgSpecValidator, ) @@ -50,8 +51,7 @@ DOCUMENTATION = """ value: description: - list of subnets or individual address or any other values input for ipv6 plugin - type: list - elements: str + type: raw required: True query: description: @@ -136,10 +136,9 @@ EXAMPLES = r""" RETURN = """ data: - type: list - elements: str + type: raw description: - - Returns list with values valid for a particular query. + - Returns values valid for a particular query. """ @@ -149,6 +148,24 @@ def _ipv6(*args, **kwargs): keys = ["value", "query"] data = dict(zip(keys, args[1:])) data.update(kwargs) + try: + if isinstance(data["value"], str): + pass + elif isinstance(data["value"], list): + pass + else: + raise AnsibleError( + "Unrecognized type <{0}> for ipv6 filter <{1}>".format( + type(data["value"]), "value" + ) + ) + + except (TypeError, ValueError): + raise AnsibleError( + "Unrecognized type <{0}> for ipv6 filter <{1}>".format( + type(data["value"]), "value" + ) + ) aav = AnsibleArgSpecValidator(data=data, schema=DOCUMENTATION, name="ipv6") valid, errors, updated_data = aav.validate() if not valid: diff --git a/plugins/filter/ipwrap.py b/plugins/filter/ipwrap.py index d170b93..53c575b 100644 --- a/plugins/filter/ipwrap.py +++ b/plugins/filter/ipwrap.py @@ -14,6 +14,7 @@ from ansible_collections.ansible.utils.plugins.plugin_utils.base.ipaddr_utils im _need_netaddr, ) from ansible.errors import AnsibleFilterError +from ansible.errors import AnsibleError from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( AnsibleArgSpecValidator, ) @@ -53,8 +54,7 @@ DOCUMENTATION = """ description: - list of subnets or individual address or any other values input. Example. ['192.24.2.1', 'host.fqdn', '::1', '192.168.32.0/24', 'fe80::100/10', True, '', '42540766412265424405338506004571095040/64'] - type: list - elements: str + type: raw required: True query: description: @@ -136,10 +136,9 @@ EXAMPLES = r""" RETURN = """ data: - type: list - elements: str + type: raw description: - - Returns list with values valid for a particular query. + - Returns values valid for a particular query. """ @@ -149,6 +148,26 @@ def _ipwrap(*args, **kwargs): keys = ["value"] data = dict(zip(keys, args[1:])) data.update(kwargs) + try: + if isinstance(data["value"], str): + pass + elif isinstance(data["value"], list): + pass + elif isinstance(data["value"], bool): + pass + else: + raise AnsibleError( + "Unrecognized type <{0}> for ipwrap filter <{1}>".format( + type(data["value"]), "value" + ) + ) + + except (TypeError, ValueError): + raise AnsibleError( + "Unrecognized type <{0}> for ipwrap filter <{1}>".format( + type(data["value"]), "value" + ) + ) aav = AnsibleArgSpecValidator( data=data, schema=DOCUMENTATION, name="ipwrap" ) diff --git a/plugins/filter/next_nth_usable.py b/plugins/filter/next_nth_usable.py index baaa58d..ce66070 100644 --- a/plugins/filter/next_nth_usable.py +++ b/plugins/filter/next_nth_usable.py @@ -91,10 +91,9 @@ EXAMPLES = r""" RETURN = """ data: - type: list - elements: str + type: str description: - - Returns list with values valid for a particular query. + - Returns the next nth usable ip within a network described by value. """ diff --git a/plugins/filter/previous_nth_usable.py b/plugins/filter/previous_nth_usable.py index d84eb2d..cc4f802 100644 --- a/plugins/filter/previous_nth_usable.py +++ b/plugins/filter/previous_nth_usable.py @@ -90,10 +90,9 @@ EXAMPLES = r""" RETURN = """ data: - type: list - elements: str + type: str description: - - Returns list with values valid for a particular query. + - Returns the previous nth usable ip within a network described by value. """ diff --git a/plugins/filter/slaac.py b/plugins/filter/slaac.py index 0cdf0e6..0a44c17 100644 --- a/plugins/filter/slaac.py +++ b/plugins/filter/slaac.py @@ -79,7 +79,7 @@ RETURN = """ data: type: str description: - - Returns nth host from network + - Returns the SLAAC address within a network for a given HW/MAC address. """ diff --git a/plugins/plugin_utils/base/ipaddr_utils.py b/plugins/plugin_utils/base/ipaddr_utils.py index d7d4e74..6c03720 100644 --- a/plugins/plugin_utils/base/ipaddr_utils.py +++ b/plugins/plugin_utils/base/ipaddr_utils.py @@ -199,7 +199,7 @@ def _last_usable_query(v, vtype): def _link_local_query(v, value): v_ip = netaddr.IPAddress(str(v.ip)) if v.version == 4: - if ipaddr(str(v_ip), "169.254.0.0/24"): + if ipaddr(str(v_ip), "169.254.0.0/16"): return value elif v.version == 6: diff --git a/tests/integration/targets/utils_ipaddr_filter/tasks/ipaddr.yaml b/tests/integration/targets/utils_ipaddr_filter/tasks/ipaddr.yaml index 9f172af..b609953 100644 --- a/tests/integration/targets/utils_ipaddr_filter/tasks/ipaddr.yaml +++ b/tests/integration/targets/utils_ipaddr_filter/tasks/ipaddr.yaml @@ -42,3 +42,19 @@ - name: Assert result for ipaddr network query assert: that: "{{ result4 == ipaddr_result4 }}" + +- name: ipaddr filter with network/prefix query + ansible.builtin.set_fact: + result5: "{{ '192.168.0.0/23' | ansible.utils.ipaddr('network/prefix') }}" + +- name: Assert result for ipaddr filter with network/prefix query + assert: + that: "{{ result5 == '192.168.0.0/23' }}" + +- name: ipaddr filter with chained filters + ansible.builtin.set_fact: + result6: "{{ '192.168.255.0' | ansible.utils.ipaddr('network') | ansible.utils.ipmath(123) }}" + +- name: Assert result for ipaddr filter with chained filters + assert: + that: "{{ result6 == '192.168.255.123' }}" diff --git a/tests/integration/targets/utils_ipaddr_filter/tasks/ipv4.yaml b/tests/integration/targets/utils_ipaddr_filter/tasks/ipv4.yaml index 2f7c754..b227600 100644 --- a/tests/integration/targets/utils_ipaddr_filter/tasks/ipv4.yaml +++ b/tests/integration/targets/utils_ipaddr_filter/tasks/ipv4.yaml @@ -33,3 +33,11 @@ - name: Assert result for ipv4 filter with address query. assert: that: "{{ result3 == result3_val }}" + +- name: ipv4 filter with single value + ansible.builtin.set_fact: + result4: "{{ '192.24.2.1' | ansible.utils.ipv4('ipv6') }}" + +- name: Assert result for ipv4 filter with single value + assert: + that: "{{ result4 == '::ffff:192.24.2.1/128' }}" diff --git a/tests/integration/targets/utils_ipaddr_filter/tasks/ipv6.yaml b/tests/integration/targets/utils_ipaddr_filter/tasks/ipv6.yaml index ca8a1f9..46769df 100644 --- a/tests/integration/targets/utils_ipaddr_filter/tasks/ipv6.yaml +++ b/tests/integration/targets/utils_ipaddr_filter/tasks/ipv6.yaml @@ -33,3 +33,11 @@ - name: Assert result for ipv6 filter with address query. assert: that: "{{ result3 == ipv6_result3 }}" + +- name: ipv6 filter with single value + ansible.builtin.set_fact: + result4: "{{ '::ffff:192.168.32.0/120' | ansible.utils.ipv6('ipv4') }}" + +- name: Assert result for ipv6 filter with single value + assert: + that: "{{ result4 == '192.168.32.0/24' }}" diff --git a/tests/integration/targets/utils_ipaddr_filter/tasks/ipwrap.yaml b/tests/integration/targets/utils_ipaddr_filter/tasks/ipwrap.yaml index 315a808..2cda66f 100644 --- a/tests/integration/targets/utils_ipaddr_filter/tasks/ipwrap.yaml +++ b/tests/integration/targets/utils_ipaddr_filter/tasks/ipwrap.yaml @@ -17,3 +17,11 @@ - name: Assert result for ipwrap. assert: that: "{{ result1 == ipwrap_result1 }}" + +- name: ipwrap filter with single value + ansible.builtin.set_fact: + result4: "{{ 'fe80::100/10' | ansible.utils.ipwrap }}" + +- name: Assert result for ipv6 filter with single value + assert: + that: "{{ result4 == '[fe80::100]/10' }}" diff --git a/tests/integration/targets/utils_ipaddr_filter/vars/main.yaml b/tests/integration/targets/utils_ipaddr_filter/vars/main.yaml index 39fd97c..15bc0d2 100644 --- a/tests/integration/targets/utils_ipaddr_filter/vars/main.yaml +++ b/tests/integration/targets/utils_ipaddr_filter/vars/main.yaml @@ -39,7 +39,7 @@ ipwrap_result1: - "192.168.32.0/24" - "[fe80::100]/10" - "[2001:db8:32c:faad::]/64" - - "True" + - True ipv6_result1: - "::ffff:192.168.32.0/120" diff --git a/tests/unit/plugins/filter/test_ipwrap.py b/tests/unit/plugins/filter/test_ipwrap.py index 8ff4197..c21e69e 100644 --- a/tests/unit/plugins/filter/test_ipwrap.py +++ b/tests/unit/plugins/filter/test_ipwrap.py @@ -35,7 +35,7 @@ VALID_OUTPUT = [ "192.168.32.0/24", "[fe80::100]/10", "[2001:db8:32c:faad::]/64", - "True", + True, ] @@ -55,4 +55,4 @@ class TestIpWrap(unittest.TestCase): args = ["", "::1", ""] result = _ipwrap(*args) - self.assertEqual(result, ["[::1]"]) + self.assertEqual(result, "[::1]")