From 0336f8b20b4b3cf02f89be1159b08340a067167e Mon Sep 17 00:00:00 2001 From: sjmiller609 <7516283+sjmiller609@users.noreply.github.com> Date: Thu, 20 Aug 2026 13:42:31 +0000 Subject: [PATCH 1/2] Add instance expiration reaper --- cmd/api/api/instances.go | 72 ++- cmd/api/api/instances_test.go | 268 +++++++++++ cmd/api/main.go | 8 + lib/instances/create.go | 44 +- lib/instances/errors.go | 6 + lib/instances/expiration.go | 13 + lib/instances/fork.go | 11 + lib/instances/fork_test.go | 12 +- lib/instances/manager.go | 22 +- lib/instances/metrics.go | 10 + lib/instances/snapshot.go | 6 +- lib/instances/snapshot_test.go | 11 + lib/instances/ttl_reaper.go | 119 +++++ lib/instances/ttl_reaper_test.go | 240 ++++++++++ lib/instances/types.go | 5 + lib/instances/update.go | 41 +- lib/instances/update_test.go | 133 +++++- lib/oapi/oapi.go | 769 ++++++++++++++++--------------- openapi.yaml | 33 +- 19 files changed, 1427 insertions(+), 396 deletions(-) create mode 100644 lib/instances/expiration.go create mode 100644 lib/instances/ttl_reaper.go create mode 100644 lib/instances/ttl_reaper_test.go diff --git a/cmd/api/api/instances.go b/cmd/api/api/instances.go index adcaf05fa..da534d388 100644 --- a/cmd/api/api/instances.go +++ b/cmd/api/api/instances.go @@ -134,6 +134,24 @@ func (s *ApiService) CreateInstance(ctx context.Context, request oapi.CreateInst resourceTags = toMapTags(request.Body.Tags) } + if request.Body.Ttl != nil && request.Body.ExpiresAt != nil { + return oapi.CreateInstance400JSONResponse{ + Code: "invalid_request", + Message: "ttl and expires_at are mutually exclusive", + }, nil + } + var ttl time.Duration + if request.Body.Ttl != nil { + parsedTTL, err := parseTTL(*request.Body.Ttl) + if err != nil { + return oapi.CreateInstance400JSONResponse{ + Code: "invalid_ttl", + Message: err.Error(), + }, nil + } + ttl = parsedTTL + } + // Parse network enabled (default: true) networkEnabled := true if request.Body.Network != nil && request.Body.Network.Enabled != nil { @@ -314,6 +332,8 @@ func (s *ApiService) CreateInstance(ctx context.Context, request oapi.CreateInst NetworkBandwidthUpload: networkBandwidthUpload, Env: env, Tags: resourceTags, + TTL: ttl, + ExpiresAt: request.Body.ExpiresAt, NetworkEnabled: networkEnabled, NetworkEgress: networkEgress, Credentials: credentials, @@ -363,6 +383,11 @@ func (s *ApiService) CreateInstance(ctx context.Context, request oapi.CreateInst Code: "insufficient_resources", Message: err.Error(), }, nil + case errors.Is(err, instances.ErrInvalidExpiresAt): + return oapi.CreateInstance400JSONResponse{ + Code: "invalid_expires_at", + Message: err.Error(), + }, nil case errors.Is(err, instances.ErrInvalidRequest): return oapi.CreateInstance400JSONResponse{ Code: "invalid_request", @@ -986,9 +1011,8 @@ func (s *ApiService) StatInstancePath(ctx context.Context, request oapi.StatInst return response, nil } -// UpdateInstance updates mutable properties of a running instance. -// Currently supports updating env vars referenced by credential policies for key rotation. -// Note: Resolution is handled by ResolveResource middleware +// UpdateInstance updates mutable instance properties. +// Note: Resolution is handled by ResolveResource middleware. func (s *ApiService) UpdateInstance(ctx context.Context, request oapi.UpdateInstanceRequestObject) (oapi.UpdateInstanceResponseObject, error) { inst := mw.GetResolvedInstance[instances.Instance](ctx) if inst == nil { @@ -1031,6 +1055,23 @@ func (s *ApiService) UpdateInstance(ctx context.Context, request oapi.UpdateInst Message: err.Error(), }, nil } + if request.Body.Ttl != nil && request.Body.ExpiresAt != nil { + return oapi.UpdateInstance400JSONResponse{ + Code: "invalid_request", + Message: "ttl and expires_at are mutually exclusive", + }, nil + } + var ttl *time.Duration + if request.Body.Ttl != nil { + parsedTTL, err := parseTTL(*request.Body.Ttl) + if err != nil { + return oapi.UpdateInstance400JSONResponse{ + Code: "invalid_ttl", + Message: err.Error(), + }, nil + } + ttl = &parsedTTL + } result, err := s.InstanceManager.UpdateInstance(ctx, inst.Id, instances.UpdateInstanceRequest{ Env: env, @@ -1038,6 +1079,8 @@ func (s *ApiService) UpdateInstance(ctx context.Context, request oapi.UpdateInst HealthCheck: healthCheck, RestartPolicy: restartPolicy, RestartPolicySet: request.Body.RestartPolicy != nil, + TTL: ttl, + ExpiresAt: request.Body.ExpiresAt, }) if err != nil { switch { @@ -1051,6 +1094,16 @@ func (s *ApiService) UpdateInstance(ctx context.Context, request oapi.UpdateInst Code: "invalid_state", Message: err.Error(), }, nil + case errors.Is(err, instances.ErrInstanceExpired): + return oapi.UpdateInstance409JSONResponse{ + Code: "instance_expired", + Message: err.Error(), + }, nil + case errors.Is(err, instances.ErrInvalidExpiresAt): + return oapi.UpdateInstance400JSONResponse{ + Code: "invalid_expires_at", + Message: err.Error(), + }, nil case errors.Is(err, instances.ErrInvalidRequest): return oapi.UpdateInstance400JSONResponse{ Code: "invalid_request", @@ -1142,6 +1195,7 @@ func instanceToOAPI(inst instances.Instance) oapi.Instance { DiskIoBps: diskIoBpsStr, Network: nil, CreatedAt: inst.CreatedAt, + ExpiresAt: inst.ExpiresAt, StartedAt: inst.StartedAt, StoppedAt: inst.StoppedAt, ExitCode: inst.ExitCode, @@ -1155,7 +1209,6 @@ func instanceToOAPI(inst instances.Instance) oapi.Instance { if inst.Platform != "" { oapiInst.Platform = lo.ToPtr(inst.Platform) } - if inst.ExitMessage != "" { oapiInst.ExitMessage = lo.ToPtr(inst.ExitMessage) } @@ -1308,6 +1361,17 @@ func toOAPISnapshotPolicy(policy instances.SnapshotPolicy) oapi.SnapshotPolicy { return out } +func parseTTL(value string) (time.Duration, error) { + ttl, err := time.ParseDuration(value) + if err != nil { + return 0, fmt.Errorf("ttl must be a valid duration: %w", err) + } + if ttl < 0 { + return 0, fmt.Errorf("ttl cannot be negative") + } + return ttl, nil +} + func parseOptionalDuration(value string, field string) (*time.Duration, error) { duration, err := time.ParseDuration(value) if err != nil { diff --git a/cmd/api/api/instances_test.go b/cmd/api/api/instances_test.go index d23e7c21e..5aab835b6 100644 --- a/cmd/api/api/instances_test.go +++ b/cmd/api/api/instances_test.go @@ -2,6 +2,7 @@ package api import ( "context" + "encoding/json" "fmt" "os" "testing" @@ -284,6 +285,11 @@ func (m *captureUpdateManager) UpdateInstance(ctx context.Context, id string, re } now := time.Now() + expiresAt := req.ExpiresAt + if req.TTL != nil && *req.TTL > 0 { + resolved := now.Add(*req.TTL) + expiresAt = &resolved + } return &instances.Instance{ StoredMetadata: instances.StoredMetadata{ Id: id, @@ -294,6 +300,7 @@ func (m *captureUpdateManager) UpdateInstance(ctx context.Context, id string, re HealthCheck: req.HealthCheck, RestartPolicy: req.RestartPolicy, CreatedAt: now, + ExpiresAt: expiresAt, HypervisorType: hypervisor.TypeCloudHypervisor, }, State: instances.StateRunning, @@ -307,6 +314,11 @@ func (m *captureCreateManager) CreateInstance(ctx context.Context, req instances } now := time.Now() + expiresAt := req.ExpiresAt + if req.TTL > 0 { + resolved := now.Add(req.TTL) + expiresAt = &resolved + } return &instances.Instance{ StoredMetadata: instances.StoredMetadata{ Id: "inst-hotplug-default", @@ -320,12 +332,142 @@ func (m *captureCreateManager) CreateInstance(ctx context.Context, req instances HealthCheck: req.HealthCheck, RestartPolicy: req.RestartPolicy, CreatedAt: now, + ExpiresAt: expiresAt, HypervisorType: hypervisor.TypeCloudHypervisor, }, State: instances.StateRunning, }, nil } +func TestCreateInstance_TTL(t *testing.T) { + t.Parallel() + + svc := newTestService(t) + mockMgr := newCaptureCreateManager(svc.InstanceManager) + svc.InstanceManager = mockMgr + ttl := "90m" + + resp, err := svc.CreateInstance(ctx(), oapi.CreateInstanceRequestObject{Body: &oapi.CreateInstanceRequest{ + Name: "test-ttl", + Image: "docker.io/library/alpine:latest", + Ttl: &ttl, + }}) + require.NoError(t, err) + created, ok := resp.(oapi.CreateInstance201JSONResponse) + require.True(t, ok) + require.NotNil(t, mockMgr.lastReq) + assert.Equal(t, 90*time.Minute, mockMgr.lastReq.TTL) + require.NotNil(t, created.ExpiresAt) + assert.Equal(t, created.CreatedAt.Add(90*time.Minute), *created.ExpiresAt) +} + +func TestCreateInstance_ZeroTTLDisablesExpiration(t *testing.T) { + t.Parallel() + + svc := newTestService(t) + mockMgr := newCaptureCreateManager(svc.InstanceManager) + svc.InstanceManager = mockMgr + ttl := "0s" + + resp, err := svc.CreateInstance(ctx(), oapi.CreateInstanceRequestObject{Body: &oapi.CreateInstanceRequest{ + Name: "test-no-expiration", + Image: "docker.io/library/alpine:latest", + Ttl: &ttl, + }}) + require.NoError(t, err) + created, ok := resp.(oapi.CreateInstance201JSONResponse) + require.True(t, ok) + assert.Zero(t, mockMgr.lastReq.TTL) + assert.Nil(t, created.ExpiresAt) +} + +func TestCreateInstance_ExpiresAt(t *testing.T) { + t.Parallel() + + svc := newTestService(t) + mockMgr := newCaptureCreateManager(svc.InstanceManager) + svc.InstanceManager = mockMgr + expiresAt := time.Now().Add(24 * time.Hour).UTC().Truncate(time.Second) + + resp, err := svc.CreateInstance(ctx(), oapi.CreateInstanceRequestObject{Body: &oapi.CreateInstanceRequest{ + Name: "test-expires-at", + Image: "docker.io/library/alpine:latest", + ExpiresAt: &expiresAt, + }}) + require.NoError(t, err) + created, ok := resp.(oapi.CreateInstance201JSONResponse) + require.True(t, ok) + require.NotNil(t, mockMgr.lastReq.ExpiresAt) + assert.Equal(t, expiresAt, *mockMgr.lastReq.ExpiresAt) + require.NotNil(t, created.ExpiresAt) + assert.Equal(t, expiresAt, *created.ExpiresAt) +} + +func TestCreateInstance_MapsInvalidExpiresAt(t *testing.T) { + t.Parallel() + + svc := newTestService(t) + mockMgr := newCaptureCreateManager(svc.InstanceManager) + mockMgr.err = fmt.Errorf("%w: must be in the future", instances.ErrInvalidExpiresAt) + svc.InstanceManager = mockMgr + expiresAt := time.Now().Add(-time.Hour) + + resp, err := svc.CreateInstance(ctx(), oapi.CreateInstanceRequestObject{Body: &oapi.CreateInstanceRequest{ + Name: "test-expired-deadline", + Image: "docker.io/library/alpine:latest", + ExpiresAt: &expiresAt, + }}) + require.NoError(t, err) + badRequest, ok := resp.(oapi.CreateInstance400JSONResponse) + require.True(t, ok) + assert.Equal(t, "invalid_expires_at", badRequest.Code) +} + +func TestInstanceResponseIncludesNullExpiresAt(t *testing.T) { + t.Parallel() + + encoded, err := json.Marshal(instanceToOAPI(instances.Instance{})) + require.NoError(t, err) + assert.Contains(t, string(encoded), `"expires_at":null`) +} + +func TestCreateInstance_RejectsConflictingExpiration(t *testing.T) { + t.Parallel() + + svc := newTestService(t) + ttl := "1h" + expiresAt := time.Now().Add(2 * time.Hour) + resp, err := svc.CreateInstance(ctx(), oapi.CreateInstanceRequestObject{Body: &oapi.CreateInstanceRequest{ + Name: "test-conflicting-expiration", + Image: "docker.io/library/alpine:latest", + Ttl: &ttl, + ExpiresAt: &expiresAt, + }}) + require.NoError(t, err) + badRequest, ok := resp.(oapi.CreateInstance400JSONResponse) + require.True(t, ok) + assert.Equal(t, "invalid_request", badRequest.Code) +} + +func TestCreateInstance_InvalidTTL(t *testing.T) { + t.Parallel() + + for _, ttl := range []string{"not-a-duration", "-1h"} { + t.Run(ttl, func(t *testing.T) { + svc := newTestService(t) + resp, err := svc.CreateInstance(ctx(), oapi.CreateInstanceRequestObject{Body: &oapi.CreateInstanceRequest{ + Name: "test-invalid-ttl", + Image: "docker.io/library/alpine:latest", + Ttl: &ttl, + }}) + require.NoError(t, err) + badRequest, ok := resp.(oapi.CreateInstance400JSONResponse) + require.True(t, ok) + assert.Equal(t, "invalid_ttl", badRequest.Code) + }) + } +} + func TestCreateInstance_MapsQEMUMicroVMHypervisor(t *testing.T) { t.Parallel() @@ -1067,6 +1209,92 @@ func TestUpdateInstance_MapsEnvPatch(t *testing.T) { assert.Equal(t, "rotated-key-456", mockMgr.lastReq.Env["OUTBOUND_OPENAI_KEY"]) } +func TestUpdateInstance_MapsTTL(t *testing.T) { + t.Parallel() + + svc := newTestService(t) + mockMgr := newCaptureUpdateManager(svc.InstanceManager) + svc.InstanceManager = mockMgr + resolved := &instances.Instance{StoredMetadata: instances.StoredMetadata{Id: "inst-update-ttl"}} + ttl := "6h" + + resp, err := svc.UpdateInstance(mw.WithResolvedInstance(ctx(), resolved.Id, resolved), oapi.UpdateInstanceRequestObject{ + Id: resolved.Id, + Body: &oapi.UpdateInstanceRequest{Ttl: &ttl}, + }) + require.NoError(t, err) + updated, ok := resp.(oapi.UpdateInstance200JSONResponse) + require.True(t, ok) + require.NotNil(t, mockMgr.lastReq.TTL) + assert.Equal(t, 6*time.Hour, *mockMgr.lastReq.TTL) + require.NotNil(t, updated.ExpiresAt) + assert.WithinDuration(t, time.Now().Add(6*time.Hour), *updated.ExpiresAt, time.Second) +} + +func TestUpdateInstance_ZeroTTLDisablesExpiration(t *testing.T) { + t.Parallel() + + svc := newTestService(t) + mockMgr := newCaptureUpdateManager(svc.InstanceManager) + svc.InstanceManager = mockMgr + resolved := &instances.Instance{StoredMetadata: instances.StoredMetadata{Id: "inst-disable-expiration"}} + ttl := "0s" + + resp, err := svc.UpdateInstance(mw.WithResolvedInstance(ctx(), resolved.Id, resolved), oapi.UpdateInstanceRequestObject{ + Id: resolved.Id, + Body: &oapi.UpdateInstanceRequest{Ttl: &ttl}, + }) + require.NoError(t, err) + updated, ok := resp.(oapi.UpdateInstance200JSONResponse) + require.True(t, ok) + require.NotNil(t, mockMgr.lastReq.TTL) + assert.Zero(t, *mockMgr.lastReq.TTL) + assert.Nil(t, updated.ExpiresAt) +} + +func TestUpdateInstance_MapsExpiresAt(t *testing.T) { + t.Parallel() + + svc := newTestService(t) + mockMgr := newCaptureUpdateManager(svc.InstanceManager) + svc.InstanceManager = mockMgr + resolved := &instances.Instance{StoredMetadata: instances.StoredMetadata{Id: "inst-update-expires-at"}} + expiresAt := time.Now().Add(24 * time.Hour).UTC().Truncate(time.Second) + + resp, err := svc.UpdateInstance(mw.WithResolvedInstance(ctx(), resolved.Id, resolved), oapi.UpdateInstanceRequestObject{ + Id: resolved.Id, + Body: &oapi.UpdateInstanceRequest{ExpiresAt: &expiresAt}, + }) + require.NoError(t, err) + updated, ok := resp.(oapi.UpdateInstance200JSONResponse) + require.True(t, ok) + require.NotNil(t, mockMgr.lastReq.ExpiresAt) + assert.Equal(t, expiresAt, *mockMgr.lastReq.ExpiresAt) + require.NotNil(t, updated.ExpiresAt) + assert.Equal(t, expiresAt, *updated.ExpiresAt) +} + +func TestUpdateInstance_RejectsConflictingExpiration(t *testing.T) { + t.Parallel() + + svc := newTestService(t) + resolved := &instances.Instance{StoredMetadata: instances.StoredMetadata{Id: "inst-conflicting-expiration"}} + ttl := "1h" + expiresAt := time.Now().Add(2 * time.Hour) + + resp, err := svc.UpdateInstance(mw.WithResolvedInstance(ctx(), resolved.Id, resolved), oapi.UpdateInstanceRequestObject{ + Id: resolved.Id, + Body: &oapi.UpdateInstanceRequest{ + Ttl: &ttl, + ExpiresAt: &expiresAt, + }, + }) + require.NoError(t, err) + badRequest, ok := resp.(oapi.UpdateInstance400JSONResponse) + require.True(t, ok) + assert.Equal(t, "invalid_request", badRequest.Code) +} + func TestUpdateInstance_MapsAutoStandbyPatch(t *testing.T) { t.Parallel() svc := newTestService(t) @@ -1365,6 +1593,46 @@ func TestUpdateInstance_RequiresBody(t *testing.T) { assert.Contains(t, badReq.Message, "request body is required") } +func TestUpdateInstance_MapsInvalidExpiresAt(t *testing.T) { + t.Parallel() + + svc := newTestService(t) + mockMgr := newCaptureUpdateManager(svc.InstanceManager) + mockMgr.err = fmt.Errorf("%w: must be in the future", instances.ErrInvalidExpiresAt) + svc.InstanceManager = mockMgr + resolved := &instances.Instance{StoredMetadata: instances.StoredMetadata{Id: "inst-invalid-expires-at"}} + expiresAt := time.Now().Add(-time.Hour) + + resp, err := svc.UpdateInstance(mw.WithResolvedInstance(ctx(), resolved.Id, resolved), oapi.UpdateInstanceRequestObject{ + Id: resolved.Id, + Body: &oapi.UpdateInstanceRequest{ExpiresAt: &expiresAt}, + }) + require.NoError(t, err) + badRequest, ok := resp.(oapi.UpdateInstance400JSONResponse) + require.True(t, ok) + assert.Equal(t, "invalid_expires_at", badRequest.Code) +} + +func TestUpdateInstance_MapsExpiredError(t *testing.T) { + t.Parallel() + + svc := newTestService(t) + mockMgr := newCaptureUpdateManager(svc.InstanceManager) + mockMgr.err = fmt.Errorf("%w: expiration deadline has passed", instances.ErrInstanceExpired) + svc.InstanceManager = mockMgr + resolved := &instances.Instance{StoredMetadata: instances.StoredMetadata{Id: "inst-expired"}} + ttl := "1h" + + resp, err := svc.UpdateInstance(mw.WithResolvedInstance(ctx(), resolved.Id, resolved), oapi.UpdateInstanceRequestObject{ + Id: resolved.Id, + Body: &oapi.UpdateInstanceRequest{Ttl: &ttl}, + }) + require.NoError(t, err) + conflict, ok := resp.(oapi.UpdateInstance409JSONResponse) + require.True(t, ok) + assert.Equal(t, "instance_expired", conflict.Code) +} + func TestUpdateInstance_MapsInvalidRequestError(t *testing.T) { t.Parallel() svc := newTestService(t) diff --git a/cmd/api/main.go b/cmd/api/main.go index 04eb38d29..f1bbfcf3d 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -663,6 +663,14 @@ func run() error { return restartController.StartRestartPolicyController(gctx) }) } + if ttlReaper, ok := app.InstanceManager.(interface { + StartTTLReaper(context.Context) error + }); ok { + grp.Go(func() error { + logger.Info("starting instance ttl reaper") + return ttlReaper.StartTTLReaper(gctx) + }) + } logger.Info("hypeman initialization complete", "duration", time.Since(startupStarted)) diff --git a/lib/instances/create.go b/lib/instances/create.go index 4e2245b73..59155950a 100644 --- a/lib/instances/create.go +++ b/lib/instances/create.go @@ -96,6 +96,9 @@ func (m *manager) createInstance( log.ErrorContext(ctx, "invalid create request", "error", err) return nil, err } + if err := validateExpiresAt(req.ExpiresAt, m.nowUTC()); err != nil { + return nil, err + } if req.GPU != nil && req.GPU.Profile != "" && !devices.Capabilities().SupportsVGPU { return nil, fmt.Errorf("%w: %w", ErrInvalidRequest, devices.ErrVGPUNotSupportedOnMacOS) } @@ -172,6 +175,17 @@ func (m *manager) createInstance( ctx = enrichInstancesTrace(ctx, attribute.String("instance_id", id)) log.DebugContext(ctx, "generated instance ID", "instance_id", id) + // Keep the reaper from deleting metadata while creation is still in flight. + instanceLock, ownsInstanceLock := m.loadOrStoreInstanceLock(id) + removeInstanceLockOnFailure := ownsInstanceLock + instanceLock.Lock() + defer func() { + if retErr != nil && removeInstanceLockOnFailure { + m.instanceLocks.CompareAndDelete(id, instanceLock) + } + instanceLock.Unlock() + }() + // 4. Generate vsock configuration vsockCID := generateVsockCID(id) vsockSocket := m.paths.InstanceSocket(id, hypervisor.VsockSocketNameForType(hvType)) @@ -179,6 +193,7 @@ func (m *manager) createInstance( // 5. Check instance doesn't already exist if _, err := m.loadMetadata(id); err == nil { + removeInstanceLockOnFailure = false return nil, ErrAlreadyExists } @@ -329,6 +344,11 @@ func (m *manager) createInstance( } // 11. Create instance metadata + createdAt := m.nowUTC() + expiresAt, err := resolveCreateExpiration(req, createdAt) + if err != nil { + return nil, err + } stored := &StoredMetadata{ Id: id, Name: req.Name, @@ -347,7 +367,8 @@ func (m *manager) createInstance( NetworkEnabled: req.NetworkEnabled, NetworkEgress: cloneNetworkEgressPolicy(req.NetworkEgress), Credentials: cloneCredentialPolicies(req.Credentials), - CreatedAt: time.Now(), + CreatedAt: createdAt, + ExpiresAt: expiresAt, StartedAt: nil, StoppedAt: nil, ProgramStartedAt: nil, @@ -561,6 +582,21 @@ func (m *manager) createInstance( return &finalInst, nil } +func resolveCreateExpiration(req CreateInstanceRequest, now time.Time) (*time.Time, error) { + if req.ExpiresAt != nil { + if err := validateExpiresAt(req.ExpiresAt, now); err != nil { + return nil, err + } + expiresAt := req.ExpiresAt.UTC() + return &expiresAt, nil + } + if req.TTL == 0 { + return nil, nil + } + expiresAt := now.Add(req.TTL) + return &expiresAt, nil +} + // validateCreateRequest validates the create instance request. // The request is mutated in-place to persist normalized egress/credential policy fields. func validateCreateRequest(req *CreateInstanceRequest) error { @@ -585,6 +621,12 @@ func validateCreateRequest(req *CreateInstanceRequest) error { if req.Vcpus < 0 { return fmt.Errorf("vcpus cannot be negative") } + if req.TTL < 0 { + return fmt.Errorf("%w: ttl cannot be negative", ErrInvalidRequest) + } + if req.TTL > 0 && req.ExpiresAt != nil { + return fmt.Errorf("%w: ttl and expires_at are mutually exclusive", ErrInvalidRequest) + } if req.NetworkEgress != nil && req.NetworkEgress.Enabled { if !req.NetworkEnabled { return fmt.Errorf("%w: network.egress requires network.enabled=true", ErrInvalidRequest) diff --git a/lib/instances/errors.go b/lib/instances/errors.go index c61f10392..8d7042eb5 100644 --- a/lib/instances/errors.go +++ b/lib/instances/errors.go @@ -12,6 +12,12 @@ var ( // ErrInvalidRequest is returned when request validation fails ErrInvalidRequest = errors.New("invalid request") + // ErrInstanceExpired is returned when an expiration update loses the expiry race. + ErrInstanceExpired = errors.New("instance expired") + + // ErrInvalidExpiresAt is returned when an absolute expiration is not in the future. + ErrInvalidExpiresAt = errors.New("invalid expires_at") + // ErrAlreadyExists is returned when creating an instance that already exists ErrAlreadyExists = errors.New("instance already exists") diff --git a/lib/instances/expiration.go b/lib/instances/expiration.go new file mode 100644 index 000000000..d14e63511 --- /dev/null +++ b/lib/instances/expiration.go @@ -0,0 +1,13 @@ +package instances + +import ( + "fmt" + "time" +) + +func validateExpiresAt(expiresAt *time.Time, now time.Time) error { + if expiresAt != nil && !expiresAt.After(now) { + return fmt.Errorf("%w: must be in the future", ErrInvalidExpiresAt) + } + return nil +} diff --git a/lib/instances/fork.go b/lib/instances/fork.go index ea6d3a4c5..d65d5131b 100644 --- a/lib/instances/fork.go +++ b/lib/instances/fork.go @@ -278,6 +278,7 @@ func (m *manager) forkInstanceFromStoppedOrStandby(ctx context.Context, id strin forkMeta.Id = forkID forkMeta.Name = req.Name forkMeta.CreatedAt = now + forkMeta.ExpiresAt = nil forkMeta.StartedAt = nil forkMeta.StoppedAt = nil forkMeta.HypervisorPID = nil @@ -613,6 +614,10 @@ func cloneStoredMetadata(src StoredMetadata) StoredMetadata { pid := *src.HypervisorPID dst.HypervisorPID = &pid } + if src.ExpiresAt != nil { + expiresAt := *src.ExpiresAt + dst.ExpiresAt = &expiresAt + } if src.StartedAt != nil { startedAt := *src.StartedAt dst.StartedAt = &startedAt @@ -643,3 +648,9 @@ func cloneStoredMetadataWithoutPendingStandbyCompression(src StoredMetadata) Sto dst.PendingStandbyCompression = nil return dst } + +func cloneStoredMetadataForSnapshot(src StoredMetadata) StoredMetadata { + dst := cloneStoredMetadataWithoutPendingStandbyCompression(src) + dst.ExpiresAt = nil + return dst +} diff --git a/lib/instances/fork_test.go b/lib/instances/fork_test.go index d51a687ef..32dc06ee6 100644 --- a/lib/instances/fork_test.go +++ b/lib/instances/fork_test.go @@ -577,6 +577,11 @@ func TestForkInstanceFromStandbyCancelsCompressionJobAndCopiesRawMemory(t *testi sourceID := "fork-standby-compressed-src" createStandbySnapshotSourceFixture(t, manager, sourceID, sourceID, manager.defaultHypervisor) + expiresAt := time.Now().Add(time.Hour) + sourceMeta, err := manager.loadMetadata(sourceID) + require.NoError(t, err) + sourceMeta.ExpiresAt = &expiresAt + require.NoError(t, manager.saveMetadata(sourceMeta)) rawPath := filepath.Join(manager.paths.InstanceSnapshotLatest(sourceID), "memory-ranges") require.NoError(t, os.WriteFile(rawPath, []byte("some guest memory"), 0o644)) @@ -584,7 +589,7 @@ func TestForkInstanceFromStandbyCancelsCompressionJobAndCopiesRawMemory(t *testi require.NoError(t, os.MkdirAll(filepath.Dir(snapshotConfigPath), 0o755)) require.NoError(t, os.WriteFile(snapshotConfigPath, []byte(`{}`), 0o644)) - _, _, err := compressSnapshotMemoryFile(ctx, rawPath, snapshotstore.SnapshotCompressionConfig{ + _, _, err = compressSnapshotMemoryFile(ctx, rawPath, snapshotstore.SnapshotCompressionConfig{ Enabled: true, Algorithm: snapshotstore.SnapshotCompressionAlgorithmZstd, Level: intPtr(1), @@ -619,6 +624,7 @@ func TestForkInstanceFromStandbyCancelsCompressionJobAndCopiesRawMemory(t *testi }, true) require.NoError(t, err) require.NotNil(t, forked) + assert.Nil(t, forked.ExpiresAt) assert.True(t, canceled.Load(), "standby compression job should be canceled before copying the source guest directory") @@ -671,6 +677,7 @@ func TestCloneStoredMetadataForFork_DeepCopiesReferenceFields(t *testing.T) { t.Parallel() startedAt := time.Now().Add(-2 * time.Minute) stoppedAt := time.Now().Add(-1 * time.Minute) + expiresAt := time.Now().Add(time.Hour) notBefore := time.Now().Add(5 * time.Minute) pid := 1234 exitCode := 17 @@ -687,6 +694,7 @@ func TestCloneStoredMetadataForFork_DeepCopiesReferenceFields(t *testing.T) { Devices: []string{"0000:01:00.0"}, Entrypoint: []string{"/bin/sh", "-c"}, Cmd: []string{"echo", "hello"}, + ExpiresAt: &expiresAt, StartedAt: &startedAt, StoppedAt: &stoppedAt, HypervisorPID: &pid, @@ -741,6 +749,7 @@ func TestCloneStoredMetadataForFork_DeepCopiesReferenceFields(t *testing.T) { now := time.Now() *cloned.PendingStandbyCompression.Policy.Level = 1 cloned.PendingStandbyCompression.NotBefore = now + *cloned.ExpiresAt = now *cloned.StartedAt = now *cloned.StoppedAt = now @@ -760,6 +769,7 @@ func TestCloneStoredMetadataForFork_DeepCopiesReferenceFields(t *testing.T) { require.NotNil(t, src.PendingStandbyCompression.Policy.Level) require.Equal(t, 3, *src.PendingStandbyCompression.Policy.Level) require.Equal(t, notBefore, src.PendingStandbyCompression.NotBefore) + require.Equal(t, expiresAt, *src.ExpiresAt) require.Equal(t, startedAt, *src.StartedAt) require.Equal(t, stoppedAt, *src.StoppedAt) } diff --git a/lib/instances/manager.go b/lib/instances/manager.go index 5d595d823..8855ba4f8 100644 --- a/lib/instances/manager.go +++ b/lib/instances/manager.go @@ -179,7 +179,9 @@ type manager struct { tracer trace.Tracer now func() time.Time writeFile func(string, []byte, os.FileMode) error + deleteInstanceFn func(context.Context, string) error deleteSnapshotFn func(context.Context, string) error + ttlReaperDeleteTimeout time.Duration egressProxy *egressproxy.Service egressProxyServiceOptions egressproxy.ServiceOptions egressProxyMu sync.Mutex @@ -376,8 +378,13 @@ func (m *manager) supportsConcurrentForkPrepare(hvType hypervisor.Type) bool { // getInstanceLock returns or creates a lock for a specific instance func (m *manager) getInstanceLock(id string) *sync.RWMutex { - lock, _ := m.instanceLocks.LoadOrStore(id, &sync.RWMutex{}) - return lock.(*sync.RWMutex) + lock, _ := m.loadOrStoreInstanceLock(id) + return lock +} + +func (m *manager) loadOrStoreInstanceLock(id string) (*sync.RWMutex, bool) { + lock, loaded := m.instanceLocks.LoadOrStore(id, &sync.RWMutex{}) + return lock.(*sync.RWMutex), !loaded } // maybePersistExitInfo persists exit info to metadata under the instance write lock. @@ -440,10 +447,17 @@ func (m *manager) DeleteInstance(ctx context.Context, id string) error { lock.Lock() defer lock.Unlock() - err := m.deleteInstance(ctx, id) + return m.deleteInstanceLocked(ctx, id) +} + +func (m *manager) deleteInstanceLocked(ctx context.Context, id string) error { + deleteInstance := m.deleteInstance + if m.deleteInstanceFn != nil { + deleteInstance = m.deleteInstanceFn + } + err := deleteInstance(ctx, id) if err == nil { m.notifyLifecycleDelete(ctx, id) - // Clean up the lock after successful deletion m.instanceLocks.Delete(id) } return err diff --git a/lib/instances/metrics.go b/lib/instances/metrics.go index 494cc2402..1ada5ac1e 100644 --- a/lib/instances/metrics.go +++ b/lib/instances/metrics.go @@ -93,6 +93,7 @@ type Metrics struct { snapshotCompressionPreemptionsTotal metric.Int64Counter lifecycleEventsDroppedTotal metric.Int64Counter forkMemFileShareFallbacksTotal metric.Int64Counter + ttlReaperDeletionsTotal metric.Int64Counter tracer trace.Tracer } @@ -261,6 +262,14 @@ func newInstanceMetrics(meter metric.Meter, tracer trace.Tracer, m *manager) (*M return nil, err } + ttlReaperDeletionsTotal, err := meter.Int64Counter( + "hypeman_instances_ttl_reaper_deletions_total", + metric.WithDescription("Total number of instance TTL reaper deletion attempts"), + ) + if err != nil { + return nil, err + } + // Register observable gauge for instance counts by state instancesTotal, err := meter.Int64ObservableGauge( "hypeman_instances_total", @@ -454,6 +463,7 @@ func newInstanceMetrics(meter metric.Meter, tracer trace.Tracer, m *manager) (*M snapshotCompressionPreemptionsTotal: snapshotCompressionPreemptionsTotal, lifecycleEventsDroppedTotal: lifecycleEventsDroppedTotal, forkMemFileShareFallbacksTotal: forkMemFileShareFallbacksTotal, + ttlReaperDeletionsTotal: ttlReaperDeletionsTotal, tracer: tracer, }, nil } diff --git a/lib/instances/snapshot.go b/lib/instances/snapshot.go index 669d087f0..eef7a6092 100644 --- a/lib/instances/snapshot.go +++ b/lib/instances/snapshot.go @@ -151,7 +151,7 @@ func (m *manager) createSnapshot(ctx context.Context, id string, req CreateSnaps SourceHypervisor: stored.HypervisorType, CreatedAt: time.Now(), }, - StoredMetadata: cloneStoredMetadataWithoutPendingStandbyCompression(meta.StoredMetadata), + StoredMetadata: cloneStoredMetadataForSnapshot(meta.StoredMetadata), } sizeBytes, err := snapshotstore.DirectoryFileSize(snapshotGuestDir) if err != nil { @@ -203,7 +203,7 @@ func (m *manager) createSnapshot(ctx context.Context, id string, req CreateSnaps SourceHypervisor: stored.HypervisorType, CreatedAt: time.Now(), }, - StoredMetadata: cloneStoredMetadataWithoutPendingStandbyCompression(meta.StoredMetadata), + StoredMetadata: cloneStoredMetadataForSnapshot(meta.StoredMetadata), } sizeBytes, err := snapshotstore.DirectoryFileSize(snapshotGuestDir) if err != nil { @@ -299,6 +299,7 @@ func (m *manager) restoreSnapshot(ctx context.Context, id string, snapshotID str restored := cloneStoredMetadataWithoutPendingStandbyCompression(rec.StoredMetadata) restored.Id = sourceMeta.Id restored.Name = sourceMeta.Name + restored.ExpiresAt = sourceMeta.ExpiresAt restored.DataDir = m.paths.InstanceDir(id) restored.HypervisorPID = nil restored.StartedAt = nil @@ -422,6 +423,7 @@ func (m *manager) forkSnapshot(ctx context.Context, snapshotID string, req ForkS forkMeta.Id = forkID forkMeta.Name = req.Name forkMeta.CreatedAt = now + forkMeta.ExpiresAt = nil forkMeta.StartedAt = nil forkMeta.StoppedAt = nil forkMeta.HypervisorPID = nil diff --git a/lib/instances/snapshot_test.go b/lib/instances/snapshot_test.go index 144fdc478..917f88d46 100644 --- a/lib/instances/snapshot_test.go +++ b/lib/instances/snapshot_test.go @@ -23,6 +23,11 @@ func TestStoppedSnapshotLifecycleAndForkAfterSourceDeletion(t *testing.T) { hvType := mgr.defaultHypervisor sourceID := "snapshot-stopped-src" createStoppedSnapshotSourceFixture(t, mgr, sourceID, "snapshot-stopped-src", hvType) + expiresAt := time.Now().Add(24 * time.Hour) + sourceMeta, err := mgr.loadMetadata(sourceID) + require.NoError(t, err) + sourceMeta.ExpiresAt = &expiresAt + require.NoError(t, mgr.saveMetadata(sourceMeta)) snap, err := mgr.CreateSnapshot(ctx, sourceID, CreateSnapshotRequest{ Kind: SnapshotKindStopped, @@ -30,6 +35,9 @@ func TestStoppedSnapshotLifecycleAndForkAfterSourceDeletion(t *testing.T) { }) require.NoError(t, err) require.Equal(t, SnapshotKindStopped, snap.Kind) + snapshotMeta, err := mgr.loadSnapshotRecord(snap.Id) + require.NoError(t, err) + assert.Nil(t, snapshotMeta.StoredMetadata.ExpiresAt) restored, err := mgr.RestoreSnapshot(ctx, sourceID, snap.Id, RestoreSnapshotRequest{ TargetState: StateStopped, @@ -38,6 +46,8 @@ func TestStoppedSnapshotLifecycleAndForkAfterSourceDeletion(t *testing.T) { require.NoError(t, err) require.Equal(t, StateStopped, restored.State) require.Equal(t, hvType, restored.HypervisorType) + require.NotNil(t, restored.ExpiresAt) + assert.True(t, expiresAt.Equal(*restored.ExpiresAt)) require.NoError(t, mgr.DeleteInstance(ctx, sourceID)) @@ -53,6 +63,7 @@ func TestStoppedSnapshotLifecycleAndForkAfterSourceDeletion(t *testing.T) { require.NoError(t, err) require.Equal(t, StateStopped, forked.State) require.Equal(t, hvType, forked.HypervisorType) + assert.Nil(t, forked.ExpiresAt) t.Cleanup(func() { _ = deleteTestInstanceNow(context.Background(), mgr, forked.Id) }) require.NoError(t, mgr.DeleteSnapshot(ctx, snap.Id)) diff --git a/lib/instances/ttl_reaper.go b/lib/instances/ttl_reaper.go new file mode 100644 index 000000000..16dccfdc0 --- /dev/null +++ b/lib/instances/ttl_reaper.go @@ -0,0 +1,119 @@ +package instances + +import ( + "context" + "errors" + "path/filepath" + "time" + + "github.com/kernel/hypeman/lib/logger" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/metric" +) + +const ( + instanceTTLReaperInterval = time.Minute + instanceTTLReaperDeleteTimeout = 30 * time.Second +) + +// StartTTLReaper deletes instances after their configured expiration time. +func (m *manager) StartTTLReaper(ctx context.Context) error { + m.reapExpiredInstances(ctx) + + ticker := time.NewTicker(instanceTTLReaperInterval) + defer ticker.Stop() + + for { + select { + case <-ctx.Done(): + return nil + case <-ticker.C: + m.reapExpiredInstances(ctx) + } + } +} + +func (m *manager) reapExpiredInstances(ctx context.Context) { + log := logger.FromContext(ctx) + metaFiles, err := m.listMetadataFiles() + if err != nil { + log.ErrorContext(ctx, "instance ttl reaper failed to list metadata", "error", err) + return + } + + now := m.nowUTC() + for _, metaFile := range metaFiles { + if ctx.Err() != nil { + return + } + + id := filepath.Base(filepath.Dir(metaFile)) + meta, err := m.loadMetadata(id) + if errors.Is(err, ErrNotFound) { + continue + } + if err != nil { + log.ErrorContext(ctx, "instance ttl reaper failed to load metadata", "instance_id", id, "error", err) + continue + } + if !instanceExpired(&meta.StoredMetadata, now) { + continue + } + + deleteCtx, cancel := context.WithTimeout(ctx, m.instanceTTLReaperDeleteTimeout()) + deleted, err := m.reapExpiredInstance(deleteCtx, id) + timedOut := errors.Is(deleteCtx.Err(), context.DeadlineExceeded) + cancel() + + switch { + case err == nil && deleted: + m.recordTTLReaperDeletion(ctx, "success") + case err == nil: + continue + case timedOut: + m.recordTTLReaperDeletion(ctx, "timeout") + log.ErrorContext(ctx, "instance ttl reaper timed out deleting instance", "instance_id", id, "error", err) + case errors.Is(err, ErrNotFound): + m.recordTTLReaperDeletion(ctx, "not_found") + default: + m.recordTTLReaperDeletion(ctx, "error") + log.ErrorContext(ctx, "instance ttl reaper failed to delete instance", "instance_id", id, "error", err) + } + } +} + +func (m *manager) reapExpiredInstance(ctx context.Context, id string) (bool, error) { + lock := m.getInstanceLock(id) + // Active lifecycle operations take precedence; retry on the next sweep. + if !lock.TryLock() { + return false, nil + } + defer lock.Unlock() + + meta, err := m.loadMetadata(id) + if err != nil { + return false, err + } + if !instanceExpired(&meta.StoredMetadata, m.nowUTC()) { + return false, nil + } + return true, m.deleteInstanceLocked(ctx, id) +} + +func (m *manager) instanceTTLReaperDeleteTimeout() time.Duration { + if m.ttlReaperDeleteTimeout > 0 { + return m.ttlReaperDeleteTimeout + } + return instanceTTLReaperDeleteTimeout +} + +func instanceExpired(meta *StoredMetadata, now time.Time) bool { + return meta != nil && meta.ExpiresAt != nil && !now.Before(*meta.ExpiresAt) +} + +func (m *manager) recordTTLReaperDeletion(ctx context.Context, status string) { + if m.metrics == nil { + return + } + m.metrics.ttlReaperDeletionsTotal.Add(ctx, 1, metric.WithAttributes(attribute.String("status", status))) +} diff --git a/lib/instances/ttl_reaper_test.go b/lib/instances/ttl_reaper_test.go new file mode 100644 index 000000000..02548bf78 --- /dev/null +++ b/lib/instances/ttl_reaper_test.go @@ -0,0 +1,240 @@ +package instances + +import ( + "context" + "os" + "testing" + "time" + + "github.com/kernel/hypeman/lib/paths" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestResolveCreateExpiration(t *testing.T) { + t.Parallel() + + now := time.Date(2026, 8, 20, 12, 0, 0, 0, time.UTC) + expiresAt, err := resolveCreateExpiration(CreateInstanceRequest{TTL: 6 * time.Hour}, now) + require.NoError(t, err) + require.NotNil(t, expiresAt) + assert.Equal(t, now.Add(6*time.Hour), *expiresAt) + + expiresAt, err = resolveCreateExpiration(CreateInstanceRequest{}, now) + require.NoError(t, err) + assert.Nil(t, expiresAt) + + past := now.Add(-time.Second) + _, err = resolveCreateExpiration(CreateInstanceRequest{ExpiresAt: &past}, now) + require.ErrorIs(t, err, ErrInvalidExpiresAt) +} + +func TestInstanceExpired(t *testing.T) { + t.Parallel() + + now := time.Date(2026, 8, 20, 12, 0, 0, 0, time.UTC) + before := now.Add(time.Hour) + at := now + after := now.Add(-time.Hour) + + for _, tc := range []struct { + name string + meta *StoredMetadata + want bool + }{ + {name: "before deadline", meta: &StoredMetadata{ExpiresAt: &before}}, + {name: "at deadline", meta: &StoredMetadata{ExpiresAt: &at}, want: true}, + {name: "after deadline", meta: &StoredMetadata{ExpiresAt: &after}, want: true}, + {name: "expiration disabled", meta: &StoredMetadata{}}, + {name: "missing metadata"}, + } { + t.Run(tc.name, func(t *testing.T) { + assert.Equal(t, tc.want, instanceExpired(tc.meta, now)) + }) + } +} + +func TestTTLReaperUsesPersistedExpirationAfterRestart(t *testing.T) { + t.Parallel() + + now := time.Date(2026, 8, 20, 12, 0, 0, 0, time.UTC) + p := paths.New(t.TempDir()) + writer := &manager{paths: p} + + save := func(id string, expiresAt *time.Time) { + t.Helper() + require.NoError(t, writer.ensureDirectories(id)) + require.NoError(t, writer.saveMetadata(&metadata{StoredMetadata: StoredMetadata{ + Id: id, + Name: id, + CreatedAt: now.Add(-time.Hour), + ExpiresAt: expiresAt, + DataDir: p.InstanceDir(id), + }})) + } + + expiredAt := now.Add(-time.Minute) + future := now.Add(time.Hour) + save("expired", &expiredAt) + save("not-expired", &future) + save("no-expiration", nil) + + restarted := &manager{ + paths: p, + now: func() time.Time { return now }, + lifecycleEvents: newLifecycleSubscribersWithBufferSize(defaultLifecycleEventBufferSize), + } + restarted.reapExpiredInstances(context.Background()) + + _, err := os.Stat(p.InstanceDir("expired")) + require.ErrorIs(t, err, os.ErrNotExist) + for _, id := range []string{"not-expired", "no-expiration"} { + _, err := os.Stat(p.InstanceDir(id)) + require.NoError(t, err) + } +} + +func TestReapExpiredInstanceRechecksExpirationUnderLock(t *testing.T) { + t.Parallel() + + now := time.Date(2026, 8, 20, 12, 0, 0, 0, time.UTC) + p := paths.New(t.TempDir()) + m := &manager{ + paths: p, + now: func() time.Time { return now }, + lifecycleEvents: newLifecycleSubscribersWithBufferSize(defaultLifecycleEventBufferSize), + } + id := "extended-before-reap" + require.NoError(t, m.ensureDirectories(id)) + expiredAt := now.Add(-time.Minute) + meta := &metadata{StoredMetadata: StoredMetadata{ + Id: id, + Name: id, + CreatedAt: now.Add(-time.Hour), + ExpiresAt: &expiredAt, + DataDir: p.InstanceDir(id), + }} + require.NoError(t, m.saveMetadata(meta)) + require.True(t, instanceExpired(&meta.StoredMetadata, now)) + + future := now.Add(time.Hour) + meta.ExpiresAt = &future + require.NoError(t, m.saveMetadata(meta)) + + deleted, err := m.reapExpiredInstance(context.Background(), id) + require.NoError(t, err) + assert.False(t, deleted) + _, err = os.Stat(p.InstanceDir(id)) + require.NoError(t, err) +} + +func TestStartTTLReaperSweepsBeforeFirstTick(t *testing.T) { + t.Parallel() + + now := time.Date(2026, 8, 20, 12, 0, 0, 0, time.UTC) + p := paths.New(t.TempDir()) + m := &manager{ + paths: p, + now: func() time.Time { return now }, + lifecycleEvents: newLifecycleSubscribersWithBufferSize(defaultLifecycleEventBufferSize), + } + id := "expired-at-startup" + expiredAt := now.Add(-time.Minute) + require.NoError(t, m.ensureDirectories(id)) + require.NoError(t, m.saveMetadata(&metadata{StoredMetadata: StoredMetadata{ + Id: id, + Name: id, + CreatedAt: now.Add(-time.Hour), + ExpiresAt: &expiredAt, + DataDir: p.InstanceDir(id), + }})) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + done := make(chan error, 1) + go func() { + done <- m.StartTTLReaper(ctx) + }() + + require.Eventually(t, func() bool { + _, err := os.Stat(p.InstanceDir(id)) + return os.IsNotExist(err) + }, time.Second, 10*time.Millisecond) + cancel() + select { + case err := <-done: + require.NoError(t, err) + case <-time.After(time.Second): + t.Fatal("ttl reaper did not stop after cancellation") + } +} + +func TestTTLReaperDeleteTimeoutDoesNotBlockSweep(t *testing.T) { + t.Parallel() + + now := time.Date(2026, 8, 20, 12, 0, 0, 0, time.UTC) + p := paths.New(t.TempDir()) + m := &manager{ + paths: p, + now: func() time.Time { return now }, + lifecycleEvents: newLifecycleSubscribersWithBufferSize(defaultLifecycleEventBufferSize), + ttlReaperDeleteTimeout: 10 * time.Millisecond, + } + expiredAt := now.Add(-time.Minute) + for _, id := range []string{"a-timeout", "b-deleted"} { + require.NoError(t, m.ensureDirectories(id)) + require.NoError(t, m.saveMetadata(&metadata{StoredMetadata: StoredMetadata{ + Id: id, + Name: id, + CreatedAt: now.Add(-time.Hour), + ExpiresAt: &expiredAt, + DataDir: p.InstanceDir(id), + }})) + } + + var calls []string + m.deleteInstanceFn = func(ctx context.Context, id string) error { + calls = append(calls, id) + if id == "a-timeout" { + <-ctx.Done() + return ctx.Err() + } + return m.deleteInstanceData(id) + } + + m.reapExpiredInstances(context.Background()) + + assert.Equal(t, []string{"a-timeout", "b-deleted"}, calls) + _, err := os.Stat(p.InstanceDir("a-timeout")) + require.NoError(t, err) + _, err = os.Stat(p.InstanceDir("b-deleted")) + require.ErrorIs(t, err, os.ErrNotExist) +} + +func TestReapExpiredInstanceSkipsBusyCreateLock(t *testing.T) { + t.Parallel() + + now := time.Date(2026, 8, 20, 12, 0, 0, 0, time.UTC) + p := paths.New(t.TempDir()) + m := &manager{paths: p, now: func() time.Time { return now }} + id := "creating-instance" + expiredAt := now.Add(-time.Minute) + require.NoError(t, m.ensureDirectories(id)) + require.NoError(t, m.saveMetadata(&metadata{StoredMetadata: StoredMetadata{ + Id: id, + Name: id, + CreatedAt: now.Add(-time.Hour), + ExpiresAt: &expiredAt, + DataDir: p.InstanceDir(id), + }})) + + lock := m.getInstanceLock(id) + lock.Lock() + deleted, err := m.reapExpiredInstance(context.Background(), id) + lock.Unlock() + + require.NoError(t, err) + assert.False(t, deleted) + _, err = os.Stat(p.InstanceDir(id)) + require.NoError(t, err) +} diff --git a/lib/instances/types.go b/lib/instances/types.go index df3ab7ff8..973fe93cf 100644 --- a/lib/instances/types.go +++ b/lib/instances/types.go @@ -115,6 +115,7 @@ type StoredMetadata struct { // Timestamps (stored for historical tracking) CreatedAt time.Time + ExpiresAt *time.Time // Absolute expiration time; nil disables expiration StartedAt *time.Time // Boot epoch start time (set on create/start; preserved across standby restore) StoppedAt *time.Time // Last time VM was stopped @@ -274,6 +275,8 @@ type CreateInstanceRequest struct { AutoStandby *autostandby.Policy // Optional automatic standby policy HealthCheck *healthcheck.Policy // Optional workload health check policy RestartPolicy *restartpolicy.Policy // Optional whole-instance restart policy + TTL time.Duration // Optional lifetime from creation; zero disables expiration + ExpiresAt *time.Time // Optional absolute expiration time; mutually exclusive with TTL AllowSystemVolumeMounts bool // Internal only: permits attaching reserved system volumes. Never populated from API requests. SystemVolumeMountPaths []string // Internal only: exact system paths reserved volumes may mount at. } @@ -291,6 +294,8 @@ type UpdateInstanceRequest struct { HealthCheck *healthcheck.Policy // Replaces the persisted health check policy when non-nil RestartPolicy *restartpolicy.Policy // Replaces the persisted restart policy when non-nil RestartPolicySet bool // True when restart policy was present in the update request + TTL *time.Duration // Relative lifetime from when the update is committed; zero disables expiration + ExpiresAt *time.Time // Absolute expiration time; mutually exclusive with TTL } // ForkInstanceRequest is the domain request for forking an instance. diff --git a/lib/instances/update.go b/lib/instances/update.go index cdea9e4cf..221f73b49 100644 --- a/lib/instances/update.go +++ b/lib/instances/update.go @@ -5,6 +5,7 @@ import ( "fmt" "log/slog" "sort" + "time" "github.com/kernel/hypeman/lib/egressproxy" "github.com/kernel/hypeman/lib/logger" @@ -16,7 +17,7 @@ type updateInstanceRulesService interface { // updateInstance updates mutable instance properties. // Env updates recompute egress proxy header inject rules with the new secret -// values. Auto-standby updates only change persisted metadata. +// values. Other updates only change persisted metadata. func (m *manager) updateInstance(ctx context.Context, id string, req UpdateInstanceRequest) (*Instance, error) { log := logger.FromContext(ctx) @@ -52,10 +53,17 @@ func (m *manager) updateInstance(ctx context.Context, id string, req UpdateInsta if err := validateUpdateInstanceRequest(meta, req); err != nil { return nil, err } + expiresAt, expirationSet, err := resolveExpirationUpdate(meta, req, m.nowUTC()) + if err != nil { + return nil, err + } if len(req.Env) > 0 && inst.State != StateRunning && inst.State != StateInitializing { return nil, fmt.Errorf("%w: instance must be running or initializing to update env (current state: %s)", ErrInvalidState, inst.State) } nextMeta := deepCopyMetadata(meta) + if expirationSet { + nextMeta.ExpiresAt = expiresAt + } if req.AutoStandby != nil { nextMeta.AutoStandby = cloneAutoStandbyPolicy(req.AutoStandby) } @@ -113,9 +121,36 @@ func (m *manager) updateInstance(ctx context.Context, id string, req UpdateInsta return updated, nil } +func resolveExpirationUpdate(meta *metadata, req UpdateInstanceRequest, now time.Time) (*time.Time, bool, error) { + if req.TTL == nil && req.ExpiresAt == nil { + return nil, false, nil + } + if instanceExpired(&meta.StoredMetadata, now) { + return nil, false, fmt.Errorf("%w: expiration deadline has passed", ErrInstanceExpired) + } + if req.TTL != nil { + if *req.TTL == 0 { + return nil, true, nil + } + expiresAt := now.Add(*req.TTL) + return &expiresAt, true, nil + } + if err := validateExpiresAt(req.ExpiresAt, now); err != nil { + return nil, false, err + } + expiresAt := req.ExpiresAt.UTC() + return &expiresAt, true, nil +} + func validateUpdateInstanceRequest(meta *metadata, req UpdateInstanceRequest) error { - if len(req.Env) == 0 && req.AutoStandby == nil && req.HealthCheck == nil && !req.RestartPolicySet { - return fmt.Errorf("%w: request must include env, auto_standby, health_check, and/or restart_policy", ErrInvalidRequest) + if len(req.Env) == 0 && req.AutoStandby == nil && req.HealthCheck == nil && !req.RestartPolicySet && req.TTL == nil && req.ExpiresAt == nil { + return fmt.Errorf("%w: request must include env, auto_standby, health_check, restart_policy, ttl, and/or expires_at", ErrInvalidRequest) + } + if req.TTL != nil && req.ExpiresAt != nil { + return fmt.Errorf("%w: ttl and expires_at are mutually exclusive", ErrInvalidRequest) + } + if req.TTL != nil && *req.TTL < 0 { + return fmt.Errorf("%w: ttl cannot be negative", ErrInvalidRequest) } if req.HealthCheck != nil { if meta == nil { diff --git a/lib/instances/update_test.go b/lib/instances/update_test.go index f3f1e16f6..800a4ddb3 100644 --- a/lib/instances/update_test.go +++ b/lib/instances/update_test.go @@ -30,7 +30,32 @@ func TestValidateUpdateInstanceRequest(t *testing.T) { err := validateUpdateInstanceRequest(baseMeta, UpdateInstanceRequest{}) require.Error(t, err) assert.ErrorIs(t, err, ErrInvalidRequest) - assert.Contains(t, err.Error(), "env, auto_standby, health_check, and/or restart_policy") + assert.Contains(t, err.Error(), "env, auto_standby, health_check, restart_policy, ttl, and/or expires_at") + }) + + t.Run("allows disabling expiration", func(t *testing.T) { + ttl := time.Duration(0) + err := validateUpdateInstanceRequest(baseMeta, UpdateInstanceRequest{TTL: &ttl}) + require.NoError(t, err) + }) + + t.Run("rejects conflicting expiration fields", func(t *testing.T) { + ttl := time.Hour + expiresAt := time.Now().Add(time.Hour) + err := validateUpdateInstanceRequest(baseMeta, UpdateInstanceRequest{TTL: &ttl, ExpiresAt: &expiresAt}) + require.ErrorIs(t, err, ErrInvalidRequest) + }) + + t.Run("rejects negative ttl", func(t *testing.T) { + ttl := -time.Second + err := validateUpdateInstanceRequest(baseMeta, UpdateInstanceRequest{TTL: &ttl}) + require.ErrorIs(t, err, ErrInvalidRequest) + }) + + t.Run("rejects past absolute expiration consistently", func(t *testing.T) { + now := time.Now() + _, _, err := resolveExpirationUpdate(baseMeta, UpdateInstanceRequest{ExpiresAt: &now}, now) + require.ErrorIs(t, err, ErrInvalidExpiresAt) }) t.Run("rejects instances without credential backed envs", func(t *testing.T) { @@ -401,3 +426,109 @@ func TestManagerUpdateInstanceHealthCheckOnlyPublishesLifecycleUpdate(t *testing t.Fatal("timed out waiting for lifecycle update event") } } + +func TestManagerUpdateInstanceTTLIsRelativeToUpdate(t *testing.T) { + t.Parallel() + + m, _ := setupTestManager(t) + now := time.Date(2026, 8, 20, 12, 0, 0, 0, time.UTC) + m.now = func() time.Time { return now } + id := "inst-update-ttl" + require.NoError(t, m.ensureDirectories(id)) + oldExpiration := now.Add(time.Hour) + require.NoError(t, m.saveMetadata(&metadata{StoredMetadata: StoredMetadata{ + Id: id, + Name: id, + CreatedAt: now.Add(-24 * time.Hour), + ExpiresAt: &oldExpiration, + DataDir: m.paths.InstanceDir(id), + }})) + + ttl := 6 * time.Hour + updated, err := m.UpdateInstance(context.Background(), id, UpdateInstanceRequest{TTL: &ttl}) + require.NoError(t, err) + require.NotNil(t, updated.ExpiresAt) + assert.Equal(t, now.Add(ttl), *updated.ExpiresAt) + + restarted := &manager{paths: m.paths} + persisted, err := restarted.loadMetadata(id) + require.NoError(t, err) + require.NotNil(t, persisted.ExpiresAt) + assert.Equal(t, now.Add(ttl), *persisted.ExpiresAt) +} + +func TestManagerUpdateInstanceDisablePreventsStaleReaperDelete(t *testing.T) { + t.Parallel() + + manager, _ := setupTestManager(t) + now := time.Date(2026, 8, 20, 12, 0, 0, 0, time.UTC) + manager.now = func() time.Time { return now } + id := "inst-disable-expiration" + require.NoError(t, manager.ensureDirectories(id)) + expiresAt := now.Add(time.Minute) + require.NoError(t, manager.saveMetadata(&metadata{StoredMetadata: StoredMetadata{ + Id: id, + Name: id, + CreatedAt: now.Add(-time.Hour), + ExpiresAt: &expiresAt, + DataDir: manager.paths.InstanceDir(id), + }})) + + disable := time.Duration(0) + updated, err := manager.UpdateInstance(context.Background(), id, UpdateInstanceRequest{TTL: &disable}) + require.NoError(t, err) + assert.Nil(t, updated.ExpiresAt) + + now = now.Add(2 * time.Hour) + manager.reapExpiredInstances(context.Background()) + _, err = manager.loadMetadata(id) + require.NoError(t, err) +} + +func TestManagerUpdateInstanceExpirationLosesAfterDeadline(t *testing.T) { + t.Parallel() + + manager, _ := setupTestManager(t) + now := time.Date(2026, 8, 20, 12, 0, 0, 0, time.UTC) + manager.now = func() time.Time { return now } + id := "inst-expired-before-update" + require.NoError(t, manager.ensureDirectories(id)) + expiresAt := now + require.NoError(t, manager.saveMetadata(&metadata{StoredMetadata: StoredMetadata{ + Id: id, + Name: id, + CreatedAt: now.Add(-time.Hour), + ExpiresAt: &expiresAt, + DataDir: manager.paths.InstanceDir(id), + }})) + + ttl := time.Hour + _, err := manager.UpdateInstance(context.Background(), id, UpdateInstanceRequest{TTL: &ttl}) + require.ErrorIs(t, err, ErrInstanceExpired) +} + +func TestManagerUpdateInstanceExpirationLosesAfterReaperDelete(t *testing.T) { + t.Parallel() + + manager, _ := setupTestManager(t) + now := time.Date(2026, 8, 20, 12, 0, 0, 0, time.UTC) + manager.now = func() time.Time { return now } + id := "inst-reaped-before-update" + require.NoError(t, manager.ensureDirectories(id)) + expiresAt := now + require.NoError(t, manager.saveMetadata(&metadata{StoredMetadata: StoredMetadata{ + Id: id, + Name: id, + CreatedAt: now.Add(-time.Hour), + ExpiresAt: &expiresAt, + DataDir: manager.paths.InstanceDir(id), + }})) + + deleted, err := manager.reapExpiredInstance(context.Background(), id) + require.NoError(t, err) + require.True(t, deleted) + + ttl := time.Hour + _, err = manager.UpdateInstance(context.Background(), id, UpdateInstanceRequest{TTL: &ttl}) + require.ErrorIs(t, err, ErrNotFound) +} diff --git a/lib/oapi/oapi.go b/lib/oapi/oapi.go index 52ab3b2c0..d6d065935 100644 --- a/lib/oapi/oapi.go +++ b/lib/oapi/oapi.go @@ -704,6 +704,9 @@ type CreateInstanceRequest struct { // Env Environment variables Env *map[string]string `json:"env,omitempty"` + // ExpiresAt Absolute expiration time. Must be in the future and is mutually exclusive with ttl. + ExpiresAt *time.Time `json:"expires_at,omitempty"` + // Gpu GPU configuration for the instance Gpu *GPUConfig `json:"gpu,omitempty"` @@ -766,6 +769,9 @@ type CreateInstanceRequest struct { // Tags User-defined key-value tags. Tags *Tags `json:"tags,omitempty"` + // Ttl Relative lifetime from instance creation, in Go duration format. Use "0s" or omit both expiration fields to disable automatic expiration. Mutually exclusive with expires_at. + Ttl *string `json:"ttl,omitempty"` + // Vcpus Number of virtual CPUs Vcpus *int `json:"vcpus,omitempty"` @@ -1240,6 +1246,9 @@ type Instance struct { // ExitMessage Human-readable description of exit (e.g., "command not found", "killed by signal 9 (SIGKILL) - OOM") ExitMessage *string `json:"exit_message,omitempty"` + // ExpiresAt Absolute expiration time, or null when automatic expiration is disabled. + ExpiresAt *time.Time `json:"expires_at"` + // Gpu GPU information attached to the instance Gpu *InstanceGPU `json:"gpu,omitempty"` @@ -1846,11 +1855,17 @@ type UpdateInstanceRequest struct { // are accepted. Use this to rotate real credential values without restarting the VM. Env *map[string]string `json:"env,omitempty"` + // ExpiresAt Absolute expiration time. Must be in the future and is mutually exclusive with ttl. + ExpiresAt *time.Time `json:"expires_at,omitempty"` + // HealthCheck Workload health check policy. Health is reported separately from instance lifecycle state. HealthCheck *HealthCheck `json:"health_check,omitempty"` // RestartPolicy Whole-instance restart supervision policy. RestartPolicy *RestartPolicy `json:"restart_policy,omitempty"` + + // Ttl Relative lifetime from when this update is committed, in Go duration format. Use "0s" to disable automatic expiration. Mutually exclusive with expires_at. + Ttl *string `json:"ttl,omitempty"` } // Volume defines model for Volume. @@ -18818,381 +18833,385 @@ func (sh *strictHandler) GetVolume(w http.ResponseWriter, r *http.Request, id st // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", - "eSdugOoBAA==", + "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", + "/2DqTitN7gEA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/openapi.yaml b/openapi.yaml index b117d2035..e85fc61b3 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -530,6 +530,15 @@ components: $ref: "#/components/schemas/HealthCheck" restart_policy: $ref: "#/components/schemas/RestartPolicy" + ttl: + type: string + description: Relative lifetime from when this update is committed, in Go duration format. Use "0s" to disable automatic expiration. Mutually exclusive with expires_at. + example: "6h" + expires_at: + type: string + format: date-time + description: Absolute expiration time. Must be in the future and is mutually exclusive with ttl. + example: "2026-08-21T18:00:00Z" CreateInstanceRequest: type: object @@ -601,6 +610,15 @@ components: format: "Bearer ${value}" tags: $ref: "#/components/schemas/Tags" + ttl: + type: string + description: Relative lifetime from instance creation, in Go duration format. Use "0s" or omit both expiration fields to disable automatic expiration. Mutually exclusive with expires_at. + example: "24h" + expires_at: + type: string + format: date-time + description: Absolute expiration time. Must be in the future and is mutually exclusive with ttl. + example: "2026-08-21T18:00:00Z" network: type: object description: Network configuration for the instance @@ -977,7 +995,7 @@ components: Instance: type: object - required: [id, name, image, state, created_at] + required: [id, name, image, state, created_at, expires_at] properties: id: type: string @@ -1072,6 +1090,12 @@ components: format: date-time description: Creation timestamp (RFC3339) example: "2025-01-15T10:30:00Z" + expires_at: + type: string + format: date-time + nullable: true + description: Absolute expiration time, or null when automatic expiration is disabled. + example: "2026-08-21T18:00:00Z" started_at: type: string format: date-time @@ -2838,9 +2862,8 @@ paths: patch: summary: Update instance properties description: | - Update mutable properties of a running instance. Currently supports updating - only the environment variables referenced by existing credential policies, - enabling secret/key rotation without instance restart. + Update mutable instance properties. TTL values are relative to when the update + is committed. Expiration updates are rejected after the current deadline passes. operationId: updateInstance security: - bearerAuth: [] @@ -2877,7 +2900,7 @@ paths: schema: $ref: "#/components/schemas/Error" 409: - description: Invalid state (instance must be running or initializing) + description: Invalid state or instance expiration deadline already passed content: application/json: schema: From 127bc5081aa7208b8fddb1ad2d93c6c36a142c3b Mon Sep 17 00:00:00 2001 From: sjmiller609 <7516283+sjmiller609@users.noreply.github.com> Date: Fri, 21 Aug 2026 18:15:24 +0000 Subject: [PATCH 2/2] Harden instance expiration handling --- cmd/api/api/instances.go | 4 +- cmd/api/api/instances_test.go | 10 +- lib/instances/create.go | 8 +- lib/instances/ttl_reaper.go | 30 +- lib/instances/ttl_reaper_test.go | 39 +- lib/instances/types.go | 2 +- lib/instances/update.go | 47 +- lib/instances/update_test.go | 57 ++- lib/oapi/oapi.go | 758 +++++++++++++++---------------- openapi.yaml | 2 +- 10 files changed, 535 insertions(+), 422 deletions(-) diff --git a/cmd/api/api/instances.go b/cmd/api/api/instances.go index da534d388..04698ddc3 100644 --- a/cmd/api/api/instances.go +++ b/cmd/api/api/instances.go @@ -140,7 +140,7 @@ func (s *ApiService) CreateInstance(ctx context.Context, request oapi.CreateInst Message: "ttl and expires_at are mutually exclusive", }, nil } - var ttl time.Duration + var ttl *time.Duration if request.Body.Ttl != nil { parsedTTL, err := parseTTL(*request.Body.Ttl) if err != nil { @@ -149,7 +149,7 @@ func (s *ApiService) CreateInstance(ctx context.Context, request oapi.CreateInst Message: err.Error(), }, nil } - ttl = parsedTTL + ttl = &parsedTTL } // Parse network enabled (default: true) diff --git a/cmd/api/api/instances_test.go b/cmd/api/api/instances_test.go index 5aab835b6..06abe3e54 100644 --- a/cmd/api/api/instances_test.go +++ b/cmd/api/api/instances_test.go @@ -315,8 +315,8 @@ func (m *captureCreateManager) CreateInstance(ctx context.Context, req instances now := time.Now() expiresAt := req.ExpiresAt - if req.TTL > 0 { - resolved := now.Add(req.TTL) + if req.TTL != nil && *req.TTL > 0 { + resolved := now.Add(*req.TTL) expiresAt = &resolved } return &instances.Instance{ @@ -356,7 +356,8 @@ func TestCreateInstance_TTL(t *testing.T) { created, ok := resp.(oapi.CreateInstance201JSONResponse) require.True(t, ok) require.NotNil(t, mockMgr.lastReq) - assert.Equal(t, 90*time.Minute, mockMgr.lastReq.TTL) + require.NotNil(t, mockMgr.lastReq.TTL) + assert.Equal(t, 90*time.Minute, *mockMgr.lastReq.TTL) require.NotNil(t, created.ExpiresAt) assert.Equal(t, created.CreatedAt.Add(90*time.Minute), *created.ExpiresAt) } @@ -377,7 +378,8 @@ func TestCreateInstance_ZeroTTLDisablesExpiration(t *testing.T) { require.NoError(t, err) created, ok := resp.(oapi.CreateInstance201JSONResponse) require.True(t, ok) - assert.Zero(t, mockMgr.lastReq.TTL) + require.NotNil(t, mockMgr.lastReq.TTL) + assert.Zero(t, *mockMgr.lastReq.TTL) assert.Nil(t, created.ExpiresAt) } diff --git a/lib/instances/create.go b/lib/instances/create.go index 59155950a..0d21e8e91 100644 --- a/lib/instances/create.go +++ b/lib/instances/create.go @@ -590,10 +590,10 @@ func resolveCreateExpiration(req CreateInstanceRequest, now time.Time) (*time.Ti expiresAt := req.ExpiresAt.UTC() return &expiresAt, nil } - if req.TTL == 0 { + if req.TTL == nil || *req.TTL == 0 { return nil, nil } - expiresAt := now.Add(req.TTL) + expiresAt := now.Add(*req.TTL) return &expiresAt, nil } @@ -621,10 +621,10 @@ func validateCreateRequest(req *CreateInstanceRequest) error { if req.Vcpus < 0 { return fmt.Errorf("vcpus cannot be negative") } - if req.TTL < 0 { + if req.TTL != nil && *req.TTL < 0 { return fmt.Errorf("%w: ttl cannot be negative", ErrInvalidRequest) } - if req.TTL > 0 && req.ExpiresAt != nil { + if req.TTL != nil && req.ExpiresAt != nil { return fmt.Errorf("%w: ttl and expires_at are mutually exclusive", ErrInvalidRequest) } if req.NetworkEgress != nil && req.NetworkEgress.Enabled { diff --git a/lib/instances/ttl_reaper.go b/lib/instances/ttl_reaper.go index 16dccfdc0..5c5fad974 100644 --- a/lib/instances/ttl_reaper.go +++ b/lib/instances/ttl_reaper.go @@ -60,17 +60,14 @@ func (m *manager) reapExpiredInstances(ctx context.Context) { continue } - deleteCtx, cancel := context.WithTimeout(ctx, m.instanceTTLReaperDeleteTimeout()) - deleted, err := m.reapExpiredInstance(deleteCtx, id) - timedOut := errors.Is(deleteCtx.Err(), context.DeadlineExceeded) - cancel() + deleted, err := m.reapExpiredInstanceWithTimeout(ctx, id) switch { case err == nil && deleted: m.recordTTLReaperDeletion(ctx, "success") case err == nil: continue - case timedOut: + case errors.Is(err, context.DeadlineExceeded): m.recordTTLReaperDeletion(ctx, "timeout") log.ErrorContext(ctx, "instance ttl reaper timed out deleting instance", "instance_id", id, "error", err) case errors.Is(err, ErrNotFound): @@ -82,6 +79,29 @@ func (m *manager) reapExpiredInstances(ctx context.Context) { } } +type ttlReaperDeleteResult struct { + deleted bool + err error +} + +func (m *manager) reapExpiredInstanceWithTimeout(ctx context.Context, id string) (bool, error) { + deleteCtx, cancel := context.WithTimeout(ctx, m.instanceTTLReaperDeleteTimeout()) + defer cancel() + + resultCh := make(chan ttlReaperDeleteResult, 1) + go func() { + deleted, err := m.reapExpiredInstance(deleteCtx, id) + resultCh <- ttlReaperDeleteResult{deleted: deleted, err: err} + }() + + select { + case result := <-resultCh: + return result.deleted, result.err + case <-deleteCtx.Done(): + return false, deleteCtx.Err() + } +} + func (m *manager) reapExpiredInstance(ctx context.Context, id string) (bool, error) { lock := m.getInstanceLock(id) // Active lifecycle operations take precedence; retry on the next sweep. diff --git a/lib/instances/ttl_reaper_test.go b/lib/instances/ttl_reaper_test.go index 02548bf78..0e0cf9d71 100644 --- a/lib/instances/ttl_reaper_test.go +++ b/lib/instances/ttl_reaper_test.go @@ -15,7 +15,8 @@ func TestResolveCreateExpiration(t *testing.T) { t.Parallel() now := time.Date(2026, 8, 20, 12, 0, 0, 0, time.UTC) - expiresAt, err := resolveCreateExpiration(CreateInstanceRequest{TTL: 6 * time.Hour}, now) + ttl := 6 * time.Hour + expiresAt, err := resolveCreateExpiration(CreateInstanceRequest{TTL: &ttl}, now) require.NoError(t, err) require.NotNil(t, expiresAt) assert.Equal(t, now.Add(6*time.Hour), *expiresAt) @@ -27,6 +28,16 @@ func TestResolveCreateExpiration(t *testing.T) { past := now.Add(-time.Second) _, err = resolveCreateExpiration(CreateInstanceRequest{ExpiresAt: &past}, now) require.ErrorIs(t, err, ErrInvalidExpiresAt) + + zero := time.Duration(0) + future := now.Add(time.Hour) + err = validateCreateRequest(&CreateInstanceRequest{ + Name: "conflicting-expiration", + Image: "alpine", + TTL: &zero, + ExpiresAt: &future, + }) + require.ErrorIs(t, err, ErrInvalidRequest) } func TestInstanceExpired(t *testing.T) { @@ -178,7 +189,7 @@ func TestTTLReaperDeleteTimeoutDoesNotBlockSweep(t *testing.T) { paths: p, now: func() time.Time { return now }, lifecycleEvents: newLifecycleSubscribersWithBufferSize(defaultLifecycleEventBufferSize), - ttlReaperDeleteTimeout: 10 * time.Millisecond, + ttlReaperDeleteTimeout: 100 * time.Millisecond, } expiredAt := now.Add(-time.Minute) for _, id := range []string{"a-timeout", "b-deleted"} { @@ -192,23 +203,35 @@ func TestTTLReaperDeleteTimeoutDoesNotBlockSweep(t *testing.T) { }})) } - var calls []string - m.deleteInstanceFn = func(ctx context.Context, id string) error { - calls = append(calls, id) + calls := make(chan string, 2) + releaseStuckDelete := make(chan struct{}) + stuckDeleteDone := make(chan struct{}) + m.deleteInstanceFn = func(_ context.Context, id string) error { + calls <- id if id == "a-timeout" { - <-ctx.Done() - return ctx.Err() + <-releaseStuckDelete + err := m.deleteInstanceData(id) + close(stuckDeleteDone) + return err } return m.deleteInstanceData(id) } m.reapExpiredInstances(context.Background()) - assert.Equal(t, []string{"a-timeout", "b-deleted"}, calls) + assert.Equal(t, "a-timeout", <-calls) + assert.Equal(t, "b-deleted", <-calls) _, err := os.Stat(p.InstanceDir("a-timeout")) require.NoError(t, err) _, err = os.Stat(p.InstanceDir("b-deleted")) require.ErrorIs(t, err, os.ErrNotExist) + + close(releaseStuckDelete) + select { + case <-stuckDeleteDone: + case <-time.After(time.Second): + t.Fatal("timed-out deletion did not finish after release") + } } func TestReapExpiredInstanceSkipsBusyCreateLock(t *testing.T) { diff --git a/lib/instances/types.go b/lib/instances/types.go index 973fe93cf..a90ecd574 100644 --- a/lib/instances/types.go +++ b/lib/instances/types.go @@ -275,7 +275,7 @@ type CreateInstanceRequest struct { AutoStandby *autostandby.Policy // Optional automatic standby policy HealthCheck *healthcheck.Policy // Optional workload health check policy RestartPolicy *restartpolicy.Policy // Optional whole-instance restart policy - TTL time.Duration // Optional lifetime from creation; zero disables expiration + TTL *time.Duration // Optional lifetime from creation; zero disables expiration ExpiresAt *time.Time // Optional absolute expiration time; mutually exclusive with TTL AllowSystemVolumeMounts bool // Internal only: permits attaching reserved system volumes. Never populated from API requests. SystemVolumeMountPaths []string // Internal only: exact system paths reserved volumes may mount at. diff --git a/lib/instances/update.go b/lib/instances/update.go index 221f73b49..f5a2a420a 100644 --- a/lib/instances/update.go +++ b/lib/instances/update.go @@ -53,17 +53,13 @@ func (m *manager) updateInstance(ctx context.Context, id string, req UpdateInsta if err := validateUpdateInstanceRequest(meta, req); err != nil { return nil, err } - expiresAt, expirationSet, err := resolveExpirationUpdate(meta, req, m.nowUTC()) - if err != nil { + if err := validateExpirationUpdate(meta, req, m.nowUTC()); err != nil { return nil, err } if len(req.Env) > 0 && inst.State != StateRunning && inst.State != StateInitializing { return nil, fmt.Errorf("%w: instance must be running or initializing to update env (current state: %s)", ErrInvalidState, inst.State) } nextMeta := deepCopyMetadata(meta) - if expirationSet { - nextMeta.ExpiresAt = expiresAt - } if req.AutoStandby != nil { nextMeta.AutoStandby = cloneAutoStandbyPolicy(req.AutoStandby) } @@ -76,6 +72,9 @@ func (m *manager) updateInstance(ctx context.Context, id string, req UpdateInsta nextMeta.RestartStatus = restartStatusAfterPolicyUpdate(nextMeta.RestartStatus) } if len(req.Env) == 0 { + if err := applyExpirationUpdateAtCommit(nextMeta, req, m.nowUTC()); err != nil { + return nil, err + } if err := m.saveMetadata(nextMeta); err != nil { return nil, fmt.Errorf("save metadata: %w", err) } @@ -108,7 +107,13 @@ func (m *manager) updateInstance(ctx context.Context, id string, req UpdateInsta return nil, fmt.Errorf("egress proxy service unavailable") } - if err := applyUpdatedInstanceEnv(ctx, log, id, nextMeta, prevEnv, nextEnv, m.saveMetadata, svc); err != nil { + saveAtCommit := func(meta *metadata) error { + if err := applyExpirationUpdateAtCommit(meta, req, m.nowUTC()); err != nil { + return err + } + return m.saveMetadata(meta) + } + if err := applyUpdatedInstanceEnv(ctx, log, id, nextMeta, prevEnv, nextEnv, saveAtCommit, svc); err != nil { return nil, err } @@ -121,12 +126,33 @@ func (m *manager) updateInstance(ctx context.Context, id string, req UpdateInsta return updated, nil } -func resolveExpirationUpdate(meta *metadata, req UpdateInstanceRequest, now time.Time) (*time.Time, bool, error) { +func applyExpirationUpdateAtCommit(meta *metadata, req UpdateInstanceRequest, now time.Time) error { + expiresAt, expirationSet, err := resolveExpirationUpdate(meta, req, now) + if err != nil { + return err + } + if expirationSet { + meta.ExpiresAt = expiresAt + } + return nil +} + +func validateExpirationUpdate(meta *metadata, req UpdateInstanceRequest, now time.Time) error { if req.TTL == nil && req.ExpiresAt == nil { - return nil, false, nil + return nil } if instanceExpired(&meta.StoredMetadata, now) { - return nil, false, fmt.Errorf("%w: expiration deadline has passed", ErrInstanceExpired) + return fmt.Errorf("%w: expiration deadline has passed", ErrInstanceExpired) + } + return validateExpiresAt(req.ExpiresAt, now) +} + +func resolveExpirationUpdate(meta *metadata, req UpdateInstanceRequest, now time.Time) (*time.Time, bool, error) { + if err := validateExpirationUpdate(meta, req, now); err != nil { + return nil, false, err + } + if req.TTL == nil && req.ExpiresAt == nil { + return nil, false, nil } if req.TTL != nil { if *req.TTL == 0 { @@ -135,9 +161,6 @@ func resolveExpirationUpdate(meta *metadata, req UpdateInstanceRequest, now time expiresAt := now.Add(*req.TTL) return &expiresAt, true, nil } - if err := validateExpiresAt(req.ExpiresAt, now); err != nil { - return nil, false, err - } expiresAt := req.ExpiresAt.UTC() return &expiresAt, true, nil } diff --git a/lib/instances/update_test.go b/lib/instances/update_test.go index 800a4ddb3..2c2ff54e2 100644 --- a/lib/instances/update_test.go +++ b/lib/instances/update_test.go @@ -431,15 +431,23 @@ func TestManagerUpdateInstanceTTLIsRelativeToUpdate(t *testing.T) { t.Parallel() m, _ := setupTestManager(t) - now := time.Date(2026, 8, 20, 12, 0, 0, 0, time.UTC) - m.now = func() time.Time { return now } + requestTime := time.Date(2026, 8, 20, 12, 0, 0, 0, time.UTC) + commitTime := requestTime.Add(2 * time.Minute) + nowCalls := 0 + m.now = func() time.Time { + nowCalls++ + if nowCalls == 1 { + return requestTime + } + return commitTime + } id := "inst-update-ttl" require.NoError(t, m.ensureDirectories(id)) - oldExpiration := now.Add(time.Hour) + oldExpiration := requestTime.Add(time.Hour) require.NoError(t, m.saveMetadata(&metadata{StoredMetadata: StoredMetadata{ Id: id, Name: id, - CreatedAt: now.Add(-24 * time.Hour), + CreatedAt: requestTime.Add(-24 * time.Hour), ExpiresAt: &oldExpiration, DataDir: m.paths.InstanceDir(id), }})) @@ -448,13 +456,50 @@ func TestManagerUpdateInstanceTTLIsRelativeToUpdate(t *testing.T) { updated, err := m.UpdateInstance(context.Background(), id, UpdateInstanceRequest{TTL: &ttl}) require.NoError(t, err) require.NotNil(t, updated.ExpiresAt) - assert.Equal(t, now.Add(ttl), *updated.ExpiresAt) + assert.GreaterOrEqual(t, nowCalls, 2) + assert.Equal(t, commitTime.Add(ttl), *updated.ExpiresAt) restarted := &manager{paths: m.paths} persisted, err := restarted.loadMetadata(id) require.NoError(t, err) require.NotNil(t, persisted.ExpiresAt) - assert.Equal(t, now.Add(ttl), *persisted.ExpiresAt) + assert.Equal(t, commitTime.Add(ttl), *persisted.ExpiresAt) +} + +func TestManagerUpdateInstanceRejectsExpirationThatPassesBeforeCommit(t *testing.T) { + t.Parallel() + + m, _ := setupTestManager(t) + requestTime := time.Date(2026, 8, 20, 12, 0, 0, 0, time.UTC) + commitTime := requestTime.Add(2 * time.Minute) + nowCalls := 0 + m.now = func() time.Time { + nowCalls++ + if nowCalls == 1 { + return requestTime + } + return commitTime + } + id := "inst-expires-during-update" + expiresAt := requestTime.Add(time.Minute) + require.NoError(t, m.ensureDirectories(id)) + require.NoError(t, m.saveMetadata(&metadata{StoredMetadata: StoredMetadata{ + Id: id, + Name: id, + CreatedAt: requestTime.Add(-time.Hour), + ExpiresAt: &expiresAt, + DataDir: m.paths.InstanceDir(id), + }})) + + ttl := time.Hour + _, err := m.UpdateInstance(context.Background(), id, UpdateInstanceRequest{TTL: &ttl}) + require.ErrorIs(t, err, ErrInstanceExpired) + assert.GreaterOrEqual(t, nowCalls, 2) + + persisted, err := m.loadMetadata(id) + require.NoError(t, err) + require.NotNil(t, persisted.ExpiresAt) + assert.Equal(t, expiresAt, *persisted.ExpiresAt) } func TestManagerUpdateInstanceDisablePreventsStaleReaperDelete(t *testing.T) { diff --git a/lib/oapi/oapi.go b/lib/oapi/oapi.go index d6d065935..2ee09469e 100644 --- a/lib/oapi/oapi.go +++ b/lib/oapi/oapi.go @@ -1246,7 +1246,7 @@ type Instance struct { // ExitMessage Human-readable description of exit (e.g., "command not found", "killed by signal 9 (SIGKILL) - OOM") ExitMessage *string `json:"exit_message,omitempty"` - // ExpiresAt Absolute expiration time, or null when automatic expiration is disabled. + // ExpiresAt Absolute expiration time, or null when automatic expiration is disabled. Instance TTL is cleared on fork. ExpiresAt *time.Time `json:"expires_at"` // Gpu GPU information attached to the instance @@ -18833,385 +18833,385 @@ func (sh *strictHandler) GetVolume(w http.ResponseWriter, r *http.Request, id st // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", - "/2DqTitN7gEA", + "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", + "VAd7z5/udj59+PT/BwAA//+uhiQVbu4BAA==", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/openapi.yaml b/openapi.yaml index e85fc61b3..eac70a5ee 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -1094,7 +1094,7 @@ components: type: string format: date-time nullable: true - description: Absolute expiration time, or null when automatic expiration is disabled. + description: Absolute expiration time, or null when automatic expiration is disabled. Instance TTL is cleared on fork. example: "2026-08-21T18:00:00Z" started_at: type: string