Merge "Add CIDR format validation"
This commit is contained in:
commit
f81cb5dbd1
@ -11,10 +11,8 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import netaddr
|
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from heat.common import exception
|
|
||||||
from heat.common.i18n import _
|
from heat.common.i18n import _
|
||||||
from heat.common.i18n import _LW
|
from heat.common.i18n import _LW
|
||||||
from heat.engine import attributes
|
from heat.engine import attributes
|
||||||
@ -79,7 +77,10 @@ class CloudNetwork(resource.Resource):
|
|||||||
properties.Schema.STRING,
|
properties.Schema.STRING,
|
||||||
_("The IP block from which to allocate the network. For example, "
|
_("The IP block from which to allocate the network. For example, "
|
||||||
"172.16.0.0/24 or 2001:DB8::/64."),
|
"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):
|
def validate(self):
|
||||||
super(CloudNetwork, self).validate()
|
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):
|
def _resolve_attribute(self, name):
|
||||||
net = self.network()
|
net = self.network()
|
||||||
|
@ -116,12 +116,15 @@ class CloudNetworkTest(common.HeatTestCase):
|
|||||||
self.assertEqual(expect_label, res.FnGetAtt('label'))
|
self.assertEqual(expect_label, res.FnGetAtt('label'))
|
||||||
self.assertEqual(expect_cidr, res.FnGetAtt('cidr'))
|
self.assertEqual(expect_cidr, res.FnGetAtt('cidr'))
|
||||||
|
|
||||||
def test_create_bad_cider(self, mock_client):
|
def test_create_bad_cidr(self, mock_client):
|
||||||
self._template['resources']['cnw']['properties']['cidr'] = "bad cidr"
|
prop = self._template['resources']['cnw']['properties']
|
||||||
|
prop['cidr'] = "bad cidr"
|
||||||
self._parse_stack()
|
self._parse_stack()
|
||||||
exc = self.assertRaises(exception.StackValidationFailed,
|
exc = self.assertRaises(exception.StackValidationFailed,
|
||||||
self.stack.validate)
|
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):
|
def test_check(self, mock_client):
|
||||||
self._setup_stack(mock_client)
|
self._setup_stack(mock_client)
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import netaddr
|
import netaddr
|
||||||
|
import six
|
||||||
|
|
||||||
from neutronclient.common import exceptions
|
from neutronclient.common import exceptions
|
||||||
from neutronclient.neutron import v2_0 as neutronV20
|
from neutronclient.neutron import v2_0 as neutronV20
|
||||||
@ -189,3 +190,21 @@ class MACConstraint(constraints.BaseCustomConstraint):
|
|||||||
def validate(self, value, context):
|
def validate(self, value, context):
|
||||||
self._error_message = 'Invalid MAC address.'
|
self._error_message = 'Invalid MAC address.'
|
||||||
return netaddr.valid_mac(value)
|
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
|
||||||
|
@ -298,12 +298,18 @@ class FirewallRule(neutron.NeutronResource):
|
|||||||
SOURCE_IP_ADDRESS: properties.Schema(
|
SOURCE_IP_ADDRESS: properties.Schema(
|
||||||
properties.Schema.STRING,
|
properties.Schema.STRING,
|
||||||
_('Source IP address or CIDR.'),
|
_('Source IP address or CIDR.'),
|
||||||
update_allowed=True
|
update_allowed=True,
|
||||||
|
constraints=[
|
||||||
|
constraints.CustomConstraint('net_cidr')
|
||||||
|
]
|
||||||
),
|
),
|
||||||
DESTINATION_IP_ADDRESS: properties.Schema(
|
DESTINATION_IP_ADDRESS: properties.Schema(
|
||||||
properties.Schema.STRING,
|
properties.Schema.STRING,
|
||||||
_('Destination IP address or CIDR.'),
|
_('Destination IP address or CIDR.'),
|
||||||
update_allowed=True
|
update_allowed=True,
|
||||||
|
constraints=[
|
||||||
|
constraints.CustomConstraint('net_cidr')
|
||||||
|
]
|
||||||
),
|
),
|
||||||
SOURCE_PORT: properties.Schema(
|
SOURCE_PORT: properties.Schema(
|
||||||
properties.Schema.STRING,
|
properties.Schema.STRING,
|
||||||
|
@ -105,7 +105,10 @@ class SecurityGroup(neutron.NeutronResource):
|
|||||||
RULE_REMOTE_IP_PREFIX: properties.Schema(
|
RULE_REMOTE_IP_PREFIX: properties.Schema(
|
||||||
properties.Schema.STRING,
|
properties.Schema.STRING,
|
||||||
_('The remote IP prefix (CIDR) to be associated with this '
|
_('The remote IP prefix (CIDR) to be associated with this '
|
||||||
'security group rule.')
|
'security group rule.'),
|
||||||
|
constraints=[
|
||||||
|
constraints.CustomConstraint('net_cidr')
|
||||||
|
]
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,10 @@ class Subnet(neutron.NeutronResource):
|
|||||||
CIDR: properties.Schema(
|
CIDR: properties.Schema(
|
||||||
properties.Schema.STRING,
|
properties.Schema.STRING,
|
||||||
_('The CIDR.'),
|
_('The CIDR.'),
|
||||||
required=True
|
required=True,
|
||||||
|
constraints=[
|
||||||
|
constraints.CustomConstraint('net_cidr')
|
||||||
|
]
|
||||||
),
|
),
|
||||||
VALUE_SPECS: properties.Schema(
|
VALUE_SPECS: properties.Schema(
|
||||||
properties.Schema.MAP,
|
properties.Schema.MAP,
|
||||||
|
@ -219,7 +219,13 @@ class IPsecSiteConnection(neutron.NeutronResource):
|
|||||||
PEER_CIDRS: properties.Schema(
|
PEER_CIDRS: properties.Schema(
|
||||||
properties.Schema.LIST,
|
properties.Schema.LIST,
|
||||||
_('Remote subnet(s) in CIDR format.'),
|
_('Remote subnet(s) in CIDR format.'),
|
||||||
required=True
|
required=True,
|
||||||
|
schema=properties.Schema(
|
||||||
|
properties.Schema.STRING,
|
||||||
|
constraints=[
|
||||||
|
constraints.CustomConstraint('net_cidr')
|
||||||
|
]
|
||||||
|
)
|
||||||
),
|
),
|
||||||
MTU: properties.Schema(
|
MTU: properties.Schema(
|
||||||
properties.Schema.INTEGER,
|
properties.Schema.INTEGER,
|
||||||
|
@ -254,3 +254,30 @@ class TestMACConstraint(common.HeatTestCase):
|
|||||||
]
|
]
|
||||||
for mac in invalidate_format:
|
for mac in invalidate_format:
|
||||||
self.assertFalse(self.constraint.validate(mac, None))
|
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))
|
||||||
|
@ -75,6 +75,7 @@ heat.constraints =
|
|||||||
trove.flavor = heat.engine.clients.os.trove:FlavorConstraint
|
trove.flavor = heat.engine.clients.os.trove:FlavorConstraint
|
||||||
ip_addr = heat.engine.clients.os.neutron:IPConstraint
|
ip_addr = heat.engine.clients.os.neutron:IPConstraint
|
||||||
mac_addr = heat.engine.clients.os.neutron:MACConstraint
|
mac_addr = heat.engine.clients.os.neutron:MACConstraint
|
||||||
|
net_cidr = heat.engine.clients.os.neutron:CIDRConstraint
|
||||||
|
|
||||||
heat.stack_lifecycle_plugins =
|
heat.stack_lifecycle_plugins =
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user