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

Terraform v1.10.0 rejects for_each on imports in some valid cases #36111

Closed
dancorne opened this issue Nov 27, 2024 · 8 comments · Fixed by #36119
Closed

Terraform v1.10.0 rejects for_each on imports in some valid cases #36111

dancorne opened this issue Nov 27, 2024 · 8 comments · Fixed by #36119
Assignees

Comments

@dancorne
Copy link

Terraform Version

$ terraform -version
Terraform v1.10.0
on darwin_arm64
+ provider registry.terraform.io/hashicorp/random v3.6.3

Terraform Configuration Files

variable "feature_switch" {
  type    = bool
  default = false
}

module "feature" {
  count = var.feature_switch ? 1 : 0
  source   = "./feature"
}

import {
  for_each = var.feature_switch ? toset(["feature"]) : toset([])
  to       = module.feature[0].random_string.test
  id       = "test"
}

In feature/main.tf:

resource "random_string" "test" {
  length   = 4
}

Debug Output

https://gist.github.com/dancorne/e5e0d2b7120eff24acc50a3b62b0816d

Expected Behavior

Terraform should optionally import resources, regardless of whether they use count/for_each.

Actual Behavior

╷
│ Error: Use of import for_each in an invalid context
│
│   on main.tf line 12, in import:
│   12:   for_each = var.feature_switch ? toset(["feature"]) : toset([])
│
│ Use of for_each in import requires a resource using count or for_each.

Steps to Reproduce

Using the two files above, terraform validate or terraform plan will fail, whether the feature_switch flag is enabled or disabled.

Additional Context

It looks like Terraform in v1.10.0 is pickier about then resource graph when importing. This will create challenges when trying to optionally import resources e.g. as part of a migration from one root module to another.

The error message suggests any import blocks using for_each need the resource to also use for_each (or count), however the example above shows a resource within a module using for_each isn't considered acceptable.

I there's two possible issues here:

  • Terraform will not allow a for_each on an import a resource that's not also using for_each/count. The error message suggests this is intentional, but perhaps the use-case of using for_each to be a conditional wasn't considered? In those circumstances 0 or 1 instances of import matching a single non-conditional resource makes sense when you want to import something that might or might not be there, eg depending on the AWS account you're applying to.
  • Terraform doesn't consider whether count/for_each is used on a module the resource is in. Thi really complicates any use of count/for_each on modules where imports are used.

Interestingly, the example is trivial to workaround: it's possible to add count = 1 to the resource and update the import resource to use [0] and it works as expected. I don't think this should be required for all resources in a module using for_each though.

References

This looks like the relevant PR where the behaviour changed: #35516

@dancorne dancorne added bug new new issue not yet triaged labels Nov 27, 2024
@jbardin jbardin added enhancement and removed bug new new issue not yet triaged labels Nov 27, 2024
@jbardin
Copy link
Member

jbardin commented Nov 27, 2024

Hi @dancorne

Thanks for filing the issue! This appears to be working as designed, and matches the spec for implementation (hence the error message Use of for_each in import requires a resource using count or for_each.). The import block cannot be expanded if the target resource does not have a corresponding expansion.

It looks like you are trying to use the for_each to create a conditional import, which is not fully supported. I think once we have that ironed out this use case will be better supported.

@jbardin jbardin added the v1.10 label Nov 27, 2024
@dancorne
Copy link
Author

Thanks for the response @jbardin, it did sound as-intended but where can I find the spec out of interest? I'm not clear one what should and shouldn't be supported now, and it's worked this way for a while so it seems like a regression.

Conditional imports like the example above are our main situation, but I can think of others that won't work now which did before. For example, to manage a number of AWS auto-scaling groups with different AMIs a simple way to do that would be to have a module with auto-scaling group, launch template etc, and a variable to iterate over (example code below). As soon as something in the module needs importing it won't work without a workaround.

variable "amis" {
  type    = set(string)
  default = ["ami-1234", "ami-5678"]
}

module "asg" {
  for_each = var.amis
  source   = "./asg"
}

import {
  for_each = var.amis
  to       = module.asg[each.key].random_string.test
  id       = "test"
}

@jbardin
Copy link
Member

jbardin commented Nov 27, 2024

Thank @dancorne,

I think you're right, that definitely does look like an oversight when importing into a module. I'm going to check if it's safe to just skip that validation for now, since wherever that validation lived before didn't appear to work either.

@flcdrg
Copy link

flcdrg commented Nov 29, 2024

This is a regression for us. This was working fine in 1.9.x as a way to have conditional imports. A blocker for us upgrading to 1.10.x at the moment.

@stuartleeks
Copy link

@jbardin - is there somewhere that documents the scenarios where for_each on an import block is supported?

It's tremendously useful for conditional imports by in your comment you mentioned that it's "not fully supported". I'm keen to dig into that further to understand how to stay within supported scenarios :-)

@skeggse
Copy link

skeggse commented Dec 4, 2024

It looks like you are trying to use the for_each to create a conditional import, which is not fully supported. I think once we have that ironed out this use case will be better supported.

I spent a bunch of time building out a tool that would generate conditional imports for us, and it was working great on 1.9.6! Then we upgraded to 1.10.0 and it broke :(

IMO this was a great feature, and the regression is really disappointing. Will #36136 fix the regression?

@jbardin
Copy link
Member

jbardin commented Dec 5, 2024

@skeggse, #36136 should have already fixed the regression in 1.10.1! If you still have something which isn't working, please file a new issue with the details.

@stuartleeks, There is no way to always handle an import which may or may not already exist. Leveraging an existing data source which can successfully return zero-or-more results can work when combined with for_each, but that's not currently possible for all resource types. We're evaluating the feasibility #33633, but technically the import process almost never fails due to how it works by default in providers, so there is some extra design work required for that to be possible.

Copy link
Contributor

github-actions bot commented Jan 5, 2025

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 Jan 5, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants