GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — plexxi-v2.4.1 ( 80dd48 )
by
unknown
06:22
created

MistralRunnerCallbackTest.test_callback_retry_exhausted()   B

Complexity

Conditions 2

Size

Total Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
c 0
b 0
f 0
dl 0
loc 30
rs 8.8571
1
# -*- coding: UTF-8 -*-
2
# Licensed to the StackStorm, Inc ('StackStorm') under one or more
3
# contributor license agreements.  See the NOTICE file distributed with
4
# this work for additional information regarding copyright ownership.
5
# The ASF licenses this file to You under the Apache License, Version 2.0
6
# (the "License"); you may not use this file except in compliance with
7
# the License.  You may obtain a copy of the License at
8
#
9
#     http://www.apache.org/licenses/LICENSE-2.0
10
#
11
# Unless required by applicable law or agreed to in writing, software
12
# distributed under the License is distributed on an "AS IS" BASIS,
13
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
# See the License for the specific language governing permissions and
15
# limitations under the License.
16
17
import mock
18
from mock import call
19
import requests
20
21
from mistralclient.api.v2 import action_executions
22
from oslo_config import cfg
23
24
# XXX: actionsensor import depends on config being setup.
25
import st2tests.config as tests_config
26
tests_config.parse_args()
27
28
from st2common.bootstrap import actionsregistrar
29
from st2common.bootstrap import runnersregistrar
30
from st2common.constants import action as action_constants
31
from st2common.models.db.liveaction import LiveActionDB
32
from st2common.persistence.liveaction import LiveAction
33
from st2common.runners import base as runners
34
from st2common.services import action as action_service
35
from st2common.transport.liveaction import LiveActionPublisher
36
from st2common.transport.publishers import CUDPublisher
37
from st2common.util import loader
38
from st2tests import DbTestCase
39
from st2tests import fixturesloader
40
from st2tests.mocks.liveaction import MockLiveActionPublisher
41
42
43
MISTRAL_RUNNER_NAME = 'mistral_v2'
44
TEST_PACK = 'mistral_tests'
45
TEST_PACK_PATH = fixturesloader.get_fixtures_packs_base_path() + '/' + TEST_PACK
46
47
PACKS = [
48
    TEST_PACK_PATH,
49
    fixturesloader.get_fixtures_packs_base_path() + '/core'
50
]
51
52
NON_EMPTY_RESULT = 'non-empty'
53
54
55
@mock.patch.object(
56
    CUDPublisher,
57
    'publish_update',
58
    mock.MagicMock(return_value=None))
59
@mock.patch.object(
60
    CUDPublisher,
61
    'publish_create',
62
    mock.MagicMock(side_effect=MockLiveActionPublisher.publish_create))
63
@mock.patch.object(
64
    LiveActionPublisher,
65
    'publish_state',
66
    mock.MagicMock(side_effect=MockLiveActionPublisher.publish_state))
67
class MistralRunnerCallbackTest(DbTestCase):
68
69
    @classmethod
70
    def setUpClass(cls):
71
        super(MistralRunnerCallbackTest, cls).setUpClass()
72
73
        # Override the retry configuration here otherwise st2tests.config.parse_args
74
        # in DbTestCase.setUpClass will reset these overrides.
75
        cfg.CONF.set_override('retry_exp_msec', 100, group='mistral')
76
        cfg.CONF.set_override('retry_exp_max_msec', 200, group='mistral')
77
        cfg.CONF.set_override('retry_stop_max_msec', 200, group='mistral')
78
        cfg.CONF.set_override('api_url', 'http://0.0.0.0:9101', group='auth')
79
80
        # Register runners.
81
        runnersregistrar.register_runners()
82
83
        # Register test pack(s).
84
        actions_registrar = actionsregistrar.ActionsRegistrar(
85
            use_pack_cache=False,
86
            fail_on_failure=True
87
        )
88
89
        for pack in PACKS:
90
            actions_registrar.register_from_pack(pack)
91
92
        # Get an instance of the callback module and reference to mistral status map
93
        cls.callback_module = loader.register_callback_module(MISTRAL_RUNNER_NAME)
94
        cls.callback_class = cls.callback_module.get_instance()
95
        cls.status_map = cls.callback_module.STATUS_MAP
