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.
Completed
Pull Request — kale/action-datastore (#6)
by Manas
05:59
created

st2common.models.api.ActionAPI.from_model()   A

Complexity

Conditions 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 10
rs 9.4285
cc 2
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
18
from st2common.util import isotime
19
from st2common.util import schema as util_schema
20
from st2common import log as logging
21
from st2common.models.api.base import BaseAPI
22
from st2common.models.api.base import APIUIDMixin
23
from st2common.models.api.tag import TagsHelper
24
from st2common.models.api.notification import (NotificationSubSchemaAPI, NotificationsHelper)
25
from st2common.models.db.action import ActionDB
26
from st2common.models.db.actionalias import ActionAliasDB
27
from st2common.models.db.executionstate import ActionExecutionStateDB
28
from st2common.models.db.liveaction import LiveActionDB
29
from st2common.models.db.runner import RunnerTypeDB
30
from st2common.constants.action import LIVEACTION_STATUSES
31
from st2common.models.system.common import ResourceReference
32
33
34
__all__ = [
35
    'ActionAPI',
36
    'ActionCreateAPI',
37
    'LiveActionAPI',
38
    'RunnerTypeAPI'
39
]
40
41
42
LOG = logging.getLogger(__name__)
43
44
45
class RunnerTypeAPI(BaseAPI):
46
    """
47
    The representation of an RunnerType in the system. An RunnerType
48
    has a one-to-one mapping to a particular ActionRunner implementation.
49
    """
50
    model = RunnerTypeDB
51
    schema = {
52
        "title": "Runner",
53
        "description": "A handler for a specific type of actions.",
54
        "type": "object",
55
        "properties": {
56
            "id": {
57
                "description": "The unique identifier for the action runner.",
58
                "type": "string",
59
                "default": None
60
            },
61
            "name": {
62
                "description": "The name of the action runner.",
63
                "type": "string",
64
                "required": True
65
            },
66
            "description": {
67
                "description": "The description of the action runner.",
68
                "type": "string"
69
            },
70
            "enabled": {
71
                "description": "Enable or disable the action runner.",
72
                "type": "boolean",
73
                "default": True
74
            },
75
            "runner_module": {
76
                "description": "The python module that implements the "
77
                               "action runner for this type.",
78
                "type": "string",
79
                "required": True
80
            },
81
            "query_module": {
82
                "description": "The python module that implements the "
83
                               "results tracker (querier) for the runner.",
84
                "type": "string",
85
                "required": False
86
            },
87
            "runner_parameters": {
88
                "description": "Input parameters for the action runner.",
89
                "type": "object",
90
                "patternProperties": {
91
                    "^\w+$": util_schema.get_action_parameters_schema()
0 ignored issues
show
Bug introduced by
A suspicious escape sequence \w was found. Did you maybe forget to add an r prefix?

Escape sequences in Python are generally interpreted according to rules similar to standard C. Only if strings are prefixed with r or R are they interpreted as regular expressions.

The escape sequence that was used indicates that you might have intended to write a regular expression.

Learn more about the available escape sequences. in the Python documentation.

Loading history...
92
                }
93
            }
94
        },
95
        "additionalProperties": False
96
    }
97
98
    def __init__(self, **kw):
0 ignored issues
show
Bug introduced by
The __init__ method of the super-class BaseAPI is not called.

It is generally advisable to initialize the super-class by calling its __init__ method:

class SomeParent:
    def __init__(self):
        self.x = 1

class SomeChild(SomeParent):
    def __init__(self):
        # Initialize the super class
        SomeParent.__init__(self)
Loading history...
99
        # Ideally, you should not do that. You should not redefine __init__ to validate and then set
100
        # default values, instead you should define defaults in schema and use BaseAPI __init__
101
        # validator to unwrap them. The problem here is that draft schema also contains default
102
        # values and we don't want them to be unwrapped at the same time. I've tried to remove the
103
        # default values from draft schema, but, either because of a bug or some weird intention, it
104
        # has continued to resolve $ref'erenced properties against the initial draft schema, not the
105
        # modified one
106
        for key, value in kw.items():
107
            setattr(self, key, value)
108
        if not hasattr(self, 'runner_parameters'):
109
            setattr(self, 'runner_parameters', dict())
110
111
    @classmethod
112
    def to_model(cls, runner_type):
113
        name = runner_type.name
114
        description = runner_type.description
115
        enabled = bool(runner_type.enabled)
116
        runner_module = str(runner_type.runner_module)
117
        runner_parameters = getattr(runner_type, 'runner_parameters', dict())
118
        query_module = getattr(runner_type, 'query_module', None)
119
120
        model = cls.model(name=name, description=description, enabled=enabled,
121
                          runner_module=runner_module, runner_parameters=runner_parameters,
122
                          query_module=query_module)
123
124
        return model
125
126
127
class ActionAPI(BaseAPI, APIUIDMixin):
128
    """
129
    The system entity that represents a Stack Action/Automation in the system.
130
    """
131
132
    model = ActionDB
133
    schema = {
134
        "title": "Action",
135
        "description": "An activity that happens as a response to the external event.",
136
        "type": "object",
137
        "properties": {
138
            "id": {
139
                "description": "The unique identifier for the action.",
140
                "type": "string"
141
            },
142
            "ref": {
143
                "description": "System computed user friendly reference for the action. \
144
                                Provided value will be overridden by computed value.",
145
                "type": "string"
146
            },
147
            "uid": {
148
                "type": "string"
149
            },
150
            "name": {
151
                "description": "The name of the action.",
152
                "type": "string",
153
                "required": True
154
            },
155
            "description": {
156
                "description": "The description of the action.",
157
                "type": "string"
158
            },
159
            "enabled": {
160
                "description": "Enable or disable the action from invocation.",
161
                "type": "boolean",
162
                "default": True
163
            },
164
            "runner_type": {
165
                "description": "The type of runner that executes the action.",
166
                "type": "string",
167
                "required": True
168
            },
169
            "entry_point": {
170
                "description": "The entry point for the action.",
171
                "type": "string",
172
                "default": ""
173
            },
174
            "pack": {
175
                "description": "The content pack this action belongs to.",
176
                "type": "string"
177
            },
178
            "parameters": {
179
                "description": "Input parameters for the action.",
180
                "type": "object",
181
                "patternProperties": {
182
                    "^\w+$": util_schema.get_action_parameters_schema()
0 ignored issues
show
Bug introduced by
A suspicious escape sequence \w was found. Did you maybe forget to add an r prefix?

Escape sequences in Python are generally interpreted according to rules similar to standard C. Only if strings are prefixed with r or R are they interpreted as regular expressions.

The escape sequence that was used indicates that you might have intended to write a regular expression.

Learn more about the available escape sequences. in the Python documentation.

Loading history...
183
                },
184
                "default": {}
185
            },
186
            "tags": {
187
                "description": "User associated metadata assigned to this object.",
188
                "type": "array",
189
                "items": {"type": "object"}
190
            },
191
            "notify": {
192
                "description": "Notification settings for action.",
193
                "type": "object",
194
                "properties": {
195
                    "on-complete": NotificationSubSchemaAPI,
196
                    "on-failure": NotificationSubSchemaAPI,
197
                    "on-success": NotificationSubSchemaAPI
198
                },
199
                "additionalProperties": False
200
            }
201
        },
202
        "additionalProperties": False
203
    }
204
205
    def __init__(self, **kw):
0 ignored issues
show
Bug introduced by
The __init__ method of the super-class BaseAPI is not called.

It is generally advisable to initialize the super-class by calling its __init__ method:

class SomeParent:
    def __init__(self):
        self.x = 1

class SomeChild(SomeParent):
    def __init__(self):
        # Initialize the super class
        SomeParent.__init__(self)
Loading history...
206
        for key, value in kw.items():
207
            setattr(self, key, value)
208
        if not hasattr(self, 'parameters'):
209
            setattr(self, 'parameters', dict())
210
        if not hasattr(self, 'entry_point'):
211
            setattr(self, 'entry_point', '')
212
213
    @classmethod
214
    def from_model(cls, model, mask_secrets=False):
215
        action = cls._from_model(model)
216
        action['runner_type'] = action['runner_type']['name']
217
        action['tags'] = TagsHelper.from_model(model.tags)
218
219
        if getattr(model, 'notify', None):
220
            action['notify'] = NotificationsHelper.from_model(model.notify)
221
222
        return cls(**action)
223
224
    @classmethod
225
    def to_model(cls, action):
226
        name = getattr(action, 'name', None)
227
        description = getattr(action, 'description', None)
228
        enabled = bool(getattr(action, 'enabled', True))
229
        entry_point = str(action.entry_point)
230
        pack = str(action.pack)
231
        runner_type = {'name': str(action.runner_type)}
232
        parameters = getattr(action, 'parameters', dict())
233
        tags = TagsHelper.to_model(getattr(action, 'tags', []))
234
        ref = ResourceReference.to_string_reference(pack=pack, name=name)
235
236
        if getattr(action, 'notify', None):
237
            notify = NotificationsHelper.to_model(action.notify)
238
        else:
239
            # We use embedded document model for ``notify`` in action model. If notify is
240
            # set notify to None, Mongoengine interprets ``None`` as unmodified
241
            # field therefore doesn't delete the embedded document. Therefore, we need
242
            # to use an empty document.
243
            notify = NotificationsHelper.to_model({})
244
245
        model = cls.model(name=name, description=description, enable=enabled, enabled=enabled,
246
                          entry_point=entry_point, pack=pack, runner_type=runner_type,
247
                          tags=tags, parameters=parameters, notify=notify,
248
                          ref=ref)
249
250
        return model
251
252
253
class ActionCreateAPI(ActionAPI, APIUIDMixin):
254
    """
255
    API model for create action operations.
256
    """
257
    schema = copy.deepcopy(ActionAPI.schema)
258
    schema['properties']['data_files'] = {
259
        'description': 'Optional action script and data files which are written to the filesystem.',
260
        'type': 'array',
261
        'items': {
262
            'type': 'object',
263
            'properties': {
264
                'file_path': {
265
                    'type': 'string',
266
                    'required': True
267
                },
268
                'content': {
269
                    'type': 'string',
270
                    'required': True
271
                },
272
            },
273
            'additionalProperties': False
274
        },
275
        'default': []
276
    }
277
278
279
class LiveActionAPI(BaseAPI):
280
    """The system entity that represents the execution of a Stack Action/Automation
281
    in the system.
282
    """
283
284
    model = LiveActionDB
285
    schema = {
286
        "title": "liveaction",
287
        "description": "An execution of an action.",
288
        "type": "object",
289
        "properties": {
290
            "id": {
291
                "description": "The unique identifier for the action execution.",
292
                "type": "string"
293
            },
294
            "status": {
295
                "description": "The current status of the action execution.",
296
                "type": "string",
297
                "enum": LIVEACTION_STATUSES
298
            },
299
            "start_timestamp": {
300
                "description": "The start time when the action is executed.",
301
                "type": "string",
302
                "pattern": isotime.ISO8601_UTC_REGEX
303
            },
304
            "end_timestamp": {
305
                "description": "The timestamp when the action has finished.",
306
                "type": "string",
307
                "pattern": isotime.ISO8601_UTC_REGEX
308
            },
309
            "action": {
310
                "description": "Reference to the action to be executed.",
311
                "type": "string",
312
                "required": True
313
            },
314
            "parameters": {
315
                "description": "Input parameters for the action.",
316
                "type": "object",
317
                "patternProperties": {
318
                    "^\w+$": {
0 ignored issues
show
Bug introduced by
A suspicious escape sequence \w was found. Did you maybe forget to add an r prefix?

Escape sequences in Python are generally interpreted according to rules similar to standard C. Only if strings are prefixed with r or R are they interpreted as regular expressions.

The escape sequence that was used indicates that you might have intended to write a regular expression.

Learn more about the available escape sequences. in the Python documentation.

Loading history...
319
                        "anyOf": [
320
                            {"type": "array"},
321
                            {"type": "boolean"},
322
                            {"type": "integer"},
323
                            {"type": "number"},
324
                            {"type": "object"},
325
                            {"type": "string"},
326
                            {"type": "null"}
327
                        ]
328
                    }
329
                }
330
            },
331
            "result": {
332
                "anyOf": [{"type": "array"},
333
                          {"type": "boolean"},
334
                          {"type": "integer"},
335
                          {"type": "number"},
336
                          {"type": "object"},
337
                          {"type": "string"}]
338
            },
339
            "context": {
340
                "type": "object"
341
            },
342
            "callback": {
343
                "type": "object"
344
            },
345
            "runner_info": {
346
                "type": "object"
347
            },
348
            "notify": {
349
                "description": "Notification settings for liveaction.",
350
                "type": "object",
351
                "properties": {
352
                    "on-complete": NotificationSubSchemaAPI,
353
                    "on-failure": NotificationSubSchemaAPI,
354
                    "on-success": NotificationSubSchemaAPI
355
                },
356
                "additionalProperties": False
357
            }
358
        },
359
        "additionalProperties": False
360
    }
361
362
    @classmethod
363
    def from_model(cls, model, mask_secrets=False):
364
        doc = super(cls, cls)._from_model(model, mask_secrets=mask_secrets)
365
        if model.start_timestamp:
366
            doc['start_timestamp'] = isotime.format(model.start_timestamp, offset=False)
367
        if model.end_timestamp:
368
            doc['end_timestamp'] = isotime.format(model.end_timestamp, offset=False)
369
370
        if getattr(model, 'notify', None):
371
            doc['notify'] = NotificationsHelper.from_model(model.notify)
372
373
        return cls(**doc)
374
375
    @classmethod
376
    def to_model(cls, live_action):
377
        name = getattr(live_action, 'name', None)
378
        description = getattr(live_action, 'description', None)
379
        action = live_action.action
380
381
        if getattr(live_action, 'start_timestamp', None):
382
            start_timestamp = isotime.parse(live_action.start_timestamp)
383
        else:
384
            start_timestamp = None
385
386
        if getattr(live_action, 'end_timestamp', None):
387
            end_timestamp = isotime.parse(live_action.end_timestamp)
388
        else:
389
            end_timestamp = None
390
391
        status = getattr(live_action, 'status', None)
392
        parameters = getattr(live_action, 'parameters', dict())
393
        context = getattr(live_action, 'context', dict())
394
        callback = getattr(live_action, 'callback', dict())
395
        result = getattr(live_action, 'result', None)
396
397
        if getattr(live_action, 'notify', None):
398
            notify = NotificationsHelper.to_model(live_action.notify)
399
        else:
400
            notify = None
401
402
        model = cls.model(name=name, description=description, action=action,
403
                          start_timestamp=start_timestamp, end_timestamp=end_timestamp,
404
                          status=status, parameters=parameters, context=context,
405
                          callback=callback, result=result, notify=notify)
406
407
        return model
408
409
410
class ActionExecutionStateAPI(BaseAPI):
411
    """
412
    System entity that represents state of an action in the system.
413
    This is used only in tests for now.
414
    """
415
    model = ActionExecutionStateDB
416
    schema = {
417
        "title": "ActionExecutionState",
418
        "description": "Execution state of an action.",
419
        "type": "object",
420
        "properties": {
421
            "id": {
422
                "description": "The unique identifier for the action execution state.",
423
                "type": "string"
424
            },
425
            "execution_id": {
426
                "type": "string",
427
                "description": "ID of the action execution.",
428
                "required": True
429
            },
430
            "query_context": {
431
                "type": "object",
432
                "description": "query context to be used by querier.",
433
                "required": True
434
            },
435
            "query_module": {
436
                "type": "string",
437
                "description": "Name of the query module.",
438
                "required": True
439
            }
440
        },
441
        "additionalProperties": False
442
    }
443
444
    @classmethod
445
    def to_model(cls, state):
446
        execution_id = state.execution_id
447
        query_module = state.query_module
448
        query_context = state.query_context
449
450
        model = cls.model(execution_id=execution_id, query_module=query_module,
451
                          query_context=query_context)
452
        return model
453
454
455
class ActionAliasAPI(BaseAPI, APIUIDMixin):
456
    """
457
    Alias for an action in the system.
458
    """
459
    model = ActionAliasDB
460
    schema = {
461
        "title": "ActionAlias",
462
        "description": "Alias for an action.",
463
        "type": "object",
464
        "properties": {
465
            "id": {
466
                "description": "The unique identifier for the action alias.",
467
                "type": "string"
468
            },
469
            "ref": {
470
                "description": "System computed user friendly reference for the alias. \
471
                                Provided value will be overridden by computed value.",
472
                "type": "string"
473
            },
474
            "uid": {
475
                "type": "string"
476
            },
477
            "name": {
478
                "type": "string",
479
                "description": "Name of the action alias.",
480
                "required": True
481
            },
482
            "pack": {
483
                "description": "The content pack this actionalias belongs to.",
484
                "type": "string",
485
                "required": True
486
            },
487
            "description": {
488
                "type": "string",
489
                "description": "Description of the action alias.",
490
                "default": None
491
            },
492
            "enabled": {
493
                "description": "Flag indicating of action alias is enabled.",
494
                "type": "boolean",
495
                "default": True
496
            },
497
            "action_ref": {
498
                "type": "string",
499
                "description": "Reference to the aliased action.",
500
                "required": True
501
            },
502
            "formats": {
503
                "type": "array",
504
                "items": {
505
                    "anyOf": [
506
                        {"type": "string"},
507
                        {
508
                            "type": "object",
509
                            "properties": {
510
                                "display": {"type": "string"},
511
                                "representation": {
512
                                    "type": "array",
513
                                    "items": {"type": "string"}
514
                                }
515
                            }
516
                        }
517
                    ]
518
                },
519
                "description": "Possible parameter format."
520
            },
521
            "ack": {
522
                "type": "object",
523
                "properties": {
524
                    "enabled": {"type": "boolean"},
525
                    "format": {"type": "string"},
526
                    "append_url": {"type": "boolean"}
527
                },
528
                "description": "Acknowledgement message format."
529
            },
530
            "result": {
531
                "type": "object",
532
                "properties": {
533
                    "enabled": {"type": "boolean"},
534
                    "format": {"type": "string"}
535
                },
536
                "description": "Execution message format."
537
            }
538
        },
539
        "additionalProperties": False
540
    }
541
542
    @classmethod
543
    def to_model(cls, alias):
544
        name = alias.name
545
        description = getattr(alias, 'description', None)
546
        pack = alias.pack
547
        ref = ResourceReference.to_string_reference(pack=pack, name=name)
548
        enabled = getattr(alias, 'enabled', True)
549
        action_ref = alias.action_ref
550
        formats = alias.formats
551
        ack = getattr(alias, 'ack', None)
552
        result = getattr(alias, 'result', None)
553
554
        model = cls.model(name=name, description=description, pack=pack, ref=ref, enabled=enabled,
555
                          action_ref=action_ref, formats=formats, ack=ack, result=result)
556
        return model
557
558
559
class AliasExecutionAPI(BaseAPI):
560
    """
561
    Alias for an action in the system.
562
    """
563
    model = None
564
    schema = {
565
        "title": "AliasExecution",
566
        "description": "Execution of an ActionAlias.",
567
        "type": "object",
568
        "properties": {
569
            "name": {
570
                "type": "string",
571
                "description": "Name of the action alias which matched.",
572
                "required": True
573
            },
574
            "format": {
575
                "type": "string",
576
                "description": "Format string which matched.",
577
                "required": True
578
            },
579
            "command": {
580
                "type": "string",
581
                "description": "Command used in chat.",
582
                "required": True
583
            },
584
            "user": {
585
                "type": "string",
586
                "description": "User that requested the execution.",
587
                "default": "channel"  # TODO: This value doesnt get set
588
            },
589
            "source_channel": {
590
                "type": "string",
591
                "description": "Channel from which the execution was requested. This is not the \
592
                                channel as defined by the notification system.",
593
                "required": True
594
            },
595
            "notification_channel": {
596
                "type": "string",
597
                "description": "StackStorm notification channel to use to respond.",
598
                "required": False
599
            },
600
            "notification_route": {
601
                "type": "string",
602
                "description": "StackStorm notification route to use to respond.",
603
                "required": False
604
            }
605
        },
606
        "additionalProperties": False
607
    }
608
609
    @classmethod
610
    def to_model(cls, aliasexecution):
611
        # probably should be unsupported
612
        raise NotImplementedError()
613
614
    @classmethod
615
    def from_model(cls, aliasexecution):
0 ignored issues
show
Bug introduced by
Arguments number differs from overridden 'from_model' method
Loading history...
616
        raise NotImplementedError()
617