Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ipcut filter plugin #291

Merged
merged 17 commits into from
Aug 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/release-drafter.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
---
# see https://github.com/ansible-community/devtools
_extends: ansible-community/devtools
3 changes: 2 additions & 1 deletion .github/workflows/ack.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
---
# See https://github.com/ansible-community/devtools/blob/main/.github/workflows/ack.yml
name: ack

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

on:
on: # yamllint disable-line rule:truthy
pull_request_target:
types: [opened, labeled, unlabeled, synchronize]

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/codecoverage.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: code_coverage

on:
on: # yamllint disable-line rule:truthy
push:
pull_request:
branches: [ main ]
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/push.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
---
# push workflow is shared and expected to perform actions after a merge happens
# on a maintenance branch (default or release). For example updating the
# draft release-notes.
Expand All @@ -9,7 +10,7 @@ concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

on:
on: # yamllint disable-line rule:truthy
push:
# branches to consider in the event; optional, defaults to all
branches:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: release
on:
on: # yamllint disable-line rule:truthy
release:
types: [published]

Expand Down
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
---
name: tests

concurrency:
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/token_refresh.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
name: refresh_automation_hub_token
on:
on: # yamllint disable-line rule:truthy
schedule:
- cron: '0 0 * * *'
workflow_dispatch:
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Name | Description
[ansible.utils.index_of](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.index_of_filter.rst)|Find the indices of items in a list matching some criteria
[ansible.utils.ip4_hex](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.ip4_hex_filter.rst)|This filter is designed to convert IPv4 address to Hexadecimal notation with optional delimiter.
[ansible.utils.ipaddr](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.ipaddr_filter.rst)|This filter is designed to return the input value if a query is True, else False.
[ansible.utils.ipcut](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.ipcut_filter.rst)|This filter is designed to get 1st or last few bits of IP address.
[ansible.utils.ipmath](https://github.com/ansible-collections/ansible.utils/blob/main/docs/ansible.utils.ipmath_filter.rst)|This filter is designed to do simple IP math/arithmetic.
[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.
Expand Down
3 changes: 3 additions & 0 deletions changelogs/fragments/ipcut.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
minor_changes:
- Add ipcut filter plugin.(https://github.com/ansible-collections/ansible.utils/issues/251)
150 changes: 150 additions & 0 deletions docs/ansible.utils.ipcut_filter.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
.. _ansible.utils.ipcut_filter:


*******************
ansible.utils.ipcut
*******************

**This filter is designed to get 1st or last few bits of IP address.**


Version added: 2.11.0

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


Synopsis
--------
- This filter is designed to fetch 1st or last few bits of Ip address.




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>amount</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
</td>
<td>
</td>
<td>
<div>integer for arithmetic. Example -1,2,3</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>list of subnets or individual address or any other values input for ip_cut plugin</div>
</td>
</tr>
</table>
<br/>




Examples
--------

.. code-block:: yaml

#### examples
- name: Get first 64 bits of Ipv6 address
debug:
msg: "{{ '1234:4321:abcd:dcba::17' | ansible.utils.ipcut(64) }}"

- name: Get last 80 bits of Ipv6 address
debug:
msg: "{{ '1234:4321:abcd:dcba::17' | ansible.utils.ipcut(-80) }}"
# PLAY [IPCUT filter plugin examples] ************************************************************************************************

# TASK [Get first X bits of Ipv6 address] ********************************************************************************************
# ok: [localhost] => {
# "msg": "1234:4321:abcd:dcba"
# }

# TASK [Get last X bits of Ipv6 address] *********************************************************************************************
# ok: [localhost] => {
# "msg": "dcba:0:0:0:17"
# }

# PLAY RECAP *************************************************************************************************************************
# localhost : ok=2 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 of portion of IP.</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.
152 changes: 152 additions & 0 deletions plugins/filter/ipcut.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# -*- coding: utf-8 -*-
# Copyright 2023 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: ip_cut
"""
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


__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: ipcut
author: Ashwini Mhatre (@amhatre)
version_added: "2.11.0"
short_description: This filter is designed to get 1st or last few bits of IP address.
description:
- This filter is designed to fetch 1st or last few bits of Ip address.
options:
value:
description:
- list of subnets or individual address or any other values input for ip_cut plugin
type: str
required: True
amount:
type: int
description: integer for arithmetic. Example -1,2,3
"""

EXAMPLES = r"""
#### examples
- name: Get first 64 bits of Ipv6 address
debug:
msg: "{{ '1234:4321:abcd:dcba::17' | ansible.utils.ipcut(64) }}"

- name: Get last 80 bits of Ipv6 address
debug:
msg: "{{ '1234:4321:abcd:dcba::17' | ansible.utils.ipcut(-80) }}"
# PLAY [IPCUT filter plugin examples] ************************************************************************************************

# TASK [Get first X bits of Ipv6 address] ********************************************************************************************
# ok: [localhost] => {
# "msg": "1234:4321:abcd:dcba"
# }

# TASK [Get last X bits of Ipv6 address] *********************************************************************************************
# ok: [localhost] => {
# "msg": "dcba:0:0:0:17"
# }

# PLAY RECAP *************************************************************************************************************************
# localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
"""

RETURN = """
data:
type: str
description:
- Returns result of portion of IP.
"""


@pass_environment
def _ipcut(*args, **kwargs):
"""Fetch first or last bits of IPV6 address"""
keys = ["value", "amount"]
data = dict(zip(keys, args[1:]))
data.update(kwargs)
aav = AnsibleArgSpecValidator(data=data, schema=DOCUMENTATION, name="ipmath")
valid, errors, updated_data = aav.validate()
if not valid:
raise AnsibleFilterError(errors)
return ipcut(**updated_data)


def ipcut(value, amount):
ipv6_oct = []
try:
ip = netaddr.IPAddress(value)
ipv6address = ip.bits().replace(":", "")
except (netaddr.AddrFormatError, ValueError):
msg = "You must pass a valid IP address; {0} is invalid".format(value)
raise AnsibleFilterError(msg)

if not isinstance(amount, int):
msg = ("You must pass an integer for arithmetic; " "{0} is not a valid integer").format(
amount,
)
raise AnsibleFilterError(msg)
else:
if amount < 0:
ipsub = ipv6address[amount:]
else:
ipsub = ipv6address[0:amount]

ipsubfinal = []

for i in range(0, len(ipsub), 16):
oct_sub = i + 16
ipsubfinal.append(ipsub[i:oct_sub])

for i in ipsubfinal:
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 fetch first or last bits of IPV6 address
"ipcut": _ipcut,
}

def filters(self):
"""ipcut filter"""
if HAS_NETADDR:
return self.filter_map
else:
return dict((f, partial(_need_netaddr, f)) for f in self.filter_map)
2 changes: 1 addition & 1 deletion plugins/filter/next_nth_usable.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def next_nth_usable(value, offset):
except Exception:
return False

if type(offset) != int:
if type(offset) is not int:
raise AnsibleFilterError("Must pass in an integer")
if v.size > 1:
first_usable, last_usable = _first_last(v)
Expand Down
2 changes: 1 addition & 1 deletion plugins/filter/previous_nth_usable.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def previous_nth_usable(value, offset):
except Exception:
return False

if type(offset) != int:
if type(offset) is not int:
raise AnsibleFilterError("Must pass in an integer")
if v.size > 1:
first_usable, last_usable = _first_last(v)
Expand Down
Loading
Loading