Brings one pod to running reality and supervises it.
start_link/2 takes a %Tank.Pod{} and, at the Linx.Process :ready
checkpoint, runs the full host-side bring-up:
- pull the image and derive run params (
Tank.OCI), - spawn the workload into namespaces, parked at the checkpoint,
- build the rootfs (
Tank.Runtime.Rootfs) with per-pod/etcfiles, - configure the network (
Tank.Runtime.Network), - apply cgroup limits,
proceed— the workloadexecves inside its container.
Scope (M4)
One container per pod (sidecars are M7); the workload runs as the image's
default user with no user namespace; container stdio goes to /dev/null
(log capture is a later concern). A pod's netns may still hold several NICs.
Owner events
The :owner option receives:
{:tank, :running, host_pid}— configured and running.{:tank, :exited, code}/{:tank, :signaled, signum}/{:tank, :error, reason}— terminal.
The GenServer stops when its workload terminates: a clean exit → :normal, a
non-zero exit or signal → {:shutdown, {:workload_exited | :workload_signaled, …}} (an expected outcome, so OTP logs no crash report), and a genuine setup
or session failure → an abnormal reason. The reconciler reads the reason and
rebuilds the whole composite — a fresh rootfs and namespace — per the pod's
:restart policy.
Options
:owner— pid for{:tank, _}events (default: none).:data_dir— base dir for per-pod scratch (<data_dir>/run/<pod>); defaults to:tank, :data_diror a tmp dir.:image— keyword opts forwarded toTank.Image.pull/2(e.g.:cache).
Summary
Types
What Tank.exec/3 needs to enter the container: the workload's host pid plus
the container's resolved env (image Env merged with the spec's) and
working_dir — so an exec session inherits the container's environment, not
the host's.
Functions
Begin an attach to a tty: true container's main process: hand the session's
event stream to attacher and return the session pid for Linx.Tty.attach/3.
Supervisor child spec. restart: :temporary — OTP never restarts a runtime;
Tank.Reconciler owns restart (it monitors the runtime and acts on the stop
reason per the pod's :restart policy). Pod policy lives in the reconciler,
not the child spec.
End an attach: take ownership of the session back and re-derive the workload's state. If it terminated while detached, the runtime acts on it now (stopping so the reconciler applies the restart policy). Best-effort — a no-op if the runtime is already gone.
The container's exec context, once :running. {:error, :not_running} before then.
The workload's host pid, once :running. {:error, :not_running} before then.
Start and bring up one pod. See the moduledoc for options.
Types
@type exec_context() :: %{ host_pid: pos_integer(), env: [String.t()], working_dir: String.t() }
What Tank.exec/3 needs to enter the container: the workload's host pid plus
the container's resolved env (image Env merged with the spec's) and
working_dir — so an exec session inherits the container's environment, not
the host's.
Functions
Begin an attach to a tty: true container's main process: hand the session's
event stream to attacher and return the session pid for Linx.Tty.attach/3.
{:error, :not_running} if the workload isn't up yet; {:error, :not_a_tty}
if the container wasn't started with tty: true (there is no PTY to attach
to). Pair every success with end_attach/1.
Supervisor child spec. restart: :temporary — OTP never restarts a runtime;
Tank.Reconciler owns restart (it monitors the runtime and acts on the stop
reason per the pod's :restart policy). Pod policy lives in the reconciler,
not the child spec.
@spec end_attach(pid()) :: :ok
End an attach: take ownership of the session back and re-derive the workload's state. If it terminated while detached, the runtime acts on it now (stopping so the reconciler applies the restart policy). Best-effort — a no-op if the runtime is already gone.
@spec exec_context(pid()) :: {:ok, exec_context()} | {:error, :not_running}
The container's exec context, once :running. {:error, :not_running} before then.
@spec host_pid(pid()) :: {:ok, pos_integer()} | {:error, :not_running}
The workload's host pid, once :running. {:error, :not_running} before then.
@spec start_link( Tank.Pod.t(), keyword() ) :: GenServer.on_start()
Start and bring up one pod. See the moduledoc for options.