]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
heat engine : WaitCondition add Handle property validation
authorSteven Hardy <shardy@redhat.com>
Fri, 1 Feb 2013 13:01:18 +0000 (13:01 +0000)
committerSteven Hardy <shardy@redhat.com>
Fri, 1 Feb 2013 16:13:12 +0000 (16:13 +0000)
Add validation to the Handle property for WaitCondition, so
we check that the identifier in the provided URL maps to
a WaitConditionHandle resource in the same stack as the
WaitCondition

fixes bug 1100754

Change-Id: I44c8f52435016fad5a35183472d2b0df26c1915d

heat/engine/resources/wait_condition.py
heat/tests/test_waitcondition.py

index 373ea1e917c2e81ba75240ccc7fa6139844269a8..4fb2b4293e9086fe39c5bbc43c123964fe976154 100644 (file)
@@ -204,6 +204,26 @@ class WaitCondition(resource.Resource):
                               self.timeout / self.SLEEP_DIV),
                               self.MIN_SLEEP)
 
+    def _validate_handle_url(self):
+        handle_url = self.properties['Handle']
+        handle_id = identifier.ResourceIdentifier.from_arn_url(handle_url)
+        if handle_id.tenant != self.stack.context.tenant_id:
+            raise ValueError("WaitCondition invalid Handle tenant %s" %
+                             handle_id.tenant)
+        if handle_id.stack_name != self.stack.name:
+            raise ValueError("WaitCondition invalid Handle stack %s" %
+                             handle_id.stack_name)
+        if handle_id.stack_id != self.stack.id:
+            raise ValueError("WaitCondition invalid Handle stack %s" %
+                             handle_id.stack_id)
+        if handle_id.resource_name not in self.stack:
+            raise ValueError("WaitCondition invalid Handle %s" %
+                             handle_id.resource_name)
+        if not isinstance(self.stack[handle_id.resource_name],
+                          WaitConditionHandle):
+            raise ValueError("WaitCondition invalid Handle %s" %
+                             handle_id.resource_name)
+
     def _get_handle_resource_name(self):
         handle_url = self.properties['Handle']
         handle_id = identifier.ResourceIdentifier.from_arn_url(handle_url)
@@ -213,6 +233,7 @@ class WaitCondition(resource.Resource):
         return eventlet.Timeout(self.timeout)
 
     def handle_create(self):
+        self._validate_handle_url()
         tmo = None
         status = FAILURE
         reason = "Unknown reason"
index cd3865ec38326716c638de6417c7824d5bf26480..8baba8bbd3ce607d1969e0353a2b403390cd9a2c 100644 (file)
@@ -17,6 +17,7 @@ import mox
 import uuid
 import time
 import datetime
+import json
 
 import eventlet
 import unittest
@@ -96,22 +97,26 @@ class WaitConditionTest(unittest.TestCase):
     # Note tests creating a stack should be decorated with @stack_delete_after
     # to ensure the stack is properly cleaned up
     def create_stack(self, stack_name='test_stack',
-                     template=test_template_waitcondition, params={}):
+                     template=test_template_waitcondition, params={},
+                     stub=True):
         temp = template_format.parse(template)
         template = parser.Template(temp)
         parameters = parser.Parameters(stack_name, template, params)
-        stack = parser.Stack(context.get_admin_context(), stack_name,
-                             template, parameters)
+        ctx = context.get_admin_context()
+        ctx.tenant_id = 'test_tenant'
+        stack = parser.Stack(ctx, stack_name, template, parameters)
 
-        stack.store()
+        self.stack_id = stack.store()
 
-        self.m.StubOutWithMock(wc.WaitConditionHandle, 'keystone')
-        wc.WaitConditionHandle.keystone().MultipleTimes().AndReturn(self.fc)
+        if stub:
+            self.m.StubOutWithMock(wc.WaitConditionHandle, 'keystone')
+            wc.WaitConditionHandle.keystone().MultipleTimes().AndReturn(
+                self.fc)
 
-        id = identifier.ResourceIdentifier('test_tenant', stack.name,
-                                           stack.id, '', 'WaitHandle')
-        self.m.StubOutWithMock(wc.WaitConditionHandle, 'identifier')
-        wc.WaitConditionHandle.identifier().MultipleTimes().AndReturn(id)
+            id = identifier.ResourceIdentifier('test_tenant', stack.name,
+                                               stack.id, '', 'WaitHandle')
+            self.m.StubOutWithMock(wc.WaitConditionHandle, 'identifier')
+            wc.WaitConditionHandle.identifier().MultipleTimes().AndReturn(id)
 
         return stack
 
@@ -263,6 +268,113 @@ class WaitConditionTest(unittest.TestCase):
         self.assertEqual(wc_att, u'{"123": "foo", "456": "dog"}')
         self.m.VerifyAll()
 
