Skip to content

Commit

Permalink
Add basename and dirname functions
Browse files Browse the repository at this point in the history
Adds `basename` and `dirname` interpolation. I want to add a `stack` tag to our infrastructure, the value of which is set to `${basename(path.cwd)}`. We currently use `${replace(path.cwd, "/^.+\\//", "")}` instead, but this is extremeley unreadable. The existance of a `basename` function would be very useful for this use case.

I don't have an immediate use case for a `dirname` function, but it seemed reasonable to add it as well.
  • Loading branch information
Joshua Spence authored and apparentlymart committed Mar 28, 2017
1 parent 8b1df45 commit af2c84d
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 0 deletions.
25 changes: 25 additions & 0 deletions config/interpolate_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"io/ioutil"
"math"
"net"
"path/filepath"
"regexp"
"sort"
"strconv"
Expand Down Expand Up @@ -52,6 +53,7 @@ func listVariableValueToStringSlice(values []ast.Variable) ([]string, error) {
// Funcs is the mapping of built-in functions for configuration.
func Funcs() map[string]ast.Function {
return map[string]ast.Function{
"basename": interpolationFuncBasename(),
"base64decode": interpolationFuncBase64Decode(),
"base64encode": interpolationFuncBase64Encode(),
"base64sha256": interpolationFuncBase64Sha256(),
Expand All @@ -62,6 +64,7 @@ func Funcs() map[string]ast.Function {
"coalesce": interpolationFuncCoalesce(),
"compact": interpolationFuncCompact(),
"concat": interpolationFuncConcat(),
"dirname": interpolationFuncDirname(),
"distinct": interpolationFuncDistinct(),
"element": interpolationFuncElement(),
"file": interpolationFuncFile(),
Expand Down Expand Up @@ -600,6 +603,17 @@ func interpolationFuncIndex() ast.Function {
}
}

// interpolationFuncBasename implements the "dirname" function.
func interpolationFuncDirname() ast.Function {
return ast.Function{
ArgTypes: []ast.Type{ast.TypeString},
ReturnType: ast.TypeString,
Callback: func(args []interface{}) (interface{}, error) {
return filepath.Dir(args[0].(string)), nil
},
}
}

// interpolationFuncDistinct implements the "distinct" function that
// removes duplicate elements from a list.
func interpolationFuncDistinct() ast.Function {
Expand Down Expand Up @@ -1006,6 +1020,17 @@ func interpolationFuncValues(vs map[string]ast.Variable) ast.Function {
}
}

// interpolationFuncBasename implements the "basename" function.
func interpolationFuncBasename() ast.Function {
return ast.Function{
ArgTypes: []ast.Type{ast.TypeString},
ReturnType: ast.TypeString,
Callback: func(args []interface{}) (interface{}, error) {
return filepath.Base(args[0].(string)), nil
},
}
}

// interpolationFuncBase64Encode implements the "base64encode" function that
// allows Base64 encoding.
func interpolationFuncBase64Encode() ast.Function {
Expand Down
24 changes: 24 additions & 0 deletions config/interpolate_funcs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,18 @@ func TestInterpolateFuncMerge(t *testing.T) {

}

func TestInterpolateFuncDirname(t *testing.T) {
testFunction(t, testFunctionConfig{
Cases: []testFunctionCase{
{
`${dirname("/foo/bar/baz")}`,
"/foo/bar",
false,
},
},
})
}

func TestInterpolateFuncDistinct(t *testing.T) {
testFunction(t, testFunctionConfig{
Cases: []testFunctionCase{
Expand Down Expand Up @@ -1777,6 +1789,18 @@ func TestInterpolateFuncElement(t *testing.T) {
})
}

func TestInterpolateFuncBasename(t *testing.T) {
testFunction(t, testFunctionConfig{
Cases: []testFunctionCase{
{
`${basename("/foo/bar/baz")}`,
"baz",
false,
},
},
})
}

func TestInterpolateFuncBase64Encode(t *testing.T) {
testFunction(t, testFunctionConfig{
Cases: []testFunctionCase{
Expand Down
4 changes: 4 additions & 0 deletions website/source/docs/configuration/interpolation.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ syntax `name(arg, arg2, ...)`. For example, to read a file:

The supported built-in functions are:

* `basename(path)` - Returns the last element of a path.

* `base64decode(string)` - Given a base64-encoded string, decodes it and
returns the original string.

Expand Down Expand Up @@ -183,6 +185,8 @@ The supported built-in functions are:
* `concat(list1, list2, ...)` - Combines two or more lists into a single list.
Example: `concat(aws_instance.db.*.tags.Name, aws_instance.web.*.tags.Name)`

* `dirname(path)` - Returns all but the last element of path, typically the path's directory.

* `distinct(list)` - Removes duplicate items from a list. Keeps the first
occurrence of each element, and removes subsequent occurrences. This
function is only valid for flat lists. Example: `distinct(var.usernames)`
Expand Down

0 comments on commit af2c84d

Please sign in to comment.