stdshell

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Aug 5, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package stdshell is a REAL leaf provider that runs a user-supplied script. A stdshell resource carries its script INLINE in the spec; per task the worker writes the script to a temp file, runs it under the configured interpreter (bash by default), captures stdout/stderr, and records the result as status. It is the simplest "run this command as a converge resource" kind — self-contained, no external program to install (cf. the generic `stdio` provider, whose spec is opaque and driven by a separate stdio program).

Error semantics (so the engine retries correctly):

  • a bad spec (no script) is TERMINAL — a same-generation retry can't fix it.
  • the script exiting non-zero is a TRANSIENT failure by default (the engine retries with backoff up to the kind's max_transient_attempts), UNLESS the script exits with code 2, which is TERMINAL (the same "config/usage error" convention the stdio provider uses) — a script opts into terminal deliberately so a genuinely-unfixable run stops retrying and dead-letters.
  • a ctx cancellation/timeout (worker drain, lease loss, per-run timeout) is TRANSIENT — the run was cut short, not the script's own verdict.

The script runs under the task's context, so a cancelled task (drain, lease loss) or a configured timeout kills the process — no run outlives its claim.

It serves the single fixed kind "stdshell" (no env var to rename it). It imports only sdk/* — no internal/* — exactly what an external team ships.

Index

Constants

View Source
const Kind converge.Kind = "stdshell"

Kind is the FIXED kind this provider serves — "stdshell". Its reference CRD lives beside this package in stdshell.kind.json. Unlike the stdio provider (whose kind names are operator-chosen via STDIO_KINDS), the stdshell provider serves exactly one built-in kind; there is no env var to rename it.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	// DefaultInterpreter is the interpreter used when a spec sets none. Empty →
	// "bash".
	DefaultInterpreter string `json:"default_interpreter,omitempty" doc:"Interpreter used when a resource spec sets none (default bash)."`
	// Env is baseline environment KEY=VALUE pairs for every script of the kind, layered
	// over the worker's environment (a spec's Env overrides on a key clash).
	Env map[string]string `json:"env,omitempty" doc:"Baseline environment variables (KEY→VALUE) for every script of this kind."`
	// DefaultTimeoutSeconds bounds a run when the spec sets no TimeoutSeconds. 0 =
	// no provider-imposed timeout (the task deadline still applies).
	DefaultTimeoutSeconds int `` /* 138-byte string literal not displayed */
}

Config is the shell kind's providerconfig — the DEFAULTS applied to every shell resource of the kind (each overridable per-resource via the spec). It lets an operator standardise the interpreter, a baseline environment, and a timeout for a named kind without repeating them in every resource.

type Provider

type Provider struct {
	// contains filtered or unexported fields
}

Provider is the worker-side logic: it implements converge.Provider (the ONE SDK provider contract — Kind/Work/OnConfig/Ready). It runs an inline script per task, so it is a pure leaf — always Ready, no downstream to dial. Imports only sdk/* — no internal/*, exactly what an external team ships.

It holds two pieces of per-worker state gathered when the Provider is built:

  • environ: os.Environ() captured once, the base environment layered under a resource's config/spec env for every child process.
  • defaultSpec (guarded by mu): the kind's LIVE default providerconfig `spec`, the latest OnConfig push. Work overlays the per-resource override on it per task via converge.EffectiveConfig, so an operator's providerconfig edit lands with no restart.

func New

func New() *Provider

New builds a Provider capturing os.Environ() as the base environment for child processes. The zero Provider value (stdshell.Provider{}) is also usable — its environ is nil, meaning the child inherits nothing beyond the config/spec env — but New is the canonical constructor and the one Runtime uses.

func (*Provider) Kind

func (p *Provider) Kind() converge.KindVersion

Kind is the single (kind, version) this provider serves — the fixed kind "stdshell" at web-API version 1 (explicit; there is no implicit default).

func (*Provider) OnConfig

func (p *Provider) OnConfig(cfg converge.ProviderConfig)

OnConfig stores the kind's latest default providerconfig `spec` under the guard so Work can overlay the per-resource override on it per task. The stdshell config is spec-only (no bundle), so cfg.Data is ignored; an empty cfg.Spec (a deleted default) clears it.

func (*Provider) Ready

func (p *Provider) Ready() bool

Ready is always true: a pure leaf that runs an inline script has no downstream to dial, so it can always do work.

func (*Provider) Work

Work runs one task: decode the spec, resolve the effective config (the kind's live default from OnConfig overlaid with the per-resource override), write the inline script to a temp file, run it under the interpreter with the task's context, and map the result (exit code + output) to an Outcome carrying status and a Ready condition. stdshell declares a single reaction, so Work does not switch on req.Reaction — every reaction runs this one body.

type Spec

type Spec struct {
	// Script is the script text to run, inline. It is written to a temp file and
	// executed by Interpreter. Required; an empty script fails TERMINALLY (a
	// misconfiguration a same-generation retry can't fix).
	Script string `json:"script" doc:"The script text to run, inline (executed by the interpreter)."`
	// Interpreter is the program the script is run under (an absolute path or a
	// name on PATH). Empty defaults to the kind's configured DefaultInterpreter,
	// then to "bash". The script path is passed as the interpreter's final argument
	// after Args (e.g. bash [Args…] /tmp/script).
	Interpreter string `` /* 150-byte string literal not displayed */
	// Args are extra arguments passed to the interpreter BEFORE the script path
	// (e.g. ["-x"] for bash trace, or a python module flag).
	Args []string `json:"args,omitempty" doc:"Extra arguments passed to the interpreter before the script path."`
	// Env is extra environment KEY=VALUE pairs for the script, layered over the
	// worker's own environment and the kind config's Env (spec wins on a clash).
	Env map[string]string `json:"env,omitempty" doc:"Extra environment variables (KEY→VALUE) for the script."`
	// TimeoutSeconds bounds this run. 0 = fall back to the kind config's
	// DefaultTimeoutSeconds (also 0 = no provider timeout; the task deadline still
	// applies). A run that overruns is killed and the task fails transiently.
	TimeoutSeconds int `json:"timeout_seconds,omitempty" doc:"Per-run timeout in seconds (0 = the kind config default, then no provider timeout)."`
}

Spec is a stdshell resource's desired state: the script to run plus how to run it. Unlike the generic `stdio` provider (whose spec is fully opaque and interpreted by an external program), the stdshell provider interprets the spec itself — the script text is inline, so a resource is entirely self-contained (no external program, no fetch, no bundle) and the DB row IS the source of truth.

type Status

type Status struct {
	// ExitCode is the script's process exit code (0 on success — a non-zero exit
	// makes the whole task fail, so a persisted status always carries ExitCode 0;
	// the field is kept for completeness + forward compatibility).
	ExitCode int `json:"exit_code" doc:"The script's process exit code (0 on success)."`
	// Stdout / Stderr are the captured, tail-bounded output streams (the last
	// MaxOutputBytes of each) so a chatty script can't bloat the status row.
	Stdout string `json:"stdout,omitempty" doc:"Captured stdout (tail-bounded)."`
	Stderr string `json:"stderr,omitempty" doc:"Captured stderr (tail-bounded)."`
}

Status is the run result recorded on the resource: the exit code and captured output (bounded). A downstream consumer can value-flow a field out of here.

Jump to

Keyboard shortcuts

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