Documentation
¶
Overview ¶
Package sandboxd is a small HTTP client for the node-local sandboxd warm-pool daemon (the sandbox repo's docs/sandboxd-api.md). It uses only the standard library. The L2 ClaimGateway fronts one of these clients per node: Claim transfers ownership of an already-running microVM in sub-millisecond time, and Release destroys a sandbox's VM on owner-authorized teardown.
Index ¶
- Variables
- type Checkpoint
- type CheckpointClaimSpec
- type CheckpointSpec
- type ClaimResult
- type ClaimSpec
- type Client
- func (c *Client) Checkpoint(ctx context.Context, id string, spec CheckpointSpec) (Checkpoint, error)
- func (c *Client) Checkpoints(ctx context.Context) ([]Checkpoint, error)
- func (c *Client) Claim(ctx context.Context, spec ClaimSpec) (ClaimResult, error)
- func (c *Client) ClaimCheckpoint(ctx context.Context, checkpointID string, spec CheckpointClaimSpec) (ClaimResult, error)
- func (c *Client) DeleteCheckpoint(ctx context.Context, checkpointID string) error
- func (c *Client) Fork(ctx context.Context, id string, spec ForkSpec) (ForkResult, error)
- func (c *Client) Hibernate(ctx context.Context, id string) error
- func (c *Client) Info(ctx context.Context) (*NodeInfo, error)
- func (c *Client) Promote(ctx context.Context, id string, spec PromoteSpec) (PoolKey, error)
- func (c *Client) Release(ctx context.Context, id, token string) error
- func (c *Client) Sandbox(ctx context.Context, id string) (SandboxSummary, error)
- func (c *Client) Sandboxes(ctx context.Context) ([]SandboxSummary, error)
- func (c *Client) SetPools(ctx context.Context, pools []PoolSpec) (*NodeInfo, error)
- func (c *Client) Stats(ctx context.Context, id string) (SandboxStats, error)
- func (c *Client) Wake(ctx context.Context, id string) error
- type ForkResult
- type ForkSpec
- type HTTPError
- type NodeInfo
- type NodePool
- type Option
- type PoolKey
- type PoolSpec
- type PromoteResult
- type PromoteSpec
- type SandboxStats
- type SandboxSummary
Constants ¶
This section is empty.
Variables ¶
var ErrNodeAtCapacity = errors.New("sandboxd: node at capacity or draining")
ErrNodeAtCapacity is returned by Claim when sandboxd answers 429 (the node is at max_claims, the calling tenant is at its own max_claims, or the node is draining), or when a 200 carries only a peer redirect rather than a delivered sandbox. In every case this node handed over no VM, so the L2 gateway maps this to its ErrNoNodeCapacity sentinel and falls back to the L1 Kubernetes path.
Functions ¶
This section is empty.
Types ¶
type Checkpoint ¶
type Checkpoint struct {
ID string `json:"id"`
Name string `json:"name,omitempty"`
SandboxID string `json:"sandbox_id"`
Key PoolKey `json:"key"`
CreatedAt time.Time `json:"created_at"`
}
Checkpoint is a captured sandbox state that branches can be claimed from.
type CheckpointClaimSpec ¶
type CheckpointClaimSpec struct {
TTLSeconds int `json:"ttl_seconds,omitempty"`
}
CheckpointClaimSpec is the POST /v1/checkpoints/{id}/claim body.
type CheckpointSpec ¶
type CheckpointSpec struct {
Token string `json:"token,omitempty"`
Name string `json:"name,omitempty"`
}
CheckpointSpec is the POST /v1/sandboxes/{id}/checkpoint body.
type ClaimResult ¶
type ClaimResult struct {
ID string `json:"id"`
Token string `json:"token"`
Deadline time.Time `json:"deadline"`
OwnerAddr string `json:"owner_addr"`
// FromCheckpoint is the lineage edge when the claim branched from a checkpoint.
FromCheckpoint string `json:"from_checkpoint,omitempty"`
// Redirect, when non-empty on a 200, names warm peers to retry at instead of a
// delivered sandbox. Claim treats this as a capacity miss (see ErrNodeAtCapacity).
Redirect []string `json:"redirect,omitempty"`
}
ClaimResult is the POST /v1/claim success body.
type ClaimSpec ¶
type ClaimSpec struct {
Template string `json:"template"`
Net string `json:"net,omitempty"`
Size string `json:"size,omitempty"`
TTLSeconds int `json:"ttl_seconds,omitempty"`
// NoRedirect is set by an SDK retrying at a redirect target; the gateway does
// not chase redirects (it falls back to L1 instead), so it stays false.
NoRedirect bool `json:"no_redirect,omitempty"`
// ClaimRef is the k8s "<namespace>/<name>" of the Sandbox this claim is
// created for. sandboxd records it on the claim and echoes it in its
// operator index, so the aggregated read path can map a listed sandbox back
// to the name it was claimed under. Empty for claims with no k8s identity.
ClaimRef string `json:"claim_ref,omitempty"`
}
ClaimSpec is the POST /v1/claim body. Net defaults to "none" and Size to "small" server-side; TTLSeconds 0 means the server default.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client talks to a single sandboxd instance. It is safe for concurrent use.
func New ¶
New returns a Client for the sandboxd at baseURL, authenticating resource verbs with the node api_token (may be empty when sandboxd runs without auth).
func (*Client) Checkpoint ¶
func (c *Client) Checkpoint(ctx context.Context, id string, spec CheckpointSpec) (Checkpoint, error)
Checkpoint performs POST /v1/sandboxes/{id}/checkpoint, capturing the sandbox's state under a fresh id. The source keeps running.
func (*Client) Checkpoints ¶
func (c *Client) Checkpoints(ctx context.Context) ([]Checkpoint, error)
Checkpoints performs GET /v1/checkpoints, newest first.
func (*Client) Claim ¶
Claim performs POST /v1/claim, returning the delivered sandbox on success. A 429, or a 200 that carries only a peer redirect, yields ErrNodeAtCapacity.
func (*Client) ClaimCheckpoint ¶
func (c *Client) ClaimCheckpoint(ctx context.Context, checkpointID string, spec CheckpointClaimSpec) (ClaimResult, error)
ClaimCheckpoint performs POST /v1/checkpoints/{id}/claim, delivering a fresh sandbox branched from the checkpoint's exact state.
func (*Client) DeleteCheckpoint ¶
DeleteCheckpoint performs DELETE /v1/checkpoints/{id}. A 404 is success.
func (*Client) Fork ¶
Fork performs POST /v1/sandboxes/{id}/fork, branching the sandbox into count children. The parent is checkpointed in place and keeps running; each child is a fresh claim with its own id and lease.
func (*Client) Hibernate ¶
Hibernate performs POST /v1/sandboxes/{id}/hibernate: it snapshots the sandbox and stops its VM, freeing the node's memory. This is the pause verb; its cost is proportional to guest RAM because the memory is written out.
func (*Client) Info ¶ added in v0.1.2
Info performs GET /v1/info: the node's live per-pool warm state and lifecycle counters, read without touching its pool config.
func (*Client) Promote ¶
Promote performs POST /v1/sandboxes/{id}/promote, publishing the sandbox as a node-local template that later claims for that key clone from.
func (*Client) Release ¶
Release performs POST /v1/sandboxes/{id}/release, which DESTROYS the VM. It authenticates with the sandbox's own token. A 404 (unknown id or already gone) is treated as success, matching the SDK. Callers must only reach this on owner-authorized teardown — see the ClaimGateway.Release contract.
func (*Client) Sandbox ¶
Sandbox performs GET /v1/sandboxes/{id}, the single-sandbox read that avoids scanning the whole-node listing.
func (*Client) Sandboxes ¶
func (c *Client) Sandboxes(ctx context.Context) ([]SandboxSummary, error)
Sandboxes performs GET /v1/sandboxes, this node's live claims.
func (*Client) SetPools ¶
SetPools performs PUT /v1/pools, replacing this node's desired warm targets with the supplied set (an omitted pool is drained). It authenticates with the node api_token. The whole set is sent in one request because sandboxd replaces its pool config wholesale — a partial list silently drains the rest.
type ForkResult ¶
type ForkResult struct {
Children []ClaimResult `json:"children"`
}
ForkResult carries one claim per child; children are fresh sandboxes with their own ids and leases, and the parent keeps running.
type ForkSpec ¶
type ForkSpec struct {
Token string `json:"token,omitempty"`
Count int `json:"count"`
TTLSeconds int `json:"ttl_seconds,omitempty"`
}
ForkSpec is the POST /v1/sandboxes/{id}/fork body. Token stays empty on the operator path; Count must be within the node's max_fork_count.
type HTTPError ¶
type HTTPError struct {
StatusCode int
// Message is the decoded {"error": "..."} body when present.
Message string
}
HTTPError carries a non-2xx sandboxd status that is not otherwise typed (e.g. 400 bad body, 401 bad api token, 409 egress mismatch, 500 provisioning failed).
type NodeInfo ¶
type NodeInfo struct {
Pools []NodePool `json:"pools"`
Claimed int `json:"claimed"`
Hibernated int `json:"hibernated"`
Archived int `json:"archived"`
}
NodeInfo is the PUT /v1/pools (and GET /v1/info) response: the node's live per-pool warm state plus its lifecycle counters.
type NodePool ¶
type NodePool struct {
Key PoolKey `json:"key"`
Warm int `json:"warm"`
Refilling int `json:"refilling"`
Target int `json:"target"`
Golden bool `json:"golden"`
}
NodePool is one pool's live state in a NodeInfo. Only the fields the warm-pool driver reports on are decoded.
type Option ¶
type Option func(*Client)
Option configures a Client.
func WithHTTPClient ¶
WithHTTPClient overrides the default *http.Client (for custom transports or timeouts). The default client has no timeout: sandboxd keeps read/write timeouts at zero because cold claims legitimately block, so callers bound the call with the context instead.
type PoolKey ¶
type PoolKey struct {
Template string `json:"template"`
Net string `json:"net,omitempty"`
Size string `json:"size,omitempty"`
Engine string `json:"engine,omitempty"`
}
PoolKey is a checkpoint's or template's pool identity.
type PoolSpec ¶
type PoolSpec struct {
Template string `json:"template"`
Net string `json:"net,omitempty"`
Size string `json:"size,omitempty"`
Warm int `json:"warm"`
}
PoolSpec is one entry of the PUT /v1/pools body: the desired warm watermark for a single (template, net, size) pool on this node. It mirrors the claim key so a SandboxWarmPool's target lands on the exact pool a Create claims from.
type PromoteResult ¶
type PromoteResult struct {
Key PoolKey `json:"key"`
}
PromoteResult returns the promoted template's full key.
type PromoteSpec ¶
PromoteSpec is the POST /v1/sandboxes/{id}/promote body: it publishes the sandbox's state as a node-local template future claims clone from.
type SandboxStats ¶
type SandboxStats struct {
ID string `json:"id"`
CPUCount int `json:"cpu_count"`
MemTotalBytes int64 `json:"mem_total_bytes"`
MemUsedBytes int64 `json:"mem_used_bytes"`
Hibernated bool `json:"hibernated"`
MeasuredAt time.Time `json:"measured_at"`
MemUsedMeasured bool `json:"mem_used_measured"`
}
SandboxStats is one sandbox's resource usage. CPUCount and MemTotalBytes are the tier the VM was booted with (authoritative); MemUsedBytes is the host VMM's resident set and is only meaningful when MemUsedMeasured is true — a hibernated sandbox has no process to measure.
type SandboxSummary ¶
type SandboxSummary struct {
ID string `json:"id"`
Key PoolKey `json:"key"`
Deadline time.Time `json:"deadline"`
Hibernated bool `json:"hibernated"`
Archived bool `json:"archived,omitempty"`
FromCheckpoint string `json:"from_checkpoint,omitempty"`
ClaimRef string `json:"claim_ref,omitempty"`
}
SandboxSummary is one live claim as the owning node reports it.