Skip to content
This repository has been archived by the owner on Sep 14, 2020. It is now read-only.

Commit

Permalink
Merge pull request #315 from nolar/simplify-registries-4
Browse files Browse the repository at this point in the history
Simplify registries: no prefixes, direct sub-registries access
  • Loading branch information
nolar authored Feb 20, 2020
2 parents a45fe91 + 1ad5f29 commit 51a3a70
Show file tree
Hide file tree
Showing 38 changed files with 2,259 additions and 494 deletions.
149 changes: 105 additions & 44 deletions kopf/on.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ def creation_handler(**kwargs):
from kopf.reactor import callbacks
from kopf.reactor import causation
from kopf.reactor import errors as errors_
from kopf.reactor import handlers
from kopf.reactor import handling
from kopf.reactor import registries
from kopf.structs import bodies
from kopf.structs import dicts
from kopf.structs import resources

ResourceHandlerDecorator = Callable[[callbacks.ResourceHandlerFn], callbacks.ResourceHandlerFn]
ActivityHandlerDecorator = Callable[[callbacks.ActivityHandlerFn], callbacks.ActivityHandlerFn]
Expand All @@ -37,12 +39,15 @@ def startup( # lgtm[py/similar-function]
registry: Optional[registries.OperatorRegistry] = None,
) -> ActivityHandlerDecorator:
def decorator(fn: callbacks.ActivityHandlerFn) -> callbacks.ActivityHandlerFn:
actual_registry = registry if registry is not None else registries.get_default_registry()
return actual_registry.register_activity_handler(
fn=fn, id=id,
real_registry = registry if registry is not None else registries.get_default_registry()
real_id = registries.generate_id(fn=fn, id=id)
handler = handlers.ActivityHandler(
fn=fn, id=real_id,
errors=errors, timeout=timeout, retries=retries, backoff=backoff, cooldown=cooldown,
activity=causation.Activity.STARTUP,
)
real_registry.activity_handlers.append(handler)
return fn
return decorator


Expand All @@ -57,12 +62,15 @@ def cleanup( # lgtm[py/similar-function]
registry: Optional[registries.OperatorRegistry] = None,
) -> ActivityHandlerDecorator:
def decorator(fn: callbacks.ActivityHandlerFn) -> callbacks.ActivityHandlerFn:
actual_registry = registry if registry is not None else registries.get_default_registry()
return actual_registry.register_activity_handler(
fn=fn, id=id,
real_registry = registry if registry is not None else registries.get_default_registry()
real_id = registries.generate_id(fn=fn, id=id)
handler = handlers.ActivityHandler(
fn=fn, id=real_id,
errors=errors, timeout=timeout, retries=retries, backoff=backoff, cooldown=cooldown,
activity=causation.Activity.CLEANUP,
)
real_registry.activity_handlers.append(handler)
return fn
return decorator


Expand All @@ -78,12 +86,15 @@ def login( # lgtm[py/similar-function]
) -> ActivityHandlerDecorator:
""" ``@kopf.on.login()`` handler for custom (re-)authentication. """
def decorator(fn: callbacks.ActivityHandlerFn) -> callbacks.ActivityHandlerFn:
actual_registry = registry if registry is not None else registries.get_default_registry()
return actual_registry.register_activity_handler(
fn=fn, id=id,
real_registry = registry if registry is not None else registries.get_default_registry()
real_id = registries.generate_id(fn=fn, id=id)
handler = handlers.ActivityHandler(
fn=fn, id=real_id,
errors=errors, timeout=timeout, retries=retries, backoff=backoff, cooldown=cooldown,
activity=causation.Activity.AUTHENTICATION,
)
real_registry.activity_handlers.append(handler)
return fn
return decorator


Expand All @@ -99,12 +110,15 @@ def probe( # lgtm[py/similar-function]
) -> ActivityHandlerDecorator:
""" ``@kopf.on.probe()`` handler for arbitrary liveness metrics. """
def decorator(fn: callbacks.ActivityHandlerFn) -> callbacks.ActivityHandlerFn:
actual_registry = registry if registry is not None else registries.get_default_registry()
return actual_registry.register_activity_handler(
fn=fn, id=id,
real_registry = registry if registry is not None else registries.get_default_registry()
real_id = registries.generate_id(fn=fn, id=id)
handler = handlers.ActivityHandler(
fn=fn, id=real_id,
errors=errors, timeout=timeout, retries=retries, backoff=backoff, cooldown=cooldown,
activity=causation.Activity.PROBE,
)
real_registry.activity_handlers.append(handler)
return fn
return decorator


Expand All @@ -125,13 +139,18 @@ def resume( # lgtm[py/similar-function]
) -> ResourceHandlerDecorator:
""" ``@kopf.on.resume()`` handler for the object resuming on operator (re)start. """
def decorator(fn: callbacks.ResourceHandlerFn) -> callbacks.ResourceHandlerFn:
actual_registry = registry if registry is not None else registries.get_default_registry()
return actual_registry.register_resource_changing_handler(
group=group, version=version, plural=plural,
reason=None, initial=True, deleted=deleted, id=id,
real_registry = registry if registry is not None else registries.get_default_registry()
real_resource = resources.Resource(group, version, plural)
real_id = registries.generate_id(fn=fn, id=id)
handler = handlers.ResourceHandler(
fn=fn, id=real_id, field=None,
errors=errors, timeout=timeout, retries=retries, backoff=backoff, cooldown=cooldown,
fn=fn, labels=labels, annotations=annotations, when=when,
labels=labels, annotations=annotations, when=when,
initial=True, deleted=deleted, requires_finalizer=None,
reason=None,
)
real_registry.resource_changing_handlers[real_resource].append(handler)
return fn
return decorator


Expand All @@ -151,13 +170,18 @@ def create( # lgtm[py/similar-function]
) -> ResourceHandlerDecorator:
""" ``@kopf.on.create()`` handler for the object creation. """
def decorator(fn: callbacks.ResourceHandlerFn) -> callbacks.ResourceHandlerFn:
actual_registry = registry if registry is not None else registries.get_default_registry()
return actual_registry.register_resource_changing_handler(
group=group, version=version, plural=plural,
reason=causation.Reason.CREATE, id=id,
real_registry = registry if registry is not None else registries.get_default_registry()
real_resource = resources.Resource(group, version, plural)
real_id = registries.generate_id(fn=fn, id=id)
handler = handlers.ResourceHandler(
fn=fn, id=real_id, field=None,
errors=errors, timeout=timeout, retries=retries, backoff=backoff, cooldown=cooldown,
fn=fn, labels=labels, annotations=annotations, when=when,
labels=labels, annotations=annotations, when=when,
initial=None, deleted=None, requires_finalizer=None,
reason=causation.Reason.CREATE,
)
real_registry.resource_changing_handlers[real_resource].append(handler)
return fn
return decorator


Expand All @@ -177,13 +201,18 @@ def update( # lgtm[py/similar-function]
) -> ResourceHandlerDecorator:
""" ``@kopf.on.update()`` handler for the object update or change. """
def decorator(fn: callbacks.ResourceHandlerFn) -> callbacks.ResourceHandlerFn:
actual_registry = registry if registry is not None else registries.get_default_registry()
return actual_registry.register_resource_changing_handler(
group=group, version=version, plural=plural,
reason=causation.Reason.UPDATE, id=id,
real_registry = registry if registry is not None else registries.get_default_registry()
real_resource = resources.Resource(group, version, plural)
real_id = registries.generate_id(fn=fn, id=id)
handler = handlers.ResourceHandler(
fn=fn, id=real_id, field=None,
errors=errors, timeout=timeout, retries=retries, backoff=backoff, cooldown=cooldown,
fn=fn, labels=labels, annotations=annotations, when=when,
labels=labels, annotations=annotations, when=when,
initial=None, deleted=None, requires_finalizer=None,
reason=causation.Reason.UPDATE,
)
real_registry.resource_changing_handlers[real_resource].append(handler)
return fn
return decorator


Expand All @@ -204,14 +233,18 @@ def delete( # lgtm[py/similar-function]
) -> ResourceHandlerDecorator:
""" ``@kopf.on.delete()`` handler for the object deletion. """
def decorator(fn: callbacks.ResourceHandlerFn) -> callbacks.ResourceHandlerFn:
actual_registry = registry if registry is not None else registries.get_default_registry()
return actual_registry.register_resource_changing_handler(
group=group, version=version, plural=plural,
reason=causation.Reason.DELETE, id=id,
real_registry = registry if registry is not None else registries.get_default_registry()
real_resource = resources.Resource(group, version, plural)
real_id = registries.generate_id(fn=fn, id=id)
handler = handlers.ResourceHandler(
fn=fn, id=real_id, field=None,
errors=errors, timeout=timeout, retries=retries, backoff=backoff, cooldown=cooldown,
fn=fn, requires_finalizer=bool(not optional),
labels=labels, annotations=annotations, when=when,
initial=None, deleted=None, requires_finalizer=bool(not optional),
reason=causation.Reason.DELETE,
)
real_registry.resource_changing_handlers[real_resource].append(handler)
return fn
return decorator


Expand All @@ -232,13 +265,19 @@ def field( # lgtm[py/similar-function]
) -> ResourceHandlerDecorator:
""" ``@kopf.on.field()`` handler for the individual field changes. """
def decorator(fn: callbacks.ResourceHandlerFn) -> callbacks.ResourceHandlerFn:
actual_registry = registry if registry is not None else registries.get_default_registry()
return actual_registry.register_resource_changing_handler(
group=group, version=version, plural=plural,
reason=None, field=field, id=id,
real_registry = registry if registry is not None else registries.get_default_registry()
real_resource = resources.Resource(group, version, plural)
real_field = dicts.parse_field(field) or None # to not store tuple() as a no-field case.
real_id = registries.generate_id(fn=fn, id=id, suffix=".".join(real_field or []))
handler = handlers.ResourceHandler(
fn=fn, id=real_id, field=real_field,
errors=errors, timeout=timeout, retries=retries, backoff=backoff, cooldown=cooldown,
fn=fn, labels=labels, annotations=annotations, when=when,
labels=labels, annotations=annotations, when=when,
initial=None, deleted=None, requires_finalizer=None,
reason=None,
)
real_registry.resource_changing_handlers[real_resource].append(handler)
return fn
return decorator


Expand All @@ -253,11 +292,18 @@ def event( # lgtm[py/similar-function]
) -> ResourceHandlerDecorator:
""" ``@kopf.on.event()`` handler for the silent spies on the events. """
def decorator(fn: callbacks.ResourceHandlerFn) -> callbacks.ResourceHandlerFn:
actual_registry = registry if registry is not None else registries.get_default_registry()
return actual_registry.register_resource_watching_handler(
group=group, version=version, plural=plural,
id=id, fn=fn, labels=labels, annotations=annotations, when=when,
real_registry = registry if registry is not None else registries.get_default_registry()
real_resource = resources.Resource(group, version, plural)
real_id = registries.generate_id(fn=fn, id=id)
handler = handlers.ResourceHandler(
fn=fn, id=real_id, field=None,
errors=None, timeout=None, retries=None, backoff=None, cooldown=None,
labels=labels, annotations=annotations, when=when,
initial=None, deleted=None, requires_finalizer=None,
reason=None,
)
real_registry.resource_watching_handlers[real_resource].append(handler)
return fn
return decorator


Expand All @@ -272,6 +318,9 @@ def this( # lgtm[py/similar-function]
backoff: Optional[float] = None,
cooldown: Optional[float] = None, # deprecated, use `backoff`
registry: Optional[registries.ResourceChangingRegistry] = None,
labels: Optional[bodies.Labels] = None,
annotations: Optional[bodies.Annotations] = None,
when: Optional[callbacks.WhenHandlerFn] = None,
) -> ResourceHandlerDecorator:
"""
``@kopf.on.this()`` decorator for the dynamically generated sub-handlers.
Expand Down Expand Up @@ -303,11 +352,19 @@ def create_task(*, spec, task=task, **kwargs):
create function will have its own value, not the latest in the for-cycle.
"""
def decorator(fn: callbacks.ResourceHandlerFn) -> callbacks.ResourceHandlerFn:
actual_registry = registry if registry is not None else handling.subregistry_var.get()
return actual_registry.register(
id=id, fn=fn,
parent_handler = handling.handler_var.get()
real_registry = registry if registry is not None else handling.subregistry_var.get()
real_id = registries.generate_id(fn=fn, id=id,
prefix=parent_handler.id if parent_handler else None)
handler = handlers.ResourceHandler(
fn=fn, id=real_id, field=None,
errors=errors, timeout=timeout, retries=retries, backoff=backoff, cooldown=cooldown,
labels=labels, annotations=annotations, when=when,
initial=None, deleted=None, requires_finalizer=None,
reason=None,
)
real_registry.append(handler)
return fn
return decorator


Expand All @@ -321,6 +378,9 @@ def register( # lgtm[py/similar-function]
backoff: Optional[float] = None,
cooldown: Optional[float] = None, # deprecated, use `backoff`
registry: Optional[registries.ResourceChangingRegistry] = None,
labels: Optional[bodies.Labels] = None,
annotations: Optional[bodies.Annotations] = None,
when: Optional[callbacks.WhenHandlerFn] = None,
) -> callbacks.ResourceHandlerFn:
"""
Register a function as a sub-handler of the currently executed handler.
Expand Down Expand Up @@ -349,5 +409,6 @@ def create_single_task(task=task, **_):
decorator = this(
id=id, registry=registry,
errors=errors, timeout=timeout, retries=retries, backoff=backoff, cooldown=cooldown,
labels=labels, annotations=annotations, when=when,
)
return decorator(fn)
2 changes: 1 addition & 1 deletion kopf/reactor/activities.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ async def run_activity(

# For the activity handlers, we have neither bodies, nor patches, just the state.
cause = causation.ActivityCause(logger=logger, activity=activity)
handlers = registry.get_activity_handlers(activity=activity)
handlers = registry.activity_handlers.get_handlers(activity=activity)
outcomes = await handling.run_handlers_until_done(
cause=cause,
handlers=handlers,
Expand Down
14 changes: 7 additions & 7 deletions kopf/reactor/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def __getattribute__(self, name: str) -> Any:
@dataclasses.dataclass
class ActivityHandler(BaseHandler):
fn: callbacks.ActivityHandlerFn # type clarification
activity: Optional[causation.Activity] = None
activity: Optional[causation.Activity]
_fallback: bool = False # non-public!


Expand All @@ -55,12 +55,12 @@ class ResourceHandler(BaseHandler):
fn: callbacks.ResourceHandlerFn # type clarification
reason: Optional[causation.Reason]
field: Optional[dicts.FieldPath]
initial: Optional[bool] = None
deleted: Optional[bool] = None # used for mixed-in (initial==True) @on.resume handlers only.
labels: Optional[bodies.Labels] = None
annotations: Optional[bodies.Annotations] = None
when: Optional[callbacks.WhenHandlerFn] = None
requires_finalizer: Optional[bool] = None
initial: Optional[bool]
deleted: Optional[bool] # used for mixed-in (initial==True) @on.resume handlers only.
labels: Optional[bodies.Labels]
annotations: Optional[bodies.Annotations]
when: Optional[callbacks.WhenHandlerFn]
requires_finalizer: Optional[bool]

@property
def event(self) -> Optional[causation.Reason]:
Expand Down
30 changes: 23 additions & 7 deletions kopf/reactor/handling.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,22 +104,38 @@ async def execute(
raise TypeError("Only one of the fns, handlers, registry can be passed. Got more.")

elif fns is not None and isinstance(fns, collections.abc.Mapping):
subregistry = registries.ResourceChangingRegistry(prefix=parent_prefix)
subregistry = registries.ResourceChangingRegistry()
for id, fn in fns.items():
subregistry.register(fn=fn, id=id)
real_id = registries.generate_id(fn=fn, id=id, prefix=parent_prefix)
handler = handlers_.ResourceHandler(
fn=fn, id=real_id,
errors=None, timeout=None, retries=None, backoff=None, cooldown=None,
labels=None, annotations=None, when=None,
initial=None, deleted=None, requires_finalizer=None,
reason=None, field=None,
)
subregistry.append(handler)

elif fns is not None and isinstance(fns, collections.abc.Iterable):
subregistry = registries.ResourceChangingRegistry(prefix=parent_prefix)
subregistry = registries.ResourceChangingRegistry()
for fn in fns:
subregistry.register(fn=fn)
real_id = registries.generate_id(fn=fn, id=None, prefix=parent_prefix)
handler = handlers_.ResourceHandler(
fn=fn, id=real_id,
errors=None, timeout=None, retries=None, backoff=None, cooldown=None,
labels=None, annotations=None, when=None,
initial=None, deleted=None, requires_finalizer=None,
reason=None, field=None,
)
subregistry.append(handler)

elif fns is not None:
raise ValueError(f"fns must be a mapping or an iterable, got {fns.__class__}.")

elif handlers is not None:
subregistry = registries.ResourceChangingRegistry(prefix=parent_prefix)
subregistry = registries.ResourceChangingRegistry()
for handler in handlers:
subregistry.append(handler=handler)
subregistry.append(handler)

# Use the registry as is; assume that the caller knows what they do.
elif registry is not None:
Expand Down Expand Up @@ -350,7 +366,7 @@ async def invoke_handler(
# This replaces the multiple kwargs passing through the whole call stack (easy to forget).
with invocation.context([
(sublifecycle_var, lifecycle),
(subregistry_var, registries.ResourceChangingRegistry(prefix=handler.id)),
(subregistry_var, registries.ResourceChangingRegistry()),
(subexecuted_var, False),
(handler_var, handler),
(cause_var, cause),
Expand Down
Loading

0 comments on commit 51a3a70

Please sign in to comment.