|
| 1 | +import os |
| 2 | + |
| 3 | +import six |
| 4 | +import jsonschema |
| 5 | +from oslo.config import cfg |
| 6 | + |
| 7 | +from st2common.util import jsonify |
| 8 | + |
| 9 | + |
| 10 | +# https://github.com/json-schema/json-schema/blob/master/draft-04/schema |
| 11 | +# The source material is licensed under the AFL or BSD license. |
| 12 | +PATH = os.path.join(os.path.dirname(os.path.realpath(__file__))) |
| 13 | +SCHEMA_DRAFT4 = jsonify.load_file('%s/draft4.json' % PATH) |
| 14 | +SCHEMA_ACTION_PARAMS = jsonify.load_file('%s/action_params.json' % PATH) |
| 15 | + |
| 16 | +SCHEMA_ANY_TYPE = { |
| 17 | + "anyOf": [ |
| 18 | + {"type": "array"}, |
| 19 | + {"type": "boolean"}, |
| 20 | + {"type": "integer"}, |
| 21 | + {"type": "number"}, |
| 22 | + {"type": "object"}, |
| 23 | + {"type": "string"} |
| 24 | + ] |
| 25 | +} |
| 26 | + |
| 27 | + |
| 28 | +def get_standard_draft_schema(): |
| 29 | + return SCHEMA_DRAFT4 |
| 30 | + |
| 31 | + |
| 32 | +def get_action_params_schema(): |
| 33 | + return SCHEMA_ACTION_PARAMS |
| 34 | + |
| 35 | + |
| 36 | +def extend_with_default(validator_class): |
| 37 | + validate_properties = validator_class.VALIDATORS["properties"] |
| 38 | + |
| 39 | + def set_defaults(validator, properties, instance, schema): |
| 40 | + for error in validate_properties( |
| 41 | + validator, properties, instance, schema, |
| 42 | + ): |
| 43 | + yield error |
| 44 | + |
| 45 | + for property, subschema in six.iteritems(properties): |
| 46 | + if "default" in subschema: |
| 47 | + instance.setdefault(property, subschema["default"]) |
| 48 | + |
| 49 | + return jsonschema.validators.extend( |
| 50 | + validator_class, {"properties": set_defaults}, |
| 51 | + ) |
| 52 | + |
| 53 | + |
| 54 | +def get_validator(assign_property_default=False): |
| 55 | + validator = jsonschema.Draft4Validator |
| 56 | + return extend_with_default(validator) if assign_property_default else validator |
| 57 | + |
| 58 | + |
| 59 | +def get_parameter_schema(model): |
| 60 | + # Dynamically construct JSON schema from the parameters metadata. |
| 61 | + schema = {"$schema": cfg.CONF.schema.draft} |
| 62 | + from st2common.util.action_db import get_runnertype_by_name |
| 63 | + runner_type = get_runnertype_by_name(model.runner_type['name']) |
| 64 | + # Any 'required' runner parameter which is provided in the action is no longer |
| 65 | + # considered 'required' by the runner. The action could choose to keep it |
| 66 | + # 'required' but will have to explicitly call it out. |
| 67 | + runner_required_parameters = [p for p in runner_type.required_parameters |
| 68 | + if p not in model.parameters] |
| 69 | + required = list(set(runner_required_parameters + model.required_parameters)) |
| 70 | + normalize = lambda x: {k: v if v else SCHEMA_ANY_TYPE for k, v in six.iteritems(x)} |
| 71 | + properties = normalize(runner_type.runner_parameters) |
| 72 | + properties.update(normalize(model.parameters)) |
| 73 | + if properties: |
| 74 | + schema['title'] = model.name |
| 75 | + if model.description: |
| 76 | + schema['description'] = model.description |
| 77 | + schema['type'] = 'object' |
| 78 | + schema['properties'] = properties |
| 79 | + if required: |
| 80 | + schema['required'] = required |
| 81 | + schema['additionalProperties'] = False |
| 82 | + return schema |
0 commit comments