From c09bbacdbc1953cdd020579d360d024cf46fe657 Mon Sep 17 00:00:00 2001
From: Priyam Sahoo <42550351+priyamsahoo@users.noreply.github.com>
Date: Mon, 3 May 2021 19:52:35 +0530
Subject: [PATCH] Added 'in_any_network', 'in_network', 'in_one_network' test
plugins (#66)
Added 'in_any_network', 'in_network', 'in_one_network' test plugins
Reviewed-by: https://github.com/apps/ansible-zuul
---
README.md | 3 +
.../fragments/add_netaddr_test_plugins_1.yml | 3 +
docs/ansible.utils.in_any_network_test.rst | 170 ++++++++++++++++
docs/ansible.utils.in_network_test.rst | 183 ++++++++++++++++++
docs/ansible.utils.in_one_network_test.rst | 168 ++++++++++++++++
plugins/plugin_utils/base/ipaddress_utils.py | 86 ++++++++
plugins/test/in_any_network.py | 112 +++++++++++
plugins/test/in_network.py | 128 ++++++++++++
plugins/test/in_one_network.py | 111 +++++++++++
test-requirements.txt | 1 +
.../tasks/include/in_any_network.yml | 17 ++
.../netaddr_test/tasks/include/in_network.yml | 33 ++++
.../tasks/include/in_one_network.yml | 16 ++
.../targets/netaddr_test/tasks/main.yaml | 13 ++
.../targets/netaddr_test/vars/main.yaml | 5 +
.../unit/plugins/test/test_in_any_network.py | 50 +++++
tests/unit/plugins/test/test_in_network.py | 45 +++++
.../unit/plugins/test/test_in_one_network.py | 50 +++++
18 files changed, 1194 insertions(+)
create mode 100644 changelogs/fragments/add_netaddr_test_plugins_1.yml
create mode 100644 docs/ansible.utils.in_any_network_test.rst
create mode 100644 docs/ansible.utils.in_network_test.rst
create mode 100644 docs/ansible.utils.in_one_network_test.rst
create mode 100644 plugins/plugin_utils/base/ipaddress_utils.py
create mode 100644 plugins/test/in_any_network.py
create mode 100644 plugins/test/in_network.py
create mode 100644 plugins/test/in_one_network.py
create mode 100644 tests/integration/targets/netaddr_test/tasks/include/in_any_network.yml
create mode 100644 tests/integration/targets/netaddr_test/tasks/include/in_network.yml
create mode 100644 tests/integration/targets/netaddr_test/tasks/include/in_one_network.yml
create mode 100644 tests/integration/targets/netaddr_test/tasks/main.yaml
create mode 100644 tests/integration/targets/netaddr_test/vars/main.yaml
create mode 100644 tests/unit/plugins/test/test_in_any_network.py
create mode 100644 tests/unit/plugins/test/test_in_network.py
create mode 100644 tests/unit/plugins/test/test_in_one_network.py
diff --git a/README.md b/README.md
index f67ddfe..2bf1be3 100644
--- a/README.md
+++ b/README.md
@@ -47,6 +47,9 @@ Name | Description
### Test plugins
Name | Description
--- | ---
+[ansible.utils.in_any_network](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.in_any_network_test.rst)|Test if Test if an IP or network falls in any network
+[ansible.utils.in_network](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.in_network_test.rst)|Test if IP address falls in the network
+[ansible.utils.in_one_network](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.in_one_network_test.rst)|Test if IP address belongs in any one of the networks in the list
[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_1.yml b/changelogs/fragments/add_netaddr_test_plugins_1.yml
new file mode 100644
index 0000000..95f1ed1
--- /dev/null
+++ b/changelogs/fragments/add_netaddr_test_plugins_1.yml
@@ -0,0 +1,3 @@
+---
+minor_changes:
+ - Add in_any_network, in_network, in_one_network test plugins
diff --git a/docs/ansible.utils.in_any_network_test.rst b/docs/ansible.utils.in_any_network_test.rst
new file mode 100644
index 0000000..43c804c
--- /dev/null
+++ b/docs/ansible.utils.in_any_network_test.rst
@@ -0,0 +1,170 @@
+.. _ansible.utils.in_any_network_test:
+
+
+****************************
+ansible.utils.in_any_network
+****************************
+
+**Test if Test if an IP or network falls in any network**
+
+
+Version added: 2.2.0
+
+.. contents::
+ :local:
+ :depth: 1
+
+
+Synopsis
+--------
+- This plugin checks if the provided IP or network address belongs to the provided list network addresses
+
+
+
+
+Parameters
+----------
+
+.. raw:: html
+
+
+
+ Parameter |
+ Choices/Defaults |
+ Configuration |
+ Comments |
+
+
+
+
+ ip
+
+
+ string
+ / required
+
+ |
+
+ |
+
+ |
+
+ A string that represents an IP address of a host or network
+ {'For example': '10.1.1.1'}
+ |
+
+
+
+
+ networks
+
+
+ list
+ / required
+
+ |
+
+ |
+
+ |
+
+ A list of string and each string represents a network address in CIDR form
+ {'For example': ['10.0.0.0/8', '192.168.1.0/24']}
+ |
+
+
+
+
+
+
+
+Examples
+--------
+
+.. code-block:: yaml
+
+ #### Simple examples
+
+ - name: Set network list
+ ansible.builtin.set_fact:
+ networks:
+ - "10.0.0.0/8"
+ - "192.168.1.0/24"
+
+ - name: Check if 10.1.1.1 is in the provided network list
+ ansible.builtin.set_fact:
+ data: "{{ '10.1.1.1' is ansible.utils.in_any_network networks }}"
+
+ # TASK [Check if 10.1.1.1 is in the provided network list] **************************
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": true
+ # },
+ # "changed": false
+ # }
+
+ - name: Set network list
+ ansible.builtin.set_fact:
+ networks:
+ - "10.0.0.0/8"
+ - "192.168.1.0/24"
+ - "172.16.0.0/16"
+
+ - name: Check if 8.8.8.8 is not in the provided network list
+ ansible.builtin.set_fact:
+ data: "{{ '8.8.8.8' is not ansible.utils.in_any_network networks }}"
+
+ # TASK [Check if 8.8.8.8 is not in the provided network list] ************************
+ # 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.in_network_test.rst b/docs/ansible.utils.in_network_test.rst
new file mode 100644
index 0000000..46b0d84
--- /dev/null
+++ b/docs/ansible.utils.in_network_test.rst
@@ -0,0 +1,183 @@
+.. _ansible.utils.in_network_test:
+
+
+************************
+ansible.utils.in_network
+************************
+
+**Test if IP address falls in the network**
+
+
+Version added: 2.2.0
+
+.. contents::
+ :local:
+ :depth: 1
+
+
+Synopsis
+--------
+- This plugin checks if the provided IP address belongs to the provided network
+
+
+
+
+Parameters
+----------
+
+.. raw:: html
+
+
+
+ Parameter |
+ Choices/Defaults |
+ Configuration |
+ Comments |
+
+
+
+
+ ip
+
+
+ string
+ / required
+
+ |
+
+ |
+
+ |
+
+ A string that represents an IP address
+ {'For example': '10.1.1.1'}
+ |
+
+
+
+
+ network
+
+
+ string
+ / required
+
+ |
+
+ |
+
+ |
+
+ A string that represents the network address in CIDR form
+ {'For example': '10.0.0.0/8'}
+ |
+
+
+
+
+
+
+
+Examples
+--------
+
+.. code-block:: yaml
+
+ #### Simple examples
+
+ - name: Check if 10.1.1.1 is in 10.0.0.0/8
+ ansible.builtin.set_fact:
+ data: "{{ '10.1.1.1' is ansible.utils.in_network '10.0.0.0/8' }}"
+
+ # TASK [Check if 10.1.1.1 is in 10.0.0.0/8] ***********************************
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": true
+ # },
+ # "changed": false
+ # }
+
+ - name: Check if 10.1.1.1 is not in 192.168.1.0/24
+ ansible.builtin.set_fact:
+ data: "{{ '10.1.1.1' is not ansible.utils.in_network '192.168.1.0/24' }}"
+
+ # TASK [Check if 10.1.1.1 is not in 192.168.1.0/24] ****************************
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": true
+ # },
+ # "changed": false
+ # }
+
+ - name: Check if 2001:db8:a::123 is in 2001:db8:a::/64
+ ansible.builtin.set_fact:
+ data: "{{ '2001:db8:a::123' is ansible.utils.in_network '2001:db8:a::/64' }}"
+
+ # TASK [Check if 2001:db8:a::123 is in 2001:db8:a::/64] ****************************
+ # task path: /home/prsahoo/playbooks/collections/localhost_test/utils_in_network.yml:16
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": true
+ # },
+ # "changed": false
+ # }
+
+ - name: Check if 2001:db8:a::123 is not in 10.0.0.0/8
+ ansible.builtin.set_fact:
+ data: "{{ '2001:db8:a::123' is not ansible.utils.in_network '10.0.0.0/8' }}"
+
+ # TASK [Check if 2001:db8:a::123 is not in 10.0.0.0/8] *********************************
+ # task path: /home/prsahoo/playbooks/collections/localhost_test/utils_in_network.yml:20
+ # 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.in_one_network_test.rst b/docs/ansible.utils.in_one_network_test.rst
new file mode 100644
index 0000000..c697da3
--- /dev/null
+++ b/docs/ansible.utils.in_one_network_test.rst
@@ -0,0 +1,168 @@
+.. _ansible.utils.in_one_network_test:
+
+
+****************************
+ansible.utils.in_one_network
+****************************
+
+**Test if IP address belongs in any one of the networks in the list**
+
+
+Version added: 2.2.0
+
+.. contents::
+ :local:
+ :depth: 1
+
+
+Synopsis
+--------
+- This plugin checks if the provided IP address belongs to the provided list network addresses
+
+
+
+
+Parameters
+----------
+
+.. raw:: html
+
+
+
+ Parameter |
+ Choices/Defaults |
+ Configuration |
+ Comments |
+
+
+
+
+ ip
+
+
+ string
+ / required
+
+ |
+
+ |
+
+ |
+
+ A string that represents an IP address
+ {'For example': '10.1.1.1'}
+ |
+
+
+
+
+ networks
+
+
+ list
+ / required
+
+ |
+
+ |
+
+ |
+
+ A list of string and each string represents a network address in CIDR form
+ {'For example': ['10.0.0.0/8', '192.168.1.0/24']}
+ |
+
+
+
+
+
+
+
+Examples
+--------
+
+.. code-block:: yaml
+
+ #### Simple examples
+
+ - name: Set network list
+ ansible.builtin.set_fact:
+ networks:
+ - "10.0.0.0/8"
+ - "192.168.1.0/24"
+
+ - name: Check if 10.1.1.1 is in the provided network list
+ ansible.builtin.set_fact:
+ data: "{{ '10.1.1.1' is ansible.utils.in_one_network networks }}"
+
+ # TASK [Check if 10.1.1.1 is in the provided network list] **********************
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": true
+ # },
+ # "changed": false
+
+ - name: Set network list
+ ansible.builtin.set_fact:
+ networks:
+ - "10.0.0.0/8"
+ - "10.1.1.0/24"
+
+ - name: Check if 10.1.1.1 is not in the provided network list
+ ansible.builtin.set_fact:
+ data: "{{ '10.1.1.1' is not ansible.utils.in_one_network networks }}"
+
+ # TASK [Check if 10.1.1.1 is in not the provided network list] ************************
+ # 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/plugin_utils/base/ipaddress_utils.py b/plugins/plugin_utils/base/ipaddress_utils.py
new file mode 100644
index 0000000..25f7bc6
--- /dev/null
+++ b/plugins/plugin_utils/base/ipaddress_utils.py
@@ -0,0 +1,86 @@
+# -*- 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)
+
+"""
+The utils file for all netaddr tests
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+from ansible.errors import AnsibleError
+from ansible.module_utils.basic import missing_required_lib
+from ansible.module_utils.six import ensure_text
+from functools import wraps
+from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import (
+ check_argspec,
+)
+
+try:
+ import ipaddress
+
+ HAS_IPADDRESS = True
+except ImportError:
+ HAS_IPADDRESS = False
+
+
+def ip_network(ip):
+ """ PY2 compat shim, PY2 requires unicode
+ """
+
+ if not HAS_IPADDRESS:
+ raise AnsibleError(missing_required_lib("ipaddress"))
+
+ return ipaddress.ip_network(ensure_text(ip))
+
+
+def ip_address(ip):
+ """ PY2 compat shim, PY2 requires unicode
+ """
+
+ if not HAS_IPADDRESS:
+ raise AnsibleError(missing_required_lib("ipaddress"))
+
+ return ipaddress.ip_address(ensure_text(ip))
+
+
+def _need_ipaddress(func):
+ @wraps(func)
+ def wrapper(*args, **kwargs):
+ if not HAS_IPADDRESS:
+ raise AnsibleError(missing_required_lib("ipaddress"))
+ return func(*args, **kwargs)
+
+ return wrapper
+
+
+def _is_subnet_of(network_a, network_b):
+ try:
+ if network_a._version != network_b._version:
+ return False
+ return (
+ network_b.network_address <= network_a.network_address
+ and network_b.broadcast_address >= network_a.broadcast_address
+ )
+ except Exception:
+ return False
+
+
+def _validate_args(plugin, doc, params):
+ """ argspec validator utility function
+ """
+
+ valid, argspec_result, updated_params = check_argspec(
+ doc, plugin + " test", **params
+ )
+
+ if not valid:
+ raise AnsibleError(
+ "{argspec_result} with errors: {argspec_errors}".format(
+ argspec_result=argspec_result.get("msg"),
+ argspec_errors=argspec_result.get("errors"),
+ )
+ )
diff --git a/plugins/test/in_any_network.py b/plugins/test/in_any_network.py
new file mode 100644
index 0000000..882cac4
--- /dev/null
+++ b/plugins/test/in_any_network.py
@@ -0,0 +1,112 @@
+# -*- 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: in_any_network
+"""
+
+from __future__ import absolute_import, division, print_function
+from ansible_collections.ansible.utils.plugins.test.in_network import (
+ _in_network,
+)
+from ansible_collections.ansible.utils.plugins.plugin_utils.base.ipaddress_utils import (
+ _validate_args,
+)
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+ name: in_any_network
+ author: Priyam Sahoo (@priyamsahoo)
+ version_added: "2.2.0"
+ short_description: Test if Test if an IP or network falls in any network
+ description:
+ - This plugin checks if the provided IP or network address belongs to the provided list network addresses
+ options:
+ ip:
+ description:
+ - A string that represents an IP address of a host or network
+ - For example: "10.1.1.1"
+ type: str
+ required: True
+ networks:
+ description:
+ - A list of string and each string represents a network address in CIDR form
+ - For example: ['10.0.0.0/8', '192.168.1.0/24']
+ type: list
+ required: True
+ notes:
+"""
+
+EXAMPLES = r"""
+
+#### Simple examples
+
+- name: Set network list
+ ansible.builtin.set_fact:
+ networks:
+ - "10.0.0.0/8"
+ - "192.168.1.0/24"
+
+- name: Check if 10.1.1.1 is in the provided network list
+ ansible.builtin.set_fact:
+ data: "{{ '10.1.1.1' is ansible.utils.in_any_network networks }}"
+
+# TASK [Check if 10.1.1.1 is in the provided network list] **************************
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": true
+# },
+# "changed": false
+# }
+
+- name: Set network list
+ ansible.builtin.set_fact:
+ networks:
+ - "10.0.0.0/8"
+ - "192.168.1.0/24"
+ - "172.16.0.0/16"
+
+- name: Check if 8.8.8.8 is not in the provided network list
+ ansible.builtin.set_fact:
+ data: "{{ '8.8.8.8' is not ansible.utils.in_any_network networks }}"
+
+# TASK [Check if 8.8.8.8 is not in the provided network list] ************************
+# 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)
+"""
+
+
+def _in_any_network(ip, networks):
+ """Test if an IP or network is in any network"""
+
+ params = {"ip": ip, "networks": networks}
+ _validate_args("in_any_network", DOCUMENTATION, params)
+
+ bools = [_in_network(ip, network) for network in networks]
+ if True in bools:
+ return True
+ return False
+
+
+class TestModule(object):
+ """ network jinja test"""
+
+ test_map = {"in_any_network": _in_any_network}
+
+ def tests(self):
+ return self.test_map
diff --git a/plugins/test/in_network.py b/plugins/test/in_network.py
new file mode 100644
index 0000000..ef3f0ad
--- /dev/null
+++ b/plugins/test/in_network.py
@@ -0,0 +1,128 @@
+# -*- 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: in_network
+"""
+
+from __future__ import absolute_import, division, print_function
+from ansible_collections.ansible.utils.plugins.plugin_utils.base.ipaddress_utils import (
+ ip_network,
+ _is_subnet_of,
+ _need_ipaddress,
+)
+from ansible_collections.ansible.utils.plugins.plugin_utils.base.ipaddress_utils import (
+ _validate_args,
+)
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+ name: in_network
+ author: Priyam Sahoo (@priyamsahoo)
+ version_added: "2.2.0"
+ short_description: Test if IP address falls in the network
+ description:
+ - This plugin checks if the provided IP address belongs to the provided network
+ options:
+ ip:
+ description:
+ - A string that represents an IP address
+ - For example: "10.1.1.1"
+ type: str
+ required: True
+ network:
+ description:
+ - A string that represents the network address in CIDR form
+ - For example: "10.0.0.0/8"
+ type: str
+ required: True
+ notes:
+"""
+
+EXAMPLES = r"""
+
+#### Simple examples
+
+- name: Check if 10.1.1.1 is in 10.0.0.0/8
+ ansible.builtin.set_fact:
+ data: "{{ '10.1.1.1' is ansible.utils.in_network '10.0.0.0/8' }}"
+
+# TASK [Check if 10.1.1.1 is in 10.0.0.0/8] ***********************************
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": true
+# },
+# "changed": false
+# }
+
+- name: Check if 10.1.1.1 is not in 192.168.1.0/24
+ ansible.builtin.set_fact:
+ data: "{{ '10.1.1.1' is not ansible.utils.in_network '192.168.1.0/24' }}"
+
+# TASK [Check if 10.1.1.1 is not in 192.168.1.0/24] ****************************
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": true
+# },
+# "changed": false
+# }
+
+- name: Check if 2001:db8:a::123 is in 2001:db8:a::/64
+ ansible.builtin.set_fact:
+ data: "{{ '2001:db8:a::123' is ansible.utils.in_network '2001:db8:a::/64' }}"
+
+# TASK [Check if 2001:db8:a::123 is in 2001:db8:a::/64] ****************************
+# task path: /home/prsahoo/playbooks/collections/localhost_test/utils_in_network.yml:16
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": true
+# },
+# "changed": false
+# }
+
+- name: Check if 2001:db8:a::123 is not in 10.0.0.0/8
+ ansible.builtin.set_fact:
+ data: "{{ '2001:db8:a::123' is not ansible.utils.in_network '10.0.0.0/8' }}"
+
+# TASK [Check if 2001:db8:a::123 is not in 10.0.0.0/8] *********************************
+# task path: /home/prsahoo/playbooks/collections/localhost_test/utils_in_network.yml:20
+# 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 _in_network(ip, network):
+ """Test if an address or network is in a network"""
+
+ params = {"ip": ip, "network": network}
+ _validate_args("in_network", DOCUMENTATION, params)
+
+ try:
+ return _is_subnet_of(ip_network(ip), ip_network(network))
+ except Exception:
+ return False
+
+
+class TestModule(object):
+ """ network jinja test"""
+
+ test_map = {"in_network": _in_network}
+
+ def tests(self):
+ return self.test_map
diff --git a/plugins/test/in_one_network.py b/plugins/test/in_one_network.py
new file mode 100644
index 0000000..7850252
--- /dev/null
+++ b/plugins/test/in_one_network.py
@@ -0,0 +1,111 @@
+# -*- 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: in_one_network
+"""
+
+from __future__ import absolute_import, division, print_function
+from ansible_collections.ansible.utils.plugins.test.in_network import (
+ _in_network,
+)
+from ansible_collections.ansible.utils.plugins.plugin_utils.base.ipaddress_utils import (
+ _validate_args,
+)
+
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+ name: in_one_network
+ author: Priyam Sahoo (@priyamsahoo)
+ version_added: "2.2.0"
+ short_description: Test if IP address belongs in any one of the networks in the list
+ description:
+ - This plugin checks if the provided IP address belongs to the provided list network addresses
+ options:
+ ip:
+ description:
+ - A string that represents an IP address
+ - For example: "10.1.1.1"
+ type: str
+ required: True
+ networks:
+ description:
+ - A list of string and each string represents a network address in CIDR form
+ - For example: ['10.0.0.0/8', '192.168.1.0/24']
+ type: list
+ required: True
+ notes:
+"""
+
+EXAMPLES = r"""
+
+#### Simple examples
+
+- name: Set network list
+ ansible.builtin.set_fact:
+ networks:
+ - "10.0.0.0/8"
+ - "192.168.1.0/24"
+
+- name: Check if 10.1.1.1 is in the provided network list
+ ansible.builtin.set_fact:
+ data: "{{ '10.1.1.1' is ansible.utils.in_one_network networks }}"
+
+# TASK [Check if 10.1.1.1 is in the provided network list] **********************
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": true
+# },
+# "changed": false
+
+- name: Set network list
+ ansible.builtin.set_fact:
+ networks:
+ - "10.0.0.0/8"
+ - "10.1.1.0/24"
+
+- name: Check if 10.1.1.1 is not in the provided network list
+ ansible.builtin.set_fact:
+ data: "{{ '10.1.1.1' is not ansible.utils.in_one_network networks }}"
+
+# TASK [Check if 10.1.1.1 is in not the provided network list] ************************
+# 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)
+"""
+
+
+def _in_one_network(ip, networks):
+ """Test if an IP or network is in one network"""
+
+ params = {"ip": ip, "networks": networks}
+ _validate_args("in_one_network", DOCUMENTATION, params)
+
+ bools = [_in_network(ip, network) for network in networks]
+ if bools.count(True) == 1:
+ return True
+ return False
+
+
+class TestModule(object):
+ """ network jinja test"""
+
+ test_map = {"in_one_network": _in_one_network}
+
+ def tests(self):
+ return self.test_map
diff --git a/test-requirements.txt b/test-requirements.txt
index 538e15f..e454ff0 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -1,6 +1,7 @@
black==19.3b0 ; python_version > '3.5'
coverage==4.5.4
flake8
+ipaddress ; python_version < '3.0'
mock ; python_version < '3.5'
pytest-xdist
yamllint
diff --git a/tests/integration/targets/netaddr_test/tasks/include/in_any_network.yml b/tests/integration/targets/netaddr_test/tasks/include/in_any_network.yml
new file mode 100644
index 0000000..0c69b04
--- /dev/null
+++ b/tests/integration/targets/netaddr_test/tasks/include/in_any_network.yml
@@ -0,0 +1,17 @@
+---
+- name: "in_any_network: :Check if 10.1.1.1 is in the provided network list"
+ assert:
+ that:
+ - "{{ '10.1.1.1' is ansible.utils.in_any_network networks }}"
+
+- name: "in_any_network: Check if 8.8.8.8 is not in the provided network list"
+ assert:
+ that: "{{ '8.8.8.8' is not ansible.utils.in_any_network networks }}"
+
+- name: "in_any_network: Test invalidness"
+ ansible.builtin.set_fact:
+ criteria_check: "{{ '192.168.4.56' is ansible.utils.in_any_network networks }}"
+
+- name: "in_any_network: Assert invalidness"
+ assert:
+ that: "{{ criteria_check == false }}"
diff --git a/tests/integration/targets/netaddr_test/tasks/include/in_network.yml b/tests/integration/targets/netaddr_test/tasks/include/in_network.yml
new file mode 100644
index 0000000..8627f15
--- /dev/null
+++ b/tests/integration/targets/netaddr_test/tasks/include/in_network.yml
@@ -0,0 +1,33 @@
+---
+- name: "in_network: Check if 10.1.1.1 is in 10.0.0.0/8"
+ assert:
+ that: "{{ '10.1.1.1' is ansible.utils.in_network '10.0.0.0/8' }}"
+
+- name: "in_network: Check if 10.1.1.1 is not in 192.168.1.0/24"
+ assert:
+ that: "{{ '10.1.1.1' is not ansible.utils.in_network '192.168.1.0/24' }}"
+
+- name: "in_network: Test invalidness"
+ ansible.builtin.set_fact:
+ criteria_check1: "{{ '8.8.8.8' is ansible.utils.in_network '10.0.0.0/8' }}"
+
+- name: "in_network: Assert invalidness"
+ assert:
+ that: "{{ criteria_check1 == false }}"
+
+- name: "in_network: Check if 2001:db8:a::123 is in 2001:db8:a::/64"
+ assert:
+ that: "{{ '2001:db8:a::123' is ansible.utils.in_network '2001:db8:a::/64' }}"
+
+- name: "in_network: Check if 2001:db8:a::123 is not in 10.0.0.0/8"
+ assert:
+ that: "{{ '2001:db8:a::123' is not ansible.utils.in_network '10.0.0.0/8' }}"
+
+- name: "in_network: Test invalidness"
+ ansible.builtin.set_fact:
+ criteria_check2: "{{ '2001:db8:a::123' is not ansible.utils.in_network '2001:db8:a::/64' }}"
+ register: result2
+
+- name: "in_network: Assert invalidness"
+ assert:
+ that: "{{ criteria_check2 == false }}"
diff --git a/tests/integration/targets/netaddr_test/tasks/include/in_one_network.yml b/tests/integration/targets/netaddr_test/tasks/include/in_one_network.yml
new file mode 100644
index 0000000..cb08c35
--- /dev/null
+++ b/tests/integration/targets/netaddr_test/tasks/include/in_one_network.yml
@@ -0,0 +1,16 @@
+---
+- name: "in_one_network: Check if 10.1.1.1 is in the provided network list"
+ assert:
+ that: "{{ '10.1.1.1' is ansible.utils.in_one_network networks }}"
+
+- name: "in_one_network: Check if 192.168.3.5 is not in the provided network list"
+ assert:
+ that: "{{ '192.168.3.5' is not ansible.utils.in_one_network networks }}"
+
+- name: "in_one_network: Test invalidness"
+ ansible.builtin.set_fact:
+ criteria_check: "{{ '172.168.2.16' is ansible.utils.in_one_network networks }}"
+
+- name: "in_one_network: Assert invalidness"
+ assert:
+ that: "{{ criteria_check == false }}"
diff --git a/tests/integration/targets/netaddr_test/tasks/main.yaml b/tests/integration/targets/netaddr_test/tasks/main.yaml
new file mode 100644
index 0000000..4274d75
--- /dev/null
+++ b/tests/integration/targets/netaddr_test/tasks/main.yaml
@@ -0,0 +1,13 @@
+---
+- name: Recursively find all test files
+ find:
+ file_type: file
+ paths: "{{ role_path }}/tasks/include"
+ recurse: true
+ use_regex: true
+ patterns:
+ - '^(?!_).+$'
+ register: found
+
+- include: "{{ item.path }}"
+ loop: "{{ found.files }}"
diff --git a/tests/integration/targets/netaddr_test/vars/main.yaml b/tests/integration/targets/netaddr_test/vars/main.yaml
new file mode 100644
index 0000000..ae08764
--- /dev/null
+++ b/tests/integration/targets/netaddr_test/vars/main.yaml
@@ -0,0 +1,5 @@
+---
+networks:
+ - "10.0.0.0/8"
+ - "192.168.1.0/24"
+ - "172.16.0.0/16"
diff --git a/tests/unit/plugins/test/test_in_any_network.py b/tests/unit/plugins/test/test_in_any_network.py
new file mode 100644
index 0000000..3426d6b
--- /dev/null
+++ b/tests/unit/plugins/test/test_in_any_network.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+# Copyright 2020 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: in_any_network
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import unittest
+from ansible.errors import AnsibleError
+from ansible_collections.ansible.utils.plugins.test.in_any_network import (
+ _in_any_network,
+)
+
+
+class TestInAnyNetwork(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def test_invalid_data(self):
+ """Check passing invalid argspec"""
+
+ # invalid argument
+ with self.assertRaises(AnsibleError) as error:
+ _in_any_network(
+ ip="10.1.1.1",
+ networks={
+ "name": "networks",
+ "value": ["10.0.0.0/8", "192.168.1.0/24"],
+ },
+ )
+ self.assertIn("unable to convert to list", str(error.exception))
+
+ def test_valid_data(self):
+ """Check passing valid data as per criteria"""
+
+ result = _in_any_network(
+ ip="10.1.1.1", networks=["10.0.0.0/8", "192.168.1.0/24"]
+ )
+ self.assertEqual(result, True)
+
+ result = _in_any_network(
+ ip="8.8.8.8", networks=["10.0.0.0/8", "192.168.1.0/24"]
+ )
+ self.assertEqual(result, False)
diff --git a/tests/unit/plugins/test/test_in_network.py b/tests/unit/plugins/test/test_in_network.py
new file mode 100644
index 0000000..69b0e46
--- /dev/null
+++ b/tests/unit/plugins/test/test_in_network.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+# Copyright 2020 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: in_network
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import unittest
+from ansible_collections.ansible.utils.plugins.test.in_network import (
+ _in_network,
+)
+
+
+class TestInNetwork(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def test_invalid_data(self):
+ """Check passing invalid argspec"""
+
+ # invalid argument
+ with self.assertRaises(TypeError) as error:
+ _in_network(ip="10.1.1.1")
+ self.assertIn("argument", str(error.exception))
+
+ def test_valid_data(self):
+ """Check passing valid data as per criteria"""
+
+ result = _in_network(ip="10.1.1.1", network="10.0.0.0/8")
+ self.assertEqual(result, True)
+
+ result = _in_network(ip="8.8.8.8", network="192.168.1.0/24")
+ self.assertEqual(result, False)
+
+ result = _in_network(ip="2001:db8:a::123", network="2001:db8:a::/64")
+ self.assertEqual(result, True)
+
+ result = _in_network(ip="2001:db8:a::123", network="10.0.0.0/8")
+ self.assertEqual(result, False)
diff --git a/tests/unit/plugins/test/test_in_one_network.py b/tests/unit/plugins/test/test_in_one_network.py
new file mode 100644
index 0000000..53fd79e
--- /dev/null
+++ b/tests/unit/plugins/test/test_in_one_network.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+# Copyright 2020 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: in_one_network
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import unittest
+from ansible.errors import AnsibleError
+from ansible_collections.ansible.utils.plugins.test.in_one_network import (
+ _in_one_network,
+)
+
+
+class TestInOneNetwork(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def test_invalid_data(self):
+ """Check passing invalid argspec"""
+
+ # invalid argument
+ with self.assertRaises(AnsibleError) as error:
+ _in_one_network(
+ ip="10.1.1.1",
+ networks={
+ "name": "networks",
+ "value": ["10.0.0.0/8", "192.168.1.0/24"],
+ },
+ )
+ self.assertIn("unable to convert to list", str(error.exception))
+
+ def test_valid_data(self):
+ """Check passing valid data as per criteria"""
+
+ result = _in_one_network(
+ ip="10.1.1.1", networks=["10.0.0.0/8", "192.168.1.0/24"]
+ )
+ self.assertEqual(result, True)
+
+ result = _in_one_network(
+ ip="8.8.8.8", networks=["10.0.0.0/8", "10.1.1.0/24"]
+ )
+ self.assertEqual(result, False)