feat: self-update of master and agents (#15) (#32)

This commit was merged in pull request #32.
This commit is contained in:
2026-10-13 10:17:52 +00:00
parent ec28d1e027
commit 850a670446
39 changed files with 1421 additions and 130 deletions
+11 -3
View File
@@ -58,8 +58,12 @@ DATABASE_URL=postgres://... go test -tags integration ./internal/master/store/
the agent's own container whose source equals its destination.** Mounts are read per
job (`ContainerInspect(SELF_ID)`) and checked after symlink resolution. This replaces
the old `STACKS_ROOT`.
- **Self-protection on the master**: a service is refused when its image repo equals the
repo of `AGENT_IMAGE` or the row has the `self` flag. The agent does not re-check.
- **Self-update** (an agent's own Compose service): only `up -d` runs in the helper
container; the new agent resumes the job (`updater.ResumeSelfUpdates`) before the runner
and connection start; the old agent records no result once SIGTERM cancels it. Jobs for
the agent's own service run last on the agent and the master starts them last in a
batch. An agent's own Swarm service is refused (`ReasonSelfSwarm`). Protocol 4 is needed,
also for any service with the `AGENT_IMAGE` repo.
- **Unknown message types are logged and ignored; malformed messages close the connection.**
- **Reconcile before routable**: the hub fails a reconnecting agent's jobs it does not
list in `known_jobs`, and only then accepts jobs for that connection.
@@ -124,6 +128,10 @@ DATABASE_URL=postgres://... go test -tags integration ./internal/master/store/
own Docker daemon at execution time.
- **`protocol.Service.ConfigFiles` is the raw comma-joined label string**, so `Service`
stays comparable with `==` (`inventory.Diff` depends on it).
- **Helper containers carry `se.shcizo.package-updater.self-update.*` labels** and are
not inventoried (the collector skips any container with the `.job` label). The label
strings are constants in `internal/agent/updater/selfupdate.go`, and the `.job` one is
repeated in `internal/agent/inventory`.
- **Swarm "succeeded" means the daemon accepted the new spec**, not that tasks converged.
- **Swarm updates need manager-node API access** for the agent doing the update.
- **The image's default entrypoint is `updater-agent`.** The master overrides it with
@@ -136,7 +144,7 @@ DATABASE_URL=postgres://... go test -tags integration ./internal/master/store/
knows about; only the waiting stops. The master never fails or cancels a timed-out job.
- **A webhook job's target is `<image_repo>:<request tag>`**, built from the service's own
repo, never from the request's image string. With an explicit target the "follows no tag"
refusal does not apply; removed, self, built and container still do.
refusal does not apply; removed, built, container and an agent's own Swarm service still do.
- **`available_*` is cleared by `FinishJob`** on success only when the job's `to_ref`
(as created, without `@digest`) equals `available_ref`, `available_at <= job.created_at`
(that version is now running) and, when the job's `to_ref` carries a digest, that digest