Skip to content

ateapi: add ExternalVolumeSource.external_volume - #3745

Draft
hajiler wants to merge 3 commits into
agent-substrate:mainfrom
hajiler:shared-volumes/pr2-external-volume-ref
Draft

hajiler wants to merge 3 commits into
agent-substrate:mainfrom
hajiler:shared-volumes/pr2-external-volume-ref

Conversation

@hajiler

@hajiler hajiler commented Nov 9, 2026 •

Copy link
Copy Markdown
Collaborator

Part of #1637. (design: Substrate Shared External Volumes).

API-only: adds volumes[].external.external_volume to ActorTemplate so a template can name an ExternalVolume (#3744) in its atespace. Nothing mounts it yet: CreateActorTemplate rejects a template that sets it with UNIMPLEMENTED until the resume path can resolve it, so no actor can be created against a source nothing knows how to mount. Standalone; it does not depend on #3744.

external_volume.name is required for now. Binding an unnamed slot per actor at CreateActor comes with the change that uses the reference, and only relaxes this.

The reference is an ObjectRef, like every other reference to an atespaced resource. external_volume.atespace is required and CreateActorTemplate validation rejects a value that differs from the template's metadata.atespace, since the volume is mounted into that template's actors.

AI use: drafted with an AI agent under my direction.

TODO, for the change that lifts the UNIMPLEMENTED guard:

  • Resolve external_volume on the resume path so the actor mounts the registered volume.

  • Make DeleteExternalVolume reject with FAILED_PRECONDITION while an ActorTemplate or Actor references the volume. ateapi: add the ExternalVolume resource #3744's doc on that RPC already says it does; nothing enforces it until then, which only holds because this PR rejects the reference at create.

  • Record the reference on the volume's status, and settle the ExternalVolumeStatus naming before it lands (see the deferred threads on ateapi: add the ExternalVolume resource #3744).

  • Relax external_volume.name to optional once CreateActor can bind an unnamed slot.

  • Tests pass: apivalidation table rows (gate off and on), a controlapi test for the UNIMPLEMENTED guard, hack/verify-all.sh, apitool validate, hack/verify/proto-breaking.sh.

  • Docs updated: none needed; the field is not served yet and its API reference comment says so.

@hajiler
hajiler force-pushed the shared-volumes/pr2-external-volume-ref branch 2 times, most recently from 5a93f36 to 71ec36e Compare November 9, 2026 22:18

@hajiler hajiler left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Looked at the proto change, the create-time cross-atespace check, the UNIMPLEMENTED guard, the generated code, and the tests (they pass locally). I also checked for bypass paths: there is no UpdateActorTemplate RPC, the only create path goes through the RPC validation plus the ServiceImpl guard, and with the gate off or the client opted out the generated ifDisabled forbid on external short-circuits before ref is reached. Nothing blocking; two small API-surface notes inline.

Comment thread api/ateapi/v1/ateapi.proto Outdated
// +k8s:optional
// +k8s:unionMember
// +k8s:subfield(atespace)=+k8s:required
ObjectRef ref = 2;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

docs/api-style-guide.md section 2.3 says a cross-resource reference is named after the resource it points to (actor_template, not actor_template_ref), and #3744 follows that for the same target with GetExternalVolumeRequest.external_volume / DeleteExternalVolumeRequest.external_volume. A bare ref is the one place in the API where an ObjectRef field does not say what it refers to, and once more volume kinds arrive the name gives the reader nothing.

Suggest ObjectRef external_volume = 2; (so the union reads template / external_volume), with the comment, the custom-validation path (external, external_volume, atespace), the UNIMPLEMENTED message, and the test rows updated to match. Renaming is cheap now and a wire break later.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Renamed to external_volume in a83d19e, with the validation path, the UNIMPLEMENTED message, and the test rows updated to match.

Comment thread api/ateapi/v1/ateapi.proto Outdated
// +k8s:unionMember
ExternalVolumeTemplate template = 1;

// ref references an existing ExternalVolume. The volume outlives the

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

ExternalVolume is not a message in this file yet; it lands in #3744, which is still open. If this merges first, the rendered API reference (and the comment copied into ateapi.pb.go) names a resource that does not exist anywhere in the API, and a reader has no pointer to where it is defined.

Either sequence this after #3744, or add an internal note here, e.g. (-- The ExternalVolume resource is added in #3744. --), so the dependency is visible from the proto without leaking into the user-facing docs (style guide section 13.1).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Acknowledged. This PR will be sequenced after #3744 merges, so ExternalVolume will exist in the file by the time this lands.

@hajiler hajiler changed the title ateapi: add ExternalVolumeSource.ref ateapi: add ExternalVolumeSource.external_volume Nov 11, 2026
@hajiler
hajiler force-pushed the shared-volumes/pr2-external-volume-ref branch from a83d19e to 435c68c Compare November 11, 2026 23:10
hajiler and others added 3 commits November 11, 2026 15:11
A template volume will be able to name an ExternalVolume in the actor's
atespace instead of provisioning one per actor. This adds the field as the
second member of the external volume source union, behind the same
ExternalVolumes preview gate as template.

Nothing resolves the reference yet, so CreateActorTemplate rejects a
template that sets it with UNIMPLEMENTED.

Signed-off-by: Elijah Rodriguez-Beltran <elijahrb@google.com>
Replace the one-field ExternalVolumeRef message with the shared ObjectRef,
annotated subfield(atespace)=required like other references to atespaced
resources. CreateActorTemplate validation rejects a ref whose atespace
differs from the template's metadata.atespace, since the volume is mounted
into that template's actors.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Cross-resource references are named after the resource they point to
(docs/api-style-guide.md 2.3), as agent-substrate#3744 does for its references to the
same resource. Rename ExternalVolumeSource.ref to external_volume before
it is served.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@hajiler
hajiler force-pushed the shared-volumes/pr2-external-volume-ref branch from 435c68c to ab6186e Compare November 11, 2026 23:13

This branch has not been deployed

No deployments
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.

1 participant