Home > Blockchain >  No function named try when rendering template in terraform
No function named try when rendering template in terraform

Time:01-13

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 }
  • Related