From 86923a5f2dadcff5ef261cd5f3c338de6f60f0e7 Mon Sep 17 00:00:00 2001
From: Priyam Sahoo <42550351+priyamsahoo@users.noreply.github.com>
Date: Fri, 14 May 2021 19:31:41 +0530
Subject: [PATCH] Added 'subnet_of', 'supernet_of', 'unspecified' IP test
plugins (#73)
Added 'subnet_of', 'supernet_of', 'unspecified' IP test plugins
Reviewed-by: https://github.com/apps/ansible-zuul
---
README.md | 3 +
.../fragments/add_netaddr_test_plugins_7.yml | 3 +
docs/ansible.utils.subnet_of_test.rst | 155 +++++++++++++++++
docs/ansible.utils.supernet_of_test.rst | 155 +++++++++++++++++
docs/ansible.utils.unspecified_test.rst | 162 ++++++++++++++++++
plugins/test/subnet_of.py | 100 +++++++++++
plugins/test/supernet_of.py | 100 +++++++++++
plugins/test/unspecified.py | 121 +++++++++++++
.../netaddr_test/tasks/include/subnet_of.yml | 20 +++
.../tasks/include/supernet_of.yml | 20 +++
.../tasks/include/unspecified.yml | 28 +++
tests/unit/plugins/test/test_subnet_of.py | 48 ++++++
tests/unit/plugins/test/test_supernet_of.py | 52 ++++++
tests/unit/plugins/test/test_unspecified.py | 48 ++++++
14 files changed, 1015 insertions(+)
create mode 100644 changelogs/fragments/add_netaddr_test_plugins_7.yml
create mode 100644 docs/ansible.utils.subnet_of_test.rst
create mode 100644 docs/ansible.utils.supernet_of_test.rst
create mode 100644 docs/ansible.utils.unspecified_test.rst
create mode 100644 plugins/test/subnet_of.py
create mode 100644 plugins/test/supernet_of.py
create mode 100644 plugins/test/unspecified.py
create mode 100644 tests/integration/targets/netaddr_test/tasks/include/subnet_of.yml
create mode 100644 tests/integration/targets/netaddr_test/tasks/include/supernet_of.yml
create mode 100644 tests/integration/targets/netaddr_test/tasks/include/unspecified.yml
create mode 100644 tests/unit/plugins/test/test_subnet_of.py
create mode 100644 tests/unit/plugins/test/test_supernet_of.py
create mode 100644 tests/unit/plugins/test/test_unspecified.py
diff --git a/README.md b/README.md
index 62f87e8..3d8f788 100644
--- a/README.md
+++ b/README.md
@@ -67,6 +67,9 @@ Name | Description
[ansible.utils.private](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.private_test.rst)|Test if an IP address is private
[ansible.utils.public](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.public_test.rst)|Test if an IP address is public
[ansible.utils.reserved](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.reserved_test.rst)|Test for a reserved IP address
+[ansible.utils.subnet_of](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.subnet_of_test.rst)|Test if a network is a subnet of another network
+[ansible.utils.supernet_of](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.supernet_of_test.rst)|Test if a network is a supernet of another network
+[ansible.utils.unspecified](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.unspecified_test.rst)|Test for an unspecified IP address
[ansible.utils.validate](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.validate_test.rst)|Validate data with provided criteria
diff --git a/changelogs/fragments/add_netaddr_test_plugins_7.yml b/changelogs/fragments/add_netaddr_test_plugins_7.yml
new file mode 100644
index 0000000..eb01b0c
--- /dev/null
+++ b/changelogs/fragments/add_netaddr_test_plugins_7.yml
@@ -0,0 +1,3 @@
+---
+minor_changes:
+ - Add subnet_of, supernet_of, unspecified test plugins
diff --git a/docs/ansible.utils.subnet_of_test.rst b/docs/ansible.utils.subnet_of_test.rst
new file mode 100644
index 0000000..cd5d151
--- /dev/null
+++ b/docs/ansible.utils.subnet_of_test.rst
@@ -0,0 +1,155 @@
+.. _ansible.utils.subnet_of_test:
+
+
+***********************
+ansible.utils.subnet_of
+***********************
+
+**Test if a network is a subnet of another network**
+
+
+Version added: 2.2.0
+
+.. contents::
+ :local:
+ :depth: 1
+
+
+Synopsis
+--------
+- This plugin checks if the first network is a subnet of the second network amongst the provided network addresses
+
+
+
+
+Parameters
+----------
+
+.. raw:: html
+
+
+
+ Parameter |
+ Choices/Defaults |
+ Configuration |
+ Comments |
+
+
+
+
+ network_a
+
+
+ string
+ / required
+
+ |
+
+ |
+
+ |
+
+ A string that represents the first network address
+ {'For example': ['10.1.1.0/24']}
+ |
+
+
+
+
+ network_b
+
+
+ string
+ / required
+
+ |
+
+ |
+
+ |
+
+ A string that represents the second network address
+ {'For example': ['10.0.0.0/8']}
+ |
+
+
+
+
+
+
+
+Examples
+--------
+
+.. code-block:: yaml
+
+ - name: Check if 10.1.1.0/24 is a subnet of 10.0.0.0/8
+ ansible.builtin.set_fact:
+ data: "{{ '10.1.1.0/24' is ansible.utils.subnet_of '10.0.0.0/8' }}"
+
+ # TASK [Check if 10.1.1.0/24 is a subnet of 10.0.0.0/8] **************************
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": true
+ # },
+ # "changed": false
+ # }
+
+ - name: Check if 192.168.1.0/24 is not a subnet of 10.0.0.0/8
+ ansible.builtin.set_fact:
+ data: "{{ '192.168.1.0/24' is not ansible.utils.subnet_of '10.0.0.0/8' }}"
+
+ # TASK [Check if 192.168.1.0/24 is not a subnet of 10.0.0.0/8] *******************
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": true
+ # },
+ # "changed": false
+ # }
+
+
+
+Return Values
+-------------
+Common return values are documented `here `_, the following are the fields unique to this test:
+
+.. raw:: html
+
+
+
+ Key |
+ Returned |
+ Description |
+
+
+
+
+ data
+
+
+ -
+
+ |
+ |
+
+ If jinja test satisfies plugin expression true
+ If jinja test does not satisfy plugin expression false
+
+ |
+
+
+
+
+
+Status
+------
+
+
+Authors
+~~~~~~~
+
+- Priyam Sahoo (@priyamsahoo)
+
+
+.. hint::
+ Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.
diff --git a/docs/ansible.utils.supernet_of_test.rst b/docs/ansible.utils.supernet_of_test.rst
new file mode 100644
index 0000000..2b9b4ec
--- /dev/null
+++ b/docs/ansible.utils.supernet_of_test.rst
@@ -0,0 +1,155 @@
+.. _ansible.utils.supernet_of_test:
+
+
+*************************
+ansible.utils.supernet_of
+*************************
+
+**Test if a network is a supernet of another network**
+
+
+Version added: 2.2.0
+
+.. contents::
+ :local:
+ :depth: 1
+
+
+Synopsis
+--------
+- This plugin checks if the first network is a supernet of the second network amongst the provided network addresses
+
+
+
+
+Parameters
+----------
+
+.. raw:: html
+
+
+
+ Parameter |
+ Choices/Defaults |
+ Configuration |
+ Comments |
+
+
+
+
+ network_a
+
+
+ string
+ / required
+
+ |
+
+ |
+
+ |
+
+ A string that represents the first network address
+ {'For example': ['10.1.1.0/24']}
+ |
+
+
+
+
+ network_b
+
+
+ string
+ / required
+
+ |
+
+ |
+
+ |
+
+ A string that represents the second network address
+ {'For example': ['10.0.0.0/8']}
+ |
+
+
+
+
+
+
+
+Examples
+--------
+
+.. code-block:: yaml
+
+ - name: Check if 10.0.0.0/8 is a supernet of 10.1.1.0/24
+ ansible.builtin.set_fact:
+ data: "{{ '10.0.0.0/8' is ansible.utils.supernet_of '10.1.1.0/24' }}"
+
+ # TASK [Check if 10.0.0.0/8 is a supernet of 10.1.1.0/24] ************************
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": true
+ # },
+ # "changed": false
+ # }
+
+ - name: Check if 10.0.0.0/8 is not a supernet of 192.168.1.0/24
+ ansible.builtin.set_fact:
+ data: "{{ '10.0.0.0/8' is not ansible.utils.supernet_of '192.168.1.0/24' }}"
+
+ # TASK [Check if 10.0.0.0/8 is not a supernet of 192.168.1.0/24] *****************
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": true
+ # },
+ # "changed": false
+ # }
+
+
+
+Return Values
+-------------
+Common return values are documented `here `_, the following are the fields unique to this test:
+
+.. raw:: html
+
+
+
+ Key |
+ Returned |
+ Description |
+
+
+
+
+ data
+
+
+ -
+
+ |
+ |
+
+ If jinja test satisfies plugin expression true
+ If jinja test does not satisfy plugin expression false
+
+ |
+
+
+
+
+
+Status
+------
+
+
+Authors
+~~~~~~~
+
+- Priyam Sahoo (@priyamsahoo)
+
+
+.. hint::
+ Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.
diff --git a/docs/ansible.utils.unspecified_test.rst b/docs/ansible.utils.unspecified_test.rst
new file mode 100644
index 0000000..ef93539
--- /dev/null
+++ b/docs/ansible.utils.unspecified_test.rst
@@ -0,0 +1,162 @@
+.. _ansible.utils.unspecified_test:
+
+
+*************************
+ansible.utils.unspecified
+*************************
+
+**Test for an unspecified IP address**
+
+
+Version added: 2.2.0
+
+.. contents::
+ :local:
+ :depth: 1
+
+
+Synopsis
+--------
+- This plugin checks if the provided value is an unspecified IP address
+
+
+
+
+Parameters
+----------
+
+.. raw:: html
+
+
+
+ Parameter |
+ Choices/Defaults |
+ Configuration |
+ Comments |
+
+
+
+
+ ip
+
+
+ string
+ / required
+
+ |
+
+ |
+
+ |
+
+ A string that represents the value against which the test is going to be performed
+ {'For example': ['0.0.0.0', '0:0:0:0:0:0:0:0', '::', '::1']}
+ |
+
+
+
+
+
+
+
+Examples
+--------
+
+.. code-block:: yaml
+
+ #### Simple examples
+
+ - name: Check if 0.0.0.0 is an unspecified IP address
+ ansible.builtin.set_fact:
+ data: "{{ '0.0.0.0' is ansible.utils.unspecified }}"
+
+ # TASK [Check if 0.0.0.0 is an unspecified IP address] ***************************
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": true
+ # },
+ # "changed": false
+ # }
+
+ - name: Check if 0:0:0:0:0:0:0:0 is an unspecified IP address
+ ansible.builtin.set_fact:
+ data: "{{ '0:0:0:0:0:0:0:0' is ansible.utils.unspecified }}"
+
+ # TASK [Check if 0:0:0:0:0:0:0:0 is an unspecified IP address] *******************
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": true
+ # },
+ # "changed": false
+ # }
+
+ - name: Check if "::" is an unspecified IP address
+ ansible.builtin.set_fact:
+ data: "{{ '::' is ansible.utils.unspecified }}"
+
+ # TASK [Check if "::" is an unspecified IP address] ******************************
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": true
+ # },
+ # "changed": false
+ # }
+
+ - name: Check if ::1 is not an unspecified IP address
+ ansible.builtin.set_fact:
+ data: "{{ '::1' is not ansible.utils.unspecified }}"
+
+ # TASK [Check if ::1 is not an unspecified IP address] ***************************
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": true
+ # },
+ # "changed": false
+ # }
+
+
+
+Return Values
+-------------
+Common return values are documented `here `_, the following are the fields unique to this test:
+
+.. raw:: html
+
+
+
+ Key |
+ Returned |
+ Description |
+
+
+
+
+ data
+
+
+ -
+
+ |
+ |
+
+ If jinja test satisfies plugin expression true
+ If jinja test does not satisfy plugin expression false
+
+ |
+
+
+
+
+
+Status
+------
+
+
+Authors
+~~~~~~~
+
+- Priyam Sahoo (@priyamsahoo)
+
+
+.. hint::
+ Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.
diff --git a/plugins/test/subnet_of.py b/plugins/test/subnet_of.py
new file mode 100644
index 0000000..3b08746
--- /dev/null
+++ b/plugins/test/subnet_of.py
@@ -0,0 +1,100 @@
+# -*- coding: utf-8 -*-
+# Copyright 2021 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+"""
+Test plugin file for netaddr tests: subnet_of
+"""
+
+from __future__ import absolute_import, division, print_function
+from ansible_collections.ansible.utils.plugins.plugin_utils.base.ipaddress_utils import (
+ ip_network,
+ _need_ipaddress,
+ _is_subnet_of,
+ _validate_args,
+)
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+ name: subnet_of
+ author: Priyam Sahoo (@priyamsahoo)
+ version_added: "2.2.0"
+ short_description: Test if a network is a subnet of another network
+ description:
+ - This plugin checks if the first network is a subnet of the second network amongst the provided network addresses
+ options:
+ network_a:
+ description:
+ - A string that represents the first network address
+ - For example:
+ - "10.1.1.0/24"
+ type: str
+ required: True
+ network_b:
+ description:
+ - A string that represents the second network address
+ - For example:
+ - "10.0.0.0/8"
+ type: str
+ required: True
+ notes:
+"""
+
+EXAMPLES = r"""
+
+- name: Check if 10.1.1.0/24 is a subnet of 10.0.0.0/8
+ ansible.builtin.set_fact:
+ data: "{{ '10.1.1.0/24' is ansible.utils.subnet_of '10.0.0.0/8' }}"
+
+# TASK [Check if 10.1.1.0/24 is a subnet of 10.0.0.0/8] **************************
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": true
+# },
+# "changed": false
+# }
+
+- name: Check if 192.168.1.0/24 is not a subnet of 10.0.0.0/8
+ ansible.builtin.set_fact:
+ data: "{{ '192.168.1.0/24' is not ansible.utils.subnet_of '10.0.0.0/8' }}"
+
+# TASK [Check if 192.168.1.0/24 is not a subnet of 10.0.0.0/8] *******************
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": true
+# },
+# "changed": false
+# }
+
+"""
+
+RETURN = """
+ data:
+ description:
+ - If jinja test satisfies plugin expression C(true)
+ - If jinja test does not satisfy plugin expression C(false)
+"""
+
+
+@_need_ipaddress
+def _subnet_of(network_a, network_b):
+ """ Test if a network is a subnet of another network """
+
+ params = {"network_a": network_a, "network_b": network_b}
+ _validate_args("subnet_of", DOCUMENTATION, params)
+
+ try:
+ return _is_subnet_of(ip_network(network_a), ip_network(network_b))
+ except Exception:
+ return False
+
+
+class TestModule(object):
+ """ network jinja test """
+
+ test_map = {"subnet_of": _subnet_of}
+
+ def tests(self):
+ return self.test_map
diff --git a/plugins/test/supernet_of.py b/plugins/test/supernet_of.py
new file mode 100644
index 0000000..bbb5e3c
--- /dev/null
+++ b/plugins/test/supernet_of.py
@@ -0,0 +1,100 @@
+# -*- coding: utf-8 -*-
+# Copyright 2021 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+"""
+Test plugin file for netaddr tests: supernet_of
+"""
+
+from __future__ import absolute_import, division, print_function
+from ansible_collections.ansible.utils.plugins.plugin_utils.base.ipaddress_utils import (
+ ip_network,
+ _need_ipaddress,
+ _is_subnet_of,
+ _validate_args,
+)
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+ name: supernet_of
+ author: Priyam Sahoo (@priyamsahoo)
+ version_added: "2.2.0"
+ short_description: Test if a network is a supernet of another network
+ description:
+ - This plugin checks if the first network is a supernet of the second network amongst the provided network addresses
+ options:
+ network_a:
+ description:
+ - A string that represents the first network address
+ - For example:
+ - "10.1.1.0/24"
+ type: str
+ required: True
+ network_b:
+ description:
+ - A string that represents the second network address
+ - For example:
+ - "10.0.0.0/8"
+ type: str
+ required: True
+ notes:
+"""
+
+EXAMPLES = r"""
+
+- name: Check if 10.0.0.0/8 is a supernet of 10.1.1.0/24
+ ansible.builtin.set_fact:
+ data: "{{ '10.0.0.0/8' is ansible.utils.supernet_of '10.1.1.0/24' }}"
+
+# TASK [Check if 10.0.0.0/8 is a supernet of 10.1.1.0/24] ************************
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": true
+# },
+# "changed": false
+# }
+
+- name: Check if 10.0.0.0/8 is not a supernet of 192.168.1.0/24
+ ansible.builtin.set_fact:
+ data: "{{ '10.0.0.0/8' is not ansible.utils.supernet_of '192.168.1.0/24' }}"
+
+# TASK [Check if 10.0.0.0/8 is not a supernet of 192.168.1.0/24] *****************
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": true
+# },
+# "changed": false
+# }
+
+"""
+
+RETURN = """
+ data:
+ description:
+ - If jinja test satisfies plugin expression C(true)
+ - If jinja test does not satisfy plugin expression C(false)
+"""
+
+
+@_need_ipaddress
+def _supernet_of(network_a, network_b):
+ """ Test if an network is a supernet of another network """
+
+ params = {"network_a": network_a, "network_b": network_b}
+ _validate_args("supernet_of", DOCUMENTATION, params)
+
+ try:
+ return _is_subnet_of(ip_network(network_b), ip_network(network_a))
+ except Exception:
+ return False
+
+
+class TestModule(object):
+ """ network jinja test """
+
+ test_map = {"supernet_of": _supernet_of}
+
+ def tests(self):
+ return self.test_map
diff --git a/plugins/test/unspecified.py b/plugins/test/unspecified.py
new file mode 100644
index 0000000..6e79e9e
--- /dev/null
+++ b/plugins/test/unspecified.py
@@ -0,0 +1,121 @@
+# -*- coding: utf-8 -*-
+# Copyright 2021 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+"""
+Test plugin file for netaddr tests: unspecified
+"""
+
+from __future__ import absolute_import, division, print_function
+from ansible_collections.ansible.utils.plugins.plugin_utils.base.ipaddress_utils import (
+ ip_address,
+ _need_ipaddress,
+ _validate_args,
+)
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+ name: unspecified
+ author: Priyam Sahoo (@priyamsahoo)
+ version_added: "2.2.0"
+ short_description: Test for an unspecified IP address
+ description:
+ - This plugin checks if the provided value is an unspecified IP address
+ options:
+ ip:
+ description:
+ - A string that represents the value against which the test is going to be performed
+ - For example:
+ - "0.0.0.0"
+ - "0:0:0:0:0:0:0:0"
+ - "::"
+ - "::1"
+ type: str
+ required: True
+ notes:
+"""
+
+EXAMPLES = r"""
+
+#### Simple examples
+
+- name: Check if 0.0.0.0 is an unspecified IP address
+ ansible.builtin.set_fact:
+ data: "{{ '0.0.0.0' is ansible.utils.unspecified }}"
+
+# TASK [Check if 0.0.0.0 is an unspecified IP address] ***************************
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": true
+# },
+# "changed": false
+# }
+
+- name: Check if 0:0:0:0:0:0:0:0 is an unspecified IP address
+ ansible.builtin.set_fact:
+ data: "{{ '0:0:0:0:0:0:0:0' is ansible.utils.unspecified }}"
+
+# TASK [Check if 0:0:0:0:0:0:0:0 is an unspecified IP address] *******************
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": true
+# },
+# "changed": false
+# }
+
+- name: Check if "::" is an unspecified IP address
+ ansible.builtin.set_fact:
+ data: "{{ '::' is ansible.utils.unspecified }}"
+
+# TASK [Check if "::" is an unspecified IP address] ******************************
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": true
+# },
+# "changed": false
+# }
+
+- name: Check if ::1 is not an unspecified IP address
+ ansible.builtin.set_fact:
+ data: "{{ '::1' is not ansible.utils.unspecified }}"
+
+# TASK [Check if ::1 is not an unspecified IP address] ***************************
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": true
+# },
+# "changed": false
+# }
+
+"""
+
+RETURN = """
+ data:
+ description:
+ - If jinja test satisfies plugin expression C(true)
+ - If jinja test does not satisfy plugin expression C(false)
+"""
+
+
+@_need_ipaddress
+def _unspecified(ip):
+ """ Test for an unspecified IP address """
+
+ params = {"ip": ip}
+ _validate_args("unspecified", DOCUMENTATION, params)
+
+ try:
+ return ip_address(ip).is_unspecified
+ except Exception:
+ return False
+
+
+class TestModule(object):
+ """ network jinja test"""
+
+ test_map = {"unspecified": _unspecified}
+
+ def tests(self):
+ return self.test_map
diff --git a/tests/integration/targets/netaddr_test/tasks/include/subnet_of.yml b/tests/integration/targets/netaddr_test/tasks/include/subnet_of.yml
new file mode 100644
index 0000000..a59b12a
--- /dev/null
+++ b/tests/integration/targets/netaddr_test/tasks/include/subnet_of.yml
@@ -0,0 +1,20 @@
+---
+- name: "subnet_of: Check if 10.1.1.0/24 is a subnet of 10.0.0.0/8"
+ assert:
+ that: "{{ '10.1.1.0/24' is ansible.utils.subnet_of '10.0.0.0/8' }}"
+
+- name: "subnet_of: Test invalidness"
+ ansible.builtin.set_fact:
+ criteria_check1: "{{ '10.0.0.0/8' is ansible.utils.subnet_of '10.1.1.0/24' }}"
+
+- name: "subnet_of: Assert invalidness"
+ assert:
+ that: "{{ criteria_check1 == false }}"
+
+- name: "subnet_of: Test invalidness"
+ ansible.builtin.set_fact:
+ criteria_check2: "{{ '192.168.1.0/24' is ansible.utils.subnet_of '10.0.0.0/8' }}"
+
+- name: "subnet_of: Assert invalidness"
+ assert:
+ that: "{{ criteria_check2 == false }}"
diff --git a/tests/integration/targets/netaddr_test/tasks/include/supernet_of.yml b/tests/integration/targets/netaddr_test/tasks/include/supernet_of.yml
new file mode 100644
index 0000000..8e5ce26
--- /dev/null
+++ b/tests/integration/targets/netaddr_test/tasks/include/supernet_of.yml
@@ -0,0 +1,20 @@
+---
+- name: "supernet_of: Check if 10.0.0.0/8 is a supernet of 10.1.1.0/24"
+ assert:
+ that: "{{ '10.0.0.0/8' is ansible.utils.supernet_of '10.1.1.0/24' }}"
+
+- name: "supernet_of: Test invalidness"
+ ansible.builtin.set_fact:
+ criteria_check1: "{{ '10.1.1.0/24' is ansible.utils.supernet_of '10.0.0.0/8' }}"
+
+- name: "supernet_of: Assert invalidness"
+ assert:
+ that: "{{ criteria_check1 == false }}"
+
+- name: "supernet_of: Test invalidness"
+ ansible.builtin.set_fact:
+ criteria_check2: "{{ '10.0.0.0/8' is ansible.utils.supernet_of '192.168.1.0/24' }}"
+
+- name: "supernet_of: Assert invalidness"
+ assert:
+ that: "{{ criteria_check2 == false }}"
diff --git a/tests/integration/targets/netaddr_test/tasks/include/unspecified.yml b/tests/integration/targets/netaddr_test/tasks/include/unspecified.yml
new file mode 100644
index 0000000..d371a5d
--- /dev/null
+++ b/tests/integration/targets/netaddr_test/tasks/include/unspecified.yml
@@ -0,0 +1,28 @@
+---
+- name: "unspecified: Check if 0.0.0.0 is an unspecified IP address"
+ assert:
+ that: "{{ '0.0.0.0' is ansible.utils.unspecified }}"
+
+- name: "unspecified: Check if 0:0:0:0:0:0:0:0 is an unspecified IP address"
+ assert:
+ that: "{{ '0:0:0:0:0:0:0:0' is ansible.utils.unspecified }}"
+
+- name: "unspecified: Check if :: is an unspecified IP address"
+ assert:
+ that: "{{ '::' is ansible.utils.unspecified }}"
+
+- name: "unspecified: Test invalidness"
+ ansible.builtin.set_fact:
+ criteria_check1: "{{ '127.0.0.1' is ansible.utils.unspecified }}"
+
+- name: "unspecified: Assert invalidness"
+ assert:
+ that: "{{ criteria_check1 == false }}"
+
+- name: "unspecified: Test invalidness"
+ ansible.builtin.set_fact:
+ criteria_check2: "{{ '::1' is ansible.utils.unspecified }}"
+
+- name: "unspecified: Assert invalidness"
+ assert:
+ that: "{{ criteria_check2 == false }}"
diff --git a/tests/unit/plugins/test/test_subnet_of.py b/tests/unit/plugins/test/test_subnet_of.py
new file mode 100644
index 0000000..3d6b487
--- /dev/null
+++ b/tests/unit/plugins/test/test_subnet_of.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+# Copyright 2021 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+"""
+Unit test file for netaddr test plugin: subnet_of
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import unittest
+from ansible_collections.ansible.utils.plugins.test.subnet_of import _subnet_of
+
+
+class TestSubnetOf(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def test_invalid_data(self):
+ """Check passing invalid argspec"""
+
+ # missing argument
+ with self.assertRaises(TypeError) as error:
+ _subnet_of()
+ self.assertIn("argument", str(error.exception))
+
+ with self.assertRaises(TypeError) as error:
+ _subnet_of(network_a="10.1.1.0/24")
+ self.assertIn("argument", str(error.exception))
+
+ with self.assertRaises(TypeError) as error:
+ _subnet_of(network_b="10.0.0.0/8")
+ self.assertIn("argument", str(error.exception))
+
+ def test_valid_data(self):
+ """Check passing valid data as per criteria"""
+
+ result = _subnet_of(network_a="10.1.1.0/24", network_b="10.0.0.0/8")
+ self.assertEqual(result, True)
+
+ result = _subnet_of(network_a="10.0.0.0/8", network_b="10.1.1.0/24")
+ self.assertEqual(result, False)
+
+ result = _subnet_of(network_a="192.168.1.0/24", network_b="10.0.0.0/8")
+ self.assertEqual(result, False)
diff --git a/tests/unit/plugins/test/test_supernet_of.py b/tests/unit/plugins/test/test_supernet_of.py
new file mode 100644
index 0000000..fcffc7e
--- /dev/null
+++ b/tests/unit/plugins/test/test_supernet_of.py
@@ -0,0 +1,52 @@
+# -*- coding: utf-8 -*-
+# Copyright 2021 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+"""
+Unit test file for netaddr test plugin: supernet_of
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import unittest
+from ansible_collections.ansible.utils.plugins.test.supernet_of import (
+ _supernet_of,
+)
+
+
+class TestSupernetOf(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def test_invalid_data(self):
+ """Check passing invalid argspec"""
+
+ # missing argument
+ with self.assertRaises(TypeError) as error:
+ _supernet_of()
+ self.assertIn("argument", str(error.exception))
+
+ with self.assertRaises(TypeError) as error:
+ _supernet_of(network_a="10.0.0.0/8")
+ self.assertIn("argument", str(error.exception))
+
+ with self.assertRaises(TypeError) as error:
+ _supernet_of(network_b="10.1.1.0/24")
+ self.assertIn("argument", str(error.exception))
+
+ def test_valid_data(self):
+ """Check passing valid data as per criteria"""
+
+ result = _supernet_of(network_a="10.0.0.0/8", network_b="10.1.1.0/24")
+ self.assertEqual(result, True)
+
+ result = _supernet_of(network_a="10.1.1.0/24", network_b="10.0.0.0/8")
+ self.assertEqual(result, False)
+
+ result = _supernet_of(
+ network_a="10.0.0.0/8", network_b="192.168.1.0/24"
+ )
+ self.assertEqual(result, False)
diff --git a/tests/unit/plugins/test/test_unspecified.py b/tests/unit/plugins/test/test_unspecified.py
new file mode 100644
index 0000000..6a08f14
--- /dev/null
+++ b/tests/unit/plugins/test/test_unspecified.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+# Copyright 2021 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+"""
+Unit test file for netaddr test plugin: unspecified
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import unittest
+from ansible_collections.ansible.utils.plugins.test.unspecified import (
+ _unspecified,
+)
+
+
+class TestUnspecified(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def test_invalid_data(self):
+ """Check passing invalid argspec"""
+
+ # missing argument
+ with self.assertRaises(TypeError) as error:
+ _unspecified()
+ self.assertIn("argument", str(error.exception))
+
+ def test_valid_data(self):
+ """Check passing valid data as per criteria"""
+
+ result = _unspecified(ip="0.0.0.0")
+ self.assertEqual(result, True)
+
+ result = _unspecified(ip="0:0:0:0:0:0:0:0")
+ self.assertEqual(result, True)
+
+ result = _unspecified(ip="::")
+ self.assertEqual(result, True)
+
+ result = _unspecified(ip="127.0.0.1")
+ self.assertEqual(result, False)
+
+ result = _unspecified(ip="::1")
+ self.assertEqual(result, False)