mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Adds an ipmath filter (#41985)
This commit is contained in:
parent
79e366e7ba
commit
5928ec04ca
3 changed files with 79 additions and 12 deletions
|
@ -295,15 +295,15 @@ Converting subnet masks to CIDR notation
|
||||||
Given a subnet in the form of network address and subnet mask, it can be converted into CIDR notation using ``ipaddr()``. This can be useful for converting Ansible facts gathered about network configuration from subnet masks into CIDR format::
|
Given a subnet in the form of network address and subnet mask, it can be converted into CIDR notation using ``ipaddr()``. This can be useful for converting Ansible facts gathered about network configuration from subnet masks into CIDR format::
|
||||||
|
|
||||||
ansible_default_ipv4: {
|
ansible_default_ipv4: {
|
||||||
address: "192.168.0.11",
|
address: "192.168.0.11",
|
||||||
alias: "eth0",
|
alias: "eth0",
|
||||||
broadcast: "192.168.0.255",
|
broadcast: "192.168.0.255",
|
||||||
gateway: "192.168.0.1",
|
gateway: "192.168.0.1",
|
||||||
interface: "eth0",
|
interface: "eth0",
|
||||||
macaddress: "fa:16:3e:c4:bd:89",
|
macaddress: "fa:16:3e:c4:bd:89",
|
||||||
mtu: 1500,
|
mtu: 1500,
|
||||||
netmask: "255.255.255.0",
|
netmask: "255.255.255.0",
|
||||||
network: "192.168.0.0",
|
network: "192.168.0.0",
|
||||||
type: "ether"
|
type: "ether"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,6 +379,28 @@ be automatically converted to a router address (with ``::1/48`` host address)::
|
||||||
|
|
||||||
.. _6to4: https://en.wikipedia.org/wiki/6to4
|
.. _6to4: https://en.wikipedia.org/wiki/6to4
|
||||||
|
|
||||||
|
IP Math
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
.. versionadded:: 2.7
|
||||||
|
|
||||||
|
``ipmath()`` filter can be used to do simple IP math/arithmetic.
|
||||||
|
|
||||||
|
Here are a few simple examples::
|
||||||
|
|
||||||
|
# {{ '192.168.1.5' | ipmath(5) }}
|
||||||
|
192.168.1.10
|
||||||
|
|
||||||
|
# {{ '192.168.0.5' | ipmath(-10) }}
|
||||||
|
192.167.255.251
|
||||||
|
|
||||||
|
# {{ '2001::1' | ipmath(10) }}
|
||||||
|
2001::b
|
||||||
|
|
||||||
|
# {{ '2001::5' | ipmath(-10) }}
|
||||||
|
2000:ffff:ffff:ffff:ffff:ffff:ffff:fffb
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Subnet manipulation
|
Subnet manipulation
|
||||||
^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -527,5 +549,3 @@ convert it between various formats. Examples::
|
||||||
Have a question? Stop by the google group!
|
Have a question? Stop by the google group!
|
||||||
`irc.freenode.net <http://irc.freenode.net>`_
|
`irc.freenode.net <http://irc.freenode.net>`_
|
||||||
#ansible IRC chat channel
|
#ansible IRC chat channel
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -670,6 +670,23 @@ def ipaddr(value, query='', version=False, alias='ipaddr'):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def ipmath(value, amount):
|
||||||
|
try:
|
||||||
|
ip = netaddr.IPAddress(value)
|
||||||
|
except netaddr.AddrFormatError:
|
||||||
|
msg = 'You must pass a valid IP address; {0} is invalid'.format(value)
|
||||||
|
raise errors.AnsibleFilterError(msg)
|
||||||
|
|
||||||
|
if not isinstance(amount, int):
|
||||||
|
msg = (
|
||||||
|
'You must pass an integer for arithmetic; '
|
||||||
|
'{0} is not a valid integer'
|
||||||
|
).format(amount)
|
||||||
|
raise errors.AnsibleFilterError(msg)
|
||||||
|
|
||||||
|
return str(ip + amount)
|
||||||
|
|
||||||
|
|
||||||
def ipwrap(value, query=''):
|
def ipwrap(value, query=''):
|
||||||
try:
|
try:
|
||||||
if isinstance(value, (list, tuple, types.GeneratorType)):
|
if isinstance(value, (list, tuple, types.GeneratorType)):
|
||||||
|
@ -1060,6 +1077,7 @@ class FilterModule(object):
|
||||||
# IP addresses and networks
|
# IP addresses and networks
|
||||||
'cidr_merge': cidr_merge,
|
'cidr_merge': cidr_merge,
|
||||||
'ipaddr': ipaddr,
|
'ipaddr': ipaddr,
|
||||||
|
'ipmath': ipmath,
|
||||||
'ipwrap': ipwrap,
|
'ipwrap': ipwrap,
|
||||||
'ip4_hex': ip4_hex,
|
'ip4_hex': ip4_hex,
|
||||||
'ipv4': ipv4,
|
'ipv4': ipv4,
|
||||||
|
|
|
@ -20,8 +20,10 @@ __metaclass__ = type
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from ansible.compat.tests import unittest
|
from ansible.compat.tests import unittest
|
||||||
|
from ansible.errors import AnsibleFilterError
|
||||||
from ansible.plugins.filter.ipaddr import (ipaddr, _netmask_query, nthhost, next_nth_usable,
|
from ansible.plugins.filter.ipaddr import (ipaddr, _netmask_query, nthhost, next_nth_usable,
|
||||||
previous_nth_usable, network_in_usable, network_in_network, cidr_merge)
|
previous_nth_usable, network_in_usable, network_in_network,
|
||||||
|
cidr_merge, ipmath)
|
||||||
netaddr = pytest.importorskip('netaddr')
|
netaddr = pytest.importorskip('netaddr')
|
||||||
|
|
||||||
|
|
||||||
|
@ -473,3 +475,30 @@ class TestIpFilter(unittest.TestCase):
|
||||||
subnets = ['1.12.1.1', '1.12.1.255']
|
subnets = ['1.12.1.1', '1.12.1.255']
|
||||||
self.assertEqual(cidr_merge(subnets), ['1.12.1.1/32', '1.12.1.255/32'])
|
self.assertEqual(cidr_merge(subnets), ['1.12.1.1/32', '1.12.1.255/32'])
|
||||||
self.assertEqual(cidr_merge(subnets, 'span'), '1.12.1.0/24')
|
self.assertEqual(cidr_merge(subnets, 'span'), '1.12.1.0/24')
|
||||||
|
|
||||||
|
def test_ipmath(self):
|
||||||
|
self.assertEqual(ipmath('192.168.1.5', 5), '192.168.1.10')
|
||||||
|
self.assertEqual(ipmath('192.168.1.5', -5), '192.168.1.0')
|
||||||
|
self.assertEqual(ipmath('192.168.0.5', -10), '192.167.255.251')
|
||||||
|
|
||||||
|
self.assertEqual(ipmath('2001::1', 8), '2001::9')
|
||||||
|
self.assertEqual(ipmath('2001::1', 9), '2001::a')
|
||||||
|
self.assertEqual(ipmath('2001::1', 10), '2001::b')
|
||||||
|
self.assertEqual(ipmath('2001::5', -3), '2001::2')
|
||||||
|
self.assertEqual(
|
||||||
|
ipmath('2001::5', -10),
|
||||||
|
'2000:ffff:ffff:ffff:ffff:ffff:ffff:fffb'
|
||||||
|
)
|
||||||
|
|
||||||
|
expected = 'You must pass a valid IP address; invalid_ip is invalid'
|
||||||
|
with self.assertRaises(AnsibleFilterError) as exc:
|
||||||
|
ipmath('invalid_ip', 8)
|
||||||
|
self.assertEqual(exc.exception.message, expected)
|
||||||
|
|
||||||
|
expected = (
|
||||||
|
'You must pass an integer for arithmetic; '
|
||||||
|
'some_number is not a valid integer'
|
||||||
|
)
|
||||||
|
with self.assertRaises(AnsibleFilterError) as exc:
|
||||||
|
ipmath('1.2.3.4', 'some_number')
|
||||||
|
self.assertEqual(exc.exception.message, expected)
|
||||||
|
|
Loading…
Reference in a new issue