Skip to content

Commit 0a9fe1a

Browse files
committed
fix: include append logic in no_null_override transformer (#83)
Signed-off-by: Tim Balzer <[email protected]>
1 parent 443c7df commit 0a9fe1a

File tree

2 files changed

+94
-9
lines changed

2 files changed

+94
-9
lines changed

internal/provider/mergo_function.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ func (r MergoFunction) Run(ctx context.Context, req function.RunRequest, resp *f
6060
opts := make([]func(*mergo.Config), 0)
6161
with_override := true
6262
no_null_override := false
63+
with_append := false
6364

6465
for i, arg := range args {
6566
if arg.IsNull() {
@@ -82,6 +83,7 @@ func (r MergoFunction) Run(ctx context.Context, req function.RunRequest, resp *f
8283

8384
case "append", "append_lists":
8485
opts = append(opts, mergo.WithAppendSlice)
86+
with_append = true
8587

8688
default:
8789
resp.Error = function.NewArgumentFuncError(int64(i), "unrecognised option")
@@ -105,7 +107,7 @@ func (r MergoFunction) Run(ctx context.Context, req function.RunRequest, resp *f
105107
}
106108

107109
if no_null_override {
108-
opts = append(opts, mergo.WithTransformers(noNullOverrideTransformer{}))
110+
opts = append(opts, mergo.WithTransformers(noNullOverrideTransformer{ with_append: with_append }))
109111
}
110112

111113
merged, diags := helpers.Mergo(ctx, objs, opts...)
@@ -117,19 +119,21 @@ func (r MergoFunction) Run(ctx context.Context, req function.RunRequest, resp *f
117119
resp.Error = function.ConcatFuncErrors(resp.Result.Set(ctx, &merged))
118120
}
119121

120-
type noNullOverrideTransformer struct{}
122+
type noNullOverrideTransformer struct{
123+
with_append bool
124+
}
121125

122126
func (t noNullOverrideTransformer) Transformer(typ reflect.Type) func(dst, src reflect.Value) error {
123127
if typ.Kind() == reflect.Map {
124128
return func(dst, src reflect.Value) error {
125-
deepMergeMaps(dst, src)
129+
deepMergeMaps(dst, src, t.with_append)
126130
return nil
127131
}
128132
}
129133
return nil
130134
}
131135

132-
func deepMergeMaps(dst, src reflect.Value) reflect.Value {
136+
func deepMergeMaps(dst, src reflect.Value, appendSlice bool) reflect.Value {
133137
for _, key := range src.MapKeys() {
134138
srcElem := src.MapIndex(key)
135139
dstElem := dst.MapIndex(key)
@@ -145,13 +149,13 @@ func deepMergeMaps(dst, src reflect.Value) reflect.Value {
145149

146150
if srcElem.Kind() == reflect.Map && dstElem.Kind() == reflect.Map {
147151
// recursive call
148-
newValue := deepMergeMaps(dstElem, srcElem)
152+
newValue := deepMergeMaps(dstElem, srcElem, appendSlice)
149153
dst.SetMapIndex(key, newValue)
154+
} else if !srcElem.IsValid() { // skip override of nil values
155+
continue;
156+
} else if srcElem.Kind() == reflect.Slice && dstElem.Kind() == reflect.Slice && appendSlice { // handle append
157+
dst.SetMapIndex(key, reflect.AppendSlice(dstElem, srcElem))
150158
} else {
151-
if !srcElem.IsValid() { // skip override of nil values
152-
continue
153-
}
154-
155159
dst.SetMapIndex(key, srcElem)
156160
}
157161
}

internal/provider/mergo_function_test.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,87 @@ func TestMergoFunction_Default(t *testing.T) {
216216
})
217217
}
218218

219+
func TestMergoFunction_Append_NoNullOverride(t *testing.T) {
220+
resource.UnitTest(t, resource.TestCase{
221+
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
222+
tfversion.SkipBelow(version.Must(version.NewVersion("1.8.0"))),
223+
},
224+
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
225+
Steps: []resource.TestStep{
226+
{
227+
Config: `
228+
locals {
229+
map1 = {
230+
x1 = {
231+
y1 = "foo"
232+
y2 = 1
233+
}
234+
}
235+
map2 = {
236+
x1 = {
237+
y2 = 2
238+
y3 = [1, 2, 3]
239+
}
240+
x2 = {
241+
y4 = {
242+
a = "hello"
243+
b = "world"
244+
}
245+
}
246+
}
247+
map3 = {
248+
x1 = {
249+
y1 = null
250+
y3 = [4, 5, 6]
251+
}
252+
x2 = {
253+
y4 = {
254+
b = "mergo"
255+
c = ["a", 2, ["b"]]
256+
}
257+
}
258+
}
259+
}
260+
output "test" {
261+
value = provider::deepmerge::mergo(local.map1, local.map2, local.map3, "append", "no_null_override")
262+
}
263+
`,
264+
ConfigStateChecks: []statecheck.StateCheck{
265+
statecheck.ExpectKnownOutputValue("test",
266+
knownvalue.MapExact(map[string]knownvalue.Check{
267+
"x1": knownvalue.MapExact(map[string]knownvalue.Check{
268+
"y1": knownvalue.StringExact("foo"),
269+
"y2": knownvalue.Int64Exact(2),
270+
"y3": knownvalue.ListExact([]knownvalue.Check{
271+
knownvalue.Int64Exact(1),
272+
knownvalue.Int64Exact(2),
273+
knownvalue.Int64Exact(3),
274+
knownvalue.Int64Exact(4),
275+
knownvalue.Int64Exact(5),
276+
knownvalue.Int64Exact(6),
277+
}),
278+
}),
279+
"x2": knownvalue.MapExact(map[string]knownvalue.Check{
280+
"y4": knownvalue.MapExact(map[string]knownvalue.Check{
281+
"a": knownvalue.StringExact("hello"),
282+
"b": knownvalue.StringExact("mergo"),
283+
"c": knownvalue.ListExact([]knownvalue.Check{
284+
knownvalue.StringExact("a"),
285+
knownvalue.Int64Exact(2),
286+
knownvalue.ListExact([]knownvalue.Check{
287+
knownvalue.StringExact("b"),
288+
}),
289+
}),
290+
}),
291+
}),
292+
}),
293+
),
294+
},
295+
},
296+
},
297+
})
298+
}
299+
219300
func TestMergoFunction_Append(t *testing.T) {
220301
resource.UnitTest(t, resource.TestCase{
221302
TerraformVersionChecks: []tfversion.TerraformVersionCheck{

0 commit comments

Comments
 (0)