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.1.1 ( 2317c4...ed2af2 )
by
unknown
05:10
created

MistralRunnerTest.test_callback_handler_with_result_as_dict()   A

Complexity

Conditions 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
c 2
b 0
f 0
dl 0
loc 6
rs 9.4285
1
# Licensed to the StackStorm, Inc ('StackStorm') under one or more
2
# contributor license agreements.  See the NOTICE file distributed with
3
# this work for additional information regarding copyright ownership.
4
# The ASF licenses this file to You under the Apache License, Version 2.0
5
# (the "License"); you may not use this file except in compliance with
6
# the License.  You may obtain a copy of the License at
7
#
8
#     http://www.apache.org/licenses/LICENSE-2.0
9
#
10
# Unless required by applicable law or agreed to in writing, software
11
# distributed under the License is distributed on an "AS IS" BASIS,
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
# See the License for the specific language governing permissions and
14
# limitations under the License.
15
16
import copy
17
import uuid
18
19
import mock
20
import requests
21
import yaml
22
23
from mistralclient.api.base import APIException
24
from mistralclient.api.v2 import executions
25
from mistralclient.api.v2 import workbooks
26
from mistralclient.api.v2 import workflows
27
from oslo_config import cfg
28
29
# XXX: actionsensor import depends on config being setup.
30
import st2tests.config as tests_config
31
tests_config.parse_args()
32
33
from mistral_v2 import MistralRunner
34
from st2common.bootstrap import actionsregistrar
35
from st2common.bootstrap import runnersregistrar
36
from st2common.constants import action as action_constants
37
from st2common.models.api.notification import NotificationsHelper
38
from st2common.models.db.liveaction import LiveActionDB
39
from st2common.persistence.liveaction import LiveAction
40
from st2common.runners import base as runners
41
from st2common.services import action as action_service
42
from st2common.transport.liveaction import LiveActionPublisher
43
from st2common.transport.publishers import CUDPublisher
44
from st2common.util import loader
45
from st2tests import DbTestCase
46
from st2tests import fixturesloader
47
from st2tests.mocks.liveaction import MockLiveActionPublisher
48
49
50
TEST_FIXTURES = {
51
    'workflows': [
52
        'workbook_v2.yaml',
53
        'workbook_v2_many_workflows.yaml',
54
        'workbook_v2_many_workflows_no_default.yaml',
55
        'workflow_v2.yaml',
56
        'workflow_v2_many_workflows.yaml'
57
    ],
58
    'actions': [
59
        'workbook_v2.yaml',
60
        'workbook_v2_many_workflows.yaml',
61
        'workbook_v2_many_workflows_no_default.yaml',
62
        'workflow_v2.yaml',
63
        'workflow_v2_many_workflows.yaml',
64
        'workbook_v2_name_mismatch.yaml',
65
        'workflow_v2_name_mismatch.yaml'
66
    ]
67
}
68
69
TEST_PACK = 'mistral_tests'
70
TEST_PACK_PATH = fixturesloader.get_fixtures_packs_base_path() + '/' + TEST_PACK
71
72
PACKS = [
73
    TEST_PACK_PATH,
74
    fixturesloader.get_fixtures_packs_base_path() + '/core'
75
]
76
77
# Action executions requirements
78
MISTRAL_EXECUTION = {'id': str(uuid.uuid4()), 'state': 'RUNNING', 'workflow_name': None}
79
ACTION_PARAMS = {'friend': 'Rocky'}
80
NON_EMPTY_RESULT = 'non-empty'
81
82
# Workbook with a single workflow
83
WB1_META_FILE_NAME = TEST_FIXTURES['workflows'][0]
84
WB1_META_FILE_PATH = TEST_PACK_PATH + '/actions/' + WB1_META_FILE_NAME
85
WB1_META_CONTENT = loader.load_meta_file(WB1_META_FILE_PATH)
86
WB1_NAME = WB1_META_CONTENT['pack'] + '.' + WB1_META_CONTENT['name']
87
WB1_ENTRY_POINT = TEST_PACK_PATH + '/actions/' + WB1_META_CONTENT['entry_point']
88
WB1_ENTRY_POINT_X = WB1_ENTRY_POINT.replace(WB1_META_FILE_NAME, 'xformed_' + WB1_META_FILE_NAME)
89
WB1_SPEC = yaml.safe_load(MistralRunner.get_workflow_definition(WB1_ENTRY_POINT_X))
90
WB1_YAML = yaml.safe_dump(WB1_SPEC, default_flow_style=False)
91
WB1 = workbooks.Workbook(None, {'name': WB1_NAME, 'definition': WB1_YAML})
92
WB1_OLD = workbooks.Workbook(None, {'name': WB1_NAME, 'definition': ''})
93
WB1_EXEC = copy.deepcopy(MISTRAL_EXECUTION)
94
WB1_EXEC['workflow_name'] = WB1_NAME
95
96
# Workbook with many workflows
97
WB2_META_FILE_NAME = TEST_FIXTURES['workflows'][1]
98
WB2_META_FILE_PATH = TEST_PACK_PATH + '/actions/' + WB2_META_FILE_NAME
99
WB2_META_CONTENT = loader.load_meta_file(WB2_META_FILE_PATH)
100
WB2_NAME = WB2_META_CONTENT['pack'] + '.' + WB2_META_CONTENT['name']
101
WB2_ENTRY_POINT = TEST_PACK_PATH + '/actions/' + WB2_META_CONTENT['entry_point']
102
WB2_ENTRY_POINT_X = WB2_ENTRY_POINT.replace(WB2_META_FILE_NAME, 'xformed_' + WB2_META_FILE_NAME)
103
WB2_SPEC = yaml.safe_load(MistralRunner.get_workflow_definition(WB2_ENTRY_POINT_X))
104
WB2_YAML = yaml.safe_dump(WB2_SPEC, default_flow_style=False)
105
WB2 = workbooks.Workbook(None, {'name': WB2_NAME, 'definition': WB2_YAML})
106
WB2_EXEC = copy.deepcopy(MISTRAL_EXECUTION)
107
WB2_EXEC['workflow_name'] = WB2_NAME
108
109
# Workbook with many workflows but no default workflow is defined
110
WB3_META_FILE_NAME = TEST_FIXTURES['workflows'][2]
111
WB3_META_FILE_PATH = TEST_PACK_PATH + '/actions/' + WB3_META_FILE_NAME
112
WB3_META_CONTENT = loader.load_meta_file(WB3_META_FILE_PATH)
113
WB3_NAME = WB3_META_CONTENT['pack'] + '.' + WB3_META_CONTENT['name']
114
WB3_ENTRY_POINT = TEST_PACK_PATH + '/actions/' + WB3_META_CONTENT['entry_point']
115
WB3_ENTRY_POINT_X = WB3_ENTRY_POINT.replace(WB3_META_FILE_NAME, 'xformed_' + WB3_META_FILE_NAME)
116
WB3_SPEC = yaml.safe_load(MistralRunner.get_workflow_definition(WB3_ENTRY_POINT_X))
117
WB3_YAML = yaml.safe_dump(WB3_SPEC, default_flow_style=False)
118
WB3 = workbooks.Workbook(None, {'name': WB3_NAME, 'definition': WB3_YAML})
119
WB3_EXEC = copy.deepcopy(MISTRAL_EXECUTION)
120
WB3_EXEC['workflow_name'] = WB3_NAME
121
122
# Non-workbook with a single workflow
123
WF1_META_FILE_NAME = TEST_FIXTURES['workflows'][3]
124
WF1_META_FILE_PATH = TEST_PACK_PATH + '/actions/' + WF1_META_FILE_NAME
125
WF1_META_CONTENT = loader.load_meta_file(WF1_META_FILE_PATH)
126
WF1_NAME = WF1_META_CONTENT['pack'] + '.' + WF1_META_CONTENT['name']
127
WF1_ENTRY_POINT = TEST_PACK_PATH + '/actions/' + WF1_META_CONTENT['entry_point']
128
WF1_ENTRY_POINT_X = WF1_ENTRY_POINT.replace(WF1_META_FILE_NAME, 'xformed_' + WF1_META_FILE_NAME)
129
WF1_SPEC = yaml.safe_load(MistralRunner.get_workflow_definition(WF1_ENTRY_POINT_X))
130
WF1_YAML = yaml.safe_dump(WF1_SPEC, default_flow_style=False)
131
WF1 = workflows.Workflow(None, {'name': WF1_NAME, 'definition': WF1_YAML})
132
WF1_OLD = workflows.Workflow(None, {'name': WF1_NAME, 'definition': ''})
133
WF1_EXEC = copy.deepcopy(MISTRAL_EXECUTION)
134
WF1_EXEC['workflow_name'] = WF1_NAME
135
WF1_EXEC_PAUSED = copy.deepcopy(WF1_EXEC)
136
WF1_EXEC_PAUSED['state'] = 'PAUSED'
137
138
# Non-workbook with a many workflows
139
WF2_META_FILE_NAME = TEST_FIXTURES['workflows'][4]
140
WF2_META_FILE_PATH = TEST_PACK_PATH + '/actions/' + WF2_META_FILE_NAME
141
WF2_META_CONTENT = loader.load_meta_file(WF2_META_FILE_PATH)
142
WF2_NAME = WF2_META_CONTENT['pack'] + '.' + WF2_META_CONTENT['name']
143
WF2_ENTRY_POINT = TEST_PACK_PATH + '/actions/' + WF2_META_CONTENT['entry_point']
144
WF2_ENTRY_POINT_X = WF2_ENTRY_POINT.replace(WF2_META_FILE_NAME, 'xformed_' + WF2_META_FILE_NAME)
145
WF2_SPEC = yaml.safe_load(MistralRunner.get_workflow_definition(WF2_ENTRY_POINT_X))
146
WF2_YAML = yaml.safe_dump(WF2_SPEC, default_flow_style=False)
147
WF2 = workflows.Workflow(None, {'name': WF2_NAME, 'definition': WF2_YAML})
148
WF2_EXEC = copy.deepcopy(MISTRAL_EXECUTION)
149
WF2_EXEC['workflow_name'] = WF2_NAME
150
151
152
@mock.patch.object(
153
    CUDPublisher,
154
    'publish_update',
155
    mock.MagicMock(return_value=None))
