Remove TODO from readme

See GitHub issues.
This commit is contained in:
Stéphane Bidoul 2021-11-13 13:33:47 +01:00
parent 7b6ce4f1bd
commit afe415b9e1
No known key found for this signature in database
GPG key ID: BCAB2555446B5B92
2 changed files with 36 additions and 48 deletions

View file

@ -21,19 +21,20 @@ Runboat has the following main components:
- A controller that performs the following tasks: - A controller that performs the following tasks:
- monitor deployments in a kubernetes namespaces to maintain the in-memory database; - monitor deployments in a kubernetes namespaces to maintain the in-memory database;
- on new deployments, trigger an initialization job to create the corresponding - on new deployments, trigger an initialization job to check out the GitHub repo,
postgres database and install the addons in it; install dependencies, create the corresponding postgres database and install the
addons in it;
- initialization jobs are started concurrently up to a configured limit; - initialization jobs are started concurrently up to a configured limit;
- when the initialization job succeeds, scale up the deployment, so it becomes - when the initialization job succeeds, scale up the deployment, so it becomes
accessible; accessible;
- when the initializaiton job fails, flag the deployment as failed; - when the initializaiton job fails, flag the deployment as failed;
- when there are too many deployments started, stop the oldest started; - when there are too many deployments started, stop the oldest started;
- when there are too many deployments, delete the oldest created; - when there are too many deployments, delete the oldest created;
- when a deployment is deleted, run a cleanp job to drop the database and delete - when a deployment is deleted, run a cleanup job to drop the database and delete
all kubernetes resources associated with the deployment. all kubernetes resources associated with the deployment.
When a deployment is stopped, the corresponding postgres database remains present, so When a deployment is stopped, the corresponding postgres database and filesystem volume
deployments can restart almost instantly. remains present, so deployments can restart almost instantly.
This approach allows the deployment of a very large number of builds which consume no This approach allows the deployment of a very large number of builds which consume no
memory nor CPU until they are started. The number of started deployment can also be memory nor CPU until they are started. The number of started deployment can also be
@ -45,6 +46,11 @@ resource-intensive part of the lifecycle of builds.
All state is stored in kubernetes resources (labels and annotations on deployments). The All state is stored in kubernetes resources (labels and annotations on deployments). The
controller can be stopped and restarted without losing state. controller can be stopped and restarted without losing state.
All the knowledge about *what* is deployed is in the
[src/runboat/kubefiles](./src/runboat/kubefiles) directory. The kubefile must implement
a specific contract to be managed by the runboat controller. This contract is described
in the [Kubernetes resources](#kubernetes-resources) section below.
## Requirements ## Requirements
For running the builds: For running the builds:
@ -67,27 +73,6 @@ For running the controller (runboat itself):
The controller can be run outside the kubernetes cluster or deployed inside it, or even The controller can be run outside the kubernetes cluster or deployed inside it, or even
in a different cluster. in a different cluster.
## Developing
- setup environment variables (start from `.env.sample`, the meaning of the environment
variables is documented in [settings.py](./src/runboat/settings.py))
- create a virtualenv, make sure to have pip>=21.3.1 and `pip install -c
requirements.txt -e .[test]`
- run with `uvicorn runboat.app:app --log-config=log-config.yaml`
- api documentation is at `http://localhost:8000/docs`
- run tests with `pytest` (environment variables used in tests are declared in
`.env.test`)
## Running in production
`gunicorn -w 1 -k runboat.uvicorn.RunboatUvicornWorker runboat.app:app`.
One and only one worker process !
Gunicorn also necessary so SIGINT/SIGTERM shutdowns after a few seconds. Since we use
`run_in_executor`, SIGINT/SIGTERM handling does not work very well, and gunicorn makes
it more robust. https://bugs.python.org/issue29309
## Kubernetes resources ## Kubernetes resources
All resources to be deployed in kubernetes for a build are in All resources to be deployed in kubernetes for a build are in
@ -128,36 +113,39 @@ resources:
- it removes the deployment finalizers and deletes resources matching the - it removes the deployment finalizers and deletes resources matching the
`runboat/build` label after the cleanup job succeeded. `runboat/build` label after the cleanup job succeeded.
## TODO ## Developing
Advanced prototype (min required to open the project): - setup environment variables (start from `.env.sample`, the meaning of the environment
variables is documented in [settings.py](./src/runboat/settings.py))
- create a virtualenv, make sure to have pip>=21.3.1 and `pip install -c
requirements.txt -e .[test]`
- run with `uvicorn runboat.app:app --log-config=log-config.yaml`
- api documentation is at `http://localhost:8000/docs`
- run tests with `pytest` (environment variables used in tests are declared in
`.env.test`)
- plug it on a bunch of OCA and shopinvader repos to test load ## Running in production
MVP: `gunicorn -w 1 -k runboat.uvicorn.RunboatUvicornWorker runboat.app:app`.
- better error handling in API (return 400 on user errors) One and only one worker process is allowed at the moment (although nothing really bad
- more tests should happen if there is more).
- look at other TODO in code to see if anything important remains
- basic UI (single page with a combo box to select repo and show builds by branch/pr,
with start/stop buttons)
- secure github webhooks
- deployment and more load testing
More: Gunicorn also necessary so SIGINT/SIGTERM shutdowns after a few seconds. Since we use
`run_in_executor`, SIGINT/SIGTERM handling does not work very well, and gunicorn makes
it more robust. https://bugs.python.org/issue29309
- streaming build/log and build/init-log api endpoints
- shiny UI ## Configuration
- websocket stream of build changes, for a dynamic UI
- handle PR close (delete all builds for PR) See environment variables examples in [Dockerfile](./Dockerfile),
- handle branch delete (delete all builds for branch) [.env.sample](./.env.sample) and their documentation in
- create builds for all supported repos on startup (goes with sticky branches) [settings.py](./src/runboat/settings.py).
- never undeploy last build of sticky branches
- configurable kubefiles directory
- even more tests
## Author and contributors ## Author and contributors
Authored by Stéphane Bidoul (@sbidoul). Authored by Stéphane Bidoul (@sbidoul).
Contributions welcome. Contributions welcome.
Do not hesitate to reach out for help on how to get started.

View file

@ -184,7 +184,7 @@ def _render_kubefiles(deployment_vars: DeploymentVars) -> Generator[Path, None,
__package__, "kubefiles" __package__, "kubefiles"
) as kubefiles_path, tempfile.TemporaryDirectory() as tmp_dir: ) as kubefiles_path, tempfile.TemporaryDirectory() as tmp_dir:
tmp_path = Path(tmp_dir) tmp_path = Path(tmp_dir)
# TODO async copytree, or make this whole _runder_kubefiles run_in_executor # TODO async copytree, or make this whole _render_kubefiles run_in_executor
shutil.copytree(kubefiles_path, tmp_path, dirs_exist_ok=True) shutil.copytree(kubefiles_path, tmp_path, dirs_exist_ok=True)
template = Template((tmp_path / "kustomization.yaml.jinja").read_text()) template = Template((tmp_path / "kustomization.yaml.jinja").read_text())
(tmp_path / "kustomization.yaml").write_text( (tmp_path / "kustomization.yaml").write_text(