Browse Source

Fix allowed address pair validation

Neutron requires the allowed address pair ip address to be
either an ip or a cidr.
https://review.opendev.org/#/c/575265/ made heat verify for
cidr only.

Change-Id: I2cc2785cb32cf8d788af6262992b1b76107c8292
Story: 2005674
Task: 30985
(cherry picked from commit 5e93b3e4cf)
(cherry picked from commit cec8b079c0)
changes/77/674577/1
Tom Stappaerts 3 months ago
parent
commit
ac3bf784ff

+ 9
- 5
heat/engine/constraint/common_constraints.py View File

@@ -107,14 +107,18 @@ class CIDRConstraint(constraints.BaseCustomConstraint):
107 107
 
108 108
     def validate(self, value, context, template=None):
109 109
         try:
110
-            netaddr.IPNetwork(value, implicit_prefix=True)
111
-            msg = validators.validate_subnet(value)
110
+            if '/' in value:
111
+                msg = validators.validate_subnet(value)
112
+            else:
113
+                msg = validators.validate_ip_address(value)
112 114
             if msg is not None:
113 115
                 self._error_message = msg
114 116
                 return False
115
-            return True
116
-        except Exception as ex:
117
-            self._error_message = 'Invalid net cidr %s ' % six.text_type(ex)
117
+            else:
118
+                return True
119
+        except Exception:
120
+            self._error_message = '{} is not a valid IP or CIDR'.format(
121
+                value)
118 122
             return False
119 123
 
120 124
 

+ 40
- 13
heat/tests/constraints/test_common_constraints.py View File

@@ -102,15 +102,22 @@ class TestCIDRConstraint(common.HeatTestCase):
102 102
         super(TestCIDRConstraint, self).setUp()
103 103
         self.constraint = cc.CIDRConstraint()
104 104
 
105
-    def test_valid_cidr_format(self):
105
+    def test_valid_format(self):
106 106
         validate_format = [
107 107
             '10.0.0.0/24',
108
+            '1.1.1.1',
109
+            '1.0.1.1',
110
+            '255.255.255.255',
108 111
             '6000::/64',
112
+            '2002:2002::20c:29ff:fe7d:811a',
113
+            '::1',
114
+            '2002::',
115
+            '2002::1',
109 116
         ]
110
-        for cidr in validate_format:
111
-            self.assertTrue(self.constraint.validate(cidr, None))
117
+        for value in validate_format:
118
+            self.assertTrue(self.constraint.validate(value, None))
112 119
 
113
-    def test_invalid_cidr_format(self):
120
+    def test_invalid_format(self):
114 121
         invalidate_format = [
115 122
             '::/129',
116 123
             'Invalid cidr',
@@ -120,25 +127,45 @@ class TestCIDRConstraint(common.HeatTestCase):
120 127
             '10.0/24',
121 128
             '10.0.a.10/24',
122 129
             '8.8.8.0/ 24',
123
-            '8.8.8.8'
130
+            None,
131
+            123,
132
+            '1.1',
133
+            '1.1.',
134
+            '1.1.1',
135
+            '1.1.1.',
136
+            '1.1.1.256',
137
+            '1.a.1.1',
138
+            '2002::2001::1',
139
+            '2002::g',
140
+            '2001::0::',
141
+            '20c:29ff:fe7d:811a'
124 142
         ]
125
-        for cidr in invalidate_format:
126
-            self.assertFalse(self.constraint.validate(cidr, None))
143
+        for value in invalidate_format:
144
+            self.assertFalse(self.constraint.validate(value, None))
127 145
 
128 146
     @mock.patch('neutron_lib.api.validators.validate_subnet')
129
-    def test_validate(self, mock_validate_subnet):
147
+    @mock.patch('neutron_lib.api.validators.validate_ip_address')
148
+    def test_validate(self, mock_validate_ip, mock_validate_subnet):
130 149
         test_formats = [
131 150
             '10.0.0/24',
132 151
             '10.0/24',
133
-        ]
134
-        self.assertFalse(self.constraint.validate('10.0.0.0/33', None))
152
+            '10.0.0.0/33',
135 153
 
154
+        ]
136 155
         for cidr in test_formats:
137 156
             self.assertFalse(self.constraint.validate(cidr, None))
157
+            mock_validate_subnet.assert_called_with(cidr)
158
+        self.assertEqual(mock_validate_subnet.call_count, 3)
138 159
 
139
-        mock_validate_subnet.assert_any_call('10.0.0/24')
140
-        mock_validate_subnet.assert_called_with('10.0/24')
141
-        self.assertEqual(mock_validate_subnet.call_count, 2)
160
+        test_formats = [
161
+            '10.0.0',
162
+            '10.0',
163
+            '10.0.0.0',
164
+        ]
165
+        for ip in test_formats:
166
+            self.assertFalse(self.constraint.validate(ip, None))
167
+            mock_validate_ip.assert_called_with(ip)
168
+        self.assertEqual(mock_validate_ip.call_count, 3)
142 169
 
143 170
 
144 171
 class TestISO8601Constraint(common.HeatTestCase):

+ 3
- 1
heat/tests/openstack/neutron/test_neutron_port.py View File

@@ -183,6 +183,8 @@ class NeutronPortTest(common.HeatTestCase):
183 183
 
184 184
     def test_allowed_address_pair(self):
185 185
         t = template_format.parse(neutron_port_with_address_pair_template)
186
+        t['resources']['port']['properties'][
187
+            'allowed_address_pairs'][0]['ip_address'] = '10.0.3.21'
186 188
         stack = utils.parse_stack(t)
187 189
 
188 190
         self.find_mock.return_value = 'abcd1234'
@@ -200,7 +202,7 @@ class NeutronPortTest(common.HeatTestCase):
200 202
         self.create_mock.assert_called_once_with({'port': {
201 203
             'network_id': u'abcd1234',
202 204
             'allowed_address_pairs': [{
203
-                'ip_address': u'10.0.3.21/8',
205
+                'ip_address': u'10.0.3.21',
204 206
                 'mac_address': u'00-B0-D0-86-BB-F7'
205 207
             }],
206 208
             'name': utils.PhysName(stack.name, 'port'),

+ 2
- 2
heat/tests/openstack/neutron/test_neutron_subnet.py View File

@@ -551,8 +551,8 @@ class NeutronSubnetTest(common.HeatTestCase):
551 551
                                rsrc.validate)
552 552
         msg = ("Property error: "
553 553
                "resources.sub_net.properties.host_routes[0].destination: "
554
-               "Error validating value 'invalid_cidr': Invalid net cidr "
555
-               "invalid IPNetwork invalid_cidr ")
554
+               "Error validating value 'invalid_cidr': "
555
+               "'invalid_cidr' is not a valid IP address")
556 556
         self.assertEqual(msg, six.text_type(ex))
557 557
 
558 558
     def test_ipv6_validate_ra_mode(self):

Loading…
Cancel
Save