diff --git a/heat/engine/resources/aws/wait_condition.py b/heat/engine/resources/aws/wait_condition.py index c4fc6961d..a52f1ecb6 100644 --- a/heat/engine/resources/aws/wait_condition.py +++ b/heat/engine/resources/aws/wait_condition.py @@ -16,8 +16,8 @@ from heat.common import identifier from heat.engine import attributes from heat.engine import constraints from heat.engine import properties +from heat.engine.resources.aws import wait_condition_handle as aws_wch from heat.engine.resources.openstack import wait_condition as heat_wc -from heat.engine.resources import wait_condition as wc_base from heat.engine import support @@ -92,7 +92,7 @@ class WaitCondition(heat_wc.HeatWaitCondition): raise ValueError(_("WaitCondition invalid Handle %s") % handle_id.resource_name) if not isinstance(self.stack[handle_id.resource_name], - wc_base.WaitConditionHandle): + aws_wch.WaitConditionHandle): raise ValueError(_("WaitCondition invalid Handle %s") % handle_id.resource_name) diff --git a/heat/engine/resources/aws/wait_condition_handle.py b/heat/engine/resources/aws/wait_condition_handle.py new file mode 100644 index 000000000..24bb26e01 --- /dev/null +++ b/heat/engine/resources/aws/wait_condition_handle.py @@ -0,0 +1,75 @@ +# +# 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 six + +from heat.engine.resources import wait_condition as wc_base +from heat.engine import signal_responder +from heat.engine import support + + +class WaitConditionHandle(wc_base.BaseWaitConditionHandle): + ''' + the main point of this class is to : + have no dependencies (so the instance can reference it) + generate a unique url (to be returned in the reference) + then the cfn-signal will use this url to post to and + WaitCondition will poll it to see if has been written to. + ''' + + support_status = support.SupportStatus(version='2014.1') + + METADATA_KEYS = ( + DATA, REASON, STATUS, UNIQUE_ID + ) = ( + 'Data', 'Reason', 'Status', 'UniqueId' + ) + + def handle_create(self): + super(WaitConditionHandle, self).handle_create() + self.resource_id_set(self._get_user_id()) + + def FnGetRefId(self): + ''' + Override the default resource FnGetRefId so we return the signed URL + ''' + if self.resource_id: + wc = signal_responder.WAITCONDITION + return six.text_type(self._get_signed_url(signal_type=wc)) + else: + return six.text_type(self.name) + + def metadata_update(self, new_metadata=None): + """DEPRECATED. Should use handle_signal instead.""" + self.handle_signal(details=new_metadata) + + def handle_signal(self, details=None): + ''' + Validate and update the resource metadata + metadata must use the following format: + { + "Status" : "Status (must be SUCCESS or FAILURE)", + "UniqueId" : "Some ID, should be unique for Count>1", + "Data" : "Arbitrary Data", + "Reason" : "Reason String" + } + ''' + if details is None: + return + return super(WaitConditionHandle, self).handle_signal(details) + + +def resource_mapping(): + return { + 'AWS::CloudFormation::WaitConditionHandle': WaitConditionHandle, + } diff --git a/heat/engine/resources/openstack/wait_condition_handle.py b/heat/engine/resources/openstack/wait_condition_handle.py new file mode 100644 index 000000000..77d51f1b4 --- /dev/null +++ b/heat/engine/resources/openstack/wait_condition_handle.py @@ -0,0 +1,157 @@ +# +# 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 uuid + +from heat.common.i18n import _ +from heat.engine import attributes +from heat.engine import resource +from heat.engine.resources.aws import wait_condition_handle as aws_wch +from heat.engine.resources import wait_condition as wc_base +from heat.engine import support + + +class HeatWaitConditionHandle(wc_base.BaseWaitConditionHandle): + + support_status = support.SupportStatus(version='2014.2') + + METADATA_KEYS = ( + DATA, REASON, STATUS, UNIQUE_ID + ) = ( + 'data', 'reason', 'status', 'id' + ) + + ATTRIBUTES = ( + TOKEN, + ENDPOINT, + CURL_CLI, + ) = ( + 'token', + 'endpoint', + 'curl_cli', + ) + + attributes_schema = { + TOKEN: attributes.Schema( + _('Token for stack-user which can be used for signalling handle'), + cache_mode=attributes.Schema.CACHE_NONE + ), + ENDPOINT: attributes.Schema( + _('Endpoint/url which can be used for signalling handle'), + cache_mode=attributes.Schema.CACHE_NONE + ), + CURL_CLI: attributes.Schema( + _('Convenience attribute, provides curl CLI command ' + 'prefix, which can be used for signalling handle completion or ' + 'failure. You can signal success by adding ' + '--data-binary \'{"status": "SUCCESS"}\' ' + ', or signal failure by adding ' + '--data-binary \'{"status": "FAILURE"}\''), + cache_mode=attributes.Schema.CACHE_NONE + ), + } + + def handle_create(self): + password = uuid.uuid4().hex + self.data_set('password', password, True) + self._create_user() + self.resource_id_set(self._get_user_id()) + # FIXME(shardy): The assumption here is that token expiry > timeout + # but we probably need a check here to fail fast if that's not true + # Also need to implement an update property, such that the handle + # can be replaced on update which will replace the token + token = self._user_token() + self.data_set('token', token, True) + self.data_set('endpoint', '%s/signal' % self._get_resource_endpoint()) + + def _get_resource_endpoint(self): + # Get the endpoint from stack.clients then replace the context + # project_id with the path to the resource (which includes the + # context project_id), then replace the context project with + # the one needed for signalling from the stack_user_project + heat_client_plugin = self.stack.clients.client_plugin('heat') + endpoint = heat_client_plugin.get_heat_url() + rsrc_ep = endpoint.replace(self.context.tenant_id, + self.identifier().url_path()) + return rsrc_ep.replace(self.context.tenant_id, + self.stack.stack_user_project_id) + + def handle_delete(self): + self._delete_user() + + @property + def password(self): + return self.data().get('password') + + def _resolve_attribute(self, key): + if self.resource_id: + if key == self.TOKEN: + return self.data().get('token') + elif key == self.ENDPOINT: + return self.data().get('endpoint') + elif key == self.CURL_CLI: + # Construct curl command for template-author convenience + return ('curl -i -X POST ' + '-H \'X-Auth-Token: %(token)s\' ' + '-H \'Content-Type: application/json\' ' + '-H \'Accept: application/json\' ' + '%(endpoint)s' % + dict(token=self.data().get('token'), + endpoint=self.data().get('endpoint'))) + + def handle_signal(self, details=None): + ''' + Validate and update the resource metadata. + metadata is not mandatory, but if passed it must use the following + format: + { + "status" : "Status (must be SUCCESS or FAILURE)", + "data" : "Arbitrary data", + "reason" : "Reason string" + } + Optionally "id" may also be specified, but if missing the index + of the signal received will be used. + ''' + rsrc_metadata = self.metadata_get(refresh=True) + signal_num = len(rsrc_metadata) + 1 + reason = 'Signal %s received' % signal_num + # Tolerate missing values, default to success + metadata = details or {} + metadata.setdefault(self.REASON, reason) + metadata.setdefault(self.DATA, None) + metadata.setdefault(self.UNIQUE_ID, signal_num) + metadata.setdefault(self.STATUS, self.STATUS_SUCCESS) + return super(HeatWaitConditionHandle, self).handle_signal(metadata) + + +class UpdateWaitConditionHandle(aws_wch.WaitConditionHandle): + ''' + This works identically to a regular WaitConditionHandle, except that + on update it clears all signals received and changes the handle. Using + this handle means that you must setup the signal senders to send their + signals again any time the update handle changes. This allows us to roll + out new configurations and be confident that they are rolled out once + UPDATE COMPLETE is reached. + ''' + + support_status = support.SupportStatus(version='2014.1') + + def update(self, after, before=None, prev_resource=None): + raise resource.UpdateReplace(self.name) + + +def resource_mapping(): + return { + 'OS::Heat::WaitConditionHandle': HeatWaitConditionHandle, + 'OS::Heat::UpdateWaitConditionHandle': UpdateWaitConditionHandle, + } diff --git a/heat/engine/resources/wait_condition.py b/heat/engine/resources/wait_condition.py index e1c9a7c1e..303372037 100644 --- a/heat/engine/resources/wait_condition.py +++ b/heat/engine/resources/wait_condition.py @@ -11,19 +11,11 @@ # License for the specific language governing permissions and limitations # under the License. -import six -import uuid - from heat.common import exception from heat.common.i18n import _ from heat.common.i18n import _LE from heat.common.i18n import _LW - -from heat.engine import attributes -from heat.engine import resource - from heat.engine import signal_responder -from heat.engine import support from heat.openstack.common import log as logging LOG = logging.getLogger(__name__) @@ -96,186 +88,6 @@ class BaseWaitConditionHandle(signal_responder.SignalResponder): if v[self.STATUS] == status] -class HeatWaitConditionHandle(BaseWaitConditionHandle): - - support_status = support.SupportStatus(version='2014.2') - - METADATA_KEYS = ( - DATA, REASON, STATUS, UNIQUE_ID - ) = ( - 'data', 'reason', 'status', 'id' - ) - - ATTRIBUTES = ( - TOKEN, - ENDPOINT, - CURL_CLI, - ) = ( - 'token', - 'endpoint', - 'curl_cli', - ) - - attributes_schema = { - TOKEN: attributes.Schema( - _('Token for stack-user which can be used for signalling handle'), - cache_mode=attributes.Schema.CACHE_NONE - ), - ENDPOINT: attributes.Schema( - _('Endpoint/url which can be used for signalling handle'), - cache_mode=attributes.Schema.CACHE_NONE - ), - CURL_CLI: attributes.Schema( - _('Convenience attribute, provides curl CLI command ' - 'prefix, which can be used for signalling handle completion or ' - 'failure. You can signal success by adding ' - '--data-binary \'{"status": "SUCCESS"}\' ' - ', or signal failure by adding ' - '--data-binary \'{"status": "FAILURE"}\''), - cache_mode=attributes.Schema.CACHE_NONE - ), - } - - def handle_create(self): - password = uuid.uuid4().hex - self.data_set('password', password, True) - self._create_user() - self.resource_id_set(self._get_user_id()) - # FIXME(shardy): The assumption here is that token expiry > timeout - # but we probably need a check here to fail fast if that's not true - # Also need to implement an update property, such that the handle - # can be replaced on update which will replace the token - token = self._user_token() - self.data_set('token', token, True) - self.data_set('endpoint', '%s/signal' % self._get_resource_endpoint()) - - def _get_resource_endpoint(self): - # Get the endpoint from stack.clients then replace the context - # project_id with the path to the resource (which includes the - # context project_id), then replace the context project with - # the one needed for signalling from the stack_user_project - heat_client_plugin = self.stack.clients.client_plugin('heat') - endpoint = heat_client_plugin.get_heat_url() - rsrc_ep = endpoint.replace(self.context.tenant_id, - self.identifier().url_path()) - return rsrc_ep.replace(self.context.tenant_id, - self.stack.stack_user_project_id) - - def handle_delete(self): - self._delete_user() - - @property - def password(self): - return self.data().get('password') - - def _resolve_attribute(self, key): - if self.resource_id: - if key == self.TOKEN: - return self.data().get('token') - elif key == self.ENDPOINT: - return self.data().get('endpoint') - elif key == self.CURL_CLI: - # Construct curl command for template-author convenience - return ('curl -i -X POST ' - '-H \'X-Auth-Token: %(token)s\' ' - '-H \'Content-Type: application/json\' ' - '-H \'Accept: application/json\' ' - '%(endpoint)s' % - dict(token=self.data().get('token'), - endpoint=self.data().get('endpoint'))) - - def handle_signal(self, details=None): - ''' - Validate and update the resource metadata. - metadata is not mandatory, but if passed it must use the following - format: - { - "status" : "Status (must be SUCCESS or FAILURE)", - "data" : "Arbitrary data", - "reason" : "Reason string" - } - Optionally "id" may also be specified, but if missing the index - of the signal received will be used. - ''' - rsrc_metadata = self.metadata_get(refresh=True) - signal_num = len(rsrc_metadata) + 1 - reason = 'Signal %s received' % signal_num - # Tolerate missing values, default to success - metadata = details or {} - metadata.setdefault(self.REASON, reason) - metadata.setdefault(self.DATA, None) - metadata.setdefault(self.UNIQUE_ID, signal_num) - metadata.setdefault(self.STATUS, self.STATUS_SUCCESS) - return super(HeatWaitConditionHandle, self).handle_signal(metadata) - - -class WaitConditionHandle(BaseWaitConditionHandle): - ''' - the main point of this class is to : - have no dependencies (so the instance can reference it) - generate a unique url (to be returned in the reference) - then the cfn-signal will use this url to post to and - WaitCondition will poll it to see if has been written to. - ''' - - support_status = support.SupportStatus(version='2014.1') - - METADATA_KEYS = ( - DATA, REASON, STATUS, UNIQUE_ID - ) = ( - 'Data', 'Reason', 'Status', 'UniqueId' - ) - - def handle_create(self): - super(WaitConditionHandle, self).handle_create() - self.resource_id_set(self._get_user_id()) - - def FnGetRefId(self): - ''' - Override the default resource FnGetRefId so we return the signed URL - ''' - if self.resource_id: - wc = signal_responder.WAITCONDITION - return six.text_type(self._get_signed_url(signal_type=wc)) - else: - return six.text_type(self.name) - - def metadata_update(self, new_metadata=None): - """DEPRECATED. Should use handle_signal instead.""" - self.handle_signal(details=new_metadata) - - def handle_signal(self, details=None): - ''' - Validate and update the resource metadata - metadata must use the following format: - { - "Status" : "Status (must be SUCCESS or FAILURE)", - "UniqueId" : "Some ID, should be unique for Count>1", - "Data" : "Arbitrary Data", - "Reason" : "Reason String" - } - ''' - if details is None: - return - return super(WaitConditionHandle, self).handle_signal(details) - - -class UpdateWaitConditionHandle(WaitConditionHandle): - ''' - This works identically to a regular WaitConditionHandle, except that - on update it clears all signals received and changes the handle. Using - this handle means that you must setup the signal senders to send their - signals again any time the update handle changes. This allows us to roll - out new configurations and be confident that they are rolled out once - UPDATE COMPLETE is reached. - ''' - - support_status = support.SupportStatus(version='2014.1') - - def update(self, after, before=None, prev_resource=None): - raise resource.UpdateReplace(self.name) - - class WaitConditionFailure(exception.Error): def __init__(self, wait_condition, handle): reasons = handle.get_status_reason(handle.STATUS_FAILURE) @@ -293,11 +105,3 @@ class WaitConditionTimeout(exception.Error): else: message = (_('%(len)d of %(count)d received') % vals) super(WaitConditionTimeout, self).__init__(message) - - -def resource_mapping(): - return { - 'OS::Heat::WaitConditionHandle': HeatWaitConditionHandle, - 'AWS::CloudFormation::WaitConditionHandle': WaitConditionHandle, - 'OS::Heat::UpdateWaitConditionHandle': UpdateWaitConditionHandle, - } diff --git a/heat/tests/test_autoscaling_update_policy.py b/heat/tests/test_autoscaling_update_policy.py index cbbe37a3f..ccb57bff1 100644 --- a/heat/tests/test_autoscaling_update_policy.py +++ b/heat/tests/test_autoscaling_update_policy.py @@ -26,9 +26,9 @@ from heat.engine.clients.os import nova from heat.engine import function from heat.engine.notification import stack as notification from heat.engine import parser +from heat.engine.resources.aws import wait_condition_handle as aws_wch from heat.engine.resources import instance from heat.engine.resources import loadbalancer as lb -from heat.engine.resources import wait_condition as wc from heat.tests import common from heat.tests import utils from heat.tests.v1_1 import fakes as fakes_v1_1 @@ -216,8 +216,8 @@ class AutoScalingGroupTest(common.HeatTestCase): parser.Stack.validate().MultipleTimes() def _stub_lb_create(self): - self.m.StubOutWithMock(wc.WaitConditionHandle, 'get_status') - wc.WaitConditionHandle.get_status().AndReturn(['SUCCESS']) + self.m.StubOutWithMock(aws_wch.WaitConditionHandle, 'get_status') + aws_wch.WaitConditionHandle.get_status().AndReturn(['SUCCESS']) def _stub_lb_reload(self, num=1, setup=True): if setup: diff --git a/heat/tests/test_loadbalancer.py b/heat/tests/test_loadbalancer.py index a488aac91..a4cd0e2c2 100644 --- a/heat/tests/test_loadbalancer.py +++ b/heat/tests/test_loadbalancer.py @@ -24,9 +24,9 @@ from heat.common import template_format from heat.engine.clients.os import glance from heat.engine.clients.os import nova from heat.engine import resource +from heat.engine.resources.aws import wait_condition_handle as aws_wch from heat.engine.resources import instance from heat.engine.resources import loadbalancer as lb -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 @@ -144,8 +144,8 @@ class LoadBalancerTest(common.HeatTestCase): if stub_meta: resource.Resource.metadata_set(mox.IgnoreArg()).AndReturn(None) - self.m.StubOutWithMock(wc.WaitConditionHandle, 'get_status') - wc.WaitConditionHandle.get_status().AndReturn(['SUCCESS']) + self.m.StubOutWithMock(aws_wch.WaitConditionHandle, 'get_status') + aws_wch.WaitConditionHandle.get_status().AndReturn(['SUCCESS']) def test_loadbalancer(self): self._mock_get_image_id_success(u'F20-x86_64-cfntools', 746) diff --git a/heat/tests/test_metadata_refresh.py b/heat/tests/test_metadata_refresh.py index bfcb62a6e..06db2c068 100644 --- a/heat/tests/test_metadata_refresh.py +++ b/heat/tests/test_metadata_refresh.py @@ -19,9 +19,9 @@ from heat.common import identifier from heat.common import template_format from heat.engine import environment from heat.engine import parser +from heat.engine.resources.aws import wait_condition_handle as aws_wch from heat.engine.resources import instance from heat.engine.resources import server -from heat.engine.resources import wait_condition as wc from heat.engine import scheduler from heat.engine import service from heat.tests import common @@ -238,8 +238,8 @@ class WaitCondMetadataUpdateTest(common.HeatTestCase): id = identifier.ResourceIdentifier('test_tenant_id', stack.name, stack.id, '', 'WH') - self.m.StubOutWithMock(wc.WaitConditionHandle, 'identifier') - wc.WaitConditionHandle.identifier().MultipleTimes().AndReturn(id) + self.m.StubOutWithMock(aws_wch.WaitConditionHandle, 'identifier') + aws_wch.WaitConditionHandle.identifier().MultipleTimes().AndReturn(id) self.m.StubOutWithMock(scheduler.TaskRunner, '_sleep') return stack diff --git a/heat/tests/test_waitcondition.py b/heat/tests/test_waitcondition.py index c0da4fe9d..1472a1693 100644 --- a/heat/tests/test_waitcondition.py +++ b/heat/tests/test_waitcondition.py @@ -28,6 +28,8 @@ 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.aws import wait_condition_handle as aws_wch +from heat.engine.resources.openstack import wait_condition_handle as heat_wch from heat.engine.resources import wait_condition as wc from heat.engine import rsrc_defn from heat.engine import scheduler @@ -161,20 +163,21 @@ class WaitConditionTest(common.HeatTestCase): if stub: id = identifier.ResourceIdentifier('test_tenant', stack.name, stack.id, '', 'WaitHandle') - self.m.StubOutWithMock(wc.WaitConditionHandle, 'identifier') - wc.WaitConditionHandle.identifier().MultipleTimes().AndReturn(id) + self.m.StubOutWithMock(aws_wch.WaitConditionHandle, 'identifier') + aws_wch.WaitConditionHandle.identifier().\ + MultipleTimes().AndReturn(id) if stub_status: - self.m.StubOutWithMock(wc.WaitConditionHandle, + self.m.StubOutWithMock(aws_wch.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']) + aws_wch.WaitConditionHandle.get_status().AndReturn([]) + aws_wch.WaitConditionHandle.get_status().AndReturn([]) + aws_wch.WaitConditionHandle.get_status().AndReturn(['SUCCESS']) self.m.ReplayAll() @@ -191,9 +194,9 @@ class WaitConditionTest(common.HeatTestCase): 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']) + aws_wch.WaitConditionHandle.get_status().AndReturn([]) + aws_wch.WaitConditionHandle.get_status().AndReturn([]) + aws_wch.WaitConditionHandle.get_status().AndReturn(['FAILURE']) self.m.ReplayAll() @@ -211,11 +214,13 @@ class WaitConditionTest(common.HeatTestCase): 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']) + aws_wch.WaitConditionHandle.get_status().AndReturn([]) + aws_wch.WaitConditionHandle.get_status().AndReturn(['SUCCESS']) + aws_wch.WaitConditionHandle.get_status().AndReturn(['SUCCESS', + 'SUCCESS']) + aws_wch.WaitConditionHandle.get_status().AndReturn(['SUCCESS', + 'SUCCESS', + 'SUCCESS']) self.m.ReplayAll() @@ -232,9 +237,10 @@ class WaitConditionTest(common.HeatTestCase): 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']) + aws_wch.WaitConditionHandle.get_status().AndReturn([]) + aws_wch.WaitConditionHandle.get_status().AndReturn(['SUCCESS']) + aws_wch.WaitConditionHandle.get_status().AndReturn(['SUCCESS', + 'FAILURE']) self.m.ReplayAll() @@ -264,9 +270,9 @@ class WaitConditionTest(common.HeatTestCase): scheduler.wallclock().AndReturn(st) scheduler.wallclock().AndReturn(st + 0.001) scheduler.wallclock().AndReturn(st + 0.1) - wc.WaitConditionHandle.get_status().AndReturn([]) + aws_wch.WaitConditionHandle.get_status().AndReturn([]) scheduler.wallclock().AndReturn(st + 4.1) - wc.WaitConditionHandle.get_status().AndReturn([]) + aws_wch.WaitConditionHandle.get_status().AndReturn([]) scheduler.wallclock().AndReturn(st + 5.1) self.m.ReplayAll() @@ -283,7 +289,7 @@ class WaitConditionTest(common.HeatTestCase): def test_FnGetAtt(self): self.stack = self.create_stack() - wc.WaitConditionHandle.get_status().AndReturn(['SUCCESS']) + aws_wch.WaitConditionHandle.get_status().AndReturn(['SUCCESS']) self.m.ReplayAll() self.stack.create() @@ -428,13 +434,13 @@ class WaitConditionHandleTest(common.HeatTestCase): 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']) + self.m.StubOutWithMock(aws_wch.WaitConditionHandle, 'get_status') + aws_wch.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.StubOutWithMock(aws_wch.WaitConditionHandle, 'identifier') + aws_wch.WaitConditionHandle.identifier().MultipleTimes().AndReturn(id) self.m.ReplayAll() stack.create() @@ -602,12 +608,14 @@ class WaitConditionUpdateTest(common.HeatTestCase): 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']) + self.m.StubOutWithMock(aws_wch.WaitConditionHandle, 'get_status') + aws_wch.WaitConditionHandle.get_status().AndReturn([]) + aws_wch.WaitConditionHandle.get_status().AndReturn(['SUCCESS']) + aws_wch.WaitConditionHandle.get_status().AndReturn(['SUCCESS', + 'SUCCESS']) + aws_wch.WaitConditionHandle.get_status().AndReturn(['SUCCESS', + 'SUCCESS', + 'SUCCESS']) return stack @@ -796,24 +804,25 @@ class HeatWaitConditionTest(common.HeatTestCase): 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) + self.m.StubOutWithMock(heat_wch.HeatWaitConditionHandle, + 'identifier') + heat_wch.HeatWaitConditionHandle.\ + identifier().MultipleTimes().AndReturn(id) if stub_status: - self.m.StubOutWithMock(wc.HeatWaitConditionHandle, + self.m.StubOutWithMock(heat_wch.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']) + heat_wch.HeatWaitConditionHandle.get_status().AndReturn(['SUCCESS']) + heat_wch.HeatWaitConditionHandle.get_status().AndReturn(['SUCCESS', + 'SUCCESS']) + heat_wch.HeatWaitConditionHandle.get_status().AndReturn(['SUCCESS', + 'SUCCESS', + 'SUCCESS']) self.m.ReplayAll() @@ -830,12 +839,12 @@ class HeatWaitConditionTest(common.HeatTestCase): 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']) + heat_wch.HeatWaitConditionHandle.get_status().AndReturn(['SUCCESS']) + heat_wch.HeatWaitConditionHandle.get_status().AndReturn(['SUCCESS', + 'SUCCESS']) + heat_wch.HeatWaitConditionHandle.get_status().AndReturn(['SUCCESS', + 'SUCCESS', + 'FAILURE']) self.m.ReplayAll() @@ -866,9 +875,9 @@ class HeatWaitConditionTest(common.HeatTestCase): scheduler.wallclock().AndReturn(st) scheduler.wallclock().AndReturn(st + 0.001) scheduler.wallclock().AndReturn(st + 0.1) - wc.HeatWaitConditionHandle.get_status().AndReturn([]) + heat_wch.HeatWaitConditionHandle.get_status().AndReturn([]) scheduler.wallclock().AndReturn(st + 4.1) - wc.HeatWaitConditionHandle.get_status().AndReturn([]) + heat_wch.HeatWaitConditionHandle.get_status().AndReturn([]) scheduler.wallclock().AndReturn(st + 5.1) self.m.ReplayAll() @@ -886,7 +895,7 @@ class HeatWaitConditionTest(common.HeatTestCase): def _create_heat_wc_and_handle(self): self.stack = self.create_stack( template=test_template_heat_waitcondition) - wc.HeatWaitConditionHandle.get_status().AndReturn(['SUCCESS']) + heat_wch.HeatWaitConditionHandle.get_status().AndReturn(['SUCCESS']) self.m.ReplayAll() self.stack.create()