File: test_remote_stack.py

package info (click to toggle)
heat-tempest-plugin 2.6.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 596 kB
  • sloc: python: 4,592; makefile: 22
file content (200 lines) | stat: -rw-r--r-- 8,460 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#    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.


from heatclient import exc
from tempest.lib import decorators

from heat_tempest_plugin.common import test
from heat_tempest_plugin.tests.functional import functional_base


class RemoteStackTest(functional_base.FunctionalTestsBase):
    template = '''
heat_template_version: 2013-05-23
resources:
  my_stack:
    type: OS::Heat::Stack
    properties:
      context:
$MULTI_CLOUD_PROPERTIES
        region_name: RegionOne
      template:
        get_file: remote_stack.yaml
outputs:
  key:
    value: {get_attr: [my_stack, outputs]}
'''

    remote_template = '''
heat_template_version: 2013-05-23
resources:
  random1:
    type: OS::Heat::RandomString
outputs:
  remote_key:
    value: {get_attr: [random1, value]}
'''

    def setUp(self):
        super(RemoteStackTest, self).setUp()
        self.template = self.template.replace('$MULTI_CLOUD_PROPERTIES', '')
        # replacing the template region with the one from the config
        self.template = self.template.replace('RegionOne',
                                              self.conf.region)

    @decorators.idempotent_id('7e735c40-24fb-4ef8-8585-d1c68b344476')
    def test_remote_stack_alone(self):
        stack_id = self.stack_create(template=self.remote_template)
        expected_resources = {'random1': 'OS::Heat::RandomString'}
        self.assertEqual(expected_resources, self.list_resources(stack_id))
        stack = self.client.stacks.get(stack_id)
        output_value = self._stack_output(stack, 'remote_key')
        self.assertEqual(32, len(output_value))

    @decorators.idempotent_id('aeed20d1-ebda-4544-9ace-16b0c8fc24f6')
    def test_stack_create(self):
        files = {'remote_stack.yaml': self.remote_template}
        stack_id = self.stack_create(files=files)

        expected_resources = {'my_stack': 'OS::Heat::Stack'}
        self.assertEqual(expected_resources, self.list_resources(stack_id))

        stack = self.client.stacks.get(stack_id)
        output = self._stack_output(stack, 'key')
        parent_output_value = output['remote_key']
        self.assertEqual(32, len(parent_output_value))

        rsrc = self.client.resources.get(stack_id, 'my_stack')
        remote_id = rsrc.physical_resource_id
        rstack = self.client.stacks.get(remote_id)
        self.assertEqual(remote_id, rstack.id)
        remote_output_value = self._stack_output(rstack, 'remote_key')
        self.assertEqual(32, len(remote_output_value))
        self.assertEqual(parent_output_value, remote_output_value)

        remote_resources = {'random1': 'OS::Heat::RandomString'}
        self.assertEqual(remote_resources, self.list_resources(remote_id))

    def _create_with_cloud_credential(self):
        cred_sec_id = self.conf.credential_secret_id
        if not cred_sec_id:
            raise self.skipException(
                "No credential_secret_id configured to test")
        props = """
        credential_secret_id: %(credential_secret_id)s""" % {
            'credential_secret_id': cred_sec_id
        }

        self.template = self.template.replace('$MULTI_CLOUD_PROPERTIES', props)
        files = {'remote_stack.yaml': self.remote_template}
        stack_id = self.stack_create(files=files)

        expected_resources = {'my_stack': 'OS::Heat::Stack'}
        self.assertEqual(expected_resources, self.list_resources(stack_id))

        return stack_id

    @test.requires_feature('multi_cloud')
    @decorators.idempotent_id('6b61d8e3-79df-4e84-bdcf-f734da39d52b')
    def test_stack_create_with_cloud_credential(self):
        """Test on create multi (OpenStack) cloud with credential

        This test will use same region to simulate cross OpenStack scenario.
        Provide credential_secret_id as input property.
        """
        stack_id = self._create_with_cloud_credential()
        stack = self.client.stacks.get(stack_id)
        output = self._stack_output(stack, 'key')
        parent_output_value = output['remote_key']
        self.assertEqual(32, len(parent_output_value))

        rsrc = self.client.resources.get(stack_id, 'my_stack')
        remote_id = rsrc.physical_resource_id
        # For now we use same OpenStack environment as a simulation of remote
        # OpenStack site.
        rstack = self.client.stacks.get(remote_id)
        self.assertEqual(remote_id, rstack.id)
        remote_output_value = self._stack_output(rstack, 'remote_key')
        self.assertEqual(32, len(remote_output_value))
        self.assertEqual(parent_output_value, remote_output_value)

        remote_resources = {'random1': 'OS::Heat::RandomString'}
        self.assertEqual(remote_resources, self.list_resources(remote_id))

    @decorators.idempotent_id('830bfeae-6d8a-4cb2-823d-d8b6c3a740ad')
    def test_stack_create_bad_region(self):
        tmpl_bad_region = self.template.replace(self.conf.region, 'DARKHOLE')
        files = {'remote_stack.yaml': self.remote_template}
        kwargs = {
            'template': tmpl_bad_region,
            'files': files
        }
        ex = self.assertRaises(exc.HTTPBadRequest, self.stack_create, **kwargs)

        error_msg = ('ERROR: Cannot establish connection to Heat endpoint '
                     'at region "DARKHOLE" due to '
                     '"(?:public|internal|admin)(?:URL)? endpoint for '
                     'orchestration service in DARKHOLE region not found"')
        self.assertRegex(str(ex), error_msg)

    @decorators.idempotent_id('b2190dfc-d223-4595-b168-6c42b0f3a3e5')
    def test_stack_resource_validation_fail(self):
        tmpl_bad_format = self.remote_template.replace('resources', 'resource')
        files = {'remote_stack.yaml': tmpl_bad_format}
        kwargs = {'files': files}
        ex = self.assertRaises(exc.HTTPBadRequest, self.stack_create, **kwargs)

        error_msg = ('ERROR: Failed validating stack template using Heat '
                     'endpoint at region "%s" due to '
                     '"ERROR: The template section is '
                     'invalid: resource"') % self.conf.region
        self.assertEqual(error_msg, str(ex))

    @decorators.idempotent_id('141f0478-121b-4e61-bde7-d5551bfd1fc2')
    def test_stack_update(self):
        files = {'remote_stack.yaml': self.remote_template}
        stack_id = self.stack_create(files=files)

        expected_resources = {'my_stack': 'OS::Heat::Stack'}
        self.assertEqual(expected_resources, self.list_resources(stack_id))

        rsrc = self.client.resources.get(stack_id, 'my_stack')
        physical_resource_id = rsrc.physical_resource_id
        rstack = self.client.stacks.get(physical_resource_id)
        self.assertEqual(physical_resource_id, rstack.id)

        remote_resources = {'random1': 'OS::Heat::RandomString'}
        self.assertEqual(remote_resources,
                         self.list_resources(rstack.id))
        # do an update
        update_template = self.remote_template.replace('random1', 'random2')
        files = {'remote_stack.yaml': update_template}
        self.update_stack(stack_id, self.template, files=files)

        # check if the remote stack is still there with the same ID
        self.assertEqual(expected_resources, self.list_resources(stack_id))
        rsrc = self.client.resources.get(stack_id, 'my_stack')
        physical_resource_id = rsrc.physical_resource_id
        rstack = self.client.stacks.get(physical_resource_id)
        self.assertEqual(physical_resource_id, rstack.id)

        remote_resources = {'random2': 'OS::Heat::RandomString'}
        self.assertEqual(remote_resources,
                         self.list_resources(rstack.id))

    @decorators.idempotent_id('50841af8-bdf5-4df6-a075-dc061ada6833')
    def test_stack_suspend_resume(self):
        files = {'remote_stack.yaml': self.remote_template}
        stack_id = self.stack_create(files=files)
        self.stack_suspend(stack_id)
        self.stack_resume(stack_id)