diff --git a/heat/engine/api.py b/heat/engine/api.py index 3081860784..5dc9251107 100644 --- a/heat/engine/api.py +++ b/heat/engine/api.py @@ -193,11 +193,12 @@ def format_stack_resource(resource, detail=True, with_props=False, Return a representation of the given resource that matches the API output expectations. ''' - created_time = resource.created_time or timeutils.utcnow() - last_updated_time = resource.updated_time or created_time + created_time = resource.created_time and resource.created_time.isoformat() + last_updated_time = (resource.updated_time and + resource.updated_time.isoformat()) or created_time res = { - rpc_api.RES_UPDATED_TIME: last_updated_time.isoformat(), - rpc_api.RES_CREATION_TIME: created_time.isoformat(), + rpc_api.RES_UPDATED_TIME: last_updated_time, + rpc_api.RES_CREATION_TIME: created_time, rpc_api.RES_NAME: resource.name, rpc_api.RES_PHYSICAL_ID: resource.resource_id or '', rpc_api.RES_ACTION: resource.action, diff --git a/heat/engine/resource.py b/heat/engine/resource.py index 201f3154f9..f194d3e024 100644 --- a/heat/engine/resource.py +++ b/heat/engine/resource.py @@ -213,9 +213,11 @@ class Resource(object): self.abandon_in_progress = False self.resource_id = None - # if the stack is being deleted, assume we've already been deleted - if stack.action == stack.DELETE: - self.action = self.DELETE + # if the stack is being deleted, assume we've already been deleted. + # or if the resource has not been created yet, and the stack was + # rollback, we set the resource to rollback + if stack.action == stack.DELETE or stack.action == stack.ROLLBACK: + self.action = stack.action else: self.action = self.INIT self.status = self.COMPLETE @@ -225,8 +227,8 @@ class Resource(object): self._data = {} self._rsrc_metadata = None self._stored_properties_data = None - self.created_time = None - self.updated_time = None + self.created_time = stack.created_time + self.updated_time = stack.updated_time self._rpc_client = None self.needed_by = [] self.requires = [] diff --git a/heat/tests/test_engine_api_utils.py b/heat/tests/test_engine_api_utils.py index 1b35a21b5c..e839351223 100644 --- a/heat/tests/test_engine_api_utils.py +++ b/heat/tests/test_engine_api_utils.py @@ -61,6 +61,8 @@ class FormatTest(common.HeatTestCase): id=event_id) def test_format_stack_resource(self): + self.stack.created_time = datetime(2015, 8, 3, 17, 5, 1) + self.stack.updated_time = datetime(2015, 8, 3, 17, 6, 2) res = self.stack['generic1'] resource_keys = set(( @@ -89,6 +91,30 @@ class FormatTest(common.HeatTestCase): formatted = api.format_stack_resource(res, False) self.assertEqual(resource_keys, set(six.iterkeys(formatted))) + self.assertEqual(self.stack.created_time.isoformat(), + formatted[rpc_api.RES_CREATION_TIME]) + self.assertEqual(self.stack.updated_time.isoformat(), + formatted[rpc_api.RES_UPDATED_TIME]) + self.assertEqual(res.INIT, formatted[rpc_api.RES_ACTION]) + + def test_format_stack_resource_has_been_deleted(self): + # assume the stack and resource have been deleted, + # to test the resource's action inherit from stack + self.stack.state_set(self.stack.DELETE, self.stack.COMPLETE, + 'test_delete') + res = self.stack['generic1'] + formatted = api.format_stack_resource(res, False) + self.assertEqual(res.DELETE, formatted[rpc_api.RES_ACTION]) + + def test_format_stack_resource_has_been_rollback(self): + # Rollback a stack, the resources perhaps have not been + # created yet or have been deleted when rollback. + # To test the resource's action inherit from stack + self.stack.state_set(self.stack.ROLLBACK, self.stack.COMPLETE, + 'test_rollback') + res = self.stack['generic1'] + formatted = api.format_stack_resource(res, False) + self.assertEqual(res.ROLLBACK, formatted[rpc_api.RES_ACTION]) @mock.patch.object(api, 'format_resource_properties') def test_format_stack_resource_with_props(self, mock_format_props): diff --git a/heat_integrationtests/functional/test_preview.py b/heat_integrationtests/functional/test_preview.py index b4389ffd45..19da01bc24 100644 --- a/heat_integrationtests/functional/test_preview.py +++ b/heat_integrationtests/functional/test_preview.py @@ -53,9 +53,10 @@ parameters: 'description'): self.assertIn(field, res) self.assertEqual('', res[field]) + # 'creation_time' and 'updated_time' are None when preview for field in ('creation_time', 'updated_time'): self.assertIn(field, res) - self.assertIsNotNone(res[field]) + self.assertIsNone(res[field]) self.assertIn('output', res['attributes']) # resource_identity