Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 41 additions & 9 deletions api/ateapi/v1/ateapi.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions api/ateapi/v1/ateapi.proto
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,13 @@ message ActorStatus {
// +k8s:minimum=0
// +k8s:update=NoUnset
int32 last_assigned_generation = 7;

// This actor was created by the server to build a template's golden snapshot.
// Actors created before this field was introduced may leave it unset.
//
// +k8s:optional
// +k8s:update=NoUnset
bool golden_snapshot_actor = 8;
}

// ActorCrash describes the failure that moved an Actor to CRASHED.
Expand Down Expand Up @@ -2258,6 +2265,17 @@ message ListActorsRequest {
//
// +k8s:optional
ListOptions options = 2;

// Exclude the temporary actors used to build golden snapshots. Defaults to
// false, which includes them for debugging. Only actors with
// `status.golden_snapshot_actor` set are excluded; older unmarked actors
// remain visible.
//
// Filtering may leave a page empty with a nonempty `next_page_token`.
// Keep this value unchanged while following pagination tokens.
//
// +k8s:optional
bool exclude_golden_actors = 3;
}

message ListActorsResponse {
Expand Down
61 changes: 61 additions & 0 deletions cmd/ateapi/internal/apivalidation/zz_generated.validation.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 22 additions & 3 deletions cmd/ateapi/internal/controlapi/actor.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,15 @@ import (
"k8s.io/apimachinery/pkg/util/validation/field"
)

func (s *RPCService) CreateActor(ctx context.Context, req *ateapi.CreateActorRequest) (created *ateapi.Actor, err error) {
func (s *RPCService) CreateActor(ctx context.Context, req *ateapi.CreateActorRequest) (*ateapi.Actor, error) {
return s.createActor(ctx, req, false)
}

func (s *RPCService) createGoldenActor(ctx context.Context, req *ateapi.CreateActorRequest) (*ateapi.Actor, error) {
return s.createActor(ctx, req, true)
}

func (s *RPCService) createActor(ctx context.Context, req *ateapi.CreateActorRequest, golden bool) (created *ateapi.Actor, err error) {
// First scrub any fields that users are not allowed to set, then fill the
// defaults so validation sees the final resource state.
inActor := req.Actor
Expand All @@ -64,6 +72,10 @@ func (s *RPCService) CreateActor(ctx context.Context, req *ateapi.CreateActorReq

setSpanActorRefAttributes(ctx, resources.ActorRefFromActor(inActor))

// The public RPC always scrubs status; only the template reconciler sets this.
if golden {
inActor.Status = &ateapi.ActorStatus{GoldenSnapshotActor: true}
}
// Handle the creation, including validation of the final stored object.
stored, err := s.impl.CreateActor(ctx, inActor)
setSpanActorAttributes(ctx, stored)
Expand Down Expand Up @@ -124,8 +136,9 @@ func (s *ServiceImpl) CreateActor(ctx context.Context, inActor *ateapi.Actor) (*
// Verify that the result is properly valid before storing it.
outActor := proto.CloneOf(inActor)
outActor.Status = &ateapi.ActorStatus{
State: ateapi.ActorState_ACTOR_STATE_SUSPENDED,
ExternalVolumes: externalVolumesStatus(initVols),
State: ateapi.ActorState_ACTOR_STATE_SUSPENDED,
GoldenSnapshotActor: inActor.GetStatus().GetGoldenSnapshotActor(),
ExternalVolumes: externalVolumesStatus(initVols),
}
if sourceTag != nil {
// The Actor starts out borrowing the tag's snapshot rather than
Expand Down Expand Up @@ -228,6 +241,12 @@ func (s *RPCService) ListActors(ctx context.Context, req *ateapi.ListActorsReque
if err != nil {
return nil, mapListError(fmt.Errorf("while listing actors in db: %w", err))
}
if req.GetExcludeGoldenActors() {
// Preserve the cursor even if filtering leaves this page empty.
page.Items = slices.DeleteFunc(page.Items, func(actor *ateapi.Actor) bool {
return actor.GetStatus().GetGoldenSnapshotActor()
})
}
return &ateapi.ListActorsResponse{
Actors: page.Items,
NextPageToken: page.NextPageToken,
Expand Down
Loading