Search code examples
amazon-web-servicesterraformterraform-provider-aws

Terraform jsonencode() incorrect interpretation of string and number types


I'm running into very strange behavior in terraform when making use of the jsonencode() function. I am using the AWS secrets manager terraform module to generate a database secret for my application.

It contains 3 values - database host, port and name. However, even though I provide the port wrapped in double quotes to force string interpretation it is being created in Secrets Manager as a number. My application is expecting the secret kv values to all be strings.

The 2 code below demonstrates the challenge. When passing the output directly (as in the secret_string_broken example), it is interpreted as a number. When it is provided explicitly (as in the secret_string_working example), it is interpreted as a string - as expected.

secret_string_broken = jsonencode({
  DB_HOST         = "${module.db.endpoint}"
  DB_PORT         = "${module.db.port}"
  DB_NAME         = "${module.db.db_name}"
})

secret_string_working = jsonencode({
  DB_HOST         = "${module.db.endpoint}"
  DB_PORT         = "1234"
  DB_NAME         = "${module.db.db_name}"
})

Is this an issue with my usage of the jsonencode() function? Or am I running into some strange Terraform behavior?

My guess is that terraform is making use of the output type for the module.db.port value and using that to set the value - but I'm confused by why it would ignore the wrapping double quotes.


Solution

  • Based on the documentation, the port seems to be a number. Enclosing it into quotes will not make it a string. What you could try is using the explicit type casting with tostring:

    secret_string = jsonencode({
      DB_HOST         = "${module.db.endpoint}"
      DB_PORT         = tostring(module.db.port)
      DB_NAME         = "${module.db.db_name}"
    })
    

    I also think you don't need to enclose the host and name with quotes since they will probably be strings anyway, which means this might work as well:

    secret_string = jsonencode({
      DB_HOST         = module.db.endpoint
      DB_PORT         = tostring(module.db.port)
      DB_NAME         = module.db.db_name
    })