diff --git a/README.md b/README.md index fb3b756..2e81c14 100644 --- a/README.md +++ b/README.md @@ -104,15 +104,21 @@ kubernetes cluster, or even a different one, depending on your taste. All resources to be deployed in kubernetes for a build are in [src/runboat/kubefiles](./src/runboat/kubefiles). They are gathered together from a -`kustomization.yaml` jinja template that leads to three possible resource groups +`kustomization.yaml` jinja template that leads to 5 possible resource groups depending on a `mode` variable in the jinja rendering context: - `deployment` creates a kubernetes deployment with its associated resources (pvc, - service, ingress, ...); -- `initialization` creates a job that creates the database; -- `cleanup` creates a job that drops the database; + service, ingress, ...). +- `initialization` creates a job that performs installation and initializes the database; +- `start` updates the resources before scaling up the deployment to 1. This can be + useful to scale up other resources that must only be present while the main + deployment is running. +- `stop` updates the resources after initialization and before scaling down the + deployment to 0. This can be useful to scale down other resources that must + only be present while the main deployment is running. +- `cleanup` creates a job that perform cleanup before tearing down all resources. -Besides the three modes, the controller has limited knowledge of what the kubefiles +Besides the 5 modes, the controller has limited knowledge of what the kubefiles actually deploy. It expects the following to hold true: - the `runboat/build` label is set on all resources, with the unique build name as diff --git a/src/runboat/k8s.py b/src/runboat/k8s.py index dbf6fd4..ea35f6b 100644 --- a/src/runboat/k8s.py +++ b/src/runboat/k8s.py @@ -138,6 +138,8 @@ class DeploymentMode(str, Enum): deployment = "deployment" initialize = "initialize" cleanup = "cleanup" + start = "start" + stop = "stop" class DeploymentVars(BaseModel): diff --git a/src/runboat/models.py b/src/runboat/models.py index d3dfc82..ac17dba 100644 --- a/src/runboat/models.py +++ b/src/runboat/models.py @@ -195,12 +195,6 @@ class Build(BaseModel): build_settings, ) await k8s.deploy(kubefiles_path, deployment_vars) - await github.notify_status( - commit_info.repo, - commit_info.git_commit, - GitHubStatusState.pending, - target_url=None, - ) @classmethod async def deploy(cls, commit_info: CommitInfo) -> None: @@ -211,6 +205,12 @@ class Build(BaseModel): await cls._deploy( commit_info, name, slug, job_kind=k8s.DeploymentMode.deployment ) + await github.notify_status( + commit_info.repo, + commit_info.git_commit, + GitHubStatusState.pending, + target_url=None, + ) async def start(self) -> None: """Start build if init succeeded, or reinitialize if failed.""" @@ -218,6 +218,12 @@ class Build(BaseModel): _logger.info(f"Ignoring start command for {self} that is {self.status}.") return _logger.info(f"Starting {self} that was last scaled on {self.last_scaled}.") + await self._deploy( + self.commit_info, + self.name, + self.slug, + job_kind=k8s.DeploymentMode.start, + ) await self._patch(desired_replicas=1) async def stop(self) -> None: @@ -226,6 +232,12 @@ class Build(BaseModel): return _logger.info(f"Stopping {self} that was last scaled on {self.last_scaled}.") await self._patch(desired_replicas=0) + await self._deploy( + self.commit_info, + self.name, + self.slug, + job_kind=k8s.DeploymentMode.stop, + ) async def undeploy(self) -> None: # To undeploy, we delete the deployment. Due to the finalizer, the deletion @@ -246,6 +258,12 @@ class Build(BaseModel): self.slug, job_kind=k8s.DeploymentMode.deployment, ) + await github.notify_status( + self.commit_info.repo, + self.commit_info.git_commit, + GitHubStatusState.pending, + target_url=None, + ) async def initialize(self) -> None: """Launch the initialization job.""" @@ -300,6 +318,12 @@ class Build(BaseModel): # is restarting, and is notified of existing initialization jobs. return _logger.info(f"Initialization job succeded for {self}, ready to start.") + await self._deploy( + self.commit_info, + self.name, + self.slug, + job_kind=k8s.DeploymentMode.stop, + ) if await self._patch(init_status=BuildInitStatus.succeeded): await github.notify_status( self.commit_info.repo, @@ -314,6 +338,12 @@ class Build(BaseModel): # restarting, and is notified of existing initialization jobs. return _logger.info(f"Initialization job failed for {self}.") + await self._deploy( + self.commit_info, + self.name, + self.slug, + job_kind=k8s.DeploymentMode.stop, + ) if await self._patch(init_status=BuildInitStatus.failed, desired_replicas=0): await github.notify_status( self.commit_info.repo,