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

Invalid count argument #10

Closed
alemairebe opened this issue Jun 6, 2019 · 22 comments · Fixed by #17
Closed

Invalid count argument #10

alemairebe opened this issue Jun 6, 2019 · 22 comments · Fixed by #17

Comments

@alemairebe
Copy link

Hi all,

I'm using Terraform v0.12.1 and I get this error when trying to plan my manifest. I do no see where "count" uses resources which needs to be deployed first.

Error: Invalid count argument

  on .terraform/modules/bootstrap.acm/terraform-aws-modules-terraform-aws-acm-566067c/main.tf line 30, in resource "aws_route53_record" "validation":
  30:   count = var.create_certificate && var.validation_method == "DNS" && var.validate_certificate ? length(local.distinct_domain_names) : 0

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.

Here is how I invoke the module

module "acm" {
  source  = "terraform-aws-modules/acm/aws"
  version = "v2.0.0"

  create_certificate = var.certificate_arn == "" ? true : false

  domain_name = var.acm_certificate_domain_name == "" ? join(".", list(var.name, var.route53_zone_name)) : var.acm_certificate_domain_name

  zone_id = var.certificate_arn == "" ? element(concat(data.aws_route53_zone.this.*.id, list("")), 0) : ""

  tags = "${local.tags}"
}

Thanks !

@antonbabenko
Copy link
Member

This code does not contain references to resources, but only to data-sources and static vars, so it is strange that you get this error.

From this, it looks that domain_name argument is empty. Please verify values of var.acm_certificate_domain_name, var.name and var.route53_zone_name.

@alemairebe
Copy link
Author

When I ran this code, the values were :

var.acm_certificate_domain_name=""
var.name="atlantis"
var.route53_zone_name="test.mydomain.info"

which should result in atlantis.test.mydomain.info for debug purpose , I changed my code to

module "acm" {
  source  = "terraform-aws-modules/acm/aws"
  version = "v2.0.0"

  create_certificate = var.certificate_arn == "" ? true : false

  domain_name = "atlantis.test.mydomain.info"

  zone_id = var.certificate_arn == "" ? element(concat(data.aws_route53_zone.this.*.id, list("")), 0) : ""

  tags = "${local.tags}"
}

and I still get the same message

Then I clear my .terraform folder and did a terraform init && terraform plan
seems to work now !
Maybe an update in a provider...

Thanks for looking at it 👍

@nunofernandes
Copy link

I also got the same issue. I'm in the process of upgrading to terraform 0.12 and hit this.

Terraform v0.12.2
+ provider.aws v2.16.0
+ provider.template v2.1.2

Code:

module "site-co-uk" {
  source  = "terraform-aws-modules/acm/aws"
  version = "~> 2.1"

  domain_name = "*.site.co.uk"
  zone_id     = aws_route53_zone.site-co-uk-public.zone_id

  tags = {
    Name       = "wildcard-site.co.uk"
    Terraform  = "true"
    CostCenter = "site"
  }
}

and get the same error:

terraform.0.12 plan  --target=module.site-co-uk
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

aws_route53_zone.site-co-uk-public: Refreshing state... [id=XXXXXXX]
module.site-co-uk.aws_acm_certificate.this[0]: Refreshing state... [id=arn:aws:acm:eu-west-1:12345678:certificate/XXXXXXX]

Error: Invalid count argument

  on .terraform/modules/site-co-uk/terraform-aws-modules-terraform-aws-acm-5b77784/main.tf line 30, in resource "aws_route53_record" "validation":
  30:   count = var.create_certificate && var.validation_method == "DNS" && var.validate_certificate ? length(local.distinct_domain_names) : 0

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.

Releasing state lock. This may take a few moments...

Cleaning up the .terraform directory and doing a terraform init didn't help.

@antonbabenko
Copy link
Member

Try this code:

module "site-co-uk" {
  source  = "terraform-aws-modules/acm/aws"
  version = "~> 2.1"

  domain_name = "site.co.uk"
  zone_id     = aws_route53_zone.site-co-uk-public.zone_id

  subject_alternative_names = ["*.site.co.uk"]

  tags = {
    Name       = "wildcard-site.co.uk"
    Terraform  = "true"
    CostCenter = "site"
  }
}

@nunofernandes
Copy link

@antonbabenko thanks. I tried that before but it would force the recreation of the cert:

-/+ destroy and then create replacement
+/- create replacement and then destroy

Terraform will perform the following actions:

  # module.site-co-uk.aws_acm_certificate.this[0] must be replaced
