Skip to content

Commit 776bc13

Browse files
committed
Add options to client.Delete
Allows Delete requests to carry options like GracePeriodSeconds, Preconditions, and PropagationPolicy. To use the default options, call Delete with the same signature as before: client.Delete(context.TODO(), obj) Delete options are passed to the request using the functional options pattern. This Delete call sets a GracePeriodSeconds: client.Delete(context.TODO(), obj, client.GracePeriodSeconds(1)) Multiple options can be set: client.Delete(context.TODO(), obj, client.GracePeriodSeconds(1), client.PropagationPolicy(metav1.DeletePropagationForeground)) The fake client doesn't yet implement delete options like propagation, so keep that in mind when writing tests.
1 parent c5268a8 commit 776bc13

File tree

4 files changed

+135
-3
lines changed

4 files changed

+135
-3
lines changed

pkg/client/client.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,15 +111,18 @@ func (c *client) Update(ctx context.Context, obj runtime.Object) error {
111111
}
112112

113113
// Delete implements client.Client
114-
func (c *client) Delete(ctx context.Context, obj runtime.Object) error {
114+
func (c *client) Delete(ctx context.Context, obj runtime.Object, opts ...DeleteOptionFunc) error {
115115
o, err := c.cache.getObjMeta(obj)
116116
if err != nil {
117117
return err
118118
}
119+
120+
deleteOpts := DeleteOptions{}
119121
return o.Delete().
120122
NamespaceIfScoped(o.GetNamespace(), o.isNamespaced()).
121123
Resource(o.resource()).
122124
Name(o.GetName()).
125+
Body(deleteOpts.ApplyOptions(opts).AsDeleteOptions()).
123126
Do().
124127
Error()
125128
}

pkg/client/client_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,52 @@ var _ = Describe("Client", func() {
978978
})
979979
})
980980

