Skip to content

Commit

Permalink
Feature ipv6 format (#295)
Browse files Browse the repository at this point in the history
* Create ipv6form.py

* Update ipv6form.py

* Update ipv6form.py

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

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

* Add code

* Add docs

* Add uts and integration tests. fix sanity

* iFix sanity

* Fix sanity

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Ashwini Mhatre <[email protected]>
  • Loading branch information
3 people authored Aug 10, 2023
1 parent ce5e10c commit 4deddf2
Show file tree
Hide file tree
Showing 6 changed files with 420 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Name | Description
[ansible.utils.ipsubnet](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.ipsubnet_filter.rst)|This filter can be used to manipulate network subnets in several ways.
[ansible.utils.ipv4](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.ipv4_filter.rst)|To filter only Ipv4 addresses Ipv4 filter is used.
[ansible.utils.ipv6](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.ipv6_filter.rst)|To filter only Ipv6 addresses Ipv6 filter is used.
[ansible.utils.ipv6form](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.ipv6form_filter.rst)|This filter is designed to convert ipv6 address in different formats. For example expand, compressetc.
[ansible.utils.ipwrap](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.ipwrap_filter.rst)|This filter is designed to Wrap IPv6 addresses in [ ] brackets.
[ansible.utils.keep_keys](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.keep_keys_filter.rst)|Keep specific keys from a data recursively.
[ansible.utils.macaddr](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.macaddr_filter.rst)|macaddr / MAC address filters
Expand Down
3 changes: 3 additions & 0 deletions changelogs/fragments/ipv6form.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
minor_changes:
- Add ipv6form filter plugin.(https://github.com/ansible-collections/ansible.utils/issues/230)
165 changes: 165 additions & 0 deletions docs/ansible.utils.ipv6form_filter.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
.. _ansible.utils.ipv6form_filter:


**********************
ansible.utils.ipv6form
**********************

**This filter is designed to convert ipv6 address in different formats. For example expand, compressetc.**


Version added: 2.11.0

.. contents::
:local:
:depth: 1


Synopsis
--------
- This filter is designed to convert ipv6 addresses in different formats.




Parameters
----------

.. raw:: html

<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th>Configuration</th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>format</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
</td>
<td>
<div>Different formats example. compress, expand, x509</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>value</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
/ <span style="color: red">required</span>
</div>
</td>
<td>
</td>
<td>
</td>
<td>
<div>individual ipv6 address input for ipv6_format plugin.</div>
</td>
</tr>
</table>
<br/>




Examples
--------

.. code-block:: yaml
#### examples
# Ipv6form filter plugin with different format.
- name: Expand given Ipv6 address
debug:
msg: "{{ '1234:4321:abcd:dcba::17' | ansible.utils.ipv6form('expand') }}"
- name: Compress given Ipv6 address
debug:
msg: "{{ '1234:4321:abcd:dcba:0000:0000:0000:0017' | ansible.utils.ipv6form('compress') }}"
- name: Covert given Ipv6 address in x509
debug:
msg: "{{ '1234:4321:abcd:dcba::17' | ansible.utils.ipv6form('x509') }}"
# TASK [Expand given Ipv6 address] ************************************************************************************
# task path: /home/amhatre/dev/playbook/test_ipform.yaml:7
# Loading collection ansible.utils from /home/amhatre/dev/collections/ansible_collections/ansible/utils
# ok: [localhost] => {
# "msg": "1234:4321:abcd:dcba:0000:0000:0000:0017"
# }
# TASK [Compress given Ipv6 address] *********************************************************************************
# task path: /home/amhatre/dev/playbook/test_ipform.yaml:11
# Loading collection ansible.utils from /home/amhatre/dev/collections/ansible_collections/ansible/utils
# ok: [localhost] => {
# "msg": "1234:4321:abcd:dcba::17"
# }
# TASK [Covert given Ipv6 address in x509] ****************************************************************************
# task path: /home/amhatre/dev/playbook/test_ipform.yaml:15
# Loading collection ansible.utils from /home/amhatre/dev/collections/ansible_collections/ansible/utils
# ok: [localhost] => {
# "msg": "1234:4321:abcd:dcba:0:0:0:17"
# }
# PLAY RECAP **********************************************************************************************************
# localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this filter:

.. raw:: html

<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Key</th>
<th>Returned</th>
<th width="100%">Description</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>data</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td></td>
<td>
<div>Returns result ipv6 address in expected format.</div>
<br/>
</td>
</tr>
</table>
<br/><br/>


Status
------


Authors
~~~~~~~

- Ashwini Mhatre (@amhatre)


.. 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.
176 changes: 176 additions & 0 deletions plugins/filter/ipv6form.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
# -*- 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)

"""
filter plugin file for ipaddr filters: ipv6form
"""
from __future__ import absolute_import, division, print_function

from functools import partial

from ansible.errors import AnsibleFilterError

from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import (
AnsibleArgSpecValidator,
)
from ansible_collections.ansible.utils.plugins.plugin_utils.base.ipaddr_utils import _need_netaddr
from ansible_collections.ansible.utils.plugins.plugin_utils.base.ipaddress_utils import (
_need_ipaddress,
ip_address,
)


__metaclass__ = type


try:
from jinja2.filters import pass_environment
except ImportError:
from jinja2.filters import environmentfilter as pass_environment


try:
import netaddr

HAS_NETADDR = True
except ImportError:
# in this case, we'll make the filters return error messages (see bottom)
HAS_NETADDR = False
else:

class mac_linux(netaddr.mac_unix):
pass

mac_linux.word_fmt = "%.2x"


DOCUMENTATION = """
name: ipv6form
author: Ashwini Mhatre (@amhatre)
version_added: "2.11.0"
short_description: This filter is designed to convert ipv6 address in different formats. For example expand, compressetc.
description:
- This filter is designed to convert ipv6 addresses in different formats.
options:
value:
description:
- individual ipv6 address input for ipv6_format plugin.
type: str
required: True
format:
type: str
choice:
['compress', 'expand', 'x509']
description: Different formats example. compress, expand, x509
"""

EXAMPLES = r"""
#### examples
# Ipv6form filter plugin with different format.
- name: Expand given Ipv6 address
debug:
msg: "{{ '1234:4321:abcd:dcba::17' | ansible.utils.ipv6form('expand') }}"
- name: Compress given Ipv6 address
debug:
msg: "{{ '1234:4321:abcd:dcba:0000:0000:0000:0017' | ansible.utils.ipv6form('compress') }}"
- name: Covert given Ipv6 address in x509
debug:
msg: "{{ '1234:4321:abcd:dcba::17' | ansible.utils.ipv6form('x509') }}"
# TASK [Expand given Ipv6 address] ************************************************************************************
# task path: /home/amhatre/dev/playbook/test_ipform.yaml:7
# Loading collection ansible.utils from /home/amhatre/dev/collections/ansible_collections/ansible/utils
# ok: [localhost] => {
# "msg": "1234:4321:abcd:dcba:0000:0000:0000:0017"
# }
# TASK [Compress given Ipv6 address] *********************************************************************************
# task path: /home/amhatre/dev/playbook/test_ipform.yaml:11
# Loading collection ansible.utils from /home/amhatre/dev/collections/ansible_collections/ansible/utils
# ok: [localhost] => {
# "msg": "1234:4321:abcd:dcba::17"
# }
# TASK [Covert given Ipv6 address in x509] ****************************************************************************
# task path: /home/amhatre/dev/playbook/test_ipform.yaml:15
# Loading collection ansible.utils from /home/amhatre/dev/collections/ansible_collections/ansible/utils
# ok: [localhost] => {
# "msg": "1234:4321:abcd:dcba:0:0:0:17"
# }
# PLAY RECAP **********************************************************************************************************
# localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
"""

RETURN = """
data:
type: str
description:
- Returns result ipv6 address in expected format.
"""


@pass_environment
def _ipv6form(*args, **kwargs):
"""Convert the given data from json to xml."""
keys = ["value", "format"]
data = dict(zip(keys, args[1:]))
data.update(kwargs)
aav = AnsibleArgSpecValidator(data=data, schema=DOCUMENTATION, name="ipv6form")
valid, errors, updated_data = aav.validate()
if not valid:
raise AnsibleFilterError(errors)
return ipv6form(**updated_data)


@_need_ipaddress
def ipv6form(value, format):
try:
if format == "expand":
return ip_address(value).exploded
elif format == "compress":
return ip_address(value).compressed
elif format == "x509":
return _handle_x509(value)
except ValueError:
msg = "You must pass a valid IP address; {0} is invalid".format(value)
raise AnsibleFilterError(msg)

if not isinstance(format, str):
msg = ("You must pass valid format; " "{0} is not a valid format").format(
format,
)
raise AnsibleFilterError(msg)


def _handle_x509(value):
"""Convert ipv6 address into x509 format"""
ip = netaddr.IPAddress(value)
ipv6_oct = []
ipv6address = ip.bits().split(":")
for i in ipv6address:
x = hex(int(i, 2))
ipv6_oct.append(x.replace("0x", ""))
return str(":".join(ipv6_oct))


class FilterModule(object):
"""IP address and network manipulation filters"""

filter_map = {
# This filter is designed to do ipv6 conversion in required format
"ipv6form": _ipv6form,
}

def filters(self):
"""ipv6form filter"""
if HAS_NETADDR:
return self.filter_map
else:
return dict((f, partial(_need_netaddr, f)) for f in self.filter_map)
32 changes: 32 additions & 0 deletions tests/integration/targets/utils_ipaddr_filter/tasks/ipv6form.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
- name: Expand ipv6 address
ansible.builtin.set_fact:
result1: "{{ '1234:4321:abcd:dcba::17'|ansible.utils.ipv6form ('expand')}}"

- name: Assert result for ipv6form.
ansible.builtin.assert:
that: "{{ result1 == '1234:4321:abcd:dcba:0000:0000:0000:0017' }}"

- name: Compress ipv6 address
ansible.builtin.set_fact:
result1: "{{ '1234:4321:abcd:dcba:0000:0000:0000:0017'|ansible.utils.ipv6form ('compress') }}"

- name: Assert result for ipv6form.
ansible.builtin.assert:
that: "{{ result1 == '1234:4321:abcd:dcba::17' }}"

- name: Convert ipv6 address into x509 form used by digital certificate
ansible.builtin.set_fact:
result1: "{{ '1234:4321:abcd:dcba::17'|ansible.utils.ipv6form ('x509') }}"

- name: Assert result for ipv6form.
ansible.builtin.assert:
that: "{{ result1 == '1234:4321:abcd:dcba:0:0:0:17' }}"

- name: Convert ipv6 address into x509 form used by digital certificate
ansible.builtin.set_fact:
result1: "{{ '1234:4321:abcd:dcba:0000:0000:0000:0017'|ansible.utils.ipv6form ('x509') }}"

- name: Assert result for ipv6form.
ansible.builtin.assert:
that: "{{ result1 == '1234:4321:abcd:dcba:0:0:0:17' }}"
Loading

0 comments on commit 4deddf2

Please sign in to comment.