Zane Bitter | d52903d | 2017-07-10 13:48:01 -0400 | [diff] [blame] | 1 | # 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 | |
| 13 | # Using nested get_attr functions isn't a good idea - in particular, this |
| 14 | # actually working depends on correct dependencies between the two resources |
| 15 | # whose attributes are being fetched, and these dependencies are non-local to |
| 16 | # where the get_attr calls are used. Nevertheless, it did sort-of work, and |
| 17 | # this test will help keep it that way. |
| 18 | |
| 19 | from heat_integrationtests.functional import functional_base |
| 20 | |
| 21 | |
| 22 | initial_template = ''' |
| 23 | heat_template_version: ocata |
| 24 | resources: |
| 25 | dict_resource: |
| 26 | type: OS::Heat::Value |
| 27 | properties: |
| 28 | value: |
| 29 | blarg: wibble |
| 30 | foo: bar |
| 31 | baz: quux |
| 32 | fred: barney |
| 33 | # These dependencies are required because we only want to read the |
| 34 | # attribute values for a given resource once, and therefore we do so in |
| 35 | # dependency order. This is necessarily true for a convergence traversal, |
| 36 | # but also happens when we're fetching the resource attributes e.g. to show |
| 37 | # the output values. The key1/key2 attribute values must be stored before |
| 38 | # we attempt to calculate the dep_attrs for dict_resource in order to |
| 39 | # correctly determine which attributes of dict_resource are used. |
| 40 | depends_on: |
| 41 | - key1 |
| 42 | - key2 |
| 43 | - indirect_key3_dep |
| 44 | key1: |
| 45 | type: OS::Heat::Value |
| 46 | properties: |
| 47 | value: blarg |
| 48 | key2: |
| 49 | type: OS::Heat::Value |
| 50 | properties: |
| 51 | value: foo |
| 52 | key3: |
| 53 | type: OS::Heat::Value |
| 54 | properties: |
| 55 | value: fred |
| 56 | value1: |
| 57 | type: OS::Heat::Value |
| 58 | properties: |
| 59 | value: |
| 60 | get_attr: |
| 61 | - dict_resource |
| 62 | - value |
| 63 | - {get_attr: [key1, value]} |
| 64 | indirect_key3_dep: |
| 65 | type: OS::Heat::Value |
| 66 | properties: |
| 67 | value: ignored |
| 68 | depends_on: key3 |
| 69 | outputs: |
| 70 | value1: |
| 71 | value: {get_attr: [value1, value]} |
| 72 | value2: |
| 73 | value: {get_attr: [dict_resource, value, {get_attr: [key2, value]}]} |
| 74 | value3: |
| 75 | value: {get_attr: [dict_resource, value, {get_attr: [key3, value]}]} |
| 76 | ''' |
| 77 | |
| 78 | update_template = ''' |
| 79 | heat_template_version: ocata |
| 80 | resources: |
| 81 | dict_resource: |
| 82 | type: OS::Heat::Value |
| 83 | properties: |
| 84 | value: |
| 85 | blarg: wibble |
| 86 | foo: bar |
| 87 | baz: quux |
| 88 | fred: barney |
| 89 | depends_on: |
| 90 | - key1 |
| 91 | - key2 |
| 92 | - indirect_key3_dep |
| 93 | - key4 |
| 94 | key1: |
| 95 | type: OS::Heat::Value |
| 96 | properties: |
| 97 | value: foo |
| 98 | key2: |
| 99 | type: OS::Heat::Value |
| 100 | properties: |
| 101 | value: fred |
| 102 | key3: |
| 103 | type: OS::Heat::Value |
| 104 | properties: |
| 105 | value: blarg |
| 106 | key4: |
| 107 | type: OS::Heat::Value |
| 108 | properties: |
| 109 | value: baz |
| 110 | value1: |
| 111 | type: OS::Heat::Value |
| 112 | properties: |
| 113 | value: |
| 114 | get_attr: |
| 115 | - dict_resource |
| 116 | - value |
| 117 | - {get_attr: [key1, value]} |
| 118 | value4: |
| 119 | type: OS::Heat::Value |
| 120 | properties: |
| 121 | value: |
| 122 | get_attr: |
| 123 | - dict_resource |
| 124 | - value |
| 125 | - {get_attr: [key4, value]} |
| 126 | indirect_key3_dep: |
| 127 | type: OS::Heat::Value |
| 128 | properties: |
| 129 | value: ignored |
| 130 | depends_on: key3 |
| 131 | outputs: |
| 132 | value1: |
| 133 | value: {get_attr: [value1, value]} |
| 134 | value2: |
| 135 | value: {get_attr: [dict_resource, value, {get_attr: [key2, value]}]} |
| 136 | value3: |
| 137 | value: {get_attr: [dict_resource, value, {get_attr: [key3, value]}]} |
| 138 | value4: |
| 139 | value: {get_attr: [value4, value]} |
| 140 | ''' |
| 141 | |
| 142 | |
| 143 | class NestedGetAttrTest(functional_base.FunctionalTestsBase): |
| 144 | def assertOutput(self, value, stack_identifier, key): |
| 145 | op = self.client.stacks.output_show(stack_identifier, key)['output'] |
| 146 | self.assertEqual(key, op['output_key']) |
| 147 | if 'output_error' in op: |
| 148 | raise Exception(op['output_error']) |
| 149 | self.assertEqual(value, op['output_value']) |
| 150 | |
| 151 | def test_nested_get_attr_create(self): |
| 152 | stack_identifier = self.stack_create(template=initial_template) |
| 153 | |
| 154 | self.assertOutput('wibble', stack_identifier, 'value1') |
| 155 | self.assertOutput('bar', stack_identifier, 'value2') |
| 156 | self.assertOutput('barney', stack_identifier, 'value3') |
| 157 | |
| 158 | def test_nested_get_attr_update(self): |
| 159 | stack_identifier = self.stack_create(template=initial_template) |
| 160 | self.update_stack(stack_identifier, template=update_template) |
| 161 | |
| 162 | self.assertOutput('bar', stack_identifier, 'value1') |
| 163 | self.assertOutput('barney', stack_identifier, 'value2') |
| 164 | self.assertOutput('wibble', stack_identifier, 'value3') |
| 165 | self.assertOutput('quux', stack_identifier, 'value4') |