Skip to content
This repository has been archived by the owner on May 15, 2019. It is now read-only.

Commit

Permalink
Add normalize_address normalize_prefix Jinja filters (#64)
Browse files Browse the repository at this point in the history
* add normalize_address jinja filter and rename addrmask_to_cidr to normalize_prefix

* add unit tests for normalize_prefix and normalize_address

* add unit tests fot the rest of ip_filters

* add filter prefix_to_addrmask that curns CIDR represented subnets into address mask representation

* make cidr_to_netmask return str
  • Loading branch information
matejv authored and dbarrosop committed Jun 18, 2017
1 parent a5d792c commit 771e1d3
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 5 deletions.
45 changes: 40 additions & 5 deletions napalm_yang/jinja_filters/ip_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ def filters():
return {
"netmask_to_cidr": netmask_to_cidr,
"cidr_to_netmask": cidr_to_netmask,
"addrmask_to_cidr": addrmask_to_cidr,
"normalize_prefix": normalize_prefix,
"normalize_address": normalize_address,
"prefix_to_addrmask": prefix_to_addrmask,
}


Expand All @@ -26,16 +28,49 @@ def cidr_to_netmask(value):
Examples:
>>> "{{ '24'|cidr_to_netmask }}" -> "255.255.255.0"
"""
return netaddr.IPNetwork("1.1.1.1/{}".format(value)).netmask
return str(netaddr.IPNetwork("1.1.1.1/{}".format(value)).netmask)


def addrmask_to_cidr(value):
def normalize_prefix(value):
"""
Converts an address and network mask to it's CIDR representation.
Converts an IPv4 or IPv6 prefix writen in various formats to its CIDR representation.
This filter works only on prefixes. Use normalize_address if you wish to normalize an address
without a network mask.
Examples:
>>> "{{ '192.168.0.0 255.255.255.0'|addrmask_to_cidr }}" -> "192.168.0.0/24"
>>> "{{ '192.168.0.0 255.255.255.0'|normalize_prefix }}" -> "192.168.0.0/24"
>>> "{{ '192.168/255.255.255.0'|normalize_prefix }}" -> "192.168.0.0/24"
>>> "{{ '2001:DB8:0:0:1:0:0:1/64'|normalize_prefix }}" -> "2001:db8::1:0:0:1/64"
"""
value = value.replace(' ', '/')
return str(netaddr.IPNetwork(value))


def normalize_address(value):
"""
Converts an IPv4 or IPv6 address writen in various formats to a standard textual representation.
This filter works only on addresses without network mask. Use normalize_prefix to normalize
networks.
Examples:
>>> "{{ '192.168.0.1'|normalize_address }}" -> "192.168.0.1"
>>> "{{ '192.168.1'|normalize_address }}" -> "192.168.0.1"
>>> "{{ '2001:DB8:0:0:1:0:0:1'|normalize_address }}" -> "2001:db8::1:0:0:1"
"""
return str(netaddr.IPAddress(value))


def prefix_to_addrmask(value, sep=' '):
"""
Converts a CIDR formatted prefix into an address netmask representation.
Argument sep specifies the separator between the address and netmask parts. By default it's a single space.
Examples:
>>> "{{ '192.168.0.1/24|prefix_to_addrmask }}" -> "192.168.0.1 255.255.255.0"
>>> "{{ '192.168.0.1/24|prefix_to_addrmask('/') }}" -> "192.168.0.1/255.255.255.0"
"""
prefix = netaddr.IPNetwork(value)
return '{}{}{}'.format(prefix.ip, sep, prefix.netmask)
115 changes: 115 additions & 0 deletions test/unit/test_jinja_filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
"""
Test Jinja filters
"""

# Python3 support
from __future__ import print_function
from __future__ import unicode_literals

# Python std lib
import unittest

# third party libs
try:
from netaddr.core import AddrFormatError
HAS_NETADDR = True
except ImportError:
HAS_NETADDR = False

from napalm_yang.jinja_filters import ip_filters, load_filters


class TestJinjaFilters(unittest.TestCase):
def test_netmask_to_cidr(self):
"""
Tests Jinja2 filter ```netmask_to_cidr```:
* check if load_filters returns the correct function
* check if raises AddrFormatError on invalid mask
* check if prefix length is returned as expected
"""

self.assertTrue(HAS_NETADDR)

self.assertEqual(load_filters()['netmask_to_cidr'], ip_filters.netmask_to_cidr)

self.assertRaises(AddrFormatError, ip_filters.netmask_to_cidr, 'bad')

self.assertEqual(ip_filters.netmask_to_cidr('255.255.255.0'), 24)
self.assertEqual(ip_filters.netmask_to_cidr('255.255.255.255'), 32)

def test_cidr_to_netmask(self):
"""
Tests Jinja2 filter ```cidr_to_netmask```:
* check if load_filters returns the correct function
* check if raises AddrFormatError on invalid prefix length
* check if network mask is returned as expected
"""

self.assertTrue(HAS_NETADDR)

self.assertEqual(load_filters()['cidr_to_netmask'], ip_filters.cidr_to_netmask)

self.assertRaises(AddrFormatError, ip_filters.cidr_to_netmask, 'bad')

self.assertEqual(ip_filters.cidr_to_netmask(24), '255.255.255.0')
self.assertEqual(ip_filters.cidr_to_netmask('24'), '255.255.255.0')
self.assertEqual(ip_filters.cidr_to_netmask(32), '255.255.255.255')

def test_normalize_prefix(self):
"""
Tests Jinja2 filter ```normalize_prefix```:
* check if load_filters returns the correct function
* check if raises AddrFormatError on invalid prefix
* check if IPv4 and IPv6 prefix format is returned as expected
"""

self.assertTrue(HAS_NETADDR)

self.assertEqual(load_filters()['normalize_prefix'], ip_filters.normalize_prefix)

self.assertRaises(AddrFormatError, ip_filters.normalize_prefix, 'bad')

self.assertEqual(ip_filters.normalize_prefix('192.168.0.1'), '192.168.0.1/32')
self.assertEqual(ip_filters.normalize_prefix('192.168.0.55 255.255.255.0'), '192.168.0.55/24')
self.assertEqual(ip_filters.normalize_prefix('192.168.0.55/255.255.255.0'), '192.168.0.55/24')
self.assertEqual(ip_filters.normalize_prefix('2001:0DB8:0:0000:1:0:0:1/64'), '2001:db8::1:0:0:1/64')

def test_normalize_address(self):
"""
Tests Jinja2 filter ```normalize_address```:
* check if load_filters returns the correct function
* check if raises AddrFormatError on invalid address
* check if IPv4 and IPv6 address format is returned as expected
"""

self.assertTrue(HAS_NETADDR)

self.assertEqual(load_filters()['normalize_address'], ip_filters.normalize_address)

self.assertRaises(AddrFormatError, ip_filters.normalize_address, 'bad')

self.assertEqual(ip_filters.normalize_address('192.168.0.1'), '192.168.0.1')
self.assertEqual(ip_filters.normalize_address('192.168.1'), '192.168.0.1')
self.assertEqual(ip_filters.normalize_address('2001:0DB8:0:0000:1:0:0:1'), '2001:db8::1:0:0:1')

def test_prefix_to_addrmask(self):
"""
Tests Jinja2 filter ```prefix_to_addrmask```:
* check if load_filters returns the correct function
* check if raises AddrFormatError on invalid prefix
* check if IPv4 address and netmask format is returned as expected
"""

self.assertTrue(HAS_NETADDR)

self.assertEqual(load_filters()['prefix_to_addrmask'], ip_filters.prefix_to_addrmask)

self.assertRaises(AddrFormatError, ip_filters.prefix_to_addrmask, 'bad')

self.assertEqual(ip_filters.prefix_to_addrmask('192.168.0.1/24'), '192.168.0.1 255.255.255.0')
self.assertEqual(ip_filters.prefix_to_addrmask('192.168.0.0/32', '/'), '192.168.0.0/255.255.255.255')

0 comments on commit 771e1d3

Please sign in to comment.