def owner(request, resource):
    body = Body(copy.deepcopy(OWNER))
    if request.param == 'state-changing-cause':
        cause = ChangingCause(
            logger=logging.getLogger('kopf.test.fake.logger'),
            indices=OperatorIndexers().indices,
            resource=resource,
            patch=Patch(),
            memo=Memo(),
            body=body,
            initial=False,
            reason=Reason.NOOP,
        )
        with context([(cause_var, cause)]):
            yield body
    elif request.param == 'event-watching-cause':
        cause = WatchingCause(
            logger=logging.getLogger('kopf.test.fake.logger'),
            indices=OperatorIndexers().indices,
            resource=resource,
            patch=Patch(),
            memo=Memo(),
            body=body,
            type='irrelevant',
            event=RawEvent(type='irrelevant', object=OWNER),
        )
        with context([(cause_var, cause)]):
            yield body
    else:
        raise RuntimeError(f"Wrong param for `owner` fixture: {request.param!r}")
Esempio n. 2
0
def test_with_parent(parent_handler, resource_registry_cls, cause_factory):

    cause = cause_factory(resource_registry_cls)
    registry = resource_registry_cls()

    with context([(handler_var, parent_handler), (subregistry_var, registry)]):
        kopf.subhandler()(child_fn)

    handlers = registry.get_handlers(cause)
    assert len(handlers) == 1
    assert handlers[0].fn is child_fn
    assert handlers[0].id == 'parent_fn/child_fn'
Esempio n. 3
0
async def subhandling_context() -> AsyncIterator[None]:
    with invocation.context([
        (subregistry_var, registries.ChangingRegistry()),
        (subexecuted_var, False),
    ]):
        # Go for normal handler invocation.
        yield

        # If the sub-handlers are not called explicitly, run them implicitly
        # as if it was done inside of the handler (still under the try-finally clause).
        if not subexecuted_var.get():
            await execute()
Esempio n. 4
0
def test_invalid_oldnew_for_inappropriate_subhandlers(resource, decorator,
                                                      registry):
    @decorator(*resource)
    def fn(**_):
        @kopf.subhandler(field='f', old='x')
        def fn2(**_):
            pass

    subregistry = ChangingRegistry()
    handler = registry._changing.get_all_handlers()[0]
    with context([(handler_var, handler), (subregistry_var, subregistry)]):
        with pytest.raises(TypeError,
                           match="can only be used in update handlers"):
            handler.fn()
Esempio n. 5
0
async def invoke_handler(
        *,
        handler: Handler,
        cause: Cause,
        retry: int,
        started: datetime.datetime,
        runtime: datetime.timedelta,
        settings: configuration.OperatorSettings,
        lifecycle: Optional[LifeCycleFn],
        subrefs: Set[ids.HandlerId],
        extra_context: ExtraContext,
) -> Optional[Result]:
    """
    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.subhandler`).
    """

    # For the field-handlers, the old/new/diff values must match the field, not the whole object.
    cause = handler.adjust_cause(cause)

    # The context makes it possible and easy to pass the kwargs _through_ the user-space handlers:
    # from the framework to the framework's helper functions (e.g. sub-handling, hierarchies, etc).
    with invocation.context([
        (sublifecycle_var, lifecycle),
        (subsettings_var, settings),
        (subrefs_var, list(subrefs_var.get([])) + [subrefs]),
        (handler_var, handler),
        (cause_var, cause),
    ]):
        async with extra_context():
            result = await invocation.invoke(
                handler.fn,
                settings=settings,
                kwargsrc=cause,
                kwargs=dict(
                    param=handler.param,
                    retry=retry,
                    started=started,
                    runtime=runtime,
                ),
            )

            # Since we know that we invoked the handler, we cast "any" result to a handler result.
            return Result(result)
Esempio n. 6
0
def test_subhandler_imperatively(parent_handler, cause_factory):
    cause = cause_factory(reason=Reason.UPDATE)

    registry = ChangingRegistry()
    subregistry_var.set(registry)

    def fn(**_):
        pass

    with context([(handler_var, parent_handler)]):
        kopf.register(fn)

    handlers = registry.get_handlers(cause)
    assert len(handlers) == 1
    assert handlers[0].fn is fn