blob: 6c68a192c1627038d012dbb12508b5eda8f5c12e [file] [log] [blame]
Steven Hardy6f0bda82014-12-12 17:49:10 +00001# Licensed under the Apache License, Version 2.0 (the "License"); you may
2# not use this file except in compliance with the License. You may obtain
3# a copy of the License at
4#
5# http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10# License for the specific language governing permissions and limitations
11# under the License.
12
Steven Hardy6f0bda82014-12-12 17:49:10 +000013from heatclient import exc
Pavlo Shchelokovskyy60e0ecd2014-12-14 22:17:21 +020014import six
Steven Hardy6f0bda82014-12-12 17:49:10 +000015
16from heat_integrationtests.common import test
17
18
Unmesh Gurjar0a25a732014-12-23 17:28:33 +053019template = '''
20heat_template_version: 2013-05-23
21resources:
22 random_group:
23 type: OS::Heat::ResourceGroup
24 properties:
25 count: 2
26 resource_def:
27 type: OS::Heat::RandomString
28 properties:
29 length: 30
30outputs:
31 random1:
32 value: {get_attr: [random_group, resource.0.value]}
33 random2:
34 value: {get_attr: [random_group, resource.1.value]}
35 all_values:
36 value: {get_attr: [random_group, value]}
37'''
38
39
Steven Hardy6f0bda82014-12-12 17:49:10 +000040class ResourceGroupTest(test.HeatIntegrationTest):
41
42 def setUp(self):
43 super(ResourceGroupTest, self).setUp()
44 self.client = self.orchestration_client
45
46 def _group_nested_identifier(self, stack_identifier,
47 group_name='random_group'):
48 # Get the nested stack identifier from the group
49 rsrc = self.client.resources.get(stack_identifier, group_name)
50 physical_resource_id = rsrc.physical_resource_id
51
52 nested_stack = self.client.stacks.get(physical_resource_id)
53 nested_identifier = '%s/%s' % (nested_stack.stack_name,
54 nested_stack.id)
55 parent_id = stack_identifier.split("/")[-1]
56 self.assertEqual(parent_id, nested_stack.parent)
57 return nested_identifier
58
59 def test_resource_group_zero_novalidate(self):
60 # Nested resources should be validated only when size > 0
61 # This allows features to be disabled via size=0 without
62 # triggering validation of nested resource custom contraints
63 # e.g images etc in the nested schema.
64 nested_template_fail = '''
65heat_template_version: 2013-05-23
66resources:
67 random:
68 type: OS::Heat::RandomString
69 properties:
70 length: BAD
71'''
72
73 template_zero_nested = '''
74heat_template_version: 2013-05-23
75resources:
76 random_group:
77 type: OS::Heat::ResourceGroup
78 properties:
79 count: 0
80 resource_def:
81 type: My::RandomString
82'''
83
84 files = {'provider.yaml': nested_template_fail}
85 env = {'resource_registry':
86 {'My::RandomString': 'provider.yaml'}}
87 stack_identifier = self.stack_create(
88 template=template_zero_nested,
89 files=files,
90 environment=env
91 )
92
93 self.assertEqual({u'random_group': u'OS::Heat::ResourceGroup'},
94 self.list_resources(stack_identifier))
95
96 # Check we created an empty nested stack
97 nested_identifier = self._group_nested_identifier(stack_identifier)
98 self.assertEqual({}, self.list_resources(nested_identifier))
99
100 # Prove validation works for non-zero create/update
101 template_two_nested = template_zero_nested.replace("count: 0",
102 "count: 2")
103 expected_err = "length Value 'BAD' is not an integer"
104 ex = self.assertRaises(exc.HTTPBadRequest, self.update_stack,
105 stack_identifier, template_two_nested,
106 environment=env, files=files)
107 self.assertIn(expected_err, six.text_type(ex))
108
109 ex = self.assertRaises(exc.HTTPBadRequest, self.stack_create,
110 template=template_two_nested,
111 environment=env, files=files)
112 self.assertIn(expected_err, six.text_type(ex))
Unmesh Gurjar0a25a732014-12-23 17:28:33 +0530113
114 def _validate_resources(self, stack_identifier, expected_count):
115 nested_identifier = self._group_nested_identifier(stack_identifier)
116 resources = self.list_resources(nested_identifier)
117 self.assertEqual(expected_count, len(resources))
118 expected_resources = dict(
119 (str(idx), 'OS::Heat::RandomString')
120 for idx in range(expected_count))
121
122 self.assertEqual(expected_resources, resources)
123
124 def test_create(self):
125 def validate_output(stack, output_key, length):
126 output_value = self._stack_output(stack, output_key)
127 self.assertEqual(length, len(output_value))
128 return output_value
129 # verify that the resources in resource group are identically
130 # configured, resource names and outputs are appropriate.
131 stack_identifier = self.stack_create('create_stack', template=template)
132 self.assertEqual({u'random_group': u'OS::Heat::ResourceGroup'},
133 self.list_resources(stack_identifier))
134
135 # validate count, type and name of resources in a resource group.
136 self._validate_resources(stack_identifier, 2)
137
138 # validate outputs
139 stack = self.client.stacks.get(stack_identifier)
140 outputs = []
141 outputs.append(validate_output(stack, 'random1', 30))
142 outputs.append(validate_output(stack, 'random2', 30))
143 self.assertEqual(outputs, self._stack_output(stack, 'all_values'))
144
145 def test_update_increase_decrease_count(self):
146 # create stack with resource group count 2
147 stack_identifier = self.stack_create('update_stack', template=template)
148 self.assertEqual({u'random_group': u'OS::Heat::ResourceGroup'},
149 self.list_resources(stack_identifier))
150 # verify that the resource group has 2 resources
151 self._validate_resources(stack_identifier, 2)
152
153 # increase the resource group count to 5
154 update_template = template.replace("count: 2", "count: 5")
155 self.update_stack(stack_identifier, update_template)
156 # verify that the resource group has 5 resources
157 self._validate_resources(stack_identifier, 5)
158
159 # decrease the resource group count to 3
160 update_template = template.replace("count: 2", "count: 3")
161 self.update_stack(stack_identifier, update_template)
162 # verify that the resource group has 3 resources
163 self._validate_resources(stack_identifier, 3)