Terraform: 0.13.0 cannot import resources in nested modules when count value for module is variable

Created on 12 Aug 2020  ยท  9Comments  ยท  Source: hashicorp/terraform

Terraform Version

Terraform v0.13.0

Terraform Configuration Files

.
โ”œโ”€โ”€ main.tf
โ””โ”€โ”€ test_module
    โ”œโ”€โ”€ main.tf
    โ””โ”€โ”€ test_module2
        โ””โ”€โ”€ main.tf

main.tf

provider "aws" {
  region = "us-west-2"
}

module "test_module" {
  source = "./test_module"
  regions = var.regions
}

variable "regions" {
  default = ["us-west-2", "us-east-1"]
}

test_module/main.tf

variable "regions" {}

module "test_module2" {
  count = length(var.regions)
  source = "./test_module2"
}

test_module/test_module2/main.tf

resource "null_resource" "test_resource" {}

Debug Output

https://gist.githubusercontent.com/marlock9/735c73002992f61b8e1904af6d268914/raw/90f2a580376b3403ee8de63032582a88aaeee87b/gistfile1.txt

Crash Output

No crash

Expected Behavior

Okay, null_resource doesn't support import but terraform at least try to do import.

โžœ terraform import "module.test_module.module.test_module2.null_resource.test_resource" test
module.test_module.module.test_module2.null_resource.test_resource: Importing from ID "test"...

Error: resource null_resource doesn't support import

Actual Behavior

โžœ terraform import "module.test_module.module.test_module2.null_resource.test_resource" test   

Error: Invalid count argument

  on test_module/main.tf line 4, in module "test_module2":
   4:   count = length(var.regions)

The "count" value depends on resource attributes that cannot be determined
until apply, so Terraform cannot predict how many instances will be created.
To work around this, use the -target argument to first apply only the
resources that the count depends on.

Steps to Reproduce

terraform init
terraform import "module.test_module.module.test_module2.null_resource.test_resource" test

Additional Context

terraform apply works, but import doesn't!

References

bug confirmed explained v0.13

Most helpful comment

Hi all ,thanks for reporting this!
I can confirm that the reported issue is fixed in terraform v0.13.1 (which we plan to release next week), and we no longer get the Error: Invalid count argument message in this case:

module.test_module.module.test_module2.null_resource.test_resource: Importing from ID "test"...

Error: resource null_resource doesn't support import

๐ŸŽ‰

All 9 comments

@marlock9 thank you for reporting this! I confirmed this behavior exactly as reported. For the sake of ease of reproduction, I copied your reproduction case into https://github.com/danieldreier/terraform-issue-reproductions/tree/master/25816 so the engineer who picks this up won't have to copy-paste, but it's exactly the same repro case and behavior you described.

@danieldreier Thanks.
Also I want to add that same happens for for_each.

If you change test_module/main.tf to use for_each for test_module2:

variable "regions" {}

module "test_module2" {
  for_each = toset(var.regions)
  source = "./test_module2"
}

terraform apply will work, but terraform import doesn't.
But bug in main post and above happens with static-defined (literal) values when passing them to nested module.

Another case to fix - when using some data sources outputs as count or for_each values. I think it's related because terraform apply works, while terraform import doesn't.
Same layout, main.tf

provider "aws" {
  region = "us-west-2"
}

module "test_module" {
  source = "./test_module"
}

test_module/main.tf

data "aws_region" "current" {}

module "test_module2" {
  for_each = toset([data.aws_region.current.name])
  source = "./test_module2"
}

terraform apply

