See below for the Provider Author side.
- A function will accept any number of arguments, as defined by the provider function
- A function will have a result and error/diagnostic handling
- The function syntax will maintain the top level namespace to allow for future extensibility
- Each provider will have its own namespace, that of the provider name.
- The built-in functions will have their own namespace
- Functions will be treated as pure functions, and will not have any side effects
- Functions will not have access to provider configuration
- Functions results will always be consistent given the same input.
- Functions are called whenever the config is evaluated.
- Misconfigurations of functions will be detected during
terraform validate
- Functions can be used in terraform console
- Defining a function will feel very similar to defining a resource or data source in the framework
- There will be a schema and a way to define it, with the arguments and the result.
Here is sample code:
// Prototype example code. This design has not been finalized.
type ExampleFunction struct{}
func (f ExampleFunction) Metadata(ctx context.Context, req function.MetadataRequest, resp *function.MetadataResponse) {
resp.Name = "iso8061"
}
func (f ExampleFunction) Definition(ctx context.Context, req function.DefinitionRequest, resp *function.DefinitionResponse) {
resp.Arguments = []function.Argument{
function.StringArgument{
DisplayName: "rfc3339",
Description: "RFC3339 timestamp to be converted",
},
}
resp.Description = "Converts a RFC3339 timestamp string to ISO8601"
resp.Result = function.StringResult{
Description: "ISO8601 timestamp",
}
}
func (f ExampleFunction) Run(ctx context.Context, req function.RunRequest, resp *function.RunResponse) {
var arg types.String
resp.Diagnostics.Append(req.Arguments.GetArgument(ctx, 0, &arg)...)
if resp.Diagnostics.HasError() {
return
}
if arg.IsNull() || arg.IsUnknown() {
resp.Diagnostics.Append(resp.Result.Set(ctx, /* ... */)...)
}
In many cases the go function is already implemented. In this case there could be a very generic approach using go reflection with the little assumption that the go function has the type
func (par1 type1, par2 type2, ...) (structType, error)
which for instance is the case for the arn function
func Parse(arn string) (ARN, error)
If not, a small wrapper function can be implemented.
If the field names are accepted as sufficient only the name for the function and descriptions for the input parameters need to be coded (just a sketch):
everything else can be coded by reflection in the framework.