15
15
package destroy
16
16
17
17
import (
18
+ "errors"
18
19
"fmt"
19
20
"os"
20
21
"strings"
@@ -36,6 +37,7 @@ import (
36
37
"kusionstack.io/kusion/pkg/engine/runtime/terraform"
37
38
"kusionstack.io/kusion/pkg/log"
38
39
"kusionstack.io/kusion/pkg/util/pretty"
40
+ "kusionstack.io/kusion/pkg/util/signal"
39
41
"kusionstack.io/kusion/pkg/util/terminal"
40
42
)
41
43
@@ -188,12 +190,66 @@ func (o *DestroyOptions) Run() (err error) {
188
190
}
189
191
releaseCreated = true
190
192
193
+ errCh := make (chan error , 1 )
194
+ defer close (errCh )
195
+
196
+ // wait for the SIGTERM or SIGINT
197
+ go func () {
198
+ stopCh := signal .SetupSignalHandler ()
199
+ <- stopCh
200
+ errCh <- errors .New ("receive SIGTERM or SIGINT, exit cmd" )
201
+ }()
202
+
203
+ // run destroy command
204
+ go func () {
205
+ errCh <- o .run (rel , storage )
206
+ }()
207
+
208
+ if err = <- errCh ; err != nil {
209
+ rel .Phase = apiv1 .ReleasePhaseFailed
210
+ release .UpdateDestroyRelease (storage , rel )
211
+ } else {
212
+ rel .Phase = apiv1 .ReleasePhaseSucceeded
213
+ release .UpdateDestroyRelease (storage , rel )
214
+ }
215
+
216
+ return err
217
+ }
218
+
219
+ // run executes the delete command after release is created.
220
+ func (o * DestroyOptions ) run (rel * apiv1.Release , storage release.Storage ) (err error ) {
221
+ // update release to succeeded or failed
222
+ defer func () {
223
+ if err != nil {
224
+ rel .Phase = apiv1 .ReleasePhaseFailed
225
+ release .UpdateDestroyRelease (storage , rel )
226
+ } else {
227
+ rel .Phase = apiv1 .ReleasePhaseSucceeded
228
+ err = release .UpdateDestroyRelease (storage , rel )
229
+ }
230
+ }()
231
+
232
+ // set no style
233
+ if o .NoStyle {
234
+ pterm .DisableStyling ()
235
+ }
236
+
237
+ sp := o .UI .SpinnerPrinter
238
+ sp , _ = sp .Start (fmt .Sprintf ("Computing destroy changes in the Stack %s..." , o .RefStack .Name ))
239
+
191
240
// compute changes for preview
192
241
changes , err := o .preview (rel .Spec , rel .State , o .RefProject , o .RefStack , storage )
193
242
if err != nil {
243
+ if sp != nil {
244
+ sp .Fail ()
245
+ }
194
246
return
195
247
}
196
248
249
+ if sp != nil {
250
+ sp .Success ()
251
+ }
252
+
197
253
// preview
198
254
changes .Summary (os .Stdout , o .NoStyle )
199
255
@@ -203,16 +259,11 @@ func (o *DestroyOptions) Run() (err error) {
203
259
return nil
204
260
}
205
261
206
- // set no style
207
- if o .NoStyle {
208
- pterm .DisableStyling ()
209
- }
210
-
211
262
// prompt
212
263
if ! o .Yes {
213
264
for {
214
265
var input string
215
- input , err = prompt (o .UI )
266
+ input , err = prompt (o .UI , rel , storage )
216
267
if err != nil {
217
268
return
218
269
}
@@ -395,13 +446,19 @@ func (o *DestroyOptions) destroy(rel *apiv1.Release, changes *models.Changes, st
395
446
return updatedRel , nil
396
447
}
397
448
398
- func prompt (ui * terminal.UI ) (string , error ) {
449
+ func prompt (ui * terminal.UI , rel * apiv1. Release , storage release. Storage ) (string , error ) {
399
450
options := []string {"yes" , "details" , "no" }
400
451
input , err := ui .InteractiveSelectPrinter .
401
452
WithFilter (false ).
402
453
WithDefaultText (`Do you want to destroy these diffs?` ).
403
454
WithOptions (options ).
404
455
WithDefaultOption ("details" ).
456
+ // To gracefully exit if interrupted by SIGINT or SIGTERM.
457
+ WithOnInterruptFunc (func () {
458
+ rel .Phase = apiv1 .ReleasePhaseFailed
459
+ release .UpdateDestroyRelease (storage , rel )
460
+ os .Exit (1 )
461
+ }).
405
462
Show ()
406
463
if err != nil {
407
464
fmt .Printf ("Prompt failed: %v\n " , err )
0 commit comments