88 "github.com/stackitcloud/stackit-cli/internal/pkg/confirm"
99 "github.com/stackitcloud/stackit-cli/internal/pkg/errors"
1010 "github.com/stackitcloud/stackit-cli/internal/pkg/examples"
11+ "github.com/stackitcloud/stackit-cli/internal/pkg/flags"
1112 "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
1213 "github.com/stackitcloud/stackit-cli/internal/pkg/services/postgresflex/client"
1314 postgresflexUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/postgresflex/utils"
@@ -21,23 +22,33 @@ import (
2122
2223const (
2324 instanceIdArg = "INSTANCE_ID"
25+
26+ forceDeleteFlag = "force"
2427)
2528
2629type inputModel struct {
2730 * globalflags.GlobalFlagModel
28- InstanceId string
31+ InstanceId string
32+ ForceDelete bool
2933}
3034
3135func NewCmd () * cobra.Command {
3236 cmd := & cobra.Command {
3337 Use : fmt .Sprintf ("delete %s" , instanceIdArg ),
3438 Short : "Deletes a PostgreSQL Flex instance" ,
35- Long : "Deletes a PostgreSQL Flex instance." ,
36- Args : args .SingleArg (instanceIdArg , utils .ValidateUUID ),
39+ Long : fmt .Sprintf ("%s\n %s\n %s" ,
40+ "Deletes a PostgreSQL Flex instance." ,
41+ "By default, instances will be kept in a delayed deleted state for 7 days before being permanently deleted." ,
42+ "Use the --force flag to force the immediate deletion of a delayed deleted instance." ,
43+ ),
44+ Args : args .SingleArg (instanceIdArg , utils .ValidateUUID ),
3745 Example : examples .Build (
3846 examples .NewExample (
3947 `Delete a PostgreSQL Flex instance with ID "xxx"` ,
4048 "$ stackit postgresflex instance delete xxx" ),
49+ examples .NewExample (
50+ `Force the deletion of a delayed deleted PostgreSQL Flex instance with ID "xxx"` ,
51+ "$ stackit postgresflex instance delete xxx --force" ),
4152 ),
4253 RunE : func (cmd * cobra.Command , args []string ) error {
4354 ctx := context .Background ()
@@ -65,35 +76,74 @@ func NewCmd() *cobra.Command {
6576 }
6677 }
6778
68- // Call API
69- req := buildRequest (ctx , model , apiClient )
70- err = req .Execute ()
79+ toDelete , toForceDelete , err := getNextOperations (ctx , model , apiClient )
7180 if err != nil {
72- return fmt . Errorf ( "delete PostgreSQL Flex instance: %w" , err )
81+ return err
7382 }
7483
75- // Wait for async operation, if async mode not enabled
76- if ! model .Async {
77- s := spinner .New (cmd )
78- s .Start ("Deleting instance" )
79- _ , err = wait .DeleteInstanceWaitHandler (ctx , apiClient , model .ProjectId , model .InstanceId ).WaitWithContext (ctx )
84+ if toDelete {
85+ // Call API
86+ delReq := buildDeleteRequest (ctx , model , apiClient )
87+ err = delReq .Execute ()
8088 if err != nil {
81- return fmt .Errorf ("wait for PostgreSQL Flex instance deletion: %w" , err )
89+ return fmt .Errorf ("delete PostgreSQL Flex instance: %w" , err )
90+ }
91+
92+ // Wait for async operation, if async mode not enabled
93+ if ! model .Async {
94+ s := spinner .New (cmd )
95+ s .Start ("Deleting instance" )
96+ _ , err = wait .DeleteInstanceWaitHandler (ctx , apiClient , model .ProjectId , model .InstanceId ).WaitWithContext (ctx )
97+ if err != nil {
98+ return fmt .Errorf ("wait for PostgreSQL Flex instance deletion: %w" , err )
99+ }
100+ s .Stop ()
101+ }
102+ }
103+
104+ if toForceDelete {
105+ // Call API
106+ forceDelReq := buildForceDeleteRequest (ctx , model , apiClient )
107+ err = forceDelReq .Execute ()
108+ if err != nil {
109+ return fmt .Errorf ("force delete PostgreSQL Flex instance: %w" , err )
110+ }
111+
112+ // Wait for async operation, if async mode not enabled
113+ if ! model .Async {
114+ s := spinner .New (cmd )
115+ s .Start ("Forcing deletion of instance" )
116+ _ , err = wait .ForceDeleteInstanceWaitHandler (ctx , apiClient , model .ProjectId , model .InstanceId ).WaitWithContext (ctx )
117+ if err != nil {
118+ return fmt .Errorf ("wait for PostgreSQL Flex instance force deletion: %w" , err )
119+ }
120+ s .Stop ()
82121 }
83- s .Stop ()
84122 }
85123
86124 operationState := "Deleted"
125+ if toForceDelete {
126+ operationState = "Forcefully deleted"
127+ }
87128 if model .Async {
88129 operationState = "Triggered deletion of"
130+ if toForceDelete {
131+ operationState = "Triggered forced deletion of"
132+ }
89133 }
134+
90135 cmd .Printf ("%s instance %q\n " , operationState , instanceLabel )
91136 return nil
92137 },
93138 }
139+ configureFlags (cmd )
94140 return cmd
95141}
96142
143+ func configureFlags (cmd * cobra.Command ) {
144+ cmd .Flags ().BoolP (forceDeleteFlag , "f" , false , "Force deletion of a delayed deleted instance" )
145+ }
146+
97147func parseInput (cmd * cobra.Command , inputArgs []string ) (* inputModel , error ) {
98148 instanceId := inputArgs [0 ]
99149
@@ -105,10 +155,39 @@ func parseInput(cmd *cobra.Command, inputArgs []string) (*inputModel, error) {
105155 return & inputModel {
106156 GlobalFlagModel : globalFlags ,
107157 InstanceId : instanceId ,
158+ ForceDelete : flags .FlagToBoolValue (cmd , forceDeleteFlag ),
108159 }, nil
109160}
110161
111- func buildRequest (ctx context.Context , model * inputModel , apiClient * postgresflex.APIClient ) postgresflex.ApiDeleteInstanceRequest {
162+ func buildDeleteRequest (ctx context.Context , model * inputModel , apiClient * postgresflex.APIClient ) postgresflex.ApiDeleteInstanceRequest {
112163 req := apiClient .DeleteInstance (ctx , model .ProjectId , model .InstanceId )
113164 return req
114165}
166+
167+ func buildForceDeleteRequest (ctx context.Context , model * inputModel , apiClient * postgresflex.APIClient ) postgresflex.ApiForceDeleteInstanceRequest {
168+ req := apiClient .ForceDeleteInstance (ctx , model .ProjectId , model .InstanceId )
169+ return req
170+ }
171+
172+ type PostgreSQLFlexClient interface {
173+ GetInstanceExecute (ctx context.Context , projectId , instanceId string ) (* postgresflex.InstanceResponse , error )
174+ ListVersionsExecute (ctx context.Context , projectId string ) (* postgresflex.ListVersionsResponse , error )
175+ GetUserExecute (ctx context.Context , projectId , instanceId , userId string ) (* postgresflex.GetUserResponse , error )
176+ }
177+
178+ func getNextOperations (ctx context.Context , model * inputModel , apiClient PostgreSQLFlexClient ) (toDelete , toForceDelete bool , err error ) {
179+ instanceStatus , err := postgresflexUtils .GetInstanceStatus (ctx , apiClient , model .ProjectId , model .InstanceId )
180+ if err != nil {
181+ return false , false , fmt .Errorf ("get PostgreSQL Flex instance status: %w" , err )
182+ }
183+
184+ if instanceStatus == wait .InstanceStateDeleted {
185+ if ! model .ForceDelete {
186+ return false , false , fmt .Errorf ("instance is already deleted, use --force to force the deletion of a delayed deleted instance" )
187+ }
188+
189+ return false , model .ForceDelete , nil
190+ }
191+
192+ return true , model .ForceDelete , nil
193+ }
0 commit comments