Documentation
¶
Overview ¶
Package sandbox is the Go SDK for the cocoon sandbox control plane: claim a microVM from a sandboxd node, run commands in it over the relayed silkd protocol, release it.
Index ¶
- Constants
- type Checkpoint
- type Client
- func (c *Client) Attach(ownerAddr, id, token string) *Sandbox
- func (c *Client) Checkpoints(ctx context.Context) ([]*Checkpoint, error)
- func (c *Client) DeleteTemplate(ctx context.Context, template string, opts ...Option) error
- func (c *Client) Drain(ctx context.Context) (*NodeInfo, error)
- func (c *Client) Info(ctx context.Context) (*NodeInfo, error)
- func (c *Client) Lookup(ctx context.Context, id, token string) (*Sandbox, error)
- func (c *Client) New(ctx context.Context, template string, opts ...Option) (*Sandbox, error)
- func (c *Client) SetPools(ctx context.Context, pools []PoolSpec) (*NodeInfo, error)
- func (c *Client) SetPoolsCluster(ctx context.Context, pools []PoolSpec) ([]PoolResult, error)
- func (c *Client) Uncordon(ctx context.Context) (*NodeInfo, error)
- type ClientOption
- type Cmd
- type ExitError
- type Lsp
- type NetShape
- type NodeInfo
- type Option
- type PoolKey
- type PoolResult
- type PoolSpec
- type PoolStatus
- type PortConn
- func (p *PortConn) Close() error
- func (p *PortConn) CloseWrite() error
- func (p *PortConn) LocalAddr() net.Addr
- func (p *PortConn) Read(b []byte) (int, error)
- func (p *PortConn) RemoteAddr() net.Addr
- func (p *PortConn) SetDeadline(time.Time) error
- func (p *PortConn) SetReadDeadline(time.Time) error
- func (p *PortConn) SetWriteDeadline(time.Time) error
- func (p *PortConn) Write(b []byte) (int, error)
- type Pty
- type PtyOpts
- type Sandbox
- func (s *Sandbox) Attach(ctx context.Context, pid uint32, stdout, stderr io.Writer) (code int32, exited bool, err error)
- func (s *Sandbox) Checkpoint(ctx context.Context, name string) (*Checkpoint, error)
- func (s *Sandbox) Close() error
- func (s *Sandbox) DialPort(ctx context.Context, port uint16) (*PortConn, error)
- func (s *Sandbox) Exec(ctx context.Context, argv ...string) (string, error)
- func (s *Sandbox) Find(ctx context.Context, path, pattern, glob string) ([]wire.Match, error)
- func (s *Sandbox) Fork(ctx context.Context, count int, ttl time.Duration) ([]*Sandbox, error)
- func (s *Sandbox) GitAdd(ctx context.Context, path string, files ...string) error
- func (s *Sandbox) GitBranches(ctx context.Context, path string) (*wire.GitBranches, error)
- func (s *Sandbox) GitCheckout(ctx context.Context, path, name string) error
- func (s *Sandbox) GitClone(ctx context.Context, url, path, branch string, depth uint32, auth string) error
- func (s *Sandbox) GitCommit(ctx context.Context, path, message, author string) (string, error)
- func (s *Sandbox) GitCreateBranch(ctx context.Context, path, name string) error
- func (s *Sandbox) GitDeleteBranch(ctx context.Context, path, name string) error
- func (s *Sandbox) GitPull(ctx context.Context, path, auth string) error
- func (s *Sandbox) GitPush(ctx context.Context, path, auth string) error
- func (s *Sandbox) GitStatus(ctx context.Context, path string) (*wire.GitStatusResult, error)
- func (s *Sandbox) Hibernate(ctx context.Context) error
- func (s *Sandbox) Kill(ctx context.Context, pid uint32, sig int32) error
- func (s *Sandbox) ListDir(ctx context.Context, path string) ([]wire.DirEntry, error)
- func (s *Sandbox) Logs(ctx context.Context, pid uint32, stdout, stderr io.Writer) (code int32, exited bool, err error)
- func (s *Sandbox) Mkdir(ctx context.Context, path string, parents bool) error
- func (s *Sandbox) NewSession(ctx context.Context, opts ...SessionOption) (*Session, error)
- func (s *Sandbox) OpenPty(ctx context.Context, opts PtyOpts) (*Pty, error)
- func (s *Sandbox) Owner() string
- func (s *Sandbox) PreviewURL(ctx context.Context, port uint16, ttl time.Duration) (string, error)
- func (s *Sandbox) Promote(ctx context.Context, template string) (*Template, error)
- func (s *Sandbox) ProxyPort(ctx context.Context, localAddr string, port uint16) (net.Listener, error)
- func (s *Sandbox) Ps(ctx context.Context) ([]wire.ProcInfo, error)
- func (s *Sandbox) Pull(ctx context.Context, path string, tarStream io.Writer) error
- func (s *Sandbox) Push(ctx context.Context, dest string, tarStream io.Reader) error
- func (s *Sandbox) ReadFile(ctx context.Context, path string) ([]byte, error)
- func (s *Sandbox) Remove(ctx context.Context, path string, recursive bool) error
- func (s *Sandbox) Rename(ctx context.Context, from, to string) error
- func (s *Sandbox) Replace(ctx context.Context, files []string, pattern, replacement string) ([]wire.Replaced, error)
- func (s *Sandbox) Run(ctx context.Context, cmd Cmd) (int, error)
- func (s *Sandbox) Sessions(ctx context.Context) ([]string, error)
- func (s *Sandbox) Spawn(ctx context.Context, cmd Cmd) (uint32, error)
- func (s *Sandbox) StartLsp(ctx context.Context, language, root string) (*Lsp, error)
- func (s *Sandbox) Stat(ctx context.Context, path string) (wire.FileInfo, error)
- func (s *Sandbox) Token() string
- func (s *Sandbox) Watch(ctx context.Context, path string, recursive bool) (*Watcher, error)
- func (s *Sandbox) WriteFile(ctx context.Context, path string, data []byte, mode *uint32) error
- type Session
- type SessionOption
- type Size
- type Template
- type Watcher
Constants ¶
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Checkpoint ¶
type Checkpoint struct {
ID string
Name string
SandboxID string
CreatedAt time.Time
// contains filtered or unexported fields
}
Checkpoint is a captured sandbox state bound to the node that holds it. New claims fresh sandboxes branched from the captured moment, any number of times; the source sandbox is unaffected and can keep being checkpointed, so successive captures form a tree.
func (*Checkpoint) Delete ¶
func (ck *Checkpoint) Delete(ctx context.Context) error
Delete removes the checkpoint from its node and asks every peer that node currently sees to drop any replica a heal pulled — best-effort eventual cleanup, not a fleet-wide revocation. A peer that misses that broadcast (offline, partitioned, or joined later) keeps serving branches from its replica until the node's checkpoint_ttl_hours ages it out; with that TTL at its default of 0 (keep forever), an unreachable peer's replica has no cleanup bound at all. See the cluster docs' placement lifecycle.
func (*Checkpoint) New ¶
New claims a sandbox cloned from the checkpoint, on the checkpoint's node. The snapshot pins the key axes; WithTimeout may set the TTL. A node that no longer holds the checkpoint redirects to a probed owner, which New follows transparently; if every candidate fails transiently, New falls back to the origin once so it heals (pulls the checkpoint) locally.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client talks to one sandboxd node.
func Connect ¶
func Connect(addr string, opts ...ClientOption) (*Client, error)
Connect returns a client for a sandboxd node. addr accepts a comma-separated seed list for forward compatibility; v0 uses the first entry.
func (*Client) Attach ¶ added in v0.1.3
Attach binds a handle to an already-claimed sandbox whose owner data-plane address is already known (e.g. delivered by the L3 apiserver as annotations), with no lookup round-trip. Use it to exec/agent into a sandbox claimed out of band. ownerAddr is the node's sandboxd data-plane address; token is the per-sandbox credential.
func (*Client) Checkpoints ¶
func (c *Client) Checkpoints(ctx context.Context) ([]*Checkpoint, error)
Checkpoints lists the CONNECTED node's checkpoints, newest first; the returned handles are bound to that node.
func (*Client) DeleteTemplate ¶
DeleteTemplate removes a promoted template by name. When the entry node does not hold it but the mesh's gossip names an owner, the delete follows the redirect there (one hop); gossip lags a fresh promote by about a tick, so right after promoting prefer Template.Delete on the returned handle. The options pick the template's key axes exactly as a claim would (network lane, size); the same defaults apply.
func (*Client) Drain ¶
Drain cordons the entry node (root token): new claims/forks/branches are refused, live claims run to their leases; poll Info until Claimed is zero.
func (*Client) Lookup ¶
Lookup relocates a sandbox handle whose owner address was lost, given its id and token: it asks the entry node, then scatters across the cluster's peers concurrently, and returns a handle bound to whichever node confirms ownership first — one hung peer must not stall the whole lookup.
func (*Client) New ¶
New claims a sandbox for template. Without options the node serves its defaults: the no-network lane and the smallest size tier. New returns when the sandbox's silkd is reachable; a warm pool hit is milliseconds, a cold key can take the full boot. Against a cluster, a warm miss redirects to a peer that holds one, which New follows transparently; if every candidate fails transiently (full, mid-heal, unreachable), New falls back to the origin once so it provisions or heals locally.
func (*Client) SetPools ¶
SetPools replaces the entry node's desired warm pools (PUT /v1/pools): a declarative full replace, so omitted pools drain. Requires the operator token.
func (*Client) SetPoolsCluster ¶
SetPoolsCluster applies pools to the entry node and every peer, returning a per-node result; retrying failed nodes is the whole protocol (idempotent replace). A non-nil error means peer discovery failed and only the entry node was reached — an incomplete apply to retry, not a single-node cluster (nil).
type ClientOption ¶
type ClientOption func(*Client)
ClientOption configures Connect.
func WithAPIToken ¶
func WithAPIToken(token string) ClientOption
WithAPIToken sets the operator bearer for every node-scoped call — claim and info, plus drain, pools, templates, checkpoints, and fork/promote/preview.
type Cmd ¶
type Cmd struct {
Argv []string
Cwd string
Env map[string]string
User string
Session string // when set, runs inside that persistent shell session
// Stdin is consumed until EOF or until the command exits. A blocking
// reader (e.g. os.Stdin) whose command exits first keeps its pump
// goroutine parked in Read until the next bytes arrive — do not share
// one reader across Runs, the stale pump would swallow them. nil closes
// the child's stdin immediately.
Stdin io.Reader
Stdout io.Writer // nil discards
Stderr io.Writer // nil discards
}
Cmd describes a streaming Run.
type Lsp ¶
type Lsp struct {
ServerID string
// contains filtered or unexported fields
}
Lsp is a language server running in the sandbox, spoken to over the relay. silkd is a broker: it spawns the flavor image's server and pipes JSON-RPC bytes; the caller frames and correlates (agents already speak LSP).
func (*Lsp) Request ¶
Request opens the JSON-RPC byte stream to the language server: the returned PortConn writes go to the server's stdin, reads come from its stdout. A server serves one Request for its lifetime — closing the stream ends the session and reaps the server (start a new one to work again).
type NodeInfo ¶
type NodeInfo struct {
Pools []PoolStatus `json:"pools"`
Claimed int `json:"claimed"`
Hibernated int `json:"hibernated"`
Archived int `json:"archived"`
Draining bool `json:"draining,omitempty"`
Peers []string `json:"peers,omitempty"`
}
NodeInfo is one node's operational state from GET /v1/info.
type Option ¶
type Option func(*claimRequest)
Option configures a New claim.
func WithTimeout ¶
WithTimeout bounds the sandbox's lifetime: the owning node reaps it after d (rounded up to seconds) even if the client vanishes.
type PoolKey ¶
type PoolKey struct {
Template string `json:"template"`
Net NetShape `json:"net"`
Size Size `json:"size"`
}
PoolKey identifies one warm pool on a node.
type PoolResult ¶
PoolResult is one node's outcome from SetPoolsCluster.
type PoolSpec ¶
type PoolSpec struct {
Template string `json:"template"`
Net NetShape `json:"net,omitempty"`
Size Size `json:"size,omitempty"`
Warm int `json:"warm"`
WarmMax int `json:"warm_max,omitempty"`
IdleHibernateSeconds int `json:"idle_hibernate_seconds,omitempty"`
ArchiveAfterSeconds int `json:"archive_after_seconds,omitempty"`
ArchiveDeleteAfterSeconds int `json:"archive_delete_after_seconds,omitempty"`
}
PoolSpec is a desired warm pool for SetPools. Egress is config-owned on the node and rejected by the API, so it has no field here.
type PoolStatus ¶
type PoolStatus struct {
Key PoolKey `json:"key"`
Warm int `json:"warm"`
Refilling int `json:"refilling"`
Target int `json:"target"`
Golden bool `json:"golden"`
}
PoolStatus reports one warm pool on a node.
type PortConn ¶
type PortConn struct {
// contains filtered or unexported fields
}
PortConn is a net.Conn to a TCP port inside the sandbox, relayed over the silkd protocol (works on the no-network lane — the vsock relay is its only transport). Read returns io.EOF when the guest server closes; CloseWrite half-closes the guest socket. Deadlines are not supported (bound the DialPort ctx instead).
func (*PortConn) CloseWrite ¶
CloseWrite half-closes the guest socket (the server sees EOF) while reads keep draining its response.
func (*PortConn) LocalAddr ¶
LocalAddr implements net.Conn; the relay has no meaningful socket address.
func (*PortConn) RemoteAddr ¶
func (*PortConn) SetDeadline ¶
SetDeadline implements net.Conn; deadlines are unsupported — bound the DialPort ctx instead.
func (*PortConn) SetReadDeadline ¶
SetReadDeadline implements net.Conn; unsupported, see SetDeadline.
func (*PortConn) SetWriteDeadline ¶
SetWriteDeadline implements net.Conn; unsupported, see SetDeadline.
type Pty ¶
type Pty struct {
PID uint32
// contains filtered or unexported fields
}
Pty is an open pseudo-terminal in the sandbox. Read yields terminal output (EOF when the shell exits), Write feeds input, Resize adjusts the window, and Close (or canceling the OpenPty ctx) ends the session.
func (*Pty) ExitCode ¶
ExitCode reports the shell's exit code once Read has returned io.EOF; ok is false while the shell is still running.
func (*Pty) Read ¶
Read returns terminal output; io.EOF signals the shell has exited (check ExitCode after).
type Sandbox ¶
type Sandbox struct {
ID string
Deadline time.Time
// FromCheckpoint names the checkpoint this sandbox branched from; empty
// for pool and template claims.
FromCheckpoint string
// contains filtered or unexported fields
}
Sandbox is a claimed sandbox handle; all data-plane calls dial its owning node directly.
func (*Sandbox) Attach ¶
func (s *Sandbox) Attach(ctx context.Context, pid uint32, stdout, stderr io.Writer) (code int32, exited bool, err error)
Attach replays the buffered output, then follows live output until the process exits, returning its exit code. exited is false only when the proc table dropped the process mid-attach (reap race).
func (*Sandbox) Checkpoint ¶
Checkpoint captures the sandbox's full state — memory, disk, running processes — without stopping it, and returns a handle that branches new sandboxes from that exact moment. name is an optional label.
func (*Sandbox) Close ¶
Close releases the sandbox on its node; releasing one already gone is not an error. It takes no ctx so it stays defer-friendly — bounded internally.
func (*Sandbox) DialPort ¶
DialPort connects to 127.0.0.1:port inside the sandbox. The ctx governs the connection's lifetime: canceling it (or Close) tears the relay down. A port nobody listens on fails here with silkd's not_found error.
func (*Sandbox) Exec ¶
Exec runs argv to completion and returns its stdout; a non-zero exit surfaces as *ExitError carrying stderr, alongside the partial stdout.
func (*Sandbox) Find ¶
Find returns the lines under path matching pattern (a regular expression); glob, when non-empty, narrows the walk to file names matching it (`*` and `?` wildcards).
func (*Sandbox) Fork ¶
Fork clones the sandbox into count children — memory, disk, and guest state (sessions, processes, tmpfs) duplicate at the fork point, and each child gets a fresh machine identity and its own lease. ttl bounds every child's lifetime; zero means the server default. All-or-nothing: on error no child survived. Forking a hibernated sandbox reuses its memory image without waking it.
func (*Sandbox) GitBranches ¶
GitBranches lists the repo's branches and the current one.
func (*Sandbox) GitCheckout ¶
GitCheckout checks out branch name.
func (*Sandbox) GitClone ¶
func (s *Sandbox) GitClone(ctx context.Context, url, path, branch string, depth uint32, auth string) error
GitClone clones url into path in the sandbox; depth > 0 makes a shallow clone. Auth, when non-empty, is a token sent as an in-memory Authorization header. Needs the egress lane.
func (*Sandbox) GitCommit ¶
GitCommit stages nothing (call GitAdd first); it commits the index with message and author ("Name <email>") and returns the new commit hash.
func (*Sandbox) GitCreateBranch ¶
GitCreateBranch creates branch name.
func (*Sandbox) GitDeleteBranch ¶
GitDeleteBranch force-deletes branch name.
func (*Sandbox) GitPush ¶
GitPush pushes the current branch. Auth as in GitClone. Needs the egress lane; on the no-network lane it fails with a typed error pointing at Push.
func (*Sandbox) Hibernate ¶
Hibernate atomically snapshots the sandbox and stops its VM, freeing its memory; the next call that reaches the guest wakes it transparently with sessions, processes, and memory state intact. The TTL keeps running — a hibernated sandbox is still reaped at its deadline.
func (*Sandbox) Kill ¶
Kill signals a tracked process; sig 0 sends SIGKILL. Killing one that already exited is a no-op success — its OS pid may be recycled, so silkd never signals a reaped child.
func (*Sandbox) ListDir ¶
ListDir returns the entries of a directory (batched frames are concatenated).
func (*Sandbox) Logs ¶
func (s *Sandbox) Logs(ctx context.Context, pid uint32, stdout, stderr io.Writer) (code int32, exited bool, err error)
Logs replays a tracked process's ring-buffered output into the writers (nil discards). exited reports whether the process has ended; code is its exit code when it has.
func (*Sandbox) NewSession ¶
NewSession opens a persistent shell.
func (*Sandbox) OpenPty ¶
OpenPty starts a shell under a pty. The ctx governs the pty's lifetime: canceling it (or calling Close) tears the session down.
func (*Sandbox) Owner ¶
Owner returns the data-plane address of the node that owns the sandbox — on a cluster the node a redirected claim landed on.
func (*Sandbox) PreviewURL ¶
PreviewURL mints a shareable URL that serves the sandbox's guest HTTP port from a plain browser, valid for ttl (the node clamps it to the claim's lease). Requires the node to have preview configured.
func (*Sandbox) Promote ¶
Promote publishes the sandbox's current state as a template on its owning node: later claims for it (with this sandbox's network lane and size) clone from it, provision-on-demand. Re-promoting to the same name replaces the template. Like Fork, a hibernated sandbox is promoted from its memory image without waking. Templates are node-local — the returned handle is bound to the owning node, and its New/Delete always reach it (name-based Client calls only see the connected node's templates).
func (*Sandbox) ProxyPort ¶
func (s *Sandbox) ProxyPort(ctx context.Context, localAddr string, port uint16) (net.Listener, error)
ProxyPort listens on localAddr (e.g. "127.0.0.1:0") and pipes every accepted connection to the sandbox port, so unmodified local tools reach the guest server. Closing the listener stops new connections; canceling ctx tears down the live ones.
func (*Sandbox) Ps ¶
Ps lists the guest's tracked processes — execs, spawns, and ptys — with state and exit codes.
func (*Sandbox) Push ¶
Push extracts a tar stream under dest in the sandbox — the no-network lane's way to move a project in. tarStream is a reader of tar bytes (e.g. from archive/tar); silkd runs `tar -x` under dest.
func (*Sandbox) Replace ¶
func (s *Sandbox) Replace(ctx context.Context, files []string, pattern, replacement string) ([]wire.Replaced, error)
Replace rewrites pattern (a regular expression) to replacement in each of files, returning one result per file with its replacement count.
func (*Sandbox) Run ¶
Run executes cmd in the sandbox, streaming stdio over one relayed silkd connection, and returns the exit code.
func (*Sandbox) Spawn ¶
Spawn starts cmd detached: it returns the guest pid as soon as the process starts, and the process keeps running with a bounded output ring readable later via Logs or Attach. cmd's Stdin/Stdout/Stderr are ignored; cmd.Session must be empty — the session exec path cannot detach.
func (*Sandbox) StartLsp ¶
StartLsp spawns the language server the flavor image provides for language (rooted at root), returning a handle. On the base image, which ships no language servers, this fails with silkd's typed not_found.
func (*Sandbox) Token ¶
Token is the per-sandbox bearer secret — persist it with ID to reattach later via Lookup (treat it like a credential).
type Session ¶
type Session struct {
ID string
// contains filtered or unexported fields
}
Session is a persistent shell in the sandbox: cwd, env, and shell state survive across Exec calls until Close.
type SessionOption ¶
type SessionOption func(*wire.SessionCreate)
SessionOption configures NewSession.
func WithSessionCwd ¶
func WithSessionCwd(dir string) SessionOption
WithSessionCwd sets the session's initial working directory.
func WithSessionEnv ¶
func WithSessionEnv(env map[string]string) SessionOption
WithSessionEnv sets the session's initial environment.
type Size ¶
type Size string
Size is a T-shirt resource tier; free-form CPU/memory would fragment the node's warm pools.
type Template ¶
type Template struct {
Name string
// contains filtered or unexported fields
}
Template is a promoted template bound to the node that holds it. Its New and Delete dial the owner directly — no gossip involved — so unlike the name-based Client calls they are usable the instant Promote returns.
type Watcher ¶
type Watcher struct {
// contains filtered or unexported fields
}
Watcher is an open filesystem watch. Events yields events until the watch ends — by Close, ctx cancellation, or a watcher error on the sandbox side — after which Err reports the terminal error (nil after a clean Close).
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
silkdtest
Package silkdtest fakes a silkd daemon for host-side tests: deterministic frame semantics over any listener, plus the hybrid-vsock muxer handshake for tests that dial a UDS the way sandboxd does.
|
Package silkdtest fakes a silkd daemon for host-side tests: deterministic frame semantics over any listener, plus the hybrid-vsock muxer handshake for tests that dial a UDS the way sandboxd does. |