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 register_resource_changing_handler( self, group: str, version: str, plural: str, fn: callbacks.ResourceHandlerFn, id: Optional[str] = None, reason: Optional[causation.Reason] = None, event: Optional[str] = None, # deprecated, use `reason` field: Optional[dicts.FieldSpec] = None, errors: Optional[errors_.ErrorsMode] = None, timeout: Optional[float] = None, retries: Optional[int] = None, backoff: Optional[float] = None, cooldown: Optional[float] = None, # deprecated, use `backoff` initial: Optional[bool] = None, deleted: Optional[bool] = None, requires_finalizer: bool = False, labels: Optional[bodies.Labels] = None, annotations: Optional[bodies.Annotations] = None, when: Optional[callbacks.WhenHandlerFn] = None, ) -> callbacks.ResourceHandlerFn: """ Register an additional handler function for the specific resource and specific reason. """ resource = resources_.Resource(group, version, plural) return self._resource_changing_handlers[resource].register( reason=reason, event=event, field=field, fn=fn, id=id, errors=errors, timeout=timeout, retries=retries, backoff=backoff, cooldown=cooldown, initial=initial, deleted=deleted, requires_finalizer=requires_finalizer, labels=labels, annotations=annotations, when=when, )
def register_state_changing_handler( self, group: str, version: str, plural: str, fn: HandlerFn, id: Optional[str] = None, reason: Optional[causation.Reason] = None, event: Optional[str] = None, # deprecated, use `reason` field: Optional[dicts.FieldSpec] = None, timeout: Optional[float] = None, initial: Optional[bool] = None, requires_finalizer: bool = False, labels: Optional[bodies.Labels] = None, annotations: Optional[bodies.Annotations] = None, ) -> HandlerFn: """ Register an additional handler function for the specific resource and specific reason. """ resource = resources_.Resource(group, version, plural) registry = self._cause_handlers.setdefault(resource, SimpleRegistry()) registry.register(reason=reason, event=event, field=field, fn=fn, id=id, timeout=timeout, initial=initial, requires_finalizer=requires_finalizer, labels=labels, annotations=annotations) return fn # to be usable as a decorator too.
async def discover( *, resource: resources.Resource, context: Optional[auth.APIContext] = None, # injected by the decorator ) -> Optional[Dict[str, object]]: if context is None: raise RuntimeError("API instance is not injected by the decorator.") if resource.api_version not in context._discovered_resources: async with context._discovery_lock: if resource.api_version not in context._discovered_resources: context._discovered_resources[resource.api_version] = {} try: response = await context.session.get( url=resource.get_version_url(server=context.server), ) response.raise_for_status() respdata = await response.json() context._discovered_resources[resource.api_version].update( { resources.Resource(resource.group, resource.version, info['name']): info for info in respdata['resources'] }) except aiohttp.ClientResponseError as e: if e.status in [403, 404]: pass else: raise return context._discovered_resources[resource.api_version].get( resource, None)
def register_resource_watching_handler( self, group: str, version: str, plural: str, fn: callbacks.ResourceWatchingFn, id: Optional[str] = None, labels: Optional[filters.MetaFilter] = None, annotations: Optional[filters.MetaFilter] = None, when: Optional[callbacks.WhenFilterFn] = None, ) -> callbacks.ResourceWatchingFn: """ Register an additional handler function for low-level events. """ warnings.warn( "registry.register_resource_watching_handler() is deprecated; " "use @kopf.on... decorators with registry= kwarg.", DeprecationWarning) resource = resources_.Resource(group, version, plural) return self.resource_watching_handlers[resource].register( fn=fn, id=id, labels=labels, annotations=annotations, when=when, )
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 register_resource_changing_handler( self, group: str, version: str, plural: str, fn: callbacks.ResourceChangingFn, id: Optional[str] = None, reason: Optional[handlers.Reason] = None, event: Optional[str] = None, # deprecated, use `reason` field: Optional[dicts.FieldSpec] = None, errors: Optional[handlers.ErrorsMode] = None, timeout: Optional[float] = None, retries: Optional[int] = None, backoff: Optional[float] = None, cooldown: Optional[float] = None, # deprecated, use `backoff` initial: Optional[bool] = None, deleted: Optional[bool] = None, requires_finalizer: bool = False, labels: Optional[filters.MetaFilter] = None, annotations: Optional[filters.MetaFilter] = None, when: Optional[callbacks.WhenFilterFn] = None, ) -> callbacks.ResourceChangingFn: """ Register an additional handler function for the specific resource and specific reason. """ warnings.warn("registry.register_resource_changing_handler() is deprecated; " "use @kopf.on... decorators with registry= kwarg.", DeprecationWarning) resource = resources_.Resource(group, version, plural) return self.resource_changing_handlers[resource].register( reason=reason, event=event, field=field, fn=fn, id=id, errors=errors, timeout=timeout, retries=retries, backoff=backoff, cooldown=cooldown, initial=initial, deleted=deleted, requires_finalizer=requires_finalizer, labels=labels, annotations=annotations, when=when, )
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 register_resource_changing_handler( self, group: str, version: str, plural: str, fn: ResourceHandlerFn, id: Optional[str] = None, reason: Optional[causation.Reason] = None, event: Optional[str] = None, # deprecated, use `reason` field: Optional[dicts.FieldSpec] = None, timeout: Optional[float] = None, initial: Optional[bool] = None, requires_finalizer: bool = False, labels: Optional[bodies.Labels] = None, annotations: Optional[bodies.Annotations] = None, ) -> ResourceHandlerFn: """ Register an additional handler function for the specific resource and specific reason. """ resource = resources_.Resource(group, version, plural) return self._resource_changing_handlers[resource].register( reason=reason, event=event, field=field, fn=fn, id=id, timeout=timeout, initial=initial, requires_finalizer=requires_finalizer, labels=labels, annotations=annotations, )
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 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 register_event_watching_handler( self, group: str, version: str, plural: str, fn: HandlerFn, id: Optional[str] = None, labels: Optional[bodies.Labels] = None, annotations: Optional[bodies.Annotations] = None, ) -> HandlerFn: """ Register an additional handler function for low-level events. """ resource = resources_.Resource(group, version, plural) registry = self._event_handlers.setdefault(resource, SimpleRegistry()) registry.register(fn=fn, id=id, labels=labels, annotations=annotations) return fn # to be usable as a decorator too.
def register_resource_watching_handler( self, group: str, version: str, plural: str, fn: ResourceHandlerFn, id: Optional[str] = None, labels: Optional[bodies.Labels] = None, annotations: Optional[bodies.Annotations] = None, ) -> ResourceHandlerFn: """ Register an additional handler function for low-level events. """ resource = resources_.Resource(group, version, plural) return self._resource_watching_handlers[resource].register( fn=fn, id=id, labels=labels, annotations=annotations, )
def decorator( fn: callbacks.ResourceWatchingFn) -> callbacks.ResourceWatchingFn: _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.ResourceWatchingHandler( fn=fn, id=real_id, errors=None, timeout=None, retries=None, backoff=None, cooldown=None, labels=labels, annotations=annotations, when=when, ) real_registry.resource_watching_handlers[real_resource].append(handler) return fn
import socket from typing import Any, Dict, Iterable, Optional, Union, NoReturn, Mapping, cast import iso8601 from kopf.clients import fetching from kopf.clients import patching from kopf.structs import bodies from kopf.structs import patches from kopf.structs import primitives from kopf.structs import resources logger = logging.getLogger(__name__) # The CRD info on the special sync-object. CLUSTER_PEERING_RESOURCE = resources.Resource('zalando.org', 'v1', 'clusterkopfpeerings') NAMESPACED_PEERING_RESOURCE = resources.Resource('zalando.org', 'v1', 'kopfpeerings') LEGACY_PEERING_RESOURCE = resources.Resource('zalando.org', 'v1', 'kopfpeerings') PEERING_DEFAULT_NAME = 'default' # The class used to represent a peer in the parsed peers list (for convenience). # The extra fields are for easier calculation when and if the peer is dead to the moment. class Peer: def __init__( self, id: str, *, name: str, priority: int = 0,
import enum from typing import TypeVar, Optional, Union, Collection, List, Tuple, cast import aiohttp from kopf.clients import auth from kopf.clients import discovery from kopf.structs import bodies from kopf.structs import resources _T = TypeVar('_T') CRD_CRD = resources.Resource('apiextensions.k8s.io', 'v1beta1', 'customresourcedefinitions') class _UNSET(enum.Enum): token = enum.auto() @auth.reauthenticated_request async def read_crd( *, resource: resources.Resource, default: Union[_T, _UNSET] = _UNSET.token, context: Optional[auth.APIContext] = None, # injected by the decorator ) -> Union[bodies.Body, _T]: if context is None: raise RuntimeError("API instance is not injected by the decorator.") try: response = await context.session.get(
import copy import datetime import logging from typing import Optional import aiohttp from kopf.clients import auth from kopf.structs import bodies from kopf.structs import resources logger = logging.getLogger(__name__) EVENTS_V1BETA1_CRD = resources.Resource('events.k8s.io', 'v1beta1', 'events') EVENTS_CORE_V1_CRD = resources.Resource('', 'v1', 'events') MAX_MESSAGE_LENGTH = 1024 CUT_MESSAGE_INFIX = '...' @auth.reauthenticated_request async def post_event( *, ref: bodies.ObjectReference, type: str, reason: str, message: str = '', context: Optional[auth.APIContext] = None, # injected by the decorator ) -> None: """ Issue an event for the object.