Files
wehub-resource-sync e0e362d700
SDK Tests / changes (push) Successful in 2m29s
Real E2E Tests / changes (push) Successful in 2m29s
Deploy Docs Pages / build (push) Has been cancelled
Deploy Docs Pages / deploy (push) Has been cancelled
Real E2E Tests / JavaScript E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Python E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Java E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / C# E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Go E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Real E2E CI (push) Has been cancelled
SDK Tests / SDK CI (push) Has been cancelled
SDK Tests / CLI Tests (push) Has been cancelled
SDK Tests / Python SDK Quality (code-interpreter) (push) Has been cancelled
SDK Tests / Python SDK Quality (sandbox) (push) Has been cancelled
SDK Tests / Python SDK Tests (code-interpreter) (push) Has been cancelled
SDK Tests / JavaScript SDK Quality And Tests (code-interpreter) (push) Has been cancelled
SDK Tests / JavaScript SDK Quality And Tests (sandbox) (push) Has been cancelled
SDK Tests / Python SDK Tests (sandbox) (push) Has been cancelled
SDK Tests / CLI Quality (push) Has been cancelled
SDK Tests / Kotlin SDK Quality And Tests (sandbox) (push) Has been cancelled
SDK Tests / Kotlin SDK Quality And Tests (code-interpreter) (push) Has been cancelled
SDK Tests / C# SDK Quality And Tests (code-interpreter) (push) Has been cancelled
SDK Tests / C# SDK Quality And Tests (sandbox) (push) Has been cancelled
SDK Tests / Go SDK Quality And Tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:39:33 +08:00

14 KiB

title, description
title description
Go SDK Go client library for the OpenSandbox API covering lifecycle, execd, and egress operations.

OpenSandbox Go SDK

Go client library for the OpenSandbox API.

Covers all three OpenAPI specs:

  • Lifecycle -- Create, manage, and destroy sandbox instances
  • Execd -- Execute commands, manage files, monitor metrics inside sandboxes
  • Egress -- Inspect and mutate sandbox network policy at runtime

Installation

# go 1.20+
go get github.com/alibaba/OpenSandbox/sdks/sandbox/go

Quick Start

Create and manage a sandbox

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/alibaba/OpenSandbox/sdks/sandbox/go"
)

