Beispiel #1
0
def get_controller(wf_ex, wf_spec=None):
    """Gets a workflow controller instance by given workflow execution object.

    :param wf_ex: Workflow execution object.
    :param wf_spec: Workflow specification object. If passed, the method works
        faster.
    :returns: Workflow controller class.
    """

    if not wf_spec:
        wf_spec = spec_parser.get_workflow_spec_by_execution_id(wf_ex.id)

    wf_type = wf_spec.get_type()

    ctrl_cls = None

    for cls in u.iter_subclasses(WorkflowController):
        if cls.__workflow_type__ == wf_type:
            ctrl_cls = cls
            break

    if not ctrl_cls:
        raise exc.MistralError(
            'Failed to find a workflow controller [type=%s]' % wf_type)

    return ctrl_cls(wf_ex, wf_spec)
Beispiel #2
0
def register_secure_model_hooks():
    # Make sure 'project_id' is always properly set.
    for sec_model_class in utils.iter_subclasses(MistralSecureModelBase):
        if '__abstract__' not in sec_model_class.__dict__:
            event.listen(sec_model_class.project_id,
                         'set',
                         _set_project_id,
                         retval=True)
Beispiel #3
0
def register_name_validator():
    """Register an event listener on the attribute.

    This event listener will validate that name of object does not
    contains spaces every time a 'set' occurs.
    """
    for cls in utils.iter_subclasses(Definition):
        event.listen(getattr(cls, "name"), 'set',
                     lambda t, v, o, i: validate_name_has_no_spaces(v))
Beispiel #4
0
def register_length_validator(attr_name):
    """Register an event listener on the attribute.

    This event listener will validate the size every
    time a 'set' occurs.
    """
    for cls in utils.iter_subclasses(Execution):
        if hasattr(cls, attr_name):
            event.listen(
                getattr(cls, attr_name), 'set',
                lambda t, v, o, i: validate_long_type_length(
                    cls, attr_name, v))
Beispiel #5
0
    def test_itersubclasses(self):
        class A(object):
            pass

        class B(A):
            pass

        class C(A):
            pass

        class D(C):
            pass

        self.assertEqual([B, C, D], list(utils.iter_subclasses(A)))
Beispiel #6
0
def instantiate_spec(spec_cls, data, validate=False):
    """Instantiates specification accounting for specification hierarchies.

    :param spec_cls: Specification concrete or base class. In case if base
        class or the hierarchy is provided this method relies on attributes
        _polymorphic_key and _polymorphic_value in order to find a concrete
        class that needs to be instantiated.
    :param data: Raw specification data as a dictionary.
    :type data: dict
    :param validate: If it's False then semantics and schema validation
        will be skipped.
    :type validate: bool
    """

    if issubclass(spec_cls, BaseSpecList):
        # Ignore polymorphic search for specification lists because
        # it doesn't make sense for them.
        return spec_cls(data, validate)

    if not hasattr(spec_cls, '_polymorphic_key'):
        spec = spec_cls(data, validate)

        if validate:
            spec.validate_semantics()

        return spec

    # In order to do polymorphic search we need to make sure that
    # a spec is backed by a dictionary. Otherwise we can't extract
    # a polymorphic key.
    if not isinstance(data, dict):
        raise exc.InvalidModelException(
            "A specification with polymorphic key must be backed by"
            " a dictionary [spec_cls=%s, data=%s]" % (spec_cls, data)
        )

    key = spec_cls._polymorphic_key

    if not isinstance(key, tuple):
        key_name = key
        key_default = None
    else:
        key_name = key[0]
        key_default = key[1]

    polymorphic_val = data.get(key_name, key_default)

    global _POLYMORPHIC_CACHE

    cache_key = (spec_cls, polymorphic_val)

    concrete_spec_cls = _POLYMORPHIC_CACHE.get(cache_key)

    if concrete_spec_cls is None:
        for cls in utils.iter_subclasses(spec_cls):
            if not hasattr(cls, '_polymorphic_value'):
                raise exc.DSLParsingException(
                    "Class '%s' is expected to have attribute"
                    " '_polymorphic_value' because it's a part of"
                    " specification hierarchy inherited "
                    "from class '%s'." % (cls, spec_cls)
                )

            if cls._polymorphic_value == polymorphic_val:
                concrete_spec_cls = cls

                _POLYMORPHIC_CACHE[cache_key] = concrete_spec_cls

    if concrete_spec_cls is None:
        raise exc.DSLParsingException(
            'Failed to find a specification class to instantiate '
            '[spec_cls=%s, data=%s]' % (spec_cls, data)
        )

    spec = concrete_spec_cls(data, validate)

    if validate:
        spec.validate_semantics()

    return spec
Beispiel #7
0
    @property
    def executions(self):
        return (self.action_executions
                if not self.spec.get('workflow') else self.workflow_executions)

    def to_dict(self):
        d = super(TaskExecution, self).to_dict()

        utils.datetime_to_str_in_dict(d, 'started_at')
        utils.datetime_to_str_in_dict(d, 'finished_at')

        return d


for cls in utils.iter_subclasses(Execution):
    event.listen(
        # Catch and trim Execution.state_info to always fit allocated size.
        # Note that the limit is 65500 which is less than 65535 (2^16 -1).
        # The reason is that utils.cut() is not exactly accurate in case if
        # the value is not a string, but, for example, a dictionary. If we
        # limit it exactly to 65535 then once in a while it may go slightly
        # beyond the allowed maximum size. It may depend on the order of
        # keys in a string representation and other things that are hidden
        # inside utils.cut_dict() method.
        cls.state_info,
        'set',
        lambda t, v, o, i: utils.cut(v, 65500),
        retval=True)

# Many-to-one for 'ActionExecution' and 'TaskExecution'.