Skip to content

Commit d9b576d

Browse files
authored
Merge pull request kubernetes#93384 from zhouya0/support_kubectl_delete_foreground
Support kubectl delete orphan/foreground/background options
2 parents 63d4a03 + 383b5f6 commit d9b576d

File tree

12 files changed

+170
-104
lines changed

12 files changed

+170
-104
lines changed

staging/src/k8s.io/kubectl/pkg/cmd/apply/apply.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,11 @@ func (o *ApplyOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
244244
return err
245245
}
246246

247-
o.DeleteOptions = o.DeleteFlags.ToOptions(o.DynamicClient, o.IOStreams)
247+
o.DeleteOptions, err = o.DeleteFlags.ToOptions(o.DynamicClient, o.IOStreams)
248+
if err != nil {
249+
return err
250+
}
251+
248252
err = o.DeleteOptions.FilenameOptions.RequireFilenameOrKustomize()
249253
if err != nil {
250254
return err

staging/src/k8s.io/kubectl/pkg/cmd/apply/patcher.go

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/jonboulle/clockwork"
2626
"k8s.io/apimachinery/pkg/api/errors"
2727
"k8s.io/apimachinery/pkg/api/meta"
28+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2829
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2930
"k8s.io/apimachinery/pkg/runtime"
3031
"k8s.io/apimachinery/pkg/types"
@@ -57,10 +58,10 @@ type Patcher struct {
5758
Overwrite bool
5859
BackOff clockwork.Clock
5960

60-
Force bool
61-
Cascade bool
62-
Timeout time.Duration
63-
GracePeriod int
61+
Force bool
62+
CascadingStrategy metav1.DeletionPropagation
63+
Timeout time.Duration
64+
GracePeriod int
6465

6566
// If set, forces the patch against a specific resourceVersion
6667
ResourceVersion *string
@@ -78,21 +79,21 @@ func newPatcher(o *ApplyOptions, info *resource.Info, helper *resource.Helper) (
7879
}
7980

8081
return &Patcher{
81-
Mapping: info.Mapping,
82-
Helper: helper,
83-
Overwrite: o.Overwrite,
84-
BackOff: clockwork.NewRealClock(),
85-
Force: o.DeleteOptions.ForceDeletion,
86-
Cascade: o.DeleteOptions.Cascade,
87-
Timeout: o.DeleteOptions.Timeout,
88-
GracePeriod: o.DeleteOptions.GracePeriod,
89-
OpenapiSchema: openapiSchema,
90-
Retries: maxPatchRetry,
82+
Mapping: info.Mapping,
83+
Helper: helper,
84+
Overwrite: o.Overwrite,
85+
BackOff: clockwork.NewRealClock(),
86+
Force: o.DeleteOptions.ForceDeletion,
87+
CascadingStrategy: o.DeleteOptions.CascadingStrategy,
88+
Timeout: o.DeleteOptions.Timeout,
89+
GracePeriod: o.DeleteOptions.GracePeriod,
90+
OpenapiSchema: openapiSchema,
91+
Retries: maxPatchRetry,
9192
}, nil
9293
}
9394

9495
func (p *Patcher) delete(namespace, name string) error {
95-
options := asDeleteOptions(p.Cascade, p.GracePeriod)
96+
options := asDeleteOptions(p.CascadingStrategy, p.GracePeriod)
9697
_, err := p.Helper.DeleteWithOptions(namespace, name, &options)
9798
return err
9899
}

staging/src/k8s.io/kubectl/pkg/cmd/apply/prune.go

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ type pruner struct {
4141
labelSelector string
4242
fieldSelector string
4343

44-
cascade bool
45-
dryRunStrategy cmdutil.DryRunStrategy
46-
gracePeriod int
44+
cascadingStrategy metav1.DeletionPropagation
45+
dryRunStrategy cmdutil.DryRunStrategy
46+
gracePeriod int
4747

4848
toPrinter func(string) (printers.ResourcePrinter, error)
4949

@@ -59,9 +59,9 @@ func newPruner(o *ApplyOptions) pruner {
5959
visitedUids: o.VisitedUids,
6060
visitedNamespaces: o.VisitedNamespaces,
6161

62-
cascade: o.DeleteOptions.Cascade,
63-
dryRunStrategy: o.DryRunStrategy,
64-
gracePeriod: o.DeleteOptions.GracePeriod,
62+
cascadingStrategy: o.DeleteOptions.CascadingStrategy,
63+
dryRunStrategy: o.DryRunStrategy,
64+
gracePeriod: o.DeleteOptions.GracePeriod,
6565

6666
toPrinter: o.ToPrinter,
6767

@@ -139,27 +139,23 @@ func (p *pruner) prune(namespace string, mapping *meta.RESTMapping) error {
139139
}
140140

141141
func (p *pruner) delete(namespace, name string, mapping *meta.RESTMapping) error {
142-
return runDelete(namespace, name, mapping, p.dynamicClient, p.cascade, p.gracePeriod, p.dryRunStrategy == cmdutil.DryRunServer)
142+
return runDelete(namespace, name, mapping, p.dynamicClient, p.cascadingStrategy, p.gracePeriod, p.dryRunStrategy == cmdutil.DryRunServer)
143143
}
144144

145-
func runDelete(namespace, name string, mapping *meta.RESTMapping, c dynamic.Interface, cascade bool, gracePeriod int, serverDryRun bool) error {
146-
options := asDeleteOptions(cascade, gracePeriod)
145+
func runDelete(namespace, name string, mapping *meta.RESTMapping, c dynamic.Interface, cascadingStrategy metav1.DeletionPropagation, gracePeriod int, serverDryRun bool) error {
146+
options := asDeleteOptions(cascadingStrategy, gracePeriod)
147147
if serverDryRun {
148148
options.DryRun = []string{metav1.DryRunAll}
149149
}
150150
return c.Resource(mapping.Resource).Namespace(namespace).Delete(context.TODO(), name, options)
151151
}
152152

153-
func asDeleteOptions(cascade bool, gracePeriod int) metav1.DeleteOptions {
153+
func asDeleteOptions(cascadingStrategy metav1.DeletionPropagation, gracePeriod int) metav1.DeleteOptions {
154154
options := metav1.DeleteOptions{}
155155
if gracePeriod >= 0 {
156156
options = *metav1.NewDeleteOptions(int64(gracePeriod))
157157
}
158-
policy := metav1.DeletePropagationForeground
159-
if !cascade {
160-
policy = metav1.DeletePropagationOrphan
161-
}
162-
options.PropagationPolicy = &policy
158+
options.PropagationPolicy = &cascadingStrategy
163159
return options
164160
}
165161

staging/src/k8s.io/kubectl/pkg/cmd/delete/delete.go

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ type DeleteOptions struct {
102102
FieldSelector string
103103
DeleteAll bool
104104
DeleteAllNamespaces bool
105+
CascadingStrategy metav1.DeletionPropagation
105106
IgnoreNotFound bool
106-
Cascade bool
107107
DeleteNow bool
108108
ForceDeletion bool
109109
WaitForDeletion bool
@@ -136,7 +136,8 @@ func NewCmdDelete(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra
136136
Long: deleteLong,
137137
Example: deleteExample,
138138
Run: func(cmd *cobra.Command, args []string) {
139-
o := deleteFlags.ToOptions(nil, streams)
139+
o, err := deleteFlags.ToOptions(nil, streams)
140+
cmdutil.CheckErr(err)
140141
cmdutil.CheckErr(o.Complete(f, args, cmd))
141142
cmdutil.CheckErr(o.Validate())
142143
cmdutil.CheckErr(o.RunDelete(f))
@@ -301,11 +302,7 @@ func (o *DeleteOptions) DeleteResult(r *resource.Result) error {
301302
if o.GracePeriod >= 0 {
302303
options = metav1.NewDeleteOptions(int64(o.GracePeriod))
303304
}
304-
policy := metav1.DeletePropagationBackground
305-
if !o.Cascade {
306-
policy = metav1.DeletePropagationOrphan
307-
}
308-
options.PropagationPolicy = &policy
305+
options.PropagationPolicy = &o.CascadingStrategy
309306

310307
if warnClusterScope && info.Mapping.Scope.Name() == meta.RESTScopeNameRoot {
311308
fmt.Fprintf(o.ErrOut, "warning: deleting cluster-scoped resources, not scoped to the provided namespace\n")

staging/src/k8s.io/kubectl/pkg/cmd/delete/delete_flags.go

Lines changed: 60 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,16 @@ limitations under the License.
1717
package delete
1818

1919
import (
20+
"fmt"
21+
"strconv"
2022
"time"
2123

2224
"github.com/spf13/cobra"
2325

26+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2427
"k8s.io/cli-runtime/pkg/genericclioptions"
2528
"k8s.io/client-go/dynamic"
29+
"k8s.io/klog/v2"
2630
)
2731

2832
// DeleteFlags composes common printer flag structs
@@ -32,20 +36,20 @@ type DeleteFlags struct {
3236
LabelSelector *string
3337
FieldSelector *string
3438

35-
All *bool
36-
AllNamespaces *bool
37-
Cascade *bool
38-
Force *bool
39-
GracePeriod *int
40-
IgnoreNotFound *bool
41-
Now *bool
42-
Timeout *time.Duration
43-
Wait *bool
44-
Output *string
45-
Raw *string
39+
All *bool
40+
AllNamespaces *bool
41+
CascadingStrategy *string
42+
Force *bool
43+
GracePeriod *int
44+
IgnoreNotFound *bool
45+
Now *bool
46+
Timeout *time.Duration
47+
Wait *bool
48+
Output *string
49+
Raw *string
4650
}
4751

48-
func (f *DeleteFlags) ToOptions(dynamicClient dynamic.Interface, streams genericclioptions.IOStreams) *DeleteOptions {
52+
func (f *DeleteFlags) ToOptions(dynamicClient dynamic.Interface, streams genericclioptions.IOStreams) (*DeleteOptions, error) {
4953
options := &DeleteOptions{
5054
DynamicClient: dynamicClient,
5155
IOStreams: streams,
@@ -73,8 +77,12 @@ func (f *DeleteFlags) ToOptions(dynamicClient dynamic.Interface, streams generic
7377
if f.AllNamespaces != nil {
7478
options.DeleteAllNamespaces = *f.AllNamespaces
7579
}
76-
if f.Cascade != nil {
77-
options.Cascade = *f.Cascade
80+
if f.CascadingStrategy != nil {
81+
var err error
82+
options.CascadingStrategy, err = getCascadingStrategy(*f.CascadingStrategy)
83+
if err != nil {
84+
return nil, err
85+
}
7886
}
7987
if f.Force != nil {
8088
options.ForceDeletion = *f.Force
@@ -98,7 +106,7 @@ func (f *DeleteFlags) ToOptions(dynamicClient dynamic.Interface, streams generic
98106
options.Raw = *f.Raw
99107
}
100108

101-
return options
109+
return options, nil
102110
}
103111

104112
func (f *DeleteFlags) AddFlags(cmd *cobra.Command) {
@@ -118,8 +126,13 @@ func (f *DeleteFlags) AddFlags(cmd *cobra.Command) {
118126
if f.Force != nil {
119127
cmd.Flags().BoolVar(f.Force, "force", *f.Force, "If true, immediately remove resources from API and bypass graceful deletion. Note that immediate deletion of some resources may result in inconsistency or data loss and requires confirmation.")
120128
}
121-
if f.Cascade != nil {
122-
cmd.Flags().BoolVar(f.Cascade, "cascade", *f.Cascade, "If true, run background cascade deletion of the resources managed by this resource (e.g. Pods created by a ReplicationController). Default true.")
129+
if f.CascadingStrategy != nil {
130+
cmd.Flags().StringVar(
131+
f.CascadingStrategy,
132+
"cascade",
133+
*f.CascadingStrategy,
134+
`Must be "background", "orphan", or "foreground". Selects the deletion cascading strategy for the dependents (e.g. Pods created by a ReplicationController). Defaults to background.`)
135+
cmd.Flags().Lookup("cascade").NoOptDefVal = "background"
123136
}
124137
if f.Now != nil {
125138
cmd.Flags().BoolVar(f.Now, "now", *f.Now, "If true, resources are signaled for immediate shutdown (same as --grace-period=1).")
@@ -146,7 +159,7 @@ func (f *DeleteFlags) AddFlags(cmd *cobra.Command) {
146159

147160
// NewDeleteCommandFlags provides default flags and values for use with the "delete" command
148161
func NewDeleteCommandFlags(usage string) *DeleteFlags {
149-
cascade := true
162+
cascadingStrategy := "background"
150163
gracePeriod := -1
151164

152165
// setup command defaults
@@ -172,8 +185,8 @@ func NewDeleteCommandFlags(usage string) *DeleteFlags {
172185
LabelSelector: &labelSelector,
173186
FieldSelector: &fieldSelector,
174187

175-
Cascade: &cascade,
176-
GracePeriod: &gracePeriod,
188+
CascadingStrategy: &cascadingStrategy,
189+
GracePeriod: &gracePeriod,
177190

178191
All: &all,
179192
AllNamespaces: &allNamespaces,
@@ -189,7 +202,7 @@ func NewDeleteCommandFlags(usage string) *DeleteFlags {
189202

190203
// NewDeleteFlags provides default flags and values for use in commands outside of "delete"
191204
func NewDeleteFlags(usage string) *DeleteFlags {
192-
cascade := true
205+
cascadingStrategy := "background"
193206
gracePeriod := -1
194207

195208
force := false
@@ -203,12 +216,36 @@ func NewDeleteFlags(usage string) *DeleteFlags {
203216
return &DeleteFlags{
204217
FileNameFlags: &genericclioptions.FileNameFlags{Usage: usage, Filenames: &filenames, Kustomize: &kustomize, Recursive: &recursive},
205218

206-
Cascade: &cascade,
207-
GracePeriod: &gracePeriod,
219+
CascadingStrategy: &cascadingStrategy,
220+
GracePeriod: &gracePeriod,
208221

209222
// add non-defaults
210223
Force: &force,
211224
Timeout: &timeout,
212225
Wait: &wait,
213226
}
214227
}
228+
229+
func getCascadingStrategy(cascadingFlag string) (metav1.DeletionPropagation, error) {
230+
b, err := strconv.ParseBool(cascadingFlag)
231+
// The flag is not a boolean
232+
if err != nil {
233+
switch cascadingFlag {
234+
case "orphan":
235+
return metav1.DeletePropagationOrphan, nil
236+
case "foreground":
237+
return metav1.DeletePropagationForeground, nil
238+
case "background":
239+
return metav1.DeletePropagationBackground, nil
240+
default:
241+
return metav1.DeletePropagationBackground, fmt.Errorf(`Invalid cascade value (%v). Must be "background", "foreground", or "orphan".`, cascadingFlag)
242+
}
243+
}
244+
// The flag was a boolean
245+
if b {
246+
klog.Warningf(`--cascade=%v is deprecated (boolean value) and can be replaced with --cascade=%s.`, cascadingFlag, "background")
247+
return metav1.DeletePropagationBackground, nil
248+
}
249+
klog.Warningf(`--cascade=%v is deprecated (boolean value) and can be replaced with --cascade=%s.`, cascadingFlag, "orphan")
250+
return metav1.DeletePropagationOrphan, nil
251+
}

0 commit comments

Comments
 (0)