Skip to content

Commit aef159a

Browse files
committed
⚠ Change client.Patch to take client.Object
This allows us to use metav1 accessors to speed up the merge-patch implementation.
1 parent 442bac3 commit aef159a

File tree

3 files changed

+13
-54
lines changed

3 files changed

+13
-54
lines changed

pkg/client/interfaces.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ type Patch interface {
3939
// Type is the PatchType of the patch.
4040
Type() types.PatchType
4141
// Data is the raw data representing the patch.
42-
Data(obj runtime.Object) ([]byte, error)
42+
Data(obj Object) ([]byte, error)
4343
}
4444

4545
// TODO(directxman12): is there a sane way to deal with get/delete options?

pkg/client/patch.go

Lines changed: 10 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ import (
2020
"fmt"
2121

2222
jsonpatch "github.com/evanphx/json-patch"
23-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24-
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2523
"k8s.io/apimachinery/pkg/runtime"
2624
"k8s.io/apimachinery/pkg/types"
2725
"k8s.io/apimachinery/pkg/util/json"
@@ -47,7 +45,7 @@ func (s *patch) Type() types.PatchType {
4745
}
4846

4947
// Data implements Patch.
50-
func (s *patch) Data(obj runtime.Object) ([]byte, error) {
48+
func (s *patch) Data(obj Object) ([]byte, error) {
5149
return s.data, nil
5250
}
5351

@@ -87,7 +85,7 @@ type MergeFromOptions struct {
8785
}
8886

8987
type mergeFromPatch struct {
90-
from runtime.Object
88+
from Object
9189
opts MergeFromOptions
9290
}
9391

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

99-
func (*mergeFromPatch) data(original, modified Object, opts MergeFromOptions) ([]byte, error) {
100-
if opts.OptimisticLock {
97+
// Data implements Patch.
98+
func (s *mergeFromPatch) Data(obj Object) ([]byte, error) {
99+
original := s.from
100+
modified := obj
101+
102+
if s.opts.OptimisticLock {
101103
version := original.GetResourceVersion()
102104
if len(version) == 0 {
103105
return nil, fmt.Errorf("cannot use OptimisticLock, object %q does not have any resource version we can use", original)
@@ -120,64 +122,21 @@ func (*mergeFromPatch) data(original, modified Object, opts MergeFromOptions) ([
120122
return nil, err
121123
}
122124

123-
return jsonpatch.CreateMergePatch(originalJSON, modifiedJSON)
124-
}
125-
126-
// Data implements Patch.
127-
func (s *mergeFromPatch) Data(obj runtime.Object) ([]byte, error) {
128-
fromObject, fromOk := s.from.(Object)
129-
objObject, objOk := obj.(Object)
130-
131-
if fromOk && objOk {
132-
return s.data(fromObject, objObject, s.opts)
133-
}
134-
135-
originalJSON, err := json.Marshal(s.from)
136-
if err != nil {
137-
return nil, err
138-
}
139-
140-
modifiedJSON, err := json.Marshal(obj)
141-
if err != nil {
142-
return nil, err
143-
}
144-
145125
data, err := jsonpatch.CreateMergePatch(originalJSON, modifiedJSON)
146126
if err != nil {
147127
return nil, err
148128
}
149129

150-
if s.opts.OptimisticLock {
151-
dataMap := map[string]interface{}{}
152-
if err := json.Unmarshal(data, &dataMap); err != nil {
153-
return nil, err
154-
}
155-
fromMeta, ok := s.from.(metav1.Object)
156-
if !ok {
157-
return nil, fmt.Errorf("cannot use OptimisticLock, from object %q is not a valid metav1.Object", s.from)
158-
}
159-
resourceVersion := fromMeta.GetResourceVersion()
160-
if len(resourceVersion) == 0 {
161-
return nil, fmt.Errorf("cannot use OptimisticLock, from object %q does not have any resource version we can use", s.from)
162-
}
163-
u := &unstructured.Unstructured{Object: dataMap}
164-
u.SetResourceVersion(resourceVersion)
165-
data, err = json.Marshal(u)
166-
if err != nil {
167-
return nil, err
168-
}
169-
}
170-
171130
return data, nil
172131
}
173132

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

179138
// MergeFromWithOptions creates a Patch that patches using the merge-patch strategy with the given object as base.
180-
func MergeFromWithOptions(obj runtime.Object, opts ...MergeFromOption) Patch {
139+
func MergeFromWithOptions(obj Object, opts ...MergeFromOption) Patch {
181140
options := &MergeFromOptions{}
182141
for _, opt := range opts {
183142
opt.ApplyToMergeFrom(options)

pkg/controller/controllerutil/controllerutil.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,8 @@ func CreateOrPatch(ctx context.Context, c client.Client, obj client.Object, f Mu
249249
}
250250

251251
// Create patches for the object and its possible status.
252-
objPatch := client.MergeFrom(obj.DeepCopyObject())
253-
statusPatch := client.MergeFrom(obj.DeepCopyObject())
252+
objPatch := client.MergeFrom(obj.DeepCopyObject().(client.Object))
253+
statusPatch := client.MergeFrom(obj.DeepCopyObject().(client.Object))
254254

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

0 commit comments

Comments
 (0)