deb-heat/heat/tests/test_swiftsignal.py
Jason Dunsmore 837a093a24 Use physical_resource_name to generate the resource ID
The SwiftSignalHandle URL can be too long for the database column,
resulting in an unhandled exception and failed stack.

Use the SwiftSignalHandle's physical_resource_name() method to generate
the resource ID and use FnGetRefId to fetch the handle URL instead.

Change-Id: Iee5fc684b1f2f64ed543022a9e51612c1f80bb1e
Closes-Bug: #1398927
2014-12-03 12:33:10 -06:00

854 lines
36 KiB
Python

#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import copy
import json
import time
import uuid
import mock
import six
from swiftclient import client as swiftclient_client
from swiftclient import exceptions as swiftclient_exceptions
from testtools import matchers
from heat.common import exception
from heat.common import template_format
from heat.engine.clients.os import swift
from heat.engine import environment
from heat.engine import resource
from heat.engine import rsrc_defn
from heat.engine import scheduler
from heat.engine import stack
from heat.tests import common
from heat.tests import utils
swiftsignal_template = '''
heat_template_version: 2013-05-23
resources:
test_wait_condition:
type: "OS::Heat::SwiftSignal"
properties:
handle: { get_resource: test_wait_condition_handle }
timeout: 1
count: 2
test_wait_condition_handle:
type: "OS::Heat::SwiftSignalHandle"
'''
swiftsignalhandle_template = '''
heat_template_version: 2013-05-23
resources:
test_wait_condition_handle:
type: "OS::Heat::SwiftSignalHandle"
'''
container_header = {
'content-length': '2',
'x-container-object-count': '0',
'accept-ranges': 'bytes',
'date': 'Fri, 25 Jul 2014 16:02:03 GMT',
'x-timestamp': '1405019787.66969',
'x-trans-id': 'tx6651b005324341f685e71-0053d27f7bdfw1',
'x-container-bytes-used': '0',
'content-type': 'application/json; charset=utf-8',
'x-versions-location': 'test'
}
obj_header = {
'content-length': '5',
'accept-ranges': 'bytes',
'last-modified': 'Fri, 25 Jul 2014 16:05:26 GMT',
'etag': '5a105e8b9d40e1329780d62ea2265d8a',
'x-timestamp': '1406304325.40094',
'x-trans-id': 'tx2f40ff2b4daa4015917fc-0053d28045dfw1',
'date': 'Fri, 25 Jul 2014 16:05:25 GMT',
'content-type': 'application/octet-stream'
}
def create_stack(template, stack_id=None):
tmpl = template_format.parse(template)
template = stack.tmpl.Template(tmpl)
ctx = utils.dummy_context(tenant_id='test_tenant')
st = stack.Stack(ctx, 'test_st', template,
environment.Environment(),
disable_rollback=True)
# Stub out the stack ID so we have a known value
if stack_id is None:
stack_id = str(uuid.uuid4())
with utils.UUIDStub(stack_id):
st.store()
st.id = stack_id
return st
def cont_index(obj_name, num_version_hist):
objects = [{'bytes': 11,
'last_modified': '2014-07-03T19:42:03.281640',
'hash': '9214b4e4460fcdb9f3a369941400e71e',
'name': "02b" + obj_name + '/1404416326.51383',
'content_type': 'application/octet-stream'}] * num_version_hist
objects.append({'bytes': 8,
'last_modified': '2014-07-03T19:42:03.849870',
'hash': '9ab7c0738852d7dd6a2dc0b261edc300',
'name': obj_name,
'content_type': 'application/x-www-form-urlencoded'})
return (container_header, objects)
class SwiftSignalHandleTest(common.HeatTestCase):
def setUp(self):
super(SwiftSignalHandleTest, self).setUp()
utils.setup_dummy_db()
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_create(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
mock_swift_object.get_container.return_value = cont_index(obj_name, 2)
mock_swift_object.get_object.return_value = (obj_header, '{"id": "1"}')
st.create()
handle = st.resources['test_wait_condition_handle']
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
regexp = ("http://fake-host.com:8080/v1/AUTH_test_tenant/%s/test_st-"
"test_wait_condition_handle-abcdefghijkl"
"\?temp_url_sig=[0-9a-f]{40}&temp_url_expires=[0-9]{10}"
% st.id)
res_id = st.resources['test_wait_condition_handle'].resource_id
self.assertEqual(res_id, handle.physical_resource_name())
self.assertThat(handle.FnGetRefId(), matchers.MatchesRegex(regexp))
# Since the account key is mocked out above
self.assertFalse(mock_swift_object.post_account.called)
header = {'x-versions-location': st.id}
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)
exc = swiftclient_exceptions.ClientException("Container DELETE failed",
http_status=404)
mock_swift_object.delete_container.side_effect = exc
rsrc = st.resources['test_wait_condition_handle']
scheduler.TaskRunner(rsrc.delete)()
self.assertEqual(('DELETE', 'COMPLETE'), rsrc.state)
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)
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)
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.side_effect = exc
rsrc = st.resources['test_wait_condition_handle']
scheduler.TaskRunner(rsrc.delete)()
self.assertEqual(('DELETE', 'COMPLETE'), rsrc.state)
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)
mock_swift_object = mock.Mock()
mock_swift.return_value = mock_swift_object
mock_swift_object.head_account.return_value = {}
mock_swift_object.url = "http://fake-host.com:8080/v1/AUTH_1234"
st.create()
handle = st['test_wait_condition_handle']
uprops = copy.copy(handle.properties.data)
uprops['count'] = '5'
update_snippet = rsrc_defn.ResourceDefinition(handle.name,
handle.type(),
uprops)
updater = scheduler.TaskRunner(handle.update, update_snippet)
self.assertRaises(resource.UpdateReplace, updater)
class SwiftSignalTest(common.HeatTestCase):
def setUp(self):
super(SwiftSignalTest, self).setUp()
utils.setup_dummy_db()
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_create(self, mock_name, mock_swift):
st = create_stack(swiftsignal_template)
handle = st['test_wait_condition_handle']
mock_swift_object = mock.Mock()
mock_swift.return_value = mock_swift_object
mock_swift_object.url = "http://fake-host.com:8080/v1/AUTH_1234"
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': '123456'
}
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
mock_swift_object.get_container.return_value = cont_index(obj_name, 2)
mock_swift_object.get_object.return_value = (obj_header, '')
st.create()
self.assertEqual(('CREATE', 'COMPLETE'), st.state)
@mock.patch.object(swift.SwiftClientPlugin, 'get_signal_url')
def test_validate_handle_url_bad_tempurl(self, mock_handle_url):
mock_handle_url.return_value = (
"http://fake-host.com:8080/v1/my-container/"
"test_st-test_wait_condition_handle?temp_url_sig="
"12d8f9f2c923fbeb555041d4ed63d83de6768e95&"
"temp_url_expires=1404762741")
st = create_stack(swiftsignal_template)
st.create()
self.assertIn('not a valid SwiftSignalHandle. The Swift TempURL path',
six.text_type(st.status_reason))
@mock.patch.object(swift.SwiftClientPlugin, 'get_signal_url')
def test_validate_handle_url_bad_container_name(self, mock_handle_url):
mock_handle_url.return_value = (
"http://fake-host.com:8080/v1/AUTH_test_tenant/my-container/"
"test_st-test_wait_condition_handle?temp_url_sig="
"12d8f9f2c923fbeb555041d4ed63d83de6768e95&"
"temp_url_expires=1404762741")
st = create_stack(swiftsignal_template)
st.create()
self.assertIn('not a valid SwiftSignalHandle. The container name',
six.text_type(st.status_reason))
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_multiple_signals_same_id_complete(self, mock_name, mock_swift):
st = create_stack(swiftsignal_template)
handle = st['test_wait_condition_handle']
mock_swift_object = mock.Mock()
mock_swift.return_value = mock_swift_object
mock_swift_object.url = "http://fake-host.com:8080/v1/AUTH_1234"
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': '123456'
}
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
mock_swift_object.get_container.return_value = cont_index(obj_name, 2)
mock_swift_object.get_object.side_effect = (
(obj_header, json.dumps({'id': 1})),
(obj_header, json.dumps({'id': 1})),
(obj_header, json.dumps({'id': 1})),
(obj_header, json.dumps({'id': 1})),
(obj_header, json.dumps({'id': 2})),
(obj_header, json.dumps({'id': 3})),
)
st.create()
self.assertEqual(('CREATE', 'COMPLETE'), st.state)
@mock.patch.object(scheduler, 'wallclock')
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_multiple_signals_same_id_timeout(self, mock_name, mock_swift,
mock_clock):
st = create_stack(swiftsignal_template)
handle = st['test_wait_condition_handle']
mock_swift_object = mock.Mock()
mock_swift.return_value = mock_swift_object
mock_swift_object.url = "http://fake-host.com:8080/v1/AUTH_1234"
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': '123456'
}
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
mock_swift_object.get_container.return_value = cont_index(obj_name, 2)
mock_swift_object.get_object.return_value = (obj_header,
json.dumps({'id': 1}))
time_now = time.time()
time_series = [t + time_now for t in xrange(1, 100)]
scheduler.wallclock.side_effect = time_series
st.create()
self.assertIn("Resource CREATE failed: SwiftSignalTimeout",
st.status_reason)
wc = st['test_wait_condition']
self.assertEqual("SwiftSignalTimeout: 1 of 2 received - Signal 1 "
"recieved", wc.status_reason)
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_post_complete_to_handle(self, mock_name, mock_swift):
st = create_stack(swiftsignal_template)
handle = st['test_wait_condition_handle']
mock_swift_object = mock.Mock()
mock_swift.return_value = mock_swift_object
mock_swift_object.url = "http://fake-host.com:8080/v1/AUTH_1234"
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': '123456'
}
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
mock_swift_object.get_container.return_value = cont_index(obj_name, 2)
mock_swift_object.get_object.side_effect = (
(obj_header, json.dumps({'id': 1, 'status': "SUCCESS"})),
(obj_header, json.dumps({'id': 1, 'status': "SUCCESS"})),
(obj_header, json.dumps({'id': 2, 'status': "SUCCESS"})),
)
st.create()
self.assertEqual(('CREATE', 'COMPLETE'), st.state)
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_post_failed_to_handle(self, mock_name, mock_swift):
st = create_stack(swiftsignal_template)
handle = st['test_wait_condition_handle']
mock_swift_object = mock.Mock()
mock_swift.return_value = mock_swift_object
mock_swift_object.url = "http://fake-host.com:8080/v1/AUTH_1234"
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': '123456'
}
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
mock_swift_object.get_container.return_value = cont_index(obj_name, 1)
mock_swift_object.get_object.side_effect = (
# Create
(obj_header, json.dumps({'id': 1, 'status': "FAILURE",
'reason': "foo"})),
(obj_header, json.dumps({'id': 2, 'status': "FAILURE",
'reason': "bar"})),
# SwiftSignalFailure
(obj_header, json.dumps({'id': 1, 'status': "FAILURE",
'reason': "foo"})),
(obj_header, json.dumps({'id': 2, 'status': "FAILURE",
'reason': "bar"})),
)
st.create()
self.assertEqual(('CREATE', 'FAILED'), st.state)
wc = st['test_wait_condition']
self.assertEqual("SwiftSignalFailure: foo;bar", wc.status_reason)
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_data(self, mock_name, mock_swift):
st = create_stack(swiftsignal_template)
handle = st['test_wait_condition_handle']
mock_swift_object = mock.Mock()
mock_swift.return_value = mock_swift_object
mock_swift_object.url = "http://fake-host.com:8080/v1/AUTH_1234"
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': '123456'
}
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
mock_swift_object.get_container.return_value = cont_index(obj_name, 2)
mock_swift_object.get_object.side_effect = (
# st create
(obj_header, json.dumps({'id': 1, 'data': "foo"})),
(obj_header, json.dumps({'id': 2, 'data': "bar"})),
(obj_header, json.dumps({'id': 3, 'data': "baz"})),
# FnGetAtt call
(obj_header, json.dumps({'id': 1, 'data': "foo"})),
(obj_header, json.dumps({'id': 2, 'data': "bar"})),
(obj_header, json.dumps({'id': 3, 'data': "baz"})),
)
st.create()
self.assertEqual(('CREATE', 'COMPLETE'), st.state)
wc = st['test_wait_condition']
self.assertEqual(json.dumps({1: 'foo', 2: 'bar', 3: 'baz'}),
wc.FnGetAtt('data'))
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_data_noid(self, mock_name, mock_swift):
st = create_stack(swiftsignal_template)
handle = st['test_wait_condition_handle']
mock_swift_object = mock.Mock()
mock_swift.return_value = mock_swift_object
mock_swift_object.url = "http://fake-host.com:8080/v1/AUTH_1234"
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': '123456'
}
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
mock_swift_object.get_container.return_value = cont_index(obj_name, 1)
mock_swift_object.get_object.side_effect = (
# st create
(obj_header, json.dumps({'data': "foo", 'reason': "bar",
'status': "SUCCESS"})),
(obj_header, json.dumps({'data': "dog", 'reason': "cat",
'status': "SUCCESS"})),
# FnGetAtt call
(obj_header, json.dumps({'data': "foo", 'reason': "bar",
'status': "SUCCESS"})),
(obj_header, json.dumps({'data': "dog", 'reason': "cat",
'status': "SUCCESS"})),
)
st.create()
self.assertEqual(('CREATE', 'COMPLETE'), st.state)
wc = st['test_wait_condition']
self.assertEqual(json.dumps({1: 'foo', 2: 'dog'}), wc.FnGetAtt('data'))
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_data_nodata(self, mock_name, mock_swift):
st = create_stack(swiftsignal_template)
handle = st['test_wait_condition_handle']
mock_swift_object = mock.Mock()
mock_swift.return_value = mock_swift_object
mock_swift_object.url = "http://fake-host.com:8080/v1/AUTH_1234"
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': '123456'
}
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
mock_swift_object.get_container.return_value = cont_index(obj_name, 1)
mock_swift_object.get_object.side_effect = (
# st create
(obj_header, ''),
(obj_header, ''),
# FnGetAtt call
(obj_header, ''),
(obj_header, ''),
)
st.create()
self.assertEqual(('CREATE', 'COMPLETE'), st.state)
wc = st['test_wait_condition']
self.assertEqual(json.dumps({1: None, 2: None}), wc.FnGetAtt('data'))
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_data_partial_complete(self, mock_name, mock_swift):
st = create_stack(swiftsignal_template)
handle = st['test_wait_condition_handle']
wc = st['test_wait_condition']
mock_swift_object = mock.Mock()
mock_swift.return_value = mock_swift_object
mock_swift_object.url = "http://fake-host.com:8080/v1/AUTH_1234"
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': '123456'
}
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
mock_swift_object.get_container.return_value = cont_index(obj_name, 1)
mock_swift_object.get_object.return_value = (
obj_header, json.dumps({'status': 'SUCCESS'}))
st.create()
self.assertEqual(['SUCCESS', 'SUCCESS'], wc.get_status())
expected = [{'status': 'SUCCESS', 'reason': 'Signal 1 recieved',
'data': None, 'id': 1},
{'status': 'SUCCESS', 'reason': 'Signal 2 recieved',
'data': None, 'id': 2}]
self.assertEqual(expected, wc.get_signals())
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_get_status_none_complete(self, mock_name, mock_swift):
st = create_stack(swiftsignal_template)
handle = st['test_wait_condition_handle']
wc = st['test_wait_condition']
mock_swift_object = mock.Mock()
mock_swift.return_value = mock_swift_object
mock_swift_object.url = "http://fake-host.com:8080/v1/AUTH_1234"
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': '123456'
}
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
mock_swift_object.get_container.return_value = cont_index(obj_name, 1)
mock_swift_object.get_object.return_value = (obj_header, '')
st.create()
self.assertEqual(['SUCCESS', 'SUCCESS'], wc.get_status())
expected = [{'status': 'SUCCESS', 'reason': 'Signal 1 recieved',
'data': None, 'id': 1},
{'status': 'SUCCESS', 'reason': 'Signal 2 recieved',
'data': None, 'id': 2}]
self.assertEqual(expected, wc.get_signals())
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_get_status_partial_complete(self, mock_name, mock_swift):
st = create_stack(swiftsignal_template)
handle = st['test_wait_condition_handle']
wc = st['test_wait_condition']
mock_swift_object = mock.Mock()
mock_swift.return_value = mock_swift_object
mock_swift_object.url = "http://fake-host.com:8080/v1/AUTH_1234"
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': '123456'
}
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
mock_swift_object.get_container.return_value = cont_index(obj_name, 1)
mock_swift_object.get_object.return_value = (
obj_header, json.dumps({'id': 1, 'status': "SUCCESS"}))
st.create()
self.assertEqual(['SUCCESS'], wc.get_status())
expected = [{'status': 'SUCCESS', 'reason': 'Signal 1 recieved',
'data': None, 'id': 1}]
self.assertEqual(expected, wc.get_signals())
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_get_status_failure(self, mock_name, mock_swift):
st = create_stack(swiftsignal_template)
handle = st['test_wait_condition_handle']
wc = st['test_wait_condition']
mock_swift_object = mock.Mock()
mock_swift.return_value = mock_swift_object
mock_swift_object.url = "http://fake-host.com:8080/v1/AUTH_1234"
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': '123456'
}
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
mock_swift_object.get_container.return_value = cont_index(obj_name, 1)
mock_swift_object.get_object.return_value = (
obj_header, json.dumps({'id': 1, 'status': "FAILURE"}))
st.create()
self.assertEqual(('CREATE', 'FAILED'), st.state)
self.assertEqual(['FAILURE'], wc.get_status())
expected = [{'status': 'FAILURE', 'reason': 'Signal 1 recieved',
'data': None, 'id': 1}]
self.assertEqual(expected, wc.get_signals())
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_getatt_token(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.url = "http://fake-host.com:8080/v1/AUTH_1234"
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': '123456'
}
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
mock_swift_object.get_container.return_value = cont_index(obj_name, 1)
mock_swift_object.get_object.side_effect = (
# st create
(obj_header, ''),
(obj_header, ''),
)
st.create()
self.assertEqual(('CREATE', 'COMPLETE'), st.state)
self.assertEqual('', handle.FnGetAtt('token'))
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_getatt_endpoint(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.url = "http://fake-host.com:8080/v1/AUTH_1234"
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': '123456'
}
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
mock_swift_object.get_container.return_value = cont_index(obj_name, 1)
mock_swift_object.get_object.side_effect = (
# st create
(obj_header, ''),
(obj_header, ''),
)
st.create()
self.assertEqual(('CREATE', 'COMPLETE'), st.state)
expected = ('http://fake-host.com:8080/v1/AUTH_test_tenant/%s/'
'test_st-test_wait_condition_handle-abcdefghijkl\?temp_'
'url_sig=[0-9a-f]{40}&temp_url_expires=[0-9]{10}') % st.id
self.assertThat(handle.FnGetAtt('endpoint'),
matchers.MatchesRegex(expected))
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_getatt_curl_cli(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.url = "http://fake-host.com:8080/v1/AUTH_1234"
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': '123456'
}
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
mock_swift_object.get_container.return_value = cont_index(obj_name, 1)
mock_swift_object.get_object.side_effect = (
# st create
(obj_header, ''),
(obj_header, ''),
)
st.create()
self.assertEqual(('CREATE', 'COMPLETE'), st.state)
expected = ('curl -i -X PUT \'http://fake-host.com:8080/v1/'
'AUTH_test_tenant/%s/test_st-test_wait_condition_'
'handle-abcdefghijkl\?temp_url_sig=[0-9a-f]{40}&'
'temp_url_expires=[0-9]{10}\'') % st.id
self.assertThat(handle.FnGetAtt('curl_cli'),
matchers.MatchesRegex(expected))
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_invalid_json_data(self, mock_name, mock_swift):
st = create_stack(swiftsignal_template)
handle = st['test_wait_condition_handle']
mock_swift_object = mock.Mock()
mock_swift.return_value = mock_swift_object
mock_swift_object.url = "http://fake-host.com:8080/v1/AUTH_1234"
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': '123456'
}
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
mock_swift_object.get_container.return_value = cont_index(obj_name, 1)
mock_swift_object.get_object.side_effect = (
# st create
(obj_header, '{"status": "SUCCESS"'),
(obj_header, '{"status": "FAI'),
)
st.create()
self.assertEqual(('CREATE', 'FAILED'), st.state)
wc = st['test_wait_condition']
self.assertEqual('Error: Failed to parse JSON data: {"status": '
'"SUCCESS"', wc.status_reason)
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_unknown_status(self, mock_name, mock_swift):
st = create_stack(swiftsignal_template)
handle = st['test_wait_condition_handle']
mock_swift_object = mock.Mock()
mock_swift.return_value = mock_swift_object
mock_swift_object.url = "http://fake-host.com:8080/v1/AUTH_1234"
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': '123456'
}
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
mock_swift_object.get_container.return_value = cont_index(obj_name, 1)
mock_swift_object.get_object.return_value = (
obj_header, '{"status": "BOO"}')
st.create()
self.assertEqual(('CREATE', 'FAILED'), st.state)
wc = st['test_wait_condition']
self.assertEqual('Error: Unknown status: BOO', wc.status_reason)
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_swift_objects_deleted(self, mock_name, mock_swift):
st = create_stack(swiftsignal_template)
handle = st['test_wait_condition_handle']
mock_swift_object = mock.Mock()
mock_swift.return_value = mock_swift_object
mock_swift_object.url = "http://fake-host.com:8080/v1/AUTH_1234"
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': '123456'
}
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
mock_swift_object.get_container.side_effect = (
cont_index(obj_name, 2), # Objects are there during create
(container_header, []), # The user deleted the objects
)
mock_swift_object.get_object.side_effect = (
(obj_header, json.dumps({'id': 1})), # Objects there during create
(obj_header, json.dumps({'id': 2})),
(obj_header, json.dumps({'id': 3})),
)
st.create()
self.assertEqual(('CREATE', 'COMPLETE'), st.state)
wc = st['test_wait_condition']
self.assertEqual("null", wc.FnGetAtt('data'))
@mock.patch.object(swift.SwiftClientPlugin, '_create')
@mock.patch.object(resource.Resource, 'physical_resource_name')
def test_swift_container_deleted(self, mock_name, mock_swift):
st = create_stack(swiftsignal_template)
handle = st['test_wait_condition_handle']
mock_swift_object = mock.Mock()
mock_swift.return_value = mock_swift_object
mock_swift_object.url = "http://fake-host.com:8080/v1/AUTH_1234"
mock_swift_object.head_account.return_value = {
'x-account-meta-temp-url-key': '123456'
}
obj_name = "%s-%s-abcdefghijkl" % (st.name, handle.name)
mock_name.return_value = obj_name
mock_swift_object.get_container.side_effect = [
cont_index(obj_name, 2), # Objects are there during create
swiftclient_client.ClientException("Container GET failed",
http_status=404) # User deleted
]
mock_swift_object.get_object.side_effect = (
(obj_header, json.dumps({'id': 1})), # Objects there during create
(obj_header, json.dumps({'id': 2})),
(obj_header, json.dumps({'id': 3})),
)
st.create()
self.assertEqual(('CREATE', 'COMPLETE'), st.state)
wc = st['test_wait_condition']
self.assertEqual("null", wc.FnGetAtt('data'))