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(),
|
"slice": interpolationFuncSlice(),
|
||||||
"sort": interpolationFuncSort(),
|
"sort": interpolationFuncSort(),
|
||||||
"split": interpolationFuncSplit(),
|
"split": interpolationFuncSplit(),
|
||||||
|
"substr": interpolationFuncSubstr(),
|
||||||
"timestamp": interpolationFuncTimestamp(),
|
"timestamp": interpolationFuncTimestamp(),
|
||||||
"title": interpolationFuncTitle(),
|
"title": interpolationFuncTitle(),
|
||||||
"trimspace": interpolationFuncTrimSpace(),
|
"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)}"]`.
|
`a_resource_param = ["${split(",", var.CSV_STRING)}"]`.
|
||||||
Example: `split(",", module.amod.server_ids)`
|
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
|
* `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
|
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.
|
[`ignore_changes`](/docs/configuration/resources.html#ignore-changes) lifecycle attribute.
|
||||||
|
|
Loading…
Reference in New Issue