Add validator to check for IP or subnet or none

This adds a validator to check if a value is an IP address, an IP
subnet, or none.

This was originally part of the neutron-fwaas API definition migration
to neutron-lib[1], but it was suggested that this should be pulled into
a separate change.

[1] https://review.openstack.org/389388

Change-Id: I8dcf49adc7754d0c9aa0479ede2de481325bb3e3
This commit is contained in:
Nate Johnston 2016-12-07 02:31:57 +00:00
parent 322ae30246
commit bddc699eef
3 changed files with 67 additions and 0 deletions

View File

@ -540,6 +540,22 @@ def validate_ip_address_or_none(data, valid_values=None):
return validate_ip_address(data, valid_values)
def validate_ip_or_subnet_or_none(data, valid_values=None):
"""Validate data is an IP address, a valid IP subnet string, or None.
:param data: The data to validate.
:param valid_values: Not used!
:return: None if data is None or a valid IP address or a valid IP subnet,
otherwise a human readable message indicating why the data is neither an
IP address nor IP subnet.
"""
msg_ip = validate_ip_address_or_none(data)
msg_subnet = validate_subnet_or_none(data)
if msg_ip is not None and msg_subnet is not None:
return _("'%(data)s' is neither a valid IP address, nor "
"is it a valid IP subnet") % {'data': data}
def validate_subnet(data, valid_values=None):
"""Validate data is an IP network subnet string.
@ -888,6 +904,7 @@ validators = {'type:dict': validate_dict,
'type:hostroutes': validate_hostroutes,
'type:ip_address': validate_ip_address,
'type:ip_address_or_none': validate_ip_address_or_none,
'type:ip_or_subnet_or_none': validate_ip_or_subnet_or_none,
'type:ip_pools': validate_ip_pools,
'type:mac_address': validate_mac_address,
'type:mac_address_or_none': validate_mac_address_or_none,

View File

@ -1026,3 +1026,50 @@ class TestAttributeValidation(base.BaseTestCase):
{'port_id': '11111111-ffff-ffff-ffff-000000000000'},
]
self.assertIsNone(validators.validate_subports(body))
class TestValidateIPSubnetNone(base.BaseTestCase):
def test_validate_none(self):
self.assertIsNone(validators.validate_ip_or_subnet_or_none(None))
def test_validate_ipv4(self):
testdata = "172.0.0.1"
self.assertIsNone(validators.validate_ip_or_subnet_or_none(testdata))
def test_validate_ipv4_subnet(self):
testdata = "172.0.0.1/24"
self.assertIsNone(validators.validate_ip_or_subnet_or_none(testdata))
def test_validate_ipv6(self):
testdata = "2001:0db8:0a0b:12f0:0000:0000:0000:0001"
self.assertIsNone(validators.validate_ip_or_subnet_or_none(testdata))
def test_validate_ipv6_subnet(self):
testdata = "::1/128"
self.assertIsNone(validators.validate_ip_or_subnet_or_none(testdata))
def test_validate_ipv4_invalid(self):
testdata = "300.0.0.1"
self.assertEqual(("'300.0.0.1' is neither a valid IP address, nor is "
"it a valid IP subnet"),
validators.validate_ip_or_subnet_or_none(testdata))
def test_validate_ipv4_subnet_invalid(self):
testdata = "172.0.0.1/45"
self.assertEqual(("'172.0.0.1/45' is neither a valid IP address, nor "
"is it a valid IP subnet"),
validators.validate_ip_or_subnet_or_none(testdata))
def test_validate_ipv6_invalid(self):
testdata = "xxxx:0db8:0a0b:12f0:0000:0000:0000:0001"
self.assertEqual(("'xxxx:0db8:0a0b:12f0:0000:0000:0000:0001' is "
"neither a valid IP address, nor is it a valid IP "
"subnet"),
validators.validate_ip_or_subnet_or_none(testdata))
def test_validate_ipv6_subnet_invalid(self):
testdata = "::1/2048"
self.assertEqual(("'::1/2048' is neither a valid IP address, nor is "
"it a valid IP subnet"),
validators.validate_ip_or_subnet_or_none(testdata))

View File

@ -0,0 +1,3 @@
---
features:
- Added validator validate_ip_or_subnet_or_none