deb-heat/heat_integrationtests/functional/test_aws_stack.py
Angus Salkeld bbb18e76f3 Use helper functions stack_suspend and stack_resume
These wait for the stack state to get to complete,
this wasn't done consistently. In test_autoscaling we were
only waiting for the resource state to get to SUSPEND_COMPLETE
and this lead to a time sensitive bug.

Change-Id: Id985d833dc0b4cab1e3cb9d8f67d5d8cc94b5863
Closes-bug: #1438717
2015-04-10 15:44:07 +10:00

208 lines
7.7 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 hashlib
import json
import random
import urlparse
from oslo_log import log as logging
from swiftclient import utils as swiftclient_utils
import yaml
from heat_integrationtests.common import test
LOG = logging.getLogger(__name__)
class AwsStackTest(test.HeatIntegrationTest):
test_template = '''
HeatTemplateFormatVersion: '2012-12-12'
Resources:
the_nested:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: the.yaml
Parameters:
KeyName: foo
Outputs:
output_foo:
Value: {"Fn::GetAtt": [the_nested, Outputs.Foo]}
'''
nested_template = '''
HeatTemplateFormatVersion: '2012-12-12'
Parameters:
KeyName:
Type: String
Outputs:
Foo:
Value: bar
'''
update_template = '''
HeatTemplateFormatVersion: '2012-12-12'
Parameters:
KeyName:
Type: String
Outputs:
Foo:
Value: foo
'''
nested_with_res_template = '''
HeatTemplateFormatVersion: '2012-12-12'
Parameters:
KeyName:
Type: String
Resources:
NestedResource:
Type: OS::Heat::RandomString
Outputs:
Foo:
Value: {"Fn::GetAtt": [NestedResource, value]}
'''
def setUp(self):
super(AwsStackTest, self).setUp()
self.client = self.orchestration_client
self.object_container_name = AwsStackTest.__name__
self.project_id = self.identity_client.auth_ref.project_id
self.object_client.put_container(self.object_container_name)
self.nested_name = '%s.yaml' % test.rand_name()
def publish_template(self, name, contents):
oc = self.object_client
# post the object
oc.put_object(self.object_container_name, name, contents)
# TODO(asalkeld) see if this is causing problems.
# self.addCleanup(self.object_client.delete_object,
# self.object_container_name, name)
# make the tempurl
key_header = 'x-account-meta-temp-url-key'
if key_header not in oc.head_account():
swift_key = hashlib.sha224(
str(random.getrandbits(256))).hexdigest()[:32]
LOG.warn('setting swift key to %s' % swift_key)
oc.post_account({key_header: swift_key})
key = oc.head_account()[key_header]
path = '/v1/AUTH_%s/%s/%s' % (self.project_id,
self.object_container_name, name)
timeout = self.conf.build_timeout * 10
tempurl = swiftclient_utils.generate_temp_url(path, timeout,
key, 'GET')
sw_url = urlparse.urlparse(oc.url)
return '%s://%s%s' % (sw_url.scheme, sw_url.netloc, tempurl)
def test_nested_stack_create(self):
url = self.publish_template(self.nested_name, self.nested_template)
self.template = self.test_template.replace('the.yaml', url)
stack_identifier = self.stack_create(template=self.template)
stack = self.client.stacks.get(stack_identifier)
self.assert_resource_is_a_stack(stack_identifier, 'the_nested')
self.assertEqual('bar', self._stack_output(stack, 'output_foo'))
def test_nested_stack_create_with_timeout(self):
url = self.publish_template(self.nested_name, self.nested_template)
self.template = self.test_template.replace('the.yaml', url)
timeout_template = yaml.load(self.template)
props = timeout_template['Resources']['the_nested']['Properties']
props['TimeoutInMinutes'] = '50'
stack_identifier = self.stack_create(
template=timeout_template)
stack = self.client.stacks.get(stack_identifier)
self.assert_resource_is_a_stack(stack_identifier, 'the_nested')
self.assertEqual('bar', self._stack_output(stack, 'output_foo'))
def test_nested_stack_adopt_ok(self):
url = self.publish_template(self.nested_name,
self.nested_with_res_template)
self.template = self.test_template.replace('the.yaml', url)
adopt_data = {
"resources": {
"the_nested": {
"resource_id": "test-res-id",
"resources": {
"NestedResource": {
"type": "OS::Heat::RandomString",
"resource_id": "test-nested-res-id",
"resource_data": {"value": "goopie"}
}
}
}
},
"environment": {"parameters": {}},
"template": yaml.load(self.template)
}
stack_identifier = self.stack_adopt(adopt_data=json.dumps(adopt_data))
self.assert_resource_is_a_stack(stack_identifier, 'the_nested')
stack = self.client.stacks.get(stack_identifier)
self.assertEqual('goopie', self._stack_output(stack, 'output_foo'))
def test_nested_stack_adopt_fail(self):
url = self.publish_template(self.nested_name,
self.nested_with_res_template)
self.template = self.test_template.replace('the.yaml', url)
adopt_data = {
"resources": {
"the_nested": {
"resource_id": "test-res-id",
"resources": {
}
}
},
"environment": {"parameters": {}},
"template": yaml.load(self.template)
}
stack_identifier = self.stack_adopt(adopt_data=json.dumps(adopt_data),
wait_for_status='ADOPT_FAILED')
rsrc = self.client.resources.get(stack_identifier, 'the_nested')
self.assertEqual('ADOPT_FAILED', rsrc.resource_status)
def test_nested_stack_update(self):
url = self.publish_template(self.nested_name, self.nested_template)
self.template = self.test_template.replace('the.yaml', url)
stack_identifier = self.stack_create(template=self.template)
original_nested_id = self.assert_resource_is_a_stack(
stack_identifier, 'the_nested')
stack = self.client.stacks.get(stack_identifier)
self.assertEqual('bar', self._stack_output(stack, 'output_foo'))
new_template = yaml.load(self.template)
props = new_template['Resources']['the_nested']['Properties']
props['TemplateURL'] = self.publish_template(self.nested_name,
self.update_template)
self.update_stack(stack_identifier, new_template)
# Expect the physical resource name staying the same after update,
# so that the nested was actually updated instead of replaced.
new_nested_id = self.assert_resource_is_a_stack(
stack_identifier, 'the_nested')
self.assertEqual(original_nested_id, new_nested_id)
updt_stack = self.client.stacks.get(stack_identifier)
self.assertEqual('foo', self._stack_output(updt_stack, 'output_foo'))
def test_nested_stack_suspend_resume(self):
url = self.publish_template(self.nested_name, self.nested_template)
self.template = self.test_template.replace('the.yaml', url)
stack_identifier = self.stack_create(template=self.template)
self.stack_suspend(stack_identifier)
self.stack_resume(stack_identifier)