96
97
    @classmethod
98
    def get_runner_class(cls, runner_name):
99
        return runners.get_runner(runner_name).__class__
100
101
    def test_callback_handler_status_map(self):
102
        # Ensure all StackStorm status are mapped otherwise leads to zombie workflow.
103
        self.assertListEqual(sorted(self.status_map.keys()),
104
                             sorted(action_constants.LIVEACTION_STATUSES))
105
106
    @mock.patch.object(
107
        action_executions.ActionExecutionManager, 'update',
108
        mock.MagicMock(return_value=None))
109
    def test_callback_handler_with_result_as_text(self):
110
        self.callback_class.callback('http://127.0.0.1:8989/v2/action_executions/12345', {},
111
                                     action_constants.LIVEACTION_STATUS_SUCCEEDED,
112
                                     '<html></html>')
113
114
        action_executions.ActionExecutionManager.update.assert_called_with(
115
            '12345',
116
            state='SUCCESS',
117
            output='<html></html>'
118
        )
119
120
    @mock.patch.object(
121
        action_executions.ActionExecutionManager, 'update',
122
        mock.MagicMock(return_value=None))
123
    def test_callback_handler_with_result_as_dict(self):
124
        self.callback_class.callback('http://127.0.0.1:8989/v2/action_executions/12345', {},
125
                                     action_constants.LIVEACTION_STATUS_SUCCEEDED, {'a': 1})
126
127
        action_executions.ActionExecutionManager.update.assert_called_with(
128
            '12345',
129
            state='SUCCESS',
130
            output='{"a": 1}'
131
        )
132
133
    @mock.patch.object(
134
        action_executions.ActionExecutionManager, 'update',
135
        mock.MagicMock(return_value=None))
136
    def test_callback_handler_with_result_as_json_str(self):
137
        self.callback_class.callback('http://127.0.0.1:8989/v2/action_executions/12345', {},
138
                                     action_constants.LIVEACTION_STATUS_SUCCEEDED, '{"a": 1}')
139
140
        action_executions.ActionExecutionManager.update.assert_called_with(
141
            '12345',
142
            state='SUCCESS',
143
            output='{"a": 1}'
144
        )
145
146
        self.callback_class.callback('http://127.0.0.1:8989/v2/action_executions/12345', {},
147
                                     action_constants.LIVEACTION_STATUS_SUCCEEDED, "{'a': 1}")
148
149
        action_executions.ActionExecutionManager.update.assert_called_with(
150
            '12345',
151
            state='SUCCESS',
152
            output='{"a": 1}'
153
        )
154
155
        self.callback_class.callback('http://127.0.0.1:8989/v2/action_executions/12345', {},
156
                                     action_constants.LIVEACTION_STATUS_SUCCEEDED, u"{'a': 1}")
157
158
        action_executions.ActionExecutionManager.update.assert_called_with(
159
            '12345',
160
            state='SUCCESS',
161
            output='{"a": 1}'
162
        )
163
164
        self.callback_class.callback('http://127.0.0.1:8989/v2/action_executions/12345', {},
165
                                     action_constants.LIVEACTION_STATUS_SUCCEEDED, "{u'a': u'xyz'}")
166
167
        action_executions.ActionExecutionManager.update.assert_called_with(
168
            '12345',
169
            state='SUCCESS',
170
            output='{"a": "xyz"}'
171
        )
172
173
    @mock.patch.object(
174
        action_executions.ActionExecutionManager, 'update',
175
        mock.MagicMock(return_value=None))
176
    def test_callback_handler_with_result_as_list(self):
177
        self.callback_class.callback('http://127.0.0.1:8989/v2/action_executions/12345', {},
178
                                     action_constants.LIVEACTION_STATUS_SUCCEEDED,
179
                                     ["a", "b", "c"])
180
181
        action_executions.ActionExecutionManager.update.assert_called_with(
182
            '12345',
183
            state='SUCCESS',
184
            output='["a", "b", "c"]'
185
        )
186
187
    @mock.patch.object(
188
        action_executions.ActionExecutionManager, 'update',
189
        mock.MagicMock(return_value=None))
190
    def test_callback_handler_with_result_as_list_str(self):
