diff --git a/README.md b/README.md
index 4bed84a..62f87e8 100644
--- a/README.md
+++ b/README.md
@@ -64,6 +64,9 @@ Name | Description
[ansible.utils.loopback](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.loopback_test.rst)|Test if an IP address is a loopback
[ansible.utils.mac](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.mac_test.rst)|Test if something appears to be a valid MAC address
[ansible.utils.multicast](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.multicast_test.rst)|Test for a multicast IP address
+[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.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_6.yml b/changelogs/fragments/add_netaddr_test_plugins_6.yml
new file mode 100644
index 0000000..40dd2fd
--- /dev/null
+++ b/changelogs/fragments/add_netaddr_test_plugins_6.yml
@@ -0,0 +1,3 @@
+---
+minor_changes:
+ - Add private, public, reserved test plugins
diff --git a/docs/ansible.utils.private_test.rst b/docs/ansible.utils.private_test.rst
new file mode 100644
index 0000000..12fa23f
--- /dev/null
+++ b/docs/ansible.utils.private_test.rst
@@ -0,0 +1,136 @@
+.. _ansible.utils.private_test:
+
+
+*********************
+ansible.utils.private
+*********************
+
+**Test if an IP address is private**
+
+
+Version added: 2.2.0
+
+.. contents::
+ :local:
+ :depth: 1
+
+
+Synopsis
+--------
+- This plugin checks if the provided value is a private 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', '8.8.8.8', '192.168.1.250']}
+ |
+
+
+
+
+
+
+
+Examples
+--------
+
+.. code-block:: yaml
+
+ - name: Check if 10.1.1.1 is a private IP address
+ ansible.builtin.set_fact:
+ data: "{{ '10.1.1.1' is ansible.utils.private }}"
+
+ # TASK [Check if 10.1.1.1 is a private IP address] *******************************
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": true
+ # },
+ # "changed": false
+ # }
+
+ - name: Check if 8.8.8.8 is not a private IP address
+ ansible.builtin.set_fact:
+ data: "{{ '8.8.8.8' is not ansible.utils.private }}"
+
+ # TASK [Check if 8.8.8.8 is not a private 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/docs/ansible.utils.public_test.rst b/docs/ansible.utils.public_test.rst
new file mode 100644
index 0000000..f3d8727
--- /dev/null
+++ b/docs/ansible.utils.public_test.rst
@@ -0,0 +1,136 @@
+.. _ansible.utils.public_test:
+
+
+********************
+ansible.utils.public
+********************
+
+**Test if an IP address is public**
+
+
+Version added: 2.2.0
+
+.. contents::
+ :local:
+ :depth: 1
+
+
+Synopsis
+--------
+- This plugin checks if the provided value is a public 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': ['8.8.8.8', '10.1.1.1', '192.168.1.250']}
+ |
+
+
+
+
+
+
+
+Examples
+--------
+
+.. code-block:: yaml
+
+ - name: Check if 8.8.8.8 is a public IP address
+ ansible.builtin.set_fact:
+ data: "{{ '8.8.8.8' is ansible.utils.public }}"
+
+ # TASK [Check if 8.8.8.8 is a public IP address] *********************************
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": true
+ # },
+ # "changed": false
+ # }
+
+ - name: Check if 10.1.1.1 is not a public IP address
+ ansible.builtin.set_fact:
+ data: "{{ '10.1.1.1' is not ansible.utils.public }}"
+
+ # TASK [Check if 10.1.1.1 is not a public 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/docs/ansible.utils.reserved_test.rst b/docs/ansible.utils.reserved_test.rst
new file mode 100644
index 0000000..6dabece
--- /dev/null
+++ b/docs/ansible.utils.reserved_test.rst
@@ -0,0 +1,136 @@
+.. _ansible.utils.reserved_test:
+
+
+**********************
+ansible.utils.reserved
+**********************
+
+**Test for a reserved IP address**
+
+
+Version added: 2.2.0
+
+.. contents::
+ :local:
+ :depth: 1
+
+
+Synopsis
+--------
+- This plugin checks if the provided value is a reserved 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': ['253.0.0.1', '128.146.1.7']}
+ |
+
+
+
+
+
+
+
+Examples
+--------
+
+.. code-block:: yaml
+
+ - name: Check if 253.0.0.1 is a reserved IP address
+ ansible.builtin.set_fact:
+ data: "{{ '253.0.0.1' is ansible.utils.reserved }}"
+
+ # TASK [Check if 253.0.0.1 is a reserved IP address] *****************************
+ # ok: [localhost] => {
+ # "ansible_facts": {
+ # "data": true
+ # },
+ # "changed": false
+ # }
+
+ - name: Check if 128.146.1.7 is not a reserved IP address
+ ansible.builtin.set_fact:
+ data: "{{ '128.146.1.7' is not ansible.utils.reserved }}"
+
+ # TASK [Check if 128.146.1.7 is not a reserved 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/private.py b/plugins/test/private.py
new file mode 100644
index 0000000..26e13e4
--- /dev/null
+++ b/plugins/test/private.py
@@ -0,0 +1,94 @@
+# -*- 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: private
+"""
+
+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: private
+ author: Priyam Sahoo (@priyamsahoo)
+ version_added: "2.2.0"
+ short_description: Test if an IP address is private
+ description:
+ - This plugin checks if the provided value is a private 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"
+ - "8.8.8.8"
+ - "192.168.1.250"
+ type: str
+ required: True
+ notes:
+"""
+
+EXAMPLES = r"""
+
+- name: Check if 10.1.1.1 is a private IP address
+ ansible.builtin.set_fact:
+ data: "{{ '10.1.1.1' is ansible.utils.private }}"
+
+# TASK [Check if 10.1.1.1 is a private IP address] *******************************
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": true
+# },
+# "changed": false
+# }
+
+- name: Check if 8.8.8.8 is not a private IP address
+ ansible.builtin.set_fact:
+ data: "{{ '8.8.8.8' is not ansible.utils.private }}"
+
+# TASK [Check if 8.8.8.8 is not a private 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 _private(ip):
+ """ Test if an IP address is private """
+
+ params = {"ip": ip}
+ _validate_args("private", DOCUMENTATION, params)
+
+ try:
+ return ip_address(ip).is_private
+ except Exception:
+ return False
+
+
+class TestModule(object):
+ """ network jinja test"""
+
+ test_map = {"private": _private}
+
+ def tests(self):
+ return self.test_map
diff --git a/plugins/test/public.py b/plugins/test/public.py
new file mode 100644
index 0000000..a0973db
--- /dev/null
+++ b/plugins/test/public.py
@@ -0,0 +1,94 @@
+# -*- 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: public
+"""
+
+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: public
+ author: Priyam Sahoo (@priyamsahoo)
+ version_added: "2.2.0"
+ short_description: Test if an IP address is public
+ description:
+ - This plugin checks if the provided value is a public IP address
+ options:
+ ip:
+ description:
+ - A string that represents the value against which the test is going to be performed
+ - For example:
+ - "8.8.8.8"
+ - "10.1.1.1"
+ - "192.168.1.250"
+ type: str
+ required: True
+ notes:
+"""
+
+EXAMPLES = r"""
+
+- name: Check if 8.8.8.8 is a public IP address
+ ansible.builtin.set_fact:
+ data: "{{ '8.8.8.8' is ansible.utils.public }}"
+
+# TASK [Check if 8.8.8.8 is a public IP address] *********************************
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": true
+# },
+# "changed": false
+# }
+
+- name: Check if 10.1.1.1 is not a public IP address
+ ansible.builtin.set_fact:
+ data: "{{ '10.1.1.1' is not ansible.utils.public }}"
+
+# TASK [Check if 10.1.1.1 is not a public 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 _public(ip):
+ """ Test if an IP address is public """
+
+ params = {"ip": ip}
+ _validate_args("public", DOCUMENTATION, params)
+
+ try:
+ return ip_address(ip).is_global
+ except Exception:
+ return False
+
+
+class TestModule(object):
+ """ network jinja test"""
+
+ test_map = {"public": _public}
+
+ def tests(self):
+ return self.test_map
diff --git a/plugins/test/reserved.py b/plugins/test/reserved.py
new file mode 100644
index 0000000..81b1120
--- /dev/null
+++ b/plugins/test/reserved.py
@@ -0,0 +1,93 @@
+# -*- 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: reserved
+"""
+
+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: reserved
+ author: Priyam Sahoo (@priyamsahoo)
+ version_added: "2.2.0"
+ short_description: Test for a reserved IP address
+ description:
+ - This plugin checks if the provided value is a reserved IP address
+ options:
+ ip:
+ description:
+ - A string that represents the value against which the test is going to be performed
+ - For example:
+ - "253.0.0.1"
+ - "128.146.1.7"
+ type: str
+ required: True
+ notes:
+"""
+
+EXAMPLES = r"""
+
+- name: Check if 253.0.0.1 is a reserved IP address
+ ansible.builtin.set_fact:
+ data: "{{ '253.0.0.1' is ansible.utils.reserved }}"
+
+# TASK [Check if 253.0.0.1 is a reserved IP address] *****************************
+# ok: [localhost] => {
+# "ansible_facts": {
+# "data": true
+# },
+# "changed": false
+# }
+
+- name: Check if 128.146.1.7 is not a reserved IP address
+ ansible.builtin.set_fact:
+ data: "{{ '128.146.1.7' is not ansible.utils.reserved }}"
+
+# TASK [Check if 128.146.1.7 is not a reserved 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 _reserved(ip):
+ """ Test for a reserved IP address """
+
+ params = {"ip": ip}
+ _validate_args("reserved", DOCUMENTATION, params)
+
+ try:
+ return ip_address(ip).is_reserved
+ except Exception:
+ return False
+
+
+class TestModule(object):
+ """ network jinja test"""
+
+ test_map = {"reserved": _reserved}
+
+ def tests(self):
+ return self.test_map
diff --git a/tests/integration/targets/netaddr_test/tasks/include/private.yml b/tests/integration/targets/netaddr_test/tasks/include/private.yml
new file mode 100644
index 0000000..2aaabd3
--- /dev/null
+++ b/tests/integration/targets/netaddr_test/tasks/include/private.yml
@@ -0,0 +1,12 @@
+---
+- name: "private: Check if 10.1.1.1 is a private IP address"
+ assert:
+ that: "{{ '10.1.1.1' is ansible.utils.private }}"
+
+- name: "private: Test invalidness"
+ ansible.builtin.set_fact:
+ criteria_check: "{{ '8.8.8.8' is ansible.utils.private }}"
+
+- name: "private: Assert invalidness"
+ assert:
+ that: "{{ criteria_check == false }}"
diff --git a/tests/integration/targets/netaddr_test/tasks/include/public.yml b/tests/integration/targets/netaddr_test/tasks/include/public.yml
new file mode 100644
index 0000000..eb21870
--- /dev/null
+++ b/tests/integration/targets/netaddr_test/tasks/include/public.yml
@@ -0,0 +1,12 @@
+---
+- name: "public: Check if 8.8.8.8 is a public IP address"
+ assert:
+ that: "{{ '8.8.8.8' is ansible.utils.public }}"
+
+- name: "public: Test invalidness"
+ ansible.builtin.set_fact:
+ criteria_check: "{{ '10.1.1.1' is ansible.utils.public }}"
+
+- name: "public: Assert invalidness"
+ assert:
+ that: "{{ criteria_check == false }}"
diff --git a/tests/integration/targets/netaddr_test/tasks/include/reserved.yml b/tests/integration/targets/netaddr_test/tasks/include/reserved.yml
new file mode 100644
index 0000000..20af728
--- /dev/null
+++ b/tests/integration/targets/netaddr_test/tasks/include/reserved.yml
@@ -0,0 +1,12 @@
+---
+- name: "reserved: Check if 253.0.0.1 is a reserved IP address"
+ assert:
+ that: "{{ '253.0.0.1' is ansible.utils.reserved }}"
+
+- name: "reserved: Test invalidness"
+ ansible.builtin.set_fact:
+ criteria_check: "{{ '128.146.1.7' is ansible.utils.reserved }}"
+
+- name: "reserved: Assert invalidness"
+ assert:
+ that: "{{ criteria_check == false }}"
diff --git a/tests/unit/plugins/test/test_private.py b/tests/unit/plugins/test/test_private.py
new file mode 100644
index 0000000..3a8fab0
--- /dev/null
+++ b/tests/unit/plugins/test/test_private.py
@@ -0,0 +1,40 @@
+# -*- 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: private
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import unittest
+from ansible_collections.ansible.utils.plugins.test.private import _private
+
+
+class TestPrivate(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def test_invalid_data(self):
+ """Check passing invalid argspec"""
+
+ # missing argument
+ with self.assertRaises(TypeError) as error:
+ _private()
+ self.assertIn("argument", str(error.exception))
+
+ def test_valid_data(self):
+ """Check passing valid data as per criteria"""
+
+ result = _private(ip="10.1.1.1")
+ self.assertEqual(result, True)
+
+ result = _private(ip="8.8.8.8")
+ self.assertEqual(result, False)
+
+ result = _private(ip="string")
+ self.assertEqual(result, False)
diff --git a/tests/unit/plugins/test/test_public.py b/tests/unit/plugins/test/test_public.py
new file mode 100644
index 0000000..032543c
--- /dev/null
+++ b/tests/unit/plugins/test/test_public.py
@@ -0,0 +1,40 @@
+# -*- 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: public
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import unittest
+from ansible_collections.ansible.utils.plugins.test.public import _public
+
+
+class TestPublic(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def test_invalid_data(self):
+ """Check passing invalid argspec"""
+
+ # missing argument
+ with self.assertRaises(TypeError) as error:
+ _public()
+ self.assertIn("argument", str(error.exception))
+
+ def test_valid_data(self):
+ """Check passing valid data as per criteria"""
+
+ result = _public(ip="8.8.8.8")
+ self.assertEqual(result, True)
+
+ result = _public(ip="10.1.1.1")
+ self.assertEqual(result, False)
+
+ result = _public(ip="string")
+ self.assertEqual(result, False)
diff --git a/tests/unit/plugins/test/test_reserved.py b/tests/unit/plugins/test/test_reserved.py
new file mode 100644
index 0000000..1a58056
--- /dev/null
+++ b/tests/unit/plugins/test/test_reserved.py
@@ -0,0 +1,40 @@
+# -*- 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: reserved
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import unittest
+from ansible_collections.ansible.utils.plugins.test.reserved import _reserved
+
+
+class TestReserved(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def test_invalid_data(self):
+ """Check passing invalid argspec"""
+
+ # missing argument
+ with self.assertRaises(TypeError) as error:
+ _reserved()
+ self.assertIn("argument", str(error.exception))
+
+ def test_valid_data(self):
+ """Check passing valid data as per criteria"""
+
+ result = _reserved(ip="253.0.0.1")
+ self.assertEqual(result, True)
+
+ result = _reserved(ip="128.146.1.7")
+ self.assertEqual(result, False)
+
+ result = _reserved(ip="string")
+ self.assertEqual(result, False)