Skip to content

Bump Substrate to 3a2ca623 (go.ate.dev/substrate): string sandbox class, required actor CPU and memory limits - #91

Merged
Tomer Glottmann (tomergee) merged 5 commits into
mainfrom
bump-substrate-6edd1fcc
Oct 16, 2026
Merged

Tomer Glottmann (tomergee) merged 5 commits into
mainfrom
bump-substrate-6edd1fcc

Conversation

@tomergee

@tomergee Tomer Glottmann (tomergee) commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator

Moves the Substrate pin from da35a983 (2026-10-13, #84) to main at 3a2ca623 (2026-10-16), about 106 upstream commits. First opened at 6edd1fcc (2026-10-15); re-pinned on 2026-10-16, see Update below.

A smoke test of env main (1c08a7a) on a cluster running Substrate main failed at ActorTemplate registration. Run through Substrate main's own path (kubectl-ate's parser, defaults.Apply, ValidateCreateActorTemplateRequest), the template from main fails with:

actor_template.sandbox_config.sandbox_class: Unsupported value: "SANDBOX_CLASS_GVISOR": supported values: "gvisor", "microvm"
actor_template.resources: Required value

Review points addressed (7325ee3)

From an independent review of this PR:

  • --cpu / --memory follow Substrate's resources.limits validation: positive, at most 32 characters, cpu at most 999.999 cores, memory at most an int64 byte count. Before, --cpu=1000 printed a template the control plane rejects. The check moved from resolveImages into validateResources; tests cover each bound and both accepted maxima.
  • An explicit --cpu= or --memory= is an error instead of silently meaning the default.
  • TestDeriveImageTemplateKeepsResources: a template derived for a rootfs image keeps the base's limits.
  • README: the exact compatibility boundary (63a17a92, with 9ec49759 and c58f374a), an upgrade note (Substrate has no UpdateActorTemplate, and a base registered before the upgrade has no limits, thus each derived template fails resources: Required: delete the base and its derived templates and register the base again), and the cpu ceiling next to the --cpu docs.
  • The NeMo Gym README deploy command (NeMo Gym README has an outdated deployment command #76) was fixed in 086561e.

Verified at 7325ee3: go build, go vet, go test -race ./... twice (12 packages ok), make verify-gofmt verify-boilerplate, staticcheck clean. The CLI refuses --cpu=1000 and --cpu=, and accepts --cpu=999.999 and --memory=1Ei. Substrate main is one commit past the pin, with no API or CRD change.

Update 2026-10-16: re-pinned to 3a2ca623, module path go.ate.dev/substrate

Rebased onto main at 7be7449 (after #86) and bumped from 6edd1fcc to 3a2ca623, 34 more commits.

  • Substrate moved its Go module to the vanity path go.ate.dev/substrate (substrate#2181); go.ate.dev serves go-import metadata for the GitHub repository. All Substrate imports move to the new path, and the dependabot rules follow it. No other code change.
  • API: a compiled-descriptor diff of ateapi.proto between the two pins shows only three new worker-side fields (Worker.worker_spiffe_id, WorkerAssignment.worker_spiffe_id, MintWorkerActorCertificateRequest.worker). Nothing env sends or decodes is removed or retyped.
  • WorkerPool: no field change. A pool without a ServiceAccount now runs workers as ateworker, which the controller creates in the pool's namespace (088381b6), so the manifest needs nothing. The renames in 3a2ca623 itself are in the atelet and ateom protos.
  • README: the new pin, and the exact compatibility boundary from review (Substrate at or after 63a17a92, which has the string class from 9ec49759, the required limits from c58f374a, and the worker image rename).
  • Verified: go build, go vet, go test -race ./... (12 packages), make verify-gofmt verify-boilerplate, staticcheck clean, go mod tidy a no-op. The templates from this branch (default, --cpu 500m --memory 8Gi, --rootfs-image) pass Substrate 3a2ca623's kubectl-ate parse, defaults.Apply and ValidateCreateActorTemplateRequest.
  • Not in this PR: an intermittent failure of TestGuestCallWaitsForWake under a parallel go test ./... reproduces on main too. Three tests in guest/process/service_test.go use DefaultConfig(""), which resolves to the shared $TMPDIR/ate-jobs, and their cleanup removes that directory while other test binaries write to it (creating stdout log: … no such file or directory). A separate test-only fix.

What env needed

Breaks registration:

  • substrate#2586 makes SandboxConfig.sandbox_class a string at the same field number. The template now uses atev1alpha1.SandboxClassGvisor, the constant the WorkerPool already uses, so pool and template share one value.
  • substrate#2285 requires CPU and memory limits on every ActorTemplate. ate-env manifest template gains --cpu and --memory (Kubernetes quantities, default 2 and 4Gi, the Python client's ResourceLimits default). Bad or non-positive quantities fail client-side. Templates derived per rootfs image clone the base and inherit the limits; no change in DeriveImageTemplate.

Compile-only:

  • substrate#2575 renames ContainerWakeupProbe to WakeupProbe. Field number, message body and JSON key are unchanged, so the YAML is the same.
  • substrate#2620 deletes ACTOR_STATE_PAUSED and _PAUSING: a paused actor is SUSPENDED with a node-local snapshot. ate-env never pauses, so the two cases leave ActorStatusToEnvStatus with a comment, and the fake's PauseActor reports SUSPENDED. ENVIRONMENT_STATUS_PAUSED/_PAUSING stay in env's proto for wire compatibility; they are no longer produced.
  • substrate#2254 renames the worker image ateom-gvisor to ateworker-gvisor. Help text, the missing-flag error and docs follow; --ateom-image stays as an alias.

Checked and not relevant to env: the List* requests move page_size/page_token into ListOptions (substrate#2593), but env calls no List RPC. A descriptor diff of ateapi.proto between the two pins shows no other same-number type change or removed field in a message env sends or decodes. The WorkerPool CRD fields are unchanged.

Compatibility

After this PR, ate-env needs Substrate from 2026-10-14 or later: an older control plane rejects sandboxClass: gvisor. The README says so. A release cut after this PR targets current Substrate; one cut before targets da35a983.

Verification

  • go build, go vet, go test -race ./...: 12 packages ok. make verify-gofmt verify-boilerplate pass. staticcheck clean. go mod tidy is a no-op. Python client: 119 passed.
  • New tests: default limits and the gvisor class on the template, custom limits, rejection of two, 4GB!, 0 and -1Gi, and --cpu/--memory through the command into the YAML.
  • Server-side validation, against Substrate 6edd1fcc (kubectl-ate parse, defaults.Apply, ValidateCreateActorTemplateRequest): templates from this branch with default limits, with --cpu 500m --memory 8Gi, and with --rootfs-image are all valid; the template from main fails as quoted above.
  • Not yet run on a cluster: the test cluster I use runs a Substrate from 2026-10-12, which predates the string sandbox class. Results go in a comment once it runs Substrate main.

Also

  • Fixes NeMo Gym README has an outdated deployment command #76: the NeMo Gym README's deploy command passed --guest-image and --snapshots-bucket to ate-env manifest, which rejects them. It is now ate-env manifest --api-image --worker-image, then ate-env manifest template --guest-image --snapshots-bucket once ate-env-api runs. Both commands verified against this branch's CLI; the old one still fails with unknown flag: --guest-image.

Tomer Glottmann (tomergee) added a commit to tomergee/env that referenced this pull request Oct 16, 2026
…t flags for class, capabilities and limits

Completes the integration around the M0 driver:

- docs/openshell.md: the design page. Object model (which OpenShell object
  becomes which ate-env and Substrate object), the component diagram, how a
  sandbox comes up, the lifecycle vocabulary the gateway derives phases
  from, and what differs from OpenShell's own drivers (single actor, shared
  resolv.conf, credentials through the guest, capabilities, kernel).
- ate-env manifest template --sandbox-class, --sandbox-config, --cap-add,
  --cpu, --memory, and ate-env manifest --sandbox-class/--sandbox-config for
  the worker pool, with tests. The OpenShell template no longer needs a
  hand-written YAML: the generated one is identical to the one verified on
  the cluster. Defaults keep today's gvisor output unchanged. Overlaps agent-substrate#91,
  which will turn the class into a string; the flag names are the same.
- integrations/openshell: README rewritten as install, use, lifecycle,
  troubleshooting, development and known gaps; hack/install.sh (pool,
  template, gateway; re-runnable), hack/smoke.sh (create, exec, stop, start,
  ssh, forward, upload, download, delete, leak check with timings),
  deploy/workerpool.yaml, examples/agent_loop.py (OpenShell Python SDK
  driving a sandbox as a tool, policy built from the protobuf types) and
  examples/policy-example.yaml. make openshell-images builds the layer and
  the driver.
- driver: the condition mapping is a pure function, conditionsFor, with
  table tests that mirror the gateway's derive_phase; observe() only fetches
  the live status. No behaviour change. Gateway manifest pinned to the image
  built from this tree.

Verified on the cluster: install.sh re-run (pool updated, template kept,
gateway rolled to the new image), smoke.sh all steps passed twice, the SDK
example end to end (create 20 s, exec 0.1 s, stop 10 s, start 11 s).
Moves the Substrate pin from da35a983 (2026-10-13) to main at 6edd1fcc
(2026-10-15). Against that Substrate, env main's ActorTemplate is rejected
at registration:

- substrate#2586 made SandboxConfig.sandbox_class a string ("gvisor",
  "microvm") at the same field number. The template now names it with
  atev1alpha1.SandboxClassGvisor, the constant the WorkerPool already uses.
- substrate#2285 requires cpu and memory limits on every ActorTemplate.
  `ate-env manifest template` writes them, from new --cpu and --memory
  flags (Kubernetes quantities, default 2 and 4Gi, validated client-side).
  Templates derived per rootfs image clone the base and inherit them.

Compile-only follow-ups:

- substrate#2575 renamed ContainerWakeupProbe to WakeupProbe; the field
  number and JSON key are unchanged.
- substrate#2620 deleted ACTOR_STATE_PAUSED and _PAUSING: a paused actor
  is SUSPENDED with a node-local snapshot. ate-env never pauses, so the
  two cases leave ActorStatusToEnvStatus; the fake's PauseActor reports
  SUSPENDED.
- substrate#2254 renamed the worker image ateom-gvisor to
  ateworker-gvisor; the --worker-image help and error text follow, and
  --ateom-image stays as an alias.
The README names the new pin and what the cluster must accept (string
sandbox class, CPU and memory limits), says a Substrate older than
2026-10-14 needs an ate-env from before this bump, and documents the
--cpu and --memory defaults. The worker image is ateworker-gvisor in the
README, docs/release.md and the nemo-gym example.
…ifest template

The README passed --guest-image and --snapshots-bucket to `ate-env manifest`,
which fails with "unknown flag: --guest-image": those flags belong to
`ate-env manifest template`. Deploy with `ate-env manifest --api-image
--worker-image`, then register the template with `ate-env manifest template
--guest-image --snapshots-bucket` once ate-env-api runs, as the root README
does.

Fixes #76.
…substrate

Substrate main moved its module path to the vanity import go.ate.dev/substrate
(substrate#2181, 68a082c3); go.ate.dev serves go-import metadata pointing at
the GitHub repository. Every Substrate import moves to the new path, the
dependabot rules follow it, and gofmt reorders two import blocks.

Nothing else in env changes. Between 6edd1fcc and 3a2ca623 the ateapi proto
only gains worker-side fields (Worker.worker_spiffe_id,
WorkerAssignment.worker_spiffe_id, MintWorkerActorCertificateRequest.worker);
no field env sends or decodes is removed or retyped. WorkerPool keeps its
fields; a pool without a ServiceAccount now runs workers as "ateworker", which
the controller creates in the pool's namespace (088381b6), so the manifest
needs nothing. The renames in 3a2ca623 are in the atelet and ateom protos.

The README names the new pin and the exact compatibility boundary: Substrate
at or after 63a17a92 (2026-10-15), which accepts the string sandbox class
(9ec49759) and requires the limits (c58f374a), and renamed the worker image.
@tomergee Tomer Glottmann (tomergee) changed the title Bump Substrate to 6edd1fcc: string sandbox class, required actor CPU and memory limits Bump Substrate to 3a2ca623 (go.ate.dev/substrate): string sandbox class, required actor CPU and memory limits Oct 16, 2026
…ounds; README upgrade note

From review of #91:

- --cpu and --memory now follow Substrate's resources.limits validation
  (internal/resources.ValidateLimit and the Limits.quantity maxLength): a
  positive quantity of at most 32 characters, cpu at most 999.999 cores,
  memory at most an int64 byte count. Before, --cpu=1000 printed a template
  the control plane rejects. The check moves out of resolveImages into
  validateResources.
- An explicit --cpu= or --memory= is an error instead of silently meaning
  the default.
- A test proves that a template derived for a rootfs image keeps the base's
  limits.
- README: after upgrading across the boundary, delete and register base
  templates again (Substrate has no UpdateActorTemplate, and a base without
  limits makes each derived template fail resources: Required), and the cpu
  ceiling next to the --cpu docs.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@tomergee
Tomer Glottmann (tomergee) merged commit a044830 into main Oct 16, 2026
14 checks passed
Tomer Glottmann (tomergee) added a commit to tomergee/env that referenced this pull request Oct 16, 2026
…t flags for class and capabilities

Completes the integration around the M0 driver, rebased onto agent-substrate#91 (Substrate
3a2ca623 at go.ate.dev/substrate: string sandbox class, required limits,
--cpu/--memory on manifest template).

- docs/openshell.md: the design page. Object model (which OpenShell object
  becomes which ate-env and Substrate object), the component diagram, how a
  sandbox comes up, the lifecycle vocabulary the gateway derives phases
  from, and what differs from OpenShell's own drivers (single actor, shared
  resolv.conf, credentials through the guest, capabilities, kernel).
- ate-env manifest template --sandbox-class, --sandbox-config and --cap-add
  next to agent-substrate#91's --cpu/--memory, and ate-env manifest --sandbox-class/
  --sandbox-config for the worker pool, with tests. The OpenShell template no
  longer needs a hand-written YAML; defaults keep today's gvisor output.
- third_party/openshell: options.proto leaves out the MethodOptions
  extension authorization = 50000. go.ate.dev/substrate registers
  ateapi.method on MethodOptions with the same number, and Go's protobuf
  registry panics at init when one binary links both; the compute-driver
  contract uses only the secret field option (50001).
- integrations/openshell: README rewritten as install, use, lifecycle,
  troubleshooting, development and known gaps; hack/install.sh (pool,
  template, gateway; re-runnable), hack/smoke.sh (create, exec, stop, start,
  ssh, forward, upload, download, delete, leak check with timings),
  deploy/workerpool.yaml, examples/agent_loop.py (OpenShell Python SDK
  driving a sandbox as a tool, policy built from the protobuf types) and
  examples/policy-example.yaml. make openshell-images builds the layer and
  the driver.
- driver: the condition mapping is a pure function, conditionsFor, with
  table tests that mirror the gateway's derive_phase; observe() only fetches
  the live status. No behaviour change. Gateway manifest pinned to the image
  built from this tree.

Verified on the cluster after the rebase: the driver starts (no registry
panic), smoke.sh passes end to end, install.sh re-runs cleanly, the SDK
example runs (create 20 s, exec 0.1 s, stop 10 s, start 11 s). The
generated template needs Substrate 63a17a92 or later on the cluster.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NeMo Gym README has an outdated deployment command

2 participants