deb-heat/heat/tests/test_waitcondition.py
tengqm 3d2b7facda Make all assertEqual() calls conform to convention
It is a convention to have assertEqual() assertions invoked with
'expected value' before 'actual value', or else the debug output may
become very confusing.  This patch fixes about 100 violations in current
test cases where about 3580 assertEqual calls are made.

Closes-Bug: 1259292
Change-Id: I2e0474d9821716baf35a3bbb2952c63a84749dd3
2014-12-03 19:07:26 +08:00

1047 lines
39 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 datetime
import json
import six
import time
import uuid
import mox
from oslo.config import cfg
from heat.common import identifier
from heat.common import template_format
from heat.db import api as db_api
from heat.engine.clients.os import heat_plugin
from heat.engine import environment
from heat.engine import parser
from heat.engine import resource
from heat.engine.resources import wait_condition as wc
from heat.engine import rsrc_defn
from heat.engine import scheduler
from heat.tests import common
from heat.tests import utils
test_template_waitcondition = '''
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Just a WaitCondition.",
"Parameters" : {},
"Resources" : {
"WaitHandle" : {
"Type" : "AWS::CloudFormation::WaitConditionHandle"
},
"WaitForTheHandle" : {
"Type" : "AWS::CloudFormation::WaitCondition",
"Properties" : {
"Handle" : {"Ref" : "WaitHandle"},
"Timeout" : "5"
}
}
}
}
'''
test_template_wc_count = '''
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Just a WaitCondition.",
"Parameters" : {},
"Resources" : {
"WaitHandle" : {
"Type" : "AWS::CloudFormation::WaitConditionHandle"
},
"WaitForTheHandle" : {
"Type" : "AWS::CloudFormation::WaitCondition",
"Properties" : {
"Handle" : {"Ref" : "WaitHandle"},
"Timeout" : "5",
"Count" : "3"
}
}
}
}
'''
test_template_update_waitcondition = '''
{
"HeatTemplateFormatVersion" : "2012-12-12",
"Description" : "Updatable Wait Condition",
"Parameters" : {},
"Resources" : {
"WaitHandle" : {
"Type" : "OS::Heat::UpdateWaitConditionHandle"
},
"WaitForTheHandle" : {
"Type" : "AWS::CloudFormation::WaitCondition",
"Properties" : {
"Handle" : {"Ref" : "WaitHandle"},
"Timeout" : "5",
"Count" : "3"
}
}
}
}
'''
test_template_heat_waitcondition = '''
heat_template_version: 2013-05-23
resources:
wait_condition:
type: OS::Heat::WaitCondition
properties:
handle: {get_resource: wait_handle}
timeout: 5
wait_handle:
type: OS::Heat::WaitConditionHandle
'''
test_template_heat_waitcondition_count = '''
heat_template_version: 2013-05-23
resources:
wait_condition:
type: OS::Heat::WaitCondition
properties:
handle: {get_resource: wait_handle}
count: 3
timeout: 5
wait_handle:
type: OS::Heat::WaitConditionHandle
'''
test_template_heat_waithandle = '''
heat_template_version: 2013-05-23
resources:
wait_handle:
type: OS::Heat::WaitConditionHandle
'''
class WaitConditionTest(common.HeatTestCase):
def setUp(self):
super(WaitConditionTest, self).setUp()
cfg.CONF.set_default('heat_waitcondition_server_url',
'http://server.test:8000/v1/waitcondition')
self.stub_keystoneclient()
def create_stack(self, stack_id=None,
template=test_template_waitcondition, params=None,
stub=True, stub_status=True):
params = params or {}
temp = template_format.parse(template)
template = parser.Template(temp)
ctx = utils.dummy_context(tenant_id='test_tenant')
stack = parser.Stack(ctx, 'test_stack', template,
environment.Environment(params),
disable_rollback=True)
# Stub out the stack ID so we have a known value
if stack_id is None:
stack_id = str(uuid.uuid4())
self.stack_id = stack_id
with utils.UUIDStub(self.stack_id):
stack.store()
if stub:
id = identifier.ResourceIdentifier('test_tenant', stack.name,
stack.id, '', 'WaitHandle')
self.m.StubOutWithMock(wc.WaitConditionHandle, 'identifier')
wc.WaitConditionHandle.identifier().MultipleTimes().AndReturn(id)
if stub_status:
self.m.StubOutWithMock(wc.WaitConditionHandle,
'get_status')
return stack
def test_post_success_to_handle(self):
self.stack = self.create_stack()
wc.WaitConditionHandle.get_status().AndReturn([])
wc.WaitConditionHandle.get_status().AndReturn([])
wc.WaitConditionHandle.get_status().AndReturn(['SUCCESS'])
self.m.ReplayAll()
self.stack.create()
rsrc = self.stack['WaitForTheHandle']
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE),
rsrc.state)
r = db_api.resource_get_by_name_and_stack(None, 'WaitHandle',
self.stack.id)
self.assertEqual('WaitHandle', r.name)
self.m.VerifyAll()
def test_post_failure_to_handle(self):
self.stack = self.create_stack()
wc.WaitConditionHandle.get_status().AndReturn([])
wc.WaitConditionHandle.get_status().AndReturn([])
wc.WaitConditionHandle.get_status().AndReturn(['FAILURE'])
self.m.ReplayAll()
self.stack.create()
rsrc = self.stack['WaitForTheHandle']
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
reason = rsrc.status_reason
self.assertTrue(reason.startswith('WaitConditionFailure:'))
r = db_api.resource_get_by_name_and_stack(None, 'WaitHandle',
self.stack.id)
self.assertEqual('WaitHandle', r.name)
self.m.VerifyAll()
def test_post_success_to_handle_count(self):
self.stack = self.create_stack(template=test_template_wc_count)
wc.WaitConditionHandle.get_status().AndReturn([])
wc.WaitConditionHandle.get_status().AndReturn(['SUCCESS'])
wc.WaitConditionHandle.get_status().AndReturn(['SUCCESS', 'SUCCESS'])
wc.WaitConditionHandle.get_status().AndReturn(['SUCCESS', 'SUCCESS',
'SUCCESS'])
self.m.ReplayAll()
self.stack.create()
rsrc = self.stack['WaitForTheHandle']
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE),
rsrc.state)
r = db_api.resource_get_by_name_and_stack(None, 'WaitHandle',
self.stack.id)
self.assertEqual('WaitHandle', r.name)
self.m.VerifyAll()
def test_post_failure_to_handle_count(self):
self.stack = self.create_stack(template=test_template_wc_count)
wc.WaitConditionHandle.get_status().AndReturn([])
wc.WaitConditionHandle.get_status().AndReturn(['SUCCESS'])
wc.WaitConditionHandle.get_status().AndReturn(['SUCCESS', 'FAILURE'])
self.m.ReplayAll()
self.stack.create()
rsrc = self.stack['WaitForTheHandle']
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
reason = rsrc.status_reason
self.assertTrue(reason.startswith('WaitConditionFailure:'))
r = db_api.resource_get_by_name_and_stack(None, 'WaitHandle',
self.stack.id)
self.assertEqual('WaitHandle', r.name)
self.m.VerifyAll()
def test_timeout(self):
st = time.time()
self.stack = self.create_stack()
# Avoid the stack create exercising the timeout code at the same time
self.m.StubOutWithMock(self.stack, 'timeout_secs')
self.stack.timeout_secs().MultipleTimes().AndReturn(None)
self.m.StubOutWithMock(scheduler, 'wallclock')
scheduler.wallclock().AndReturn(st)
scheduler.wallclock().AndReturn(st + 0.001)
scheduler.wallclock().AndReturn(st + 0.1)
wc.WaitConditionHandle.get_status().AndReturn([])
scheduler.wallclock().AndReturn(st + 4.1)
wc.WaitConditionHandle.get_status().AndReturn([])
scheduler.wallclock().AndReturn(st + 5.1)
self.m.ReplayAll()
self.stack.create()
rsrc = self.stack['WaitForTheHandle']
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
reason = rsrc.status_reason
self.assertTrue(reason.startswith('WaitConditionTimeout:'))
self.m.VerifyAll()
def test_FnGetAtt(self):
self.stack = self.create_stack()
wc.WaitConditionHandle.get_status().AndReturn(['SUCCESS'])
self.m.ReplayAll()
self.stack.create()
rsrc = self.stack['WaitForTheHandle']
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
wc_att = rsrc.FnGetAtt('Data')
self.assertEqual(unicode({}), wc_att)
handle = self.stack['WaitHandle']
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), handle.state)
test_metadata = {'Data': 'foo', 'Reason': 'bar',
'Status': 'SUCCESS', 'UniqueId': '123'}
ret = handle.handle_signal(test_metadata)
wc_att = rsrc.FnGetAtt('Data')
self.assertEqual('{"123": "foo"}', wc_att)
self.assertEqual('status:SUCCESS reason:bar', ret)
test_metadata = {'Data': 'dog', 'Reason': 'cat',
'Status': 'SUCCESS', 'UniqueId': '456'}
ret = handle.handle_signal(test_metadata)
wc_att = rsrc.FnGetAtt('Data')
self.assertEqual(u'{"123": "foo", "456": "dog"}', wc_att)
self.assertEqual('status:SUCCESS reason:cat', ret)
self.m.VerifyAll()
def test_validate_handle_url_bad_stackid(self):
self.m.ReplayAll()
stack_id = 'STACK_HUBSID_1234'
t = json.loads(test_template_waitcondition)
badhandle = ("http://server.test:8000/v1/waitcondition/" +
"arn%3Aopenstack%3Aheat%3A%3Atest_tenant" +
"%3Astacks%2Ftest_stack%2F" +
"bad1" +
"%2Fresources%2FWaitHandle")
t['Resources']['WaitForTheHandle']['Properties']['Handle'] = badhandle
self.stack = self.create_stack(template=json.dumps(t), stub=False,
stack_id=stack_id)
self.m.ReplayAll()
rsrc = self.stack['WaitForTheHandle']
self.assertRaises(ValueError, rsrc.handle_create)
self.m.VerifyAll()
def test_validate_handle_url_bad_stackname(self):
self.m.ReplayAll()
stack_id = 'STACKABCD1234'
t = json.loads(test_template_waitcondition)
badhandle = ("http://server.test:8000/v1/waitcondition/" +
"arn%3Aopenstack%3Aheat%3A%3Atest_tenant" +
"%3Astacks%2FBAD_stack%2F" +
stack_id + "%2Fresources%2FWaitHandle")
t['Resources']['WaitForTheHandle']['Properties']['Handle'] = badhandle
self.stack = self.create_stack(template=json.dumps(t), stub=False,
stack_id=stack_id)
rsrc = self.stack['WaitForTheHandle']
self.assertRaises(ValueError, rsrc.handle_create)
self.m.VerifyAll()
def test_validate_handle_url_bad_tenant(self):
self.m.ReplayAll()
stack_id = 'STACKABCD1234'
t = json.loads(test_template_waitcondition)
badhandle = ("http://server.test:8000/v1/waitcondition/" +
"arn%3Aopenstack%3Aheat%3A%3ABAD_tenant" +
"%3Astacks%2Ftest_stack%2F" +
stack_id + "%2Fresources%2FWaitHandle")
t['Resources']['WaitForTheHandle']['Properties']['Handle'] = badhandle
self.stack = self.create_stack(stack_id=stack_id,
template=json.dumps(t), stub=False)
rsrc = self.stack['WaitForTheHandle']
self.assertRaises(ValueError, rsrc.handle_create)
self.m.VerifyAll()
def test_validate_handle_url_bad_resource(self):
self.m.ReplayAll()
stack_id = 'STACK_HUBR_1234'
t = json.loads(test_template_waitcondition)
badhandle = ("http://server.test:8000/v1/waitcondition/" +
"arn%3Aopenstack%3Aheat%3A%3Atest_tenant" +
"%3Astacks%2Ftest_stack%2F" +
stack_id + "%2Fresources%2FBADHandle")
t['Resources']['WaitForTheHandle']['Properties']['Handle'] = badhandle
self.stack = self.create_stack(stack_id=stack_id,
template=json.dumps(t), stub=False)
rsrc = self.stack['WaitForTheHandle']
self.assertRaises(ValueError, rsrc.handle_create)
self.m.VerifyAll()
def test_validate_handle_url_bad_resource_type(self):
self.m.ReplayAll()
stack_id = 'STACKABCD1234'
t = json.loads(test_template_waitcondition)
badhandle = ("http://server.test:8000/v1/waitcondition/" +
"arn%3Aopenstack%3Aheat%3A%3Atest_tenant" +
"%3Astacks%2Ftest_stack%2F" +
stack_id + "%2Fresources%2FWaitForTheHandle")
t['Resources']['WaitForTheHandle']['Properties']['Handle'] = badhandle
self.stack = self.create_stack(stack_id=stack_id,
template=json.dumps(t), stub=False)
rsrc = self.stack['WaitForTheHandle']
self.assertRaises(ValueError, rsrc.handle_create)
self.m.VerifyAll()
class WaitConditionHandleTest(common.HeatTestCase):
def setUp(self):
super(WaitConditionHandleTest, self).setUp()
cfg.CONF.set_default('heat_waitcondition_server_url',
'http://server.test:8000/v1/waitcondition')
self.stub_keystoneclient()
def create_stack(self, stack_name=None, stack_id=None):
temp = template_format.parse(test_template_waitcondition)
template = parser.Template(temp)
ctx = utils.dummy_context(tenant_id='test_tenant')
if stack_name is None:
stack_name = utils.random_name()
stack = parser.Stack(ctx, stack_name, template,
disable_rollback=True)
# Stub out the UUID for this test, so we can get an expected signature
if stack_id is not None:
with utils.UUIDStub(stack_id):
stack.store()
else:
stack.store()
self.stack_id = stack.id
# Stub waitcondition status so all goes CREATE_COMPLETE
self.m.StubOutWithMock(wc.WaitConditionHandle, 'get_status')
wc.WaitConditionHandle.get_status().AndReturn(['SUCCESS'])
id = identifier.ResourceIdentifier('test_tenant', stack.name,
stack.id, '', 'WaitHandle')
self.m.StubOutWithMock(wc.WaitConditionHandle, 'identifier')
wc.WaitConditionHandle.identifier().MultipleTimes().AndReturn(id)
self.m.ReplayAll()
stack.create()
return stack
def test_handle(self):
stack_id = 'STACKABCD1234'
stack_name = 'test_stack2'
created_time = datetime.datetime(2012, 11, 29, 13, 49, 37)
self.stack = self.create_stack(stack_id=stack_id,
stack_name=stack_name)
rsrc = self.stack['WaitHandle']
# clear the url
rsrc.data_set('ec2_signed_url', None, False)
rsrc.created_time = created_time
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
expected_url = "".join([
'http://server.test:8000/v1/waitcondition/',
'arn%3Aopenstack%3Aheat%3A%3Atest_tenant%3Astacks%2F',
'test_stack2%2F', stack_id, '%2Fresources%2F',
'WaitHandle?',
'Timestamp=2012-11-29T13%3A49%3A37Z&',
'SignatureMethod=HmacSHA256&',
'AWSAccessKeyId=4567&',
'SignatureVersion=2&',
'Signature=',
'fHyt3XFnHq8%2FSwYaVcHdJka1hz6jdK5mHtgbo8OOKbQ%3D'])
self.assertEqual(unicode(expected_url), rsrc.FnGetRefId())
self.m.VerifyAll()
def test_handle_signal(self):
self.stack = self.create_stack()
rsrc = self.stack['WaitHandle']
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
test_metadata = {'Data': 'foo', 'Reason': 'bar',
'Status': 'SUCCESS', 'UniqueId': '123'}
rsrc.handle_signal(test_metadata)
handle_metadata = {u'123': {u'Data': u'foo',
u'Reason': u'bar',
u'Status': u'SUCCESS'}}
self.assertEqual(handle_metadata, rsrc.metadata_get())
self.m.VerifyAll()
def test_handle_signal_invalid(self):
self.stack = self.create_stack()
rsrc = self.stack['WaitHandle']
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
# handle_signal should raise a ValueError if the metadata
# is missing any of the expected keys
err_metadata = {'Data': 'foo', 'Status': 'SUCCESS', 'UniqueId': '123'}
self.assertRaises(ValueError, rsrc.handle_signal,
err_metadata)
err_metadata = {'Data': 'foo', 'Reason': 'bar', 'UniqueId': '1234'}
self.assertRaises(ValueError, rsrc.handle_signal,
err_metadata)
err_metadata = {'Data': 'foo', 'Reason': 'bar', 'UniqueId': '1234'}
self.assertRaises(ValueError, rsrc.handle_signal,
err_metadata)
err_metadata = {'data': 'foo', 'reason': 'bar',
'status': 'SUCCESS', 'uniqueid': '1234'}
self.assertRaises(ValueError, rsrc.handle_signal,
err_metadata)
# Also any Status other than SUCCESS or FAILURE should be rejected
err_metadata = {'Data': 'foo', 'Reason': 'bar',
'Status': 'UCCESS', 'UniqueId': '123'}
self.assertRaises(ValueError, rsrc.handle_signal,
err_metadata)
err_metadata = {'Data': 'foo', 'Reason': 'bar',
'Status': 'wibble', 'UniqueId': '123'}
self.assertRaises(ValueError, rsrc.handle_signal,
err_metadata)
err_metadata = {'Data': 'foo', 'Reason': 'bar',
'Status': 'success', 'UniqueId': '123'}
self.assertRaises(ValueError, rsrc.handle_signal,
err_metadata)
err_metadata = {'Data': 'foo', 'Reason': 'bar',
'Status': 'FAIL', 'UniqueId': '123'}
self.assertRaises(ValueError, rsrc.handle_signal,
err_metadata)
self.m.VerifyAll()
def test_get_status(self):
self.stack = self.create_stack()
rsrc = self.stack['WaitHandle']
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
# UnsetStubs, don't want get_status stubbed anymore..
self.m.VerifyAll()
self.m.UnsetStubs()
self.assertEqual([], rsrc.get_status())
test_metadata = {'Data': 'foo', 'Reason': 'bar',
'Status': 'SUCCESS', 'UniqueId': '123'}
ret = rsrc.handle_signal(test_metadata)
self.assertEqual(['SUCCESS'], rsrc.get_status())
self.assertEqual('status:SUCCESS reason:bar', ret)
test_metadata = {'Data': 'foo', 'Reason': 'bar2',
'Status': 'SUCCESS', 'UniqueId': '456'}
ret = rsrc.handle_signal(test_metadata)
self.assertEqual(['SUCCESS', 'SUCCESS'], rsrc.get_status())
self.assertEqual('status:SUCCESS reason:bar2', ret)
def test_get_status_reason(self):
self.stack = self.create_stack()
rsrc = self.stack['WaitHandle']
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
test_metadata = {'Data': 'foo', 'Reason': 'bar',
'Status': 'SUCCESS', 'UniqueId': '123'}
ret = rsrc.handle_signal(test_metadata)
self.assertEqual(['bar'], rsrc.get_status_reason('SUCCESS'))
self.assertEqual('status:SUCCESS reason:bar', ret)
test_metadata = {'Data': 'dog', 'Reason': 'cat',
'Status': 'SUCCESS', 'UniqueId': '456'}
ret = rsrc.handle_signal(test_metadata)
self.assertEqual(['bar', 'cat'], rsrc.get_status_reason('SUCCESS'))
self.assertEqual('status:SUCCESS reason:cat', ret)
test_metadata = {'Data': 'boo', 'Reason': 'hoo',
'Status': 'FAILURE', 'UniqueId': '789'}
ret = rsrc.handle_signal(test_metadata)
self.assertEqual(['hoo'], rsrc.get_status_reason('FAILURE'))
self.assertEqual('status:FAILURE reason:hoo', ret)
self.m.VerifyAll()
class WaitConditionUpdateTest(common.HeatTestCase):
def setUp(self):
super(WaitConditionUpdateTest, self).setUp()
cfg.CONF.set_default('heat_waitcondition_server_url',
'http://server.test:8000/v1/waitcondition')
self.stub_keystoneclient()
scheduler.ENABLE_SLEEP = False
def tearDown(self):
super(WaitConditionUpdateTest, self).tearDown()
scheduler.ENABLE_SLEEP = True
def create_stack(self, tmpl=None):
if tmpl is None:
tmpl = test_template_wc_count
temp = template_format.parse(tmpl)
template = parser.Template(temp)
ctx = utils.dummy_context(tenant_id='test_tenant')
stack = parser.Stack(ctx, 'test_stack', template,
environment.Environment({}),
disable_rollback=True)
stack_id = str(uuid.uuid4())
self.stack_id = stack_id
with utils.UUIDStub(self.stack_id):
stack.store()
self.m.StubOutWithMock(wc.WaitConditionHandle, 'get_status')
wc.WaitConditionHandle.get_status().AndReturn([])
wc.WaitConditionHandle.get_status().AndReturn(['SUCCESS'])
wc.WaitConditionHandle.get_status().AndReturn(['SUCCESS', 'SUCCESS'])
wc.WaitConditionHandle.get_status().AndReturn(['SUCCESS', 'SUCCESS',
'SUCCESS'])
return stack
def get_stack(self, stack_id):
ctx = utils.dummy_context(tenant_id='test_tenant')
stack = parser.Stack.load(ctx, stack_id)
self.stack_id = stack_id
return stack
def test_update(self):
self.stack = self.create_stack()
self.m.ReplayAll()
self.stack.create()
rsrc = self.stack['WaitForTheHandle']
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
self.m.UnsetStubs()
wait_condition_handle = self.stack['WaitHandle']
test_metadata = {'Data': 'foo', 'Reason': 'bar',
'Status': 'SUCCESS', 'UniqueId': '1'}
self._handle_signal(wait_condition_handle, test_metadata, 5)
uprops = copy.copy(rsrc.properties.data)
uprops['Count'] = '5'
update_snippet = rsrc_defn.ResourceDefinition(rsrc.name,
rsrc.type(),
uprops)
updater = scheduler.TaskRunner(rsrc.update, update_snippet)
updater()
self.assertEqual((rsrc.UPDATE, rsrc.COMPLETE), rsrc.state)
def test_handle_update(self):
self.stack = self.create_stack()
self.m.ReplayAll()
self.stack.create()
rsrc = self.stack['WaitForTheHandle']
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
self.m.UnsetStubs()
wait_condition_handle = self.stack['WaitHandle']
test_metadata = {'Data': 'foo', 'Reason': 'bar',
'Status': 'SUCCESS', 'UniqueId': '1'}
self._handle_signal(wait_condition_handle, test_metadata, 5)
prop_diff = {"Count": 5}
props = copy.copy(rsrc.properties.data)
props.update(prop_diff)
update_defn = rsrc_defn.ResourceDefinition(rsrc.name, rsrc.type(),
props)
updater = rsrc.handle_update(update_defn, {}, prop_diff)
updater.run_to_completion()
self.assertEqual(5, rsrc.properties['Count'])
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
def test_handle_update_restored_from_db(self):
self.stack = self.create_stack()
self.m.ReplayAll()
self.stack.create()
rsrc = self.stack['WaitForTheHandle']
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
self.m.UnsetStubs()
wait_condition_handle = self.stack['WaitHandle']
test_metadata = {'Data': 'foo', 'Reason': 'bar',
'Status': 'SUCCESS', 'UniqueId': '1'}
self._handle_signal(wait_condition_handle, test_metadata, 2)
self.stack.store()
self.stack = self.get_stack(self.stack_id)
rsrc = self.stack['WaitForTheHandle']
self._handle_signal(wait_condition_handle, test_metadata, 3)
prop_diff = {"Count": 5}
props = copy.copy(rsrc.properties.data)
props.update(prop_diff)
update_defn = rsrc_defn.ResourceDefinition(rsrc.name, rsrc.type(),
props)
updater = rsrc.handle_update(update_defn, {}, prop_diff)
updater.run_to_completion()
self.assertEqual(5, rsrc.properties['Count'])
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
def _handle_signal(self, rsrc, metadata, times=1):
for time in range(times):
metadata['UniqueId'] = metadata['UniqueId'] * 2
ret = rsrc.handle_signal(metadata)
self.assertEqual("status:%s reason:%s" %
(metadata[rsrc.STATUS], metadata[rsrc.REASON]),
ret)
def test_handle_update_timeout(self):
self.stack = self.create_stack()
self.m.ReplayAll()
self.stack.create()
rsrc = self.stack['WaitForTheHandle']
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
self.m.UnsetStubs()
st = time.time()
self.m.StubOutWithMock(scheduler.TaskRunner, '_sleep')
scheduler.TaskRunner._sleep(mox.IgnoreArg()).MultipleTimes().AndReturn(
None)
self.m.StubOutWithMock(scheduler, 'wallclock')
scheduler.wallclock().AndReturn(st)
scheduler.wallclock().AndReturn(st + 0.001)
scheduler.wallclock().AndReturn(st + 0.1)
scheduler.wallclock().AndReturn(st + 4.1)
scheduler.wallclock().AndReturn(st + 5.1)
self.m.ReplayAll()
prop_diff = {"Count": 5}
props = copy.copy(rsrc.properties.data)
props.update(prop_diff)
update_defn = rsrc_defn.ResourceDefinition(rsrc.name, rsrc.type(),
props)
updater = rsrc.handle_update(update_defn, {}, prop_diff)
self.assertEqual(5, rsrc.properties['Count'])
ex = self.assertRaises(wc.WaitConditionTimeout,
updater.run_to_completion)
self.assertEqual("0 of 5 received", six.text_type(ex))
self.m.VerifyAll()
self.m.UnsetStubs()
def test_update_updatehandle(self):
self.stack = self.create_stack(test_template_update_waitcondition)
self.m.ReplayAll()
self.stack.create()
rsrc = self.stack['WaitForTheHandle']
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
self.m.UnsetStubs()
wait_condition_handle = self.stack['WaitHandle']
self.assertRaises(
resource.UpdateReplace, wait_condition_handle.update, None, None)
class HeatWaitConditionTest(common.HeatTestCase):
def setUp(self):
super(HeatWaitConditionTest, self).setUp()
self.stub_keystoneclient()
self.tenant_id = 'test_tenant'
def create_stack(self, stack_id=None,
template=test_template_heat_waitcondition_count,
params={},
stub=True, stub_status=True):
temp = template_format.parse(template)
template = parser.Template(temp)
ctx = utils.dummy_context(tenant_id=self.tenant_id)
stack = parser.Stack(ctx, 'test_stack', template,
environment.Environment(params),
disable_rollback=True)
# Stub out the stack ID so we have a known value
if stack_id is None:
stack_id = str(uuid.uuid4())
self.stack_id = stack_id
with utils.UUIDStub(self.stack_id):
stack.store()
if stub:
id = identifier.ResourceIdentifier('test_tenant', stack.name,
stack.id, '', 'wait_handle')
self.m.StubOutWithMock(wc.HeatWaitConditionHandle, 'identifier')
wc.HeatWaitConditionHandle.identifier().MultipleTimes().AndReturn(
id)
if stub_status:
self.m.StubOutWithMock(wc.HeatWaitConditionHandle,
'get_status')
return stack
def test_post_complete_to_handle(self):
self.stack = self.create_stack()
wc.HeatWaitConditionHandle.get_status().AndReturn(['SUCCESS'])
wc.HeatWaitConditionHandle.get_status().AndReturn(['SUCCESS',
'SUCCESS'])
wc.HeatWaitConditionHandle.get_status().AndReturn(['SUCCESS',
'SUCCESS',
'SUCCESS'])
self.m.ReplayAll()
self.stack.create()
rsrc = self.stack['wait_condition']
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE),
rsrc.state)
r = db_api.resource_get_by_name_and_stack(None, 'wait_handle',
self.stack.id)
self.assertEqual('wait_handle', r.name)
self.m.VerifyAll()
def test_post_failed_to_handle(self):
self.stack = self.create_stack()
wc.HeatWaitConditionHandle.get_status().AndReturn(['SUCCESS'])
wc.HeatWaitConditionHandle.get_status().AndReturn(['SUCCESS',
'SUCCESS'])
wc.HeatWaitConditionHandle.get_status().AndReturn(['SUCCESS',
'SUCCESS',
'FAILURE'])
self.m.ReplayAll()
self.stack.create()
rsrc = self.stack['wait_condition']
self.assertEqual((rsrc.CREATE, rsrc.FAILED),
rsrc.state)
reason = rsrc.status_reason
self.assertTrue(reason.startswith('WaitConditionFailure:'))
r = db_api.resource_get_by_name_and_stack(None, 'wait_handle',
self.stack.id)
self.assertEqual('wait_handle', r.name)
self.m.VerifyAll()
def test_timeout(self):
st = time.time()
self.stack = self.create_stack()
# Avoid the stack create exercising the timeout code at the same time
self.m.StubOutWithMock(self.stack, 'timeout_secs')
self.stack.timeout_secs().MultipleTimes().AndReturn(None)
self.m.StubOutWithMock(scheduler, 'wallclock')
scheduler.wallclock().AndReturn(st)
scheduler.wallclock().AndReturn(st + 0.001)
scheduler.wallclock().AndReturn(st + 0.1)
wc.HeatWaitConditionHandle.get_status().AndReturn([])
scheduler.wallclock().AndReturn(st + 4.1)
wc.HeatWaitConditionHandle.get_status().AndReturn([])
scheduler.wallclock().AndReturn(st + 5.1)
self.m.ReplayAll()
self.stack.create()
rsrc = self.stack['wait_condition']
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
reason = rsrc.status_reason
self.assertTrue(reason.startswith('WaitConditionTimeout:'))
self.m.VerifyAll()
def _create_heat_wc_and_handle(self):
self.stack = self.create_stack(
template=test_template_heat_waitcondition)
wc.HeatWaitConditionHandle.get_status().AndReturn(['SUCCESS'])
self.m.ReplayAll()
self.stack.create()
rsrc = self.stack['wait_condition']
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
wc_att = rsrc.FnGetAtt('data')
self.assertEqual(unicode({}), wc_att)
handle = self.stack['wait_handle']
self.assertEqual((handle.CREATE, handle.COMPLETE), handle.state)
return (rsrc, handle)
def test_data(self):
rsrc, handle = self._create_heat_wc_and_handle()
test_metadata = {'data': 'foo', 'reason': 'bar',
'status': 'SUCCESS', 'id': '123'}
ret = handle.handle_signal(details=test_metadata)
wc_att = rsrc.FnGetAtt('data')
self.assertEqual('{"123": "foo"}', wc_att)
self.assertEqual('status:SUCCESS reason:bar', ret)
test_metadata = {'data': 'dog', 'reason': 'cat',
'status': 'SUCCESS', 'id': '456'}
ret = handle.handle_signal(details=test_metadata)
wc_att = rsrc.FnGetAtt('data')
self.assertEqual(u'{"123": "foo", "456": "dog"}', wc_att)
self.assertEqual('status:SUCCESS reason:cat', ret)
self.m.VerifyAll()
def test_data_noid(self):
rsrc, handle = self._create_heat_wc_and_handle()
test_metadata = {'data': 'foo', 'reason': 'bar',
'status': 'SUCCESS'}
ret = handle.handle_signal(details=test_metadata)
wc_att = rsrc.FnGetAtt('data')
self.assertEqual('{"1": "foo"}', wc_att)
self.assertEqual('status:SUCCESS reason:bar', ret)
test_metadata = {'data': 'dog', 'reason': 'cat',
'status': 'SUCCESS'}
ret = handle.handle_signal(details=test_metadata)
wc_att = rsrc.FnGetAtt('data')
self.assertEqual(u'{"1": "foo", "2": "dog"}', wc_att)
self.assertEqual('status:SUCCESS reason:cat', ret)
self.m.VerifyAll()
def test_data_nodata(self):
rsrc, handle = self._create_heat_wc_and_handle()
ret = handle.handle_signal()
expected = 'status:SUCCESS reason:Signal 1 received'
self.assertEqual(expected, ret)
wc_att = rsrc.FnGetAtt('data')
self.assertEqual('{"1": null}', wc_att)
handle.handle_signal()
wc_att = rsrc.FnGetAtt('data')
self.assertEqual(u'{"1": null, "2": null}', wc_att)
self.m.VerifyAll()
def test_data_partial_complete(self):
rsrc, handle = self._create_heat_wc_and_handle()
test_metadata = {'status': 'SUCCESS'}
ret = handle.handle_signal(details=test_metadata)
expected = 'status:SUCCESS reason:Signal 1 received'
self.assertEqual(expected, ret)
wc_att = rsrc.FnGetAtt('data')
self.assertEqual('{"1": null}', wc_att)
test_metadata = {'status': 'SUCCESS'}
ret = handle.handle_signal(details=test_metadata)
expected = 'status:SUCCESS reason:Signal 2 received'
self.assertEqual(expected, ret)
wc_att = rsrc.FnGetAtt('data')
self.assertEqual(u'{"1": null, "2": null}', wc_att)
self.m.VerifyAll()
def _create_heat_handle(self):
self.stack = self.create_stack(
template=test_template_heat_waithandle, stub_status=False)
self.m.ReplayAll()
self.stack.create()
handle = self.stack['wait_handle']
self.assertEqual((handle.CREATE, handle.COMPLETE), handle.state)
return handle
def test_get_status_none_complete(self):
handle = self._create_heat_handle()
ret = handle.handle_signal()
expected = 'status:SUCCESS reason:Signal 1 received'
self.assertEqual(expected, ret)
self.assertEqual(['SUCCESS'], handle.get_status())
md_expected = {'1': {'data': None, 'reason': 'Signal 1 received',
'status': 'SUCCESS'}}
self.assertEqual(md_expected, handle.metadata_get())
self.m.VerifyAll()
def test_get_status_partial_complete(self):
handle = self._create_heat_handle()
test_metadata = {'status': 'SUCCESS'}
ret = handle.handle_signal(details=test_metadata)
expected = 'status:SUCCESS reason:Signal 1 received'
self.assertEqual(expected, ret)
self.assertEqual(['SUCCESS'], handle.get_status())
md_expected = {'1': {'data': None, 'reason': 'Signal 1 received',
'status': 'SUCCESS'}}
self.assertEqual(md_expected, handle.metadata_get())
self.m.VerifyAll()
def test_get_status_failure(self):
handle = self._create_heat_handle()
test_metadata = {'status': 'FAILURE'}
ret = handle.handle_signal(details=test_metadata)
expected = 'status:FAILURE reason:Signal 1 received'
self.assertEqual(expected, ret)
self.assertEqual(['FAILURE'], handle.get_status())
md_expected = {'1': {'data': None, 'reason': 'Signal 1 received',
'status': 'FAILURE'}}
self.assertEqual(md_expected, handle.metadata_get())
self.m.VerifyAll()
def test_getatt_token(self):
handle = self._create_heat_handle()
self.assertEqual('adomainusertoken', handle.FnGetAtt('token'))
self.m.VerifyAll()
def test_getatt_endpoint(self):
self.m.StubOutWithMock(heat_plugin.HeatClientPlugin, 'get_heat_url')
heat_plugin.HeatClientPlugin.get_heat_url().AndReturn(
'foo/%s' % self.tenant_id)
self.m.ReplayAll()
handle = self._create_heat_handle()
expected = ('foo/aprojectid/stacks/test_stack/%s/resources/'
'wait_handle/signal'
% self.stack_id)
self.assertEqual(expected, handle.FnGetAtt('endpoint'))
self.m.VerifyAll()
def test_getatt_curl_cli(self):
self.m.StubOutWithMock(heat_plugin.HeatClientPlugin, 'get_heat_url')
heat_plugin.HeatClientPlugin.get_heat_url().AndReturn(
'foo/%s' % self.tenant_id)
self.m.ReplayAll()
handle = self._create_heat_handle()
expected = ("curl -i -X POST -H 'X-Auth-Token: adomainusertoken' "
"-H 'Content-Type: application/json' "
"-H 'Accept: application/json' "
"foo/aprojectid/stacks/test_stack/%s/resources/wait_handle"
"/signal" % self.stack_id)
self.assertEqual(expected, handle.FnGetAtt('curl_cli'))
self.m.VerifyAll()