Skip to content

Commit ea680f0

Browse files
authored
Merge pull request #80 from apelisse/oneof-lists
Oneof lists
2 parents 70a0bfd + 94fe617 commit ea680f0

File tree

6 files changed

+79
-40
lines changed

6 files changed

+79
-40
lines changed

merge/union_test.go

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,24 @@ var unionFieldsParser = func() typed.ParseableType {
3939
- name: type
4040
type:
4141
scalar: string
42-
union:
43-
discriminator: type
42+
- name: fieldA
43+
type:
44+
scalar: string
45+
- name: fieldB
46+
type:
47+
scalar: string
48+
unions:
49+
- discriminator: type
4450
fields:
4551
- fieldName: numeric
4652
discriminatedBy: Numeric
4753
- fieldName: string
48-
discriminatedBy: String`)
54+
discriminatedBy: String
55+
- fields:
56+
- fieldName: fieldA
57+
discriminatedBy: FieldA
58+
- fieldName: fieldB
59+
discriminatedBy: FieldB`)
4960
if err != nil {
5061
panic(err)
5162
}
@@ -123,6 +134,31 @@ func TestUnion(t *testing.T) {
123134
},
124135
},
125136
},
137+
"union_apply_multiple_unions": {
138+
Ops: []Operation{
139+
Apply{
140+
Manager: "default",
141+
APIVersion: "v1",
142+
Object: `
143+
string: "some string"
144+
fieldA: "fieldA string"
145+
`,
146+
},
147+
Apply{
148+
Manager: "default",
149+
APIVersion: "v1",
150+
Object: `
151+
numeric: 0
152+
fieldB: "fieldB string"
153+
`,
154+
},
155+
},
156+
Object: `
157+
type: Numeric
158+
numeric: 0
159+
fieldB: "fieldB string"
160+
`,
161+
},
126162
}
127163