191
        self.callback_class.callback('http://127.0.0.1:8989/v2/action_executions/12345', {},
192
                                     action_constants.LIVEACTION_STATUS_SUCCEEDED,
193
                                     '["a", "b", "c"]')
194
195
        action_executions.ActionExecutionManager.update.assert_called_with(
196
            '12345',
197
            state='SUCCESS',
198
            output='["a", "b", "c"]'
199
        )
200
201
        self.callback_class.callback('http://127.0.0.1:8989/v2/action_executions/12345', {},
202
                                     action_constants.LIVEACTION_STATUS_SUCCEEDED,
203
                                     u'["a", "b", "c"]')
204
205
        action_executions.ActionExecutionManager.update.assert_called_with(
206
            '12345',
207
            state='SUCCESS',
208
            output='["a", "b", "c"]'
209
        )
210
211
        self.callback_class.callback('http://127.0.0.1:8989/v2/action_executions/12345', {},
212
                                     action_constants.LIVEACTION_STATUS_SUCCEEDED,
213
                                     '[u"a", "b", "c"]')
214
215
        action_executions.ActionExecutionManager.update.assert_called_with(
216
            '12345',
217
            state='SUCCESS',
218
            output='["a", "b", "c"]'
219
        )
220
221
    @mock.patch.object(
222
        action_executions.ActionExecutionManager, 'update',
223
        mock.MagicMock(return_value=None))
224
    def test_callback_handler_with_result_unicode_str(self):
225
        self.callback_class.callback('http://127.0.0.1:8989/v2/action_executions/12345', {},
226
                                     action_constants.LIVEACTION_STATUS_SUCCEEDED, '什麼')
227
228
        action_executions.ActionExecutionManager.update.assert_called_with(
229
            '12345',
230
            state='SUCCESS',
231
            output='\\u4ec0\\u9ebc'
232
        )
233
234
    @mock.patch.object(
235
        action_executions.ActionExecutionManager, 'update',
236
        mock.MagicMock(return_value=None))
237
    def test_callback_handler_with_result_unicode_encoded_as_ascii_str(self):
238
        self.callback_class.callback('http://127.0.0.1:8989/v2/action_executions/12345', {},
239
                                     action_constants.LIVEACTION_STATUS_SUCCEEDED, '\u4ec0\u9ebc')
240
241
        action_executions.ActionExecutionManager.update.assert_called_with(
242
            '12345',
243
            state='SUCCESS',
244
            output='\\\\u4ec0\\\\u9ebc'
245
        )
246
247
    @mock.patch.object(
248
        action_executions.ActionExecutionManager, 'update',
249
        mock.MagicMock(return_value=None))
250
    def test_callback_handler_with_result_unicode_encoded_as_type(self):
251
        self.callback_class.callback('http://127.0.0.1:8989/v2/action_executions/12345', {},
252
                                     action_constants.LIVEACTION_STATUS_SUCCEEDED, u'\u4ec0\u9ebc')
253
254
        action_executions.ActionExecutionManager.update.assert_called_with(
255
            '12345',
256
            state='SUCCESS',
257
            output='\\u4ec0\\u9ebc'
258
        )
259
260
    @mock.patch.object(
261
        action_executions.ActionExecutionManager, 'update',
262
        mock.MagicMock(return_value=None))
263
    def test_callback_handler_with_result_as_list_with_unicode_str(self):
264
        self.callback_class.callback('http://127.0.0.1:8989/v2/action_executions/12345', {},
265
                                     action_constants.LIVEACTION_STATUS_SUCCEEDED,
266
                                     ['\u4ec0\u9ebc'])
267
268
        action_executions.ActionExecutionManager.update.assert_called_with(
269
            '12345',
270
            state='SUCCESS',
271
            output='["\\\\u4ec0\\\\u9ebc"]'
272
        )
273
274
    @mock.patch.object(
275
        action_executions.ActionExecutionManager, 'update',
276
        mock.MagicMock(return_value=None))
277
    def test_callback_handler_with_result_as_list_with_unicode_type(self):
278
        self.callback_class.callback('http://127.0.0.1:8989/v2/action_executions/12345', {},
279
                                     action_constants.LIVEACTION_STATUS_SUCCEEDED,
280
                                     [u'\u4ec0\u9ebc'])