156
@mock.patch.object(
157
    CUDPublisher,
158
    'publish_create',
159
    mock.MagicMock(side_effect=MockLiveActionPublisher.publish_create))
160
@mock.patch.object(
161
    LiveActionPublisher,
162
    'publish_state',
163
    mock.MagicMock(side_effect=MockLiveActionPublisher.publish_state))
164
class MistralRunnerTest(DbTestCase):
165
166
    @classmethod
167
    def setUpClass(cls):
168
        super(MistralRunnerTest, cls).setUpClass()
169
170
        # Override the retry configuration here otherwise st2tests.config.parse_args
171
        # in DbTestCase.setUpClass will reset these overrides.
172
        cfg.CONF.set_override('retry_exp_msec', 100, group='mistral')
173
        cfg.CONF.set_override('retry_exp_max_msec', 200, group='mistral')
174
        cfg.CONF.set_override('retry_stop_max_msec', 200, group='mistral')
175
        cfg.CONF.set_override('api_url', 'http://0.0.0.0:9101', group='auth')
176
177
        # Register runners.
178
        runnersregistrar.register_runners()
179
180
        # Register test pack(s).
181
        actions_registrar = actionsregistrar.ActionsRegistrar(
182
            use_pack_cache=False,
183
            fail_on_failure=True
184
        )
