runtime

package
v0.0.0-...-73ddf49 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 2, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package runtime is mdev's compute-backend seam: the contract every sandbox backend (Docker, Kubernetes, a cloud VM provider like Hetzner, …) satisfies.

Everything else in mdev is runtime-blind and reused unchanged behind any backend: the reverse tunnel (supervisor dials the daemon, outbound-only), the in-sandbox supervisor's process supervision + declared-port routing, file sync, the hostname reverse proxy, and the MCP control surface.

A Runner is not a monolith; it is composed from capabilities — a Compute (where the toolchain runs + named services resolve) and an optional Backing (the sandbox's backing services). Assemble sequences them and builds the supervisor command once, so a new backend implements only the capability that is genuinely new and reuses the rest. Backends are in-tree: each is a package with a typed Config and a New(Spec, Daemon, Config) constructor that the caller dispatches to (see cmd/sandbox). The contracts here name no Docker (or Kubernetes) concept — that is what keeps the core agnostic.

Index

Constants

View Source
const ImageBinaryPath = "/usr/local/bin/mdev"

ImageBinaryPath is where the mdev binary lives inside the published multi-arch mdev image (see Dockerfile) and where backends install it in the sandbox's main container. Every backend seeds the supervisor from that image, so the container runtime — not mdev, not the operator — resolves the binary's platform.

View Source
const LabelSandbox = "mdev.sandbox"

LabelSandbox is the label every backend stamps on the objects it creates (containers, pods, services, networks, …), valued with the sandbox name, so teardown and discovery can find them.

View Source
const WorkspaceMount = "/workspace"

WorkspaceMount is the in-sandbox path the worktree is synced to and the cwd for process workloads. Uniform across backends, so the shared supervisor command can reference it.

Variables

This section is empty.

Functions

func ResolvePath

func ResolvePath(root, p string) string

ResolvePath resolves a (possibly relative) config path against the worktree root, shared by backends that take file paths in their `with:` config.

func Routes

func Routes(name string, ports []int) []wire.Remote

Routes turns a discovered service into one route per exposed port, shared by every backend so the hostname scheme is uniform: each port is reachable at "<name>-<port>.<sandbox>.<domain>" and dials name:<port> via DNS. name is the service's DNS name; ports are deduped; empty input yields nil.

func SupervisorArgs

func SupervisorArgs(spec Spec, remotes []wire.Remote) []string

SupervisorArgs builds the in-sandbox supervisor command (after the binary path), shared by every backend. remotes are the alias→host:port routes the supervisor resolves via the backend's name resolution.

Types

type Backing

type Backing interface {
	Up(ctx context.Context) ([]wire.Remote, error)
	// Down tears the backing services down. Best-effort; the shared
	// orchestrator calls it before destroying the compute.
	Down(ctx context.Context)
}

Backing brings up the sandbox's backing services and reports their routes. Optional — a backend with no backing concept can omit it (nil).

type Compute

type Compute interface {
	// Prepare creates the isolated compute (network/namespace/VM). Idempotent.
	Prepare(ctx context.Context) error
	// RunSupervisor delivers the mdev supervisor into the toolchain and starts it with
	// args (which begin "supervisor …"; the compute prepends the binary path).
	// Returns a Handle over the supervisor's lifetime.
	RunSupervisor(ctx context.Context, args []string) (Handle, error)
	// Destroy tears the whole sandbox down. Best-effort.
	Destroy(ctx context.Context)
}

Compute is a backend's compute plane: an isolated place where the toolchain runs and where named services resolve (Docker container+network, k8s namespace+pod, a cloud VM, …).

type Daemon

type Daemon struct {
	Token     string
	AdminAddr string // the daemon's admin listen address, e.g. ":14434"
	Image     string // multi-arch mdev image supervisors are seeded from
}

Daemon is the daemon-provided context every backend needs: the bearer token the supervisor authenticates the tunnel with, the admin listen address a backend turns into the URL the supervisor dials (host.docker.internal:<port> locally, a cluster-reachable ingress in the cloud), and the multi-arch mdev image the supervisor binary is seeded from. A backend's New fills Spec.Dialback from this + its own config.

type Dialback

type Dialback struct {
	URL   string
	Token string
}

Dialback is how the in-sandbox supervisor connects back to the daemon. URL is the admin URL as dialed from inside the sandbox (host.docker.internal locally, a cluster-reachable ingress in the cloud); the backend's New supplies it. Token authenticates the tunnel upgrade.

type Handle

type Handle interface {
	Done() <-chan struct{}
}

Handle observes a running sandbox. Done closes when the supervisor exits.

func NewHandle

func NewHandle(done <-chan struct{}) Handle

NewHandle wraps a done channel as a Handle, so backends don't each define an identical adapter type.

type Runner

type Runner interface {
	// Up provisions the sandbox, brings up its backing services + workloads,
	// and starts `mdev supervisor` inside the toolchain compute (the supervisor then
	// dials the daemon and registers). Returns once provisioned; the Handle
	// observes the supervisor's lifetime.
	Up(ctx context.Context) (Handle, error)
	// Down removes everything Up created. Best-effort and idempotent.
	Down(ctx context.Context)
}

Runner hosts one sandbox. Constructed per-sandbox by a backend's New (dispatched in cmd's buildRuntime); Up/Down is the lifecycle the orchestrator drives.

func Assemble

func Assemble(spec Spec, compute Compute, backing Backing) Runner

Assemble builds a Runner from a Compute and an optional Backing. The returned Runner runs the shared lifecycle (prepare → backing → start the supervisor with the discovered routes; teardown in reverse), so backends implement only the capabilities and never the sequencing.

type Spec

type Spec struct {
	Name          string          // sandbox identity (tunnel registration key)
	WorkspaceRoot string          // host path to the worktree; the file-sync source root
	Image         string          // toolchain image for the main + process workloads
	Processes     []wire.Workload // run: workloads, handed to the supervisor
	Dialback      Dialback        // how the in-sandbox supervisor connects home
}

Spec is the runtime-neutral description of one sandbox: WHAT to run, never HOW. It names no backend concept. Backing services are deliberately absent — they are backend-specific and arrive through the backend's typed config, not here.

Directories

Path Synopsis
Package docker is the local-Docker backend: a runtime.Compute (per-sandbox network + the main toolchain container the supervisor runs in, delivered via `docker cp` + `docker exec`) and a runtime.Backing (the compose engine).
Package docker is the local-Docker backend: a runtime.Compute (per-sandbox network + the main toolchain container the supervisor runs in, delivered via `docker cp` + `docker exec`) and a runtime.Backing (the compose engine).
Package k8s is the Kubernetes backend: a runtime.Compute (namespace + token Secret + a main Pod whose init container seeds the supervisor into a shared volume) and a runtime.Backing (apply the sandbox's manifests).
Package k8s is the Kubernetes backend: a runtime.Compute (namespace + token Secret + a main Pod whose init container seeds the supervisor into a shared volume) and a runtime.Backing (apply the sandbox's manifests).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL