def watcher_in_background(settings, resource, event_loop, worker_spy, stream): # Prevent remembering the streaming objects in the mocks. async def do_nothing(*args, **kwargs): pass # Prevent any real streaming for the very beginning, before it even starts. stream.feed([]) # Spawn a watcher in the background. coro = watcher( namespace=None, resource=resource, settings=settings, processor=do_nothing, ) task = event_loop.create_task(coro) try: # Go for a test. yield task finally: # Terminate the watcher to cleanup the loop. task.cancel() try: event_loop.run_until_complete(task) except asyncio.CancelledError: pass
async def spawn_missing_watchers( *, processor: queueing.WatchStreamProcessor, settings: configuration.OperatorSettings, indexed_resources: Container[ references.Resource], # only "if in", never "for in"! watched_resources: Iterable[references.Resource], watched_namespaces: Iterable[references.Namespace], ensemble: Ensemble, ) -> None: # Block the operator globally until specialised per-resource-kind blockers are created. # NB: Must be created before the point of parallelisation! operator_blocked = await ensemble.operator_indexed.make_toggle( name="orchestration blocker") # Spawn watchers and create the specialised per-resource-kind blockers. for resource, namespace in itertools.product(watched_resources, watched_namespaces): namespace = namespace if resource.namespaced else None dkey = EnsembleKey(resource=resource, namespace=namespace) if dkey not in ensemble.watcher_tasks: what = f"{resource}@{namespace}" resource_indexed: Optional[aiotoggles.Toggle] = None if resource in indexed_resources: resource_indexed = await ensemble.operator_indexed.make_toggle( name=what) ensemble.watcher_tasks[dkey] = aiotasks.create_guarded_task( name=f"watcher for {what}", logger=logger, cancellable=True, coro=queueing.watcher( operator_paused=ensemble.operator_paused, operator_indexed=ensemble.operator_indexed, resource_indexed=resource_indexed, settings=settings, resource=resource, namespace=namespace, processor=functools.partial(processor, resource=resource))) # Unblock globally, let the specialised per-resource-kind blockers hold the readiness. await ensemble.operator_indexed.drop_toggle(operator_blocked) # Ensure that all guarded tasks got control for a moment to enter the guard. await asyncio.sleep(0)
async def spawn_missing_peerings( *, settings: configuration.OperatorSettings, identity: peering.Identity, resources: Collection[references.Resource], namespaces: Collection[references.Namespace], ensemble: Ensemble, ) -> None: for resource, namespace in itertools.product(resources, namespaces): namespace = namespace if resource.namespaced else None dkey = EnsembleKey(resource=resource, namespace=namespace) if dkey not in ensemble.peering_tasks: what = f"{settings.peering.name}@{namespace}" is_preactivated = settings.peering.mandatory conflicts_found = await ensemble.operator_paused.make_toggle( is_preactivated, name=what) ensemble.conflicts_found[dkey] = conflicts_found ensemble.pinging_tasks[dkey] = aiotasks.create_guarded_task( name=f"peering keep-alive for {what}", logger=logger, cancellable=True, coro=peering.keepalive(namespace=namespace, resource=resource, settings=settings, identity=identity)) ensemble.peering_tasks[dkey] = aiotasks.create_guarded_task( name=f"peering observer for {what}", logger=logger, cancellable=True, coro=queueing.watcher(settings=settings, resource=resource, namespace=namespace, processor=functools.partial( peering.process_peering_event, conflicts_found=conflicts_found, namespace=namespace, resource=resource, settings=settings, identity=identity))) # Ensure that all guarded tasks got control for a moment to enter the guard. await asyncio.sleep(0)