fix: netaddr fallback to is_private when is_global is not available (#348)

* fix: netaddr fallback to is_private when is_global is not available

* fix: adjust fallback logic to edge cases

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix: address pylint errors

* fix: comment spacing in test task broken by prettier

* changelog update

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: Marcin Lewandowski <mlewandowski@pl.ibm.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Ruchi Pakhle <ruchipakhle@gmail.com>
pull/350/head
Marcin Lewandowski 2024-04-15 12:41:26 +02:00 committed by GitHub
parent b0627b8d16
commit fc3a2a116b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 74 additions and 3 deletions

View File

@ -0,0 +1,5 @@
---
minor_changes:
- Implemented fallback to the IPAddress.is_private() method in cases where IPAddress.is_global() is not available. This adjustment ensures compatibility with netaddr versions older than 0.10.0.
- With the release of netaddr 1.0 (on 2024-02-10), the IPAddress.is_private() method was removed. Consequently, ansible.utils < 4.0 is only compatible with netaddr < 1.0, while ansible.utils >= 4.0 requires netaddr >= 0.10.1.
- To address compatibility issues with older netaddr versions, this pull request introduces backward compatibility by reverting to IPAddress.is_private() when IPAddress.is_global() is unavailable. This ensures smooth operation with netaddr versions prior to 0.10.0.

View File

@ -288,8 +288,42 @@ def _previous_usable_query(v, vtype):
return str(netaddr.IPAddress(int(v.ip) - 1))
def _ip_is_global(ip):
# fallback to support netaddr < 1.0.0
# attempt to emulate IPAddress.is_global() if it's not available
# note that there still might be some behavior differences (e.g. exceptions)
has_is_global = callable(getattr(ip, "is_global", None))
return (
ip.is_global()
if has_is_global
else (
not (ip.is_private() or ip.is_link_local() or ip.is_reserved())
and all(
ip not in netaddr.IPNetwork(ipv6net)
for ipv6net in [
"::1/128",
"::/128",
"::ffff:0:0/96",
"64:ff9b:1::/48",
"100::/64",
"2001::/23",
"2001:db8::/32",
"2002::/16",
]
)
or ip in netaddr.IPRange("239.0.0.0", "239.255.255.255") # Administrative Multicast
or ip in netaddr.IPNetwork("233.252.0.0/24") # Multicast test network
or ip in netaddr.IPRange("234.0.0.0", "238.255.255.255")
or ip in netaddr.IPRange("225.0.0.0", "231.255.255.255")
or ip in netaddr.IPNetwork("192.88.99.0/24") # 6to4 anycast relays (RFC 3068)
or ip in netaddr.IPNetwork("192.0.0.9/32")
or ip in netaddr.IPNetwork("192.0.0.10/32")
)
)
def _private_query(v, value):
if not v.ip.is_global():
if not _ip_is_global(v.ip):
return value
@ -298,7 +332,7 @@ def _public_query(v, value):
if all(
[
v_ip.is_unicast(),
v_ip.is_global(),
_ip_is_global(v_ip),
not v_ip.is_loopback(),
not v_ip.is_netmask(),
not v_ip.is_hostmask(),

View File

@ -10,6 +10,22 @@
- "42540766412265424405338506004571095040/64"
- true
- name: Set ipaddress list for private/public test
ansible.builtin.set_fact:
value_private_public: "{{ value + value_private_public_additional }}"
vars:
value_private_public_additional:
# valid private subnet address
- 172.16.0.1
# exception: globally reachable address
- 192.0.0.9
# multicast test network: considered global in netaddr
- 233.252.0.1
- 234.0.0.1
# administrative multicast: considered global in netaddr
- 225.0.0.1
- 239.0.0.1
- name: Ipaddr filter with empty string query
ansible.builtin.set_fact:
result1: "{{ value | ansible.utils.ipaddr }}"
@ -28,12 +44,20 @@
- name: Ipaddr filter with public network query
ansible.builtin.set_fact:
result3: "{{ value | ansible.utils.ipaddr('public') }}"
result3: "{{ value_private_public | ansible.utils.ipaddr('public') }}"
- name: Assert result for ipaddr public network query
ansible.builtin.assert:
that: "{{ result3 == ipaddr_result3 }}"
- name: Ipaddr filter with private network query
ansible.builtin.set_fact:
result_private: "{{ value_private_public | ansible.utils.ipaddr('private') }}"
- name: Assert result for ipaddr private network query
ansible.builtin.assert:
that: "{{ result_private == ipaddr_result_private }}"
- name: Ipaddr filter with network query
ansible.builtin.set_fact:
result4: "{{ value | ansible.utils.ipaddr('net') }}"

View File

@ -26,11 +26,19 @@ ipaddr_result2:
ipaddr_result3:
- 192.24.2.1
- 192.0.0.9
ipaddr_result4:
- 192.168.32.0/24
- 2001:db8:32c:faad::/64
ipaddr_result_private:
- ::1
- 192.168.32.0/24
- fe80::100/10
- 2001:db8:32c:faad::/64
- 172.16.0.1
ipwrap_result1:
- "192.24.2.1"
- "host.fqdn"