func main() {
    ctx := context.Background()

    lc := opensandbox.NewLifecycleClient("http://localhost:8080/v1", "your-api-key")

    sbx, err := lc.CreateSandbox(ctx, opensandbox.CreateSandboxRequest{
        Image:      opensandbox.ImageSpec{URI: "python:3.12"},
        Entrypoint: []string{"/bin/sh"},
        ResourceLimits: opensandbox.ResourceLimits{
            "cpu":    "500m",
            "memory": "512Mi",
        },
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Created sandbox: %s (state: %s)\n", sbx.ID, sbx.Status.State)

    sbx, err = lc.GetSandbox(ctx, sbx.ID)
    if err != nil {
        log.Fatal(err)
    }

    list, err := lc.ListSandboxes(ctx, opensandbox.ListOptions{
        States:   []opensandbox.SandboxState{opensandbox.StateRunning},
        PageSize: 10,
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Running sandboxes: %d\n", list.Pagination.TotalItems)

    _ = lc.PauseSandbox(ctx, sbx.ID)
    _ = lc.ResumeSandbox(ctx, sbx.ID)

    _ = lc.DeleteSandbox(ctx, sbx.ID)
}

Run a command with streaming output

exec := opensandbox.NewExecdClient("http://localhost:9090", "your-execd-token")

err := exec.RunCommand(ctx, opensandbox.RunCommandRequest{
    Command: "echo 'Hello from sandbox!'",
    Timeout: 30000,
}, func(event opensandbox.StreamEvent) error {
    switch event.Event {
    case "stdout":
        fmt.Print(event.Data)
    case "stderr":
        fmt.Fprintf(os.Stderr, "%s", event.Data)
    case "execution_complete":
        fmt.Println("\n[done]")
    }
    return nil
})

Check egress policy

egress := opensandbox.NewEgressClient("http://localhost:18080", "your-egress-token")

policy, err := egress.GetPolicy(ctx)
fmt.Printf("Mode: %s, Default: %s\n", policy.Mode, policy.Policy.DefaultAction)

updated, err := egress.PatchPolicy(ctx, []opensandbox.NetworkRule{
    {Action: "allow", Target: "api.example.com"},
})

Use Credential Vault

Credential Vault injects outbound credentials from the egress sidecar while keeping real secrets out of sandbox environment variables, commands, files, and logs. Create the sandbox with CredentialProxy enabled, then write credentials and bindings through the sandbox helpers or EgressClient.

config := opensandbox.ConnectionConfig{
    Domain:   "localhost:8080",
    Protocol: "http",
    APIKey:   "your-api-key",
}

sandbox, err := opensandbox.CreateSandbox(ctx, config, opensandbox.SandboxCreateOptions{
    Image: "python:3.11",
    NetworkPolicy: &opensandbox.NetworkPolicy{
        DefaultAction: "deny",
        Egress: []opensandbox.NetworkRule{
            {Action: "allow", Target: "api.example.com"},
        },
    },
    CredentialProxy: &opensandbox.CredentialProxyConfig{Enabled: true},
})
if err != nil {
    return err
}

_, err = sandbox.CreateCredentialVault(ctx, opensandbox.CredentialVaultCreateRequest{
    Credentials: []opensandbox.Credential{
        {
            Name: "api-token",
            Source: opensandbox.InlineCredentialSource{
                Type:  opensandbox.CredentialSourceInline,
                Value: "<token>",
            },
        },
    },
    Bindings: []opensandbox.CredentialBinding{
        {
            Name: "api-token",
            Match: opensandbox.CredentialMatch{
                Schemes: []opensandbox.CredentialScheme{opensandbox.CredentialSchemeHTTPS},
                Ports:   []int{443},
                Hosts:   []string{"api.example.com"},
                Paths:   []string{"/v1/*"},
            },
            Auth: opensandbox.CredentialAuth{
                Type:       opensandbox.CredentialAuthAPIKey,
                Name:       "x-api-key",
                Credential: "api-token",
            },
        },
    },
})

See Credential Vault for auth types, binding guidance, and Git/curl examples.

Sandbox Pool (Client-Side)

Use SandboxPool to keep an idle buffer of ready sandboxes and reduce acquire latency.

::: warning Experimental SandboxPool is still evolving based on production feedback and may introduce breaking changes in future releases. :::

package main

import (
    "context"
    "fmt"
    "log"
    "time"

    opensandbox "github.com/alibaba/OpenSandbox/sdks/sandbox/go"
)

func main() {
    ctx := context.Background()

    pool, err := opensandbox.NewSandboxPoolBuilder().
        PoolName("demo-pool").
        OwnerID("worker-1").
        MaxIdle(3).
        ConnectionConfig(opensandbox.ConnectionConfig{
            Domain: "api.opensandbox.io",
        }).
        CreationSpec(opensandbox.PoolCreationSpec{
            Image: "ubuntu:22.04",
        }).
        StateStore(opensandbox.NewInMemoryPoolStateStore()). // single-process only
        Build()
    if err != nil {
        log.Fatal(err)
    }

    if err := pool.Start(ctx); err != nil {
        log.Fatal(err)
    }

    failFast := opensandbox.AcquirePolicyFailFast
    sb, err := pool.Acquire(ctx, opensandbox.AcquireOptions{
        SandboxTimeout: 10 * time.Minute,
        Policy:         &failFast,
    })
    if err != nil {
        log.Fatal(err)
    }

    result, err := sb.RunCommand(ctx, "echo pool-ok", nil)
    if err == nil {
        fmt.Println(result.Text())
    }

    _ = sb.Kill(context.Background())
    // Drain idle sandboxes before shutdown (single-process cleanup).
    pool.ReleaseAllIdle(ctx)
    _ = pool.Shutdown(ctx, true)
}

For distributed deployment with multiple processes or pods, use RedisPoolStateStore. The store accepts a caller-managed redis.Client and does not create or close Redis connections.

import (
    "github.com/redis/go-redis/v9"
    opensandbox "github.com/alibaba/OpenSandbox/sdks/sandbox/go"
    "github.com/alibaba/OpenSandbox/sdks/sandbox/go/poolredis"
)

redisClient := redis.NewClient(&redis.Options{
    Addr: "redis.example.com:6379",
})

store, err := poolredis.NewRedisPoolStateStore(poolredis.RedisPoolStateStoreConfig{
    Client:    redisClient,
    KeyPrefix: "opensandbox:pool:prod",
})
if err != nil {
    log.Fatal(err)
}

pool, err := opensandbox.NewSandboxPoolBuilder().
    PoolName("prod-pool").
    OwnerID("worker-1").
    MaxIdle(10).
    StateStore(store).
    ConnectionConfig(opensandbox.ConnectionConfig{
        Domain: "api.opensandbox.io",
    }).
    CreationSpec(opensandbox.PoolCreationSpec{
        Image: "ubuntu:22.04",
    }).
    PrimaryLockTTL(60 * time.Second).
    Build()

::: info Pool Lifecycle Semantics

  • Acquire() is only allowed when pool state is RUNNING.
  • In DRAINING / STOPPED, Acquire() returns *PoolNotRunningError.
  • MaxIdle is the target/cap for ready idle sandboxes. It is not a global limit on borrowed sandboxes or sandboxes created by DirectCreate.
  • OwnerID is the lock owner identity (node/process id), not the pool identifier. If omitted, SDK auto-generates a default.
  • Use WarmupSandboxPreparer(...) if you need to prepare a sandbox after warmup readiness succeeds and before it is put into the idle pool. :::

::: tip Distributed Deployment

  • InMemoryPoolStateStore is for single-process development and tests.
  • For distributed deployment, all nodes in one logical pool must share the same Redis key prefix and PoolName.
  • All nodes sharing one pool must use the same creation and warmup definition. If that definition changes, use a new PoolName or key prefix and drain the old pool.
  • Resize(ctx, maxIdle) can be called from any node. The call returns after the target is stored in the shared state store; the current primary applies replenish or shrink work during periodic reconcile.
  • Use Resize(ctx, 0) and wait for Snapshot().IdleCount == 0 to drain a distributed idle buffer. ReleaseAllIdle() is only a best-effort cleanup pass in distributed mode.
  • Configure PrimaryLockTTL greater than WarmupReadyTimeout plus expected warmup preparer time. :::

API Reference

LifecycleClient

Created with NewLifecycleClient(baseURL, apiKey string, opts ...Option).

Method Description
CreateSandbox(ctx, req) Create a new sandbox from a container image
GetSandbox(ctx, id) Get sandbox details by ID
ListSandboxes(ctx, opts) List sandboxes with filtering and pagination
DeleteSandbox(ctx, id) Delete a sandbox
PauseSandbox(ctx, id) Pause a running sandbox
ResumeSandbox(ctx, id) Resume a paused sandbox
RenewExpiration(ctx, id, expiresAt) Extend sandbox expiration time
GetEndpoint(ctx, sandboxID, port, useServerProxy) Get public endpoint for a sandbox port
GetSignedEndpoint(ctx, sandboxID, port, expires) Get signed endpoint URL with OSEP-0011 route token

ExecdClient

Created with NewExecdClient(baseURL, accessToken string, opts ...Option).

Health:

Method Description
Ping(ctx) Check server health

Code Execution:

Method Description
ListContexts(ctx, language) List active code execution contexts
CreateContext(ctx, req) Create a code execution context
GetContext(ctx, contextID) Get context details
DeleteContext(ctx, contextID) Delete a context
DeleteContextsByLanguage(ctx, language) Delete all contexts for a language
ExecuteCode(ctx, req, handler) Execute code with SSE streaming
InterruptCode(ctx, sessionID) Interrupt running code

Command Execution:

Method Description
CreateSession(ctx) Create a bash session
RunInSession(ctx, sessionID, req, handler) Run command in session with SSE
DeleteSession(ctx, sessionID) Delete a bash session
RunCommand(ctx, req, handler) Run a command with SSE streaming
InterruptCommand(ctx, sessionID) Interrupt running command
GetCommandStatus(ctx, commandID) Get command execution status
GetCommandLogs(ctx, commandID, cursor) Get command stdout/stderr

File Operations:

Method Description
GetFileInfo(ctx, path) Get file metadata
DeleteFiles(ctx, paths) Delete files
SetPermissions(ctx, req) Change file permissions
MoveFiles(ctx, req) Move/rename files
SearchFiles(ctx, dir, pattern) Search files by glob pattern
ListDirectory(ctx, path) List immediate directory contents (server-side default depth)
ListDirectoryWithDepth(ctx, path, depth) List directory contents up to the given depth (0 returns empty)
ReplaceInFiles(ctx, req) Text replacement in files
UploadFile(ctx, file, opts) Upload a file to the sandbox
UploadFiles(ctx, entries) Upload multiple files to the sandbox
DownloadFile(ctx, remotePath, rangeHeader) Download a file from the sandbox

Directory Operations:

Method Description
CreateDirectory(ctx, path, mode) Create a directory (mkdir -p)
DeleteDirectory(ctx, path) Delete a directory recursively

Metrics:

Method Description
GetMetrics(ctx) Get system resource metrics
WatchMetrics(ctx, handler) Stream metrics via SSE

EgressClient

Created with NewEgressClient(baseURL, authToken string, opts ...Option).

Method Description
GetPolicy(ctx) Get current egress policy
PatchPolicy(ctx, rules) Merge rules into current policy
CreateCredentialVault(ctx, req) Create sandbox-local Credential Vault state
GetCredentialVault(ctx) Get sanitized Credential Vault state
PatchCredentialVault(ctx, req) Atomically mutate credentials and bindings
DeleteCredentialVault(ctx) Delete sandbox-local Credential Vault state
ListCredentialVaultCredentials(ctx) List sanitized credential metadata
GetCredentialVaultCredential(ctx, name) Get sanitized metadata for one credential
ListCredentialVaultBindings(ctx) List sanitized binding metadata
GetCredentialVaultBinding(ctx, name) Get sanitized metadata for one binding

SSE Streaming

Methods that stream output (RunCommand, ExecuteCode, RunInSession, WatchMetrics) accept an EventHandler callback:

type EventHandler func(event StreamEvent) error

Each StreamEvent contains:

  • Event -- the event type (e.g. "stdout", "stderr", "result", "execution_complete"). For NDJSON streams, this is extracted from the JSON type field automatically.
  • Data -- the raw event payload (JSON string for NDJSON streams).
  • ID -- optional event identifier

Return a non-nil error from the handler to stop processing the stream early.

Client Options

All client constructors accept optional Option functions:

client := opensandbox.NewLifecycleClient(url, key,
    opensandbox.WithHTTPClient(myHTTPClient),
)

client := opensandbox.NewExecdClient(url, token,
    opensandbox.WithTimeout(60 * time.Second),
)

::: info TLS Certificate Strength SDK-created HTTP clients enforce NIST 2030 minimum TLS certificate strength by default (RSA >= 2048, EC >= 224, DSA P >= 2048/Q >= 224, hash >= 224). If you must interoperate with legacy endpoints, set AllowWeakServerCertKeyLengths: true in TransportConfig. :::

Error Handling

Non-2xx responses are returned as *opensandbox.APIError:

_, err := lc.GetSandbox(ctx, "nonexistent")
if apiErr, ok := err.(*opensandbox.APIError); ok {
    fmt.Printf("HTTP %d: %s — %s\n", apiErr.StatusCode, apiErr.Response.Code, apiErr.Response.Message)
}

License

Apache 2.0