185
186
        for pack in PACKS:
187
            actions_registrar.register_from_pack(pack)
188
189
    @classmethod
190
    def get_runner_class(cls, runner_name):
191
        return runners.get_runner(runner_name).__class__
192
193
    def test_build_context(self):
194
        parent = {
195
            'mistral': {
196
                'workflow_name': 'foo',
197
                'workflow_execution_id': 'b222b934-7473-4cd4-a2ec-e204a8c93848',
198
                'task_tags': None,
199
                'task_name': 'some_fancy_wf_task',
200
                'task_id': '6c7d4334-3e7d-49c6-918d-698e846affaf',
201
                'action_execution_id': '24da5c88-834c-4a65-8b56-4ddbd654eb68'
202
            }
203
        }
204
205
        current = {
206
            'workflow_name': 'foo.subwf',
207
            'workflow_execution_id': '135e3446-4c89-4afe-821f-6ec6a0849b27'
208
        }
209
210
        context = MistralRunner._build_mistral_context(parent, current)
211
        self.assertTrue(context is not None)
212
        self.assertTrue('parent' in context['mistral'].keys())
213
214
        parent_dict = {
215
            'workflow_name': parent['mistral']['workflow_name'],
216
            'workflow_execution_id': parent['mistral']['workflow_execution_id']
217
        }
