Exemple #1
0
def test_all_args(mocker):
    logger = mocker.Mock()
    resource = mocker.Mock()
    event = mocker.Mock()
    body = mocker.Mock()
    patch = mocker.Mock()
    diff = mocker.Mock()
    old = mocker.Mock()
    new = mocker.Mock()
    cause = Cause(
        resource=resource,
        logger=logger,
        event=event,
        body=body,
        patch=patch,
        diff=diff,
        old=old,
        new=new,
    )
    assert cause.resource is resource
    assert cause.logger is logger
    assert cause.event is event
    assert cause.body is body
    assert cause.patch is patch
    assert cause.diff is diff
    assert cause.old is old
    assert cause.new is new
Exemple #2
0
    def new_detect_fn(**kwargs):

        # Avoid collision of our mocked values with the passed kwargs.
        original_event = kwargs.pop('event', None)
        original_body = kwargs.pop('body', None)
        original_diff = kwargs.pop('diff', None)
        event = mock.event if mock.event is not None else original_event
        initial = bool(event == RESUME)
        body = copy.deepcopy(
            mock.body) if mock.body is not None else original_body
        diff = copy.deepcopy(
            mock.diff) if mock.diff is not None else original_diff

        # Pass through kwargs: resource, logger, patch, diff, old, new.
        # I.e. everything except what we mock: event & body.
        cause = Cause(event=event,
                      initial=initial,
                      body=body,
                      diff=diff,
                      **kwargs)

        # Needed for the k8s-event creation, as they are attached to objects.
        body.setdefault('apiVersion', f'{resource.group}/{resource.version}')
        body.setdefault('kind', 'KopfExample')  # TODO: resource.???
        body.setdefault('metadata', {}).setdefault('namespace',
                                                   'some-namespace')
        body.setdefault('metadata', {}).setdefault('name', 'some-name')
        body.setdefault('metadata', {}).setdefault('uid', 'some-uid')

        return cause
Exemple #3
0
def test_required_args(mocker):
    logger = mocker.Mock()
    resource = mocker.Mock()
    event = mocker.Mock()
    initial = mocker.Mock()
    body = mocker.Mock()
    patch = mocker.Mock()
    digest = mocker.Mock()
    cause = Cause(
        resource=resource,
        logger=logger,
        event=event,
        initial=initial,
        body=body,
        patch=patch,
        digest=digest,
    )
    assert cause.resource is resource
    assert cause.logger is logger
    assert cause.event is event
    assert cause.initial is initial
    assert cause.body is body
    assert cause.patch is patch
    assert cause.digest is digest
    assert cause.diff is None
    assert cause.old is None
    assert cause.new is None
Exemple #4
0
async def _call_handler(handler: registries.Handler, *args,
                        cause: causation.Cause, lifecycle: Callable, **kwargs):
    """
    Invoke one handler only, according to the calling conventions.

    Specifically, calculate the handler-specific fields (e.g. field diffs).

    Ensure the global context for this asyncio task is set to the handler and
    its cause -- for proper population of the sub-handlers via the decorators
    (see `@kopf.on.this`).
    """

    # For the field-handlers, the old/new/diff values must match the field, not the whole object.
    old = cause.old if handler.field is None else dicts.resolve(
        cause.old, handler.field, None)
    new = cause.new if handler.field is None else dicts.resolve(
        cause.new, handler.field, None)
    diff = cause.diff if handler.field is None else diffs.reduce(
        cause.diff, handler.field)
    cause = cause._replace(old=old, new=new, diff=diff)

    # Store the context of the current resource-object-event-handler, to be used in `@kopf.on.this`,
    # and maybe other places, and consumed in the recursive `execute()` calls for the children.
    # This replaces the multiple kwargs passing through the whole call stack (easy to forget).
    sublifecycle_token = sublifecycle_var.set(lifecycle)
    subregistry_token = subregistry_var.set(
        registries.SimpleRegistry(prefix=handler.id))
    subexecuted_token = subexecuted_var.set(False)
    handler_token = handler_var.set(handler)
    cause_token = cause_var.set(cause)

    # And call it. If the sub-handlers are not called explicitly, run them implicitly
    # as if it was done inside of the handler (i.e. under try-finally block).
    try:
        result = await invocation.invoke(
            handler.fn,
            *args,
            cause=cause,
            **kwargs,
        )

        if not subexecuted_var.get():
            await execute()

        return result

    finally:
        # Reset the context to the parent's context, or to nothing (if already in a root handler).
        sublifecycle_var.reset(sublifecycle_token)
        subregistry_var.reset(subregistry_token)
        subexecuted_var.reset(subexecuted_token)
        handler_var.reset(handler_token)
        cause_var.reset(cause_token)
Exemple #5
0
def test_no_args():
    with pytest.raises(TypeError):
        Cause()