From 851916b08773e3a933a44f1df7ac0a0f92d71965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul?= Date: Sun, 31 Oct 2021 17:01:58 +0100 Subject: [PATCH] Factorize get build by name --- src/runboat/api.py | 14 +++++++------- src/runboat/controller.py | 38 ++++++++++++++++++++++++++------------ 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/runboat/api.py b/src/runboat/api.py index 2374bac..e9f4e88 100644 --- a/src/runboat/api.py +++ b/src/runboat/api.py @@ -117,8 +117,8 @@ async def trigger_pull(org: str, repo: str, pr: int): ) -def _build_by_name(name: str) -> models.Build: - build = controller.db.get(name) +async def _build_by_name(name: str) -> models.Build: + build = await controller.get_build(name) if build is None: raise HTTPException(status.HTTP_404_NOT_FOUND) return build @@ -126,7 +126,7 @@ def _build_by_name(name: str) -> models.Build: @router.get("/builds/{name}", response_model=Build) async def build(name: str): - return _build_by_name(name) + return await _build_by_name(name) @router.get( @@ -135,7 +135,7 @@ async def build(name: str): responses={200: {"content": {"text/plain": {}}}}, ) async def init_log(name: str): - # build = _build_by_name(name) + # build = await _build_by_name(name) ... @@ -152,19 +152,19 @@ async def log(name: str): @router.post("/builds/{name}/start") async def start(name: str): """Start the deployment.""" - build = _build_by_name(name) + build = await _build_by_name(name) await build.start() @router.post("/builds/{name}/stop") async def stop(name: str): """Stop the deployment.""" - build = _build_by_name(name) + build = await _build_by_name(name) await build.stop() @router.delete("/builds/{name}", dependencies=[Depends(authenticated)]) async def delete(name: str): """Delete the deployment and drop the database.""" - build = _build_by_name(name) + build = await _build_by_name(name) await build.undeploy() diff --git a/src/runboat/controller.py b/src/runboat/controller.py index 6085f71..77e948d 100644 --- a/src/runboat/controller.py +++ b/src/runboat/controller.py @@ -94,6 +94,18 @@ class Controller: with contextlib.suppress(asyncio.TimeoutError): await asyncio.wait_for(self._wakeup_event.wait(), 10) + async def get_build(self, build_name: str, db_only: bool = True) -> Build | None: + build = self.db.get(build_name) + if build is not None: + return build + if not db_only: + build = await Build.from_name(build_name) + if build is not None: + if self.db.add(build): + self._wakeup() + return build + return None + async def deployment_watcher(self) -> None: self.reset() # empty the local db each time we start watching async for event_type, deployment in k8s.watch_deployments(): @@ -119,19 +131,21 @@ class Controller: if job_kind not in ("initialize", "cleanup"): continue if event_type in ("ADDED", "MODIFIED"): - build = self.db.get(build_name) + _logger.debug( + "job %s for %s status %s", job_kind, build_name, job.status + ) + # Look for build in local db and also in k8s api. + # This is necessary because job events may come before build events + # have arrived. + build = await self.get_build(build_name, db_only=False) if build is None: - # Not found in db, look in k8s api, in case the controller - # is starting and the db has not been populated yet. - build = await Build.from_name(build_name) - if build is None: - _logger.warning( - f"Received job event for {build_name} " - f"but the corresponding deployment is gone. " - f"Deleting all build resources." - ) - await k8s.delete_resources(build_name) - continue + _logger.warning( + f"Received job event for {build_name} " + f"but the corresponding deployment is gone. " + f"Deleting all build resources." + ) + await k8s.delete_resources(build_name) + continue if job_kind == "initialize": if job.status.active: await build.on_initialize_started()