281
282
        action_executions.ActionExecutionManager.update.assert_called_with(
283
            '12345',
284
            state='SUCCESS',
285
            output='["\\\\u4ec0\\\\u9ebc"]'
286
        )
287
288
    @mock.patch.object(
289
        action_executions.ActionExecutionManager, 'update',
290
        mock.MagicMock(return_value=None))
291
    def test_callback_handler_with_result_as_dict_with_unicode_str(self):
292
        self.callback_class.callback('http://127.0.0.1:8989/v2/action_executions/12345', {},
293
                                     action_constants.LIVEACTION_STATUS_SUCCEEDED,
294
                                     {'a': '\u4ec0\u9ebc'})
295
296
        action_executions.ActionExecutionManager.update.assert_called_with(
297
            '12345',
298
            state='SUCCESS',
299
            output='{"a": "\\\\u4ec0\\\\u9ebc"}'
300
        )
301
302
    @mock.patch.object(
303
        action_executions.ActionExecutionManager, 'update',
304
        mock.MagicMock(return_value=None))
305
    def test_callback_handler_with_result_as_dict_with_unicode_type(self):
306
        self.callback_class.callback('http://127.0.0.1:8989/v2/action_executions/12345', {},
307
                                     action_constants.LIVEACTION_STATUS_SUCCEEDED,
308
                                     {'a': u'\u4ec0\u9ebc'})
309
310
        action_executions.ActionExecutionManager.update.assert_called_with(
311
            '12345',
312
            state='SUCCESS',
313
            output='{"a": "\\\\u4ec0\\\\u9ebc"}'
314
        )
315
316
    @mock.patch.object(
317
        action_executions.ActionExecutionManager, 'update',
318
        mock.MagicMock(return_value=None))
319
    def test_callback_success_state(self):
320
        local_runner_cls = self.get_runner_class('local_runner')
321
        local_run_result = (action_constants.LIVEACTION_STATUS_SUCCEEDED, NON_EMPTY_RESULT, None)
322
        local_runner_cls.run = mock.Mock(return_value=local_run_result)
323
        expected_mistral_status = self.status_map[local_run_result[0]]
324
325
        liveaction = LiveActionDB(
326
            action='core.local', parameters={'cmd': 'uname -a'},
327
            callback={
328
                'source': MISTRAL_RUNNER_NAME,
329
                'url': 'http://127.0.0.1:8989/v2/action_executions/12345'
330
            }
331
        )
332
333
        liveaction, execution = action_service.request(liveaction)
334
        liveaction = LiveAction.get_by_id(str(liveaction.id))
335
336
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
337
338
        action_executions.ActionExecutionManager.update.assert_called_with(
339
            '12345', state=expected_mistral_status, output=NON_EMPTY_RESULT)
340
341
    @mock.patch.object(
342
        action_executions.ActionExecutionManager, 'update',
343
        mock.MagicMock(return_value=None))
344
    def test_callback_incomplete_state(self):
345
        local_runner_cls = self.get_runner_class('local_runner')
346
        local_run_result = (action_constants.LIVEACTION_STATUS_RUNNING, NON_EMPTY_RESULT, None)
347
        local_runner_cls.run = mock.Mock(return_value=local_run_result)
348
349
        liveaction = LiveActionDB(
350
            action='core.local', parameters={'cmd': 'uname -a'},
351
            callback={
352
                'source': MISTRAL_RUNNER_NAME,
353
                'url': 'http://127.0.0.1:8989/v2/action_executions/12345'
354
            }
355
        )
356
357
        liveaction, execution = action_service.request(liveaction)
358
        liveaction = LiveAction.get_by_id(str(liveaction.id))
359
360
        self.assertEqual(liveaction.status, local_run_result[0])
361
        self.assertFalse(action_executions.ActionExecutionManager.update.called)
362
363
    @mock.patch.object(
364
        action_executions.ActionExecutionManager, 'update',
365
        mock.MagicMock(return_value=None))
366
    def test_callback_canceling_state(self):
367
        local_runner_cls = self.get_runner_class('local_runner')
368
        local_run_result = (action_constants.LIVEACTION_STATUS_CANCELING, NON_EMPTY_RESULT, None)
369
        local_runner_cls.run = mock.Mock(return_value=local_run_result)
