Merge "Add CIDR format validation"

This commit is contained in:
Jenkins 2015-05-15 17:40:44 +00:00 committed by Gerrit Code Review
commit f81cb5dbd1
9 changed files with 80 additions and 15 deletions

View File

@ -11,10 +11,8 @@
# License for the specific language governing permissions and limitations
# under the License.
import netaddr
from oslo_log import log as logging
from heat.common import exception
from heat.common.i18n import _
from heat.common.i18n import _LW
from heat.engine import attributes
@ -79,7 +77,10 @@ class CloudNetwork(resource.Resource):
properties.Schema.STRING,
_("The IP block from which to allocate the network. For example, "
"172.16.0.0/24 or 2001:DB8::/64."),
required=True
required=True,
constraints=[
constraints.CustomConstraint('net_cidr')
]
)
}
@ -154,10 +155,6 @@ class CloudNetwork(resource.Resource):
def validate(self):
super(CloudNetwork, self).validate()
try:
netaddr.IPNetwork(self.properties[self.CIDR])
except netaddr.core.AddrFormatError:
raise exception.StackValidationFailed(message=_("Invalid cidr"))
def _resolve_attribute(self, name):
net = self.network()

View File

@ -116,12 +116,15 @@ class CloudNetworkTest(common.HeatTestCase):
self.assertEqual(expect_label, res.FnGetAtt('label'))
self.assertEqual(expect_cidr, res.FnGetAtt('cidr'))
def test_create_bad_cider(self, mock_client):
self._template['resources']['cnw']['properties']['cidr'] = "bad cidr"
def test_create_bad_cidr(self, mock_client):
prop = self._template['resources']['cnw']['properties']
prop['cidr'] = "bad cidr"
self._parse_stack()
exc = self.assertRaises(exception.StackValidationFailed,
self.stack.validate)
self.assertIn("Invalid cidr", six.text_type(exc))
self.assertIn("Invalid net cidr", six.text_type(exc))
# reset property
prop['cidr'] = "172.16.0.0/24"
def test_check(self, mock_client):
self._setup_stack(mock_client)

View File

@ -12,6 +12,7 @@
# under the License.
import netaddr
import six
from neutronclient.common import exceptions
from neutronclient.neutron import v2_0 as neutronV20
@ -189,3 +190,21 @@ class MACConstraint(constraints.BaseCustomConstraint):
def validate(self, value, context):
self._error_message = 'Invalid MAC address.'
return netaddr.valid_mac(value)
class CIDRConstraint(constraints.BaseCustomConstraint):
def _validate_whitespace(self, data):
self._error_message = ("Invalid net cidr '%s' contains "
"whitespace" % data)
if len(data.split()) > 1:
return False
return True
def validate(self, value, context):
try:
netaddr.IPNetwork(value)
return self._validate_whitespace(value)
except Exception as ex:
self._error_message = 'Invalid net cidr %s ' % six.text_type(ex)
return False

View File

@ -298,12 +298,18 @@ class FirewallRule(neutron.NeutronResource):
SOURCE_IP_ADDRESS: properties.Schema(
properties.Schema.STRING,
_('Source IP address or CIDR.'),
update_allowed=True
update_allowed=True,
constraints=[
constraints.CustomConstraint('net_cidr')
]
),
DESTINATION_IP_ADDRESS: properties.Schema(
properties.Schema.STRING,
_('Destination IP address or CIDR.'),
update_allowed=True
update_allowed=True,
constraints=[
constraints.CustomConstraint('net_cidr')
]
),
SOURCE_PORT: properties.Schema(
properties.Schema.STRING,

View File

@ -105,7 +105,10 @@ class SecurityGroup(neutron.NeutronResource):
RULE_REMOTE_IP_PREFIX: properties.Schema(
properties.Schema.STRING,
_('The remote IP prefix (CIDR) to be associated with this '
'security group rule.')
'security group rule.'),
constraints=[
constraints.CustomConstraint('net_cidr')
]
),
}

View File

@ -84,7 +84,10 @@ class Subnet(neutron.NeutronResource):
CIDR: properties.Schema(
properties.Schema.STRING,
_('The CIDR.'),
required=True
required=True,
constraints=[
constraints.CustomConstraint('net_cidr')
]
),
VALUE_SPECS: properties.Schema(
properties.Schema.MAP,

View File

@ -219,7 +219,13 @@ class IPsecSiteConnection(neutron.NeutronResource):
PEER_CIDRS: properties.Schema(
properties.Schema.LIST,
_('Remote subnet(s) in CIDR format.'),
required=True
required=True,
schema=properties.Schema(
properties.Schema.STRING,
constraints=[
constraints.CustomConstraint('net_cidr')
]
)
),
MTU: properties.Schema(
properties.Schema.INTEGER,

View File

@ -254,3 +254,30 @@ class TestMACConstraint(common.HeatTestCase):
]
for mac in invalidate_format:
self.assertFalse(self.constraint.validate(mac, None))
class TestCIDRConstraint(common.HeatTestCase):
def setUp(self):
super(TestCIDRConstraint, self).setUp()
self.constraint = neutron.CIDRConstraint()
def test_valid_cidr_format(self):
validate_format = [
'10.0.0.0/24',
'6000::/64',
'8.8.8.8'
]
for cidr in validate_format:
self.assertTrue(self.constraint.validate(cidr, None))
def test_invalid_cidr_format(self):
invalidate_format = [
'::/129',
'Invalid cidr',
'300.0.0.0/24',
'10.0.0.0/33',
'8.8.8.0/ 24'
]
for cidr in invalidate_format:
self.assertFalse(self.constraint.validate(cidr, None))

View File

@ -75,6 +75,7 @@ heat.constraints =
trove.flavor = heat.engine.clients.os.trove:FlavorConstraint
ip_addr = heat.engine.clients.os.neutron:IPConstraint
mac_addr = heat.engine.clients.os.neutron:MACConstraint
net_cidr = heat.engine.clients.os.neutron:CIDRConstraint
heat.stack_lifecycle_plugins =