218
219
        self.assertDictEqual(context['mistral']['parent'], parent_dict)
220
        self.assertEqual(context['mistral']['workflow_execution_id'],
221
                         current['workflow_execution_id'])
222
223
        parent = None
224
        context = MistralRunner._build_mistral_context(parent, current)
225
        self.assertDictEqual(context['mistral'], current)
226
227
    @mock.patch.object(
228
        workflows.WorkflowManager, 'list',
229
        mock.MagicMock(return_value=[]))
230
    @mock.patch.object(
231
        workflows.WorkflowManager, 'get',
232
        mock.MagicMock(return_value=WF1))
233
    @mock.patch.object(
234
        workflows.WorkflowManager, 'create',
235
        mock.MagicMock(return_value=[WF1]))
236
    @mock.patch.object(
237
        executions.ExecutionManager, 'create',
238
        mock.MagicMock(return_value=executions.Execution(None, WF1_EXEC)))
239
    def test_launch_workflow(self):
240
        liveaction = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS)
241
        liveaction, execution = action_service.request(liveaction)
242
        liveaction = LiveAction.get_by_id(str(liveaction.id))
243
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING)
244
245
        mistral_context = liveaction.context.get('mistral', None)
246
        self.assertIsNotNone(mistral_context)
247
        self.assertEqual(mistral_context['execution_id'], WF1_EXEC.get('id'))
248
        self.assertEqual(mistral_context['workflow_name'], WF1_EXEC.get('workflow_name'))
249
250
        workflow_input = copy.deepcopy(ACTION_PARAMS)
251
        workflow_input.update({'count': '3'})
252
253
        env = {
254
            'st2_execution_id': str(execution.id),
255
            'st2_liveaction_id': str(liveaction.id),
256
            'st2_action_api_url': 'http://0.0.0.0:9101/v1',
257
            '__actions': {
258
                'st2.action': {
259
                    'st2_context': {
260
                        'api_url': 'http://0.0.0.0:9101/v1',
261
                        'endpoint': 'http://0.0.0.0:9101/v1/actionexecutions',
262
                        'parent': {
263
                            'execution_id': str(execution.id)
264
                        },
265
                        'notify': {},
266
                        'skip_notify_tasks': []
267
                    }
268
                }
269
            }
270
        }
271
272
        executions.ExecutionManager.create.assert_called_with(
273
            WF1_NAME, workflow_input=workflow_input, env=env)
274
275
    @mock.patch.object(
276
        workflows.WorkflowManager, 'list',
277
        mock.MagicMock(return_value=[]))
278
    @mock.patch.object(
279
        workflows.WorkflowManager, 'get',
280
        mock.MagicMock(return_value=WF1))
281
    @mock.patch.object(
282
        workflows.WorkflowManager, 'create',
283
        mock.MagicMock(return_value=[WF1]))
284
    @mock.patch.object(
285
        executions.ExecutionManager, 'create',
286
        mock.MagicMock(return_value=executions.Execution(None, WF1_EXEC)))
287
    def test_launch_workflow_with_st2_https(self):
288
        cfg.CONF.set_override('api_url', 'https://0.0.0.0:9101', group='auth')
289
290
        liveaction = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS)
291
        liveaction, execution = action_service.request(liveaction)
292
        liveaction = LiveAction.get_by_id(str(liveaction.id))
293
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING)
294
295
        mistral_context = liveaction.context.get('mistral', None)
296
        self.assertIsNotNone(mistral_context)
297
        self.assertEqual(mistral_context['execution_id'], WF1_EXEC.get('id'))
298
        self.assertEqual(mistral_context['workflow_name'], WF1_EXEC.get('workflow_name'))
299
300
        workflow_input = copy.deepcopy(ACTION_PARAMS)
301
        workflow_input.update({'count': '3'})
