diff --git a/README.md b/README.md
index 2bf1be3..98452b7 100644
--- a/README.md
+++ b/README.md
@@ -50,6 +50,8 @@ 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.ip](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.ip_test.rst)|Test if something in an IP address or network
+[ansible.utils.ip_address](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.ip_address_test.rst)|Test if something in an 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_2.yml b/changelogs/fragments/add_netaddr_test_plugins_2.yml
new file mode 100644
index 0000000..f48486a
--- /dev/null
+++ b/changelogs/fragments/add_netaddr_test_plugins_2.yml
@@ -0,0 +1,3 @@
+---
+minor_changes:
+ - Add ip, ip_address test plugins
diff --git a/docs/ansible.utils.in_network_test.rst b/docs/ansible.utils.in_network_test.rst
index 46b0d84..adf9cfa 100644
--- a/docs/ansible.utils.in_network_test.rst
+++ b/docs/ansible.utils.in_network_test.rst
@@ -100,7 +100,7 @@ Examples
- 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": {
diff --git a/docs/ansible.utils.ip_address_test.rst b/docs/ansible.utils.ip_address_test.rst
new file mode 100644
index 0000000..4d59e09
--- /dev/null
+++ b/docs/ansible.utils.ip_address_test.rst
@@ -0,0 +1,150 @@
+.. _ansible.utils.ip_address_test:
+
+
+************************
+ansible.utils.ip_address
+************************
+
+**Test if something in an IP address**
+
+
+Version added: 2.2.0
+
+.. contents::
+ :local:
+ :depth: 1
+
+
+Synopsis
+--------
+- This plugin checks if the provided value is a valid host 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': ['10.1.1.1', 'hello-world']}
+ |
+
+
+
+
+
+
+
+Examples
+--------
+
+.. code-block:: yaml
+
+ #### Simple examples
+
+ - name: Check if 10.1.1.1 is a valid IP address
+ ansible.builtin.set_fact:
+ data: "{{ '10.1.1.1' is ansible.utils.ip_address }}"
+
+ # TASK [Check if 10.1.1.1 is a valid IP address] *************************************
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": true
+ # },
+ # "changed": false
+ # }
+
+ - name: Check if "hello-world" is not a valid IP address
+ ansible.builtin.set_fact:
+ data: "{{ 'hello-world' is not ansible.utils.ip_address }}"
+
+ # TASK [Check if "hello-world" is not a valid IP address] ****************************
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": true
+ # },
+ # "changed": false
+ # }
+
+ - name: Check if 10.0.0.0/8 is a valid IP address
+ ansible.builtin.set_fact:
+ data: "{{ '10.0.0.0/8' is ansible.utils.ip_address }}"
+
+ # TASK [Check if 10.0.0.0/8 is a valid IP address] ***********************************
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": false
+ # },
+ # "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.ip_test.rst b/docs/ansible.utils.ip_test.rst
new file mode 100644
index 0000000..f4445de
--- /dev/null
+++ b/docs/ansible.utils.ip_test.rst
@@ -0,0 +1,174 @@
+.. _ansible.utils.ip_test:
+
+
+****************
+ansible.utils.ip
+****************
+
+**Test if something in an IP address or network**
+
+
+Version added: 2.2.0
+
+.. contents::
+ :local:
+ :depth: 1
+
+
+Synopsis
+--------
+- This plugin checks if the provided value is a valid host or network 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': ['10.1.1.1', '2001:db8:a::123', 'hello-world']}
+ |
+
+
+
+
+
+
+
+Examples
+--------
+
+.. code-block:: yaml
+
+ #### Simple examples
+
+ - name: Check if 10.1.1.1 is a valid IP address
+ ansible.builtin.set_fact:
+ data: "{{ '10.1.1.1' is ansible.utils.ip }}"
+
+ # TASK [Check if 10.1.1.1 is a valid IP address] *****************************
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": true
+ # },
+ # "changed": false
+ # }
+
+ - name: Check if 2001:db8:a::123 is a valid IP address
+ ansible.builtin.set_fact:
+ data: "{{ '2001:db8:a::123' is ansible.utils.ip }}"
+
+ # TASK [Check if 2001:db8:a::123 is a valid IP address] **********************
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": true
+ # },
+ # "changed": false
+ # }
+
+ - name: Check if "hello-world" is not a valid IP address
+ ansible.builtin.set_fact:
+ data: "{{ 'hello-world' is not ansible.utils.ip }}"
+
+ # TASK [Check if "hello-world" is not a valid IP address] ********************
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": true
+ # },
+ # "changed": false
+ # }
+
+ - name: Check if 300.1.1.1 is a valid IP address
+ ansible.builtin.set_fact:
+ data: "{{ '300.1.1.1' is ansible.utils.ip }}"
+
+ # TASK [Check if 300.1.1.1 is a valid IP address] ****************************
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": false
+ # },
+ # "changed": false
+ # }
+
+ - name: Check if 10.0.0.0/8 is a valid IP address
+ ansible.builtin.set_fact:
+ data: "{{ '10.0.0.0/8' is ansible.utils.ip }}"
+
+ # TASK [Check if 10.0.0.0/8 is a valid 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/ip.py b/plugins/test/ip.py
new file mode 100644
index 0000000..edca1b0
--- /dev/null
+++ b/plugins/test/ip.py
@@ -0,0 +1,133 @@
+# -*- 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: ip
+"""
+
+from __future__ import absolute_import, division, print_function
+from ansible_collections.ansible.utils.plugins.plugin_utils.base.ipaddress_utils import (
+ ip_network,
+ _need_ipaddress,
+ _validate_args,
+)
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+ name: ip
+ author: Priyam Sahoo (@priyamsahoo)
+ version_added: "2.2.0"
+ short_description: Test if something in an IP address or network
+ description:
+ - This plugin checks if the provided value is a valid host or network IP address
+ options:
+ ip:
+ description:
+ - A string that represents the value against which the test is going to be performed
+ - For example:
+ - "10.1.1.1"
+ - "2001:db8:a::123"
+ - "hello-world"
+ type: str
+ required: True
+ notes:
+"""
+
+EXAMPLES = r"""
+
+#### Simple examples
+
+- name: Check if 10.1.1.1 is a valid IP address
+ ansible.builtin.set_fact:
+ data: "{{ '10.1.1.1' is ansible.utils.ip }}"
+
+# TASK [Check if 10.1.1.1 is a valid IP address] *****************************
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": true
+# },
+# "changed": false
+# }
+
+- name: Check if 2001:db8:a::123 is a valid IP address
+ ansible.builtin.set_fact:
+ data: "{{ '2001:db8:a::123' is ansible.utils.ip }}"
+
+# TASK [Check if 2001:db8:a::123 is a valid IP address] **********************
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": true
+# },
+# "changed": false
+# }
+
+- name: Check if "hello-world" is not a valid IP address
+ ansible.builtin.set_fact:
+ data: "{{ 'hello-world' is not ansible.utils.ip }}"
+
+# TASK [Check if "hello-world" is not a valid IP address] ********************
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": true
+# },
+# "changed": false
+# }
+
+- name: Check if 300.1.1.1 is a valid IP address
+ ansible.builtin.set_fact:
+ data: "{{ '300.1.1.1' is ansible.utils.ip }}"
+
+# TASK [Check if 300.1.1.1 is a valid IP address] ****************************
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": false
+# },
+# "changed": false
+# }
+
+- name: Check if 10.0.0.0/8 is a valid IP address
+ ansible.builtin.set_fact:
+ data: "{{ '10.0.0.0/8' is ansible.utils.ip }}"
+
+# TASK [Check if 10.0.0.0/8 is a valid 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 _ip(ip):
+ """ Test if something in an IP address or network """
+
+ params = {"ip": ip}
+ _validate_args("ip", DOCUMENTATION, params)
+
+ try:
+ ip_network(ip)
+ return True
+ except Exception:
+ return False
+
+
+class TestModule(object):
+ """ network jinja test"""
+
+ test_map = {"ip": _ip}
+
+ def tests(self):
+ return self.test_map
diff --git a/plugins/test/ip_address.py b/plugins/test/ip_address.py
new file mode 100644
index 0000000..0de06ab
--- /dev/null
+++ b/plugins/test/ip_address.py
@@ -0,0 +1,108 @@
+# -*- 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: ip_address
+"""
+
+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: ip_address
+ author: Priyam Sahoo (@priyamsahoo)
+ version_added: "2.2.0"
+ short_description: Test if something in an IP address
+ description:
+ - This plugin checks if the provided value is a valid host IP address
+ options:
+ ip:
+ description:
+ - A string that represents the value against which the test is going to be performed
+ - For example:
+ - "10.1.1.1"
+ - "hello-world"
+ type: str
+ required: True
+ notes:
+"""
+
+EXAMPLES = r"""
+
+#### Simple examples
+
+- name: Check if 10.1.1.1 is a valid IP address
+ ansible.builtin.set_fact:
+ data: "{{ '10.1.1.1' is ansible.utils.ip_address }}"
+
+# TASK [Check if 10.1.1.1 is a valid IP address] *************************************
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": true
+# },
+# "changed": false
+# }
+
+- name: Check if "hello-world" is not a valid IP address
+ ansible.builtin.set_fact:
+ data: "{{ 'hello-world' is not ansible.utils.ip_address }}"
+
+# TASK [Check if "hello-world" is not a valid IP address] ****************************
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": true
+# },
+# "changed": false
+# }
+
+- name: Check if 10.0.0.0/8 is a valid IP address
+ ansible.builtin.set_fact:
+ data: "{{ '10.0.0.0/8' is ansible.utils.ip_address }}"
+
+# TASK [Check if 10.0.0.0/8 is a valid IP address] ***********************************
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": false
+# },
+# "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 _ip_address(ip):
+ """Test if something in an IP address"""
+
+ params = {"ip": ip}
+ _validate_args("ip_address", DOCUMENTATION, params)
+
+ try:
+ ip_address(ip)
+ return True
+ except Exception:
+ return False
+
+
+class TestModule(object):
+ """ network jinja test"""
+
+ test_map = {"ip_address": _ip_address}
+
+ def tests(self):
+ return self.test_map
diff --git a/tests/integration/targets/netaddr_test/tasks/include/in_network.yml b/tests/integration/targets/netaddr_test/tasks/include/in_network.yml
index 8627f15..256df7b 100644
--- a/tests/integration/targets/netaddr_test/tasks/include/in_network.yml
+++ b/tests/integration/targets/netaddr_test/tasks/include/in_network.yml
@@ -26,7 +26,6 @@
- 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:
diff --git a/tests/integration/targets/netaddr_test/tasks/include/ip.yml b/tests/integration/targets/netaddr_test/tasks/include/ip.yml
new file mode 100644
index 0000000..11b76bd
--- /dev/null
+++ b/tests/integration/targets/netaddr_test/tasks/include/ip.yml
@@ -0,0 +1,28 @@
+---
+- name: "ip: Check if 10.1.1.1 is a valid IP address"
+ assert:
+ that: "{{ '10.1.1.1' is ansible.utils.ip }}"
+
+- name: "ip: Check if 2001:db8:a::123 is a valid IP address"
+ assert:
+ that: "{{ '2001:db8:a::123' is ansible.utils.ip }}"
+
+- name: "ip: Check if 10.0.0.0/8 is a valid IP address"
+ assert:
+ that: "{{ '10.0.0.0/8' is ansible.utils.ip }}"
+
+- name: "ip: Test invalidness"
+ ansible.builtin.set_fact:
+ criteria_check1: "{{ 'string' is ansible.utils.ip }}"
+
+- name: "ip: Assert invalidness"
+ assert:
+ that: "{{ criteria_check1 == false }}"
+
+- name: "ip: Test invalidness"
+ ansible.builtin.set_fact:
+ criteria_check2: "{{ '300.1.1.1' is ansible.utils.ip }}"
+
+- name: "ip: Assert invalidness"
+ assert:
+ that: "{{ criteria_check2 == false }}"
diff --git a/tests/integration/targets/netaddr_test/tasks/include/ip_address.yml b/tests/integration/targets/netaddr_test/tasks/include/ip_address.yml
new file mode 100644
index 0000000..b92da2a
--- /dev/null
+++ b/tests/integration/targets/netaddr_test/tasks/include/ip_address.yml
@@ -0,0 +1,32 @@
+---
+- name: "ip_address: Check if 10.1.1.1 is a valid IP address"
+ assert:
+ that: "{{ '10.1.1.1' is ansible.utils.ip_address }}"
+
+- name: "ip_address: Check if 2001:db8:a::123 is a valid IP address"
+ assert:
+ that: "{{ '2001:db8:a::123' is ansible.utils.ip_address }}"
+
+- name: "ip_address: Test invalidness"
+ ansible.builtin.set_fact:
+ criteria_check1: "{{ '10.0.0.0/8' is ansible.utils.ip_address }}"
+
+- name: "ip_address: Assert invalidness"
+ assert:
+ that: "{{ criteria_check1 == false }}"
+
+- name: "ip_address: Test invalidness"
+ ansible.builtin.set_fact:
+ criteria_check2: "{{ 'string' is ansible.utils.ip_address }}"
+
+- name: "ip_address: Assert invalidness"
+ assert:
+ that: "{{ criteria_check2 == false }}"
+
+- name: "ip_address: Test invalidness"
+ ansible.builtin.set_fact:
+ criteria_check3: "{{ '300.1.1.1' is ansible.utils.ip_address }}"
+
+- name: "ip_address: Assert invalidness"
+ assert:
+ that: "{{ criteria_check3 == false }}"
diff --git a/tests/unit/plugins/test/test_in_any_network.py b/tests/unit/plugins/test/test_in_any_network.py
index 3426d6b..802b3c1 100644
--- a/tests/unit/plugins/test/test_in_any_network.py
+++ b/tests/unit/plugins/test/test_in_any_network.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2020 Red Hat
+# Copyright 2021 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
diff --git a/tests/unit/plugins/test/test_in_network.py b/tests/unit/plugins/test/test_in_network.py
index 69b0e46..b9ac571 100644
--- a/tests/unit/plugins/test/test_in_network.py
+++ b/tests/unit/plugins/test/test_in_network.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2020 Red Hat
+# Copyright 2021 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
diff --git a/tests/unit/plugins/test/test_in_one_network.py b/tests/unit/plugins/test/test_in_one_network.py
index 53fd79e..dc00000 100644
--- a/tests/unit/plugins/test/test_in_one_network.py
+++ b/tests/unit/plugins/test/test_in_one_network.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2020 Red Hat
+# Copyright 2021 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
diff --git a/tests/unit/plugins/test/test_ip.py b/tests/unit/plugins/test/test_ip.py
new file mode 100644
index 0000000..f45f7f4
--- /dev/null
+++ b/tests/unit/plugins/test/test_ip.py
@@ -0,0 +1,46 @@
+# -*- 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: ip
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import unittest
+from ansible_collections.ansible.utils.plugins.test.ip import _ip
+
+
+class TestIp(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def test_invalid_data(self):
+ """Check passing invalid argspec"""
+
+ # missing argument
+ with self.assertRaises(TypeError) as error:
+ _ip()
+ self.assertIn("argument", str(error.exception))
+
+ def test_valid_data(self):
+ """Check passing valid data as per criteria"""
+
+ result = _ip(ip="10.1.1.1")
+ self.assertEqual(result, True)
+
+ result = _ip(ip="2001:db8:a::123")
+ self.assertEqual(result, True)
+
+ result = _ip(ip="string")
+ self.assertEqual(result, False)
+
+ result = _ip(ip="300.1.1.1")
+ self.assertEqual(result, False)
+
+ result = _ip(ip="10.0.0.0/8")
+ self.assertEqual(result, True)
diff --git a/tests/unit/plugins/test/test_ip_address.py b/tests/unit/plugins/test/test_ip_address.py
new file mode 100644
index 0000000..de70213
--- /dev/null
+++ b/tests/unit/plugins/test/test_ip_address.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: ip_address
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import unittest
+from ansible_collections.ansible.utils.plugins.test.ip_address import (
+ _ip_address,
+)
+
+
+class TestIpAddress(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def test_invalid_data(self):
+ """Check passing invalid argspec"""
+
+ # missing argument
+ with self.assertRaises(TypeError) as error:
+ _ip_address()
+ self.assertIn("argument", str(error.exception))
+
+ def test_valid_data(self):
+ """Check passing valid data as per criteria"""
+
+ result = _ip_address(ip="10.1.1.1")
+ self.assertEqual(result, True)
+
+ result = _ip_address(ip="2001:db8:a::123")
+ self.assertEqual(result, True)
+
+ result = _ip_address(ip="string")
+ self.assertEqual(result, False)
+
+ result = _ip_address(ip="300.1.1.1")
+ self.assertEqual(result, False)
+
+ result = _ip_address(ip="10.0.0.0/8")
+ self.assertEqual(result, False)