From 4ba8388f3a70fe9af3c1eed2844204eb14515371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 2 Oct 2019 09:16:20 +0200 Subject: [PATCH] Cherry picks for v6.4.1 (#19554) * 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 (cherry picked from commit 8e508e5ce48e38d96a5da8cba49f1482c5134601) * Updated version to 6.4.1 --- package.json | 2 +- pkg/services/provisioning/values/values.go | 8 +++++++- .../provisioning/values/values_test.go | 20 +++++++++++++++++-- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index c72724420c8..38f3ff69c99 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "license": "Apache-2.0", "private": true, "name": "grafana", - "version": "6.4.0", + "version": "6.4.1", "repository": { "type": "git", "url": "http://github.com/grafana/grafana.git" 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{