Skip to content

Commit

Permalink
⚠ Change client.Patch to take client.Object
Browse files Browse the repository at this point in the history
This allows us to use metav1 accessors to speed up the merge-patch
implementation.
  • Loading branch information
cbandy committed Mar 3, 2021
1 parent 442bac3 commit aef159a
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 54 deletions.
2 changes: 1 addition & 1 deletion pkg/client/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ type Patch interface {
// Type is the PatchType of the patch.
Type() types.PatchType
// Data is the raw data representing the patch.
Data(obj runtime.Object) ([]byte, error)
Data(obj Object) ([]byte, error)
}

// TODO(directxman12): is there a sane way to deal with get/delete options?
Expand Down
61 changes: 10 additions & 51 deletions pkg/client/patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ import (
"fmt"

jsonpatch "github.com/evanphx/json-patch"
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/types"
"k8s.io/apimachinery/pkg/util/json"
Expand All @@ -47,7 +45,7 @@ func (s *patch) Type() types.PatchType {
}

// Data implements Patch.
func (s *patch) Data(obj runtime.Object) ([]byte, error) {
func (s *patch) Data(obj Object) ([]byte, error) {
return s.data, nil
}

Expand Down Expand Up @@ -87,7 +85,7 @@ type MergeFromOptions struct {
}

type mergeFromPatch struct {
from runtime.Object
from Object
opts MergeFromOptions
}

Expand All @@ -96,8 +94,12 @@ func (s *mergeFromPatch) Type() types.PatchType {
return types.MergePatchType
}

func (*mergeFromPatch) data(original, modified Object, opts MergeFromOptions) ([]byte, error) {
if opts.OptimisticLock {
// Data implements Patch.
func (s *mergeFromPatch) Data(obj Object) ([]byte, error) {
original := s.from
modified := obj

if s.opts.OptimisticLock {
version := original.GetResourceVersion()
if len(version) == 0 {
return nil, fmt.Errorf("cannot use OptimisticLock, object %q does not have any resource version we can use", original)
Expand All @@ -120,64 +122,21 @@ func (*mergeFromPatch) data(original, modified Object, opts MergeFromOptions) ([
return nil, err
}

return jsonpatch.CreateMergePatch(originalJSON, modifiedJSON)
}

// Data implements Patch.
func (s *mergeFromPatch) Data(obj runtime.Object) ([]byte, error) {
fromObject, fromOk := s.from.(Object)
objObject, objOk := obj.(Object)

if fromOk && objOk {
return s.data(fromObject, objObject, s.opts)
}

originalJSON, err := json.Marshal(s.from)
if err != nil {
return nil, err
}

modifiedJSON, err := json.Marshal(obj)
if err != nil {
return nil, err
}

data, err := jsonpatch.CreateMergePatch(originalJSON, modifiedJSON)
if err != nil {
return nil, err
}

if s.opts.OptimisticLock {
dataMap := map[string]interface{}{}
if err := json.Unmarshal(data, &dataMap); err != nil {
return nil, err
}
fromMeta, ok := s.from.(metav1.Object)
if !ok {
return nil, fmt.Errorf("cannot use OptimisticLock, from object %q is not a valid metav1.Object", s.from)
}
resourceVersion := fromMeta.GetResourceVersion()
if len(resourceVersion) == 0 {
return nil, fmt.Errorf("cannot use OptimisticLock, from object %q does not have any resource version we can use", s.from)
}
u := &unstructured.Unstructured{Object: dataMap}
u.SetResourceVersion(resourceVersion)
data, err = json.Marshal(u)
if err != nil {
return nil, err
}
}

return data, nil
}

// MergeFrom creates a Patch that patches using the merge-patch strategy with the given object as base.
func MergeFrom(obj runtime.Object) Patch {
func MergeFrom(obj Object) Patch {
return &mergeFromPatch{from: obj}
}

// MergeFromWithOptions creates a Patch that patches using the merge-patch strategy with the given object as base.
func MergeFromWithOptions(obj runtime.Object, opts ...MergeFromOption) Patch {
func MergeFromWithOptions(obj Object, opts ...MergeFromOption) Patch {
options := &MergeFromOptions{}
for _, opt := range opts {
opt.ApplyToMergeFrom(options)
Expand Down
4 changes: 2 additions & 2 deletions pkg/controller/controllerutil/controllerutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,8 @@ func CreateOrPatch(ctx context.Context, c client.Client, obj client.Object, f Mu
}

// Create patches for the object and its possible status.
objPatch := client.MergeFrom(obj.DeepCopyObject())
statusPatch := client.MergeFrom(obj.DeepCopyObject())
objPatch := client.MergeFrom(obj.DeepCopyObject().(client.Object))
statusPatch := client.MergeFrom(obj.DeepCopyObject().(client.Object))

// Create a copy of the original object as well as converting that copy to
// unstructured data.
Expand Down

0 comments on commit aef159a

Please sign in to comment.