Skip to content
Fuse
Esc
navigateopen⌘Jpreview
On this page

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)
}
  • Create provisions from a Spec (CPUs, RAM, storage, and optionally GPU) and blocks server-side until the environment is running or provisioning fails, so the returned *EnvironmentInfo already reflects the outcome. No separate poll-until-ready step is needed for the common case. Spec carries GPUs, GPUKind, and GPUProfile; set GPUProfile to a mig-parted profile such as 1g.10gb to request MIG instances instead of whole devices. The TypeScript and Python SDKs carry the same GPU surface, including HostCapacity.GPUDevices and the GPUDevice type.
  • Exec runs one command inside the guest and returns its exit code with stdout/stderr kept apart. A non-zero ExitCode is a successful call, not an error, the command ran and failed, which is the answer you asked for. Only a non-nil error means the command couldn’t run at all (VM not found, VM not running, or the provider has no guest to exec into). Exec requires the master token, see Errors.
  • Destroy tears the environment down from any state and is idempotent, a second call on an already-gone environment returns a not_found *APIError rather 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.

Was this page helpful?