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

locals throwing a declaration error after updating to v2.28.0 and v2.28.1 #1586

Closed
1 task
haflidif opened this issue Oct 11, 2023 · 7 comments
Closed
1 task
Assignees
Labels
bug Something isn't working diagnostics

Comments

@haflidif
Copy link

haflidif commented Oct 11, 2023

Extension Version

v2.28.1

VS Code Version

Version: 1.83.0 (user setup)
Commit: e7e037083ff4455cf320e344325dacb480062c3c
Date: 2023-10-03T16:12:16.321Z
Electron: 25.8.4
ElectronBuildId: 24154031
Chromium: 114.0.5735.289
Node.js: 18.15.0
V8: 11.4.183.29-electron.0
OS: Windows_NT x64 10.0.22621

Operating System

Windows 11 22H2 Enterprise Version

Terraform Version

Terraform v1.6.0 on windows_amd64

Steps to Reproduce

  1. Create a locals.tf file
  2. Create two local objects.

locals.tf

locals {
  testing = {
    one = {
      name   = "one"
      number = 1
    },
    two = {
      description = "two"
      number      = 2
    }
  }

  testing_with_list = {
    one = {
      name   = "one"
      number = 1
    },
    two = {
      description = "two"
      number      = 2
      list        = ["one", "two"]
    }
  }
}
  1. create terraform.tf file

terraform.tf

resource "null_resource" "declaration_working_as_expected" {
  for_each = local.testing
}

resource "null_resource" "declaration_not_working_as_expected" {
  for_each = local.testing_with_list
}

When having a list inside the object, or even set of objects you get the error No declaration found for "local.testing_with_list" Terraform

Expected Behavior

Expected Behavior:
image

Actual Behavior

image

NOTE: The error also appears when you have set of objects within the local block.

Terraform Configuration

locals.tf

locals {
  testing = {
    one = {
      name   = "one"
      number = 1
    },
    two = {
      description = "two"
      number      = 2
    }
  }

  testing_with_list = {
    one = {
      name   = "one"
      number = 1
    },
    two = {
      description = "two"
      number      = 2
      list = [ "one", "two", "three"]
    }
  }
}

terraform.tf

resource "null_resource" "declaration_working_as_expected" {
  for_each = local.testing
}

resource "null_resource" "declaration_not_working_as_expected" {
  for_each = local.testing_with_list
}

Project Structure

.
├── terraform
│   ├── locals.tf
│   └── terraform.tf

Gist

No response

Anything Else?

No response

Workarounds

No response

References

Help Wanted

  • I'm interested in contributing a fix myself

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave "+1" or other comments that do not add relevant new information or questions, they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment
@haflidif haflidif added the bug Something isn't working label Oct 11, 2023
@haflidif
Copy link
Author

haflidif commented Oct 11, 2023

looks like the workaround is to disable enhanced validation instead of downgrading according to the post here:

On a separate note, you can stay on the latest version and disable the validation using the following option:

"terraform.validation.enableEnhancedValidation": false,

There should be no need to downgrade to older versions.

Originally posted by @radeksimko in #1579 (comment)

But that doesn't solve this bug with the Enhanced validation and it not being able to validate set of objects, lists etc.

@radeksimko
Copy link
Member

Thank you for the report, I was able to reproduce it.

I suspect this is similar to hashicorp/hcl-lang#330

I will look into it.

@radeksimko
Copy link
Member

radeksimko commented Oct 11, 2023

It turns out this is after all a little different to hashicorp/hcl-lang#330


For added clarity - {} indicate an object and [] indicate a tuple, unless the attribute has constraints to suggest otherwise - which locals do not, so in both cases these are treated as objects and tuples, not map and not list. It may be slightly confusing due to Terraform doing automatic type conversion between some types at certain point.


As far as I can tell, it is an edge case involving mismatch between an object which is not cleanly convertible to a map, where for for_each we expect a map.

The configuration in the example is - type-wise speaking - a little unusual in that for_each is "iterating" over an object, where (as is the nature of objects) each attribute is of a different type. A map in HCL/Terraform always assumes values of the same type, and therefore the two are not convertible.

That said I cannot confidently say this would be unusual from usage perspective. For various reasons, many users and configurations use types in one unexpected way or another. 😅

You can also verify this by converting the types more explicitly:

terraform console
> tomap({foo = 42, bar = "noot" })
tomap({
  "bar" = "noot"
  "foo" = "42"
})
> tomap({foo = 42, bar = true })
╷
│ Error: Invalid function argument
│
│   on <console-input> line 1:
│   (source code not available)
│
│ Invalid value for "v" parameter: cannot convert object to map of any single type.
╵

Also as shown above, you only get away with the conversion in the first local because the primitive types (string and number) happen to be convertible between each other. Boolean or tuple cannot be converted into string or number.


It's not entirely clear to me how Terraform (CLI) internally deals with such a case. I suspect there's some further special handling of for_each we'll have to look into.

@radeksimko
Copy link
Member

After looking through the codebase, I can tell that objects are still considered valid types for for_each, although not really documented anywhere:

https://github.com/hashicorp/terraform/blob/07b814c030daae39dea764571bef9cecf26e49be/internal/terraform/eval_for_each.go#L275-L284

The under-documentation is somewhat intentional. The support for objects is primarily there for historical/backwards-compatible reasons.

The problem with iterating over an object is that you cannot be sure about the type (and validity) of each.value, which can cause problems downstream.

For most (not necessarily 100%) cases there are better solutions which do not involve objects. For example, you can iterate over the keys only:

locals {
  testing = {
    one = {
      name   = "one"
      number = 1
    },
    two = {
      description = "two"
      number      = 2
    }
  }

  testing_with_list = {
    one = {
      name   = "one"
      number = 1
    },
    two = {
      description = "two"
      number      = 2
      list        = ["one", "two", "three"]
    }
  }
}

resource "null_resource" "declaration_working_as_expected" {
  for_each = keys(local.testing)
}

resource "null_resource" "declaration_not_working_as_expected" {
  for_each = keys(local.testing_with_list)
}

It is still unusual to even begin with objects like that if you only need to be looping over the keys (object attribute names), but at least this prevents you from making the mistake of accessing each.value in a context where it may not be valid.

@radeksimko
Copy link
Member

A PR fixing the issue is now pending review: hashicorp/hcl-lang#333

Once that is merged and released, you should no longer see the diagnostic error.

However, I would still advise you to review the choices of types and data structures in that example, for the reasons mentioned.

@radeksimko radeksimko self-assigned this Oct 11, 2023
@dbanck
Copy link
Member

dbanck commented Oct 13, 2023

A new version 2.28.2 was just released. This fixes the reported bug. The update should appear automatically in VS Code.

Thank you for the detailed report @haflidif


In case you experience any different validation related bug, please do let us know through a new issue.

@dbanck dbanck closed this as completed Oct 13, 2023
Copy link

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 13, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working diagnostics
Projects
None yet
Development

No branches or pull requests

3 participants