Skip to content

Commit

Permalink
Use runtime.Unstructured interface instead of Unstructured struct
Browse files Browse the repository at this point in the history
Signed-off-by: Vince Prignano <vincepri@redhat.com>
  • Loading branch information
vincepri committed Feb 2, 2023
1 parent 6adc01f commit 4357393
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 63 deletions.
2 changes: 1 addition & 1 deletion pkg/cache/informer_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func (ic *informerCache) objectTypeForListObject(list client.ObjectList) (*schem
gvk.Kind = strings.TrimSuffix(gvk.Kind, "List")

// Handle unstructured.UnstructuredList.
if _, isUnstructured := list.(*unstructured.UnstructuredList); isUnstructured {
if _, isUnstructured := list.(runtime.Unstructured); isUnstructured {
u := &unstructured.Unstructured{}
u.SetGroupVersionKind(gvk)
return &gvk, u, nil
Expand Down
5 changes: 2 additions & 3 deletions pkg/cache/internal/informers.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
Expand Down Expand Up @@ -307,7 +306,7 @@ func (ip *Informers) Get(ctx context.Context, gvk schema.GroupVersionKind, obj r

func (ip *Informers) informersByType(obj runtime.Object) map[schema.GroupVersionKind]*Cache {
switch obj.(type) {
case *unstructured.Unstructured, *unstructured.UnstructuredList:
case runtime.Unstructured:
return ip.tracker.Unstructured
case *metav1.PartialObjectMetadata, *metav1.PartialObjectMetadataList:
return ip.tracker.Metadata
Expand Down Expand Up @@ -394,7 +393,7 @@ func (ip *Informers) makeListWatcher(gvk schema.GroupVersionKind, obj runtime.Ob
//
// Unstructured
//
case *unstructured.Unstructured, *unstructured.UnstructuredList:
case runtime.Unstructured:
// If the rest configuration has a negotiated serializer passed in,
// we should remove it and use the one that the dynamic client sets for us.
cfg := rest.CopyConfig(ip.config)
Expand Down
28 changes: 13 additions & 15 deletions pkg/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (

"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
Expand Down Expand Up @@ -230,9 +229,8 @@ func (c *client) shouldBypassCache(obj runtime.Object) (bool, error) {
return true, nil
}
if !c.cacheUnstructured {
_, isUnstructured := obj.(*unstructured.Unstructured)
_, isUnstructuredList := obj.(*unstructured.UnstructuredList)
return isUnstructured || isUnstructuredList, nil
_, isUnstructured := obj.(runtime.Unstructured)
return isUnstructured, nil
}
return false, nil
}
Expand Down Expand Up @@ -269,7 +267,7 @@ func (c *client) RESTMapper() meta.RESTMapper {
// Create implements client.Client.
func (c *client) Create(ctx context.Context, obj Object, opts ...CreateOption) error {
switch obj.(type) {
case *unstructured.Unstructured:
case runtime.Unstructured:
return c.unstructuredClient.Create(ctx, obj, opts...)
case *metav1.PartialObjectMetadata:
return fmt.Errorf("cannot create using only metadata")
Expand All @@ -282,7 +280,7 @@ func (c *client) Create(ctx context.Context, obj Object, opts ...CreateOption) e
func (c *client) Update(ctx context.Context, obj Object, opts ...UpdateOption) error {
defer c.resetGroupVersionKind(obj, obj.GetObjectKind().GroupVersionKind())
switch obj.(type) {
case *unstructured.Unstructured:
case runtime.Unstructured:
return c.unstructuredClient.Update(ctx, obj, opts...)
case *metav1.PartialObjectMetadata:
return fmt.Errorf("cannot update using only metadata -- did you mean to patch?")
Expand All @@ -294,7 +292,7 @@ func (c *client) Update(ctx context.Context, obj Object, opts ...UpdateOption) e
// Delete implements client.Client.
func (c *client) Delete(ctx context.Context, obj Object, opts ...DeleteOption) error {
switch obj.(type) {
case *unstructured.Unstructured:
case runtime.Unstructured:
return c.unstructuredClient.Delete(ctx, obj, opts...)
case *metav1.PartialObjectMetadata:
return c.metadataClient.Delete(ctx, obj, opts...)
Expand All @@ -306,7 +304,7 @@ func (c *client) Delete(ctx context.Context, obj Object, opts ...DeleteOption) e
// DeleteAllOf implements client.Client.
func (c *client) DeleteAllOf(ctx context.Context, obj Object, opts ...DeleteAllOfOption) error {
switch obj.(type) {
case *unstructured.Unstructured:
case runtime.Unstructured:
return c.unstructuredClient.DeleteAllOf(ctx, obj, opts...)
case *metav1.PartialObjectMetadata:
return c.metadataClient.DeleteAllOf(ctx, obj, opts...)
Expand All @@ -319,7 +317,7 @@ func (c *client) DeleteAllOf(ctx context.Context, obj Object, opts ...DeleteAllO
func (c *client) Patch(ctx context.Context, obj Object, patch Patch, opts ...PatchOption) error {
defer c.resetGroupVersionKind(obj, obj.GetObjectKind().GroupVersionKind())
switch obj.(type) {
case *unstructured.Unstructured:
case runtime.Unstructured:
return c.unstructuredClient.Patch(ctx, obj, patch, opts...)
case *metav1.PartialObjectMetadata:
return c.metadataClient.Patch(ctx, obj, patch, opts...)
Expand All @@ -337,7 +335,7 @@ func (c *client) Get(ctx context.Context, key ObjectKey, obj Object, opts ...Get
}

switch obj.(type) {
case *unstructured.Unstructured:
case runtime.Unstructured:
return c.unstructuredClient.Get(ctx, key, obj, opts...)
case *metav1.PartialObjectMetadata:
// Metadata only object should always preserve the GVK coming in from the caller.
Expand All @@ -357,7 +355,7 @@ func (c *client) List(ctx context.Context, obj ObjectList, opts ...ListOption) e
}

switch x := obj.(type) {
case *unstructured.UnstructuredList:
case runtime.Unstructured:
return c.unstructuredClient.List(ctx, obj, opts...)
case *metav1.PartialObjectMetadataList:
// Metadata only object should always preserve the GVK.
Expand Down Expand Up @@ -531,7 +529,7 @@ func (po *SubResourcePatchOptions) ApplyToSubResourcePatch(o *SubResourcePatchOp

func (sc *subResourceClient) Get(ctx context.Context, obj Object, subResource Object, opts ...SubResourceGetOption) error {
switch obj.(type) {
case *unstructured.Unstructured:
case runtime.Unstructured:
return sc.client.unstructuredClient.GetSubResource(ctx, obj, subResource, sc.subResource, opts...)
case *metav1.PartialObjectMetadata:
return errors.New("can not get subresource using only metadata")
Expand All @@ -546,7 +544,7 @@ func (sc *subResourceClient) Create(ctx context.Context, obj Object, subResource
defer sc.client.resetGroupVersionKind(subResource, subResource.GetObjectKind().GroupVersionKind())

switch obj.(type) {
case *unstructured.Unstructured:
case runtime.Unstructured:
return sc.client.unstructuredClient.CreateSubResource(ctx, obj, subResource, sc.subResource, opts...)
case *metav1.PartialObjectMetadata:
return fmt.Errorf("cannot update status using only metadata -- did you mean to patch?")
Expand All @@ -559,7 +557,7 @@ func (sc *subResourceClient) Create(ctx context.Context, obj Object, subResource
func (sc *subResourceClient) Update(ctx context.Context, obj Object, opts ...SubResourceUpdateOption) error {
defer sc.client.resetGroupVersionKind(obj, obj.GetObjectKind().GroupVersionKind())
switch obj.(type) {
case *unstructured.Unstructured:
case runtime.Unstructured:
return sc.client.unstructuredClient.UpdateSubResource(ctx, obj, sc.subResource, opts...)
case *metav1.PartialObjectMetadata:
return fmt.Errorf("cannot update status using only metadata -- did you mean to patch?")
Expand All @@ -572,7 +570,7 @@ func (sc *subResourceClient) Update(ctx context.Context, obj Object, opts ...Sub
func (sc *subResourceClient) Patch(ctx context.Context, obj Object, patch Patch, opts ...SubResourcePatchOption) error {
defer sc.client.resetGroupVersionKind(obj, obj.GetObjectKind().GroupVersionKind())
switch obj.(type) {
case *unstructured.Unstructured:
case runtime.Unstructured:
return sc.client.unstructuredClient.PatchSubResource(ctx, obj, sc.subResource, patch, opts...)
case *metav1.PartialObjectMetadata:
return sc.client.metadataClient.PatchSubResource(ctx, obj, sc.subResource, patch, opts...)
Expand Down
5 changes: 1 addition & 4 deletions pkg/client/client_rest_resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (

"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
Expand Down Expand Up @@ -82,9 +81,7 @@ func (c *clientRestResources) getResource(obj runtime.Object) (*resourceMeta, er
return nil, err
}

_, isUnstructured := obj.(*unstructured.Unstructured)
_, isUnstructuredList := obj.(*unstructured.UnstructuredList)
isUnstructured = isUnstructured || isUnstructuredList
_, isUnstructured := obj.(runtime.Unstructured)

// It's better to do creation work twice than to not let multiple
// people make requests at once
Expand Down
14 changes: 8 additions & 6 deletions pkg/client/fake/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,20 +290,22 @@ func (t versionedTracker) Create(gvr schema.GroupVersionResource, obj runtime.Ob
return nil
}

// convertFromUnstructuredIfNecessary will convert *unstructured.Unstructured for a GVK that is recocnized
// convertFromUnstructuredIfNecessary will convert runtime.Unstructured for a GVK that is recocnized
// by the schema into the whatever the schema produces with New() for said GVK.
// This is required because the tracker unconditionally saves on manipulations, but its List() implementation
// tries to assign whatever it finds into a ListType it gets from schema.New() - Thus we have to ensure
// we save as the very same type, otherwise subsequent List requests will fail.
func convertFromUnstructuredIfNecessary(s *runtime.Scheme, o runtime.Object) (runtime.Object, error) {
u, isUnstructured := o.(*unstructured.Unstructured)
if !isUnstructured || !s.Recognizes(u.GroupVersionKind()) {
gvk := o.GetObjectKind().GroupVersionKind()

u, isUnstructured := o.(runtime.Unstructured)
if !isUnstructured || !s.Recognizes(gvk) {
return o, nil
}

typed, err := s.New(u.GroupVersionKind())
typed, err := s.New(gvk)
if err != nil {
return nil, fmt.Errorf("scheme recognizes %s but failed to produce an object for it: %w", u.GroupVersionKind().String(), err)
return nil, fmt.Errorf("scheme recognizes %s but failed to produce an object for it: %w", gvk, err)
}

unstructuredSerialized, err := json.Marshal(u)
Expand Down Expand Up @@ -436,7 +438,7 @@ func (c *fakeClient) List(ctx context.Context, obj client.ObjectList, opts ...cl

gvk.Kind = strings.TrimSuffix(gvk.Kind, "List")

if _, isUnstructuredList := obj.(*unstructured.UnstructuredList); isUnstructuredList && !c.scheme.Recognizes(gvk) {
if _, isUnstructuredList := obj.(runtime.Unstructured); isUnstructuredList && !c.scheme.Recognizes(gvk) {
// We need to register the ListKind with UnstructuredList:
// https://github.com/kubernetes/kubernetes/blob/7b2776b89fb1be28d4e9203bdeec079be903c103/staging/src/k8s.io/client-go/dynamic/fake/simple.go#L44-L51
c.schemeWriteLock.Lock()
Expand Down
45 changes: 22 additions & 23 deletions pkg/client/unstructured_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"fmt"
"strings"

"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
)

Expand All @@ -35,12 +34,12 @@ type unstructuredClient struct {

// Create implements client.Client.
func (uc *unstructuredClient) Create(ctx context.Context, obj Object, opts ...CreateOption) error {
u, ok := obj.(*unstructured.Unstructured)
u, ok := obj.(runtime.Unstructured)
if !ok {
return fmt.Errorf("unstructured client did not understand object: %T", obj)
}

gvk := u.GroupVersionKind()
gvk := u.GetObjectKind().GroupVersionKind()

o, err := uc.resources.getObjMeta(obj)
if err != nil {
Expand All @@ -58,18 +57,18 @@ func (uc *unstructuredClient) Create(ctx context.Context, obj Object, opts ...Cr
Do(ctx).
Into(obj)

u.SetGroupVersionKind(gvk)
u.GetObjectKind().SetGroupVersionKind(gvk)
return result
}

// Update implements client.Client.
func (uc *unstructuredClient) Update(ctx context.Context, obj Object, opts ...UpdateOption) error {
u, ok := obj.(*unstructured.Unstructured)
u, ok := obj.(runtime.Unstructured)
if !ok {
return fmt.Errorf("unstructured client did not understand object: %T", obj)
}

gvk := u.GroupVersionKind()
gvk := u.GetObjectKind().GroupVersionKind()

o, err := uc.resources.getObjMeta(obj)
if err != nil {
Expand All @@ -88,13 +87,13 @@ func (uc *unstructuredClient) Update(ctx context.Context, obj Object, opts ...Up
Do(ctx).
Into(obj)

u.SetGroupVersionKind(gvk)
u.GetObjectKind().SetGroupVersionKind(gvk)
return result
}

// Delete implements client.Client.
func (uc *unstructuredClient) Delete(ctx context.Context, obj Object, opts ...DeleteOption) error {
if _, ok := obj.(*unstructured.Unstructured); !ok {
if _, ok := obj.(runtime.Unstructured); !ok {
return fmt.Errorf("unstructured client did not understand object: %T", obj)
}

Expand All @@ -117,7 +116,7 @@ func (uc *unstructuredClient) Delete(ctx context.Context, obj Object, opts ...De

// DeleteAllOf implements client.Client.
func (uc *unstructuredClient) DeleteAllOf(ctx context.Context, obj Object, opts ...DeleteAllOfOption) error {
if _, ok := obj.(*unstructured.Unstructured); !ok {
if _, ok := obj.(runtime.Unstructured); !ok {
return fmt.Errorf("unstructured client did not understand object: %T", obj)
}

Expand All @@ -140,7 +139,7 @@ func (uc *unstructuredClient) DeleteAllOf(ctx context.Context, obj Object, opts

// Patch implements client.Client.
func (uc *unstructuredClient) Patch(ctx context.Context, obj Object, patch Patch, opts ...PatchOption) error {
if _, ok := obj.(*unstructured.Unstructured); !ok {
if _, ok := obj.(runtime.Unstructured); !ok {
return fmt.Errorf("unstructured client did not understand object: %T", obj)
}

Expand Down Expand Up @@ -169,12 +168,12 @@ func (uc *unstructuredClient) Patch(ctx context.Context, obj Object, patch Patch

// Get implements client.Client.
func (uc *unstructuredClient) Get(ctx context.Context, key ObjectKey, obj Object, opts ...GetOption) error {
u, ok := obj.(*unstructured.Unstructured)
u, ok := obj.(runtime.Unstructured)
if !ok {
return fmt.Errorf("unstructured client did not understand object: %T", obj)
}

gvk := u.GroupVersionKind()
gvk := u.GetObjectKind().GroupVersionKind()

getOpts := GetOptions{}
getOpts.ApplyOptions(opts)
Expand All @@ -192,19 +191,19 @@ func (uc *unstructuredClient) Get(ctx context.Context, key ObjectKey, obj Object
Do(ctx).
Into(obj)

u.SetGroupVersionKind(gvk)
u.GetObjectKind().SetGroupVersionKind(gvk)

return result
}

// List implements client.Client.
func (uc *unstructuredClient) List(ctx context.Context, obj ObjectList, opts ...ListOption) error {
u, ok := obj.(*unstructured.UnstructuredList)
u, ok := obj.(runtime.Unstructured)
if !ok {
return fmt.Errorf("unstructured client did not understand object: %T", obj)
}

gvk := u.GroupVersionKind()
gvk := u.GetObjectKind().GroupVersionKind()
gvk.Kind = strings.TrimSuffix(gvk.Kind, "List")

r, err := uc.resources.getResource(obj)
Expand All @@ -224,11 +223,11 @@ func (uc *unstructuredClient) List(ctx context.Context, obj ObjectList, opts ...
}

func (uc *unstructuredClient) GetSubResource(ctx context.Context, obj, subResourceObj Object, subResource string, opts ...SubResourceGetOption) error {
if _, ok := obj.(*unstructured.Unstructured); !ok {
if _, ok := obj.(runtime.Unstructured); !ok {
return fmt.Errorf("unstructured client did not understand object: %T", subResource)
}

if _, ok := subResourceObj.(*unstructured.Unstructured); !ok {
if _, ok := subResourceObj.(runtime.Unstructured); !ok {
return fmt.Errorf("unstructured client did not understand object: %T", obj)
}

Expand All @@ -255,11 +254,11 @@ func (uc *unstructuredClient) GetSubResource(ctx context.Context, obj, subResour
}

func (uc *unstructuredClient) CreateSubResource(ctx context.Context, obj, subResourceObj Object, subResource string, opts ...SubResourceCreateOption) error {
if _, ok := obj.(*unstructured.Unstructured); !ok {
if _, ok := obj.(runtime.Unstructured); !ok {
return fmt.Errorf("unstructured client did not understand object: %T", subResourceObj)
}

if _, ok := subResourceObj.(*unstructured.Unstructured); !ok {
if _, ok := subResourceObj.(runtime.Unstructured); !ok {
return fmt.Errorf("unstructured client did not understand object: %T", obj)
}

Expand Down Expand Up @@ -287,7 +286,7 @@ func (uc *unstructuredClient) CreateSubResource(ctx context.Context, obj, subRes
}

func (uc *unstructuredClient) UpdateSubResource(ctx context.Context, obj Object, subResource string, opts ...SubResourceUpdateOption) error {
if _, ok := obj.(*unstructured.Unstructured); !ok {
if _, ok := obj.(runtime.Unstructured); !ok {
return fmt.Errorf("unstructured client did not understand object: %T", obj)
}

Expand Down Expand Up @@ -322,12 +321,12 @@ func (uc *unstructuredClient) UpdateSubResource(ctx context.Context, obj Object,
}

func (uc *unstructuredClient) PatchSubResource(ctx context.Context, obj Object, subResource string, patch Patch, opts ...SubResourcePatchOption) error {
u, ok := obj.(*unstructured.Unstructured)
u, ok := obj.(runtime.Unstructured)
if !ok {
return fmt.Errorf("unstructured client did not understand object: %T", obj)
}

gvk := u.GroupVersionKind()
gvk := u.GetObjectKind().GroupVersionKind()

o, err := uc.resources.getObjMeta(obj)
if err != nil {
Expand Down Expand Up @@ -357,6 +356,6 @@ func (uc *unstructuredClient) PatchSubResource(ctx context.Context, obj Object,
Do(ctx).
Into(body)

u.SetGroupVersionKind(gvk)
u.GetObjectKind().SetGroupVersionKind(gvk)
return result
}
Loading

0 comments on commit 4357393

Please sign in to comment.