Skip to content

Commit 877aee0

Browse files
authored
Merge pull request #158 from apelisse/return-nil-on-non-change-apply
merge: Apply returns nil object if unchanged
2 parents 333e024 + c840d7e commit 877aee0

File tree

4 files changed

+161
-5
lines changed

4 files changed

+161
-5
lines changed

fieldpath/managers.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,37 @@ func (v versionedSet) Applied() bool {
5858
// what version).
5959
type ManagedFields map[string]VersionedSet
6060

61+
// Equals returns true if the two managedfields are the same, false
62+
// otherwise.
63+
func (lhs ManagedFields) Equals(rhs ManagedFields) bool {
64+
if len(lhs) != len(rhs) {
65+
return false
66+
}
67+
68+
for manager, left := range lhs {
69+
right, ok := rhs[manager]
70+
if !ok {
71+
return false
72+
}
73+
if left.APIVersion() != right.APIVersion() || left.Applied() != right.Applied() {
74+
return false
75+
}
76+
if !left.Set().Equals(right.Set()) {
77+
return false
78+
}
79+
}
80+
return true
81+
}
82+
83+
// Copy the list, this is mostly a shallow copy.
84+
func (lhs ManagedFields) Copy() ManagedFields {
85+
copy := ManagedFields{}
86+
for manager, set := range lhs {
87+
copy[manager] = set
88+
}
89+
return copy
90+
}
91+
6192
// Difference returns a symmetric difference between two Managers. If a
6293
// given user's entry has version X in lhs and version Y in rhs, then
6394
// the return value for that user will be from rhs. If the difference for

fieldpath/managers_test.go

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ var (
3030
_P = fieldpath.MakePathOrDie
3131
)
3232

33-
func TestManagersDifference(t *testing.T) {
33+
func TestManagersEquals(t *testing.T) {
3434
tests := []struct {
3535
name string
3636
lhs fieldpath.ManagedFields
@@ -164,3 +164,123 @@ func TestManagersDifference(t *testing.T) {
164164
})
165165
}
166166
}
167+
168+
func TestManagersDifference(t *testing.T) {
169+
tests := []struct {
170+
name string
171+
lhs fieldpath.ManagedFields
172+
rhs fieldpath.ManagedFields
173+
equal bool
174+
}{
175+
{
176+
name: "Empty sets",
177+
equal: true,
178+
},
179+
{
180+
name: "Same everything",
181+
lhs: fieldpath.ManagedFields{
182+
"one": fieldpath.NewVersionedSet(
183+
_NS(_P("numeric"), _P("string"), _P("bool")),
184+
"v1",
185+
false,
186+
),
187+
},
188+
rhs: fieldpath.ManagedFields{
189+
"one": fieldpath.NewVersionedSet(
190+
_NS(_P("numeric"), _P("string"), _P("bool")),
191+
"v1",
192+
false,
193+
),
194+
},
195+
equal: true,
196+
},
197+
{
198+
name: "Empty RHS",
199+
lhs: fieldpath.ManagedFields{
200+
"default": fieldpath.NewVersionedSet(
201+
_NS(_P("numeric"), _P("string"), _P("bool")),
202+
"v1",
203+
false,
204+
),
205+
},
206+
equal: false,
207+
},
208+
{
209+
name: "Empty LHS",
210+
rhs: fieldpath.ManagedFields{
211+
"default": fieldpath.NewVersionedSet(
212+
_NS(_P("numeric"), _P("string"), _P("bool")),
213+
"v1",
214+
false,
215+
),
216+
},
217+
equal: false,
218+
},
219+
{
220+
name: "Different managers",
221+
lhs: fieldpath.ManagedFields{
222+
"one": fieldpath.NewVersionedSet(
223+
_NS(_P("numeric"), _P("string"), _P("bool")),
224+
"v1",
225+
false,
226+
),
227+
},
228+
rhs: fieldpath.ManagedFields{
229+
"two": fieldpath.NewVersionedSet(
230+
_NS(_P("numeric"), _P("string"), _P("bool")),
231+
"v1",
232+
false,
233+
),
234+
},
235+
equal: false,
236+
},
237+
{
238+
name: "Same manager, different version",
239+
lhs: fieldpath.ManagedFields{
240+
"one": fieldpath.NewVersionedSet(
241+
_NS(_P("numeric"), _P("string"), _P("integer")),
242+
"v1",
243+
false,
244+
),
245+
},
246+
rhs: fieldpath.ManagedFields{
247+
"one": fieldpath.NewVersionedSet(
248+
_NS(_P("numeric"), _P("string"), _P("bool")),
249+
"v2",
250+
false,
251+
),
252+
},
253+
equal: false,
254+
},
255+
{
256+
name: "Set difference",
257+
lhs: fieldpath.ManagedFields{
258+
"one": fieldpath.NewVersionedSet(
259+
_NS(_P("numeric"), _P("string")),
260+
"v1",
261+
false,
262+
),
263+
},
264+
rhs: fieldpath.ManagedFields{
265+
"one": fieldpath.NewVersionedSet(
266+
_NS(_P("string"), _P("bool")),
267+
"v1",
268+
false,
269+
),
270+
},
271+
equal: false,
272+
},
273+
}
274+
275+
for _, test := range tests {
276+
t.Run(fmt.Sprintf(test.name), func(t *testing.T) {
277+
equal := test.lhs.Equals(test.rhs)
278+
if test.equal && !equal {
279+
difference := test.lhs.Difference(test.rhs)
280+
t.Errorf("should be equal, but are different: %v", difference)
281+
} else if !test.equal && equal {
282+
t.Errorf("should not be equal, but they are")
283+
}
284+
})
285+
}
286+
}

internal/fixture/state.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,10 @@ func (s *State) ApplyObject(tv *typed.TypedValue, version fieldpath.APIVersion,
150150
if err != nil {
151151
return err
152152
}
153-
s.Live = new
154153
s.Managers = managers
155-
154+
if new != nil {
155+
s.Live = new
156+
}
156157
return nil
157158
}
158159

merge/update.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,8 @@ func (s *Updater) Update(liveObject, newObject *typed.TypedValue, version fieldp
148148

149149
// Apply should be called when Apply is run, given the current object as
150150
// well as the configuration that is applied. This will merge the object
151-
// and return it.
151+
// and return it. If the object hasn't changed, nil is returned (the
152+
// managers can still have changed though).
152153
func (s *Updater) Apply(liveObject, configObject *typed.TypedValue, version fieldpath.APIVersion, managers fieldpath.ManagedFields, manager string, force bool) (*typed.TypedValue, fieldpath.ManagedFields, error) {
153154
managers = shallowCopyManagers(managers)
154155
var err error
@@ -178,10 +179,13 @@ func (s *Updater) Apply(liveObject, configObject *typed.TypedValue, version fiel
178179
if err != nil {
179180
return nil, fieldpath.ManagedFields{}, fmt.Errorf("failed to prune fields: %v", err)
180181
}
181-
managers, _, err = s.update(liveObject, newObject, version, managers, manager, force)
182+
managers, compare, err := s.update(liveObject, newObject, version, managers, manager, force)
182183
if err != nil {
183184
return nil, fieldpath.ManagedFields{}, err
184185
}
186+
if compare.IsSame() {
187+
newObject = nil
188+
}
185189
return newObject, managers, nil
186190
}
187191

0 commit comments

Comments
 (0)