From 8e508e5ce48e38d96a5da8cba49f1482c5134601 Mon Sep 17 00:00:00 2001 From: gotjosh Date: Wed, 2 Oct 2019 07:48:19 +0100 Subject: [PATCH] Provisioning: Handle empty nested keys on YAML provisioning datasources (#19547) * Fix: Handle empty nested keys on YAML provisioning datasources As we provision a datasource via a YAML file, we attempt to transform the file into sensible Go types that the provisioning code can use. While this happens, there is a chance some of the keys nested within the YAML array are empty. This fix allows the YAML parser to handle empty keys by null checking the return of `reflect.TypeOf` which according to the documentation: > TypeOf returns the reflection Type that represents the dynamic type of i. If i is a nil interface value, TypeOf returns nil. Can return nil. * Add tests --- pkg/services/provisioning/values/values.go | 8 +++++++- .../provisioning/values/values_test.go | 20 +++++++++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/pkg/services/provisioning/values/values.go b/pkg/services/provisioning/values/values.go index de86085671e..c08c61cbeb8 100644 --- a/pkg/services/provisioning/values/values.go +++ b/pkg/services/provisioning/values/values.go @@ -155,7 +155,13 @@ func (val *StringMapValue) Value() map[string]string { // slices and the actual interpolation is done on all simple string values in the structure. It returns a copy of any // map or slice value instead of modifying them in place. func tranformInterface(i interface{}) interface{} { - switch reflect.TypeOf(i).Kind() { + typeOf := reflect.TypeOf(i) + + if typeOf == nil { + return nil + } + + switch typeOf.Kind() { case reflect.Slice: return transformSlice(i.([]interface{})) case reflect.Map: diff --git a/pkg/services/provisioning/values/values_test.go b/pkg/services/provisioning/values/values_test.go index 064dee86d6a..d61f6e06ac5 100644 --- a/pkg/services/provisioning/values/values_test.go +++ b/pkg/services/provisioning/values/values_test.go @@ -131,6 +131,8 @@ func TestValues(t *testing.T) { - two - three: inside: $STRING + - six: + empty: four: nested: onemore: $INT @@ -146,11 +148,18 @@ func TestValues(t *testing.T) { "one": 1, "two": "test", "three": []interface{}{ - 1, "two", anyMap{ + 1, + "two", + anyMap{ "three": anyMap{ "inside": "test", }, }, + anyMap{ + "six": anyMap{ + "empty": interface{}(nil), + }, + }, }, "four": anyMap{ "nested": anyMap{ @@ -166,11 +175,18 @@ func TestValues(t *testing.T) { "one": 1, "two": "$STRING", "three": []interface{}{ - 1, "two", anyMap{ + 1, + "two", + anyMap{ "three": anyMap{ "inside": "$STRING", }, }, + anyMap{ + "six": anyMap{ + "empty": interface{}(nil), + }, + }, }, "four": anyMap{ "nested": anyMap{