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.2.1 ( 2317c4 )
by
unknown
05:42
created

PackAPI.__init__()   B

Complexity

Conditions 4

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
dl 0
loc 22
rs 8.9197
c 1
b 0
f 0
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 os
17
18
import jsonschema
19
from oslo_config import cfg
20
21
from st2common import log as logging
22
from st2common.util import schema as util_schema
23
from st2common.constants.keyvalue import SYSTEM_SCOPE
24
from st2common.constants.keyvalue import USER_SCOPE
25
from st2common.constants.pack import PACK_REF_WHITELIST_REGEX
26
from st2common.constants.pack import PACK_VERSION_REGEX
27
from st2common.constants.pack import ST2_VERSION_REGEX
28
from st2common.constants.pack import NORMALIZE_PACK_VERSION
29
from st2common.persistence.pack import ConfigSchema
30
from st2common.models.api.base import BaseAPI
31
from st2common.models.db.pack import PackDB
32
from st2common.models.db.pack import ConfigSchemaDB
33
from st2common.models.db.pack import ConfigDB
34
from st2common.exceptions.db import StackStormDBObjectNotFoundError
35
from st2common.util.pack import validate_config_against_schema
36
from st2common.util.pack import normalize_pack_version
37
38
__all__ = [
39
    'PackAPI',
40
    'ConfigSchemaAPI',
41
    'ConfigAPI',
42
43
    'ConfigItemSetAPI',
44
45
    'PackInstallRequestAPI',
46
    'PackRegisterRequestAPI',
47
    'PackSearchRequestAPI',
48
    'PackAsyncAPI'
49
]
50
51
LOG = logging.getLogger(__name__)
52
53
54
class PackAPI(BaseAPI):
55
    model = PackDB
56
    schema = {
57
        'type': 'object',
58
        'description': 'Content pack schema.',
59
        'properties': {
60
            'id': {
61
                'type': 'string',
62
                'description': 'Unique identifier for the pack.',
63
                'default': None
64
            },
65
            'name': {
66
                'type': 'string',
67
                'description': 'Display name of the pack. If the name only contains lowercase'
68
                               'letters, digits and underscores, the "ref" field is not required.',
69
                'required': True
70
            },
71
            'ref': {
72
                'type': 'string',
73
                'description': 'Reference for the pack, used as an internal id.',
74
                'default': None,
75
                'pattern': PACK_REF_WHITELIST_REGEX
76
            },
77
            'uid': {
78
                'type': 'string'
79
            },
80
            'description': {
81
                'type': 'string',
82
                'description': 'Brief description of the pack and the service it integrates with.',
83
                'required': True
84
            },
85
            'keywords': {
86
                'type': 'array',
87
                'description': 'Keywords describing the pack.',
88
                'items': {'type': 'string'},
89
                'default': []
90
            },
91
            'version': {
92
                'type': 'string',
93
                'description': 'Pack version. Must follow the semver format '
94
                               '(for instance, "0.1.0").',
95
                'pattern': PACK_VERSION_REGEX,
96
                'required': True
97
            },
98
            'stackstorm_version': {
99
                'type': 'string',
100
                'description': 'Required StackStorm version. Examples: ">1.6.0", '
101
                               '">=1.8.0, <2.2.0"',
102
                'pattern': ST2_VERSION_REGEX,
103
            },
104
            'author': {
105
                'type': 'string',
106
                'description': 'Pack author or authors.',
107
                'required': True
108
            },
109
            'email': {
110
                'type': 'string',
111
                'description': 'E-mail of the pack author.',
112
                'format': 'email'
113
            },
114
            'contributors': {
115
                'type': 'array',
116
                'items': {
117
                    'type': 'string',
118
                    'maxLength': 100
119
                },
120
                'description': ('A list of people who have contributed to the pack. Format is: '
121
                                'Name <email address> e.g. Tomaz Muraus <[email protected]>.')
122
            },
123
            'files': {
124
                'type': 'array',
125
                'description': 'A list of files inside the pack.',
126
                'items': {'type': 'string'},
127
                'default': []
128
            },
129
            'dependencies': {
130
                'type': 'array',
131
                'description': 'A list of other StackStorm packs this pack depends upon. '
132
                               'The same format as in "st2 pack install" is used: '
133
                               '"<name or full URL>[=<version or git ref>]".',
134
                'items': {'type': 'string'},
135
                'default': []
136
            },
137
            'system': {
138
                'type': 'object',
139
                'description': 'Specification for the system components and packages '
140
                               'required for the pack.',
141
                'default': {}
142
            }
143
        }
144
    }
