def field( group: str, version: str, plural: str, field: Union[str, List[str], Tuple[str, ...]], *, id: Optional[str] = None, timeout: Optional[float] = None, registry: Optional[registries.OperatorRegistry] = None, labels: Optional[bodies.Labels] = None, annotations: Optional[bodies.Annotations] = None, ) -> ResourceHandlerDecorator: """ ``@kopf.on.field()`` handler for the individual field changes. """ actual_registry = registry if registry is not None else registries.get_default_registry( ) def decorator( fn: registries.ResourceHandlerFn) -> registries.ResourceHandlerFn: actual_registry.register_resource_changing_handler( group=group, version=version, plural=plural, reason=None, field=field, id=id, timeout=timeout, fn=fn, labels=labels, annotations=annotations) return fn return decorator
def event( group: str, version: str, plural: str, *, id: Optional[str] = None, registry: Optional[registries.OperatorRegistry] = None, labels: Optional[bodies.Labels] = None, annotations: Optional[bodies.Annotations] = None, ) -> ResourceHandlerDecorator: """ ``@kopf.on.event()`` handler for the silent spies on the events. """ actual_registry = registry if registry is not None else registries.get_default_registry( ) def decorator( fn: registries.ResourceHandlerFn) -> registries.ResourceHandlerFn: actual_registry.register_resource_watching_handler( group=group, version=version, plural=plural, id=id, fn=fn, labels=labels, annotations=annotations) return fn return decorator
def decorator( fn: callbacks.ResourceDaemonFn) -> callbacks.ResourceDaemonFn: _warn_deprecated_signatures(fn) _warn_deprecated_filters(labels, annotations) 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.ResourceDaemonHandler( fn=fn, id=real_id, errors=errors, timeout=timeout, retries=retries, backoff=backoff, cooldown=cooldown, labels=labels, annotations=annotations, when=when, initial_delay=initial_delay, requires_finalizer=True, #TODO: requires_finalizer? "optional"? cancellation_backoff=cancellation_backoff, cancellation_timeout=cancellation_timeout, cancellation_polling=cancellation_polling, ) real_registry.resource_spawning_handlers[real_resource].append(handler) return fn
def decorator(fn: callbacks.ResourceTimerFn) -> callbacks.ResourceTimerFn: _warn_deprecated_signatures(fn) _warn_deprecated_filters(labels, annotations) 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.ResourceTimerHandler( fn=fn, id=real_id, errors=errors, timeout=timeout, retries=retries, backoff=backoff, cooldown=cooldown, labels=labels, annotations=annotations, when=when, initial_delay=initial_delay, requires_finalizer=None, sharp=sharp, idle=idle, interval=interval, ) real_registry.resource_spawning_handlers[real_resource].append(handler) return fn
def delete( group: str, version: str, plural: str, *, id: Optional[str] = None, errors: Optional[registries.ErrorsMode] = None, timeout: Optional[float] = None, retries: Optional[int] = None, backoff: Optional[float] = None, cooldown: Optional[float] = None, # deprecated, use `backoff` registry: Optional[registries.OperatorRegistry] = None, optional: Optional[bool] = None, labels: Optional[bodies.Labels] = None, annotations: Optional[bodies.Annotations] = None, ) -> ResourceHandlerDecorator: """ ``@kopf.on.delete()`` handler for the object deletion. """ actual_registry = registry if registry is not None else registries.get_default_registry() def decorator(fn: registries.ResourceHandlerFn) -> registries.ResourceHandlerFn: return actual_registry.register_resource_changing_handler( group=group, version=version, plural=plural, reason=causation.Reason.DELETE, id=id, errors=errors, timeout=timeout, retries=retries, backoff=backoff, cooldown=cooldown, fn=fn, requires_finalizer=bool(not optional), labels=labels, annotations=annotations, ) return decorator
def decorator( fn: callbacks.ResourceChangingFn) -> callbacks.ResourceChangingFn: _warn_deprecated_signatures(fn) _warn_deprecated_filters(labels, annotations) 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.ResourceChangingHandler( 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=bool(not optional), reason=handlers.Reason.DELETE, ) real_registry.resource_changing_handlers[real_resource].append(handler) return fn
def cleanup( *, id: Optional[str] = None, errors: Optional[registries.ErrorsMode] = None, timeout: Optional[float] = None, retries: Optional[int] = None, cooldown: Optional[float] = None, registry: Optional[registries.OperatorRegistry] = None, ) -> ActivityHandlerDecorator: actual_registry = registry if registry is not None else registries.get_default_registry( ) def decorator( fn: registries.ActivityHandlerFn) -> registries.ActivityHandlerFn: return actual_registry.register_activity_handler( fn=fn, id=id, errors=errors, timeout=timeout, retries=retries, cooldown=cooldown, activity=causation.Activity.CLEANUP, ) return decorator
def login( *, id: Optional[str] = None, errors: Optional[registries.ErrorsMode] = None, timeout: Optional[float] = None, retries: Optional[int] = None, cooldown: Optional[float] = None, registry: Optional[registries.OperatorRegistry] = None, ) -> ActivityHandlerDecorator: """ ``@kopf.on.login()`` handler for custom (re-)authentication. """ actual_registry = registry if registry is not None else registries.get_default_registry( ) def decorator( fn: registries.ActivityHandlerFn) -> registries.ActivityHandlerFn: return actual_registry.register_activity_handler( fn=fn, id=id, errors=errors, timeout=timeout, retries=retries, cooldown=cooldown, activity=causation.Activity.AUTHENTICATION, ) return decorator
def probe( *, id: Optional[str] = None, errors: Optional[registries.ErrorsMode] = None, timeout: Optional[float] = None, retries: Optional[int] = None, cooldown: Optional[float] = None, registry: Optional[registries.OperatorRegistry] = None, ) -> ActivityHandlerDecorator: """ ``@kopf.on.probe()`` handler for arbitrary liveness metrics. """ actual_registry = registry if registry is not None else registries.get_default_registry( ) def decorator( fn: registries.ActivityHandlerFn) -> registries.ActivityHandlerFn: return actual_registry.register_activity_handler( fn=fn, id=id, errors=errors, timeout=timeout, retries=retries, cooldown=cooldown, activity=causation.Activity.PROBE, ) return decorator
def resume( group: str, version: str, plural: str, *, id: Optional[str] = None, timeout: Optional[float] = None, registry: Optional[registries.GlobalRegistry] = None, labels: Optional[bodies.Labels] = None, annotations: Optional[bodies.Annotations] = None, ) -> HandlerDecorator: """ ``@kopf.on.resume()`` handler for the object resuming on operator (re)start. """ actual_registry = registry if registry is not None else registries.get_default_registry( ) def decorator(fn: registries.HandlerFn) -> registries.HandlerFn: actual_registry.register_state_changing_handler( group=group, version=version, plural=plural, reason=None, initial=True, id=id, timeout=timeout, fn=fn, labels=labels, annotations=annotations) return fn return decorator
def delete( group: str, version: str, plural: str, *, id: Optional[str] = None, timeout: Optional[float] = None, registry: Optional[registries.GlobalRegistry] = None, optional: Optional[bool] = None, labels: Optional[bodies.Labels] = None, annotations: Optional[bodies.Annotations] = None, ) -> HandlerDecorator: """ ``@kopf.on.delete()`` handler for the object deletion. """ actual_registry = registry if registry is not None else registries.get_default_registry( ) def decorator(fn: registries.HandlerFn) -> registries.HandlerFn: actual_registry.register_state_changing_handler( group=group, version=version, plural=plural, reason=causation.Reason.DELETE, id=id, timeout=timeout, fn=fn, requires_finalizer=bool(not optional), labels=labels, annotations=annotations) return fn return decorator
def update( group: str, version: str, plural: str, *, id: Optional[str] = None, timeout: Optional[float] = None, registry: Optional[registries.OperatorRegistry] = None, labels: Optional[bodies.Labels] = None, annotations: Optional[bodies.Annotations] = None, ) -> ResourceHandlerDecorator: """ ``@kopf.on.update()`` handler for the object update or change. """ actual_registry = registry if registry is not None else registries.get_default_registry( ) def decorator( fn: registries.ResourceHandlerFn) -> registries.ResourceHandlerFn: actual_registry.register_resource_changing_handler( group=group, version=version, plural=plural, reason=causation.Reason.UPDATE, id=id, timeout=timeout, fn=fn, labels=labels, annotations=annotations) return fn return decorator
def update(group: str, version: str, plural: str, *, id: Optional[str] = None, timeout: Optional[float] = None, registry: Optional[registries.GlobalRegistry] = None, labels: Optional[Mapping] = None, annotations: Optional[Mapping] = None): """ ``@kopf.on.update()`` handler for the object update or change. """ registry = registry if registry is not None else registries.get_default_registry( ) def decorator(fn): registry.register_cause_handler(group=group, version=version, plural=plural, event=causation.UPDATE, id=id, timeout=timeout, fn=fn, labels=labels, annotations=annotations) return fn return decorator
def startup( *, id: Optional[str] = None, errors: Optional[registries.ErrorsMode] = None, timeout: Optional[float] = None, retries: Optional[int] = None, backoff: Optional[float] = None, cooldown: Optional[float] = None, # deprecated, use `backoff` registry: Optional[registries.OperatorRegistry] = None, ) -> ActivityHandlerDecorator: actual_registry = registry if registry is not None else registries.get_default_registry( ) def decorator( fn: registries.ActivityHandlerFn) -> registries.ActivityHandlerFn: return actual_registry.register_activity_handler( fn=fn, id=id, errors=errors, timeout=timeout, retries=retries, backoff=backoff, cooldown=cooldown, activity=causation.Activity.STARTUP, ) return decorator
def field(group: str, version: str, plural: str, field: Union[str, List[str], Tuple[str, ...]], *, id: Optional[str] = None, timeout: Optional[float] = None, registry: Optional[registries.GlobalRegistry] = None, labels: Optional[Mapping] = None, annotations: Optional[Mapping] = None): """ ``@kopf.on.field()`` handler for the individual field changes. """ registry = registry if registry is not None else registries.get_default_registry( ) def decorator(fn): registry.register_cause_handler(group=group, version=version, plural=plural, event=None, field=field, id=id, timeout=timeout, fn=fn, labels=labels, annotations=annotations) return fn return decorator
def resume(group: str, version: str, plural: str, *, id: Optional[str] = None, timeout: Optional[float] = None, registry: Optional[registries.GlobalRegistry] = None, labels: Optional[Mapping] = None, annotations: Optional[Mapping] = None): """ ``@kopf.on.resume()`` handler for the object resuming on operator (re)start. """ registry = registry if registry is not None else registries.get_default_registry( ) def decorator(fn): registry.register_cause_handler(group=group, version=version, plural=plural, event=None, initial=True, id=id, timeout=timeout, fn=fn, labels=labels, annotations=annotations) return fn return decorator
def decorator( # lgtm[py/similar-function] fn: callbacks.ResourceTimerFn, ) -> callbacks.ResourceTimerFn: _warn_deprecated_signatures(fn) _warn_deprecated_filters(labels, annotations) _warn_conflicting_values(field, value) real_registry = registry if registry is not None else registries.get_default_registry( ) 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) selector = references.Selector(group, version, plural) handler = handlers.ResourceTimerHandler( fn=fn, id=real_id, errors=errors, timeout=timeout, retries=retries, backoff=backoff, cooldown=cooldown, selector=selector, labels=labels, annotations=annotations, when=when, field=real_field, value=value, initial_delay=initial_delay, requires_finalizer=True, sharp=sharp, idle=idle, interval=interval, ) real_registry.resource_spawning_handlers.append(handler) return fn
def delete(group: str, version: str, plural: str, *, id: Optional[str] = None, timeout: Optional[float] = None, registry: Optional[registries.GlobalRegistry] = None, optional: Optional[bool] = None, labels: Optional[Mapping] = None, annotations: Optional[Mapping] = None): """ ``@kopf.on.delete()`` handler for the object deletion. """ registry = registry if registry is not None else registries.get_default_registry( ) def decorator(fn): registry.register_cause_handler(group=group, version=version, plural=plural, event=causation.DELETE, id=id, timeout=timeout, fn=fn, requires_finalizer=bool(not optional), labels=labels, annotations=annotations) return fn return decorator
def decorator( # lgtm[py/similar-function] fn: callbacks.ResourceChangingFn, ) -> callbacks.ResourceChangingFn: _warn_deprecated_signatures(fn) _warn_deprecated_filters(labels, annotations) _warn_conflicting_values(field, value) real_registry = registry if registry is not None else registries.get_default_registry( ) 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) selector = references.Selector(group, version, plural) handler = handlers.ResourceChangingHandler( fn=fn, id=real_id, errors=errors, timeout=timeout, retries=retries, backoff=backoff, cooldown=cooldown, selector=selector, labels=labels, annotations=annotations, when=when, field=real_field, value=value, old=None, new=None, field_needs_change=False, initial=None, deleted=None, requires_finalizer=bool(not optional), reason=handlers.Reason.DELETE, ) real_registry.resource_changing_handlers.append(handler) return fn
def decorator( # lgtm[py/similar-function] fn: callbacks.ResourceWatchingFn, ) -> callbacks.ResourceWatchingFn: _warn_deprecated_signatures(fn) _warn_deprecated_filters(labels, annotations) _warn_conflicting_values(field, value) real_registry = registry if registry is not None else registries.get_default_registry( ) 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) selector = references.Selector(group, version, plural) handler = handlers.ResourceWatchingHandler( fn=fn, id=real_id, errors=None, timeout=None, retries=None, backoff=None, cooldown=None, selector=selector, labels=labels, annotations=annotations, when=when, field=real_field, value=value, ) real_registry.resource_watching_handlers.append(handler) return fn
def decorator( fn: callbacks.ResourceHandlerFn) -> callbacks.ResourceHandlerFn: 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
def decorator( # lgtm[py/similar-function] fn: callbacks.ResourceDaemonFn, ) -> callbacks.ResourceDaemonFn: _warn_conflicting_values(field, value) _verify_filters(labels, annotations) real_registry = registry if registry is not None else registries.get_default_registry() 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 [])) selector = references.Selector( __group_or_groupversion_or_name, __version_or_name, __name, group=group, version=version, kind=kind, plural=plural, singular=singular, shortcut=shortcut, category=category, ) handler = handlers.ResourceDaemonHandler( fn=fn, id=real_id, param=param, errors=errors, timeout=timeout, retries=retries, backoff=backoff, selector=selector, labels=labels, annotations=annotations, when=when, field=real_field, value=value, initial_delay=initial_delay, requires_finalizer=True, cancellation_backoff=cancellation_backoff, cancellation_timeout=cancellation_timeout, cancellation_polling=cancellation_polling, ) real_registry._resource_spawning.append(handler) return fn
def decorator( fn: callbacks.ResourceHandlerFn) -> callbacks.ResourceHandlerFn: 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, 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
def create_tasks( loop: asyncio.AbstractEventLoop, lifecycle: Optional[Callable] = None, registry: Optional[registries.BaseRegistry] = None, standalone: bool = False, priority: int = 0, peering_name: str = peering.PEERING_DEFAULT_NAME, namespace: Optional[str] = None, ): """ Create all the tasks needed to run the operator, but do not spawn/start them. The tasks are properly inter-connected depending on the runtime specification. They can be injected into any event loop as needed. """ # The freezer and the registry are scoped to this whole task-set, to sync them all. lifecycle = lifecycle if lifecycle is not None else lifecycles.get_default_lifecycle( ) registry = registry if registry is not None else registries.get_default_registry( ) freeze = asyncio.Event() tasks = [] # Monitor the peers, unless explicitly disabled. ourselves: Optional[peering.Peer] = peering.Peer.detect( id=peering.detect_own_id(), priority=priority, standalone=standalone, namespace=namespace, name=peering_name, ) if ourselves: tasks.extend([ loop.create_task(peering.peers_keepalive(ourselves=ourselves)), loop.create_task( watcher(namespace=namespace, resource=ourselves.resource, handler=functools.partial( peering.peers_handler, ourselves=ourselves, freeze=freeze))), # freeze is set/cleared ]) # Resource event handling, only once for every known resource (de-duplicated). for resource in registry.resources: tasks.extend([ loop.create_task( watcher(namespace=namespace, resource=resource, handler=functools.partial( handling.custom_object_handler, lifecycle=lifecycle, registry=registry, resource=resource, freeze=freeze))), # freeze is only checked ]) return tasks
def decorator( # lgtm[py/similar-function] fn: callbacks.ActivityFn, ) -> callbacks.ActivityFn: 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, param=param, errors=errors, timeout=timeout, retries=retries, backoff=backoff, activity=handlers.Activity.AUTHENTICATION, ) real_registry._activities.append(handler) return fn
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, errors=errors, timeout=timeout, retries=retries, backoff=backoff, cooldown=cooldown, activity=causation.Activity.AUTHENTICATION, )
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, )
def delete( group: str, version: str, plural: str, *, id: Optional[str] = None, timeout: Optional[float] = None, registry: Optional[registries.GlobalRegistry] = None): """ ``@kopf.on.delete()`` handler for the object deletion. """ registry = registry if registry is not None else registries.get_default_registry() def decorator(fn): registry.register( group=group, version=version, plural=plural, event=registries.DELETE, id=id, timeout=timeout, fn=fn) return fn return decorator
def decorator( # lgtm[py/similar-function] fn: callbacks.ResourceChangingFn, ) -> callbacks.ResourceChangingFn: _warn_conflicting_values(field, value) _verify_filters(labels, annotations) real_registry = registry if registry is not None else registries.get_default_registry( ) 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 [])) selector = references.Selector( __group_or_groupversion_or_name, __version_or_name, __name, group=group, version=version, kind=kind, plural=plural, singular=singular, shortcut=shortcut, category=category, ) handler = handlers.ResourceChangingHandler( fn=fn, id=real_id, param=param, errors=errors, timeout=timeout, retries=retries, backoff=backoff, selector=selector, labels=labels, annotations=annotations, when=when, field=real_field, value=value, old=None, new=None, field_needs_change=False, initial=None, deleted=None, requires_finalizer=bool(not optional), reason=handlers.Reason.DELETE, ) real_registry._resource_changing.append(handler) return fn
def decorator( fn: callbacks.ActivityHandlerFn) -> callbacks.ActivityHandlerFn: 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