| # 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') |