Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add options to client.Delete() #94

Merged
merged 2 commits into from
Sep 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion pkg/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,18 @@ func (c *client) Update(ctx context.Context, obj runtime.Object) error {
}

// Delete implements client.Client
func (c *client) Delete(ctx context.Context, obj runtime.Object) error {
func (c *client) Delete(ctx context.Context, obj runtime.Object, opts ...DeleteOptionFunc) error {
o, err := c.cache.getObjMeta(obj)
if err != nil {
return err
}

deleteOpts := DeleteOptions{}
return o.Delete().
NamespaceIfScoped(o.GetNamespace(), o.isNamespaced()).
Resource(o.resource()).
Name(o.GetName()).
Body(deleteOpts.ApplyOptions(opts).AsDeleteOptions()).
Do().
Error()
}
Expand Down
46 changes: 46 additions & 0 deletions pkg/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,52 @@ var _ = Describe("Client", func() {
})
})

Describe("DeleteOptions", func() {
It("should allow setting GracePeriodSeconds", func() {
do := &client.DeleteOptions{}
client.GracePeriodSeconds(1)(do)
gp := int64(1)
Expect(do.AsDeleteOptions().GracePeriodSeconds).To(Equal(&gp))
})

It("should allow setting Precondition", func() {
do := &client.DeleteOptions{}
pc := metav1.NewUIDPreconditions("uid")
client.Preconditions(pc)(do)
Expect(do.AsDeleteOptions().Preconditions).To(Equal(pc))
Expect(do.Preconditions).To(Equal(pc))
})

It("should allow setting PropagationPolicy", func() {
do := &client.DeleteOptions{}
client.PropagationPolicy(metav1.DeletePropagationForeground)(do)
dp := metav1.DeletePropagationForeground
Expect(do.AsDeleteOptions().PropagationPolicy).To(Equal(&dp))
})

It("should produce empty metav1.DeleteOptions if nil", func() {
var do *client.DeleteOptions
Expect(do.AsDeleteOptions()).To(Equal(&metav1.DeleteOptions{}))
do = &client.DeleteOptions{}
Expect(do.AsDeleteOptions()).To(Equal(&metav1.DeleteOptions{}))
})

It("should merge multiple options together", func() {
gp := int64(1)
pc := metav1.NewUIDPreconditions("uid")
dp := metav1.DeletePropagationForeground
do := &client.DeleteOptions{}
do.ApplyOptions([]client.DeleteOptionFunc{
client.GracePeriodSeconds(gp),
client.Preconditions(pc),
client.PropagationPolicy(dp),
})
Expect(do.GracePeriodSeconds).To(Equal(&gp))
Expect(do.Preconditions).To(Equal(pc))
Expect(do.PropagationPolicy).To(Equal(&dp))
})
})

Describe("ListOptions", func() {
It("should be able to set a LabelSelector", func() {
lo := &client.ListOptions{}
Expand Down
3 changes: 2 additions & 1 deletion pkg/client/fake/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func (c *fakeClient) Create(ctx context.Context, obj runtime.Object) error {
return c.tracker.Create(gvr, obj, accessor.GetNamespace())
}

func (c *fakeClient) Delete(ctx context.Context, obj runtime.Object) error {
func (c *fakeClient) Delete(ctx context.Context, obj runtime.Object, opts ...client.DeleteOptionFunc) error {
gvr, err := getGVRFromObject(obj)
if err != nil {
return err
Expand All @@ -114,6 +114,7 @@ func (c *fakeClient) Delete(ctx context.Context, obj runtime.Object) error {
if err != nil {
return err
}
//TODO: implement propagation
return c.tracker.Delete(gvr, accessor.GetNamespace(), accessor.GetName())
}

Expand Down
84 changes: 83 additions & 1 deletion pkg/client/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ type Writer interface {
Create(ctx context.Context, obj runtime.Object) error

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

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

// DeleteOptions contains options for delete requests. It's generally a subset
// of metav1.DeleteOptions.
type DeleteOptions struct {
// GracePeriodSeconds is the duration in seconds before the object should be
// deleted. Value must be non-negative integer. The value zero indicates
// delete immediately. If this value is nil, the default grace period for the
// specified type will be used.
GracePeriodSeconds *int64

// Preconditions must be fulfilled before a deletion is carried out. If not
// possible, a 409 Conflict status will be returned.
Preconditions *metav1.Preconditions

// PropagationPolicy determined whether and how garbage collection will be
// performed. Either this field or OrphanDependents may be set, but not both.
// The default policy is decided by the existing finalizer set in the
// metadata.finalizers and the resource-specific default policy.
// Acceptable values are: 'Orphan' - orphan the dependents; 'Background' -
// allow the garbage collector to delete the dependents in the background;
// 'Foreground' - a cascading policy that deletes all dependents in the
// foreground.
PropagationPolicy *metav1.DeletionPropagation

// Raw represents raw DeleteOptions, as passed to the API server.
Raw *metav1.DeleteOptions
}

// AsDeleteOptions returns these options as a metav1.DeleteOptions.
// This may mutate the Raw field.
func (o *DeleteOptions) AsDeleteOptions() *metav1.DeleteOptions {

if o == nil {
return &metav1.DeleteOptions{}
}
if o.Raw == nil {
o.Raw = &metav1.DeleteOptions{}
}

o.Raw.GracePeriodSeconds = o.GracePeriodSeconds
o.Raw.Preconditions = o.Preconditions
o.Raw.PropagationPolicy = o.PropagationPolicy
return o.Raw
}

// ApplyOptions executes the given DeleteOptionFuncs and returns the mutated
// DeleteOptions.
func (o *DeleteOptions) ApplyOptions(optFuncs []DeleteOptionFunc) *DeleteOptions {
for _, optFunc := range optFuncs {
optFunc(o)
}
return o
}

// DeleteOptionFunc is a function that mutates a DeleteOptions struct. It implements
// the functional options pattern. See
// https://github.com/tmrts/go-patterns/blob/master/idiom/functional-options.md.
type DeleteOptionFunc func(*DeleteOptions)

// GracePeriodSeconds is a functional option that sets the GracePeriodSeconds
// field of a DeleteOptions struct.
func GracePeriodSeconds(gp int64) DeleteOptionFunc {
return func(opts *DeleteOptions) {
opts.GracePeriodSeconds = &gp
}
}

// Preconditions is a functional option that sets the Preconditions field of a
// DeleteOptions struct.
func Preconditions(p *metav1.Preconditions) DeleteOptionFunc {
return func(opts *DeleteOptions) {
opts.Preconditions = p
}
}

// PropagationPolicy is a functional option that sets the PropagationPolicy
// field of a DeleteOptions struct.
func PropagationPolicy(p metav1.DeletionPropagation) DeleteOptionFunc {
return func(opts *DeleteOptions) {
opts.PropagationPolicy = &p
}
}

// ListOptions contains options for limitting or filtering results.
// It's generally a subset of metav1.ListOptions, with support for
// pre-parsed selectors (since generally, selectors will be executed
Expand Down