]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
api : Implement OnFailure option to cfn API CreateStack call
authorSteven Hardy <shardy@redhat.com>
Fri, 5 Jul 2013 11:25:50 +0000 (12:25 +0100)
committerSteven Hardy <shardy@redhat.com>
Mon, 22 Jul 2013 15:43:31 +0000 (16:43 +0100)
blueprint createstack-onfailure

Change-Id: I8466493fbeba2023916f2d92814c1cc8f2827e51

heat/api/cfn/v1/stacks.py
heat/tests/test_api_cfn_v1.py

index 19b9c0ad530e0e17d159ff2620e419176b3aef59..764e6b0b29f06fdbf47090e37f179310bf2954e2 100644 (file)
@@ -289,11 +289,24 @@ class StackController(object):
             keymap = {'TimeoutInMinutes': engine_api.PARAM_TIMEOUT,
                       'DisableRollback': engine_api.PARAM_DISABLE_ROLLBACK}
 
+            if 'DisableRollback' in params and 'OnFailure' in params:
+                msg = _('DisableRollback and OnFailure '
+                        'may not be used together')
+                raise exception.HeatInvalidParameterCombinationError(
+                    detail=msg)
+
             result = {}
             for k in keymap:
-                if k in req.params:
+                if k in params:
                     result[keymap[k]] = params[k]
 
+            if 'OnFailure' in params:
+                value = params['OnFailure']
+                if value == 'DO_NOTHING':
+                    result[engine_api.PARAM_DISABLE_ROLLBACK] = 'true'
+                elif value in ('ROLLBACK', 'DELETE'):
+                    result[engine_api.PARAM_DISABLE_ROLLBACK] = 'false'
+
             return result
 
         if action not in self.CREATE_OR_UPDATE_ACTION:
index 5dd18f94f9103557a1172531d7cc2fc5adeabdff..bb663efef04015733bea78ba798727698fe2ce88 100644 (file)
@@ -488,6 +488,213 @@ class CfnStackControllerTest(HeatTestCase):
         self.assertEqual(response, expected)
         self.m.VerifyAll()
 
