Merge branch 'rig-work'
This commit is contained in:
9
rig/.gitignore
vendored
9
rig/.gitignore
vendored
@@ -6,14 +6,7 @@ def
|
|||||||
.env.local
|
.env.local
|
||||||
ctrl/.env
|
ctrl/.env
|
||||||
|
|
||||||
# generated: the .dot is a build artifact rendered from arch/*.json, never hand-edited.
|
# the manifests the air-gapped installer image unpacks (docs/notes/Dockerfile.deps.md)
|
||||||
# The .svg IS committed — onboarding material should render in a repo browser.
|
|
||||||
arch/*.dot
|
|
||||||
# ctrl/Tiltfile.gen was here for a generator that no longer exists. ctrl/Tiltfile
|
|
||||||
# is now a real, committed file that derives its values when Tilt parses it, so
|
|
||||||
# there is nothing generated to ignore.
|
|
||||||
|
|
||||||
# binaries pulled by `make deps-bundle` for the air-gapped installer image
|
|
||||||
vendor
|
vendor
|
||||||
|
|
||||||
# Overlays that live with no version control of their own, or clones of their own
|
# Overlays that live with no version control of their own, or clones of their own
|
||||||
|
|||||||
1
rig/.version
Normal file
1
rig/.version
Normal file
@@ -0,0 +1 @@
|
|||||||
|
0.1.1
|
||||||
@@ -83,9 +83,8 @@ fetches with `curl`. A stock `debian:trixie-slim` has no curl — detection runs
|
|||||||
fine, then the first download dies with `curl: command not found` and an exit
|
fine, then the first download dies with `curl: command not found` and an exit
|
||||||
code of 127. That is the bootstrap paradox `ctrl/Dockerfile.deps` exists
|
code of 127. That is the bootstrap paradox `ctrl/Dockerfile.deps` exists
|
||||||
to kill — the installer carries its own toolchain so the host needs only Docker —
|
to kill — the installer carries its own toolchain so the host needs only Docker —
|
||||||
but building the image and running it are two different things, and only the
|
but `make deps image` only builds the image; running it is the step below.
|
||||||
build has a Makefile target today. **On a genuinely bare machine, run it by
|
**On a genuinely bare machine, run it by hand:**
|
||||||
hand:**
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make deps image # builds rig-deps:deps
|
make deps image # builds rig-deps:deps
|
||||||
@@ -207,13 +206,13 @@ never tracks it), or keep it anywhere else and name it by path.
|
|||||||
## Run it
|
## Run it
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make kind-up # idempotent create, then selects the context
|
make cluster up # idempotent create, then selects the context
|
||||||
make tilt-up # context + your assigned port
|
make tilt # context + your assigned port
|
||||||
```
|
```
|
||||||
|
|
||||||
`tilt-up` passes `--context kind-<name>` every time, which is the point of going
|
`make tilt` passes `--context kind-<name>` every time, which is the point of going
|
||||||
through `make` at all: tilt cannot deploy into whichever cluster you last looked
|
through `make` at all: tilt cannot deploy into whichever cluster you last looked
|
||||||
at.
|
at.
|
||||||
|
|
||||||
`make tilt-down` and `make kind-down` close the loop, and `make kind-reset` is
|
`make tilt down` and `make cluster down` close the loop, and `make cluster reset` is
|
||||||
delete-and-recreate for when a cluster wedges.
|
delete-and-recreate for when a cluster wedges.
|
||||||
|
|||||||
233
rig/README.md
233
rig/README.md
@@ -1,200 +1,99 @@
|
|||||||
# rig
|
# rig
|
||||||
|
|
||||||
A runnable local model of a large, regulated estate — legacy and new side by
|
rig builds a disposable Kubernetes environment on your machine, so you can see how a system
|
||||||
side. Its job is onboarding and exploration, not a production replica: most
|
fits together without access to any of it. It is for **onboarding and exploration**, not a
|
||||||
services are deliberately mocked, because what has to be faithful is the
|
production replica.
|
||||||
topology, not the workloads.
|
|
||||||
|
|
||||||
## Prerequisite
|
Most services in it are **not real**. What has to be faithful is the topology: names, ports,
|
||||||
|
dependency order, who can reach whom, and how it fails. That is what makes a whole estate fit on
|
||||||
**Docker.** Nothing else — no curl, no jq, no python, no apt repositories.
|
a laptop. A real 20-service platform does not fit once in 14 GB; stubs of about 30 MB each fit
|
||||||
|
three times.
|
||||||
### Starting from plain Windows
|
|
||||||
|
|
||||||
Everything here is bash and runs *inside* a Linux shell, so on a Windows machine
|
|
||||||
that means WSL. Nothing in rig installs WSL, and nothing will: `wsl --install`
|
|
||||||
enables Windows features and requires a reboot, which is not something a script
|
|
||||||
should do to a machine on your behalf — and there is no tested undo for it.
|
|
||||||
|
|
||||||
From an elevated PowerShell or Command Prompt, once:
|
|
||||||
|
|
||||||
```powershell
|
Under the hood it is a kind cluster, a local image registry and a Tilt dev loop, each with its
|
||||||
wsl --install
|
own name and ports, so several environments run side by side. What runs on it is an
|
||||||
```
|
**overlay**: a folder outside rig that holds one use case.
|
||||||
|
|
||||||
Then reboot and open the Linux shell it installed.
|
## Using rig from a project
|
||||||
|
|
||||||
**If you cloned this on the Windows side, copy it into WSL before carrying on.**
|
You don't need to read rig to use it. Get a release (`rig-<version>.tar.gz`, or a checkout at
|
||||||
WSL can reach the Windows drives at `/mnt/c`, and working from there mostly
|
the tag `rig-<version>`), extract it anywhere, and point the project at it (`RIG_DIR`). Then run
|
||||||
functions — slowly — but file watching does not: that filesystem raises no
|
`make check`: it says what the machine still lacks and which command comes next. `.version`
|
||||||
inotify events, so anything watching for edits silently stops seeing them.
|
names the release; a project records the one it was last run against. See
|
||||||
|
[`docs/notes/overlay.md`](docs/notes/overlay.md).
|
||||||
|
|
||||||
```bash
|
## Prerequisite
|
||||||
cp -r /mnt/c/Users/<you>/rig ~/rig
|
|
||||||
cd ~/rig
|
|
||||||
```
|
|
||||||
|
|
||||||
`make deps` reports it if you are running from `/mnt/...`. Then carry on below.
|
**Docker.** Nothing else: no curl, jq, python or apt repositories.
|
||||||
|
|
||||||
If it fails, the usual causes give unhelpful messages:
|
On Windows, rig runs inside WSL. Run `wsl --install` once, from an elevated shell, then reboot.
|
||||||
|
Work inside the Linux filesystem, not `/mnt/c`: file watching doesn't work there, and
|
||||||
|
`make deps` warns about it. Git Bash, MSYS and Cygwin don't work (no `/proc`, no docker socket).
|
||||||
|
|
||||||
| symptom | cause |
|
| symptom | cause |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| "the virtual machine could not be started" | virtualization disabled in BIOS/UEFI |
|
| "the virtual machine could not be started" | virtualization disabled in BIOS/UEFI |
|
||||||
| the command is not recognised | Windows build too old — needs 2004 or later |
|
| the command is not recognised | Windows build too old (needs 2004 or later) |
|
||||||
| the install starts, then nothing works | a reboot is still pending |
|
| the install starts, then nothing works | a reboot is still pending |
|
||||||
|
|
||||||
Running the scripts from **Git Bash, MSYS or Cygwin does not work** — those look
|
On a machine with nothing but Docker, [BOOTSTRAP.md](BOOTSTRAP.md) runs the toolchain through
|
||||||
close enough to a Linux shell to get started and then fail without `/proc` or a
|
the installer container.
|
||||||
docker socket. `ctrl/deps.sh` detects that and says so rather than letting you
|
|
||||||
find out the slow way.
|
|
||||||
|
|
||||||
## Read the docs first
|
|
||||||
|
|
||||||
```bash
|
|
||||||
make docs # serves on localhost, prints the URL
|
|
||||||
```
|
|
||||||
|
|
||||||
They run before anything is installed, which matters because they are the
|
|
||||||
instructions for everything else. No cluster and no toolchain required.
|
|
||||||
|
|
||||||
Why the code is the way it is — the reasoning, measurements and gotchas — lives
|
|
||||||
in [`docs/notes/`](docs/notes/), one file per script, so the code keeps short comments.
|
|
||||||
|
|
||||||
## Then
|
|
||||||
|
|
||||||
```bash
|
|
||||||
make check # is this machine ready? short; `make check all` for every detail
|
|
||||||
make deps # install the toolchain (add `core` on a managed machine)
|
|
||||||
make cluster up # cluster + registry + the profile's addons
|
|
||||||
```
|
|
||||||
|
|
||||||
That is the whole setup. `make cluster up` also starts this environment's local
|
## What it does
|
||||||
registry and wires it into the node, so an image built locally is pullable by the
|
|
||||||
cluster without going near docker.io. `make check` shows its port, among
|
|
||||||
everything else:
|
|
||||||
|
|
||||||
```bash
|
| command | does |
|
||||||
make check # ... registry localhost:<port> (running)
|
| --- | --- |
|
||||||
docker build -t localhost:<port>/app:1 .
|
| `make docs` | serves the docs locally; works before anything is installed |
|
||||||
docker push localhost:<port>/app:1
|
| `make check` | is this machine ready? memory, toolchain, cluster, the next command (`check all` for every detail) |
|
||||||
kubectl --context kind-$(basename $PWD) run app --image=localhost:<port>/app:1
|
| `make deps` | installs the pinned toolchain (`deps core` on a managed machine) |
|
||||||
```
|
| `make cluster up` | the cluster, its registry and the configured addons (`down`, `reset`, `list`, `free`) |
|
||||||
|
| `make tilt` | the dev loop: rig's part, then the overlay's Tiltfile |
|
||||||
|
| `make selftest` | checks rig itself |
|
||||||
|
| `make help` | every target |
|
||||||
|
|
||||||
The port block is derived from the directory name, so two copies of rig never
|
Every verb is a `Makefile` target calling one script in `ctrl/`. The aliases (`kind-up`,
|
||||||
collide — nothing to configure. `make check all` lists it; `bash ctrl/ports.sh persist`
|
`tilt-up`, …) call the same scripts.
|
||||||
pins it into `ctrl/.env` if you want it fixed:
|
|
||||||
|
|
||||||
```bash
|
## Overlays
|
||||||
make cluster list # every cluster on this machine, with memory
|
|
||||||
make cluster free # stop the others if memory is tight
|
|
||||||
make cluster down # remove this cluster and its registry
|
|
||||||
```
|
|
||||||
|
|
||||||
**The verbs are yours to change.** `cluster` is the script — `ctrl/cluster.sh` —
|
An overlay holds its settings (`rig.env`), its manifests (`k8s/overlays/dev`), its Tiltfile and
|
||||||
and every spelling above is a `Makefile` target that calls it. `make kind-up` is
|
images, its addons, and its kind config if it needs one. rig reads it and never writes into it.
|
||||||
an alias for `make cluster up`, kept because the other projects on this machine
|
|
||||||
answer to that spelling and muscle memory spans repos rather than stopping at
|
|
||||||
one. Nothing outside the `Makefile` reads these names, so rename them, drop the
|
|
||||||
ones you never type, or add whatever your own projects already say: each alias
|
|
||||||
is two lines at the bottom of the file, calling the same script the canonical
|
|
||||||
target does.
|
|
||||||
|
|
||||||
**`make tilt` works on a fresh copy, unedited.** rig's `ctrl/Tiltfile` does
|
|
||||||
rig's part — identity, context guard, registry, the manifests — and then includes
|
|
||||||
the overlay's own Tiltfile. With no overlay named that is `examples/starter`, so
|
|
||||||
the dev loop comes up with its two examples running and nothing to configure.
|
|
||||||
|
|
||||||
It hardcodes nothing. It asks `ctrl/ports.sh active` for this environment's
|
|
||||||
cluster name, kube context, ports and paths — the same values every other rig
|
|
||||||
script resolves through `ctrl/lib/config.sh` — so a copied and renamed rig, or a
|
|
||||||
moved overlay, deploys into its own cluster with no edits.
|
|
||||||
|
|
||||||
`make help` lists every target. `make selftest` checks rig itself, the installer's
|
|
||||||
detection included; `make selftest install` runs the installer on clean containers
|
|
||||||
([`docs/notes/installer-testing.md`](docs/notes/installer-testing.md)).
|
|
||||||
|
|
||||||
On a machine where Docker really is the only thing installed, `make deps` has
|
|
||||||
nothing to download with — see [BOOTSTRAP.md](BOOTSTRAP.md), which runs the
|
|
||||||
toolchain through the installer container and carries on to scaffolding and running
|
|
||||||
a new project.
|
|
||||||
|
|
||||||
## What runs is an overlay
|
|
||||||
|
|
||||||
rig is the machine: toolchain, cluster, registry, port block, the dev loop's
|
|
||||||
plumbing. What runs on it is an **overlay** — one folder, outside rig's version
|
|
||||||
control, holding a use case: its settings (`rig.env`), its manifests
|
|
||||||
(`k8s/overlays/dev`), its images and Tiltfile, its addons, its kind config if it
|
|
||||||
needs its own. rig reads it and never writes into it. See
|
|
||||||
[`docs/notes/overlay.md`](docs/notes/overlay.md).
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cp -r examples/starter local/myenv # local/ is gitignored
|
cp -r examples/starter local/myenv # local/ is ignored
|
||||||
OVERLAY=local/myenv make cluster up # or OVERLAY=local/myenv in ctrl/.env
|
OVERLAY=local/myenv make cluster up
|
||||||
OVERLAY=local/myenv make tilt
|
OVERLAY=local/myenv make tilt
|
||||||
```
|
```
|
||||||
|
|
||||||
An overlay can also be a repo of its own, anywhere, or a project folder that
|
With no overlay named, rig runs `examples/starter`. [`examples/data`](examples/data/) adds
|
||||||
carries rig at `<project>/rig/` with a three-line forwarding Makefile.
|
postgres, redis and airflow as plain manifests. A project can carry rig at `./rig`, or keep it
|
||||||
|
anywhere and name it with `RIG_DIR`.
|
||||||
|
|
||||||
## One environment per folder
|
The cluster name, context, image tags and ports derive from the overlay folder's name (rig's
|
||||||
|
own, with no overlay), so environments never collide, and one's teardown never touches another.
|
||||||
|
|
||||||
Cluster name, kubectl context, image tags and the host port block all derive
|
## Configuration
|
||||||
from a folder name — the overlay's when one is named, else rig's own — so copies
|
|
||||||
never collide and neither one's teardown can touch the other. Two overlays run
|
|
||||||
side by side from one rig; two copies of rig do too.
|
|
||||||
|
|
||||||
## Profiles
|
Layers, weakest first: built-in defaults < `ctrl/versions.env` < the profile < the overlay's
|
||||||
|
`rig.env` < `ctrl/.env` < the command line. A profile (`ctrl/env.d/`) is optional and says how
|
||||||
|
this machine reaches the world: `mirror` (a pull-through cache) and `offline` (air-gapped) ship
|
||||||
|
as examples. The cluster itself is one kind template: the overlay's, or rig's one-node default.
|
||||||
|
|
||||||
**rig needs no profile.** With none named it runs on built-in defaults: one node,
|
rig's own addons make the cluster work: `metallb` (LoadBalancer addresses), `cert-manager` (a
|
||||||
no addons, a local registry, the newest Kubernetes version it pins. A profile is
|
local CA), `metrics-server` (`kubectl top`). A workload's database, cache or scheduler belongs to
|
||||||
an optional file in `ctrl/env.d/`, named by `PROFILE`, that says how this machine
|
its overlay. There is no ingress controller: services are reached through LoadBalancer
|
||||||
reaches the world. rig ships two as **examples**; copy one to use it (the copy is
|
addresses, or through the overlay's own gateway on the environment's HTTP port.
|
||||||
gitignored):
|
|
||||||
|
|
||||||
| example | what it changes |
|
## Where things are
|
||||||
| --- | --- |
|
|
||||||
| `mirror.env.example` | images through a pull-through cache of an internal registry |
|
|
||||||
| `offline.env.example` | air-gapped: everything from a preloaded local registry |
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cp ctrl/env.d/mirror.env.example ctrl/env.d/mirror.env
|
|
||||||
PROFILE=mirror make cluster up
|
|
||||||
```
|
```
|
||||||
|
Makefile the verbs
|
||||||
The layers, weakest first: built-in defaults < `ctrl/versions.env` < the profile
|
.version this release: patch and minor steps are edits here; milestones get a tag
|
||||||
< the overlay's `rig.env` < `ctrl/.env` < your command line.
|
ctrl/ one script per verb; lib/config.sh (settings and layers); Tiltfile (rig's
|
||||||
|
half of the dev loop); k8s/kind-config.yaml.tpl; addons/; env.d/; versions.env
|
||||||
The **cluster itself** is one file: the overlay's `kind-config.yaml.tpl` if it has
|
docs/ index.html (make docs); notes/, one per script: why the code is as it is
|
||||||
one, else rig's `ctrl/k8s/kind-config.yaml.tpl` (one node). To change it — more
|
examples/ starter (the default overlay), data (postgres, redis, airflow)
|
||||||
nodes, other port mappings, mounts — edit it and `make cluster reset`. The node
|
standalone/ single-file kits generated from ctrl/ (make standalone); never edited by hand
|
||||||
count is read back out of it, so there is nothing to drift.
|
tests/ the installer's host fixtures
|
||||||
|
BOOTSTRAP.md from a bare machine with only Docker
|
||||||
## Addons
|
STALE.md assumptions withdrawn, each checked by selftest
|
||||||
|
|
||||||
Each addon is its own idempotent script, and `ADDONS` names the ones to install,
|
|
||||||
in order. Adding one is adding a file — there is no dispatcher to edit. An
|
|
||||||
overlay's `addons/<name>.sh` is found before rig's own.
|
|
||||||
|
|
||||||
**There is no ingress controller, deliberately.** They pin a narrow window of
|
|
||||||
Kubernetes versions, so depending on one would constrain which k8s a rig can be
|
|
||||||
built with — and running a trailing-edge control plane is often the point.
|
|
||||||
Services are reached through MetalLB and `type: LoadBalancer`, which carries no
|
|
||||||
such constraint and is also what a real cluster does.
|
|
||||||
|
|
||||||
rig's own addons make the cluster work:
|
|
||||||
|
|
||||||
| Addon | Does |
|
|
||||||
| --- | --- |
|
|
||||||
| `metallb` | gives `type: LoadBalancer` an address it can actually reach |
|
|
||||||
| `cert-manager` | a local CA, so TLS works offline |
|
|
||||||
| `metrics-server` | makes `kubectl top` work on kind |
|
|
||||||
|
|
||||||
What a workload needs — a database, a cache, a scheduler — belongs to its
|
|
||||||
overlay. [`examples/data`](examples/data/) carries postgres, redis and airflow as
|
|
||||||
plain manifests (no helm: a chart repo is a network dependency), with passwords
|
|
||||||
generated on first install and kept across re-runs:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
OVERLAY=examples/data make cluster up
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
0.1.0
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
# Machine-local config. Copy to ctrl/.env (gitignored) and edit.
|
# Machine-local config. Copy to ctrl/.env (gitignored) and edit.
|
||||||
# Cluster SHAPE: an optional profile in ctrl/env.d/. Architecture MODEL: arch/<name>.json.
|
# Cluster SHAPE: an optional profile in ctrl/env.d/.
|
||||||
# Notes: docs/notes/env.md
|
# Notes: docs/notes/env.md
|
||||||
|
|
||||||
# A profile in ctrl/env.d/ to build. Empty means rig's built-in defaults, which
|
# A profile in ctrl/env.d/ to build. Empty means rig's built-in defaults, which
|
||||||
|
|||||||
@@ -386,7 +386,8 @@ docker load < rig.tgz && make cluster up PROFILE=offline <span clas
|
|||||||
derived from the cluster's Docker network at install time, because Docker picks
|
derived from the cluster's Docker network at install time, because Docker picks
|
||||||
that subnet and it differs between machines.</p>
|
that subnet and it differs between machines.</p>
|
||||||
<p>Those addresses are reachable from the Linux side, including inside WSL. A
|
<p>Those addresses are reachable from the Linux side, including inside WSL. A
|
||||||
browser on Windows has no route to them: use the ingress host ports instead.</p>
|
browser on Windows has no route to them: use the environment's HTTP port instead, where
|
||||||
|
an overlay's gateway listens (its kind config maps it to the host).</p>
|
||||||
|
|
||||||
<h3>Networking and memory</h3>
|
<h3>Networking and memory</h3>
|
||||||
<p>The cluster uses kind's built-in networking, which does enforce standard
|
<p>The cluster uses kind's built-in networking, which does enforce standard
|
||||||
@@ -417,9 +418,9 @@ OVERLAY=local/myenv make cluster up
|
|||||||
</code></pre>
|
</code></pre>
|
||||||
<p>With none named, rig runs its own <code>examples/starter</code>.
|
<p>With none named, rig runs its own <code>examples/starter</code>.
|
||||||
<code>examples/data</code> carries postgres, redis and airflow as an overlay's own
|
<code>examples/data</code> carries postgres, redis and airflow as an overlay's own
|
||||||
addons. A project can also carry rig at <code><project>/rig/</code> and be
|
addons. A project can carry rig at <code>./rig</code>, or keep it anywhere and name
|
||||||
the overlay itself, with a three-line forwarding Makefile — see
|
it with <code>RIG_DIR</code>. <code>.version</code> names the release; the project
|
||||||
<code>docs/notes/overlay.md</code>.</p>
|
records the one it was last run against. See <code>docs/notes/overlay.md</code>.</p>
|
||||||
|
|
||||||
<h3>What runs in it</h3>
|
<h3>What runs in it</h3>
|
||||||
<p>Each component is one of three things, and switching between them is a
|
<p>Each component is one of three things, and switching between them is a
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ docker build -f ctrl/Dockerfile.deps --target deps -t <slug>-deps .
|
|||||||
docker build -f ctrl/Dockerfile.deps --target deps-full -t <slug>-deps:full .
|
docker build -f ctrl/Dockerfile.deps --target deps-full -t <slug>-deps:full .
|
||||||
```
|
```
|
||||||
|
|
||||||
`deps-full` bakes every pinned binary in at build time, and the manifests rig's own addons apply (metallb, cert-manager, metrics-server). `docker save` it and you have the whole installer as one file to carry into an air-gapped network. There, put the manifests where the addons look for them:
|
`make deps image full` builds the second. `deps-full` bakes every pinned binary in at build time, and the manifests rig's own addons apply (metallb, cert-manager, metrics-server). `docker save` it and you have the whole installer as one file to carry into an air-gapped network. There, put the manifests where the addons look for them:
|
||||||
|
|
||||||
```
|
```
|
||||||
docker run --rm -v "$PWD/vendor:/out/vendor" rig-deps:full manifests --to /out/vendor/manifests
|
docker run --rm -v "$PWD/vendor:/out/vendor" rig-deps:full manifests --to /out/vendor/manifests
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ Read positionally, so the order is a contract; ctrl/selftest.sh pins it. The two
|
|||||||
|
|
||||||
`OVERLAY` and `CLUSTER` given as make arguments (`make tilt OVERLAY=local/x`) are handed to that `$(shell ...)` explicitly. Before make 4.4, `$(shell)` runs with make's own environment and does not see command-line variables, while the recipes do: tilt would then be told one context and the Tiltfile would guard on another. An overlay's forwarder avoids the question by putting `OVERLAY` in the environment.
|
`OVERLAY` and `CLUSTER` given as make arguments (`make tilt OVERLAY=local/x`) are handed to that `$(shell ...)` explicitly. Before make 4.4, `$(shell)` runs with make's own environment and does not see command-line variables, while the recipes do: tilt would then be told one context and the Tiltfile would guard on another. An overlay's forwarder avoids the question by putting `OVERLAY` in the environment.
|
||||||
|
|
||||||
This used to be sed over ctrl/.env plus a slug computed in the Makefile, which is a SECOND derivation of values lib/config.sh already owns, and the two could disagree about the port after `ports.sh persist`, or about the name for any directory whose sanitised form differs from its raw one. One source now; the Tiltfile reads the same line.
|
One source: lib/config.sh owns these values, and the Tiltfile reads the same line. A second derivation in the Makefile could disagree about the port after `ports.sh persist`, or about the name of any directory whose sanitised form differs from its raw one.
|
||||||
|
|
||||||
## CLUSTER / KCTX fallback
|
## CLUSTER / KCTX fallback
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ The fallback matters: ports.sh sources config.sh, and if a profile or .env is br
|
|||||||
|
|
||||||
## ARGS as .PHONY
|
## ARGS as .PHONY
|
||||||
|
|
||||||
Words after the target become the script's subcommand; each gets a no-op rule so make does not treat them as goals. They are also marked PHONY, because some of those words name real directories. `cfg`, `ctrl`, `docs`, `gen` and `init` all exist at this level, and make considers a target that is an existing directory already built, so `make build ctrl` ran the build and then printed "make: 'ctrl' is up to date". The empty rule is not enough on its own; only .PHONY stops make consulting the filesystem.
|
Words after the target become the script's subcommand; each gets a no-op rule so make does not treat them as goals. They are also marked PHONY, because some of those words name real directories (`ctrl`, `docs`, `examples`), and make considers a target that is an existing directory already built: without it, `make docs ctrl` would print "make: 'ctrl' is up to date". The empty rule is not enough on its own; only .PHONY stops make consulting the filesystem.
|
||||||
|
|
||||||
## tilt: --port guard
|
## tilt: --port guard
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ switch for the host part, so the standalone `rigdeps.sh detect` is short too.
|
|||||||
rig knows what a node costs (NODE_MB), not what a workload does, so the parts come from the
|
rig knows what a node costs (NODE_MB), not what a workload does, so the parts come from the
|
||||||
overlay's rig.env: `MEMORY_BUDGET="name=MB ..."`, in the order listed; a 0 is left out, and an
|
overlay's rig.env: `MEMORY_BUDGET="name=MB ..."`, in the order listed; a 0 is left out, and an
|
||||||
entry that is not `name=MB` is a `!` line. rig.env is sourced, so an overlay can size a part by
|
entry that is not `name=MB` is a `!` line. rig.env is sourced, so an overlay can size a part by
|
||||||
its own knob (poc_rig's airflow follows its mode). When one part outweighs the rest together
|
its own knob (an airflow sized by the mode the overlay runs it in). When one part outweighs the rest together
|
||||||
(and is at least 1 GB), check names it as the first thing to switch off; `MEMORY_BUDGET_TIP`
|
(and is at least 1 GB), check names it as the first thing to switch off; `MEMORY_BUDGET_TIP`
|
||||||
says how, in the overlay's words. No budget: one `?` row says where to add it.
|
says how, in the overlay's words. No budget: one `?` row says where to add it.
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## ctrl/.env.example: header
|
## ctrl/.env.example: header
|
||||||
|
|
||||||
Machine-local config. Copy to ctrl/.env (gitignored) and edit. The cluster SHAPE is an optional profile in ctrl/env.d/ — see the *.env.example there. The architecture MODEL lives in arch/<name>.json — not in .env either.
|
Machine-local config. Copy to ctrl/.env (gitignored) and edit. The cluster SHAPE is an optional profile in ctrl/env.d/ — see the *.env.example there.
|
||||||
|
|
||||||
## ctrl/.env.example: CLUSTER
|
## ctrl/.env.example: CLUSTER
|
||||||
|
|
||||||
|
|||||||
@@ -168,13 +168,16 @@ No search path: an unset `RIG_DIR` means `./rig`, and nothing else is tried. Mov
|
|||||||
changes nothing in the cluster's name, context or ports; moving or renaming the overlay
|
changes nothing in the cluster's name, context or ports; moving or renaming the overlay
|
||||||
folder does.
|
folder does.
|
||||||
|
|
||||||
`VERSION`, at rig's top, names the rig. It travels with the folder, vendored, a
|
`.version`, at rig's top, names the rig. It travels with the folder, vendored, a
|
||||||
worktree or a plain copy, and needs no git. A project records the one it was last run
|
worktree, a plain copy or a `git archive` release, and needs no git. Patch and minor
|
||||||
against and warns on another; it does not refuse:
|
steps are edits to that file, with no tag; a `rig-<version>` tag marks a milestone only.
|
||||||
|
A project records the version it was last run against and warns on another; it does not
|
||||||
|
refuse. Releases before 0.1.1 carry `VERSION` instead, so the project reads that as a
|
||||||
|
fallback:
|
||||||
|
|
||||||
```make
|
```make
|
||||||
RIG_REF := 0.1.0
|
RIG_REF := 0.1.1
|
||||||
RIG_AT := $(strip $(shell cat '$(RIG_DIR)/VERSION' 2>/dev/null))
|
RIG_AT := $(strip $(shell cat '$(RIG_DIR)/.version' 2>/dev/null || cat '$(RIG_DIR)/VERSION' 2>/dev/null))
|
||||||
ifneq ($(RIG_AT),$(RIG_REF))
|
ifneq ($(RIG_AT),$(RIG_REF))
|
||||||
$(warning rig at $(RIG_DIR) is $(or $(RIG_AT),unversioned); this overlay was last run against rig $(RIG_REF))
|
$(warning rig at $(RIG_DIR) is $(or $(RIG_AT),unversioned); this overlay was last run against rig $(RIG_REF))
|
||||||
endif
|
endif
|
||||||
@@ -183,18 +186,3 @@ endif
|
|||||||
`rig.env` holds no secrets, by this contract. A repository whose `.gitignore` has a
|
`rig.env` holds no secrets, by this contract. A repository whose `.gitignore` has a
|
||||||
broad `*.env` (a common secrets rule) would still hide it, so an overlay living in
|
broad `*.env` (a common secrets rule) would still hide it, so an overlay living in
|
||||||
such a repo re-includes it in its own `.gitignore`: `!rig.env`.
|
such a repo re-includes it in its own `.gitignore`: `!rig.env`.
|
||||||
|
|
||||||
## Moving a copied rig to an overlay
|
|
||||||
|
|
||||||
A rig copied into a project and edited there splits cleanly:
|
|
||||||
|
|
||||||
| was, in the copy | goes to |
|
|
||||||
| --- | --- |
|
|
||||||
| `ctrl/k8s/base`, `ctrl/k8s/overlays` | `k8s/` |
|
|
||||||
| the workload parts of `ctrl/Tiltfile` | `Tiltfile` (paths now relative to the overlay) |
|
|
||||||
| `ctrl/env.d/<name>.env` | `rig.env` |
|
|
||||||
| edits to `ctrl/k8s/kind-config.yaml.tpl` | `kind-config.yaml.tpl` (`${HOST_WORKDIR}` → `${OVERLAY_DIR}`) |
|
|
||||||
| workload addons | `addons/` |
|
|
||||||
| Dockerfiles for the workload | beside the Tiltfile |
|
|
||||||
| `ctrl/.env` | `rig/ctrl/.env` (this machine's; drop a `MANIFESTS_DIR=ctrl/k8s/overlays/dev` line) |
|
|
||||||
| everything else of rig's | replaced by rig as it is |
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ So the loop is generated FROM the list: add a key to `CONFIG_OVERRIDABLE` and th
|
|||||||
|
|
||||||
## one derivation, not three
|
## one derivation, not three
|
||||||
|
|
||||||
The Makefile used to compute the cluster name itself and sed `TILT_PORT` out of `ctrl/.env`: a second derivation of values `lib/config.sh` already owns, which could disagree with it after `ports.sh persist`. It now reads `ports.sh active`. Nothing structurally prevents the sed coming back, so the agreement is asserted against the real `make -n` output rather than against the source.
|
The Makefile reads `ports.sh active` rather than deriving the cluster name and `TILT_PORT` itself: a second derivation of values `lib/config.sh` already owns could disagree with it after `ports.sh persist`. Nothing structurally prevents one coming back, so the agreement is asserted against the real `make -n` output rather than against the source.
|
||||||
|
|
||||||
`--no-print-directory` and a grep, not `tail -1`: run from `make selftest` this is a RECURSIVE make, and the "Entering/Leaving directory" lines go to STDOUT. `tail -1` then reads "make[1]: Leaving directory ..." and both checks fail, but only when invoked through make, never when the script is run directly. A test that passes one way and fails the other is worse than no test.
|
`--no-print-directory` and a grep, not `tail -1`: run from `make selftest` this is a RECURSIVE make, and the "Entering/Leaving directory" lines go to STDOUT. `tail -1` then reads "make[1]: Leaving directory ..." and both checks fail, but only when invoked through make, never when the script is run directly. A test that passes one way and fails the other is worse than no test.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user