Environments
Provisioning, running commands in, and tearing down microVMs
client.Environments provisions, inspects, drives, and tears down microVMs.
Here’s a complete flow: create one, wait for it to boot, run a command inside
it, then tear it down.
env, err := client.Environments.Create(ctx, fuse.CreateRequest{
TaskID: "build-1",
Spec: fuse.Spec{CPUs: 2, RamMB: 2048, StorageGB: 10},
})
if err != nil {
log.Fatal(err)
}
res, err := client.Environments.Exec(ctx, env.ID, fuse.ExecRequest{
Cmd: []string{"make", "test"},
})
if err != nil {
log.Fatal(err)
}
if res.ExitCode != 0 {
log.Fatalf("tests failed: %s", res.Stderr)
}
if err := client.Environments.Destroy(ctx, env.ID); err != nil {
log.Fatal(err)
}
Createprovisions from aSpec(CPUs, RAM, storage, and optionally GPU) and blocks server-side until the environment isrunningor provisioning fails, so the returned*EnvironmentInfoalready reflects the outcome. No separate poll-until-ready step is needed for the common case.SpeccarriesGPUs,GPUKind, andGPUProfile; setGPUProfileto a mig-parted profile such as1g.10gbto request MIG instances instead of whole devices. The TypeScript and Python SDKs carry the same GPU surface, includingHostCapacity.GPUDevicesand theGPUDevicetype.Execruns one command inside the guest and returns its exit code with stdout/stderr kept apart. A non-zeroExitCodeis a successful call, not anerror, the command ran and failed, which is the answer you asked for. Only a non-nilerrormeans the command couldn’t run at all (VM not found, VM not running, or the provider has no guest to exec into).Execrequires the master token, see Errors.Destroytears the environment down from any state and is idempotent, a second call on an already-gone environment returns anot_found*APIErrorrather than panicking or hanging.
Watching state instead of exec
If you need to react to lifecycle transitions rather than run a one-shot
command, Events opens a live stream instead of a single call:
events, err := client.Environments.Events(ctx, env.ID)
if err != nil {
log.Fatal(err)
}
for ev := range events {
if ev.Err != nil {
log.Fatal(ev.Err)
}
log.Println(ev.State)
if fuse.IsTerminalState(ev.State) {
break
}
}
The stream delivers the current state immediately on connect, then one event
per transition, and closes on its own after a terminal state
(destroyed/failed). See the full walkthrough in
Quickstart.
Interactive sessions
For a real terminal instead of a one-shot command, Attach opens a framed,
duplex stream to a pty inside the guest, the same mechanism behind
fuse environment shell:
stream, err := client.Environments.Attach(ctx, env.ID, fuse.AttachOptions{
Rows: 24, Cols: 80,
})
if err != nil {
log.Fatal(err)
}
defer stream.Close()
go io.Copy(stream, os.Stdin)
for {
f, err := stream.ReadFrame()
if err != nil {
break
}
if f.Type == fuse.FrameStdout || f.Type == fuse.FrameStderr {
os.Stdout.Write(f.Payload)
}
}
This needs a real terminal on the calling end (raw mode, resize handling),
it’s built for building your own fuse environment shell-style tool, not for
scripted automation, use Exec for that. Also master-token only.
Everything else
| Method | Purpose |
|---|---|
List(ctx, ListEnvironmentsOptions{...}) |
List environments, optionally filtered by TaskID/State/HostID. |
Get(ctx, vmID) |
Fetch one environment by ID. |
Drain(ctx, vmID) |
Phase one of teardown: signal the guest to stop gracefully without destroying the VM. |
Fork(ctx, vmID, ForkOptions{...}) |
Create a new environment seeded from a snapshot of this one. |
RotateToken(ctx, vmID) |
Re-issue the guest’s credentials without recreating the VM. |
Fork is unavailable wherever snapshotting is, GPU/QEMU-backed environments can’t be forked, see Providers. Full signatures are in the SDK’s Go doc comments; the shapes above mirror the HTTP API one to one.
Lifecycle states
const (
StateProvisioning = "provisioning"
StateRunning = "running"
StateDraining = "draining"
StateDestroying = "destroying"
StateDestroyed = "destroyed"
StateFailed = "failed"
)
func IsTerminalState(state string) bool
IsTerminalState reports whether state is destroyed or failed, the two
states after which an event stream closes.