+/- resource "aws_acm_certificate" "this" {
      ~ arn                       = "arn:aws:acm:eu-west-1:12345:certificate/XXXX" -> (known after apply)
      ~ domain_name               = "*.site.co.uk" -> "site.co.uk" # forces replacement
      ~ domain_validation_options = [
          - {
              - domain_name           = "*.site.co.uk"
              - resource_record_name  = "_4dcf16a519cd998d6ce83de46d6288fd.site.co.uk."
              - resource_record_type  = "CNAME"
              - resource_record_value = "_7eaf393c237a0f6745b8946051447306.ltfvzjuylp.acm-validations.aws."
            },
        ] -> (known after apply)
      ~ id                        = "arn:aws:acm:eu-west-1:12345:certificate/XXXXXX" -> (known after apply)
      ~ subject_alternative_names = [ # forces replacement
          + "*.site.co.uk",
        ]
        tags                      = {
            "CostCenter" = "site"
            "Name"       = "wildcard-site.co.uk"
            "Terraform"  = "true"
        }
      ~ validation_emails         = [] -> (known after apply)
        validation_method         = "DNS"
    }

  # module.site-co-uk.aws_acm_certificate_validation.this[0] must be replaced
-/+ resource "aws_acm_certificate_validation" "this" {
      ~ certificate_arn         = "arn:aws:acm:eu-west-1:538364834955:certificate/63ed942d-6bcd-46b4-a114-81f72025c301" -> (known after apply) # forces replacement
      ~ id                      = "2019-05-30 11:02:32 +0000 UTC" -> (known after apply)
      ~ validation_record_fqdns = [
          - "_4dcf16a519cd998d6ce83de46d6288fd.site.co.uk",
        ] -> (known after apply) # forces replacement

      - timeouts {}
    }

  # module.site-co-uk.aws_route53_record.validation[0] must be replaced
-/+ resource "aws_route53_record" "validation" {
        allow_overwrite = true
      ~ fqdn            = "_4dcf16a519cd998d6ce83de46d6288fd.site.co.uk" -> (known after apply)
      ~ id              = "Z1Y0Y8ITAJ6H01__4dcf16a519cd998d6ce83de46d6288fd.site.co.uk_CNAME" -> (known after apply)
      ~ name            = "_4dcf16a519cd998d6ce83de46d6288fd.site.co.uk" -> (known after apply) # forces replacement
      ~ records         = [
          - "_7eaf393c237a0f6745b8946051447306.ltfvzjuylp.acm-validations.aws.",
        ] -> (known after apply)
        ttl             = 60
      ~ type            = "CNAME" -> (known after apply)
        zone_id         = "Z123456"
    }

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

Is that the only way? To recreate it?

@antonbabenko
Copy link
Member

Yes, this is the easiest way. You can optionally try to taint aws_acm_certificate, but I have not tried it.

@waeltken
Copy link

waeltken commented Jul 4, 2019

Could we reopen this? I'm running into the same issue.

It happens when subject_alternative_names contains the empty array, which is also the default.

@mbravorus
Copy link

mbravorus commented Jul 7, 2019

Same issue here, occurring while invoking the module from Atlantis ecs module (same author), with no existing ACM cert specified so one is expected to be created

@antonbabenko
Copy link
Member

@waeltken @mbravorus Please provide an exact snippet of the code you are using. It is pretty much impossible for me to guess where the problem is without trying to run it myself and see the problem.