302
303
        env = {
304
            'st2_execution_id': str(execution.id),
305
            'st2_liveaction_id': str(liveaction.id),
306
            'st2_action_api_url': 'https://0.0.0.0:9101/v1',
307
            '__actions': {
308
                'st2.action': {
309
                    'st2_context': {
310
                        'api_url': 'https://0.0.0.0:9101/v1',
311
                        'endpoint': 'https://0.0.0.0:9101/v1/actionexecutions',
312
                        'parent': {
313
                            'execution_id': str(execution.id)
314
                        },
315
                        'notify': {},
316
                        'skip_notify_tasks': []
317
                    }
318
                }
319
            }
320
        }
321
322
        executions.ExecutionManager.create.assert_called_with(
323
            WF1_NAME, workflow_input=workflow_input, env=env)
324
325
    @mock.patch.object(
326
        workflows.WorkflowManager, 'list',
327
        mock.MagicMock(return_value=[]))
328
    @mock.patch.object(
329
        workflows.WorkflowManager, 'get',
330
        mock.MagicMock(return_value=WF1))
331
    @mock.patch.object(
332
        workflows.WorkflowManager, 'create',
333
        mock.MagicMock(return_value=[WF1]))
334
    @mock.patch.object(
335
        executions.ExecutionManager, 'create',
336
        mock.MagicMock(return_value=executions.Execution(None, WF1_EXEC)))
337
    def test_launch_workflow_with_notifications(self):
338
        notify_data = {'on_complete': {'routes': ['slack'],
339
                       'message': '"@channel: Action succeeded."', 'data': {}}}
340
341
        liveaction = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS, notify=notify_data)
342
        liveaction, execution = action_service.request(liveaction)
343
        liveaction = LiveAction.get_by_id(str(liveaction.id))
344
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING)
345
346
        mistral_context = liveaction.context.get('mistral', None)
347
        self.assertIsNotNone(mistral_context)
348
        self.assertEqual(mistral_context['execution_id'], WF1_EXEC.get('id'))
349
        self.assertEqual(mistral_context['workflow_name'], WF1_EXEC.get('workflow_name'))
350
351
        workflow_input = copy.deepcopy(ACTION_PARAMS)
352
        workflow_input.update({'count': '3'})
353
354
        env = {
355
            'st2_execution_id': str(execution.id),
356
            'st2_liveaction_id': str(liveaction.id),
357
            'st2_action_api_url': 'http://0.0.0.0:9101/v1',
358
            '__actions': {
359
                'st2.action': {
360
                    'st2_context': {
361
                        'api_url': 'http://0.0.0.0:9101/v1',
362
                        'endpoint': 'http://0.0.0.0:9101/v1/actionexecutions',
363
                        'parent': {
364
                            'execution_id': str(execution.id)
365
                        },
366
                        'notify': NotificationsHelper.from_model(liveaction.notify),
367
                        'skip_notify_tasks': []
368
                    }
369
                }
370
            }
371
        }
372
373
        executions.ExecutionManager.create.assert_called_with(
374
            WF1_NAME, workflow_input=workflow_input, env=env)
375
376
    @mock.patch.object(
377
        workflows.WorkflowManager, 'list',
378
        mock.MagicMock(side_effect=requests.exceptions.ConnectionError('Connection refused')))
379
    def test_launch_workflow_mistral_offline(self):
380
        liveaction = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS)
381
        liveaction, execution = action_service.request(liveaction)
382
        liveaction = LiveAction.get_by_id(str(liveaction.id))
383
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_FAILED)
384
        self.assertIn('Connection refused', liveaction.result['error'])
385
386
    @mock.patch.object(
387
        workflows.WorkflowManager, 'list',
388
        mock.MagicMock(side_effect=[requests.exceptions.ConnectionError(), []]))
389
    @mock.patch.object(
390
        workflows.WorkflowManager, 'get',
391
        mock.MagicMock(return_value=WF1))
392
    @mock.patch.object(
393
        workflows.WorkflowManager, 'create',
394
        mock.MagicMock(return_value=[WF1]))
395
    @mock.patch.object(
396
        executions.ExecutionManager, 'create',
397
        mock.MagicMock(return_value=executions.Execution(None, WF1_EXEC)))
398
    def test_launch_workflow_mistral_retry(self):
399
        liveaction = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS)
400
        liveaction, execution = action_service.request(liveaction)
401
        liveaction = LiveAction.get_by_id(str(liveaction.id))
402
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING)
403
404
        mistral_context = liveaction.context.get('mistral', None)
