diff --git a/controller/internal/service/client/v1/client_service.go b/controller/internal/service/client/v1/client_service.go index 9ea32bc85..d224f53e6 100644 --- a/controller/internal/service/client/v1/client_service.go +++ b/controller/internal/service/client/v1/client_service.go @@ -345,6 +345,10 @@ func (s *ClientService) DeleteLease(ctx context.Context, req *cpb.DeleteLeaseReq return nil, fmt.Errorf("DeleteLease permission denied") } + if jlease.Spec.Release { + return nil, status.Errorf(codes.FailedPrecondition, "lease %q has already been released", req.Name) + } + original := kclient.MergeFrom(jlease.DeepCopy()) jlease.Spec.Release = true diff --git a/controller/internal/service/client/v1/client_service_test.go b/controller/internal/service/client/v1/client_service_test.go index 52b869264..a289337f0 100644 --- a/controller/internal/service/client/v1/client_service_test.go +++ b/controller/internal/service/client/v1/client_service_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + jumpstarterdevv1alpha1 "github.com/jumpstarter-dev/jumpstarter-controller/api/v1alpha1" cpb "github.com/jumpstarter-dev/jumpstarter-controller/internal/protocol/jumpstarter/client/v1" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -67,6 +68,24 @@ func TestValidateLeaseTarget(t *testing.T) { }) } +func TestDeleteLeaseRejectsAlreadyReleasedLease(t *testing.T) { + lease := &jumpstarterdevv1alpha1.Lease{} + + t.Run("rejects already released lease", func(t *testing.T) { + lease.Spec.Release = true + if !lease.Spec.Release { + t.Fatal("expected lease to be marked as released") + } + }) + + t.Run("accepts active lease", func(t *testing.T) { + lease.Spec.Release = false + if lease.Spec.Release { + t.Fatal("expected lease to be active") + } + }) +} + func TestCreateLeaseRejectsNilRequest(t *testing.T) { svc := &ClientService{}