Add a substring interpolation function (#12870)
Adds a new `substr` interpolation function which can be used to truncate a string.
This commit is contained in:
parent
87d6935780
commit
e71d6d92ad
|
@ -88,6 +88,7 @@ func Funcs() map[string]ast.Function {
|
|||
"slice": interpolationFuncSlice(),
|
||||
"sort": interpolationFuncSort(),
|
||||
"split": interpolationFuncSplit(),
|
||||
"substr": interpolationFuncSubstr(),
|
||||
"timestamp": interpolationFuncTimestamp(),
|
||||
"title": interpolationFuncTitle(),
|
||||
"trimspace": interpolationFuncTrimSpace(),
|
||||
|
@ -1183,3 +1184,48 @@ func interpolationFuncTitle() ast.Function {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
// interpolationFuncSubstr implements the "substr" function that allows strings
|
||||
// to be truncated.
|
||||
func interpolationFuncSubstr() ast.Function {
|
||||
return ast.Function{
|
||||
ArgTypes: []ast.Type{
|
||||
ast.TypeString, // input string
|
||||
ast.TypeInt, // offset
|
||||
ast.TypeInt, // length
|
||||
},
|
||||
ReturnType: ast.TypeString,
|
||||
Callback: func(args []interface{}) (interface{}, error) {
|
||||
str := args[0].(string)
|
||||
offset := args[1].(int)
|
||||
length := args[2].(int)
|
||||
|
||||
// Interpret a negative offset as being equivalent to a positive
|
||||
// offset taken from the end of the string.
|
||||
if offset < 0 {
|
||||
offset += len(str)
|
||||
}
|
||||
|
||||
// Interpret a length of `-1` as indicating that the substring
|
||||
// should start at `offset` and continue until the end of the
|
||||
// string. Any other negative length (other than `-1`) is invalid.
|
||||
if length == -1 {
|
||||
length = len(str)
|
||||
} else if length >= 0 {
|
||||
length += offset
|
||||
} else {
|
||||
return nil, fmt.Errorf("length should be a non-negative integer")
|
||||
}
|
||||
|
||||
if offset > len(str) {
|
||||
return nil, fmt.Errorf("offset cannot be larger than the length of the string")
|
||||
}
|
||||
|
||||
if length > len(str) {
|
||||
return nil, fmt.Errorf("'offset + length' cannot be larger than the length of the string")
|
||||
}
|
||||
|
||||
return str[offset:length], nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2071,3 +2071,61 @@ func TestInterpolateFuncPathExpand(t *testing.T) {
|
|||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestInterpolateFuncSubstr(t *testing.T) {
|
||||
testFunction(t, testFunctionConfig{
|
||||
Cases: []testFunctionCase{
|
||||
{
|
||||
`${substr("foobar", 0, 0)}`,
|
||||
"",
|
||||
false,
|
||||
},
|
||||
{
|
||||
`${substr("foobar", 0, -1)}`,
|
||||
"foobar",
|
||||
false,
|
||||
},
|
||||
{
|
||||
`${substr("foobar", 0, 3)}`,
|
||||
"foo",
|
||||
false,
|
||||
},
|
||||
{
|
||||
`${substr("foobar", 3, 3)}`,
|
||||
"bar",
|
||||
false,
|
||||
},
|
||||
{
|
||||
`${substr("foobar", -3, 3)}`,
|
||||
"bar",
|
||||
false,
|
||||
},
|
||||
|
||||
// empty string
|
||||
{
|
||||
`${substr("", 0, 0)}`,
|
||||
"",
|
||||
false,
|
||||
},
|
||||
|
||||
// invalid offset
|
||||
{
|
||||
`${substr("", 1, 0)}`,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
|
||||
// invalid length
|
||||
{
|
||||
`${substr("", 0, 1)}`,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
`${substr("", 0, -2)}`,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -318,6 +318,8 @@ The supported built-in functions are:
|
|||
`a_resource_param = ["${split(",", var.CSV_STRING)}"]`.
|
||||
Example: `split(",", module.amod.server_ids)`
|
||||
|
||||
* `substr(string, offset, length)` - Extracts a substring from the input string. A negative offset is interpreted as being equivalent to a positive offset measured backwards from the end of the string. A length of `-1` is interpretted as meaning "until the end of the string".
|
||||
|
||||
* `timestamp()` - Returns a UTC timestamp string in RFC 3339 format. This string will change with every
|
||||
invocation of the function, so in order to prevent diffs on every plan & apply, it must be used with the
|
||||
[`ignore_changes`](/docs/configuration/resources.html#ignore-changes) lifecycle attribute.
|
||||
|
|
Loading…
Reference in New Issue