+    def test_create_rollback(self):
+        # Format a dummy request
+        stack_name = "wordpress"
+        template = {u'Foo': u'bar'}
+        json_template = json.dumps(template)
+        params = {'Action': 'CreateStack', 'StackName': stack_name,
+                  'TemplateBody': '%s' % json_template,
+                  'TimeoutInMinutes': 30,
+                  'DisableRollback': 'false',
+                  'Parameters.member.1.ParameterKey': 'InstanceType',
+                  'Parameters.member.1.ParameterValue': 'm1.xlarge'}
+        engine_parms = {u'InstanceType': u'm1.xlarge'}
+        engine_args = {'timeout_mins': u'30', 'disable_rollback': 'false'}
+        dummy_req = self._dummy_GET_request(params)
+
+        # Stub out the RPC call to the engine with a pre-canned response
+        engine_resp = {u'tenant': u't',
+                       u'stack_name': u'wordpress',
+                       u'stack_id': u'1',
+                       u'path': u''}
+
+        self.m.StubOutWithMock(rpc, 'call')
+        rpc.call(dummy_req.context, self.topic,
+                 {'namespace': None,
+                  'method': 'create_stack',
+                  'args': {'stack_name': stack_name,
+                           'template': template,
+                           'params': engine_parms,
+                           'files': {},
+                           'args': engine_args},
+                  'version': self.api_version}, None).AndReturn(engine_resp)
+
+        self.m.ReplayAll()
+
+        response = self.controller.create(dummy_req)
+
+        expected = {
+            'CreateStackResponse': {
+                'CreateStackResult': {
+                    u'StackId': u'arn:openstack:heat::t:stacks/wordpress/1'
+                }
+            }
+        }
+
+        self.assertEqual(response, expected)
+        self.m.VerifyAll()
+
+    def test_create_onfailure_true(self):
+        # Format a dummy request
+        stack_name = "wordpress"
+        template = {u'Foo': u'bar'}
+        json_template = json.dumps(template)
+        params = {'Action': 'CreateStack', 'StackName': stack_name,
+                  'TemplateBody': '%s' % json_template,
+                  'TimeoutInMinutes': 30,
+                  'OnFailure': 'DO_NOTHING',
+                  'Parameters.member.1.ParameterKey': 'InstanceType',
+                  'Parameters.member.1.ParameterValue': 'm1.xlarge'}
+        engine_parms = {u'InstanceType': u'm1.xlarge'}
+        engine_args = {'timeout_mins': u'30', 'disable_rollback': 'true'}
+        dummy_req = self._dummy_GET_request(params)
+
+        # Stub out the RPC call to the engine with a pre-canned response
+        engine_resp = {u'tenant': u't',
+                       u'stack_name': u'wordpress',
+                       u'stack_id': u'1',
+                       u'path': u''}
+
+        self.m.StubOutWithMock(rpc, 'call')
+        rpc.call(dummy_req.context, self.topic,
+                 {'namespace': None,
+                  'method': 'create_stack',
+                  'args': {'stack_name': stack_name,
+                           'template': template,
+                           'params': engine_parms,
+                           'files': {},
+                           'args': engine_args},
+                  'version': self.api_version}, None).AndReturn(engine_resp)
+
+        self.m.ReplayAll()
+
+        response = self.controller.create(dummy_req)
+
+        expected = {
+            'CreateStackResponse': {
+                'CreateStackResult': {
+                    u'StackId': u'arn:openstack:heat::t:stacks/wordpress/1'
+                }
+            }
+        }
+
+        self.assertEqual(response, expected)
+        self.m.VerifyAll()
+
+    def test_create_onfailure_false_delete(self):
+        # Format a dummy request
+        stack_name = "wordpress"
+        template = {u'Foo': u'bar'}
+        json_template = json.dumps(template)
+        params = {'Action': 'CreateStack', 'StackName': stack_name,
+                  'TemplateBody': '%s' % json_template,
+                  'TimeoutInMinutes': 30,
+                  'OnFailure': 'DELETE',
+                  'Parameters.member.1.ParameterKey': 'InstanceType',
+                  'Parameters.member.1.ParameterValue': 'm1.xlarge'}
+        engine_parms = {u'InstanceType': u'm1.xlarge'}
+        engine_args = {'timeout_mins': u'30', 'disable_rollback': 'false'}
+        dummy_req = self._dummy_GET_request(params)
+
+        # Stub out the RPC call to the engine with a pre-canned response
+        engine_resp = {u'tenant': u't',
+                       u'stack_name': u'wordpress',
+                       u'stack_id': u'1',
+                       u'path': u''}
+
+        self.m.StubOutWithMock(rpc, 'call')
+        rpc.call(dummy_req.context, self.topic,
+                 {'namespace': None,
+                  'method': 'create_stack',
+                  'args': {'stack_name': stack_name,
+                           'template': template,
+                           'params': engine_parms,
+                           'files': {},
+                           'args': engine_args},
+                  'version': self.api_version}, None).AndReturn(engine_resp)
+
+        self.m.ReplayAll()
+
+        response = self.controller.create(dummy_req)
+
+        expected = {
+            'CreateStackResponse': {
+                'CreateStackResult': {
+                    u'StackId': u'arn:openstack:heat::t:stacks/wordpress/1'
+                }
+            }
+        }
+
+        self.assertEqual(response, expected)
+        self.m.VerifyAll()
+
+    def test_create_onfailure_false_rollback(self):
+        # Format a dummy request
+        stack_name = "wordpress"
+        template = {u'Foo': u'bar'}
+        json_template = json.dumps(template)
+        params = {'Action': 'CreateStack', 'StackName': stack_name,
+                  'TemplateBody': '%s' % json_template,
+                  'TimeoutInMinutes': 30,
+                  'OnFailure': 'ROLLBACK',
+                  'Parameters.member.1.ParameterKey': 'InstanceType',
+                  'Parameters.member.1.ParameterValue': 'm1.xlarge'}
+        engine_parms = {u'InstanceType': u'm1.xlarge'}
+        engine_args = {'timeout_mins': u'30', 'disable_rollback': 'false'}
+        dummy_req = self._dummy_GET_request(params)
+
+        # Stub out the RPC call to the engine with a pre-canned response
+        engine_resp = {u'tenant': u't',
+                       u'stack_name': u'wordpress',
+                       u'stack_id': u'1',
+                       u'path': u''}
+
+        self.m.StubOutWithMock(rpc, 'call')
+        rpc.call(dummy_req.context, self.topic,
+                 {'namespace': None,
+                  'method': 'create_stack',
+                  'args': {'stack_name': stack_name,
+                           'template': template,
+                           'params': engine_parms,
+                           'files': {},
+                           'args': engine_args},
+                  'version': self.api_version}, None).AndReturn(engine_resp)
+
+        self.m.ReplayAll()
+
+        response = self.controller.create(dummy_req)
+
+        expected = {
+            'CreateStackResponse': {
+                'CreateStackResult': {
+                    u'StackId': u'arn:openstack:heat::t:stacks/wordpress/1'
+                }
+            }
+        }
+
+        self.assertEqual(response, expected)
+        self.m.VerifyAll()
+
+    def test_create_onfailure_err(self):
+        # Format a dummy request
+        stack_name = "wordpress"
+        template = {u'Foo': u'bar'}
+        json_template = json.dumps(template)
+        params = {'Action': 'CreateStack', 'StackName': stack_name,
+                  'TemplateBody': '%s' % json_template,
+                  'TimeoutInMinutes': 30,
+                  'DisableRollback': 'true',
+                  'OnFailure': 'DO_NOTHING',
+                  'Parameters.member.1.ParameterKey': 'InstanceType',
+                  'Parameters.member.1.ParameterValue': 'm1.xlarge'}
+        engine_parms = {u'InstanceType': u'm1.xlarge'}
+        engine_args = {'timeout_mins': u'30', 'disable_rollback': 'false'}
+        dummy_req = self._dummy_GET_request(params)
+
+        self.assertRaises(exception.HeatInvalidParameterCombinationError,
+                          self.controller.create, dummy_req)
+
     def test_create_err_no_template(self):
         # Format a dummy request with a missing template field
         stack_name = "wordpress"