981+
Describe("DeleteOptions", func() {
982+
It("should allow setting GracePeriodSeconds", func() {
983+
do := &client.DeleteOptions{}
984+
client.GracePeriodSeconds(1)(do)
985+
gp := int64(1)
986+
Expect(do.AsDeleteOptions().GracePeriodSeconds).To(Equal(&gp))
987+
})
988+
989+
It("should allow setting Precondition", func() {
990+
do := &client.DeleteOptions{}
991+
pc := metav1.NewUIDPreconditions("uid")
992+
client.Preconditions(pc)(do)
993+
Expect(do.AsDeleteOptions().Preconditions).To(Equal(pc))
994+
Expect(do.Preconditions).To(Equal(pc))
995+
})
996+
997+
It("should allow setting PropagationPolicy", func() {
998+
do := &client.DeleteOptions{}
999+
client.PropagationPolicy(metav1.DeletePropagationForeground)(do)
1000+
dp := metav1.DeletePropagationForeground
1001+
Expect(do.AsDeleteOptions().PropagationPolicy).To(Equal(&dp))
1002+
})
1003+
1004+
It("should produce empty metav1.DeleteOptions if nil", func() {
1005+
var do *client.DeleteOptions
1006+
Expect(do.AsDeleteOptions()).To(Equal(&metav1.DeleteOptions{}))
1007+
do = &client.DeleteOptions{}
1008+
Expect(do.AsDeleteOptions()).To(Equal(&metav1.DeleteOptions{}))
1009+
})
1010+
1011+
It("should merge multiple options together", func() {
1012+
gp := int64(1)
1013+
pc := metav1.NewUIDPreconditions("uid")
1014+
dp := metav1.DeletePropagationForeground
1015+
do := &client.DeleteOptions{}
1016+
do.ApplyOptions([]client.DeleteOptionFunc{
1017+
client.GracePeriodSeconds(gp),
1018+
client.Preconditions(pc),
1019+
client.PropagationPolicy(dp),
1020+
})
1021+
Expect(do.GracePeriodSeconds).To(Equal(&gp))
1022+
Expect(do.Preconditions).To(Equal(pc))
1023+
Expect(do.PropagationPolicy).To(Equal(&dp))
1024+
})
1025+
})
1026+
9811027
Describe("ListOptions", func() {
9821028
It("should be able to set a LabelSelector", func() {
9831029
lo := &client.ListOptions{}

pkg/client/fake/client.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ func (c *fakeClient) Create(ctx context.Context, obj runtime.Object) error {
105105
return c.tracker.Create(gvr, obj, accessor.GetNamespace())
106106
}
107107

108-
func (c *fakeClient) Delete(ctx context.Context, obj runtime.Object) error {
108+
func (c *fakeClient) Delete(ctx context.Context, obj runtime.Object, opts ...client.DeleteOptionFunc) error {
109109
gvr, err := getGVRFromObject(obj)
110110
if err != nil {
111111
return err
@@ -114,6 +114,7 @@ func (c *fakeClient) Delete(ctx context.Context, obj runtime.Object) error {
114114
if err != nil {
115115
return err
116116
}
117+
//TODO: implement propagation
117118
return c.tracker.Delete(gvr, accessor.GetNamespace(), accessor.GetName())
118119
}
119120

pkg/client/interfaces.go

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ type Writer interface {
5050
Create(ctx context.Context, obj runtime.Object) error
5151

5252
// Delete deletes the given obj from Kubernetes cluster.
53-
Delete(ctx context.Context, obj runtime.Object) error
53+
Delete(ctx context.Context, obj runtime.Object, opts ...DeleteOptionFunc) error
5454

5555
// Update updates the given obj in the Kubernetes cluster. obj must be a
5656
// struct pointer so that obj can be updated with the content returned by the Server.
@@ -93,6 +93,88 @@ type FieldIndexer interface {
9393
IndexField(obj runtime.Object, field string, extractValue IndexerFunc) error
9494
}
9595

96+
// DeleteOptions contains options for delete requests. It's generally a subset
97+
// of metav1.DeleteOptions.
98+
type DeleteOptions struct {
99+
// GracePeriodSeconds is the duration in seconds before the object should be
100+
// deleted. Value must be non-negative integer. The value zero indicates
101+
// delete immediately. If this value is nil, the default grace period for the
102+
// specified type will be used.
103+
GracePeriodSeconds *int64
104+
105+
// Preconditions must be fulfilled before a deletion is carried out. If not
106+
// possible, a 409 Conflict status will be returned.
107+
Preconditions *metav1.Preconditions
108+
109+
// PropagationPolicy determined whether and how garbage collection will be
110+
// performed. Either this field or OrphanDependents may be set, but not both.
111+
// The default policy is decided by the existing finalizer set in the
112+
// metadata.finalizers and the resource-specific default policy.
113+
// Acceptable values are: 'Orphan' - orphan the dependents; 'Background' -
114+
// allow the garbage collector to delete the dependents in the background;
115+
// 'Foreground' - a cascading policy that deletes all dependents in the
116+
// foreground.
117+
PropagationPolicy *metav1.DeletionPropagation
118+
119+
// Raw represents raw DeleteOptions, as passed to the API server.
120+
Raw *metav1.DeleteOptions
121+
}
122+
123+
// AsDeleteOptions returns these options as a metav1.DeleteOptions.
124+
// This may mutate the Raw field.
125+
func (o *DeleteOptions) AsDeleteOptions() *metav1.DeleteOptions {
126+
127+
if o == nil {
128+
return &metav1.DeleteOptions{}
129+
}
130+
if o.Raw == nil {
131+
o.Raw = &metav1.DeleteOptions{}
132+
}
133+
134+
o.Raw.GracePeriodSeconds = o.GracePeriodSeconds
135+
o.Raw.Preconditions = o.Preconditions
136+
o.Raw.PropagationPolicy = o.PropagationPolicy
137+
return o.Raw
138+
}
139+
140+
// ApplyOptions executes the given DeleteOptionFuncs and returns the mutated
141+
// DeleteOptions.
142+
func (o *DeleteOptions) ApplyOptions(optFuncs []DeleteOptionFunc) *DeleteOptions {
143+
for _, optFunc := range optFuncs {
144+
optFunc(o)
145+
}
146+
return o
147+
}
148+
149+
// DeleteOptionFunc is a function that mutates a DeleteOptions struct. It implements
150+
// the functional options pattern. See
151+
// https://github.com/tmrts/go-patterns/blob/master/idiom/functional-options.md.
152+
type DeleteOptionFunc func(*DeleteOptions)
153+
154+
// GracePeriodSeconds is a functional option that sets the GracePeriodSeconds
155+
// field of a DeleteOptions struct.
156+
func GracePeriodSeconds(gp int64) DeleteOptionFunc {
157+
return func(opts *DeleteOptions) {
158+
opts.GracePeriodSeconds = &gp
159+
}
160+
}
161+
162+
// Preconditions is a functional option that sets the Preconditions field of a
163+
// DeleteOptions struct.
164+
func Preconditions(p *metav1.Preconditions) DeleteOptionFunc {
165+
return func(opts *DeleteOptions) {
166+
opts.Preconditions = p
167+
}
168+
}
169+
170+
// PropagationPolicy is a functional option that sets the PropagationPolicy
171+
// field of a DeleteOptions struct.
172+
func PropagationPolicy(p metav1.DeletionPropagation) DeleteOptionFunc {
173+
return func(opts *DeleteOptions) {
174+
opts.PropagationPolicy = &p
175+
}
176+
}
177+
96178
// ListOptions contains options for limitting or filtering results.
97179
// It's generally a subset of metav1.ListOptions, with support for
98180
// pre-parsed selectors (since generally, selectors will be executed

0 commit comments

Comments
 (0)