I am rendering a .json
document containing a policy:
data "template_file" "my_role_policy" {
template = file("iam_role_policy_template.json")
vars = {
ACCESS_TO_SM = false
FOO = bar
}
}
Within the iam_role_policy_template.json
, I have the following snippet
%{ if try(ACCESS_TO_SM, false) }
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
],
"Resource": "s3://my-bucket/my-path"
}
%{ endif }
This is because there are other .tf
files using the same template that (for some reason) may not pass this variable.
The plan fails with the error
Error: failed to render : <template_file>:20,15-18: Call to unknown function; There is no function named "try".
I thought it was possible to use it in a template.
CodePudding user response:
The hashicorp/template
provider and its template_file
data source have been obsolete since 2019 and so the set of available functions and language features in that provider is effectively frozen at whatever Terraform supported at that time. It's still available for installation only for backward-compatibility for those using very old Terraform modules.
The try
function is considerably newer and so it isn't available in that provider and never will be. As recommended in the template_file
documentation, you should migrate to using the templatefile
function, which is a built-in part of the Terraform language and so always matches the features of whatever version of Terraform you are using.
You can replace your data "template_file"
block with a local value whose definition is a call to the templatefile
function:
locals {
role_policy = templatefile("${path.module}/iam_role_policy_template.json", {
ACCESS_TO_SM = false
FOO = "bar"
})
}
Elsewhere in your module, each place where you refer to data.template_file.my_role_policy.rendered
you can refer to local.role_policy
instead.
Once you've made this change, Terraform should accept your use of try
inside the template.
Separately: in your example the try
function call is not achieving anything, because the top-level variables like ACCESS_TO_SM
are always either defined or raise a static reference error. You can't use try
with direct access to top-level template variables, on to attributes and elements of collections.
For example, if you pass a map into your template then you can use try
to handle the case where an expected map key isn't present:
templatefile(..., {
example_map = tomap({
"a" = 1
})
})
${ try(example.map["b"], 2) }
...but it is not effective to use try
when its first argument is just a direct reference to a variable, because Terraform requires that you define all of the variables that the template uses and so the template would not be evaluated at all if you did not include ACCESS_TO_SM
in the set of defined variables.
CodePudding user response:
You can't use try
with %{} directtive. You would have to use try
before template:
data "template_file" "my_role_policy" {
template = file("iam_role_policy_template.json")
vars = {
ACCESS_TO_SM = try(SOME-EXPRESSION, false)
FOO = "bar"
}
}
then the template would be:
%{ if ACCESS_TO_SM == "true" }
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
],
"Resource": "s3://my-bucket/my-path"
}
%{ endif }