summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Henderson <dhenderson@gmail.com>2017-05-06 12:49:39 -0400
committerDave Henderson <dhenderson@gmail.com>2017-05-06 12:58:05 -0400
commitf358f185e00bf92bf2095b1eebcc4c950588488d (patch)
tree48f6def4ef5162c7d9b6da2f9e2fa1d0b58d78d8
parent582a78b12aa119bf7dc46b6722b5423a456bb456 (diff)
Fixing bug with 'has' and 'datasource' around referencing sub-maps in nested maps
Signed-off-by: Dave Henderson <dhenderson@gmail.com>
-rw-r--r--data_test.go8
-rw-r--r--gomplate_test.go5
-rw-r--r--test/integration/datasources_file.bats12
-rw-r--r--test/integration/typeconv_funcs.bats19
-rw-r--r--typeconv.go17
-rw-r--r--typeconv_test.go11
6 files changed, 52 insertions, 20 deletions
diff --git a/data_test.go b/data_test.go
index d4f2000d..965a2494 100644
--- a/data_test.go
+++ b/data_test.go
@@ -130,13 +130,13 @@ func TestDatasource(t *testing.T) {
data := &Data{
Sources: sources,
}
- expected := map[string]interface{}{"hello": "world"}
+ expected := map[string]interface{}{"hello": map[interface{}]interface{}{"cruel": "world"}}
actual := data.Datasource("foo")
- assert.Equal(t, expected["hello"], actual["hello"])
+ assert.Equal(t, expected, actual)
}
- test("json", "application/json", `{"hello":"world"}`)
- test("yml", "application/yaml", `hello: world`)
+ test("json", "application/json", `{"hello":{"cruel":"world"}}`)
+ test("yml", "application/yaml", "hello:\n cruel: world\n")
}
func TestDatasourceExists(t *testing.T) {
diff --git a/gomplate_test.go b/gomplate_test.go
index e35e6660..1d55751b 100644
--- a/gomplate_test.go
+++ b/gomplate_test.go
@@ -125,8 +125,9 @@ func TestHasTemplate(t *testing.T) {
"has": ty.Has,
},
}
- assert.Equal(t, "true", testTemplate(g, `{{has ("foo: true" | yaml) "foo"}}`))
- assert.Equal(t, "false", testTemplate(g, `{{has ("foo: true" | yaml) "bar"}}`))
+ assert.Equal(t, "true", testTemplate(g, `{{has ("foo:\n bar: true" | yaml) "foo"}}`))
+ assert.Equal(t, "true", testTemplate(g, `{{has ("foo:\n bar: true" | yaml).foo "bar"}}`))
+ assert.Equal(t, "false", testTemplate(g, `{{has ("foo: true" | yaml) "bah"}}`))
tmpl := `{{- $data := yaml "foo: bar\nbaz: qux\n" }}
{{- if (has $data "baz") }}
{{- $data.baz }}
diff --git a/test/integration/datasources_file.bats b/test/integration/datasources_file.bats
index 1a3ad824..9e22a834 100644
--- a/test/integration/datasources_file.bats
+++ b/test/integration/datasources_file.bats
@@ -13,17 +13,17 @@ function teardown () {
}
@test "supports json datasource file" {
- echo '{"foo": "bar"}' > $tmpdir/config.json
- gomplate -d config=$tmpdir/config.json -i '{{(datasource "config").foo}}'
+ echo '{"foo": {"bar": "baz"}}' > $tmpdir/config.json
+ gomplate -d config=$tmpdir/config.json -i '{{(datasource "config").foo.bar}}'
[ "$status" -eq 0 ]
- [[ "${output}" == "bar" ]]
+ [[ "${output}" == "baz" ]]
}
@test "supports YAML datasource file" {
- echo 'foo: bar' > $tmpdir/config.yml
- gomplate -d config=$tmpdir/config.yml -i '{{(datasource "config").foo}}'
+ echo -e 'foo:\n bar: baz' > $tmpdir/config.yml
+ gomplate -d config=$tmpdir/config.yml -i '{{(datasource "config").foo.bar}}'
[ "$status" -eq 0 ]
- [[ "${output}" == "bar" ]]
+ [[ "${output}" == "baz" ]]
}
@test "ds alias" {
diff --git a/test/integration/typeconv_funcs.bats b/test/integration/typeconv_funcs.bats
new file mode 100644
index 00000000..9127915e
--- /dev/null
+++ b/test/integration/typeconv_funcs.bats
@@ -0,0 +1,19 @@
+#!/usr/bin/env bats
+
+load helper
+
+tmpdir=$(mktemp -u)
+
+function setup () {
+ mkdir -p $tmpdir
+}
+
+function teardown () {
+ rm -rf $tmpdir || true
+}
+
+@test "'has' can handle sub-maps in nested maps" {
+ gomplate -d config=$tmpdir/config.yml -i '{{ has ("foo:\n bar:\n baz: qux" | yaml).foo.bar "baz"}}'
+ [ "$status" -eq 0 ]
+ [[ "${output}" == "true" ]]
+}
diff --git a/typeconv.go b/typeconv.go
index 27348699..8995de8a 100644
--- a/typeconv.go
+++ b/typeconv.go
@@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"log"
+ "reflect"
"strconv"
"strings"
@@ -43,13 +44,13 @@ func unmarshalArray(obj []interface{}, in string, f func([]byte, interface{}) er
// JSON - Unmarshal a JSON Object
func (t *TypeConv) JSON(in string) map[string]interface{} {
obj := make(map[string]interface{})
- return unmarshalObj(obj, in, json.Unmarshal)
+ return unmarshalObj(obj, in, yaml.Unmarshal)
}
// JSONArray - Unmarshal a JSON Array
func (t *TypeConv) JSONArray(in string) []interface{} {
obj := make([]interface{}, 1)
- return unmarshalArray(obj, in, json.Unmarshal)
+ return unmarshalArray(obj, in, yaml.Unmarshal)
}
// YAML - Unmarshal a YAML Object
@@ -102,9 +103,15 @@ func (t *TypeConv) Join(a []interface{}, sep string) string {
}
// Has determines whether or not a given object has a property with the given key
-func (t *TypeConv) Has(in map[string]interface{}, key string) bool {
- _, ok := in[key]
- return ok
+func (t *TypeConv) Has(in interface{}, key string) bool {
+ av := reflect.ValueOf(in)
+ kv := reflect.ValueOf(key)
+
+ if av.Kind() == reflect.Map {
+ return av.MapIndex(kv).IsValid()
+ }
+
+ return false
}
func toString(in interface{}) string {
diff --git a/typeconv_test.go b/typeconv_test.go
index 7f07d08e..ca88c79f 100644
--- a/typeconv_test.go
+++ b/typeconv_test.go
@@ -27,7 +27,7 @@ func TestBool(t *testing.T) {
func TestUnmarshalObj(t *testing.T) {
ty := new(TypeConv)
expected := map[string]interface{}{
- "foo": "bar",
+ "foo": map[interface{}]interface{}{"bar": "baz"},
"one": 1.0,
"true": true,
}
@@ -37,8 +37,9 @@ func TestUnmarshalObj(t *testing.T) {
assert.Equal(t, expected["one"], actual["one"])
assert.Equal(t, expected["true"], actual["true"])
}
- test(ty.JSON(`{"foo":"bar","one":1.0,"true":true}`))
- test(ty.YAML(`foo: bar
+ test(ty.JSON(`{"foo":{"bar":"baz"},"one":1.0,"true":true}`))
+ test(ty.YAML(`foo:
+ bar: baz
one: 1.0
true: true
`))
@@ -130,8 +131,12 @@ func TestHas(t *testing.T) {
in := map[string]interface{}{
"foo": "bar",
+ "baz": map[string]interface{}{
+ "qux": "quux",
+ },
}
assert.True(t, ty.Has(in, "foo"))
assert.False(t, ty.Has(in, "bar"))
+ assert.True(t, ty.Has(in["baz"], "qux"))
}