runs

package
v0.30.0 Latest Latest
Warning

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

Go to latest
Published: Oct 23, 2026 License: MIT Imports: 31 Imported by: 0

Documentation

Overview

Package runs implements per-run worker templates and the run supervisor behind `claw runs serve` (issue #372).

A template is compiled by `claw up` from a pod service declared with x-claw.lifecycle: per-run. The supervisor instantiates it once per run as a separate Compose project; Compose remains the only lifecycle writer.

Index

Constants

View Source
const (
	ReasonExitNonZero      = "exit_nonzero"
	ReasonTimeout          = "timeout"
	ReasonAuthorityExpired = "authority_expired"
	ReasonSpawnError       = "spawn_error"
	ReasonContainerMissing = "container_missing"
	ReasonDuplicate        = "duplicate"
	ReasonMismatch         = "mismatch"
	ReasonResultMissing    = "result_missing"
)

Failure reasons.

View Source
const (
	// ProofCllamaAck: cllama durably revoked the identity and drained it.
	ProofCllamaAck = "cllama_ack"
	// ProofProxyStopped: the whole pod (proxy included) was removed and the
	// run's context deleted, so no process can hold or regain its authority.
	ProofProxyStopped = "proxy_stopped"
)

Revocation proofs. A run is revoked only with one of these.

View Source
const (
	CredentialNone    = "none"
	CredentialHeld    = "held"
	CredentialMissing = "missing"
)

Credential custody states reported to the orchestrator.

View Source
const (
	CallbackAcked     = "acked"
	CallbackRejected  = "rejected"  // 401/403: the orchestrator's authority ended
	CallbackAbandoned = "abandoned" // undeliverable before authority expired
	CallbackSkipped   = "skipped"   // no credential held, or the run was cancelled

	// End aliases kept for readability at end-callback call sites.
	EndAcked     = CallbackAcked
	EndRejected  = CallbackRejected
	EndAbandoned = CallbackAbandoned
	EndSkipped   = CallbackSkipped
)

Callback outcomes. Only CallbackAcked means the orchestrator acknowledged.

View Source
const (
	LabelPod        = "claw.pod"
	LabelRole       = "claw.role"
	LabelRunKey     = "claw.run.key"
	LabelInstall    = "claw.run.installation"
	LabelRunID      = "claw.run.id"
	LabelGeneration = "claw.run.generation"
	LabelTemplate   = "claw.run.template"
	LabelTemplateID = "claw.run.template-id"
	LabelDigest     = "claw.run.spec-digest"
	LabelPodNS      = "claw.run.pod-ns"
	RoleRunWorker   = "run-worker"
)

Worker container labels. The key hash is the reconciliation handle; the others let reconcile verify a container against its ledger record.

View Source
const (
	// StateDirName is the pod-relative directory holding templates, the ledger,
	// rendered projects and the pod lock. claw up never rotates it.
	StateDirName = ".claw-runs"
	// RevocationDirName is the pod-relative proxy-owned revocation ledger dir.
	RevocationDirName = ".claw-revocations"
)
View Source
const (
	// DefaultMaxRuntime applies only if a template carries no runtime limit.
	DefaultMaxRuntime = 30 * time.Minute
)

Advancement bounds. Every external operation inherits a deadline.

View Source
const ProtocolVersion = 1

ProtocolVersion is the run supervisor wire protocol version.

View Source
const (
	SocketName = "claw-runs.sock"
)

Variables

View Source
var ErrAuthority = errors.New("orchestrator authority rejected")

ErrAuthority means the orchestrator rejected the held credential (401/403).

View Source
var ErrPodLocked = errors.New("pod run lock is held by another process")

ErrPodLocked means another process (normally `claw runs serve`) holds the pod's run lock.

Functions

func CheckSocketDir

func CheckSocketDir(dir string, uid uint32) error

CheckSocketDir verifies the socket directory is a real directory (not a symlink) owned by uid with mode 0700 or 0750. Any ancestor writable by group or others must carry the sticky bit.

func EnsurePrivateDir

func EnsurePrivateDir(path string) error

EnsurePrivateDir creates path as a 0700 directory, or verifies an existing one is a real directory (not a symlink) owned by the current user, and tightens its mode to 0700. Durable fences (the run ledger, cllama's revocation ledger) must not be writable by other host users.

func HasLiveRuns

func HasLiveRuns(podDir string) (bool, error)

HasLiveRuns reports whether any record is non-terminal. A missing ledger has no live runs.

func ListTemplates

func ListTemplates(podDir string) ([]string, error)

ListTemplates returns the names of compiled templates.

func LoadTemplate

func LoadTemplate(podDir, name string) (*Template, *ContextTemplate, error)

LoadTemplate reads and verifies one compiled template.

func PodNamespace

func PodNamespace(podDir string) string

PodNamespace is the server-owned identity of a pod on this host, derived from its absolute directory. Two pods with the same name (or the same run keys) never share a Compose project, label value or worker network.

func RunPath

func RunPath(k Key, suffix string) string

RunPath returns the API path for a run.

func TemplateDir

func TemplateDir(podDir string) string

TemplateDir returns the pod's template directory.

func WriteTemplates

func WriteTemplates(podDir string, templates []*Template, contexts map[string]*ContextTemplate) error

WriteTemplates replaces the pod's compiled templates atomically. Callers must hold the pod lock.

Types

type APIError

type APIError struct {
	Status  int    `json:"-"`
	Code    string `json:"code"`
	Message string `json:"message"`
}

APIError is a client-visible error. Messages never carry secrets or spec content.

func (*APIError) Error

func (e *APIError) Error() string

type Callbacks

type Callbacks struct {
	Start         string     `json:"start,omitempty"`
	End           string     `json:"end,omitempty"`
	LastHeartbeat *time.Time `json:"last_heartbeat,omitempty"`
}

Callbacks records lifecycle callback delivery. Start is always resolved before End for a worker that spawned.

type Client

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

Client talks to a run supervisor. It authenticates the server in two ways: the socket and its directory must be owned by the expected UID and not writable by others, and the peer credential of every connection must be that UID (path checks alone race with rename).

func Dial

func Dial(dir string, serverUID uint32) (*Client, error)

Dial prepares a client for the supervisor socket in dir run by serverUID.

func (*Client) Do

func (c *Client) Do(ctx context.Context, method, path string, body any, out any) error

Do sends one request and decodes a JSON response into out (if non-nil). A non-2xx response returns *APIError.

type CllamaRevoker

type CllamaRevoker struct {
	PodDir string
	Client *http.Client
}

CllamaRevoker calls cllama's operator revoke endpoint (cllama#54) on the published UI listener with the pod's CLLAMA_UI_TOKEN.

func (*CllamaRevoker) Revoke

func (r *CllamaRevoker) Revoke(ctx context.Context, agentID string, generation uint64) error

type Config

type Config struct {
	PodDir            string
	Executor          Executor
	Revoker           Revoker
	Notifier          Notifier // nil disables credential custody
	HeartbeatInterval time.Duration
	Now               func() time.Time
	Logf              func(format string, args ...any)
}

Config configures a Supervisor.

type Container

type Container struct {
	ID       string
	Running  bool
	Exited   bool
	ExitCode int
	ImageID  string
	Labels   map[string]string
}

Container is the read-only view of a worker container.

type ContextTemplate

type ContextTemplate struct {
	Input cllama.AgentContextInput `json:"input"`
}

ContextTemplate is the cllama context compiled for a template. It carries managed tool credentials, so it is stored 0600 and never mounted into a worker. Each run receives a copy with its own identity and allowlist.

type DockerExecutor

type DockerExecutor struct {
	Logf func(format string, args ...any)
	// Hold, when set, is the pod lock file. Every lifecycle subprocess
	// inherits it, so a SIGKILLed supervisor's in-flight compose command keeps
	// writer authority until it exits.
	Hold *os.File
	// contains filtered or unexported fields
}

DockerExecutor runs `docker compose` for lifecycle (ADR-002) and uses the Docker SDK for reads only.

func NewDockerExecutor

func NewDockerExecutor() (*DockerExecutor, error)

func (*DockerExecutor) Close

func (d *DockerExecutor) Close() error

func (*DockerExecutor) Containers

func (d *DockerExecutor) Containers(ctx context.Context, keyHash string) ([]Container, error)

Containers lists every container, running or not, labelled with the key.

func (*DockerExecutor) Down

func (d *DockerExecutor) Down(ctx context.Context, project, file string) error

Down removes a run's project and orphans. It never relies on ambient Compose discovery: with the recorded file it uses that file; if the file is gone it passes a minimal empty project on stdin, which removes only the deterministic project's containers. The project directory is pinned so no stray .env file is read.

func (*DockerExecutor) RunWorkers

func (d *DockerExecutor) RunWorkers(ctx context.Context, podNS string) ([]Container, error)

RunWorkers lists every run-worker container labelled for this pod's namespace.

func (*DockerExecutor) Stdout

func (d *DockerExecutor) Stdout(ctx context.Context, containerID string, limit int) ([]byte, bool, error)

Stdout returns at most limit bytes of the container's stdout, and whether the stream held more.

func (*DockerExecutor) Up

func (d *DockerExecutor) Up(ctx context.Context, project, file string, env map[string]string) error

Up creates and starts a run's project. Inputs reach Compose only through the process environment; compose output is discarded because it can echo interpolated configuration.

type Executor

type Executor interface {
	Up(ctx context.Context, project, file string, env map[string]string) error
	Down(ctx context.Context, project, file string) error
	Containers(ctx context.Context, keyHash string) ([]Container, error)
	// Stdout returns at most limit bytes of stdout, and whether more existed.
	Stdout(ctx context.Context, containerID string, limit int) ([]byte, bool, error)
}

Executor performs container lifecycle through Docker Compose and reads container state through the Docker SDK. It never receives the orchestrator credential.

type ExitInfo

type ExitInfo struct {
	Code int       `json:"code"`
	At   time.Time `json:"at"`
}

ExitInfo records an observed worker exit. Observing an exit is not terminal.

type HTTPNotifier

type HTTPNotifier struct {
	Origin       *url.URL
	PathTemplate string
	Client       *http.Client
	MaxSummary   int
}

HTTPNotifier delivers the Clawdapus run lifecycle callback contract:

POST {origin}{path}/start      {installation, run_id, generation}
POST {origin}{path}/heartbeat  {installation, run_id, generation}
POST {origin}{path}/end        {installation, run_id, generation, outcome, reason, summary}

path comes from supervisor configuration with "{run_id}" substituted. The origin is fixed by configuration, never by the caller, redirects are not followed, and the held credential is sent only as a bearer header.

func NewHTTPNotifier

func NewHTTPNotifier(origin, pathTemplate string) (*HTTPNotifier, error)

NewHTTPNotifier validates the configured origin.

func (*HTTPNotifier) Ended

func (n *HTTPNotifier) Ended(ctx context.Context, rec *Record, credential, outcome, reason string, summary []byte) error

func (*HTTPNotifier) Heartbeat

func (n *HTTPNotifier) Heartbeat(ctx context.Context, rec *Record, credential string) error

func (*HTTPNotifier) Started

func (n *HTTPNotifier) Started(ctx context.Context, rec *Record, credential string) error

type Key

type Key struct {
	Installation string `json:"installation"`
	RunID        string `json:"run_id"`
}

Key identifies a run.

func (Key) Hash

func (k Key) Hash() string

Hash is the stable, label-safe digest of a key. Project names, file names and container labels derive from it, never from caller strings directly.

func (Key) RunKey

func (k Key) RunKey(podNS string) string

RunKey is the pod-scoped, label-safe identity of a run's containers.

func (Key) Validate

func (k Key) Validate() error

type LaunchRequest

type LaunchRequest struct {
	Key                Key
	Generation         uint64
	SpecDigest         string
	Spec               json.RawMessage
	Credential         string
	AuthorityExpiresAt time.Time
}

LaunchRequest is a validated-at-the-edge launch.

type Ledger

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

Ledger is the supervisor's durable store: one record file per run, plus separate 0600 secret files that are never mounted anywhere.

func OpenLedger

func OpenLedger(podDir string) (*Ledger, error)

OpenLedger opens (creating if absent) the ledger under podDir.

func (*Ledger) All

func (l *Ledger) All() ([]*Record, error)

All returns every record, sorted by key hash.

func (*Ledger) DeleteSecret

func (l *Ledger) DeleteSecret(k Key, kind string) error

DeleteSecret removes a stored secret.

func (*Ledger) Get

func (l *Ledger) Get(k Key) (*Record, error)

Get returns the record for k, or (nil, nil) when none exists.

func (*Ledger) Put

func (l *Ledger) Put(rec *Record) error

Put durably writes rec.

func (*Ledger) PutSecret

func (l *Ledger) PutSecret(k Key, kind, value string) error

PutSecret durably stores a secret (kind "cllama" or "credential").

func (*Ledger) PutTombstone

func (l *Ledger) PutTombstone(k Key, generation uint64) error

PutTombstone durably records a cancel. It never lowers a recorded generation. Tombstones are written without the run's key lock so a cancel is never delayed behind a slow lifecycle operation.

func (*Ledger) Secret

func (l *Ledger) Secret(k Key, kind string) (string, bool, error)

Secret reads a stored secret; ok is false when absent.

func (*Ledger) Tombstone

func (l *Ledger) Tombstone(k Key) (uint64, bool, error)

Tombstone reports whether k was cancelled, and at which generation.

type Limits

type Limits struct {
	MaxRuntimeSeconds   int64  `json:"max_runtime_seconds"`
	MaxAuthoritySeconds int64  `json:"max_authority_seconds"`
	MaxTaskBytes        int    `json:"max_task_bytes"`
	MaxResultBytes      int    `json:"max_result_bytes"`
	Memory              string `json:"memory"`
	Pids                int    `json:"pids"`
}

Limits bound every run instantiated from a template.

func (Limits) MaxAuthority

func (l Limits) MaxAuthority() time.Duration

func (Limits) MaxRuntime

func (l Limits) MaxRuntime() time.Duration

type Notifier

type Notifier interface {
	Started(ctx context.Context, rec *Record, credential string) error
	Heartbeat(ctx context.Context, rec *Record, credential string) error
	Ended(ctx context.Context, rec *Record, credential string, outcome, reason string, summary []byte) error
}

Notifier delivers lifecycle callbacks with the held orchestrator credential.

type PodLock

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

PodLock is the single-writer fence shared by `claw runs serve`, `claw up` and `claw down`. The supervisor holds it for its whole lifetime.

func AcquirePodLock

func AcquirePodLock(podDir string) (*PodLock, error)

AcquirePodLock takes the pod's exclusive run lock without blocking.

func (*PodLock) File

func (l *PodLock) File() *os.File

File returns the locked file so lifecycle subprocesses can inherit it: the flock lives on the open file description, so writer authority cannot be reacquired while any inheriting process still runs, even if this process dies.

func (*PodLock) Release

func (l *PodLock) Release() error

Release drops the lock.

type Record

type Record struct {
	Version            int         `json:"version"`
	Key                Key         `json:"key"`
	Generation         uint64      `json:"generation"`
	SpecDigest         string      `json:"spec_digest,omitempty"`
	Spec               *Spec       `json:"spec,omitempty"`
	TemplateID         string      `json:"template_id,omitempty"`
	ImageID            string      `json:"image_id,omitempty"`
	RunAgentID         string      `json:"run_agent_id,omitempty"`
	RunKey             string      `json:"run_key,omitempty"` // pod-scoped container label value
	Project            string      `json:"project,omitempty"`
	State              State       `json:"state"`
	Cancelled          bool        `json:"cancelled"`
	Revoked            bool        `json:"revoked"`
	RevocationProof    string      `json:"revocation_proof,omitempty"`
	SpawnAttempted     bool        `json:"spawn_attempted"`
	Exit               *ExitInfo   `json:"exit_observed,omitempty"`
	Failure            string      `json:"failure,omitempty"`
	AuthorityExpiresAt time.Time   `json:"authority_expires_at"`
	Deadline           *time.Time  `json:"deadline,omitempty"`
	Credential         string      `json:"credential"`
	Callbacks          Callbacks   `json:"callbacks"`
	Result             *ResultInfo `json:"result,omitempty"`
	Timestamps         Timestamps  `json:"timestamps"`
	LastError          string      `json:"last_error,omitempty"`
}

Record is one run's durable ledger entry.

type ResultInfo

type ResultInfo struct {
	Bytes     int  `json:"bytes"`
	Truncated bool `json:"truncated"`
}

ResultInfo describes the stored result.

type Revoker

type Revoker interface {
	Revoke(ctx context.Context, agentID string, generation uint64) error
}

Revoker closes a run's cllama identity (cllama#54). It must return nil only once cllama has durably revoked the agent and drained its dispatches.

type Server

type Server struct {
	Sup        *Supervisor
	Pod        string
	AllowedUID []uint32
	Logf       func(string, ...any)
}

Server exposes a Supervisor over a Unix socket. Trust model: any process running as an allowed UID (or root) holds every template and installation grant of this pod. Peer-UID checks authenticate a Unix account, not a program.

func (*Server) Handler

func (srv *Server) Handler() http.Handler

Handler returns the v1 API.

func (*Server) Listen

func (srv *Server) Listen(ctx context.Context, dir string) error

Listen creates the socket in dir (which must pass CheckSocketDir) and serves until ctx ends.

type Spec

type Spec struct {
	Template          string   `json:"template"`
	Task              string   `json:"task"`
	Tools             []string `json:"tools"`
	MaxRuntimeSeconds int64    `json:"max_runtime_seconds,omitempty"`
}

Spec is the immutable, digest-covered launch request body.

func CanonicalSpec

func CanonicalSpec(raw json.RawMessage) ([]byte, *Spec, string, error)

CanonicalSpec validates a raw launch spec and returns its canonical JSON form (sorted keys, no insignificant whitespace, no HTML escaping), the parsed Spec, and the digest "sha256:<hex>" over the canonical bytes. Only strings, integers and string arrays are accepted, so the canonical form is unambiguous across languages.

type State

type State string

State is the public run state.

const (
	StateAccepted State = "accepted"
	StateRunning  State = "running"
	StateRevoking State = "revoking"
	StateRevoked  State = "revoked"
	StateStopped  State = "stopped"
	StateFailed   State = "failed"
)

func (State) Terminal

func (s State) Terminal() bool

type StatusView

type StatusView struct {
	Installation       string      `json:"installation"`
	RunID              string      `json:"run_id"`
	Generation         uint64      `json:"generation"`
	SpecDigest         string      `json:"spec_digest,omitempty"`
	Template           string      `json:"template,omitempty"`
	RunAgentID         string      `json:"run_agent_id,omitempty"`
	State              State       `json:"state"`
	Cancelled          bool        `json:"cancelled"`
	Revoked            bool        `json:"revoked"`
	RevocationProof    string      `json:"revocation_proof,omitempty"`
	ExitCode           *int        `json:"exit_code"`
	Failure            string      `json:"failure,omitempty"`
	Result             *ResultInfo `json:"result,omitempty"`
	Credential         string      `json:"credential"`
	Callbacks          Callbacks   `json:"callbacks"`
	AuthorityExpiresAt *time.Time  `json:"authority_expires_at,omitempty"`
	Deadline           *time.Time  `json:"deadline,omitempty"`
	Timestamps         Timestamps  `json:"timestamps"`
	Pending            string      `json:"pending,omitempty"`
}

StatusView is the public run status.

type Supervisor

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

Supervisor owns per-run worker lifecycle for one pod.

Each run key has two locks. The short admit lock covers only ledger reads and writes of the record and tombstone, so launch, cancel and credential replacement linearize without waiting on Docker, cllama or callbacks. The long step lock serializes advancement, which performs those external operations. Orchestrator-owned fields (generation, credential custody, authority expiry) are only written under the admit lock and are re-read and merged whenever advancement persists.

func NewSupervisor

func NewSupervisor(cfg Config) (*Supervisor, error)

NewSupervisor opens the ledger. Callers must hold the pod lock.

func (*Supervisor) Advance

func (s *Supervisor) Advance(ctx context.Context, k Key)

Advance drives one run's state machine as far as it can go now. Every step is idempotent, so restart reconciliation is the same code path.

func (*Supervisor) AdvanceAll

func (s *Supervisor) AdvanceAll(ctx context.Context)

AdvanceAll advances every unfinished run concurrently, bounded, so one slow run cannot delay another run's cancel, expiry or teardown. A run whose step lock is busy is skipped this round.

func (*Supervisor) Cancel

func (s *Supervisor) Cancel(ctx context.Context, k Key, generation uint64) (*Record, error)

Cancel tombstones a run and returns immediately; advancement revokes and removes it. The tombstone is written under the admit lock, which Launch holds across its final tombstone check and accepted write, so a cancel always beats a launch that has not been accepted yet. A key with no record is terminal at once.

func (*Supervisor) CheckRevocationSupport

func (s *Supervisor) CheckRevocationSupport(ctx context.Context) error

CheckRevocationSupport proves the running proxy acknowledges durable revocation (cllama#54) before any worker is started. An older or misconfigured proxy (no endpoint, no revocation dir) fails this check.

func (*Supervisor) FinalizeWithoutProxy

func (s *Supervisor) FinalizeWithoutProxy(ctx context.Context, k Key, proxyGone func(context.Context) (bool, error)) error

FinalizeWithoutProxy ends a run whose cllama acknowledgement is unavailable during a full pod teardown. The caller must have removed the pod (proxy included) and verified it is gone; proxyGone re-checks that. With no worker container and no proxy process, nothing can hold the run's authority, and deleting its context means a restarted proxy cannot authenticate it. Remote effects that were already dispatched are not undone.

func (*Supervisor) Get

func (s *Supervisor) Get(k Key) (*Record, error)

Get returns a run's status view, or nil when it was never accepted or cancelled.

func (*Supervisor) Launch

func (s *Supervisor) Launch(ctx context.Context, req LaunchRequest) (*Record, bool, error)

Launch accepts a run idempotently. It persists intent, including the run's identity and secrets, before any side effect, then advances asynchronously.

func (*Supervisor) LiveKeys

func (s *Supervisor) LiveKeys() ([]Key, error)

LiveKeys returns every unfinished run.

func (*Supervisor) Orphans

func (s *Supervisor) Orphans(ctx context.Context) ([]Container, error)

Orphans returns labelled run workers with no ledger record or tombstone. They can only exist after ledger loss, because a run's project is recorded before `compose create`; the supervisor refuses to serve while any exist.

func (*Supervisor) RemoveOrphan

func (s *Supervisor) RemoveOrphan(ctx context.Context, c Container) error

RemoveOrphan removes one orphaned run worker through Compose. The project must be a run project of this pod's namespace (clawrun-<ns>-<key>); the executor passes an empty project on stdin, never an ambient file.

func (*Supervisor) ReplaceCredential

func (s *Supervisor) ReplaceCredential(ctx context.Context, k Key, generation uint64, credential string, expires *time.Time) (*Record, error)

ReplaceCredential installs a reissued orchestrator credential and, optionally, a later authority expiry. It is persisted before the ACK.

func (*Supervisor) Result

func (s *Supervisor) Result(k Key) ([]byte, *Record, error)

Result returns a stopped run's stored answer.

func (*Supervisor) Run

func (s *Supervisor) Run(ctx context.Context, interval time.Duration)

Run advances every non-terminal run until ctx ends. It wakes on any launch or cancel and otherwise ticks at interval.

func (*Supervisor) Wait

func (s *Supervisor) Wait(ctx context.Context, k Key)

Wait blocks until the run's record changes or ctx ends.

type Template

type Template struct {
	Version  int    `json:"version"`
	ID       string `json:"template_id"`
	Name     string `json:"template"`
	Pod      string `json:"pod"`
	ClawType string `json:"claw_type"`
	// ImageRef is the reference declared in the pod; ImageID pins the exact
	// image resolved at claw up.
	ImageRef     string `json:"image_ref"`
	ImageID      string `json:"image_id"`
	RunNetwork   string `json:"run_network"`
	CllamaURL    string `json:"cllama_url"`
	CllamaAPIURL string `json:"cllama_api_url"`
	// ToolsGrant is the sorted set of managed tool names a run may enable.
	ToolsGrant []string `json:"tools_grant"`
	// ContextDigest binds the cllama context (tools, models, policy, rules,
	// with credentials redacted) into the template identity.
	ContextDigest string               `json:"context_digest"`
	Limits        Limits               `json:"limits"`
	Worker        driver.RunWorkerSpec `json:"worker"`
}

Template is the compiled, claw up-owned description of a per-run worker. The caller of a launch only selects within it.

type Timestamps

type Timestamps struct {
	Accepted *time.Time `json:"accepted,omitempty"`
	Running  *time.Time `json:"running,omitempty"`
	Revoked  *time.Time `json:"revoked,omitempty"`
	Stopped  *time.Time `json:"stopped,omitempty"`
}

Timestamps records state transitions.

type WorkerLister

type WorkerLister interface {
	RunWorkers(ctx context.Context, podNS string) ([]Container, error)
}

WorkerLister lists every run-worker container for a pod.

Jump to

Keyboard shortcuts

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