145
146
    def __init__(self, **values):
147
        name = values.get('name', None)
148
149
        # Note: If some version values are not explicitly surrounded by quotes they are recognized
150
        # as numbers so we cast them to string
151
        if values.get('version', None):
152
            values['version'] = str(values['version'])
153
154
        # Special case for old version which didn't follow semver format (e.g. 0.1, 1.0, etc.)
155
        # In case the version doesn't match that format, we simply append ".0" to the end (e.g.
156
        # 0.1 -> 0.1.0, 1.0, -> 1.0.0, etc.)
157
        if NORMALIZE_PACK_VERSION:
158
            new_version = normalize_pack_version(version=values['version'])
159
            if new_version != values['version']:
160
                LOG.warning('Pack "%s" contains invalid semver version specifer, casting it to a '
0 ignored issues
show
Coding Style Best Practice introduced by
Specify string format arguments as logging function parameters
Loading history...
161
                            'full semver version specifier (%s -> %s).\n'
162
                            'Short versions will become INVALID in StackStorm 2.2, and the pack '
163
                            'will stop working. Update the pack version in "pack.yaml".'
164
                            % (name, values['version'], new_version))
165
            values['version'] = new_version
166
167
        super(PackAPI, self).__init__(**values)
168
169
    def validate(self):
170
        # We wrap default validate() implementation and throw a more user-friendly exception in
171
        # case pack version doesn't follow a valid semver format and other errors
172
        try:
173
            super(PackAPI, self).validate()
174
        except jsonschema.ValidationError as e:
175
            msg = str(e)
176
177
            # Invalid version
178
            if "Failed validating 'pattern' in schema['properties']['version']" in msg:
179
                new_msg = ('Pack version "%s" doesn\'t follow a valid semver format. Valid '
180
                           'versions and formats include: 0.1.0, 0.2.1, 1.1.0, etc.' %
181
                           (self.version))
182
                new_msg += '\n\n' + msg
183
                raise jsonschema.ValidationError(new_msg)
184
185
            # Invalid ref / name
186
            if "Failed validating 'pattern' in schema['properties']['ref']" in msg:
187
                new_msg = ('Pack ref / name can only contain valid word characters (a-z, 0-9 and '
188
                           '_), dashes are not allowed.')
189
                new_msg += '\n\n' + msg
190
                raise jsonschema.ValidationError(new_msg)
191
192
            raise e
193
194
    @classmethod
195
    def to_model(cls, pack):
196
        ref = pack.ref
197
        name = pack.name
198
        description = pack.description
199
        keywords = getattr(pack, 'keywords', [])
200
        version = str(pack.version)
201
202
        stackstorm_version = getattr(pack, 'stackstorm_version', None)
203
        author = pack.author
204
        email = pack.email
205
        contributors = getattr(pack, 'contributors', [])
206
        files = getattr(pack, 'files', [])
207
        dependencies = getattr(pack, 'dependencies', [])
208
        system = getattr(pack, 'system', {})
209
210
        model = cls.model(ref=ref, name=name, description=description, keywords=keywords,
211
                          version=version, author=author, email=email, contributors=contributors,
212
                          files=files, dependencies=dependencies, system=system,
213
                          stackstorm_version=stackstorm_version)
214
        return model
215
216
217
class ConfigSchemaAPI(BaseAPI):
218
    model = ConfigSchemaDB
219
    schema = {
220
        "title": "ConfigSchema",
221
        "description": "Pack config schema.",
222
        "type": "object",
223
        "properties": {
224
            "id": {
225
                "description": "The unique identifier for the config schema.",
226
                "type": "string"
227
            },
228
            "pack": {
229
                "description": "The content pack this config schema belongs to.",
230
                "type": "string"
231
            },
232
            "attributes": {
233
                "description": "Config schema attributes.",
234
                "type": "object",
235
                "patternProperties": {
236
                    "^\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...
237
                },
238
                'additionalProperties': False,
239
                "default": {}
240
            }
241
        },
242
        "additionalProperties": False
243
    }
244
245
    @classmethod
246
    def to_model(cls, config_schema):
247
        pack = config_schema.pack
248
        attributes = config_schema.attributes
249
250
        model = cls.model(pack=pack, attributes=attributes)
251
        return model
252
253
254
class ConfigAPI(BaseAPI):
255
    model = ConfigDB