405
        self.assertIsNotNone(mistral_context)
406
        self.assertEqual(mistral_context['execution_id'], WF1_EXEC.get('id'))
407
        self.assertEqual(mistral_context['workflow_name'], WF1_EXEC.get('workflow_name'))
408
409
    @mock.patch.object(
410
        workflows.WorkflowManager, 'list',
411
        mock.MagicMock(return_value=[]))
412
    @mock.patch.object(
413
        workflows.WorkflowManager, 'get',
414
        mock.MagicMock(return_value=WF1))
415
    @mock.patch.object(
416
        workflows.WorkflowManager, 'create',
417
        mock.MagicMock(side_effect=[APIException(error_message='Duplicate entry.'), WF1]))
418
    @mock.patch.object(
419
        executions.ExecutionManager, 'create',
420
        mock.MagicMock(return_value=executions.Execution(None, WF1_EXEC)))
421
    def test_launch_workflow_duplicate_error(self):
422
        liveaction = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS)
423
        liveaction, execution = action_service.request(liveaction)
424
        liveaction = LiveAction.get_by_id(str(liveaction.id))
425
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING)
426
427
        mistral_context = liveaction.context.get('mistral', None)
428
        self.assertIsNotNone(mistral_context)
429
        self.assertEqual(mistral_context['execution_id'], WF1_EXEC.get('id'))
430
        self.assertEqual(mistral_context['workflow_name'], WF1_EXEC.get('workflow_name'))
431
432
    @mock.patch.object(
433
        workflows.WorkflowManager, 'list',
434
        mock.MagicMock(return_value=[]))
435
    @mock.patch.object(
436
        workflows.WorkflowManager, 'get',
437
        mock.MagicMock(return_value=WF1_OLD))
438
    @mock.patch.object(
439
        workflows.WorkflowManager, 'create',
440
        mock.MagicMock(return_value=[WF1]))
441
    @mock.patch.object(
442
        workflows.WorkflowManager, 'update',
443
        mock.MagicMock(return_value=[WF1]))
444
    @mock.patch.object(
445
        executions.ExecutionManager, 'create',
446
        mock.MagicMock(return_value=executions.Execution(None, WF1_EXEC)))
447
    def test_launch_when_workflow_definition_changed(self):
448
        liveaction = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS)
449
        liveaction, execution = action_service.request(liveaction)
450
        liveaction = LiveAction.get_by_id(str(liveaction.id))
451
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING)
452
453
        mistral_context = liveaction.context.get('mistral', None)
454
        self.assertIsNotNone(mistral_context)
455
        self.assertEqual(mistral_context['execution_id'], WF1_EXEC.get('id'))
456
        self.assertEqual(mistral_context['workflow_name'], WF1_EXEC.get('workflow_name'))
457
458
    @mock.patch.object(
459
        workflows.WorkflowManager, 'list',
460
        mock.MagicMock(return_value=[]))
461
    @mock.patch.object(
462
        workflows.WorkflowManager, 'get',
463
        mock.MagicMock(side_effect=Exception()))
464
    @mock.patch.object(
465
        workbooks.WorkbookManager, 'delete',
466
        mock.MagicMock(side_effect=Exception()))
467
    @mock.patch.object(
468
        workflows.WorkflowManager, 'create',
469
        mock.MagicMock(return_value=[WF1]))
470
    @mock.patch.object(
471
        executions.ExecutionManager, 'create',
472
        mock.MagicMock(return_value=executions.Execution(None, WF1_EXEC)))
473
    def test_launch_when_workflow_not_exists(self):
474
        liveaction = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS)
475
        liveaction, execution = action_service.request(liveaction)
476
        liveaction = LiveAction.get_by_id(str(liveaction.id))
477
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING)
478
479
        mistral_context = liveaction.context.get('mistral', None)
480
        self.assertIsNotNone(mistral_context)
481
        self.assertEqual(mistral_context['execution_id'], WF1_EXEC.get('id'))
482
        self.assertEqual(mistral_context['workflow_name'], WF1_EXEC.get('workflow_name'))
483
484
    @mock.patch.object(
485
        workflows.WorkflowManager, 'list',
486
        mock.MagicMock(return_value=[]))
487
    @mock.patch.object(
488
        workflows.WorkflowManager, 'get',
489
        mock.MagicMock(return_value=WF2))
