Skip to content

Commit 68d92bb

Browse files
committed
Switch to interface-based options
These behave more-or-less like functional options, except that a given option can be applied to more than on option type, so we can deprecate the 3 different dryrunall variants. Things with arguments generally become type aliases, with the exception of MatchingField, which gets deprecated in favor of MatchFields (a type alias to fields.Set).
1 parent 72ab3fe commit 68d92bb

13 files changed

+230
-277
lines changed

pkg/cache/informer_cache.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func (ip *informerCache) Get(ctx context.Context, key client.ObjectKey, out runt
5858
}
5959

6060
// List implements Reader
61-
func (ip *informerCache) List(ctx context.Context, out runtime.Object, opts ...client.ListOptionFunc) error {
61+
func (ip *informerCache) List(ctx context.Context, out runtime.Object, opts ...client.ListOption) error {
6262
gvk, err := apiutil.GVKForObject(out, ip.Scheme)
6363
if err != nil {
6464
return err

pkg/cache/informertest/fake_cache.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,6 @@ func (c *FakeInformers) Get(ctx context.Context, key client.ObjectKey, obj runti
136136
}
137137

138138
// List implements Cache
139-
func (c *FakeInformers) List(ctx context.Context, list runtime.Object, opts ...client.ListOptionFunc) error {
139+
func (c *FakeInformers) List(ctx context.Context, list runtime.Object, opts ...client.ListOption) error {
140140
return nil
141141
}

pkg/cache/internal/cache_reader.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ func (c *CacheReader) Get(_ context.Context, key client.ObjectKey, out runtime.O
8888
}
8989

9090
// List lists items out of the indexer and writes them to out
91-
func (c *CacheReader) List(_ context.Context, out runtime.Object, opts ...client.ListOptionFunc) error {
91+
func (c *CacheReader) List(_ context.Context, out runtime.Object, opts ...client.ListOption) error {
9292
var objs []interface{}
9393
var err error
9494

pkg/cache/multi_namespace_cache.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ func (c *multiNamespaceCache) Get(ctx context.Context, key client.ObjectKey, obj
133133
}
134134

135135
// List multi namespace cache will get all the objects in the namespaces that the cache is watching if asked for all namespaces.
136-
func (c *multiNamespaceCache) List(ctx context.Context, list runtime.Object, opts ...client.ListOptionFunc) error {
136+
func (c *multiNamespaceCache) List(ctx context.Context, list runtime.Object, opts ...client.ListOption) error {
137137
listOpts := client.ListOptions{}
138138
listOpts.ApplyOptions(opts)
139139
if listOpts.Namespace != corev1.NamespaceAll {

pkg/client/client.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ type client struct {
104104
}
105105

106106
// Create implements client.Client
107-
func (c *client) Create(ctx context.Context, obj runtime.Object, opts ...CreateOptionFunc) error {
107+
func (c *client) Create(ctx context.Context, obj runtime.Object, opts ...CreateOption) error {
108108
_, ok := obj.(*unstructured.Unstructured)
109109
if ok {
110110
return c.unstructuredClient.Create(ctx, obj, opts...)
@@ -113,7 +113,7 @@ func (c *client) Create(ctx context.Context, obj runtime.Object, opts ...CreateO
113113
}
114114

115115
// Update implements client.Client
116-
func (c *client) Update(ctx context.Context, obj runtime.Object, opts ...UpdateOptionFunc) error {
116+
func (c *client) Update(ctx context.Context, obj runtime.Object, opts ...UpdateOption) error {
117117
_, ok := obj.(*unstructured.Unstructured)
118118
if ok {
119119
return c.unstructuredClient.Update(ctx, obj, opts...)
@@ -122,7 +122,7 @@ func (c *client) Update(ctx context.Context, obj runtime.Object, opts ...UpdateO
122122
}
123123

124124
// Delete implements client.Client
125-
func (c *client) Delete(ctx context.Context, obj runtime.Object, opts ...DeleteOptionFunc) error {
125+
func (c *client) Delete(ctx context.Context, obj runtime.Object, opts ...DeleteOption) error {
126126
_, ok := obj.(*unstructured.Unstructured)
127127
if ok {
128128
return c.unstructuredClient.Delete(ctx, obj, opts...)
@@ -131,7 +131,7 @@ func (c *client) Delete(ctx context.Context, obj runtime.Object, opts ...DeleteO
131131
}
132132

133133
// Patch implements client.Client
134-
func (c *client) Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOptionFunc) error {
134+
func (c *client) Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOption) error {
135135
_, ok := obj.(*unstructured.Unstructured)
136136
if ok {
137137
return c.unstructuredClient.Patch(ctx, obj, patch, opts...)
@@ -149,7 +149,7 @@ func (c *client) Get(ctx context.Context, key ObjectKey, obj runtime.Object) err
149149
}
150150

151151
// List implements client.Client
152-
func (c *client) List(ctx context.Context, obj runtime.Object, opts ...ListOptionFunc) error {
152+
func (c *client) List(ctx context.Context, obj runtime.Object, opts ...ListOption) error {
153153
_, ok := obj.(*unstructured.UnstructuredList)
154154
if ok {
155155
return c.unstructuredClient.List(ctx, obj, opts...)
@@ -171,7 +171,7 @@ type statusWriter struct {
171171
var _ StatusWriter = &statusWriter{}
172172

173173
// Update implements client.StatusWriter
174-
func (sw *statusWriter) Update(ctx context.Context, obj runtime.Object, opts ...UpdateOptionFunc) error {
174+
func (sw *statusWriter) Update(ctx context.Context, obj runtime.Object, opts ...UpdateOption) error {
175175
_, ok := obj.(*unstructured.Unstructured)
176176
if ok {
177177
return sw.client.unstructuredClient.UpdateStatus(ctx, obj, opts...)
@@ -180,7 +180,7 @@ func (sw *statusWriter) Update(ctx context.Context, obj runtime.Object, opts ...
180180
}
181181

182182
// Patch implements client.Client
183-
func (sw *statusWriter) Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOptionFunc) error {
183+
func (sw *statusWriter) Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOption) error {
184184
_, ok := obj.(*unstructured.Unstructured)
185185
if ok {
186186
return sw.client.unstructuredClient.PatchStatus(ctx, obj, patch, opts...)

pkg/client/client_test.go

+24-68
Original file line numberDiff line numberDiff line change
@@ -2000,7 +2000,7 @@ var _ = Describe("Client", func() {
20002000
Describe("CreateOptions", func() {
20012001
It("should allow setting DryRun to 'all'", func() {
20022002
co := &client.CreateOptions{}
2003-
client.CreateDryRunAll(co)
2003+
client.DryRunAll.ApplyToCreate(co)
20042004
all := []string{metav1.DryRunAll}
20052005
Expect(co.AsCreateOptions().DryRun).To(Equal(all))
20062006
})
@@ -2016,22 +2016,22 @@ var _ = Describe("Client", func() {
20162016
Describe("DeleteOptions", func() {
20172017
It("should allow setting GracePeriodSeconds", func() {
20182018
do := &client.DeleteOptions{}
2019-
client.GracePeriodSeconds(1)(do)
2019+
client.GracePeriodSeconds(1).ApplyToDelete(do)
20202020
gp := int64(1)
20212021
Expect(do.AsDeleteOptions().GracePeriodSeconds).To(Equal(&gp))
20222022
})
20232023

20242024
It("should allow setting Precondition", func() {
20252025
do := &client.DeleteOptions{}
20262026
pc := metav1.NewUIDPreconditions("uid")
2027-
client.Preconditions(pc)(do)
2027+
client.Preconditions(*pc).ApplyToDelete(do)
20282028
Expect(do.AsDeleteOptions().Preconditions).To(Equal(pc))
20292029
Expect(do.Preconditions).To(Equal(pc))
20302030
})
20312031

20322032
It("should allow setting PropagationPolicy", func() {
20332033
do := &client.DeleteOptions{}
2034-
client.PropagationPolicy(metav1.DeletePropagationForeground)(do)
2034+
client.PropagationPolicy(metav1.DeletePropagationForeground).ApplyToDelete(do)
20352035
dp := metav1.DeletePropagationForeground
20362036
Expect(do.AsDeleteOptions().PropagationPolicy).To(Equal(&dp))
20372037
})
@@ -2048,9 +2048,9 @@ var _ = Describe("Client", func() {
20482048
pc := metav1.NewUIDPreconditions("uid")
20492049
dp := metav1.DeletePropagationForeground
20502050
do := &client.DeleteOptions{}
2051-
do.ApplyOptions([]client.DeleteOptionFunc{
2051+
do.ApplyOptions([]client.DeleteOption{
20522052
client.GracePeriodSeconds(gp),
2053-
client.Preconditions(pc),
2053+
client.Preconditions(*pc),
20542054
client.PropagationPolicy(dp),
20552055
})
20562056
Expect(do.GracePeriodSeconds).To(Equal(&gp))
@@ -2060,79 +2060,35 @@ var _ = Describe("Client", func() {
20602060
})
20612061

20622062
Describe("ListOptions", func() {
2063-
It("should be able to set a LabelSelector", func() {
2064-
lo := &client.ListOptions{}
2065-
err := lo.SetLabelSelector("foo=bar")
2066-
Expect(err).NotTo(HaveOccurred())
2067-
Expect(lo.LabelSelector.String()).To(Equal("foo=bar"))
2068-
})
2069-
2070-
It("should be able to set a FieldSelector", func() {
2071-
lo := &client.ListOptions{}
2072-
err := lo.SetFieldSelector("field1=bar")
2073-
Expect(err).NotTo(HaveOccurred())
2074-
Expect(lo.FieldSelector.String()).To(Equal("field1=bar"))
2075-
})
2076-
2077-
It("should be converted to metav1.ListOptions", func() {
2078-
lo := &client.ListOptions{}
2079-
labels := map[string]string{"foo": "bar"}
2080-
mlo := lo.MatchingLabels(labels).
2081-
MatchingField("field1", "bar").
2082-
InNamespace("test-namespace").
2083-
AsListOptions()
2063+
It("should be convertable to metav1.ListOptions", func() {
2064+
lo := (&client.ListOptions{}).ApplyOptions([]client.ListOption{
2065+
client.MatchingField("field1", "bar"),
2066+
client.InNamespace("test-namespace"),
2067+
client.MatchingLabels{"foo": "bar"},
2068+
})
2069+
mlo := lo.AsListOptions()
20842070
Expect(mlo).NotTo(BeNil())
20852071
Expect(mlo.LabelSelector).To(Equal("foo=bar"))
20862072
Expect(mlo.FieldSelector).To(Equal("field1=bar"))
20872073
})
20882074

2089-
It("should be able to set MatchingLabels", func() {
2090-
lo := &client.ListOptions{}
2091-
Expect(lo.LabelSelector).To(BeNil())
2092-
labels := map[string]string{"foo": "bar"}
2093-
lo = lo.MatchingLabels(labels)
2094-
Expect(lo.LabelSelector.String()).To(Equal("foo=bar"))
2095-
})
2096-
2097-
It("should be able to set MatchingField", func() {
2098-
lo := &client.ListOptions{}
2099-
Expect(lo.FieldSelector).To(BeNil())
2100-
lo = lo.MatchingField("field1", "bar")
2101-
Expect(lo.FieldSelector.String()).To(Equal("field1=bar"))
2102-
})
2103-
2104-
It("should be able to set InNamespace", func() {
2105-
lo := &client.ListOptions{}
2106-
lo = lo.InNamespace("test-namespace")
2107-
Expect(lo.Namespace).To(Equal("test-namespace"))
2108-
})
2109-
2110-
It("should be created from MatchingLabels", func() {
2111-
labels := map[string]string{"foo": "bar"}
2075+
It("should be populated by MatchingLabels", func() {
21122076
lo := &client.ListOptions{}
2113-
client.MatchingLabels(labels)(lo)
2077+
client.MatchingLabels{"foo": "bar"}.ApplyToList(lo)
21142078
Expect(lo).NotTo(BeNil())
21152079
Expect(lo.LabelSelector.String()).To(Equal("foo=bar"))
21162080
})
21172081

2118-
It("should be created from MatchingField", func() {
2082+
It("should be populated by MatchingField", func() {
21192083
lo := &client.ListOptions{}
2120-
client.MatchingField("field1", "bar")(lo)
2084+
client.MatchingField("field1", "bar").ApplyToList(lo)
21212085
Expect(lo).NotTo(BeNil())
21222086
Expect(lo.FieldSelector.String()).To(Equal("field1=bar"))
21232087
})
21242088

2125-
It("should be created from InNamespace", func() {
2126-
lo := &client.ListOptions{}
2127-
client.InNamespace("test")(lo)
2128-
Expect(lo).NotTo(BeNil())
2129-
Expect(lo.Namespace).To(Equal("test"))
2130-
})
2131-
2132-
It("should allow pre-built ListOptions", func() {
2089+
It("should be populated by InNamespace", func() {
21332090
lo := &client.ListOptions{}
2134-
newLo := &client.ListOptions{}
2135-
client.UseListOptions(newLo.InNamespace("test"))(lo)
2091+
client.InNamespace("test").ApplyToList(lo)
21362092
Expect(lo).NotTo(BeNil())
21372093
Expect(lo.Namespace).To(Equal("test"))
21382094
})
@@ -2141,7 +2097,7 @@ var _ = Describe("Client", func() {
21412097
Describe("UpdateOptions", func() {
21422098
It("should allow setting DryRun to 'all'", func() {
21432099
uo := &client.UpdateOptions{}
2144-
client.UpdateDryRunAll(uo)
2100+
client.DryRunAll.ApplyToUpdate(uo)
21452101
all := []string{metav1.DryRunAll}
21462102
Expect(uo.AsUpdateOptions().DryRun).To(Equal(all))
21472103
})
@@ -2157,22 +2113,22 @@ var _ = Describe("Client", func() {
21572113
Describe("PatchOptions", func() {
21582114
It("should allow setting DryRun to 'all'", func() {
21592115
po := &client.PatchOptions{}
2160-
client.PatchDryRunAll(po)
2116+
client.DryRunAll.ApplyToPatch(po)
21612117
all := []string{metav1.DryRunAll}
21622118
Expect(po.AsPatchOptions().DryRun).To(Equal(all))
21632119
})
21642120

21652121
It("should allow setting Force to 'true'", func() {
21662122
po := &client.PatchOptions{}
2167-
client.ForceOwnership(po)
2123+
client.ForceOwnership.ApplyToPatch(po)
21682124
mpo := po.AsPatchOptions()
21692125
Expect(mpo.Force).NotTo(BeNil())
21702126
Expect(*mpo.Force).To(BeTrue())
21712127
})
21722128

21732129
It("should allow setting the field manager", func() {
21742130
po := &client.PatchOptions{}
2175-
client.FieldOwner("some-owner")(po)
2131+
client.FieldOwner("some-owner").ApplyToPatch(po)
21762132
Expect(po.AsPatchOptions().FieldManager).To(Equal("some-owner"))
21772133
})
21782134

@@ -2320,7 +2276,7 @@ func (f *fakeReader) Get(ctx context.Context, key client.ObjectKey, obj runtime.
23202276
return nil
23212277
}
23222278

2323-
func (f *fakeReader) List(ctx context.Context, list runtime.Object, opts ...client.ListOptionFunc) error {
2279+
func (f *fakeReader) List(ctx context.Context, list runtime.Object, opts ...client.ListOption) error {
23242280
f.Called = f.Called + 1
23252281
return nil
23262282
}

pkg/client/doc.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ limitations under the License.
3434
// Many client operations in Kubernetes support options. These options are
3535
// represented as variadic arguments at the end of a given method call.
3636
// For instance, to use a label selector on list, you can call
37-
// err := someReader.List(context.Background(), &podList, client.MatchingLabels(someLabelMap))
37+
// err := someReader.List(context.Background(), &podList, client.MatchingLabels{"somelabel": "someval"})
3838
//
3939
// Indexing
4040
//

pkg/client/fake/client.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func (c *fakeClient) Get(ctx context.Context, key client.ObjectKey, obj runtime.
8484
return err
8585
}
8686

87-
func (c *fakeClient) List(ctx context.Context, obj runtime.Object, opts ...client.ListOptionFunc) error {
87+
func (c *fakeClient) List(ctx context.Context, obj runtime.Object, opts ...client.ListOption) error {
8888
gvk, err := apiutil.GVKForObject(obj, c.scheme)
8989
if err != nil {
9090
return err
@@ -131,7 +131,7 @@ func (c *fakeClient) List(ctx context.Context, obj runtime.Object, opts ...clien
131131
return nil
132132
}
133133

134-
func (c *fakeClient) Create(ctx context.Context, obj runtime.Object, opts ...client.CreateOptionFunc) error {
134+
func (c *fakeClient) Create(ctx context.Context, obj runtime.Object, opts ...client.CreateOption) error {
135135
createOptions := &client.CreateOptions{}
136136
createOptions.ApplyOptions(opts)
137137

@@ -152,7 +152,7 @@ func (c *fakeClient) Create(ctx context.Context, obj runtime.Object, opts ...cli
152152
return c.tracker.Create(gvr, obj, accessor.GetNamespace())
153153
}
154154

155-
func (c *fakeClient) Delete(ctx context.Context, obj runtime.Object, opts ...client.DeleteOptionFunc) error {
155+
func (c *fakeClient) Delete(ctx context.Context, obj runtime.Object, opts ...client.DeleteOption) error {
156156
gvr, err := getGVRFromObject(obj, c.scheme)
157157
if err != nil {
158158
return err
@@ -165,7 +165,7 @@ func (c *fakeClient) Delete(ctx context.Context, obj runtime.Object, opts ...cli
165165
return c.tracker.Delete(gvr, accessor.GetNamespace(), accessor.GetName())
166166
}
167167

168-
func (c *fakeClient) Update(ctx context.Context, obj runtime.Object, opts ...client.UpdateOptionFunc) error {
168+
func (c *fakeClient) Update(ctx context.Context, obj runtime.Object, opts ...client.UpdateOption) error {
169169
updateOptions := &client.UpdateOptions{}
170170
updateOptions.ApplyOptions(opts)
171171

@@ -186,7 +186,7 @@ func (c *fakeClient) Update(ctx context.Context, obj runtime.Object, opts ...cli
186186
return c.tracker.Update(gvr, obj, accessor.GetNamespace())
187187
}
188188

189-
func (c *fakeClient) Patch(ctx context.Context, obj runtime.Object, patch client.Patch, opts ...client.PatchOptionFunc) error {
189+
func (c *fakeClient) Patch(ctx context.Context, obj runtime.Object, patch client.Patch, opts ...client.PatchOption) error {
190190
patchOptions := &client.PatchOptions{}
191191
patchOptions.ApplyOptions(opts)
192192

@@ -244,13 +244,13 @@ type fakeStatusWriter struct {
244244
client *fakeClient
245245
}
246246

247-
func (sw *fakeStatusWriter) Update(ctx context.Context, obj runtime.Object, opts ...client.UpdateOptionFunc) error {
247+
func (sw *fakeStatusWriter) Update(ctx context.Context, obj runtime.Object, opts ...client.UpdateOption) error {
248248
// TODO(droot): This results in full update of the obj (spec + status). Need
249249
// a way to update status field only.
250250
return sw.client.Update(ctx, obj, opts...)
251251
}
252252

253-
func (sw *fakeStatusWriter) Patch(ctx context.Context, obj runtime.Object, patch client.Patch, opts ...client.PatchOptionFunc) error {
253+
func (sw *fakeStatusWriter) Patch(ctx context.Context, obj runtime.Object, patch client.Patch, opts ...client.PatchOption) error {
254254
// TODO(droot): This results in full update of the obj (spec + status). Need
255255
// a way to update status field only.
256256
return sw.client.Patch(ctx, obj, patch, opts...)

pkg/client/interfaces.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -58,24 +58,24 @@ type Reader interface {
5858
// List retrieves list of objects for a given namespace and list options. On a
5959
// successful call, Items field in the list will be populated with the
6060
// result returned from the server.
61-
List(ctx context.Context, list runtime.Object, opts ...ListOptionFunc) error
61+
List(ctx context.Context, list runtime.Object, opts ...ListOption) error
6262
}
6363

6464
// Writer knows how to create, delete, and update Kubernetes objects.
6565
type Writer interface {
6666
// Create saves the object obj in the Kubernetes cluster.
67-
Create(ctx context.Context, obj runtime.Object, opts ...CreateOptionFunc) error
67+
Create(ctx context.Context, obj runtime.Object, opts ...CreateOption) error
6868

6969
// Delete deletes the given obj from Kubernetes cluster.
70-
Delete(ctx context.Context, obj runtime.Object, opts ...DeleteOptionFunc) error
70+
Delete(ctx context.Context, obj runtime.Object, opts ...DeleteOption) error
7171

7272
// Update updates the given obj in the Kubernetes cluster. obj must be a
7373
// struct pointer so that obj can be updated with the content returned by the Server.
74-
Update(ctx context.Context, obj runtime.Object, opts ...UpdateOptionFunc) error
74+
Update(ctx context.Context, obj runtime.Object, opts ...UpdateOption) error
7575

7676
// Patch patches the given obj in the Kubernetes cluster. obj must be a
7777
// struct pointer so that obj can be updated with the content returned by the Server.
78-
Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOptionFunc) error
78+
Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOption) error
7979
}
8080

8181
// StatusClient knows how to create a client which can update status subresource
@@ -89,12 +89,12 @@ type StatusWriter interface {
8989
// Update updates the fields corresponding to the status subresource for the
9090
// given obj. obj must be a struct pointer so that obj can be updated
9191
// with the content returned by the Server.
92-
Update(ctx context.Context, obj runtime.Object, opts ...UpdateOptionFunc) error
92+
Update(ctx context.Context, obj runtime.Object, opts ...UpdateOption) error
9393

9494
// Patch patches the given object's subresource. obj must be a struct
9595
// pointer so that obj can be updated with the content returned by the
9696
// Server.
97-
Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOptionFunc) error
97+
Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOption) error
9898
}
9999

100100
// Client knows how to perform CRUD operations on Kubernetes objects.

0 commit comments

Comments
 (0)