256
    schema = {
257
        "title": "Config",
258
        "description": "Pack config.",
259
        "type": "object",
260
        "properties": {
261
            "id": {
262
                "description": "The unique identifier for the config.",
263
                "type": "string"
264
            },
265
            "pack": {
266
                "description": "The content pack this config belongs to.",
267
                "type": "string"
268
            },
269
            "values": {
270
                "description": "Config values.",
271
                "type": "object",
272
                "default": {}
273
            }
274
        },
275
        "additionalProperties": False
276
    }
277
278
    def validate(self, validate_against_schema=False):
0 ignored issues
show
Bug introduced by
Arguments number differs from overridden 'validate' method
Loading history...
279
        # Perform base API model validation against json schema
280
        result = super(ConfigAPI, self).validate()
281
282
        # Perform config values validation against the config values schema
283
        if validate_against_schema:
284
            cleaned_values = self._validate_config_values_against_schema()
285
            result.values = cleaned_values
286
287
        return result
288
289
    def _validate_config_values_against_schema(self):
290
        try:
291
            config_schema_db = ConfigSchema.get_by_pack(value=self.pack)
292
        except StackStormDBObjectNotFoundError:
293
            # Config schema is optional
294
            return
295
296
        # Note: We are doing optional validation so for now, we do allow additional properties
297
        instance = self.values or {}
298
        schema = config_schema_db.attributes
299
300
        configs_path = os.path.join(cfg.CONF.system.base_path, 'configs/')
301
        config_path = os.path.join(configs_path, '%s.yaml' % (self.pack))
302
303
        cleaned = validate_config_against_schema(config_schema=schema,
304
                                                 config_object=instance,
305
                                                 config_path=config_path,
306
                                                 pack_name=self.pack)
307
308
        return cleaned
309
310
    @classmethod
311
    def to_model(cls, config):
312
        pack = config.pack
313
        values = config.values
314
315
        model = cls.model(pack=pack, values=values)
316
        return model
317
318
319
class ConfigUpdateRequestAPI(BaseAPI):
320
    schema = {
321
        "type": "object"
322
    }
323
324
325
class ConfigItemSetAPI(BaseAPI):
326
    """
327
    API class used with the config set API endpoint.
328
    """
329
    model = None
330
    schema = {
331
        "title": "",
332
        "description": "",
333
        "type": "object",
334
        "properties": {
335
            "name": {
336
                "description": "Config item name (key)",
337
                "type": "string",
338
                "required": True
339
            },
340
            "value": {
341
                "description": "Config item value.",
342
                "type": ["string", "number", "boolean", "array", "object"],
343
                "required": True
344
            },
345
            "scope": {
346
                "description": "Config item scope (system / user)",
347
                "type": "string",
348
                "default": SYSTEM_SCOPE,
349
                "enum": [
350
                    SYSTEM_SCOPE,
351
                    USER_SCOPE
352
                ]
353
            },
354
            "user": {
355
                "description": "User for user-scoped items (only available to admins).",
356
                "type": "string",
357
                "required": False,
358
                "default": None
359
            }
360
        },
361
        "additionalProperties": False
362
    }
363
364
365
class PackInstallRequestAPI(BaseAPI):
366
    schema = {
367
        "type": "object",
368
        "properties": {
369
            "packs": {
370
                "type": "array"
371
            },
372
            "force": {
373
                "type": "boolean",
374
                "description": "Force pack installation",
375
                "default": False
376
            }
377
        }
378
    }
379
380
381
class PackRegisterRequestAPI(BaseAPI):
382
    schema = {
383
        "type": "object",
384
        "properties": {
385
            "types": {
386
                "type": "array",
387
                "items": {
388
                    "type": "string"
389
                }
390
            },
391
            "packs": {
392
                "type": "array",
393
                "items": {
394
                    "type": "string"
395
                }
396
            },
397
            "fail_on_failure": {
398
                "type": "boolean",
399
                "description": "True to fail on failure",
400
                "default": True
401
            }
402
        }
403
    }
404
405
406
class PackSearchRequestAPI(BaseAPI):
407
    schema = {
408
        "type": "object",
409
        "oneOf": [
410
            {
411
                "properties": {
412
                    "query": {
413
                        "type": "string",
414
                        "required": True,
415
                    },
416
                },
417
                "additionalProperties": False,
418
            },
419
            {
420
                "properties": {
421
                    "pack": {
422
                        "type": "string",
423
                        "required": True,
424
                    },
425
                },
426
                "additionalProperties": False,
427
            },
428
        ]
429
    }
430
431
432
class PackAsyncAPI(BaseAPI):
433
    schema = {
434
        "type": "object",
435
        "properties": {
436
            "execution_id": {
437
                "type": "string",
438
                "required": True
439
            }
440
        },
441
        "additionalProperties": False
442
    }
443