490
    def test_launch_workflow_with_many_workflows(self):
491
        liveaction = LiveActionDB(action=WF2_NAME, parameters=ACTION_PARAMS)
492
        liveaction, execution = action_service.request(liveaction)
493
        liveaction = LiveAction.get_by_id(str(liveaction.id))
494
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_FAILED)
495
        self.assertIn('Multiple workflows is not supported.', liveaction.result['error'])
496
497
    @mock.patch.object(
498
        workflows.WorkflowManager, 'list',
499
        mock.MagicMock(return_value=[]))
500
    @mock.patch.object(
501
        workflows.WorkflowManager, 'get',
502
        mock.MagicMock(side_effect=Exception()))
503
    def test_launch_workflow_name_mistmatch(self):
504
        action_ref = TEST_PACK + '.workflow_v2_name_mismatch'
505
        liveaction = LiveActionDB(action=action_ref, parameters=ACTION_PARAMS)
506
        liveaction, execution = action_service.request(liveaction)
507
        liveaction = LiveAction.get_by_id(str(liveaction.id))
508
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_FAILED)
509
        self.assertIn('Name of the workflow must be the same', liveaction.result['error'])
510
511
    @mock.patch.object(
512
        workflows.WorkflowManager, 'list',
513
        mock.MagicMock(return_value=[]))
514
    @mock.patch.object(
515
        workbooks.WorkbookManager, 'get',
516
        mock.MagicMock(return_value=WB1))
517
    @mock.patch.object(
518
        workbooks.WorkbookManager, 'create',
519
        mock.MagicMock(return_value=WB1))
520
    @mock.patch.object(
521
        workbooks.WorkbookManager, 'update',
522
        mock.MagicMock(return_value=WB1))
523
    @mock.patch.object(
524
        executions.ExecutionManager, 'create',
525
        mock.MagicMock(return_value=executions.Execution(None, WB1_EXEC)))
526
    def test_launch_workbook(self):
527
        liveaction = LiveActionDB(action=WB1_NAME, parameters=ACTION_PARAMS)
528
        liveaction, execution = action_service.request(liveaction)
529
        liveaction = LiveAction.get_by_id(str(liveaction.id))
530
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING)
531
532
        mistral_context = liveaction.context.get('mistral', None)
533
        self.assertIsNotNone(mistral_context)
534
        self.assertEqual(mistral_context['execution_id'], WB1_EXEC.get('id'))
535
        self.assertEqual(mistral_context['workflow_name'], WB1_EXEC.get('workflow_name'))
536
537
    @mock.patch.object(
538
        workflows.WorkflowManager, 'list',
539
        mock.MagicMock(return_value=[]))
540
    @mock.patch.object(
541
        workbooks.WorkbookManager, 'get',
542
        mock.MagicMock(return_value=WB2))
543
    @mock.patch.object(
544
        workbooks.WorkbookManager, 'create',
545
        mock.MagicMock(return_value=WB2))
546
    @mock.patch.object(
547
        workbooks.WorkbookManager, 'update',
548
        mock.MagicMock(return_value=WB2))
549
    @mock.patch.object(
550
        executions.ExecutionManager, 'create',
551
        mock.MagicMock(return_value=executions.Execution(None, WB2_EXEC)))
552
    def test_launch_workbook_with_many_workflows(self):
553
        liveaction = LiveActionDB(action=WB2_NAME, parameters=ACTION_PARAMS)
554
        liveaction, execution = action_service.request(liveaction)
555
        liveaction = LiveAction.get_by_id(str(liveaction.id))
556
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING)
557
558
        mistral_context = liveaction.context.get('mistral', None)
559
        self.assertIsNotNone(mistral_context)
560
        self.assertEqual(mistral_context['execution_id'], WB2_EXEC.get('id'))
561
        self.assertEqual(mistral_context['workflow_name'], WB2_EXEC.get('workflow_name'))
562
563
    @mock.patch.object(
564
        workflows.WorkflowManager, 'list',
565
        mock.MagicMock(return_value=[]))
566
    @mock.patch.object(
567
        workbooks.WorkbookManager, 'get',
568
        mock.MagicMock(return_value=WB3))
569
    @mock.patch.object(
570
        workbooks.WorkbookManager, 'create',
571
        mock.MagicMock(return_value=WB3))