+    @stack_delete_after
+    def test_validate_handle_url_bad_stackid(self):
+        # Stub out the stack ID so we have a known value
+        stack_id = 'STACKABCD1234'
+        self.m.StubOutWithMock(uuid, 'uuid4')
+        uuid.uuid4().AndReturn(stack_id)
+        self.m.ReplayAll()
+
+        t = json.loads(test_template_waitcondition)
+        badhandle = ("http://127.0.0.1:8000/v1/waitcondition/" +
+                     "arn%3Aopenstack%3Aheat%3A%3Atest_tenant" +
+                     "%3Astacks%2Ftest_stack%2F" +
+                     "bad1" +
+                     "%2Fresources%2FWaitHandle")
+        t['Resources']['WaitForTheHandle']['Properties']['Handle'] = badhandle
+        self.stack = self.create_stack(template=json.dumps(t), stub=False)
+        self.m.ReplayAll()
+
+        resource = self.stack.resources['WaitForTheHandle']
+        self.assertRaises(ValueError, resource.handle_create)
+
+        self.m.VerifyAll()
+
+    @stack_delete_after
+    def test_validate_handle_url_bad_stackname(self):
+        # Stub out the stack ID so we have a known value
+        stack_id = 'STACKABCD1234'
+        self.m.StubOutWithMock(uuid, 'uuid4')
+        uuid.uuid4().AndReturn(stack_id)
+        self.m.ReplayAll()
+
+        t = json.loads(test_template_waitcondition)
+        badhandle = ("http://127.0.0.1:8000/v1/waitcondition/" +
+                     "arn%3Aopenstack%3Aheat%3A%3Atest_tenant" +
+                     "%3Astacks%2FBAD_stack%2F" +
+                     stack_id + "%2Fresources%2FWaitHandle")
+        t['Resources']['WaitForTheHandle']['Properties']['Handle'] = badhandle
+        self.stack = self.create_stack(template=json.dumps(t), stub=False)
+
+        resource = self.stack.resources['WaitForTheHandle']
+        self.assertRaises(ValueError, resource.handle_create)
+
+        self.m.VerifyAll()
+
+    @stack_delete_after
+    def test_validate_handle_url_bad_tenant(self):
+        # Stub out the stack ID so we have a known value
+        stack_id = 'STACKABCD1234'
+        self.m.StubOutWithMock(uuid, 'uuid4')
+        uuid.uuid4().AndReturn(stack_id)
+        self.m.ReplayAll()
+
+        t = json.loads(test_template_waitcondition)
+        badhandle = ("http://127.0.0.1:8000/v1/waitcondition/" +
+                     "arn%3Aopenstack%3Aheat%3A%3ABAD_tenant" +
+                     "%3Astacks%2Ftest_stack%2F" +
+                     stack_id + "%2Fresources%2FWaitHandle")
+        t['Resources']['WaitForTheHandle']['Properties']['Handle'] = badhandle
+        self.stack = self.create_stack(template=json.dumps(t), stub=False)
+
+        resource = self.stack.resources['WaitForTheHandle']
+        self.assertRaises(ValueError, resource.handle_create)
+
+        self.m.VerifyAll()
+
+    @stack_delete_after
+    def test_validate_handle_url_bad_resource(self):
+        # Stub out the stack ID so we have a known value
+        stack_id = 'STACKABCD1234'
+        self.m.StubOutWithMock(uuid, 'uuid4')
+        uuid.uuid4().AndReturn(stack_id)
+        self.m.ReplayAll()
+
+        t = json.loads(test_template_waitcondition)
+        badhandle = ("http://127.0.0.1:8000/v1/waitcondition/" +
+                     "arn%3Aopenstack%3Aheat%3A%3Atest_tenant" +
+                     "%3Astacks%2Ftest_stack%2F" +
+                     stack_id + "%2Fresources%2FBADHandle")
+        t['Resources']['WaitForTheHandle']['Properties']['Handle'] = badhandle
+        self.stack = self.create_stack(template=json.dumps(t), stub=False)
+
+        resource = self.stack.resources['WaitForTheHandle']
+        self.assertRaises(ValueError, resource.handle_create)
+
+        self.m.VerifyAll()
+
+    @stack_delete_after
+    def test_validate_handle_url_bad_resource_type(self):
+        # Stub out the stack ID so we have a known value
+        stack_id = 'STACKABCD1234'
+        self.m.StubOutWithMock(uuid, 'uuid4')
+        uuid.uuid4().AndReturn(stack_id)
+        self.m.ReplayAll()
+
+        t = json.loads(test_template_waitcondition)
+        badhandle = ("http://127.0.0.1:8000/v1/waitcondition/" +
+                     "arn%3Aopenstack%3Aheat%3A%3Atest_tenant" +
+                     "%3Astacks%2Ftest_stack%2F" +
+                     stack_id + "%2Fresources%2FWaitForTheHandle")
+        t['Resources']['WaitForTheHandle']['Properties']['Handle'] = badhandle
+        self.stack = self.create_stack(template=json.dumps(t), stub=False)
+
+        resource = self.stack.resources['WaitForTheHandle']
+        self.assertRaises(ValueError, resource.handle_create)
+
+        self.m.VerifyAll()
+
 
 @attr(tag=['unit', 'resource', 'WaitConditionHandle'])
 @attr(speed='fast')