From d69b6257df6712dc0ab3443dc3d579154941c1f9 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 1 Nov 2016 22:57:11 -0700 Subject: [PATCH] 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. --- config/interpolate_funcs.go | 18 +++++++++++++++--- config/interpolate_funcs_test.go | 13 ++++++++++++- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/config/interpolate_funcs.go b/config/interpolate_funcs.go index 102901cf5..19595e735 100644 --- a/config/interpolate_funcs.go +++ b/config/interpolate_funcs.go @@ -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. diff --git a/config/interpolate_funcs_test.go b/config/interpolate_funcs_test.go index dab9bde36..ccdb22363 100644 --- a/config/interpolate_funcs_test.go +++ b/config/interpolate_funcs_test.go @@ -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) }