@@ -121,6 +121,7 @@ type DeleteOptions struct {
121
121
Quiet bool
122
122
WarnClusterScope bool
123
123
Raw string
124
+ Interactive bool
124
125
125
126
GracePeriod int
126
127
Timeout time.Duration
@@ -129,9 +130,11 @@ type DeleteOptions struct {
129
130
130
131
Output string
131
132
132
- DynamicClient dynamic.Interface
133
- Mapper meta.RESTMapper
134
- Result * resource.Result
133
+ DynamicClient dynamic.Interface
134
+ Mapper meta.RESTMapper
135
+ Result * resource.Result
136
+ PreviewResult * resource.Result
137
+ previewResourceMap map [cmdwait.ResourceLocation ]struct {}
135
138
136
139
genericiooptions.IOStreams
137
140
WarningPrinter * printers.WarningPrinter
@@ -197,8 +200,38 @@ func (o *DeleteOptions) Complete(f cmdutil.Factory, args []string, cmd *cobra.Co
197
200
return err
198
201
}
199
202
200
- if len (o .Raw ) == 0 {
201
- r := f .NewBuilder ().
203
+ // Set default WarningPrinter if not already set.
204
+ if o .WarningPrinter == nil {
205
+ o .WarningPrinter = printers .NewWarningPrinter (o .ErrOut , printers.WarningPrinterOptions {Color : term .AllowsColorOutput (o .ErrOut )})
206
+ }
207
+
208
+ if len (o .Raw ) != 0 {
209
+ return nil
210
+ }
211
+
212
+ r := f .NewBuilder ().
213
+ Unstructured ().
214
+ ContinueOnError ().
215
+ NamespaceParam (cmdNamespace ).DefaultNamespace ().
216
+ FilenameParam (enforceNamespace , & o .FilenameOptions ).
217
+ LabelSelectorParam (o .LabelSelector ).
218
+ FieldSelectorParam (o .FieldSelector ).
219
+ SelectAllParam (o .DeleteAll ).
220
+ AllNamespaces (o .DeleteAllNamespaces ).
221
+ ResourceTypeOrNameArgs (false , args ... ).RequireObject (false ).
222
+ Flatten ().
223
+ Do ()
224
+ err = r .Err ()
225
+ if err != nil {
226
+ return err
227
+ }
228
+ o .Result = r
229
+
230
+ if o .Interactive {
231
+ // preview result will be used to list resources for confirmation prior to actual delete.
232
+ // We can not use r as result object because it can only be used once. But we need to traverse
233
+ // twice. Parameters in preview result must be equal to genuine result.
234
+ previewr := f .NewBuilder ().
202
235
Unstructured ().
203
236
ContinueOnError ().
204
237
NamespaceParam (cmdNamespace ).DefaultNamespace ().
@@ -210,26 +243,22 @@ func (o *DeleteOptions) Complete(f cmdutil.Factory, args []string, cmd *cobra.Co
210
243
ResourceTypeOrNameArgs (false , args ... ).RequireObject (false ).
211
244
Flatten ().
212
245
Do ()
213
- err = r .Err ()
214
- if err != nil {
215
- return err
216
- }
217
- o .Result = r
218
-
219
- o .Mapper , err = f .ToRESTMapper ()
246
+ err = previewr .Err ()
220
247
if err != nil {
221
248
return err
222
249
}
250
+ o .PreviewResult = previewr
251
+ o .previewResourceMap = make (map [cmdwait.ResourceLocation ]struct {})
252
+ }
223
253
224
- o .DynamicClient , err = f .DynamicClient ()
225
- if err != nil {
226
- return err
227
- }
254
+ o .Mapper , err = f .ToRESTMapper ()
255
+ if err != nil {
256
+ return err
228
257
}
229
258
230
- // Set default WarningPrinter if not already set.
231
- if o . WarningPrinter = = nil {
232
- o . WarningPrinter = printers . NewWarningPrinter ( o . ErrOut , printers. WarningPrinterOptions { Color : term . AllowsColorOutput ( o . ErrOut )})
259
+ o . DynamicClient , err = f . DynamicClient ()
260
+ if err ! = nil {
261
+ return err
233
262
}
234
263
235
264
return nil
@@ -257,26 +286,31 @@ func (o *DeleteOptions) Validate() error {
257
286
return fmt .Errorf ("--force and --grace-period greater than 0 cannot be specified together" )
258
287
}
259
288
260
- if len (o .Raw ) > 0 {
261
- if len (o .FilenameOptions .Filenames ) > 1 {
262
- return fmt .Errorf ("--raw can only use a single local file or stdin" )
263
- } else if len (o .FilenameOptions .Filenames ) == 1 {
264
- if strings .Index (o .FilenameOptions .Filenames [0 ], "http://" ) == 0 || strings .Index (o .FilenameOptions .Filenames [0 ], "https://" ) == 0 {
265
- return fmt .Errorf ("--raw cannot read from a url" )
266
- }
267
- }
289
+ if len (o .Raw ) == 0 {
290
+ return nil
291
+ }
268
292
269
- if o .FilenameOptions . Recursive {
270
- return fmt .Errorf ("--raw and --recursive are mutually exclusive " )
271
- }
272
- if len (o .Output ) > 0 {
273
- return fmt .Errorf ("--raw and --output are mutually exclusive " )
274
- }
275
- if _ , err := url . ParseRequestURI (o .Raw ); err != nil {
276
- return fmt .Errorf ("--raw must be a valid URL path: %v" , err )
293
+ if o .Interactive {
294
+ return fmt .Errorf ("--interactive can not be used with --raw " )
295
+ }
296
+ if len (o .FilenameOptions . Filenames ) > 1 {
297
+ return fmt .Errorf ("--raw can only use a single local file or stdin " )
298
+ } else if len ( o . FilenameOptions . Filenames ) == 1 {
299
+ if strings . Index ( o . FilenameOptions . Filenames [ 0 ], "http://" ) == 0 || strings . Index (o .FilenameOptions . Filenames [ 0 ], "https://" ) == 0 {
300
+ return fmt .Errorf ("--raw cannot read from a url" )
277
301
}
278
302
}
279
303
304
+ if o .FilenameOptions .Recursive {
305
+ return fmt .Errorf ("--raw and --recursive are mutually exclusive" )
306
+ }
307
+ if len (o .Output ) > 0 {
308
+ return fmt .Errorf ("--raw and --output are mutually exclusive" )
309
+ }
310
+ if _ , err := url .ParseRequestURI (o .Raw ); err != nil {
311
+ return fmt .Errorf ("--raw must be a valid URL path: %v" , err )
312
+ }
313
+
280
314
return nil
281
315
}
282
316
@@ -291,6 +325,39 @@ func (o *DeleteOptions) RunDelete(f cmdutil.Factory) error {
291
325
}
292
326
return rawhttp .RawDelete (restClient , o .IOStreams , o .Raw , o .Filenames [0 ])
293
327
}
328
+
329
+ if o .Interactive {
330
+ previewInfos := []* resource.Info {}
331
+ if o .IgnoreNotFound {
332
+ o .PreviewResult = o .PreviewResult .IgnoreErrors (errors .IsNotFound )
333
+ }
334
+ err := o .PreviewResult .Visit (func (info * resource.Info , err error ) error {
335
+ if err != nil {
336
+ return err
337
+ }
338
+ previewInfos = append (previewInfos , info )
339
+ o .previewResourceMap [cmdwait.ResourceLocation {
340
+ GroupResource : info .Mapping .Resource .GroupResource (),
341
+ Namespace : info .Namespace ,
342
+ Name : info .Name ,
343
+ }] = struct {}{}
344
+
345
+ return nil
346
+ })
347
+ if err != nil {
348
+ return err
349
+ }
350
+ if len (previewInfos ) == 0 {
351
+ fmt .Fprintf (o .Out , "No resources found\n " )
352
+ return nil
353
+ }
354
+
355
+ if ! o .confirmation (previewInfos ) {
356
+ fmt .Fprintf (o .Out , "deletion is cancelled\n " )
357
+ return nil
358
+ }
359
+ }
360
+
294
361
return o .DeleteResult (o .Result )
295
362
}
296
363
@@ -306,6 +373,18 @@ func (o *DeleteOptions) DeleteResult(r *resource.Result) error {
306
373
if err != nil {
307
374
return err
308
375
}
376
+
377
+ if o .Interactive {
378
+ if _ , ok := o .previewResourceMap [cmdwait.ResourceLocation {
379
+ GroupResource : info .Mapping .Resource .GroupResource (),
380
+ Namespace : info .Namespace ,
381
+ Name : info .Name ,
382
+ }]; ! ok {
383
+ // resource not in the list of previewed resources based on resourceLocation
384
+ return nil
385
+ }
386
+ }
387
+
309
388
deletedInfos = append (deletedInfos , info )
310
389
found ++
311
390
@@ -440,3 +519,24 @@ func (o *DeleteOptions) PrintObj(info *resource.Info) {
440
519
// understandable output by default
441
520
fmt .Fprintf (o .Out , "%s \" %s\" %s\n " , kindString , info .Name , operation )
442
521
}
522
+
523
+ func (o * DeleteOptions ) confirmation (infos []* resource.Info ) bool {
524
+ fmt .Fprintf (o .Out , i18n .T ("You are about to delete the following %d resource(s):\n " ), len (infos ))
525
+ for _ , info := range infos {
526
+ groupKind := info .Mapping .GroupVersionKind
527
+ kindString := fmt .Sprintf ("%s.%s" , strings .ToLower (groupKind .Kind ), groupKind .Group )
528
+ if len (groupKind .Group ) == 0 {
529
+ kindString = strings .ToLower (groupKind .Kind )
530
+ }
531
+
532
+ fmt .Fprintf (o .Out , "%s/%s\n " , kindString , info .Name )
533
+ }
534
+ fmt .Fprintf (o .Out , i18n .T ("Do you want to continue?" )+ " (y/n): " )
535
+ var input string
536
+ _ , err := fmt .Fscan (o .In , & input )
537
+ if err != nil {
538
+ return false
539
+ }
540
+
541
+ return strings .EqualFold (input , "y" )
542
+ }
0 commit comments