Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Variables with type = any are not encoded properly for Terraform 0.12 #1211

Closed
antonbabenko opened this issue Jun 5, 2020 · 7 comments
Closed
Labels
bug Something isn't working needs design We need to flesh out the design before we can resolve the issue

Comments

@antonbabenko
Copy link
Contributor

# terragrunt.hcl
terraform {
  source = "..."
}

inputs = {
  name ="something"                 # <-- this does not work
  # name = jsonencode("something")  # <-- this works
}
# module/main.tf
variable "name" {
  type    = any      # Works as expected when type is not `any`
  default = null
}

The error message:

Error: Invalid expression

  on <value for var.name> line 1:
  (source code not available)

Expected the start of an expression, but found an invalid expression token.

It looks like terragrunt should do JSON encode for all variables, but I am not sure if it is a BC break, or not.

Using terragrunt version v0.23.23 and Terraform 0.12.26.

The workaround, for now, is to know which variables have "type = any" and wrap value with jsonencode().

@yorinasub17 yorinasub17 added bug Something isn't working needs investigation and removed needs investigation labels Jun 8, 2020
@yorinasub17
Copy link
Contributor

Investigating into this, it looks like terraform does not like the string value being passed in without quotes when type=any. However, this is problematic because we can't pass in with quotes when type=string, as the quotes make it to the final input value (we deliberately do not do a json encoding for strings for this reason).

I'm not sure there is anything we can do here other than to parse the terraform source for variables and dynamically adjust the conversion logic based on the type, but I am not sure we want to go that far. I am inclined to close this as something we won't address in terragrunt, and unfortunately have to rely on the jsonencode workaround.

Could use a second opinion though: @brikis98 what do you think?

@brikis98
Copy link
Member

@yorinasub17 Agreed. Should we also open a bug in the Terraform repo? The fact that you wrap strings with quotes sometimes in Terraform seems like an issue that would be best fixed on their end.

@Xtigyro
Copy link
Contributor

Xtigyro commented Oct 1, 2021

What's the status on this, guys?

@infraredgirl infraredgirl added needs design We need to flesh out the design before we can resolve the issue and removed needs-design labels Oct 20, 2021
@basarsoker
Copy link

Cost me 2 days. 😔 thanks a lot for the workaround.

@dserodio
Copy link

Thanks for the workaround and sorry for this "useless" comment, but since GitHub allows searching for commented issues but not subscribed issues I have to comment to easily find this issue later.

@BeyondEvil
Copy link

Is this still relevant @yhakbar ? 🤔

@yhakbar
Copy link
Collaborator

yhakbar commented Nov 27, 2024

Hey @BeyondEvil ,

Thanks for tagging me here. I can confirm the behavior still exists.

I'm going to put more code samples here to demonstrate why addressing this probably isn't a good use of Terragrunt resources right now, if it even is feasibly addressable.

Looking at the behavior of a simple fixture:

# terragrunt.hcl
inputs = {
  name = "something"
}
# main.tf
variable "name" {
  type    = any
  default = null
}

resource "local_file" "example" {
  filename = var.name
  content  = "Hello, World!"
}

We can still reproduce this issue.

* Failed to execute "tofu plan" in .
  ╷
  │ Error: Variables not allowed
  │
  │   on <value for var.name> line 1:
  │   (source code not available)
  │
  │ Variables may not be used here.
  ╵

  exit status 1

If we take the recommended fix and JSON encode the value before we send it down as the environment variable TF_VAR_name, however, we'll see that it does indeed work around the issue:

inputs = {
  name = jsonencode("something")
}
  # local_file.example will be created
  + resource "local_file" "example" {
      + content              = "Hello, World!"
      + content_base64sha256 = (known after apply)
      + content_base64sha512 = (known after apply)
      + content_md5          = (known after apply)
      + content_sha1         = (known after apply)
      + content_sha256       = (known after apply)
      + content_sha512       = (known after apply)
      + directory_permission = "0777"
      + file_permission      = "0777"
      + filename             = "something"
      + id                   = (known after apply)
    }

Also note, however, that properly typed variables will experience a regression if we do this:

# main.tf
variable "name" {
  type    = string
  default = null
}

resource "local_file" "example" {
  filename = var.name
  content  = "Hello, World!"
}
  # local_file.example will be created
  + resource "local_file" "example" {
      + content              = "Hello, World!"
      + content_base64sha256 = (known after apply)
      + content_base64sha512 = (known after apply)
      + content_md5          = (known after apply)
      + content_sha1         = (known after apply)
      + content_sha256       = (known after apply)
      + content_sha512       = (known after apply)
      + directory_permission = "0777"
      + file_permission      = "0777"
      + filename             = "\"something\""
      + id                   = (known after apply)
    }

I'm referring to filename being set to "\"something\"".

The idea of parsing .tf files to uncover whether Terragrunt should do some hidden jsonencoding on behalf of the user might work, but there are some problems with it.

  1. It would incur a performance penalty for every Terragrunt run to evaluate the correctness of performing a preemptive json encode.
  2. It would require performing OpenTofu/Terraform initialization before HCL parsing is performed and inputs are set as TF_VAR_ environment variables.

The first would happen, as Terragrunt would have to scan and parse all the .tf files that might be used in a run for variables with any types, and the second would happen, as .tf files might reference modules that have variables with any types somewhere in their configurations.

Deciding not to tackle this because the alternative is to have users either set types explicitly or explicitly using jsonencode for any types seems like the more sensible course of action for now.

If someone has an alternate solution that's preferred that wouldn't incur those two penalties, I'd welcome an enhancement issue to document the proposal.

Closing out this issue, as it has gone stale, there are documented workarounds, and it's not clear what would be an acceptable solution that doesn't degrade the experience of most Terragrunt users.

Thank you for reporting this @antonbabenko , and providing the workaround.

@yhakbar yhakbar closed this as completed Nov 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working needs design We need to flesh out the design before we can resolve the issue
Projects
None yet
Development

No branches or pull requests

9 participants