Add the pure launch toolkit for sidecar tongs#11
Merged
Conversation
A tong's readiness: block says how the launcher decides the sidecar is up before gating the anvil on it. Add parse_duration and readiness_settings so that declaration resolves to plain values -- a (mode, command, timeout_s) triple -- that the live launcher can probe against later. tcp is the implicit default for the network-facing kinds (mcp/port); a portless kind (volume/none) falls back to none, since there is no port to dial. parse_duration accepts 30s/500ms/2m/1h and bare-number seconds, and raises on a typo so a bad readiness timeout stops the launch rather than silently falling back to a default. Validate the readiness fields the launcher will consume up front: reject a tcp probe on a portless kind (it could never become ready), and reject a malformed readiness.timeout or readiness.command so the error is a clean validation message rather than an uncaught exception mid-launch. Pure helpers with no live call site; the empty-discovery launch path is unchanged.
Turn a validated tong definition into the concrete `docker run -d` argv that starts its container, and rewrite the anvil's own docker-run argv so it can reach the discovered tongs. The builders are pure -- they return argv lists and run no docker -- so the exact flags are unit-tested while the side-effectful execution stays in the launcher. tong_run_argv detaches the container under a caller-chosen name, joins it to a network under a `--network-alias` (only for the network-facing kinds; volume/none tongs need no DNS name), stamps the tong-name and config-hash labels a later launch reads to detect a stale shared container, passes env as sorted `-e`, mounts secret tmpfs dirs, and appends mounts and resources before the image. mounts: are opt-in magic words -- `workspace` and `docker-socket`, never a raw host path -- resolved to `-v` specs; resources.memory maps to `--memory`. shared/session container-name helpers give shared tongs a stable session-independent name and session tongs a per-session name carrying the session handle. inject_anvil_argv splices the network, pre-image `-e`/`-v` options, and post-image harness flags into the anvil argv without mutating it; with no arguments it returns the argv unchanged, so a zero-tong launch stays byte-identical to the direct docker run. The `--network` lookup and rewrite scan only the docker options before the image, so a same-named harness argument after the image is never read or rewritten. Validate the mount words, network entries, and resources block up front so a malformed entry fails validation rather than raising mid-launch. Pure helpers with no live call site.
Two tongs on one network cannot share a DNS alias without nondeterministic resolution. alias_collisions groups the network-facing tongs by their canonical alias and returns the aliases more than one tong resolves to, so the live launcher can refuse such a set and the planning functions can keep the first and warn. Only mcp/port tongs register a `--network-alias`, so volume/none tongs are skipped -- they never claim a DNS name and so cannot collide, matching how the network plan and the run argv assign aliases. The canonical alias is interface.name for an mcp tong and the tong name otherwise, so an mcp name can collide with another network-facing tong's name -- the check covers that case too. Pure helper with no live call site.
Two edge cases in the launch toolkit would have slipped a bad value through to the launcher instead of failing early: A bare negative or zero readiness.timeout bypassed the (sign-less) duration regex via parse_duration's numeric path and resolved to a non-positive deadline -- one that gives the readiness probe no time to succeed, so the tong would never report ready and the launch would fail for a reason far from the typo. Reject a non-positive duration with a clear error, matching how the string forms are already refused. A tong name that sanitizes to empty made session_container_name emit a trailing-dash "<session>-tong-" name; two such tongs would collide on one container name. Fall back to "<session>-tong" the way shared_container_name already drops to its bare prefix.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the pure, side-effect-free helpers the launcher will use to start
sidecar containers ("tongs") and to let an anvil reach them. Everything here
returns plain values or argv lists and runs no docker, so the exact behavior
is unit-tested in isolation; the side-effectful execution lands in a later
change. Nothing here is called from a launch path yet, so this is inert for
existing repos: with no tong definitions discovered, the anvil still launches
exactly as it does today.
What's included
Readiness resolution.
parse_durationturns30s/500ms/2m(orbare-number seconds) into float seconds and rejects a typo or a non-positive
deadline up front;
readiness_settingsresolves a tong'sreadiness:blockto a
(mode, command, timeout)triple, defaulting to a TCP probe for thenetwork-facing kinds.
Docker argv builders.
tong_run_argvassembles thedocker run -dcommand for one tong: a detached container under a chosen name, joined to a
network under a
--network-alias(only for network-facing tongs), stampedwith name and config-hash labels, with env as sorted
-e, secret tmpfsmounts, opt-in
workspace/docker-socketmounts, and resource flags beforethe image.
inject_anvil_argvrewrites the anvil's own docker-run argv tojoin the tong network and carry injected options without mutating the input,
and returns it unchanged when there is nothing to inject -- so a zero-tong
launch stays byte-identical to the direct docker run.
Naming and collision helpers. A stable, session-independent name for a
sharedtong and a unique per-session name for asessiontong (bothcollision-safe for degenerate inputs);
alias_collisionsflags any canonicalDNS alias claimed by more than one tong.
Up-front validation.
validate_tongnow also checks the readiness,mount, network, and resource fields these helpers consume, so a malformed
definition fails validation with a clear message instead of raising during a
launch.
All helpers are covered by unit tests run the same way as the existing
scripts/test_*.pysuites.