128164
for name, test := range tests {

schema/elements.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,12 @@ type Struct struct {
8888
// this list defines the canonical field ordering.
8989
Fields []StructField `yaml:"fields,omitempty"`
9090

91-
// Union is a grouping of fields with special rules. It may refer to
91+
// A Union is a grouping of fields with special rules. It may refer to
9292
// one or more fields in the above list. A given field from the above
9393
// list may be referenced in exactly 0 or 1 places in the below list.
94-
Union *Union `yaml:"union,omitempty"`
94+
// One can have multiple unions in the same struct, but the fields can't
95+
// overlap between unions.
96+
Unions []Union `yaml:"unions,omitempty"`
9597

9698
// ElementRelationship states the relationship between the struct's items.
9799
// * `separable` (or unset) implies that each element is 100% independent.

schema/schemaschema.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,12 @@ var SchemaSchemaYAML = `types:
8484
namedType: structField
8585
elementRelationship: associative
8686
keys: [ "name" ]
87-
- name: union
87+
- name: unions
8888
type:
89-
namedType: union
89+
list:
90+
elementType:
91+
namedType: union
92+
elementRelationship: atomic
9093
- name: elementRelationship
9194
type:
9295
scalar: string

typed/typed.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ func (tv TypedValue) NormalizeUnions(new *TypedValue) (*TypedValue, error) {
163163
v := *w.rhs
164164
w.out = &v
165165
}
166-
if err := normalizeUnion(w); err != nil {
166+
if err := normalizeUnions(w); err != nil {
167167
errs = append(errs, w.error(err)...)
168168
}
169169
}

typed/union.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,26 @@ import (
2424
"sigs.k8s.io/structured-merge-diff/value"
2525
)
2626

27-
func normalizeUnion(w *mergingWalker) error {
27+
func normalizeUnions(w *mergingWalker) error {
2828
atom, found := w.schema.Resolve(w.typeRef)
2929
if !found {
3030
panic(fmt.Sprintf("Unable to resolve schema in normalize union: %v/%v", w.schema, w.typeRef))
3131
}
3232
// Unions can only be in structures, and the struct must not have been removed
33-
if atom.Struct == nil || atom.Struct.Union == nil || w.out == nil {
33+
if atom.Struct == nil || w.out == nil {
3434
return nil
3535
}
3636

3737
old := &value.Map{}
3838
if w.lhs != nil {
3939
old = w.lhs.MapValue
4040
}
41-
return newUnion(atom.Struct.Union).Normalize(old, w.rhs.MapValue, w.out.MapValue)
41+
for _, union := range atom.Struct.Unions {
42+
if err := newUnion(&union).Normalize(old, w.rhs.MapValue, w.out.MapValue); err != nil {
43+
return err
44+
}
45+
}
46+
return nil
4247
}
4348

4449
type discriminated string

typed/union_test.go

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,6 @@ var unionParser = func() typed.ParseableType {
3939
- name: three
4040
type:
4141
scalar: numeric
42-
- name: nodisc
43-
type:
44-
namedType: nondiscriminated
45-
union:
46-
discriminator: discriminator
47-
fields:
48-
- fieldName: one
49-
discriminatedBy: One
50-
- fieldName: two
51-
discriminatedBy: TWO
52-
- fieldName: three
53-
discriminatedBy: three
54-
- name: nondiscriminated
55-
struct:
56-
fields:
5742
- name: a
5843
type:
5944
scalar: numeric
@@ -63,14 +48,22 @@ var unionParser = func() typed.ParseableType {
6348
- name: c
6449
type:
6550
scalar: numeric
66-
union:
51+
unions:
52+
- discriminator: discriminator
6753
fields:
54+
- fieldName: one
55+
discriminatedBy: One
56+
- fieldName: two
57+
discriminatedBy: TWO
58+
- fieldName: three
59+
discriminatedBy: three
60+
- fields:
6861
- fieldName: a
6962
discriminatedBy: A
7063
- fieldName: b
7164
discriminatedBy: B
7265
- fieldName: c
73-
discriminatedBy: C]`)
66+
discriminatedBy: C`)
7467
if err != nil {
7568
panic(err)
7669
}
@@ -98,9 +91,9 @@ func TestNormalizeUnions(t *testing.T) {
9891
},
9992
{
10093
name: "proper union update, no discriminator",
101-
old: `{"nodisc": {"a": 1}}`,
102-
new: `{"nodisc": {"b": 1}}`,
103-
out: `{"nodisc": {"b": 1}}`,
94+
old: `{"a": 1}`,
95+
new: `{"b": 1}`,
96+
out: `{"b": 1}`,
10497
},
10598
{
10699
name: "proper union update from not-set, setting discriminator",
@@ -111,8 +104,8 @@ func TestNormalizeUnions(t *testing.T) {
111104
{
112105
name: "proper union update from not-set, no discriminator",
113106
old: `{}`,
114-
new: `{"nodisc": {"b": 1}}`,
115-
out: `{"nodisc": {"b": 1}}`,
107+
new: `{"b": 1}`,
108+
out: `{"b": 1}`,
116109
},
117110
{
118111
name: "remove union, with discriminator",
@@ -134,15 +127,15 @@ func TestNormalizeUnions(t *testing.T) {
134127
},
135128
{
136129
name: "remove union, no discriminator",
137-
old: `{"nodisc": {"b": 1}}`,
130+
old: `{"b": 1}`,
138131
new: `{}`,
139132
out: `{}`,
140133
},
141134
{
142135
name: "dumb client update, no discriminator",
143-
old: `{"nodisc": {"a": 1}}`,
144-
new: `{"nodisc": {"a": 2, "b": 1}}`,
145-
out: `{"nodisc": {"b": 1}}`,
136+
old: `{"a": 1}`,
137+
new: `{"a": 2, "b": 1}`,
138+
out: `{"b": 1}`,
146139
},
147140
{
148141
name: "dumb client update, sets discriminator",
@@ -158,9 +151,9 @@ func TestNormalizeUnions(t *testing.T) {
158151
},
159152
{
160153
name: "multi-discriminator at the same time",
161-
old: `{"one": 1, "nodisc": {"a": 1}}`,
162-
new: `{"one": 1, "three": 1, "nodisc": {"a": 1, "b": 1}}`,
163-
out: `{"three": 1, "discriminator": "three", "nodisc": {"b": 1}}`,
154+
old: `{"one": 1, "a": 1}`,
155+
new: `{"one": 1, "three": 1, "a": 1, "b": 1}`,
156+
out: `{"three": 1, "discriminator": "three", "b": 1}`,
164157
},
165158
{
166159
name: "change discriminator, nothing else",

0 commit comments

Comments
 (0)