107 lines
3.8 KiB
Markdown
107 lines
3.8 KiB
Markdown
# Cabinets
|
|
|
|
A cabinet is a **dependency container** a room can switch on: postgres, redis,
|
|
airflow. The vocabulary already had the word — `execution.container` in every
|
|
room's `config.json` is *"Cabinet — tool container"* — and until now nothing
|
|
stood behind it.
|
|
|
|
The problem it solves: a generated artifact knows what it needs and had no way
|
|
to say so. A shunt built from a client's spreadsheets holds its rows in memory
|
|
happily, but the moment you want them to survive a restart you need postgres,
|
|
and wiring postgres in meant hand-editing a room's `docker-compose.yml` and then
|
|
hand-editing the cluster too. A cabinet is that declaration, made once and read
|
|
by both paths.
|
|
|
|
## Switching one on
|
|
|
|
Add `cfg/<room>/data/cabinets.json`, the same shape as its sibling `data/*.json`
|
|
files:
|
|
|
|
```json
|
|
[
|
|
{ "name": "postgres" },
|
|
{ "name": "redis" },
|
|
{ "name": "airflow", "env": { "AIRFLOW_ADMIN_PASSWORD": "change-me" } }
|
|
]
|
|
```
|
|
|
|
Then build. The compose merge is a step in [Export / Compile](#export):
|
|
|
|
```bash
|
|
python build.py --cfg sample
|
|
cd gen/sample && docker compose up -d
|
|
```
|
|
|
|
`build.py` merges each cabinet's compose fragment into the room's
|
|
`docker-compose.yml`, declares its named volumes, and appends its settings to
|
|
`.env.example` — never to `.env`.
|
|
|
|
**A service the room already declares wins.** `cfg/amar/docker-compose.yml`
|
|
ships its own `db`; switching the postgres cabinet on will not replace it. The
|
|
build says so when it skips one:
|
|
|
|
```
|
|
Composing cabinets...
|
|
cabinets: redis, airflow
|
|
cabinets already declared by the room, left alone: postgres
|
|
```
|
|
|
|
Dependencies come along automatically. Airflow without a metadata database is a
|
|
container that exits on boot, so asking for `airflow` brings `postgres` and
|
|
`redis` with it, ordered so compose reads them before the thing that needs them.
|
|
|
|
## On a cluster
|
|
|
|
Every cabinet names a `rig_addon`. Where a room runs on kind rather than
|
|
compose, the same dependency installs as a rig addon of that name:
|
|
|
|
```bash
|
|
cd rig
|
|
PROFILE=data make cluster up # installs the addons too
|
|
|
|
kubectl -n data port-forward svc/postgres 5432:5432
|
|
kubectl -n data port-forward svc/airflow 8080:8080
|
|
```
|
|
|
|
The two paths are deliberately separate — compose for a laptop, manifests for a
|
|
cluster — and `rig_addon` is the thread between them, so the room declares the
|
|
dependency once either way. The addons generate their own passwords on first
|
|
install and keep them across re-runs, so re-running never rotates a credential
|
|
out from under something already connected.
|
|
|
|
## What ships
|
|
|
|
| Cabinet | Image | Notes |
|
|
| --- | --- | --- |
|
|
| `postgres` | `postgres:16-alpine` | healthcheck wired, so `depends_on: service_healthy` works |
|
|
| `redis` | `redis:7-alpine` | cache, and the broker for anything queue-shaped |
|
|
| `airflow` | `apache/airflow:2.10.4` | one container on `standalone`; needs postgres and redis |
|
|
|
|
## Writing one
|
|
|
|
```
|
|
soleprint/station/cabinets/<name>/
|
|
cabinet.json what it is, what it needs, what it exports
|
|
service.yml the compose service, verbatim
|
|
```
|
|
|
|
`cabinet.json`:
|
|
|
|
| Key | Purpose |
|
|
| --- | --- |
|
|
| `name` | must match the directory |
|
|
| `title`, `description` | shown on the station index |
|
|
| `service` | the key to merge under in `services:` (defaults to `name`) |
|
|
| `env` | settings and defaults, written to `.env.example` |
|
|
| `volumes` | named volumes to declare at the top level |
|
|
| `depends_on` | other cabinets that must come with it |
|
|
| `rig_addon` | the matching `rig/ctrl/addons/<name>.sh`, if there is one |
|
|
| `notes` | lines written into `.env.example` as comments |
|
|
|
|
`service.yml` is a plain compose fragment with one top-level key — the service
|
|
name. It stays YAML rather than being generated from JSON so it reads like the
|
|
file it becomes, and so anything compose supports is available without this tool
|
|
learning about it first.
|
|
|
|
Adding a cabinet is adding a directory. Nothing dispatches on the name.
|