feat(sdk/go): add Go SDK foundation, types, and sandbox client (A)#2271
feat(sdk/go): add Go SDK foundation, types, and sandbox client (A)#2271rhuss wants to merge 3 commits into
Conversation
Add the Go SDK module with the full API contract and a working sandbox client as the first vertical slice. All other resource clients are present as stubs returning Unimplemented errors, to be replaced with real implementations in subsequent PRs. Contents: - Module setup (go.mod, Makefile, mise.toml) - All domain types (types/ package) - Full ClientInterface with all sub-client accessors - Shared infrastructure (errors, auth, gRPC connection, logging) - Sandbox client with converter and tests (fully functional) - Stub clients for remaining resources (exec, file, health, provider, profile, config, refresh, policy, service, ssh, tcp) Part of the Go SDK decomposition plan (NVIDIA#2270). Implements NVIDIA#2044.
| } | ||
| opts = append(opts, grpc.WithTransportCredentials(creds)) | ||
| } else { | ||
| opts = append(opts, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{MinVersion: tls.VersionTLS12}))) |
There was a problem hiding this comment.
[codex:gpt-5.5] http:// gateway addresses are accepted but still dialed with TLS. NewConnection strips both https:// and http://, then falls through to credentials.NewTLS(...) whenever TLSConfig is nil. That diverges from the existing CLI behavior, where http:// explicitly means plaintext gRPC, and it will make Go users fail against loopback/plaintext gateway URLs unless they also know to set TLS: &TLSConfig{Insecure: true}. Please make scheme parsing drive transport selection (http:// -> insecure.NewCredentials(), https:// -> TLS, no scheme -> documented default) and add a regression test for the http:// case.
There was a problem hiding this comment.
Valid, will fix. The scheme should drive transport selection instead of being silently stripped. http:// should use insecure.NewCredentials(), https:// or no scheme should use TLS. Will add a regression test for the http:// case.
| Annotations map[string]string | ||
| Environment map[string]string | ||
| UserNamespaces *bool | ||
| } |
There was a problem hiding this comment.
[codex:gpt-5.5] The implemented sandbox client cannot express the current template resource fields. The public proto has SandboxTemplate.resources for CPU/memory/resource limits and SandboxTemplate.driver_config for driver-specific settings, and the server actively validates and forwards both into compute drivers. This SDK type only exposes image/runtime/agent socket/labels/annotations/env/user namespaces, so Create will silently be unable to create sandboxes that need CPU/memory limits or driver config such as Docker CDI devices or Kubernetes scheduling. Please add these fields to the SDK SandboxTemplate type and preserve them in both SandboxSpecToProto and SandboxFromProto.
There was a problem hiding this comment.
Correct, SandboxTemplate is missing resources and driver_config fields that the proto defines. Will add them to the SDK type and update both converter directions.
| @@ -0,0 +1 @@ | |||
| 29ce6a704cba222c29b5e0d73b90280cf5ed3b9f | |||
There was a problem hiding this comment.
[codex:gpt-5.5] The vendored Go proto snapshot is behind the repository proto sources. For example, current proto/sandbox.proto includes NetworkEndpoint.credential_signing, signing_service, signing_region, json_rpc_max_body_bytes, mcp, and MCP params matchers, but sdk/go/proto/sandbox.proto stops at advisor_proposed. Current proto/openshell.proto also reserves volume_claim_templates, while the SDK snapshot still generates that field. Because the generated Go types and SDK domain model are built from this snapshot, Go clients cannot represent current policy features such as SigV4/MCP and may serialize a field the current API has explicitly removed. Please regenerate from the current proto/ sources in this branch and add a check that fails when sdk/go/proto/*.proto drift from the canonical proto files.
There was a problem hiding this comment.
Fair point. This is a first drop based on a proto snapshot that will naturally drift. Proto freshness CI checks are planned for a later PR in the series (PR F in #2270), and proto sync is also an operational requirement in the SDK acceptance scorecard RFC (#2293). For this PR, I will regenerate from the current proto sources. The CI guard will prevent future drift.
Principal Engineer Review — Go SDK foundation (A)Reviewed by checking out the branch and reading every non-generated file. Blocking1. Dead code will fail the project's own lint gate —
|
|
|
||
| // ExecInterface is defined in exec.go | ||
|
|
||
| // FileInterface is defined in file.go |
There was a problem hiding this comment.
[codex:gpt-5.5] gofmt -l $(find sdk/go -name "*.go") reports multiple handwritten files, including this one, types/sandbox.go, types/profile.go, types/refresh.go, types/network_policy.go, types/errors.go, stub_clients.go, internal/converter/network_policy.go, internal/converter/errors.go, and sandbox_client_test.go. Please run gofmt/goimports before merging so the committed SDK matches standard Go formatting.
There was a problem hiding this comment.
Good catch. Will run gofmt -w and goimports -w across all handwritten Go files before the next push.
- Make scheme parsing drive transport selection: http:// uses plaintext gRPC, https:// or no scheme uses TLS. Add regression tests. - Add Resources and DriverConfig fields to SandboxTemplate and update both converter directions (SandboxFromProto/SandboxSpecToProto). - Regenerate proto bindings from current canonical proto sources to eliminate drift (SigV4/MCP fields, params matchers, reserved fields). - Run gofmt/goimports on all handwritten Go files. Signed-off-by: Roland Huß <rhuss@redhat.com>
russellb
left a comment
There was a problem hiding this comment.
[codex:gpt-5.5] Finding 1: The Go SDK still drops active sandbox policy fields from the handwritten types/converters. The synced proto includes credential_signing, signing_service, signing_region, json_rpc_max_body_bytes, mcp, and params on L7 allow/deny rules, but PolicyNetworkEndpoint, L7Allow, L7DenyRule, and the converters omit them. Since Create sends SandboxSpecToProto, Go clients cannot express current SigV4/MCP/JSON-RPC policy controls, and server-returned policies lose these fields on round-trip. Please add SDK fields and bidirectional converter coverage for every current proto policy field. Refs: sdk/go/openshell/v1/types/network_policy.go:19, sdk/go/openshell/v1/internal/converter/network_policy.go:65, proto/sandbox.proto:131, proto/sandbox.proto:211.
[codex:gpt-5.5] Finding 2: mapToStruct ignores structpb.NewStruct errors for SandboxTemplate.Resources and DriverConfig. Invalid UTF-8 keys or unsupported map[string]any values make NewStruct return nil, err, but the SDK silently sends nil, so user-provided template config can disappear without an error. Please make sandbox spec conversion fallible, validate before CreateSandbox, or expose a safer typed representation, and add tests for invalid values. Refs: sdk/go/openshell/v1/internal/converter/copy.go:60, sdk/go/openshell/v1/internal/converter/sandbox.go:170, sdk/go/openshell/v1/sandbox_client.go:28.
- Remove dead boolCount function that would fail golangci-lint (#1) - Emit EventAdded for the first watch event instead of EventModified, matching k8s watch semantics (#7) - Add mutex locking to all mock server methods that access the shared sandboxes map, fixing latent race conditions (#12) - Skip HealthCheck integration test that calls an unimplemented stub (#13) - Scope doc.go examples: mark sections for sub-clients not yet available in this PR with "available in a future release" (#4) - Document Config.Timeout/RetryPolicy/Logger and WatchOptions fields as reserved for future use (#2, #6) Signed-off-by: Roland Huß <rhuss@redhat.com>
|
My agent's response to #2271 (comment). Most of the things are because of this artificial split to get the PRs down to something more consumable (which was also important as I hight some size limits for code agent's review when I dropped it). But thank you very much for jumping on it, I've addressed the comments (and delayed some until we get the full combo in) Thanks for the review. Here is my assessment, classifying each finding by root cause: Already addressed (in a prior fix commit
Fixed now (commit
Deferred to later PRs (expected from the A-F split):
Accepted as low-priority (not blocking):
|
Sounds good. I figured some of it would be off, but that your agent would sort it out. :) |
Context
This is the first PR in a 6-PR decomposition of the Go SDK contribution (#2044). The decomposition was discussed in the contributor meeting on 2026-07-14 to make the review process more approachable.
The first PR is intentionally the largest because it carries the shared foundation. After this merge, the SDK is usable end-to-end for sandbox management. Each subsequent PR then incrementally adds one more resource group, and after every merge the SDK is fully working with an expanded API surface.
What's in this PR
go.mod,go.sum,Makefile,mise.tomltypes/package (14 files) covering every SDK resourceClientInterface: all 10 sub-client accessors defined upfrontUnimplementederrors linking to feat(sdk/go): Go SDK PR decomposition plan #2270. Each subsequent PR replaces stubs with real implementations.How to Review
Review zones
client.go,types/*.go,errors.go,auth*.go,sandbox.go,sandbox_client.go,internal/grpc/conn.gosandbox_client_test.go,internal/converter/sandbox.go,internal/converter/sandbox_test.gosandbox_client_test.goas the test pattern exemplar. Converter tests follow table-driven patterns.stub_clients.go,go.sum,Makefile,mise.toml,doc.go, interface-only files (exec.go,file.go, etc.)proto/*.pb.go,proto/*_grpc.pb.goKey design decisions
types/package has no proto imports, insulating consumers from wire format changesErrorUnimplementedwith a link to the tracking issue. Each follow-up PR replaces stubs with real implementations without modifyingclient.go.What to look for
ClientInterfacecovers the right API surfaceIsNotFound(), etc.)Testing
All 130 tests pass:
Resolves #2044 (with remaining PRs B-F)
Part of #2270