Documentation
¶
Overview ¶
Package runner is podium-runner: PID 1 of every Podium task container.
It runs the task command as a child in its own process group, forwards signals to that group, reaps orphaned grandchildren, and reports structured events to the node over a Unix socket. Being PID 1 is the whole point: the kernel discards a default-disposition signal sent to a PID namespace's init, so a task command running as PID 1 itself cannot be asked to stop — only killed. The runner has a real handler, so `podium task cancel` becomes a prompt SIGTERM instead of a 30-second wait for SIGKILL.
This package depends on nothing outside the standard library. The binary is bind-mounted read-only into images Podium does not control.
Index ¶
- Constants
- func AddArtifact(cfg Config, args []string) int
- func AddMessage(cfg Config, args []string, stdin io.Reader) int
- func Gateway(args []string) int
- func Run(ctx context.Context, cfg Config, argv []string) int
- func ServeGateway(ctx context.Context, host string, routes []Route) error
- func Splice(c net.Conn, dial func() (net.Conn, error))
- type Config
- type Route
Constants ¶
const ( EnvTaskID = "PODIUM_TASK_ID" EnvLeaseID = "PODIUM_LEASE_ID" EnvEventsSock = "PODIUM_EVENTS_SOCK" EnvWorkDir = "PODIUM_WORKDIR" EnvKillAfter = "PODIUM_KILL_AFTER" // EnvHold is set on a task that exposes ports: when its command exits, the runner // reports the exit and stays up, so whatever the command left running keeps serving. EnvHold = "PODIUM_HOLD" )
Environment variables the node sets on the task container.
const ( DefaultEventsSock = "/podium/events.sock" DefaultWorkDir = "/workspace" // DefaultKillAfter is how long a child gets between the SIGTERM we forward and the // SIGKILL we send its group. It stays inside the node's own 30s cancel grace so the // container is already gone when the engine's SIGKILL would land. DefaultKillAfter = 25 * time.Second // DefaultDialTimeout is how long the event socket is retried before giving up. // Events are best-effort: the command runs either way. DefaultDialTimeout = 5 * time.Second )
Defaults for the values above and for the timers this package owns.
const ArtifactsDir = "/workspace/.podium/artifacts"
ArtifactsDir is where a task drops files it wants kept without asking for anything: the node collects everything under it when the task exits. It is inside the workspace volume so a sidecar or a later step can write there too.
const HoldDir = "/podium/hold"
HoldDir is a tmpfs the node mounts on a held task. The runner writes the command's exit there, because a node that restarted while the command ran has lost the event socket and can only learn the exit by reading this file.
const HoldExitFile = HoldDir + "/exit"
HoldExitFile is the file under HoldDir that holds the exit, as the exited event's JSON.
const MaxMessageBytes = 32 << 10
MaxMessageBytes caps `text`. The node's line scanner allows 64 KiB per line (maxRunnerLine); half of that leaves room for the envelope, attachments and JSON escaping.
const MessageTypeFinal = "final"
MessageTypeFinal is what a message is when the task does not say otherwise: the answer.
Variables ¶
This section is empty.
Functions ¶
func AddArtifact ¶
AddArtifact is `podium-runner artifact add PATH [--name NAME] [--type CONTENT_TYPE]`.
It writes one line to the node's event socket and exits. It is deliberately a separate invocation of the same binary rather than an API: a task can call it from any shell, in the middle of a run, with no library and no credentials — the socket is already mounted and the node is the only thing listening on it.
func AddMessage ¶
AddMessage is `podium-runner message [--type progress|final] [--attach NAME]... TEXT`. TEXT of "-" reads the message from stdin.
Like `artifact add` it is a separate invocation of the same binary rather than an API: a task says what it has to say from any shell, with no library and no credentials.
func Gateway ¶ added in v0.6.0
Gateway is `podium-runner gateway`: the container a node puts on an exposed task's network. It listens on every exposed port and forwards each connection to the sidecar or the task container that owns it, by name, which is what lets a node publish a task's ports on one address whatever its platform can route to.
func Run ¶
Run executes argv to completion and returns the exit code the runner should exit with: the child's own code, or 128+signo when a signal killed it. It never calls os.Exit, so it is testable.
func ServeGateway ¶ added in v0.6.0
ServeGateway forwards until ctx ends. host is the listen address, empty for every one.
Types ¶
type Config ¶
type Config struct {
TaskID string
LeaseID string
// EventsSock is the Unix socket the node listens on; empty means DefaultEventsSock.
EventsSock string
// WorkDir is the child's working directory.
WorkDir string
// KillAfter is the SIGTERM → SIGKILL delay for the child's process group.
KillAfter time.Duration
// DialTimeout bounds the retry window for the event socket.
DialTimeout time.Duration
// Hold keeps the runner up after the command exits, until it is asked to stop.
Hold bool
// HoldExitFile is where a held exit is also written; empty means HoldExitFile.
HoldExitFile string
// Stdout and Stderr are the files the child inherits as fd 1 and fd 2, and Stderr is
// also where the runner writes its own diagnostics. Both default to the process's.
// Stdin is always inherited.
Stdout *os.File
Stderr *os.File
}
Config is everything the runner needs. The zero value is usable: Run fills in the defaults above.
func ConfigFromEnv ¶
func ConfigFromEnv() Config
ConfigFromEnv reads the configuration the node passes in the container environment.
type Route ¶ added in v0.6.0
Route is one port the gateway listens on and the service inside the task it forwards to.
func ParseRoutes ¶ added in v0.6.0
ParseRoutes reads the gateway's arguments: PORT=HOST:PORT, one per exposed port.