Skip to content

Commit 9f5b249

Browse files
author
Mengqi Yu
committed
🐛 IsConvertible should not error on uninitialized struct.
IsConvertible used to use obj.GetObjectKind().GroupVersionKind() to get GVK which will not work if apiVersion and kind fields are not set. Now it uses scheme.ObjectKinds(obj).
1 parent 4c81828 commit 9f5b249

File tree

2 files changed

+44
-7
lines changed

2 files changed

+44
-7
lines changed

pkg/webhook/conversion/conversion.go

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,10 @@ func (wh *Webhook) convertViaHub(src, dst conversion.Convertible) error {
174174

175175
// getHub returns an instance of the Hub for passed-in object's group/kind.
176176
func (wh *Webhook) getHub(obj runtime.Object) (conversion.Hub, error) {
177-
gvks := objectGVKs(wh.scheme, obj)
177+
gvks, err := objectGVKs(wh.scheme, obj)
178+
if err != nil {
179+
return nil, err
180+
}
178181
if len(gvks) == 0 {
179182
return nil, fmt.Errorf("error retrieving gvks for object : %v", obj)
180183
}
@@ -223,7 +226,10 @@ func (wh *Webhook) allocateDstObject(apiVersion, kind string) (runtime.Object, e
223226
func IsConvertible(scheme *runtime.Scheme, obj runtime.Object) (bool, error) {
224227
var hubs, spokes, nonSpokes []runtime.Object
225228

226-
gvks := objectGVKs(scheme, obj)
229+
gvks, err := objectGVKs(scheme, obj)
230+
if err != nil {
231+
return false, err
232+
}
227233
if len(gvks) == 0 {
228234
return false, fmt.Errorf("error retrieving gvks for object : %v", obj)
229235
}
@@ -273,18 +279,27 @@ func IsConvertible(scheme *runtime.Scheme, obj runtime.Object) (bool, error) {
273279
}
274280

275281
// objectGVKs returns all (Group,Version,Kind) for the Group/Kind of given object.
276-
func objectGVKs(scheme *runtime.Scheme, obj runtime.Object) []schema.GroupVersionKind {
277-
var gvks []schema.GroupVersionKind
278-
279-
objGVK := obj.GetObjectKind().GroupVersionKind()
282+
func objectGVKs(scheme *runtime.Scheme, obj runtime.Object) ([]schema.GroupVersionKind, error) {
283+
// NB: we should not use `obj.GetObjectKind().GroupVersionKind()` to get the
284+
// GVK here, since it is parsed from apiVersion and kind fields and it may
285+
// return empty GVK if obj is an uninitialized object.
286+
objGVKs, _, err := scheme.ObjectKinds(obj)
287+
if err != nil {
288+
return nil, err
289+
}
290+
if len(objGVKs) != 1 {
291+
return nil, fmt.Errorf("expect to get only one GVK for %v", obj)
292+
}
293+
objGVK := objGVKs[0]
280294
knownTypes := scheme.AllKnownTypes()
281295

296+
var gvks []schema.GroupVersionKind
282297
for gvk := range knownTypes {
283298
if objGVK.GroupKind() == gvk.GroupKind() {
284299
gvks = append(gvks, gvk)
285300
}
286301
}
287-
return gvks
302+
return gvks, nil
288303
}
289304

290305
// PartialImplementationError represents an error due to partial conversion

pkg/webhook/conversion/conversion_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
appsv1beta1 "k8s.io/api/apps/v1beta1"
3030
apix "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
3131
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
32+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
3233
"k8s.io/apimachinery/pkg/runtime"
3334
kscheme "k8s.io/client-go/kubernetes/scheme"
3435

@@ -312,6 +313,27 @@ var _ = Describe("IsConvertible", func() {
312313
Expect(jobsv3.AddToScheme(scheme)).To(Succeed())
313314
})
314315

316+
It("should not error for uninitialized types", func() {
317+
obj := &jobsv2.ExternalJob{}
318+
319+
ok, err := IsConvertible(scheme, obj)
320+
Expect(err).NotTo(HaveOccurred())
321+
Expect(ok).To(BeTrue())
322+
})
323+
324+
It("should not error for unstructured types", func() {
325+
obj := &unstructured.Unstructured{
326+
Object: map[string]interface{}{
327+
"kind": "ExternalJob",
328+
"apiVersion": "jobs.testprojects.kb.io/v2",
329+
},
330+
}
331+
332+
ok, err := IsConvertible(scheme, obj)
333+
Expect(err).NotTo(HaveOccurred())
334+
Expect(ok).To(BeTrue())
335+
})
336+
315337
It("should return true for convertible types", func() {
316338
obj := &jobsv2.ExternalJob{
317339
TypeMeta: metav1.TypeMeta{

0 commit comments

Comments
 (0)