โžœ terraform apply                                
module.test_module.data.aws_region.current: Refreshing state...

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # module.test_module.module.test_module2["us-west-2"].null_resource.test_resource will be created
  + resource "null_resource" "test_resource" {
      + id = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

terraform import

โžœ terraform import "module.test_module.module.test_module2.null_resource.test_resource" test

Error: Invalid for_each argument

  on test_module/main.tf line 4, in module "test_module2":
   4:   for_each = toset([data.aws_region.current.name])

The "for_each" value depends on resource attributes that cannot be determined
until apply, so Terraform cannot predict how many instances will be created.
To work around this, use the -target argument to first apply only the
resources that the for_each depends on.

To exclude possible troubles with not using module index:

โžœ terraform import "module.test_module.module.test_module2[\"us-west-2\"].null_resource.test_resource" test        

Error: Invalid for_each argument

  on test_module/main.tf line 4, in module "test_module2":
   4:   for_each = toset([data.aws_region.current.name])

The "for_each" value depends on resource attributes that cannot be determined
until apply, so Terraform cannot predict how many instances will be created.
To work around this, use the -target argument to first apply only the
resources that the for_each depends on.

It's kinda artificial example but here is some real:
I want to use region name from data.aws_region provider to try to get a block from object and decide a count for module, e.g.:

count = try(var.env_setup[terraform.workspace][data.aws_region.current.name], null) == null ? 0 : 1

And again it works for terraform apply, but fails on terraform import.

Thanks for this report @marlock9! I'll attempt to add some insight here for future readers if someone wants to tackle this or alternatively mark it as a wontfix.

First, your import is to something where count is defined so your address should be:

module.test_module.module.test_module2[0].null_resource.test_resource

Which adds the index value for test_module2 to denote which module instance your import is intended for. Import can only be used for one resource at a time.

Onto more explanation: When using count or for_each on modules, there is a module expansion node nodeExpandModule and when that module expansion happens, the count value is evaluated, but in this scenario, it appears that it is getting evaluated before that variable value is evaluated (and thus is unknown). The import graph builder is different from the one used for plan/apply/other graph walks, so perhaps it is related to some difference here.

yeah, me too, but getting complaint on unrelated resource than one being imported:

terraform import -var-file=tfvars/lab.tfvars module.vpc.aws_vpc.this vpc-04d88d30de2b4c0ad
Error: Invalid count argument

  on module/vpc/cidr.tf line 29, in module "aux-cidr":
  29:   count  = (var.aux_cidr == null) ? 0 : 1

The "count" value depends on resource attributes that cannot be determined
until apply, so Terraform cannot predict how many instances will be created.
To work around this, use the -target argument to first apply only the
resources that the count depends on.



md5-37d8b28a5c85d4070984558fccffe88a



aux_cidr = "10.255.0.0/16"

yeah, me too, but getting complaint on unrelated resource than one being imported:

I observed this in #25854

I can't import a resource if there are any count-able modules or resources.

Daniels-MacBook-Pro-2:phonism danburkhol$ 
terraform import module.production-eu.module.networking.module.core.aws_vpc.vpc vpc-0ba3d76d

module.production-eu.module.networking.module.core.aws_vpc.vpc: Importing from ID "vpc-0ba3d76d"...
module.production-eu.module.networking.module.core.aws_vpc.vpc: Import prepared!
  Prepared aws_vpc for import
module.production-eu.module.networking.module.core.aws_vpc.vpc: Refreshing state... [id=vpc-0ba3d76d]

Error: Invalid for_each argument

  on terraform/environments/develop/develop.tf line 58, in module "target_group_request_anomalies":
  58:   for_each = module.networking.target_group_arn_suffixes

The "for_each" value depends on resource attributes that cannot be determined
until apply, so Terraform cannot predict how many instances will be created.
To work around this, use the -target argument to first apply only the
resources that the for_each depends on.

module.networking.target_group_arn_suffixes is dynamic but not at all related to the path I was trying to import to
module.production-eu.module.networking.module.core.aws_vpc.vpc

Can confirm as above from same issue, any countable modules present prohibit any unrelated resource import due to the graph construction failure.

As a workaround you can remove the countable module (rename file to different extension), then perform the import on the unrelated resource, then replace the countable module. The only change made to the state is the imported resource, so it doesn't matter what the rest of the graph looks like so long as all dependencies are satisfied for the resource you are importing.

Thanks for the work around! I'm commenting out all possible paths I don't want to import against and that works too.

At least this will get me by for now.

Hi all ,thanks for reporting this!
I can confirm that the reported issue is fixed in terraform v0.13.1 (which we plan to release next week), and we no longer get the Error: Invalid count argument message in this case:

module.test_module.module.test_module2.null_resource.test_resource: Importing from ID "test"...

Error: resource null_resource doesn't support import

๐ŸŽ‰

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rjinski picture rjinski  ยท  3Comments

carl-youngblood picture carl-youngblood  ยท  3Comments

rjinski picture rjinski  ยท  3Comments

pawelsawicz picture pawelsawicz  ยท  3Comments

larstobi picture larstobi  ยท  3Comments