config: formatlist accepts an empty list

Fixes #7607

An empty list is a valid value for formatlist which means to just return
an empty list as a result. The logic was somewhat convoluted here so I
cleaned that up a bit too. The function overall can definitely be
cleaned up a lot more but I left it mostly as-is to fix the bug.
This commit is contained in:
Mitchell Hashimoto 2016-11-01 22:57:11 -07:00
parent 9e5d1f10b0
commit d69b6257df
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A
2 changed files with 27 additions and 4 deletions

View File

@ -7,7 +7,6 @@ import (
"encoding/base64"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"math"
@ -499,15 +498,25 @@ func interpolationFuncFormatList() ast.Function {
varargs := make([]interface{}, len(args)-1)
copy(varargs, args[1:])
// Verify we have some arguments
if len(varargs) == 0 {
return nil, fmt.Errorf("no arguments to formatlist")
}
// Convert arguments that are lists into slices.
// Confirm along the way that all lists have the same length (n).
var n int
listSeen := false
for i := 1; i < len(args); i++ {
s, ok := args[i].([]ast.Variable)
if !ok {
continue
}
// Mark that we've seen at least one list
listSeen = true
// Convert the ast.Variable to a slice of strings
parts, err := listVariableValueToStringSlice(s)
if err != nil {
return nil, err
@ -527,8 +536,11 @@ func interpolationFuncFormatList() ast.Function {
}
}
if n == 0 {
return nil, errors.New("no lists in arguments to formatlist")
// If we didn't see a list this is an error because we
// can't determine the return value length.
if !listSeen {
return nil, fmt.Errorf(
"formatlist requires at least one list argument")
}
// Do the formatting.

View File

@ -994,6 +994,18 @@ func TestInterpolateFuncFormatList(t *testing.T) {
[]interface{}{"demo-rest-elb.id"},
false,
},
// Works with empty lists [GH-7607]
{
`${formatlist("%s", var.emptylist)}`,
[]interface{}{},
false,
},
},
Vars: map[string]ast.Variable{
"var.emptylist": {
Type: ast.TypeList,
Value: []ast.Variable{},
},
},
})
}
@ -1928,7 +1940,6 @@ func testFunction(t *testing.T, config testFunctionConfig) {
}
result, err := hil.Eval(ast, langEvalConfig(config.Vars))
t.Logf("err: %v", err)
if err != nil != tc.Error {
t.Fatalf("Case #%d:\ninput: %#v\nerr: %v", i, tc.Input, err)
}