@@ -26,11 +26,39 @@ import (
26
26
"sigs.k8s.io/structured-merge-diff/v3/value"
27
27
)
28
28
29
+ // For the sake of tests, a parser is something that can retrieve a
30
+ // ParseableType.
31
+ type Parser interface {
32
+ Type (string ) typed.ParseableType
33
+ }
34
+
35
+ // SameVersionParser can be used if all the versions are actually using the same type.
36
+ type SameVersionParser struct {
37
+ T typed.ParseableType
38
+ }
39
+
40
+ func (p SameVersionParser ) Type (_ string ) typed.ParseableType {
41
+ return p .T
42
+ }
43
+
44
+ // DeducedParser is a parser that is deduced no matter what the version
45
+ // specified.
46
+ var DeducedParser = SameVersionParser {
47
+ T : typed .DeducedParseableType ,
48
+ }
49
+
29
50
// State of the current test in terms of live object. One can check at
30
51
// any time that Live and Managers match the expectations.
52
+ //
53
+ // The parser will look for the type by using the APIVersion of the
54
+ // object it's trying to parse. If trying to parse a "v1" object, a
55
+ // corresponding "v1" type should exist in the schema. If all the
56
+ // versions should map to the same type, or to a DeducedParseableType,
57
+ // one can use the SameVersionParser or the DeducedParser types defined
58
+ // in this package.
31
59
type State struct {
32
60
Live * typed.TypedValue
33
- Parser typed. ParseableType
61
+ Parser Parser
34
62
Managers fieldpath.ManagedFields
35
63
Updater * merge.Updater
36
64
}
@@ -70,9 +98,9 @@ func FixTabsOrDie(in typed.YAMLObject) typed.YAMLObject {
70
98
return typed .YAMLObject (bytes .Join (lines , []byte {'\n' }))
71
99
}
72
100
73
- func (s * State ) checkInit () error {
101
+ func (s * State ) checkInit (version fieldpath. APIVersion ) error {
74
102
if s .Live == nil {
75
- obj , err := s .Parser .FromUnstructured (nil )
103
+ obj , err := s .Parser .Type ( string ( version )). FromUnstructured (nil )
76
104
if err != nil {
77
105
return fmt .Errorf ("failed to create new empty object: %v" , err )
78
106
}
@@ -82,7 +110,7 @@ func (s *State) checkInit() error {
82
110
}
83
111
84
112
func (s * State ) UpdateObject (tv * typed.TypedValue , version fieldpath.APIVersion , manager string ) error {
85
- err := s .checkInit ()
113
+ err := s .checkInit (version )
86
114
if err != nil {
87
115
return err
88
116
}
@@ -102,15 +130,15 @@ func (s *State) UpdateObject(tv *typed.TypedValue, version fieldpath.APIVersion,
102
130
103
131
// Update the current state with the passed in object
104
132
func (s * State ) Update (obj typed.YAMLObject , version fieldpath.APIVersion , manager string ) error {
105
- tv , err := s .Parser .FromYAML (FixTabsOrDie (obj ))
133
+ tv , err := s .Parser .Type ( string ( version )). FromYAML (FixTabsOrDie (obj ))
106
134
if err != nil {
107
135
return err
108
136
}
109
137
return s .UpdateObject (tv , version , manager )
110
138
}
111
139
112
140
func (s * State ) ApplyObject (tv * typed.TypedValue , version fieldpath.APIVersion , manager string , force bool ) error {
113
- err := s .checkInit ()
141
+ err := s .checkInit (version )
114
142
if err != nil {
115
143
return err
116
144
}
@@ -130,7 +158,7 @@ func (s *State) ApplyObject(tv *typed.TypedValue, version fieldpath.APIVersion,
130
158
131
159
// Apply the passed in object to the current state
132
160
func (s * State ) Apply (obj typed.YAMLObject , version fieldpath.APIVersion , manager string , force bool ) error {
133
- tv , err := s .Parser .FromYAML (FixTabsOrDie (obj ))
161
+ tv , err := s .Parser .Type ( string ( version )). FromYAML (FixTabsOrDie (obj ))
134
162
if err != nil {
135
163
return err
136
164
}
@@ -139,16 +167,20 @@ func (s *State) Apply(obj typed.YAMLObject, version fieldpath.APIVersion, manage
139
167
140
168
// CompareLive takes a YAML string and returns the comparison with the
141
169
// current live object or an error.
142
- func (s * State ) CompareLive (obj typed.YAMLObject ) (* typed.Comparison , error ) {
170
+ func (s * State ) CompareLive (obj typed.YAMLObject , version fieldpath. APIVersion ) (* typed.Comparison , error ) {
143
171
obj = FixTabsOrDie (obj )
144
- if err := s .checkInit (); err != nil {
172
+ if err := s .checkInit (version ); err != nil {
173
+ return nil , err
174
+ }
175
+ tv , err := s .Parser .Type (string (version )).FromYAML (obj )
176
+ if err != nil {
145
177
return nil , err
146
178
}
147
- tv , err := s .Parser . FromYAML ( obj )
179
+ live , err := s .Updater . Converter . Convert ( s . Live , version )
148
180
if err != nil {
149
181
return nil , err
150
182
}
151
- return s . Live .Compare (tv )
183
+ return live .Compare (tv )
152
184
}
153
185
154
186
// dummyConverter doesn't convert, it just returns the same exact object, as long as a version is provided.
@@ -171,7 +203,7 @@ func (dummyConverter) IsMissingVersionError(err error) bool {
171
203
// Operation is a step that will run when building a table-driven test.
172
204
type Operation interface {
173
205
run (* State ) error
174
- preprocess (typed. ParseableType ) (Operation , error )
206
+ preprocess (Parser ) (Operation , error )
175
207
}
176
208
177
209
func hasConflict (conflicts merge.Conflicts , conflict merge.Conflict ) bool {
@@ -214,8 +246,8 @@ func (a Apply) run(state *State) error {
214
246
return p .run (state )
215
247
}
216
248
217
- func (a Apply ) preprocess (parser typed. ParseableType ) (Operation , error ) {
218
- tv , err := parser .FromYAML (FixTabsOrDie (a .Object ))
249
+ func (a Apply ) preprocess (parser Parser ) (Operation , error ) {
250
+ tv , err := parser .Type ( string ( a . APIVersion )). FromYAML (FixTabsOrDie (a .Object ))
219
251
if err != nil {
220
252
return nil , err
221
253
}
@@ -260,7 +292,7 @@ func (a ApplyObject) run(state *State) error {
260
292
return nil
261
293
}
262
294
263
- func (a ApplyObject ) preprocess (parser typed. ParseableType ) (Operation , error ) {
295
+ func (a ApplyObject ) preprocess (parser Parser ) (Operation , error ) {
264
296
return a , nil
265
297
}
266
298
@@ -278,8 +310,8 @@ func (f ForceApply) run(state *State) error {
278
310
return state .Apply (f .Object , f .APIVersion , f .Manager , true )
279
311
}
280
312
281
- func (f ForceApply ) preprocess (parser typed. ParseableType ) (Operation , error ) {
282
- tv , err := parser .FromYAML (FixTabsOrDie (f .Object ))
313
+ func (f ForceApply ) preprocess (parser Parser ) (Operation , error ) {
314
+ tv , err := parser .Type ( string ( f . APIVersion )). FromYAML (FixTabsOrDie (f .Object ))
283
315
if err != nil {
284
316
return nil , err
285
317
}
@@ -304,7 +336,7 @@ func (f ForceApplyObject) run(state *State) error {
304
336
return state .ApplyObject (f .Object , f .APIVersion , f .Manager , true )
305
337
}
306
338
307
- func (f ForceApplyObject ) preprocess (parser typed. ParseableType ) (Operation , error ) {
339
+ func (f ForceApplyObject ) preprocess (parser Parser ) (Operation , error ) {
308
340
return f , nil
309
341
}
310
342
@@ -322,8 +354,8 @@ func (u Update) run(state *State) error {
322
354
return state .Update (u .Object , u .APIVersion , u .Manager )
323
355
}
324
356
325
- func (u Update ) preprocess (parser typed. ParseableType ) (Operation , error ) {
326
- tv , err := parser .FromYAML (FixTabsOrDie (u .Object ))
357
+ func (u Update ) preprocess (parser Parser ) (Operation , error ) {
358
+ tv , err := parser .Type ( string ( u . APIVersion )). FromYAML (FixTabsOrDie (u .Object ))
327
359
if err != nil {
328
360
return nil , err
329
361
}
@@ -348,7 +380,7 @@ func (u UpdateObject) run(state *State) error {
348
380
return state .UpdateObject (u .Object , u .APIVersion , u .Manager )
349
381
}
350
382
351
- func (f UpdateObject ) preprocess (parser typed. ParseableType ) (Operation , error ) {
383
+ func (f UpdateObject ) preprocess (parser Parser ) (Operation , error ) {
352
384
return f , nil
353
385
}
354
386
@@ -364,6 +396,9 @@ type TestCase struct {
364
396
// Object, if not empty, is the object as it's expected to
365
397
// be after all the operations are run.
366
398
Object typed.YAMLObject
399
+ // APIVersion should be set if the object is non-empty and
400
+ // describes the version of the object to compare to.
401
+ APIVersion fieldpath.APIVersion
367
402
// Managed, if not nil, is the ManagedFields as expected
368
403
// after all operations are run.
369
404
Managed fieldpath.ManagedFields
@@ -372,18 +407,18 @@ type TestCase struct {
372
407
}
373
408
374
409
// Test runs the test-case using the given parser and a dummy converter.
375
- func (tc TestCase ) Test (parser typed. ParseableType ) error {
410
+ func (tc TestCase ) Test (parser Parser ) error {
376
411
return tc .TestWithConverter (parser , & dummyConverter {})
377
412
}
378
413
379
414
// Bench runs the test-case using the given parser and a dummy converter, but
380
415
// doesn't check exit conditions--see the comment for BenchWithConverter.
381
- func (tc TestCase ) Bench (parser typed. ParseableType ) error {
416
+ func (tc TestCase ) Bench (parser Parser ) error {
382
417
return tc .BenchWithConverter (parser , & dummyConverter {})
383
418
}
384
419
385
420
// Preprocess all the operations by parsing the yaml before-hand.
386
- func (tc TestCase ) PreprocessOperations (parser typed. ParseableType ) error {
421
+ func (tc TestCase ) PreprocessOperations (parser Parser ) error {
387
422
for i := range tc .Ops {
388
423
op , err := tc .Ops [i ].preprocess (parser )
389
424
if err != nil {
@@ -398,7 +433,7 @@ func (tc TestCase) PreprocessOperations(parser typed.ParseableType) error {
398
433
// but doesn't do any comparison operations aftewards; you should probably run
399
434
// TestWithConverter once and reset the benchmark, to make sure the test case
400
435
// actually passes..
401
- func (tc TestCase ) BenchWithConverter (parser typed. ParseableType , converter merge.Converter ) error {
436
+ func (tc TestCase ) BenchWithConverter (parser Parser , converter merge.Converter ) error {
402
437
state := State {
403
438
Updater : & merge.Updater {Converter : converter },
404
439
Parser : parser ,
@@ -418,7 +453,7 @@ func (tc TestCase) BenchWithConverter(parser typed.ParseableType, converter merg
418
453
}
419
454
420
455
// TestWithConverter runs the test-case using the given parser and converter.
421
- func (tc TestCase ) TestWithConverter (parser typed. ParseableType , converter merge.Converter ) error {
456
+ func (tc TestCase ) TestWithConverter (parser Parser , converter merge.Converter ) error {
422
457
state := State {
423
458
Updater : & merge.Updater {Converter : converter },
424
459
Parser : parser ,
@@ -434,8 +469,6 @@ func (tc TestCase) TestWithConverter(parser typed.ParseableType, converter merge
434
469
return fmt .Errorf ("fails if unions are on: %v" , err )
435
470
}
436
471
}
437
- // We currently don't have any test that converts, we can take
438
- // care of that later.
439
472
for i , ops := range tc .Ops {
440
473
err := ops .run (& state )
441
474
if err != nil {
@@ -445,7 +478,7 @@ func (tc TestCase) TestWithConverter(parser typed.ParseableType, converter merge
445
478
446
479
// If LastObject was specified, compare it with LiveState
447
480
if tc .Object != typed .YAMLObject ("" ) {
448
- comparison , err := state .CompareLive (tc .Object )
481
+ comparison , err := state .CompareLive (tc .Object , tc . APIVersion )
449
482
if err != nil {
450
483
return fmt .Errorf ("failed to compare live with config: %v" , err )
451
484
}
0 commit comments