diff --git a/functional/test_nested_get_attr.py b/functional/test_nested_get_attr.py new file mode 100644 index 0000000..fff89a4 --- /dev/null +++ b/functional/test_nested_get_attr.py @@ -0,0 +1,165 @@ +# 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. + +# Using nested get_attr functions isn't a good idea - in particular, this +# actually working depends on correct dependencies between the two resources +# whose attributes are being fetched, and these dependencies are non-local to +# where the get_attr calls are used. Nevertheless, it did sort-of work, and +# this test will help keep it that way. + +from heat_integrationtests.functional import functional_base + + +initial_template = ''' +heat_template_version: ocata +resources: + dict_resource: + type: OS::Heat::Value + properties: + value: + blarg: wibble + foo: bar + baz: quux + fred: barney + # These dependencies are required because we only want to read the + # attribute values for a given resource once, and therefore we do so in + # dependency order. This is necessarily true for a convergence traversal, + # but also happens when we're fetching the resource attributes e.g. to show + # the output values. The key1/key2 attribute values must be stored before + # we attempt to calculate the dep_attrs for dict_resource in order to + # correctly determine which attributes of dict_resource are used. + depends_on: + - key1 + - key2 + - indirect_key3_dep + key1: + type: OS::Heat::Value + properties: + value: blarg + key2: + type: OS::Heat::Value + properties: + value: foo + key3: + type: OS::Heat::Value + properties: + value: fred + value1: + type: OS::Heat::Value + properties: + value: + get_attr: + - dict_resource + - value + - {get_attr: [key1, value]} + indirect_key3_dep: + type: OS::Heat::Value + properties: + value: ignored + depends_on: key3 +outputs: + value1: + value: {get_attr: [value1, value]} + value2: + value: {get_attr: [dict_resource, value, {get_attr: [key2, value]}]} + value3: + value: {get_attr: [dict_resource, value, {get_attr: [key3, value]}]} +''' + +update_template = ''' +heat_template_version: ocata +resources: + dict_resource: + type: OS::Heat::Value + properties: + value: + blarg: wibble + foo: bar + baz: quux + fred: barney + depends_on: + - key1 + - key2 + - indirect_key3_dep + - key4 + key1: + type: OS::Heat::Value + properties: + value: foo + key2: + type: OS::Heat::Value + properties: + value: fred + key3: + type: OS::Heat::Value + properties: + value: blarg + key4: + type: OS::Heat::Value + properties: + value: baz + value1: + type: OS::Heat::Value + properties: + value: + get_attr: + - dict_resource + - value + - {get_attr: [key1, value]} + value4: + type: OS::Heat::Value + properties: + value: + get_attr: + - dict_resource + - value + - {get_attr: [key4, value]} + indirect_key3_dep: + type: OS::Heat::Value + properties: + value: ignored + depends_on: key3 +outputs: + value1: + value: {get_attr: [value1, value]} + value2: + value: {get_attr: [dict_resource, value, {get_attr: [key2, value]}]} + value3: + value: {get_attr: [dict_resource, value, {get_attr: [key3, value]}]} + value4: + value: {get_attr: [value4, value]} +''' + + +class NestedGetAttrTest(functional_base.FunctionalTestsBase): + def assertOutput(self, value, stack_identifier, key): + op = self.client.stacks.output_show(stack_identifier, key)['output'] + self.assertEqual(key, op['output_key']) + if 'output_error' in op: + raise Exception(op['output_error']) + self.assertEqual(value, op['output_value']) + + def test_nested_get_attr_create(self): + stack_identifier = self.stack_create(template=initial_template) + + self.assertOutput('wibble', stack_identifier, 'value1') + self.assertOutput('bar', stack_identifier, 'value2') + self.assertOutput('barney', stack_identifier, 'value3') + + def test_nested_get_attr_update(self): + stack_identifier = self.stack_create(template=initial_template) + self.update_stack(stack_identifier, template=update_template) + + self.assertOutput('bar', stack_identifier, 'value1') + self.assertOutput('barney', stack_identifier, 'value2') + self.assertOutput('wibble', stack_identifier, 'value3') + self.assertOutput('quux', stack_identifier, 'value4')