[v9.4.x] Provisioning: Parse boolean and numeric values from environment variables (#63192)

Provisioning: Parse boolean and numeric values from environment variables (#63085)

(cherry picked from commit a33e316f40)

Co-authored-by: Andres Martinez Gotor <andres.martinez@grafana.com>
This commit is contained in:
Grot (@grafanabot)
2023-02-09 09:04:33 -05:00
committed by GitHub
co-authored by Andres Martinez Gotor
parent 69453133e7
commit 982624f7b1
2 changed files with 37 additions and 6 deletions
+29 -1
View File
@@ -247,7 +247,7 @@ func transformInterface(i interface{}) (interface{}, interface{}, error) {
case reflect.Map:
return transformMap(i.(map[string]interface{}))
case reflect.String:
return interpolateValue(i.(string))
return interpolateIfaceValue(i.(string))
default:
// Was int, float or some other value that we do not need to do any transform on.
return i, i, nil
@@ -281,6 +281,34 @@ func transformMap(i map[string]interface{}) (interface{}, interface{}, error) {
return transformed, raw, nil
}
func interpolateIfaceValue(val string) (interface{}, string, error) {
parts := strings.Split(val, "$$")
if len(parts) > 1 {
return interpolateValue(val)
}
expanded, err := setting.ExpandVar(val)
if err != nil {
return val, val, fmt.Errorf("failed to interpolate value '%s': %w", val, err)
}
expandedEnv := os.ExpandEnv(expanded)
if expandedEnv != val {
// If the value is an environment variable, consider it may not be a string
intV, err := strconv.ParseInt(expandedEnv, 10, 64)
if err == nil {
return intV, val, nil
}
floatV, err := strconv.ParseFloat(expandedEnv, 64)
if err == nil {
return floatV, val, nil
}
boolV, err := strconv.ParseBool(expandedEnv)
if err == nil {
return boolV, val, nil
}
}
return expandedEnv, val, nil
}
// interpolateValue returns the final value after interpolation. In addition to environment variable interpolation,
// expanders available for the settings file are expanded here.
// For a literal '$', '$$' can be used to avoid interpolation.
@@ -168,6 +168,7 @@ func TestValues(t *testing.T) {
Some text with $STRING
anchor: &label $INT
anchored: *label
boolval: $BOOL
`
unmarshalingTest(t, doc, d)
@@ -191,12 +192,13 @@ func TestValues(t *testing.T) {
},
"four": stringMap{
"nested": stringMap{
"onemore": "1",
"onemore": int64(1),
},
},
"multiline": "Some text with test\n",
"anchor": "1",
"anchored": "1",
"anchor": int64(1),
"anchored": int64(1),
"boolval": true,
})
require.Equal(t, d.Val.Raw, stringMap{
@@ -224,6 +226,7 @@ func TestValues(t *testing.T) {
"multiline": "Some text with $STRING\n",
"anchor": "$INT",
"anchored": "$INT",
"boolval": "$BOOL",
})
})
})
@@ -251,12 +254,12 @@ func TestValues(t *testing.T) {
require.Equal(t, []stringMap{
{
"interpolatedString": "test",
"interpolatedInt": "1",
"interpolatedInt": int64(1),
"string": "just a string",
},
{
"interpolatedString": "test",
"interpolatedInt": "1",
"interpolatedInt": int64(1),
"string": "just a string",
},
}, d.Val.Value())