370
        local_cancel_result = (action_constants.LIVEACTION_STATUS_CANCELING, NON_EMPTY_RESULT, None)
371
        local_runner_cls.cancel = mock.Mock(return_value=local_cancel_result)
372
373
        liveaction = LiveActionDB(
374
            action='core.local', parameters={'cmd': 'uname -a'},
375
            callback={
376
                'source': MISTRAL_RUNNER_NAME,
377
                'url': 'http://127.0.0.1:8989/v2/action_executions/12345'
378
            }
379
        )
380
381
        liveaction, execution = action_service.request(liveaction)
382
        liveaction = LiveAction.get_by_id(str(liveaction.id))
383
384
        self.assertEqual(liveaction.status, local_cancel_result[0])
385
386
        action_executions.ActionExecutionManager.update.assert_not_called()
387
388
    @mock.patch.object(
389
        action_executions.ActionExecutionManager, 'update',
390
        mock.MagicMock(return_value=None))
391
    def test_callback_canceled_state(self):
392
        local_runner_cls = self.get_runner_class('local_runner')
393
        local_run_result = (action_constants.LIVEACTION_STATUS_CANCELED, NON_EMPTY_RESULT, None)
394
        local_runner_cls.run = mock.Mock(return_value=local_run_result)
395
        expected_mistral_status = self.status_map[local_run_result[0]]
396
397
        liveaction = LiveActionDB(
398
            action='core.local', parameters={'cmd': 'uname -a'},
399
            callback={
400
                'source': MISTRAL_RUNNER_NAME,
401
                'url': 'http://127.0.0.1:8989/v2/action_executions/12345'
402
            }
403
        )
404
405
        liveaction, execution = action_service.request(liveaction)
406
        liveaction = LiveAction.get_by_id(str(liveaction.id))
407
408
        self.assertEqual(liveaction.status, local_run_result[0])
409
410
        action_executions.ActionExecutionManager.update.assert_called_with(
411
            '12345', state=expected_mistral_status, output=NON_EMPTY_RESULT)
412
413
    @mock.patch.object(
414
        action_executions.ActionExecutionManager, 'update',
415
        mock.MagicMock(return_value=None))
416
    def test_callback_pausing_state(self):
417
        local_runner_cls = self.get_runner_class('local_runner')
418
        local_run_result = (action_constants.LIVEACTION_STATUS_PAUSING, NON_EMPTY_RESULT, None)
419
        local_runner_cls.run = mock.Mock(return_value=local_run_result)
420
        local_pause_result = (action_constants.LIVEACTION_STATUS_PAUSING, NON_EMPTY_RESULT, None)
421
        local_runner_cls.pause = mock.Mock(return_value=local_pause_result)
422
423
        liveaction = LiveActionDB(
424
            action='core.local', parameters={'cmd': 'uname -a'},
425
            callback={
426
                'source': MISTRAL_RUNNER_NAME,
427
                'url': 'http://127.0.0.1:8989/v2/action_executions/12345'
428
            }
429
        )
430
431
        liveaction, execution = action_service.request(liveaction)
432
        liveaction = LiveAction.get_by_id(str(liveaction.id))
433
434
        self.assertEqual(liveaction.status, local_pause_result[0])
435
436
        action_executions.ActionExecutionManager.update.assert_not_called()
437
438
    @mock.patch.object(
439
        action_executions.ActionExecutionManager, 'update',
440
        mock.MagicMock(return_value=None))
441
    def test_callback_paused_state(self):
442
        local_runner_cls = self.get_runner_class('local_runner')
443
        local_run_result = (action_constants.LIVEACTION_STATUS_PAUSED, NON_EMPTY_RESULT, None)
444
        local_runner_cls.run = mock.Mock(return_value=local_run_result)
445
        expected_mistral_status = self.status_map[local_run_result[0]]
446
447
        liveaction = LiveActionDB(
448
            action='core.local', parameters={'cmd': 'uname -a'},
449
            callback={
450
                'source': MISTRAL_RUNNER_NAME,
451
                'url': 'http://127.0.0.1:8989/v2/action_executions/12345'
452
            }
453
        )
454
455
        liveaction, execution = action_service.request(liveaction)
456
        liveaction = LiveAction.get_by_id(str(liveaction.id))
