Don't delete stack domain project on stack-abandon
Currently we delete the stack domain project on abandon, which will break any resources being abandoned that depend on users created in the stack user domain. So add a flag to skip deletion on abandon and some tests to prove it works. Change-Id: I883831a33d5bd326523836247683c161f797ee2a Closes-Bug: #1300734
This commit is contained in:
parent
0c2ee06320
commit
6e95e28c4d
|
@ -814,7 +814,8 @@ class EngineService(service.Service):
|
|||
stack_info = stack.prepare_abandon()
|
||||
self.thread_group_mgr.start_with_acquired_lock(stack,
|
||||
lock,
|
||||
stack.delete)
|
||||
stack.delete,
|
||||
abandon=True)
|
||||
return stack_info
|
||||
|
||||
def list_resource_types(self, cnxt, support_status=None):
|
||||
|
|
|
@ -770,13 +770,17 @@ class Stack(collections.Mapping):
|
|||
|
||||
notification.send(self)
|
||||
|
||||
def delete(self, action=DELETE, backup=False):
|
||||
def delete(self, action=DELETE, backup=False, abandon=False):
|
||||
'''
|
||||
Delete all of the resources, and then the stack itself.
|
||||
The action parameter is used to differentiate between a user
|
||||
initiated delete and an automatic stack rollback after a failed
|
||||
create, which amount to the same thing, but the states are recorded
|
||||
differently.
|
||||
|
||||
Note abandon is a delete where all resources have been set to a
|
||||
RETAIN deletion policy, but we also don't want to delete anything
|
||||
required for those resources, e.g the stack_user_project.
|
||||
'''
|
||||
if action not in (self.DELETE, self.ROLLBACK):
|
||||
LOG.error(_("Unexpected action %s passed to delete!") % action)
|
||||
|
@ -784,8 +788,6 @@ class Stack(collections.Mapping):
|
|||
"Invalid action %s" % action)
|
||||
return
|
||||
|
||||
# Note abandon is a delete with
|
||||
# stack.set_deletion_policy(resource.RETAIN)
|
||||
stack_status = self.COMPLETE
|
||||
reason = 'Stack %s completed successfully' % action
|
||||
self.state_set(action, self.IN_PROGRESS, 'Stack %s started' %
|
||||
|
@ -897,7 +899,7 @@ class Stack(collections.Mapping):
|
|||
"%s ") % self.id)
|
||||
|
||||
# If the stack has a domain project, delete it
|
||||
if self.stack_user_project_id:
|
||||
if self.stack_user_project_id and not abandon:
|
||||
try:
|
||||
keystone = self.clients.client('keystone')
|
||||
keystone.delete_stack_domain_project(
|
||||
|
|
|
@ -1522,6 +1522,57 @@ class StackTest(HeatTestCase):
|
|||
self.stack.state)
|
||||
self.assertIn('Error deleting trust', self.stack.status_reason)
|
||||
|
||||
def test_delete_deletes_project(self):
|
||||
fkc = FakeKeystoneClient()
|
||||
fkc.delete_stack_domain_project = mock.Mock()
|
||||
|
||||
self.m.StubOutWithMock(keystone.KeystoneClientPlugin, '_create')
|
||||
keystone.KeystoneClientPlugin._create().AndReturn(fkc)
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.stack = parser.Stack(
|
||||
self.ctx, 'delete_trust', self.tmpl)
|
||||
stack_id = self.stack.store()
|
||||
|
||||
self.stack.set_stack_user_project_id(project_id='aproject456')
|
||||
|
||||
db_s = db_api.stack_get(self.ctx, stack_id)
|
||||
self.assertIsNotNone(db_s)
|
||||
|
||||
self.stack.delete()
|
||||
|
||||
db_s = db_api.stack_get(self.ctx, stack_id)
|
||||
self.assertIsNone(db_s)
|
||||
self.assertEqual((parser.Stack.DELETE, parser.Stack.COMPLETE),
|
||||
self.stack.state)
|
||||
fkc.delete_stack_domain_project.assert_called_once_with(
|
||||
project_id='aproject456')
|
||||
|
||||
def test_abandon_nodelete_project(self):
|
||||
fkc = FakeKeystoneClient()
|
||||
fkc.delete_stack_domain_project = mock.Mock()
|
||||
|
||||
self.m.StubOutWithMock(keystone.KeystoneClientPlugin, '_create')
|
||||
keystone.KeystoneClientPlugin._create().AndReturn(fkc)
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.stack = parser.Stack(
|
||||
self.ctx, 'delete_trust', self.tmpl)
|
||||
stack_id = self.stack.store()
|
||||
|
||||
self.stack.set_stack_user_project_id(project_id='aproject456')
|
||||
|
||||
db_s = db_api.stack_get(self.ctx, stack_id)
|
||||
self.assertIsNotNone(db_s)
|
||||
|
||||
self.stack.delete(abandon=True)
|
||||
|
||||
db_s = db_api.stack_get(self.ctx, stack_id)
|
||||
self.assertIsNone(db_s)
|
||||
self.assertEqual((parser.Stack.DELETE, parser.Stack.COMPLETE),
|
||||
self.stack.state)
|
||||
self.assertFalse(fkc.delete_stack_domain_project.called)
|
||||
|
||||
def test_suspend_resume(self):
|
||||
self.m.ReplayAll()
|
||||
tmpl = {'HeatTemplateFormatVersion': '2012-12-12',
|
||||
|
|
Loading…
Reference in New Issue