1#
2# Licensed under the Apache License, Version 2.0 (the "License");
3# you may not use this file except in compliance with the License.
4# You may obtain a copy of the License at
5#
6#    http://www.apache.org/licenses/LICENSE-2.0
7#
8# Unless required by applicable law or agreed to in writing, software
9# distributed under the License is distributed on an "AS IS" BASIS,
10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
11# implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import collections
16
17from unittest import mock
18
19from heatclient import exc
20from heatclient.osc.v1 import stack_failures
21from heatclient.tests.unit.osc.v1 import fakes as orchestration_fakes
22
23
24class ListStackFailuresTest(orchestration_fakes.TestOrchestrationv1):
25
26    def setUp(self):
27        super(ListStackFailuresTest, self).setUp()
28        self.cmd = stack_failures.ListStackFailures(self.app, None)
29        self.cmd.heat_client = self.app.client_manager.orchestration
30        self.stack_client = self.app.client_manager.orchestration.stacks
31        self.resource_client = self.app.client_manager.orchestration.resources
32        self.software_deployments_client = \
33            self.app.client_manager.orchestration.software_deployments
34
35        self.stack = mock.MagicMock(id='123', status='FAILED',
36                                    stack_name='stack')
37        self.stack_client.get.return_value = self.stack
38        self.failed_template_resource = mock.MagicMock(
39            physical_resource_id='aaaa',
40            resource_type='My::TemplateResource',
41            resource_status='CREATE_FAILED',
42            links=[{'rel': 'nested'}],
43            resource_name='my_templateresource',
44            resource_status_reason='All gone Pete Tong',
45            logical_resource_id='my_templateresource',
46        )
47        self.failed_resource = mock.MagicMock(
48            physical_resource_id='cccc',
49            resource_type='OS::Nova::Server',
50            resource_status='CREATE_FAILED',
51            links=[],
52            resource_name='my_server',
53            resource_status_reason='All gone Pete Tong',
54            logical_resource_id='my_server',
55        )
56        self.other_failed_template_resource = mock.MagicMock(
57            physical_resource_id='dddd',
58            resource_type='My::OtherTemplateResource',
59            resource_status='CREATE_FAILED',
60            links=[{'rel': 'nested'}],
61            resource_name='my_othertemplateresource',
62            resource_status_reason='RPC timeout',
63            logical_resource_id='my_othertemplateresource',
64        )
65        self.working_resource = mock.MagicMock(
66            physical_resource_id='bbbb',
67            resource_type='OS::Nova::Server',
68            resource_status='CREATE_COMPLETE',
69            resource_name='my_server',
70        )
71        self.failed_deployment_resource = mock.MagicMock(
72            physical_resource_id='eeee',
73            resource_type='OS::Heat::SoftwareDeployment',
74            resource_status='CREATE_FAILED',
75            links=[],
76            resource_name='my_deployment',
77            resource_status_reason='Returned deploy_statuscode 1',
78            logical_resource_id='my_deployment',
79        )
80        self.failed_deployment = mock.MagicMock(
81            id='eeee',
82            output_values={
83                'deploy_statuscode': '1',
84                'deploy_stderr': 'It broke',
85                'deploy_stdout': ('1\n2\n3\n4\n5\n6\n7\n8\n9\n10'
86                                  '\n11\n12')
87            },
88        )
89        self.software_deployments_client.get.return_value = (
90            self.failed_deployment)
91
92    def test_build_failed_none(self):
93        self.stack = mock.MagicMock(id='123', status='COMPLETE',
94                                    stack_name='stack')
95        failures = self.cmd._build_failed_resources('stack')
96        expected = collections.OrderedDict()
97        self.assertEqual(expected, failures)
98
99    def test_build_failed_resources(self):
100        self.resource_client.list.side_effect = [[
101            # resource-list stack
102            self.failed_template_resource,
103            self.other_failed_template_resource,
104            self.working_resource,
105        ], [  # resource-list aaaa
106            self.failed_resource
107        ], [  # resource-list dddd
108        ]]
109        failures = self.cmd._build_failed_resources('stack')
110        expected = collections.OrderedDict()
111        expected['stack.my_templateresource.my_server'] = self.failed_resource
112        expected['stack.my_othertemplateresource'] = (
113            self.other_failed_template_resource)
114        self.assertEqual(expected, failures)
115
116    def test_build_failed_resources_not_found(self):
117        self.resource_client.list.side_effect = [[
118            # resource-list stack
119            self.failed_template_resource,
120            self.other_failed_template_resource,
121            self.working_resource,
122        ], exc.HTTPNotFound(), [  # resource-list dddd
123        ]]
124
125        failures = self.cmd._build_failed_resources('stack')
126        expected = collections.OrderedDict()
127        expected['stack.my_templateresource'] = self.failed_template_resource
128        expected['stack.my_othertemplateresource'] = (
129            self.other_failed_template_resource)
130        self.assertEqual(expected, failures)
131
132    def test_build_software_deployments(self):
133        resources = {
134            'stack.my_server': self.working_resource,
135            'stack.my_deployment': self.failed_deployment_resource
136        }
137        deployments = self.cmd._build_software_deployments(resources)
138        self.assertEqual({
139            'eeee': self.failed_deployment
140        }, deployments)
141
142    def test_build_software_deployments_not_found(self):
143        resources = {
144            'stack.my_server': self.working_resource,
145            'stack.my_deployment': self.failed_deployment_resource
146        }
147        self.software_deployments_client.get.side_effect = exc.HTTPNotFound()
148        deployments = self.cmd._build_software_deployments(resources)
149        self.assertEqual({}, deployments)
150
151    def test_build_software_deployments_no_resources(self):
152        resources = {}
153        self.software_deployments_client.get.side_effect = exc.HTTPNotFound()
154        deployments = self.cmd._build_software_deployments(resources)
155        self.assertEqual({}, deployments)
156
157    def test_list_stack_failures(self):
158        self.resource_client.list.side_effect = [[
159            # resource-list stack
160            self.failed_template_resource,
161            self.other_failed_template_resource,
162            self.working_resource,
163            self.failed_deployment_resource
164        ], [  # resource-list aaaa
165            self.failed_resource
166        ], [  # resource-list dddd
167        ]]
168
169        arglist = ['stack']
170        parsed_args = self.check_parser(self.cmd, arglist, [])
171        self.cmd.take_action(parsed_args)
172
173        self.assertEqual(
174            self.app.stdout.make_string(),
175            '''stack.my_templateresource.my_server:
176  resource_type: OS::Nova::Server
177  physical_resource_id: cccc
178  status: CREATE_FAILED
179  status_reason: |
180    All gone Pete Tong
181stack.my_othertemplateresource:
182  resource_type: My::OtherTemplateResource
183  physical_resource_id: dddd
184  status: CREATE_FAILED
185  status_reason: |
186    RPC timeout
187stack.my_deployment:
188  resource_type: OS::Heat::SoftwareDeployment
189  physical_resource_id: eeee
190  status: CREATE_FAILED
191  status_reason: |
192    Returned deploy_statuscode 1
193  deploy_stdout: |
194    ...
195    3
196    4
197    5
198    6
199    7
200    8
201    9
202    10
203    11
204    12
205    (truncated, view all with --long)
206  deploy_stderr: |
207    It broke
208''')
209
210    def test_list_stack_failures_long(self):
211        self.resource_client.list.side_effect = [[
212            # resource-list stack
213            self.failed_template_resource,
214            self.other_failed_template_resource,
215            self.working_resource,
216            self.failed_deployment_resource
217        ], [  # resource-list aaaa
218            self.failed_resource
219        ], [  # resource-list dddd
220        ]]
221
222        arglist = ['--long', 'stack']
223        parsed_args = self.check_parser(self.cmd, arglist, [])
224        self.cmd.take_action(parsed_args)
225
226        self.assertEqual(
227            self.app.stdout.make_string(),
228            '''stack.my_templateresource.my_server:
229  resource_type: OS::Nova::Server
230  physical_resource_id: cccc
231  status: CREATE_FAILED
232  status_reason: |
233    All gone Pete Tong
234stack.my_othertemplateresource:
235  resource_type: My::OtherTemplateResource
236  physical_resource_id: dddd
237  status: CREATE_FAILED
238  status_reason: |
239    RPC timeout
240stack.my_deployment:
241  resource_type: OS::Heat::SoftwareDeployment
242  physical_resource_id: eeee
243  status: CREATE_FAILED
244  status_reason: |
245    Returned deploy_statuscode 1
246  deploy_stdout: |
247    1
248    2
249    3
250    4
251    5
252    6
253    7
254    8
255    9
256    10
257    11
258    12
259  deploy_stderr: |
260    It broke
261''')
262