457
458
        self.assertEqual(liveaction.status, local_run_result[0])
459
460
        action_executions.ActionExecutionManager.update.assert_called_with(
461
            '12345', state=expected_mistral_status, output=NON_EMPTY_RESULT)
462
463
    @mock.patch.object(
464
        action_executions.ActionExecutionManager, 'update',
465
        mock.MagicMock(return_value=None))
466
    def test_callback_resuming_state(self):
467
        local_runner_cls = self.get_runner_class('local_runner')
468
        local_run_result = (action_constants.LIVEACTION_STATUS_RESUMING, NON_EMPTY_RESULT, None)
469
        local_runner_cls.run = mock.Mock(return_value=local_run_result)
470
        local_resume_result = (action_constants.LIVEACTION_STATUS_RUNNING, NON_EMPTY_RESULT, None)
471
        local_runner_cls.resume = mock.Mock(return_value=local_resume_result)
472
473
        liveaction = LiveActionDB(
474
            action='core.local', parameters={'cmd': 'uname -a'},
475
            callback={
476
                'source': MISTRAL_RUNNER_NAME,
477
                'url': 'http://127.0.0.1:8989/v2/action_executions/12345'
478
            }
479
        )
480
481
        liveaction, execution = action_service.request(liveaction)
482
        liveaction = LiveAction.get_by_id(str(liveaction.id))
483
484
        self.assertEqual(liveaction.status, local_resume_result[0])
485
        self.assertFalse(action_executions.ActionExecutionManager.update.called)
486
487
    @mock.patch.object(
488
        action_executions.ActionExecutionManager, 'update',
489
        mock.MagicMock(side_effect=[
490
            requests.exceptions.ConnectionError(),
491
            None]))
492
    def test_callback_retry(self):
493
        local_runner_cls = self.get_runner_class('local_runner')
494
        local_run_result = (action_constants.LIVEACTION_STATUS_SUCCEEDED, NON_EMPTY_RESULT, None)
495
        local_runner_cls.run = mock.Mock(return_value=local_run_result)
496
497
        liveaction = LiveActionDB(
498
            action='core.local', parameters={'cmd': 'uname -a'},
499
            callback={
500
                'source': MISTRAL_RUNNER_NAME,
501
                'url': 'http://127.0.0.1:8989/v2/action_executions/12345'
502
            }
503
        )
504
505
        liveaction, execution = action_service.request(liveaction)
506
        liveaction = LiveAction.get_by_id(str(liveaction.id))
507
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
508
509
        calls = [call('12345', state='SUCCESS', output=NON_EMPTY_RESULT) for i in range(0, 2)]
510
        action_executions.ActionExecutionManager.update.assert_has_calls(calls)
511
512
    @mock.patch.object(
513
        action_executions.ActionExecutionManager, 'update',
514
        mock.MagicMock(side_effect=[
515
            requests.exceptions.ConnectionError(),
516
            requests.exceptions.ConnectionError(),
517
            requests.exceptions.ConnectionError(),
518
            requests.exceptions.ConnectionError(),
519
            None]))
520
    def test_callback_retry_exhausted(self):
521
        local_runner_cls = self.get_runner_class('local_runner')
522
        local_run_result = (action_constants.LIVEACTION_STATUS_SUCCEEDED, NON_EMPTY_RESULT, None)
523
        local_runner_cls.run = mock.Mock(return_value=local_run_result)
524
525
        liveaction = LiveActionDB(
526
            action='core.local', parameters={'cmd': 'uname -a'},
527
            callback={
528
                'source': MISTRAL_RUNNER_NAME,
529
                'url': 'http://127.0.0.1:8989/v2/action_executions/12345'
530
            }
531
        )
532
533
        liveaction, execution = action_service.request(liveaction)
534
        liveaction = LiveAction.get_by_id(str(liveaction.id))
535
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
536
537
        # This test initially setup mock for action_executions.ActionExecutionManager.update
538
        # to fail the first 4 times and return success on the 5th times. The max attempts
539
        # is set to 3. We expect only 3 calls to pass thru the update method.
540
        calls = [call('12345', state='SUCCESS', output=NON_EMPTY_RESULT) for i in range(0, 2)]
541
        action_executions.ActionExecutionManager.update.assert_has_calls(calls)
542