Skip to content

api: remove ExternalVolume.Status enum and status field #2414

Closed

Description

Problem

In pkg/proto/ateapipb/ateapi.proto (lines 352–366), ExternalVolume defines a nested Status enum and status field:

message ExternalVolume {
  ...
  enum Status {
    STATUS_UNSPECIFIED = 0;
    STATUS_PENDING = 1;
    STATUS_CREATED = 2;
    STATUS_DELETING = 3;
  }

  Status status = 4;
}

This has two issues:

  1. Inconsistent use of status: Across ateapi.proto, status is a distinct API concept reserved for server-managed container messages on resources (ActorStatus status, WorkerStatus status, TagStatus status, ActorTemplateStatus status), never for a lifecycle
    enum field.
  2. Redundant "phase"-style enum: Like Kubernetes phase fields (which Kubernetes API conventions deprecate), every value of ExternalVolume.Status duplicates state already recorded on ExternalVolume and ActorStatus:
    • STATUS_PENDING vs STATUS_CREATED is 1-to-1 with storage_volume_id == "" vs storage_volume_id != "":
      • CreateActor (volumes.go:49-53) initializes each ExternalVolume entry in actor.status.actor_volumes with volume_name, volume_type, storage_volume_id: "", and status: STATUS_PENDING.
      • ResumeActor (volumes.go:130-136) calls plugin.CreateVolume and sets storage_volume_id: resp.VolumeID and status: STATUS_CREATED in the same struct literal (detachActorVolumes in volumes.go:224-228 already checks vol.GetStorageVolumeId() == "" to skip
        unprovisioned volumes).
    • STATUS_DELETING is 1-to-1 with actor.status.state == ACTOR_STATE_DELETING:
      • STATUS_DELETING is only ever written in workflow_delete.go:335-338 inside the exact same store transaction that sets actor.status.state = ACTOR_STATE_DELETING.
      • deleteActorVolumes (volumes.go:142-160) never inspects vol.GetStatus(); ensureVolumesDeleted only checks actor.GetStatus().GetState() == ACTOR_STATE_DELETING.

Idempotency & Failure Recovery

Removing ExternalVolume.status preserves the exact same idempotency and crash-recovery guarantees as the current implementation:

  • Normal ResumeActor after provisioning: Once UpdateActor persists storage_volume_id, subsequent ResumeActor calls see vol.GetStorageVolumeId() != "" and skip plugin.CreateVolume (just as they currently check STATUS_CREATED).
  • Crash between plugin.CreateVolume and UpdateActor: Both today (STATUS_PENDING) and without status (storage_volume_id == ""), a retry of ResumeActor calls plugin.CreateVolume with the deterministic volume name actorVolumeID(actorUID, volName)
    ("substrate-<actorUID>-<volName>"), which CSI ControllerCreateVolume requires to be idempotent by name.
  • DeleteActor before storage_volume_id is persisted: Because CreateActor still pre-populates the ExternalVolume entry (with volume_name, volume_type, and empty storage_volume_id), deleteActorVolumes (volumes.go:148-154) continues to fall back to
    actorVolumeID(actorUID, vol.GetVolumeName()) when storage_volume_id == "".

Proposal

  1. Remove enum Status and Status status = 4 from ExternalVolume in pkg/proto/ateapipb/ateapi.proto.
  2. In cmd/ateapi/internal/controlapi/volumes.go and workflow_resume.go, use vol.GetStorageVolumeId() == "" to determine whether a volume still needs to be provisioned.
  3. In cmd/ateapi/internal/controlapi/workflow_delete.go, stop setting vol.Status = ExternalVolume_STATUS_DELETING when transitioning the Actor to ACTOR_STATE_DELETING.
  4. Regenerate protobufs and validation code (hack/update/codegen.sh) and update tests and docs (cmd/ateapi, internal/e2e, docs/api-guide.md).

Michelle Au (@msau42) thoughts?

Activity

  1. changed the title [-]api: remove ExternalVolume.Status enum and status field[/-] [+]api: remove `ExternalVolume.Status` enum and `status` field[/+] on Oct 9, 2026
  2. msau42 commented on Oct 9, 2026

    @msau42
    Collaborator

    That makes sense to me. My biggest concern is to make sure we can keep track of create operations that we started but have not completed, so we can make sure they are properly cleaned up if the Actor gets deleted while the volume creation is in progress.

    With the proposed change we could still keep track of that with volume_name.

  3. ericcurtin commented on Oct 10, 2026

    @ericcurtin
    Contributor

    I'll send a PR for this.

  4. added a commit that references this issue on Oct 14, 2026
    2c9a05f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/apiUser-facing API changeskind/cleanupSmall fixes that are not bugs, for example a typo in a code comment

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions