Skip to content

Commit 411eaee

Browse files
committed
Add fixup of atomic<->granular schema changes
1 parent b84068c commit 411eaee

21 files changed

+1353
-1035
lines changed

fieldpath/managers.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020

2121
// APIVersion describes the version of an object or of a fieldset.
2222
type APIVersion string
23+
type SchemaHash []byte
2324

2425
type VersionedSet interface {
2526
Set() *Set

fieldpath/managers_test.go

Lines changed: 24 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -44,112 +44,56 @@ func TestManagersEquals(t *testing.T) {
4444
{
4545
name: "Empty RHS",
4646
lhs: fieldpath.ManagedFields{
47-
"default": fieldpath.NewVersionedSet(
48-
_NS(_P("numeric"), _P("string"), _P("bool")),
49-
"v1",
50-
false,
51-
),
47+
"default": fieldpath.NewVersionedSet(_NS(_P("numeric"), _P("string"), _P("bool")), "v1", false),
5248
},
5349
out: fieldpath.ManagedFields{
54-
"default": fieldpath.NewVersionedSet(
55-
_NS(_P("numeric"), _P("string"), _P("bool")),
56-
"v1",
57-
false,
58-
),
50+
"default": fieldpath.NewVersionedSet(_NS(_P("numeric"), _P("string"), _P("bool")), "v1", false),
5951
},
6052
},
6153
{
6254
name: "Empty LHS",
6355
rhs: fieldpath.ManagedFields{
64-
"default": fieldpath.NewVersionedSet(
65-
_NS(_P("numeric"), _P("string"), _P("bool")),
66-
"v1",
67-
false,
68-
),
56+
"default": fieldpath.NewVersionedSet(_NS(_P("numeric"), _P("string"), _P("bool")), "v1", false),
6957
},
7058
out: fieldpath.ManagedFields{
71-
"default": fieldpath.NewVersionedSet(
72-
_NS(_P("numeric"), _P("string"), _P("bool")),
73-
"v1",
74-
false,
75-
),
59+
"default": fieldpath.NewVersionedSet(_NS(_P("numeric"), _P("string"), _P("bool")), "v1", false),
7660
},
7761
},
7862
{
7963
name: "Different managers",
8064
lhs: fieldpath.ManagedFields{
81-
"one": fieldpath.NewVersionedSet(
82-
_NS(_P("numeric"), _P("string"), _P("bool")),
83-
"v1",
84-
false,
85-
),
65+
"one": fieldpath.NewVersionedSet(_NS(_P("numeric"), _P("string"), _P("bool")), "v1", false),
8666
},
8767
rhs: fieldpath.ManagedFields{
88-
"two": fieldpath.NewVersionedSet(
89-
_NS(_P("numeric"), _P("string"), _P("bool")),
90-
"v1",
91-
false,
92-
),
68+
"two": fieldpath.NewVersionedSet(_NS(_P("numeric"), _P("string"), _P("bool")), "v1", false),
9369
},
9470
out: fieldpath.ManagedFields{
95-
"one": fieldpath.NewVersionedSet(
96-
_NS(_P("numeric"), _P("string"), _P("bool")),
97-
"v1",
98-
false,
99-
),
100-
"two": fieldpath.NewVersionedSet(
101-
_NS(_P("numeric"), _P("string"), _P("bool")),
102-
"v1",
103-
false,
104-
),
71+
"one": fieldpath.NewVersionedSet(_NS(_P("numeric"), _P("string"), _P("bool")), "v1", false),
72+
"two": fieldpath.NewVersionedSet(_NS(_P("numeric"), _P("string"), _P("bool")), "v1", false),
10573
},
10674
},
10775
{
10876
name: "Same manager, different version",
10977
lhs: fieldpath.ManagedFields{
110-
"one": fieldpath.NewVersionedSet(
111-
_NS(_P("numeric"), _P("string"), _P("integer")),
112-
"v1",
113-
false,
114-
),
78+
"one": fieldpath.NewVersionedSet(_NS(_P("numeric"), _P("string"), _P("integer")), "v1", false),
11579
},
11680
rhs: fieldpath.ManagedFields{
117-
"one": fieldpath.NewVersionedSet(
118-
_NS(_P("numeric"), _P("string"), _P("bool")),
119-
"v2",
120-
false,
121-
),
81+
"one": fieldpath.NewVersionedSet(_NS(_P("numeric"), _P("string"), _P("bool")), "v2", false),
12282
},
12383
out: fieldpath.ManagedFields{
124-
"one": fieldpath.NewVersionedSet(
125-
_NS(_P("numeric"), _P("string"), _P("bool")),
126-
"v2",
127-
false,
128-
),
84+
"one": fieldpath.NewVersionedSet(_NS(_P("numeric"), _P("string"), _P("bool")), "v2", false),
12985
},
13086
},
13187
{
13288
name: "Set difference",
13389
lhs: fieldpath.ManagedFields{
134-
"one": fieldpath.NewVersionedSet(
135-
_NS(_P("numeric"), _P("string")),
136-
"v1",
137-
false,
138-
),
90+
"one": fieldpath.NewVersionedSet(_NS(_P("numeric"), _P("string")), "v1", false),
13991
},
14092
rhs: fieldpath.ManagedFields{
141-
"one": fieldpath.NewVersionedSet(
142-
_NS(_P("string"), _P("bool")),
143-
"v1",
144-
false,
145-
),
93+
"one": fieldpath.NewVersionedSet(_NS(_P("string"), _P("bool")), "v1", false),
14694
},
14795
out: fieldpath.ManagedFields{
148-
"one": fieldpath.NewVersionedSet(
149-
_NS(_P("numeric"), _P("bool")),
150-
"v1",
151-
false,
152-
),
96+
"one": fieldpath.NewVersionedSet(_NS(_P("numeric"), _P("bool")), "v1", false),
15397
},
15498
},
15599
}
@@ -179,94 +123,54 @@ func TestManagersDifference(t *testing.T) {
179123
{
180124
name: "Same everything",
181125
lhs: fieldpath.ManagedFields{
182-
"one": fieldpath.NewVersionedSet(
183-
_NS(_P("numeric"), _P("string"), _P("bool")),
184-
"v1",
185-
false,
186-
),
126+
"one": fieldpath.NewVersionedSet(_NS(_P("numeric"), _P("string"), _P("bool")), "v1", false),
187127
},
188128
rhs: fieldpath.ManagedFields{
189-
"one": fieldpath.NewVersionedSet(
190-
_NS(_P("numeric"), _P("string"), _P("bool")),
191-
"v1",
192-
false,
193-
),
129+
"one": fieldpath.NewVersionedSet(_NS(_P("numeric"), _P("string"), _P("bool")), "v1", false),
194130
},
195131
equal: true,
196132
},
197133
{
198134
name: "Empty RHS",
199135
lhs: fieldpath.ManagedFields{
200-
"default": fieldpath.NewVersionedSet(
201-
_NS(_P("numeric"), _P("string"), _P("bool")),
202-
"v1",
203-
false,
204-
),
136+
"default": fieldpath.NewVersionedSet(_NS(_P("numeric"), _P("string"), _P("bool")), "v1", false),
205137
},
206138
equal: false,
207139
},
208140
{
209141
name: "Empty LHS",
210142
rhs: fieldpath.ManagedFields{
211-
"default": fieldpath.NewVersionedSet(
212-
_NS(_P("numeric"), _P("string"), _P("bool")),
213-
"v1",
214-
false,
215-
),
143+
"default": fieldpath.NewVersionedSet(_NS(_P("numeric"), _P("string"), _P("bool")), "v1", false),
216144
},
217145
equal: false,
218146
},
219147
{
220148
name: "Different managers",
221149
lhs: fieldpath.ManagedFields{
222-
"one": fieldpath.NewVersionedSet(
223-
_NS(_P("numeric"), _P("string"), _P("bool")),
224-
"v1",
225-
false,
226-
),
150+
"one": fieldpath.NewVersionedSet(_NS(_P("numeric"), _P("string"), _P("bool")), "v1", false),
227151
},
228152
rhs: fieldpath.ManagedFields{
229-
"two": fieldpath.NewVersionedSet(
230-
_NS(_P("numeric"), _P("string"), _P("bool")),
231-
"v1",
232-
false,
233-
),
153+
"two": fieldpath.NewVersionedSet(_NS(_P("numeric"), _P("string"), _P("bool")), "v1", false),
234154
},
235155
equal: false,
236156
},
237157
{
238158
name: "Same manager, different version",
239159
lhs: fieldpath.ManagedFields{
240-
"one": fieldpath.NewVersionedSet(
241-
_NS(_P("numeric"), _P("string"), _P("integer")),
242-
"v1",
243-
false,
244-
),
160+
"one": fieldpath.NewVersionedSet(_NS(_P("numeric"), _P("string"), _P("integer")), "v1", false),
245161
},
246162
rhs: fieldpath.ManagedFields{
247-
"one": fieldpath.NewVersionedSet(
248-
_NS(_P("numeric"), _P("string"), _P("bool")),
249-
"v2",
250-
false,
251-
),
163+
"one": fieldpath.NewVersionedSet(_NS(_P("numeric"), _P("string"), _P("bool")), "v2", false),
252164
},
253165
equal: false,
254166
},
255167
{
256168
name: "Set difference",
257169
lhs: fieldpath.ManagedFields{
258-
"one": fieldpath.NewVersionedSet(
259-
_NS(_P("numeric"), _P("string")),
260-
"v1",
261-
false,
262-
),
170+
"one": fieldpath.NewVersionedSet(_NS(_P("numeric"), _P("string")), "v1", false),
263171
},
264172
rhs: fieldpath.ManagedFields{
265-
"one": fieldpath.NewVersionedSet(
266-
_NS(_P("string"), _P("bool")),
267-
"v1",
268-
false,
269-
),
173+
"one": fieldpath.NewVersionedSet(_NS(_P("string"), _P("bool")), "v1", false),
270174
},
271175
equal: false,
272176
},

internal/fixture/state.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,33 @@ func (f UpdateObject) preprocess(parser Parser) (Operation, error) {
385385
return f, nil
386386
}
387387

388+
// ChangeParser is a type of operation. It simulates making changes a schema without versioning
389+
// the schema. This can be used to test the behavior of making backward compatible schema changes,
390+
// e.g. setting "elementRelationship: atomic" on an existing struct. It also may be used to ensure
391+
// that backward incompatible changes are detected appropriately.
392+
type ChangeParser struct {
393+
Parser *typed.Parser
394+
}
395+
396+
var _ Operation = &ChangeParser{}
397+
398+
func (cs ChangeParser) run(state *State) error {
399+
state.Parser = cs.Parser
400+
// Swap the schema in for use with the live object so it merges.
401+
// If the schema is incompatible, this will fail validation.
402+
403+
liveWithNewSchema, err := typed.AsTyped(state.Live.AsValue(), &cs.Parser.Schema, state.Live.TypeRef())
404+
if err != nil {
405+
return err
406+
}
407+
state.Live = liveWithNewSchema
408+
return nil
409+
}
410+
411+
func (cs ChangeParser) preprocess(_ Parser) (Operation, error) {
412+
return cs, nil
413+
}
414+
388415
// TestCase is the list of operations that need to be run, as well as
389416
// the object/managedfields as they are supposed to look like after all
390417
// the operations have been successfully performed. If Object/Managed is

merge/conflict_test.go

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,14 @@ var (
3434

3535
func TestNewFromSets(t *testing.T) {
3636
got := merge.ConflictsFromManagers(fieldpath.ManagedFields{
37-
"Bob": fieldpath.NewVersionedSet(
38-
_NS(
39-
_P("key"),
40-
_P("list", _KBF("key", "a", "id", 2), "id"),
41-
),
42-
"v1",
43-
false,
44-
),
45-
"Alice": fieldpath.NewVersionedSet(
46-
_NS(
47-
_P("value"),
48-
_P("list", _KBF("key", "a", "id", 2), "key"),
49-
),
50-
"v1",
51-
false,
52-
),
37+
"Bob": fieldpath.NewVersionedSet(_NS(
38+
_P("key"),
39+
_P("list", _KBF("key", "a", "id", 2), "id"),
40+
), "v1", false),
41+
"Alice": fieldpath.NewVersionedSet(_NS(
42+
_P("value"),
43+
_P("list", _KBF("key", "a", "id", 2), "key"),
44+
), "v1", false),
5345
})
5446
wanted := `conflicts with "Alice":
5547
- .value
@@ -64,22 +56,14 @@ conflicts with "Bob":
6456

6557
func TestToSet(t *testing.T) {
6658
conflicts := merge.ConflictsFromManagers(fieldpath.ManagedFields{
67-
"Bob": fieldpath.NewVersionedSet(
68-
_NS(
69-
_P("key"),
70-
_P("list", _KBF("key", "a", "id", 2), "id"),
71-
),
72-
"v1",
73-
false,
74-
),
75-
"Alice": fieldpath.NewVersionedSet(
76-
_NS(
77-
_P("value"),
78-
_P("list", _KBF("key", "a", "id", 2), "key"),
79-
),
80-
"v1",
81-
false,
82-
),
59+
"Bob": fieldpath.NewVersionedSet(_NS(
60+
_P("key"),
61+
_P("list", _KBF("key", "a", "id", 2), "id"),
62+
), "v1", false),
63+
"Alice": fieldpath.NewVersionedSet(_NS(
64+
_P("value"),
65+
_P("list", _KBF("key", "a", "id", 2), "key"),
66+
), "v1", false),
8367
})
8468
expected := fieldpath.NewSet(
8569
_P("key"),

0 commit comments

Comments
 (0)