Add a handle_delete method to SwiftSignalHandle

Swift containers and objects that were created by a particular
SwiftSignalHandle should be deleted when the resource is deleted.

Change-Id: Id9df03e139ca0632996f4f66c5f39e27bb04d1fb
Closes-Bug: #1379040
This commit is contained in:
Jason Dunsmore 2014-10-09 11:57:01 -05:00
parent 6bef85931e
commit d8dc9a8b9e
2 changed files with 128 additions and 0 deletions

View File

@ -105,6 +105,28 @@ class SwiftSignalHandle(resource.Resource):
elif key == self.CURL_CLI:
return ('curl -i -X PUT \'%s\'' % self.data().get('endpoint'))
def handle_delete(self):
sc = self.client_plugin('swift').client()
# Delete all versioned objects
while True:
try:
sc.delete_object(self.stack.id, self.physical_resource_name())
except Exception as exc:
if sc.is_not_found(exc):
break
raise
# Delete the container if it is empty
try:
sc.delete_container(self.stack.id)
except Exception as exc:
if sc.is_not_found(exc) or sc.is_conflict(exc):
pass
raise
self.data_delete('endpoint')
class SwiftSignal(resource.Resource):

View File

@ -19,8 +19,10 @@ import uuid
import mock
import six
from swiftclient import client as swiftclient_client
from swiftclient import exceptions as swiftclient_exceptions
from testtools.matchers import MatchesRegex
from heat.common import exception
from heat.common import template_format
from heat.engine.clients.os import swift
from heat.engine import environment
@ -150,6 +152,110 @@ class SwiftSignalHandleTest(HeatTestCase):
self.assertEqual({'headers': header},
mock_swift_object.put_container.call_args[1])
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_delete_empty_container(self, mock_name, mock_swift):
st = create_stack(swiftsignalhandle_template)
handle = st['test_wait_condition_handle']
mock_swift_object = mock.Mock()
mock_swift.return_value = mock_swift_object
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': "1234"
}
mock_swift_object.url = "http://fake-host.com:8080/v1/AUTH_1234"
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
st.create()
exc = swiftclient_exceptions.ClientException("Object DELETE failed",
http_status=404)
mock_swift_object.delete_object.side_effect = (None, None, None, exc)
mock_swift_object.delete_container.return_value = None
st.delete()
self.assertEqual(4, mock_swift_object.delete_object.call_count)
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_delete_object_error(self, mock_name, mock_swift):
st = create_stack(swiftsignalhandle_template)
handle = st['test_wait_condition_handle']
mock_swift_object = mock.Mock()
mock_swift.return_value = mock_swift_object
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': "1234"
}
mock_swift_object.url = "http://fake-host.com:8080/v1/AUTH_1234"
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
st.create()
exc = swiftclient_exceptions.ClientException("Overlimit",
http_status=413)
mock_swift_object.delete_object.side_effect = (None, None, None, exc)
mock_swift_object.is_not_found.return_value = False
rsrc = st.resources['test_wait_condition_handle']
exc = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.delete))
self.assertEqual('ClientException: Overlimit: 413', six.text_type(exc))
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_delete_container_error(self, mock_name, mock_swift):
st = create_stack(swiftsignalhandle_template)
handle = st['test_wait_condition_handle']
mock_swift_object = mock.Mock()
mock_swift.return_value = mock_swift_object
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': "1234"
}
mock_swift_object.url = "http://fake-host.com:8080/v1/AUTH_1234"
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
st.create()
exc = swiftclient_exceptions.ClientException("Object DELETE failed",
http_status=404)
mock_swift_object.delete_object.side_effect = (None, None, None, exc)
mock_swift_object.is_not_found.side_effect = (True, False)
mock_swift_object.is_conflict.return_value = False
exc = swiftclient_exceptions.ClientException("Overlimit",
http_status=413)
mock_swift_object.delete_container.side_effect = (exc,)
rsrc = st.resources['test_wait_condition_handle']
exc = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.delete))
self.assertEqual('ClientException: Overlimit: 413', six.text_type(exc))
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_delete_non_empty_container(self, mock_name, mock_swift):
st = create_stack(swiftsignalhandle_template)
handle = st['test_wait_condition_handle']
mock_swift_object = mock.Mock()
mock_swift.return_value = mock_swift_object
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': "1234"
}
mock_swift_object.url = "http://fake-host.com:8080/v1/AUTH_1234"
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
st.create()
exc = swiftclient_exceptions.ClientException("Object DELETE failed",
http_status=404)
mock_swift_object.delete_object.side_effect = (None, None, None, exc)
exc = swiftclient_exceptions.ClientException("Container DELETE failed",
http_status=409)
mock_swift_object.delete_container.return_value = exc
st.delete()
self.assertEqual(4, mock_swift_object.delete_object.call_count)
@mock.patch.object(swift.SwiftClientPlugin, '_create')
def test_handle_update(self, mock_swift):
st = create_stack(swiftsignalhandle_template)