amazon-web-servicesterraformterraform-provider-awsterraform-template-file

terraform how to specify value of apigateway invoke_url using template file feature - locals or vars dont work


I have apigateway invoke_url that is unique and created by terraform, this unique url usually has form of

https://123abc.execute-api.us-east-1.amazonaws.com

That value has to go inside index.html for s3 object, I'm using template feature of terraform:

    <!DOCTYPE html>
    <html>
      SOME CODE    
        
          var backend_url = "${backend_api_gateway}/voting"              
    
      some code
          });
    
    </html>

Trying with 'locals' in tf did not work:

locals {
  backend_api_gateway = "${aws_apigatewayv2_stage.default.invoke_url}"
}
    
resource "aws_s3_object" "index_file_vote" {
  bucket = aws_s3_bucket.frontend_vote.id
  key    = "index.html"
  content = templatefile("./vote/index.html.tpl", {
    backend_api_url = local.backend_api_gateway
  })
      
  depends_on = [aws_s3_bucket.frontend_vote, aws_apigatewayv2_api.main_apigateway] 
}

It gives error:

    Invalid function argument
    │
    │   on s3_bucket_vote.tf line 93, in resource "aws_s3_object" "index_file_vote":
    │   93:     content = templatefile("./vote/index.html.tpl", {
    │   94:         backend_api_url = local.backend_api_gateway
    │   95:     })
    │     ├────────────────
    │     │ local.backend_api_gateway will be known only after apply│
    │ Invalid value for "vars" parameter: vars map does not contain
    │ key "backend_api_gateway", referenced at
    │ ./vote/index.html.tpl:34,28-47.

Trying with vars, declaring future to be created apigateway's invoke url did not work:

variable "backend_api_gateway" {
  type = string
  default = "${aws_apigatewayv2_stage.default.invoke_url}" // error 'variables not allowed'
}

Solution

  • Since there are no modules involved, this should be easy to fix. First, the value assigned to the variable has to go away as it is not possible to use it that way. Second, you actually do not even need it. Third, you are using explicit dependencies, which is also not needed. Additionally, even though there is nothing wrong with using local variable, it is not needed. Here is the change required:

    resource "aws_s3_object" "index_file_vote" {
        bucket = aws_s3_bucket.frontend_vote.id
        key    = "index.html"
        content = templatefile("./vote/index.html.tpl", {
            backend_api_url = aws_apigatewayv2_stage.default.invoke_url
        }) 
    }