DeleteInstance deletes an instance.
(ctx context.Context, req *connect.Request[v1pb.DeleteInstanceRequest])
| 625 | |
| 626 | // DeleteInstance deletes an instance. |
| 627 | func (s *InstanceService) DeleteInstance(ctx context.Context, req *connect.Request[v1pb.DeleteInstanceRequest]) (*connect.Response[emptypb.Empty], error) { |
| 628 | instance, err := getInstanceMessage(ctx, s.store, req.Msg.Name) |
| 629 | if err != nil { |
| 630 | return nil, err |
| 631 | } |
| 632 | |
| 633 | // Handle purge (hard delete) of soft-deleted instance |
| 634 | if req.Msg.Purge { |
| 635 | // Following AIP-165, purge only works on already soft-deleted instances |
| 636 | if !instance.Deleted { |
| 637 | return nil, connect.NewError(connect.CodeFailedPrecondition, errors.Errorf("instance %q must be archived before it can be deleted", req.Msg.Name)) |
| 638 | } |
| 639 | |
| 640 | // Permanently delete the instance and all related resources |
| 641 | if err := s.store.DeleteInstance(ctx, instance.Workspace, instance.ResourceID); err != nil { |
| 642 | return nil, connect.NewError(connect.CodeInternal, errors.Wrap(err, "failed to purge instance")) |
| 643 | } |
| 644 | |
| 645 | return connect.NewResponse(&emptypb.Empty{}), nil |
| 646 | } |
| 647 | |
| 648 | // Regular soft delete flow |
| 649 | // Idempotent: if already deleted, return success |
| 650 | if instance.Deleted { |
| 651 | return connect.NewResponse(&emptypb.Empty{}), nil |
| 652 | } |
| 653 | |
| 654 | databases, err := s.store.ListDatabases(ctx, &store.FindDatabaseMessage{Workspace: common.GetWorkspaceIDFromContext(ctx), InstanceID: &instance.ResourceID}) |
| 655 | if err != nil { |
| 656 | return nil, err |
| 657 | } |
| 658 | if req.Msg.Force { |
| 659 | if len(databases) > 0 { |
| 660 | defaultProjectID, err := s.store.GetDefaultProjectID(ctx, common.GetWorkspaceIDFromContext(ctx)) |
| 661 | if err != nil { |
| 662 | return nil, connect.NewError(connect.CodeInternal, errors.Wrap(err, "failed to get default project ID")) |
| 663 | } |
| 664 | if err := s.store.BatchUpdateDatabases(ctx, databases, &store.BatchUpdateDatabases{Workspace: common.GetWorkspaceIDFromContext(ctx), ProjectID: &defaultProjectID}); err != nil { |
| 665 | return nil, connect.NewError(connect.CodeInternal, err) |
| 666 | } |
| 667 | } |
| 668 | } else { |
| 669 | var databaseNames []string |
| 670 | for _, database := range databases { |
| 671 | if !common.IsDefaultProject(common.GetWorkspaceIDFromContext(ctx), database.ProjectID) { |
| 672 | databaseNames = append(databaseNames, database.DatabaseName) |
| 673 | } |
| 674 | } |
| 675 | if len(databaseNames) > 0 { |
| 676 | return nil, connect.NewError(connect.CodeFailedPrecondition, errors.New("all databases should be transferred to the unassigned project before deleting the instance")) |
| 677 | } |
| 678 | } |
| 679 | |
| 680 | metadata := proto.CloneOf(instance.Metadata) |
| 681 | metadata.Activation = false |
| 682 | if _, err := s.store.UpdateInstance(ctx, &store.UpdateInstanceMessage{ |
| 683 | ResourceID: &instance.ResourceID, |
| 684 | Workspace: instance.Workspace, |
nothing calls this directly
no test coverage detected