572
    @mock.patch.object(
573
        workbooks.WorkbookManager, 'update',
574
        mock.MagicMock(return_value=WB3))
575
    @mock.patch.object(
576
        executions.ExecutionManager, 'create',
577
        mock.MagicMock(return_value=executions.Execution(None, WB3_EXEC)))
578
    def test_launch_workbook_with_many_workflows_no_default(self):
579
        liveaction = LiveActionDB(action=WB3_NAME, parameters=ACTION_PARAMS)
580
        liveaction, execution = action_service.request(liveaction)
581
        liveaction = LiveAction.get_by_id(str(liveaction.id))
582
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_FAILED)
583
        self.assertIn('Default workflow cannot be determined.', liveaction.result['error'])
584
585
    @mock.patch.object(
586
        workflows.WorkflowManager, 'list',
587
        mock.MagicMock(return_value=[]))
588
    @mock.patch.object(
589
        workbooks.WorkbookManager, 'get',
590
        mock.MagicMock(return_value=WB1_OLD))
591
    @mock.patch.object(
592
        workbooks.WorkbookManager, 'create',
593
        mock.MagicMock(return_value=WB1))
594
    @mock.patch.object(
595
        workbooks.WorkbookManager, 'update',
596
        mock.MagicMock(return_value=WB1))
597
    @mock.patch.object(
598
        executions.ExecutionManager, 'create',
599
        mock.MagicMock(return_value=executions.Execution(None, WB1_EXEC)))
600
    def test_launch_when_workbook_definition_changed(self):
601
        liveaction = LiveActionDB(action=WB1_NAME, parameters=ACTION_PARAMS)
602
        liveaction, execution = action_service.request(liveaction)
603
        liveaction = LiveAction.get_by_id(str(liveaction.id))
604
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING)
605
606
        mistral_context = liveaction.context.get('mistral', None)
607
        self.assertIsNotNone(mistral_context)
608
        self.assertEqual(mistral_context['execution_id'], WB1_EXEC.get('id'))
609
        self.assertEqual(mistral_context['workflow_name'], WB1_EXEC.get('workflow_name'))
610
611
    @mock.patch.object(
612
        workflows.WorkflowManager, 'list',
613
        mock.MagicMock(return_value=[]))
614
    @mock.patch.object(
615
        workbooks.WorkbookManager, 'get',
616
        mock.MagicMock(side_effect=Exception()))
617
    @mock.patch.object(
618
        workflows.WorkflowManager, 'delete',
619
        mock.MagicMock(side_effect=Exception()))
620
    @mock.patch.object(
621
        workbooks.WorkbookManager, 'create',
622
        mock.MagicMock(return_value=WB1))
623
    @mock.patch.object(
624
        executions.ExecutionManager, 'create',
625
        mock.MagicMock(return_value=executions.Execution(None, WB1_EXEC)))
626
    def test_launch_when_workbook_not_exists(self):
627
        liveaction = LiveActionDB(action=WB1_NAME, parameters=ACTION_PARAMS)
628
        liveaction, execution = action_service.request(liveaction)
629
        liveaction = LiveAction.get_by_id(str(liveaction.id))
630
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING)
631
632
        mistral_context = liveaction.context.get('mistral', None)
633
        self.assertIsNotNone(mistral_context)
634
        self.assertEqual(mistral_context['execution_id'], WB1_EXEC.get('id'))
635
        self.assertEqual(mistral_context['workflow_name'], WB1_EXEC.get('workflow_name'))
636
637
    @mock.patch.object(
638
        workflows.WorkflowManager, 'list',
639
        mock.MagicMock(return_value=[]))
640
    @mock.patch.object(
641
        workbooks.WorkbookManager, 'get',
642
        mock.MagicMock(side_effect=Exception()))
643
    def test_launch_workbook_name_mismatch(self):
644
        action_ref = TEST_PACK + '.workbook_v2_name_mismatch'
645
        liveaction = LiveActionDB(action=action_ref, parameters=ACTION_PARAMS)
646
        liveaction, execution = action_service.request(liveaction)
647
        liveaction = LiveAction.get_by_id(str(liveaction.id))
648
        self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_FAILED)
649
        self.assertIn('Name of the workbook must be the same', liveaction.result['error'])
650