Skip to content

Commit

Permalink
feat(mergo): direct translation of terraform values
Browse files Browse the repository at this point in the history
Fixes #12
  • Loading branch information
isometry committed May 4, 2024
1 parent 5784d0e commit b871a69
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 18 deletions.
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
## 0.1.0 (Unreleased)
## 0.2.0

FEATURES:

- Direct translation of terraform values.

FIXES:

- Unmarshalling errors with null values ([#12](https://github.com/isometry/terraform-provider-deepmerge/issues/12))

## 0.1.0

FEATURES:

Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ require (
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.13.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240412170617-26222e5d3d56 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6 // indirect
google.golang.org/grpc v1.63.2 // indirect
google.golang.org/protobuf v1.33.0 // indirect
google.golang.org/protobuf v1.34.0 // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -261,14 +261,14 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240412170617-26222e5d3d56 h1:zviK8GX4VlMstrK3JkexM5UHjH1VOkRebH9y3jhSBGk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240412170617-26222e5d3d56/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6 h1:DujSIu+2tC9Ht0aPNA7jgj23Iq8Ewi5sgkQ++wdvonE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4=
google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
2 changes: 2 additions & 0 deletions internal/helpers/decode.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

// Originally copied from https://github.com/hashicorp/terraform-provider-kubernetes/blob/main/internal/framework/provider/functions/encode.go

package helpers

import (
Expand Down
111 changes: 111 additions & 0 deletions internal/helpers/encode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

// Originally copied from https://github.com/hashicorp/terraform-provider-kubernetes/blob/main/internal/framework/provider/functions/encode.go

package helpers

import (
"fmt"

"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
)

func EncodeValue(v attr.Value) (any, error) {
if v.IsNull() {
return nil, nil
}

switch vv := v.(type) {
case basetypes.StringValue:
return vv.ValueString(), nil
case basetypes.NumberValue:
f, _ := vv.ValueBigFloat().Float64()
return f, nil
case basetypes.BoolValue:
return vv.ValueBool(), nil
case basetypes.ObjectValue:
return EncodeObject(vv)
case basetypes.TupleValue:
return EncodeTuple(vv)
case basetypes.MapValue:
return EncodeMap(vv)
case basetypes.ListValue:
return EncodeList(vv)
case basetypes.SetValue:
return EncodeSet(vv)
case basetypes.DynamicValue:
return EncodeValue(vv.UnderlyingValue())
default:
return nil, fmt.Errorf("tried to encode unsupported type: %T: %v", v, vv)
}
}

func EncodeSet(sv basetypes.SetValue) ([]any, error) {
elems := sv.Elements()
size := len(elems)
l := make([]any, size)
for i := 0; i < size; i++ {
var err error
l[i], err = EncodeValue(elems[i])
if err != nil {
return nil, err
}
}
return l, nil
}

func EncodeList(lv basetypes.ListValue) ([]any, error) {
elems := lv.Elements()
size := len(elems)
l := make([]any, size)
for i := 0; i < size; i++ {
var err error
l[i], err = EncodeValue(elems[i])
if err != nil {
return nil, err
}
}
return l, nil
}

func EncodeTuple(tv basetypes.TupleValue) ([]any, error) {
elems := tv.Elements()
size := len(elems)
l := make([]any, size)
for i := 0; i < size; i++ {
var err error
l[i], err = EncodeValue(elems[i])
if err != nil {
return nil, err
}
}
return l, nil
}

func EncodeObject(ov basetypes.ObjectValue) (map[string]any, error) {
attrs := ov.Attributes()
m := make(map[string]any, len(attrs))
for k, v := range attrs {
var err error
m[k], err = EncodeValue(v)
if err != nil {
return nil, err
}
}
return m, nil
}

func EncodeMap(mv basetypes.MapValue) (map[string]any, error) {
elems := mv.Elements()
m := make(map[string]any, len(elems))
for k, v := range elems {
var err error
m[k], err = EncodeValue(v)
if err != nil {
return nil, err
}
}
return m, nil
}
8 changes: 4 additions & 4 deletions internal/helpers/mergo.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package helpers

import (
"context"
"encoding/json"
"fmt"

"dario.cat/mergo"
Expand All @@ -14,11 +13,12 @@ import (
func Mergo(ctx context.Context, objs []types.Dynamic, opts ...func(*mergo.Config)) (merged types.Dynamic, diags diag.Diagnostics) {
maps := make([]map[string]any, len(objs))
for i, obj := range objs {
// TODO: don't rely on String encoding
if err := json.Unmarshal([]byte(obj.String()), &maps[i]); err != nil {
diags.Append(diag.NewErrorDiagnostic(fmt.Sprintf("Error unmarshalling argument %d", i+1), err.Error()))
x, err := EncodeValue(obj)
if err != nil {
diags.Append(diag.NewErrorDiagnostic(fmt.Sprintf("Error encoding argument %d", i+1), err.Error()))
return
}
maps[i] = x.(map[string]any)

Check failure on line 21 in internal/helpers/mergo.go

View workflow job for this annotation

GitHub Actions / Build

type assertion must be checked (forcetypeassert)

Check failure on line 21 in internal/helpers/mergo.go

View workflow job for this annotation

GitHub Actions / Build

type assertion must be checked (forcetypeassert)
}

dst := maps[0]
Expand Down
6 changes: 0 additions & 6 deletions internal/provider/mergo_function.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,6 @@ func (r MergoFunction) Run(ctx context.Context, req function.RunRequest, resp *f
return
}
value := arg.UnderlyingValue()
// if value.IsNull() {
// // skip null values
// resp.Error = function.NewArgumentFuncError(int64(i), "argument must not be null")
// return
// // continue
// }
switch ty := value.Type(ctx); ty {
case types.StringType:
switch option := arg.String(); option {
Expand Down
51 changes: 50 additions & 1 deletion internal/provider/mergo_function_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ func TestMergoFunction_Default(t *testing.T) {
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
// ConfigFile: config.StaticFile("main.tf"),
Config: `
locals {
map1 = {
Expand Down Expand Up @@ -89,6 +88,56 @@ func TestMergoFunction_Default(t *testing.T) {
),
},
},
{
Config: `
locals {
map1 = {
a = null
b = "foo"
}
map2 = {
a = "bar"
b = "baz"
}
}
output "test" {
value = provider::deepmerge::mergo(local.map1, local.map2)
}
`,
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectKnownOutputValue("test",
knownvalue.MapExact(map[string]knownvalue.Check{
"a": knownvalue.StringExact("bar"),
"b": knownvalue.StringExact("baz"),
}),
),
},
},
{
Config: `
locals {
map1 = {
a = "foo"
b = "bar"
}
map2 = {
a = null
b = "bam"
}
}
output "test" {
value = provider::deepmerge::mergo(local.map1, local.map2)
}
`,
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectKnownOutputValue("test",
knownvalue.MapExact(map[string]knownvalue.Check{
"a": knownvalue.Null(),
"b": knownvalue.StringExact("bam"),
}),
),
},
},
},
})
}
Expand Down

0 comments on commit b871a69

Please sign in to comment.