Skip to content

Commit 8886b07

Browse files
authored
Merge pull request #921 from zpzjzj/feat/go-sdk-platform-spec
feat(sdks/go): add PlatformSpec to CreateSandboxRequest
2 parents 54afd00 + cc8298e commit 8886b07

3 files changed

Lines changed: 102 additions & 0 deletions

File tree

sdks/sandbox/go/opensandbox_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,68 @@ func TestCreateSandbox_FromSnapshot(t *testing.T) {
263263
require.NoErrorf(t, err, "CreateSandbox from snapshot")
264264
}
265265

266+
func TestCreateSandbox_Platform(t *testing.T) {
267+
_, client := newLifecycleServer(t, func(w http.ResponseWriter, r *http.Request) {
268+
var req CreateSandboxRequest
269+
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
270+
assert.Fail(t, fmt.Sprintf("decode request: %v", err))
271+
return
272+
}
273+
require.NotNil(t, req.Platform, "expected Platform to be sent in the request")
274+
require.Equal(t, OSWindows, req.Platform.OS, "Platform.OS")
275+
require.Equal(t, ArchAMD64, req.Platform.Arch, "Platform.Arch")
276+
277+
jsonResponse(w, http.StatusCreated, SandboxInfo{
278+
ID: "sbx-windows",
279+
Status: SandboxStatus{State: StatePending},
280+
Platform: &PlatformSpec{OS: OSWindows, Arch: ArchAMD64},
281+
CreatedAt: time.Now().UTC().Truncate(time.Second),
282+
})
283+
})
284+
285+
info, err := client.CreateSandbox(context.Background(), CreateSandboxRequest{
286+
Image: &ImageSpec{URI: "dockurr/windows:latest"},
287+
Entrypoint: []string{"cmd", "/c", "echo hi"},
288+
ResourceLimits: ResourceLimits{"cpu": "2", "memory": "4G", "disk": "64G"},
289+
Platform: &PlatformSpec{OS: OSWindows, Arch: ArchAMD64},
290+
})
291+
require.NoErrorf(t, err, "CreateSandbox with Platform")
292+
require.NotNil(t, info.Platform, "response should echo Platform")
293+
require.Equal(t, OSWindows, info.Platform.OS, "echoed Platform.OS")
294+
require.Equal(t, ArchAMD64, info.Platform.Arch, "echoed Platform.Arch")
295+
}
296+
297+
func TestCreateSandbox_PlatformOmittedWhenNil(t *testing.T) {
298+
_, client := newLifecycleServer(t, func(w http.ResponseWriter, r *http.Request) {
299+
body, err := io.ReadAll(r.Body)
300+
if err != nil {
301+
assert.Fail(t, fmt.Sprintf("read request body: %v", err))
302+
return
303+
}
304+
var raw map[string]json.RawMessage
305+
if err := json.Unmarshal(body, &raw); err != nil {
306+
assert.Fail(t, fmt.Sprintf("unmarshal request body: %v", err))
307+
return
308+
}
309+
if _, present := raw["platform"]; present {
310+
assert.Fail(t, "platform should be omitted from JSON when nil")
311+
}
312+
313+
jsonResponse(w, http.StatusCreated, SandboxInfo{
314+
ID: "sbx-no-platform",
315+
Status: SandboxStatus{State: StatePending},
316+
CreatedAt: time.Now().UTC().Truncate(time.Second),
317+
})
318+
})
319+
320+
_, err := client.CreateSandbox(context.Background(), CreateSandboxRequest{
321+
Image: &ImageSpec{URI: "python:3.12"},
322+
Entrypoint: []string{"/bin/sh"},
323+
ResourceLimits: ResourceLimits{"cpu": "500m"},
324+
})
325+
require.NoErrorf(t, err, "CreateSandbox without Platform")
326+
}
327+
266328
func TestGetSandbox(t *testing.T) {
267329
want := SandboxInfo{
268330
ID: "sbx-456",

sdks/sandbox/go/sandbox.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ type SandboxCreateOptions struct {
6666
// Extensions for provider-specific parameters.
6767
Extensions map[string]string
6868

69+
// Platform selects the target OS/arch for the sandbox (e.g. {"os":
70+
// "windows", "arch": "amd64"}). When nil the server applies its default.
71+
Platform *PlatformSpec
72+
6973
// SkipHealthCheck skips the WaitUntilReady call after creation.
7074
SkipHealthCheck bool
7175

@@ -132,6 +136,7 @@ func CreateSandbox(ctx context.Context, config ConnectionConfig, opts SandboxCre
132136
NetworkPolicy: opts.NetworkPolicy,
133137
Volumes: opts.Volumes,
134138
Extensions: opts.Extensions,
139+
Platform: opts.Platform,
135140
}
136141
if opts.Image != "" {
137142
req.Image = &ImageSpec{URI: opts.Image, Auth: opts.ImageAuth}

sdks/sandbox/go/types.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,39 @@ type ImageAuth struct {
5555
Password string `json:"password"`
5656
}
5757

58+
// PlatformOS is the target operating system of a sandbox platform constraint.
59+
// The wire-level enum is enforced server-side; the constants below mirror the
60+
// spec so Go callers can avoid stringly-typed typos.
61+
type PlatformOS string
62+
63+
const (
64+
OSLinux PlatformOS = "linux"
65+
OSWindows PlatformOS = "windows"
66+
)
67+
68+
// PlatformArch is the target CPU architecture of a sandbox platform
69+
// constraint.
70+
type PlatformArch string
71+
72+
const (
73+
ArchAMD64 PlatformArch = "amd64"
74+
ArchARM64 PlatformArch = "arm64"
75+
)
76+
77+
// PlatformSpec is a runtime platform constraint used for scheduling and
78+
// provisioning. It is independent from Image and expresses the expected
79+
// target OS and CPU architecture for sandbox execution.
80+
//
81+
// When omitted, the server applies its own default platform selection
82+
// behavior. When provided, the runtime must satisfy the constraint or the
83+
// request fails.
84+
//
85+
// See specs/sandbox-lifecycle.yml#/components/schemas/PlatformSpec.
86+
type PlatformSpec struct {
87+
OS PlatformOS `json:"os"`
88+
Arch PlatformArch `json:"arch"`
89+
}
90+
5891
// ResourceLimits defines runtime resource constraints as key-value pairs.
5992
// Common keys: "cpu" (e.g. "500m"), "memory" (e.g. "512Mi"), "gpu" (e.g. "1").
6093
type ResourceLimits map[string]string
@@ -120,6 +153,7 @@ type CreateSandboxRequest struct {
120153
NetworkPolicy *NetworkPolicy `json:"networkPolicy,omitempty"`
121154
Volumes []Volume `json:"volumes,omitempty"`
122155
Extensions map[string]string `json:"extensions,omitempty"`
156+
Platform *PlatformSpec `json:"platform,omitempty"`
123157
}
124158

125159
// SandboxInfo represents a runtime execution environment provisioned from a
@@ -133,6 +167,7 @@ type SandboxInfo struct {
133167
Entrypoint []string `json:"entrypoint"`
134168
ExpiresAt *time.Time `json:"expiresAt,omitempty"`
135169
CreatedAt time.Time `json:"createdAt"`
170+
Platform *PlatformSpec `json:"platform,omitempty"`
136171
}
137172

138173
type SnapshotState string

0 commit comments

Comments
 (0)