Skip to content

Commit 382e16c

Browse files
committed
Add test for changing struct from granular to atomic
1 parent b84068c commit 382e16c

File tree

3 files changed

+152
-0
lines changed

3 files changed

+152
-0
lines changed

internal/fixture/state.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,32 @@ 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 it.
389+
// This can be used to test the behavior of making backward compatible schema changes, e.g.
390+
// setting "elementRelationship: atomic" on an existing struct. It also may be used to ensure that
391+
// 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+
liveWithNewSchema, err := typed.AsTyped(state.Live.AsValue(), &cs.Parser.Schema, state.Live.TypeRef())
403+
if err != nil {
404+
return err
405+
}
406+
state.Live = liveWithNewSchema
407+
return nil
408+
}
409+
410+
func (cs ChangeParser) preprocess(_ Parser) (Operation, error) {
411+
return cs, nil
412+
}
413+
388414
// TestCase is the list of operations that need to be run, as well as
389415
// the object/managedfields as they are supposed to look like after all
390416
// the operations have been successfully performed. If Object/Managed is

merge/schema_change_test.go

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
Copyright 2018 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package merge_test
18+
19+
import (
20+
"testing"
21+
22+
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
23+
. "sigs.k8s.io/structured-merge-diff/v4/internal/fixture"
24+
"sigs.k8s.io/structured-merge-diff/v4/typed"
25+
)
26+
27+
28+
var structParser = func() *typed.Parser {
29+
oldParser, err := typed.NewParser(`types:
30+
- name: v1
31+
map:
32+
fields:
33+
- name: struct
34+
type:
35+
namedType: struct
36+
- name: struct
37+
map:
38+
fields:
39+
- name: numeric
40+
type:
41+
scalar: numeric
42+
- name: string
43+
type:
44+
scalar: string`)
45+
if err != nil {
46+
panic(err)
47+
}
48+
return oldParser
49+
}()
50+
51+
var structWithAtomicParser = func() *typed.Parser {
52+
newParser, err := typed.NewParser( `types:
53+
- name: v1
54+
map:
55+
fields:
56+
- name: struct
57+
type:
58+
namedType: struct
59+
- name: struct
60+
map:
61+
fields:
62+
- name: numeric
63+
type:
64+
scalar: numeric
65+
- name: string
66+
type:
67+
scalar: string
68+
elementRelationship: atomic`)
69+
if err != nil {
70+
panic(err)
71+
}
72+
return newParser
73+
}()
74+
75+
func TestSchemaChanges(t *testing.T) {
76+
tests := map[string]TestCase{
77+
"change-struct-to-atomic": {
78+
Ops: []Operation{
79+
Apply{
80+
Manager: "one",
81+
Object: `
82+
struct:
83+
numeric: 1
84+
`,
85+
APIVersion: "v1",
86+
},
87+
ChangeParser{Parser: structWithAtomicParser},
88+
Apply{
89+
Manager: "two",
90+
Object: `
91+
struct:
92+
string: "string"
93+
`,
94+
APIVersion: "v1",
95+
},
96+
},
97+
Object: `
98+
struct:
99+
string: "string"
100+
`,
101+
APIVersion: "v1",
102+
Managed: fieldpath.ManagedFields{
103+
"two": fieldpath.NewVersionedSet(
104+
_NS(
105+
_P("struct"),
106+
),
107+
"v1",
108+
true,
109+
),
110+
},
111+
},
112+
}
113+
114+
for name, test := range tests {
115+
t.Run(name, func(t *testing.T) {
116+
if err := test.Test(structParser); err != nil {
117+
t.Fatal(err)
118+
}
119+
})
120+
}
121+
}

typed/typed.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ func (tv TypedValue) AsValue() value.Value {
7171
return tv.value
7272
}
7373

74+
// Schema removes the schema from the TypedValue.
75+
func (tv TypedValue) Schema() *schema.Schema {
76+
return tv.schema
77+
}
78+
7479
// Validate returns an error with a list of every spec violation.
7580
func (tv TypedValue) Validate() error {
7681
w := tv.walker()

0 commit comments

Comments
 (0)