Skip to content

Commit 7d674fd

Browse files
authored
Merge pull request #1521 from alvaroaleman/fix-again
🐛 Fakeclient: Fix List for unregistered type through unstructured
2 parents 745c7c9 + 4158af1 commit 7d674fd

File tree

2 files changed

+139
-2
lines changed

2 files changed

+139
-2
lines changed

pkg/client/fake/client.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@ import (
2323
"fmt"
2424
"strconv"
2525
"strings"
26+
"sync"
2627

2728
apierrors "k8s.io/apimachinery/pkg/api/errors"
2829
"k8s.io/apimachinery/pkg/api/meta"
2930
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
31+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
3032
"k8s.io/apimachinery/pkg/runtime"
3133
"k8s.io/apimachinery/pkg/runtime/schema"
3234
utilrand "k8s.io/apimachinery/pkg/util/rand"
@@ -46,8 +48,9 @@ type versionedTracker struct {
4648
}
4749

4850
type fakeClient struct {
49-
tracker versionedTracker
50-
scheme *runtime.Scheme
51+
tracker versionedTracker
52+
scheme *runtime.Scheme
53+
schemeWriteLock sync.Mutex
5154
}
5255

5356
var _ client.WithWatch = &fakeClient{}
@@ -314,6 +317,14 @@ func (c *fakeClient) List(ctx context.Context, obj client.ObjectList, opts ...cl
314317
gvk.Kind = gvk.Kind[:len(gvk.Kind)-4]
315318
}
316319

320+
if _, isUnstructuredList := obj.(*unstructured.UnstructuredList); isUnstructuredList && !c.scheme.Recognizes(gvk) {
321+
// We need tor register the ListKind with UnstructuredList:
322+
// https://github.com/kubernetes/kubernetes/blob/7b2776b89fb1be28d4e9203bdeec079be903c103/staging/src/k8s.io/client-go/dynamic/fake/simple.go#L44-L51
323+
c.schemeWriteLock.Lock()
324+
c.scheme.AddKnownTypeWithName(gvk.GroupVersion().WithKind(gvk.Kind+"List"), &unstructured.UnstructuredList{})
325+
c.schemeWriteLock.Unlock()
326+
}
327+
317328
listOpts := client.ListOptions{}
318329
listOpts.ApplyOptions(opts)
319330

pkg/client/fake/client_test.go

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,132 @@ var _ = Describe("Fake client", func() {
141141
Expect(list.Items).To(HaveLen(2))
142142
})
143143

144+
It("should be able to Create an unregistered type using unstructured", func() {
145+
item := &unstructured.Unstructured{}
146+
item.SetAPIVersion("custom/v1")
147+
item.SetKind("Image")
148+
item.SetName("my-item")
149+
err := cl.Create(context.Background(), item)
150+
Expect(err).To(BeNil())
151+
})
152+
153+
It("should be able to Get an unregisted type using unstructured", func() {
154+
By("Creating an object of an unregistered type")
155+
item := &unstructured.Unstructured{}
156+
item.SetAPIVersion("custom/v2")
157+
item.SetKind("Image")
158+
item.SetName("my-item")
159+
err := cl.Create(context.Background(), item)
160+
Expect(err).To(BeNil())
161+
162+
By("Getting and the object")
163+
item = &unstructured.Unstructured{}
164+
item.SetAPIVersion("custom/v2")
165+
item.SetKind("Image")
166+
item.SetName("my-item")
167+
err = cl.Get(context.Background(), client.ObjectKeyFromObject(item), item)
168+
Expect(err).To(BeNil())
169+
})
170+
171+
It("should be able to List an unregistered type using unstructured", func() {
172+
list := &unstructured.UnstructuredList{}
173+
list.SetAPIVersion("custom/v3")
174+
list.SetKind("ImageList")
175+
err := cl.List(context.Background(), list)
176+
Expect(err).To(BeNil())
177+
})
178+
179+
It("should be able to List an unregistered type using unstructured", func() {
180+
list := &unstructured.UnstructuredList{}
181+
list.SetAPIVersion("custom/v4")
182+
list.SetKind("Image")
183+
err := cl.List(context.Background(), list)
184+
Expect(err).To(BeNil())
185+
})
186+
187+
It("should be able to Update an unregistered type using unstructured", func() {
188+
By("Creating an object of an unregistered type")
189+
item := &unstructured.Unstructured{}
190+
item.SetAPIVersion("custom/v5")
191+
item.SetKind("Image")
192+
item.SetName("my-item")
193+
err := cl.Create(context.Background(), item)
194+
Expect(err).To(BeNil())
195+
196+
By("Updating the object")
197+
err = unstructured.SetNestedField(item.Object, int64(2), "spec", "replicas")
198+
Expect(err).To(BeNil())
199+
err = cl.Update(context.Background(), item)
200+
Expect(err).To(BeNil())
201+
202+
By("Getting the object")
203+
item = &unstructured.Unstructured{}
204+
item.SetAPIVersion("custom/v5")
205+
item.SetKind("Image")
206+
item.SetName("my-item")
207+
err = cl.Get(context.Background(), client.ObjectKeyFromObject(item), item)
208+
Expect(err).To(BeNil())
209+
210+
By("Inspecting the object")
211+
value, found, err := unstructured.NestedInt64(item.Object, "spec", "replicas")
212+
Expect(err).To(BeNil())
213+
Expect(found).To(BeTrue())
214+
Expect(value).To(Equal(int64(2)))
215+
})
216+
217+
It("should be able to Patch an unregistered type using unstructured", func() {
218+
By("Creating an object of an unregistered type")
219+
item := &unstructured.Unstructured{}
220+
item.SetAPIVersion("custom/v6")
221+
item.SetKind("Image")
222+
item.SetName("my-item")
223+
err := cl.Create(context.Background(), item)
224+
Expect(err).To(BeNil())
225+
226+
By("Updating the object")
227+
original := item.DeepCopy()
228+
err = unstructured.SetNestedField(item.Object, int64(2), "spec", "replicas")
229+
Expect(err).To(BeNil())
230+
err = cl.Patch(context.Background(), item, client.MergeFrom(original))
231+
Expect(err).To(BeNil())
232+
233+
By("Getting the object")
234+
item = &unstructured.Unstructured{}
235+
item.SetAPIVersion("custom/v6")
236+
item.SetKind("Image")
237+
item.SetName("my-item")
238+
err = cl.Get(context.Background(), client.ObjectKeyFromObject(item), item)
239+
Expect(err).To(BeNil())
240+
241+
By("Inspecting the object")
242+
value, found, err := unstructured.NestedInt64(item.Object, "spec", "replicas")
243+
Expect(err).To(BeNil())
244+
Expect(found).To(BeTrue())
245+
Expect(value).To(Equal(int64(2)))
246+
})
247+
248+
It("should be able to Delete an unregistered type using unstructured", func() {
249+
By("Creating an object of an unregistered type")
250+
item := &unstructured.Unstructured{}
251+
item.SetAPIVersion("custom/v7")
252+
item.SetKind("Image")
253+
item.SetName("my-item")
254+
err := cl.Create(context.Background(), item)
255+
Expect(err).To(BeNil())
256+
257+
By("Deleting the object")
258+
err = cl.Delete(context.Background(), item)
259+
Expect(err).To(BeNil())
260+
261+
By("Getting the object")
262+
item = &unstructured.Unstructured{}
263+
item.SetAPIVersion("custom/v7")
264+
item.SetKind("Image")
265+
item.SetName("my-item")
266+
err = cl.Get(context.Background(), client.ObjectKeyFromObject(item), item)
267+
Expect(apierrors.IsNotFound(err)).To(BeTrue())
268+
})
269+
144270
It("should support filtering by labels and their values", func() {
145271
By("Listing deployments with a particular label and value")
146272
list := &appsv1.DeploymentList{}

0 commit comments

Comments
 (0)