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