Repository navigation
feat(render): label docker resources with a session ID - #431
Conversation
5ea578b to
305e286
Compare
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com>
305e286 to
c61fed7
Compare
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Merge Risk: ⚪ Minimal · up to
|
Bump github.com/crossplane/cli/v2 to 9703fb5 (crossplane/cli#431, not yet released), which lets the caller set the render session ID that the engine labels its containers and network with. The run's ID is now that session ID: - Pass it as EngineFlags.SessionID to the docker and local engines, and set the runtime-docker-session annotation on a copy of each Function, so a session annotation the Function already carries cannot hide its container from the run. - Stop naming function containers for the run and stop creating our own render network: the engine creates and labels its own. - Reap containers, then networks, by the session and managed-by labels. Close removes the run's containers before the engine's own cleanup removes its network, then sweeps any of the run's networks left over. - Keep the engine's cleanup when starting functions fails, rather than running it straight away while orphaned containers still hold the network. Upstream moved to the moby/moby client, so dockerrun's Docker interface now uses its types and gains NetworkList. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com>
… died (#525) (#545) * fix(diff): reclaim function containers and networks left by runs that died (#525) A run that dies without cleaning up (SIGKILL, OOM, a second Ctrl+C, a CI runner tearing down the job) leaves its function containers and the crossplane-render-* network behind. Nothing tied them to the run that made them, so no later run reclaimed them, and leaked networks eventually exhaust Docker's address pools. The render engine now ties what it creates to its run, through a new cmd/diff/dockerrun package: - Every function container is named <fn>-<version>-diff-<run ID>. The upstream Docker runtime can't label a function container, but it does honour the runtime-docker-name annotation. The engine takes over this naming from CachedFunctionProvider, so `xr` containers are named too, and the provider is now only a cache. - The docker engine renders on a crossplane-diff-<run ID> network that the run creates and labels, instead of the unattributable network upstream would create. A network named by CROSSPLANE_DIFF_DOCKER_NETWORK is used but never created or removed. - A run holds a flock on <user cache dir>/crossplane-diff/runs/<run ID>.lock while it has resources. Before starting any container, it removes the containers (by name, or by network membership for the unnamed render containers), then the network, of every run whose lease it can lock, i.e. whose process is dead. With no dead run this costs no Docker call at all. - On exit the run sweeps its own resources the same way, which also catches containers upstream cleanup leaves behind. It keeps its lease if anything is left, so the next run retries. Reaping is best effort: a failure is a warning and never fails the diff. Live runs and resources crossplane-diff did not name are never touched. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com> * refactor(diff): keep EngineRenderFn.Render under the cognitive-complexity limit Move preparing the run and naming the functions' containers into claimForRun, and drop a nolint directive golangci-lint reports unused. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com> * docs(design): note that a lease does not record its run's Docker daemon Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com> * refactor(dockerrun): reap each dead run as its lease is taken Drop the shared container listing and the dead-run bookkeeping it needed. Each dead run is reaped right after its lease is locked, with one ContainerList per dead run. Dead runs are rare and few, so the extra listing costs nothing that matters, and reap no longer has a second mode where the caller supplies the listing. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com> * refactor(dockerrun): drop the lease identity re-check in tryLease The re-check guarded against a second reaper locking a lease file that the first had already reclaimed and unlinked. That reaper can only take the lock after the first has finished and closed it, so its own reap lists no containers for the run and finds the network gone: reaping twice is harmless, and the check bought nothing. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com> * refactor(diff): fold claimFunction into claimForRun claimFunction had one caller and existed only to copy and set two annotations. Do that in claimForRun's loop and keep its rationale in claimForRun's doc comment. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com> * fix(dockerrun): reclaim Docker resources by render session label Bump github.com/crossplane/cli/v2 to 9703fb5 (crossplane/cli#431, not yet released), which lets the caller set the render session ID that the engine labels its containers and network with. The run's ID is now that session ID: - Pass it as EngineFlags.SessionID to the docker and local engines, and set the runtime-docker-session annotation on a copy of each Function, so a session annotation the Function already carries cannot hide its container from the run. - Stop naming function containers for the run and stop creating our own render network: the engine creates and labels its own. - Reap containers, then networks, by the session and managed-by labels. Close removes the run's containers before the engine's own cleanup removes its network, then sweeps any of the run's networks left over. - Keep the engine's cleanup when starting functions fails, rather than running it straight away while orphaned containers still hold the network. Upstream moved to the moby/moby client, so dockerrun's Docker interface now uses its types and gains NetworkList. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com> * fix(diff): drop a function's container name from the run's copy The Docker runtime reuses an existing container of the runtime-docker-name name without relabelling it, so concurrent runs, or concurrent engines in one test binary, shared one container that the first to finish removed. The integration fixtures' -it names made the suite fail exactly that way. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com> * test(it): drop Docker runtime annotations the render engine overrides The engine now sets the session and cleanup annotations itself and drops any container name, so the fixtures' annotations did nothing. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com> * docs: describe run ownership by render session labels Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com> * docs: reconcile run-ownership docs with main's env-injecting provider Main added EnvInjectingFunctionProvider, whose design-doc entry relied on CachedFunctionProvider's per-run container names. The run now starts its own unnamed containers instead, so say that. Regenerate diff-call-sequence.svg from the merged mermaid source, and describe function container reuse in CLAUDE.md as the engine does it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com> * test(dockerrun): assert what runs leave behind, not the Docker calls they make The dockerrun and render engine tests asserted the sequence and count of Docker calls. Replace them with end-state assertions over a shared fake Docker host (testutils.FakeDocker) that behaves like the daemon where it matters: label filters apply as MatchKVList does, stopped containers are listed only with All, running ones are removed only with Force, and a network with an attached container cannot be removed. A wrong filter, flag or removal order now leaves something behind and fails on outcome. Fold Start's cases into one table and Close's into another, each comparing the containers, networks and lease files left plus warnings with one cmp.Diff. Drop the call-recording fake and the separate no-Docker-call and liveness-only tests, which mirrored the implementation; the liveness signal is covered end to end by TestRunReclaimsARunThatDied. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com> --------- Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Description of your changes
Adds the
render.crossplane.io/sessionlabel to every Docker container and networkcrossplane rendercreates, completing the label set proposed in #401 (managed-byandcleanuplanded in #407).Callers can supply the session ID, so many renders in one process (or concurrent runs) can each own a distinct session and clean up only their own resources:
EngineFlags.SessionID(--session-id). The engine applies it to the network and engine container it creates, and annotates Functions inSetup(both the Docker and local-binary engines) so Function containers carry it too.render.crossplane.io/runtime-docker-sessionannotation (RuntimeDocker.Session). An annotation already on a Function is never overwritten.Not included: the optional
created-by-pidlabel and arender cleanupsubcommand.Part of #401
I have:
go test ./cmd/crossplane/render/....🤖 Generated with Claude Code