I run examples (see https://github.com/terraform-aws-modules/terraform-aws-acm/blob/master/examples/complete-dns-validation/main.tf) as they are now and with an empty subject_alternative_names and it always works.

The problems can be when a wildcard is specified in domain_name instead of subject_alternative_names.

@antonbabenko
Copy link
Member

I've made a small improvement when trying to access non-existing element, which may be related to the initial issue.

Released v2.2.0.

@antonbabenko antonbabenko reopened this Jul 8, 2019
@mbravorus
Copy link

Thank you! Will test ASAP.

I included a more detailed code snippet for the original problem in my comment here - terraform-aws-modules/terraform-aws-atlantis#61

@mbravorus
Copy link

Just looking at the diff, I doubt it will fix the issue though - if I understand correctly, the whole issue is that terraform bails out on line 30 because it can't calculate count before apply stage, and that is most likely related to length() on a local.distinct_names because it depends on a template being rendered, which doesn't happen until apply?

Pure speculation though, I will test and report back as soon as I can

@antonbabenko
Copy link
Member

You are absolutely right, the change I made half hour ago won't fix the initial problem but fix not-yet-reported issue.

tom-butler pushed a commit to opendatacube/datacube-k8s-eks that referenced this issue Jul 24, 2019
Same error message as in terraform-aws-modules/terraform-aws-acm#10. This
change enables the cluster to be destroyed in one go.
@reegnz
Copy link

reegnz commented Jul 24, 2019

The problems can be when a wildcard is specified in domain_name instead of subject_alternative_names.

Yupp, I encountered the same issue.
I have domain_name = '*.example.com' and with the default empty list of SAN it failed like in the description.

I also added the wildcard name to SAN and now it works:

domain_name = '*.example.com'
subject_alternative_names = ['*.example.com']

Only problem is that I cannot refactor like this, since it wants to generate a new certificate now that has SAN, while I only need a single wildcard cert without SAN.

@ryzr
Copy link

ryzr commented Aug 14, 2019

Would something like this fix it?

locals {
  // Get distinct list of domains and SANs
  distinct_domain_names = distinct(concat([var.domain_name], local.san_domains))

  san_domains = [for v in var.subject_alternative_names : replace(v, "*.", "")]

  // Copy domain_validation_options for the distinct domain names
  validation_domains = [for k, v in aws_acm_certificate.certificate.domain_validation_options : tomap(v) if contains(local.distinct_domain_names, v.domain_name)]

I'm not using any wildcard SANs, so I haven't been in a position to validate whether it works as intended, but this is what I'm doing currently to avoid issues with the template resource.

Please let me know if not - I'm still trying to wrap my head around HCL.

@rldw
Copy link

rldw commented Aug 20, 2019

Having the same issue after upgrading from Terraform 0.11.x to 0.12.6 and subsequently upgrading this module.

My configuration:

module "acm" {
  source = "../aws-acm"

  domain_name  = "subdomain.mydomain.tld"
  zone_id      = "${data.aws_route53_zone.dns_zone.id}"

  subject_alternative_names = [
    "*.mydomain.tld",
  ]

  wait_for_validation = "false"
}

@threeturn
Copy link

threeturn commented Aug 28, 2019

Having the same issue. My code:


module "acm" {
  source  = "terraform-aws-modules/acm/aws"
  version = "~> 2.2.0"

  zone_id       = var.route53_zone_id
  domain_name   = local.opsworks_fqdn

  wait_for_validation = true 
}


resource "aws_route53_record" "opsworks_automate" {
  zone_id = var.route53_zone_id
  name    = var.opsworks_automate_name
  type    = "CNAME"
  ttl     = "300"
  records = [module.elb.this_elb_dns_name]
}

mpilar pushed a commit to mpilar/terraform-aws-acm that referenced this issue Sep 1, 2019
- Also added an explicit dependency for the route 53 record
- Between the two it fixed terraform-aws-modules#10 for me
antonbabenko pushed a commit that referenced this issue Sep 2, 2019
- Also added an explicit dependency for the route 53 record
- Between the two it fixed #10 for me
@antonbabenko
Copy link
Member

v2.3.0 has been released, and hopefully, it will fix this problem for everyone.

@mosesrenegade
Copy link

I have a new one that I'm not sure belongs here, but I'll ask anyway. I am doing something very specific where I am autogenerating a subdomain based on the terraform random-pet resource. The code would look like this:

resource "random_pet" "this" {
length = 2
}

module "acm" {
source = "terraform-aws-modules/acm/aws"
version = "~> 2.3.0"

zone_id = "${aws_route53_zone.class.zone_id}"

domain_name = ".${random-pet.this.id}.example.com"
subject_alternative_names = ["*.${random-pet.this.id}.example.com"]

wait_for_validation = true
}

I'm just curious if there is a way to tell terraform to do this ahead of checking for this. It does work if I run an apply first generate all the domains and then add the ACM. I'm just not sure if I can link these two things together.

@air3ijai
Copy link

air3ijai commented May 1, 2022

Was this issue fixed or not?

It is very similar to the issue The "for_each" value depends on resource attributes that cannot be determined until apply #59 in module route53/records

Code

module "acm" {
  source  = "terraform-aws-modules/acm/aws"
  version = "~> v3.4"

  domain_name = "test.tld"
  zone_id     = "XXXXXXXXXXXXXXXXXXXXX"

  subject_alternative_names = [
    "*.test.tld"
    "*.test-${random_string.test.result}.test.tld"
  ]
  depends_on = [random_string.test]
}

resource "random_string" "test" {
  length  = 5
  special = false
}

Error

│ Error: Invalid count argument
│
│   on .terraform/modules/acm/main.tf line 37, in resource "aws_route53_record" "validation":
│   37:   count = local.create_certificate && var.validation_method == "DNS" && var.create_route53_records && var.validate_certificate ? length(local.distinct_domain_names) : 0
│
│ 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.
╵

If "*.test-${random_string.test.result}.test.tld" is removed, plan works well.

@mmirik
Copy link

mmirik commented May 11, 2022

I am having this exact problem as provided by mbravorus above:


Just looking at the diff, I doubt it will fix the issue though - if I understand correctly, the whole issue is that terraform bails out on line 30 because it can't calculate count before apply stage, and that is most likely related to length() on a local.distinct_names because it depends on a template being rendered, which doesn't happen until apply?

Pure speculation though, I will test and report back as soon as I can

│ Error: Invalid count argument
│
│   on .terraform/modules/kaitoa_acm/main.tf line 37, in resource "aws_route53_record" "validation":
│   37:   count = local.create_certificate && var.validation_method == "DNS" && var.create_route53_records && var.validate_certificate ? length(local.distinct_domain_names) : 0
│
│ 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.

here is my snippet

module "admin_acm" {
  source  = "terraform-aws-modules/acm/aws"
  version = "~> 3.0"
  providers = {
    aws = aws.us-east-1
  }
  domain_name  = trimsuffix(aws_route53_record.public_domain_admin.fqdn, ".")
  zone_id      = var.public_domain_zone_id
  wait_for_validation = true
  tags = local.tags 
}

Do I have to enter the actual domain name rather than pull this from the AWS record I am creating? Is there a way to ensure that the certificate is created after the DNS record and that that record is available to the module?

@github-actions
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 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.