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

don't validate a resource block when there is a static count = 0 #36776

Open
EugenKon opened this issue Mar 26, 2025 · 5 comments
Open

don't validate a resource block when there is a static count = 0 #36776

EugenKon opened this issue Mar 26, 2025 · 5 comments
Labels
enhancement new new issue not yet triaged

Comments

@EugenKon
Copy link

EugenKon commented Mar 26, 2025

Terraform Version

v1.11.3

Terraform Configuration Files

locals {
  cdn_ssl_san = [""]
}

resource "aws_acm_certificate" "acm-ssl-cdn" {
  count = 0
  domain_name               = local.cdn_ssl_subject_domain
  subject_alternative_names = local.cdn_ssl_san
  validation_method         = "DNS"

  # https://docs.aws.amazon.com/acm/latest/userguide/acm-public-certificates.html#request-public-cli
  key_algorithm = "EC_prime256v1"
  lifecycle {
    create_before_destroy = true # Ensures a smooth transition during updates
  }

  provider = aws.cdn_provider
}

Debug Output

│ Error: expected length of subject_alternative_names.0 to be in the range (1 - 253), got
│
│   with module.private-cloud.aws_acm_certificate.acm-ssl-cdn,
│   on modules/private-cloud/ssl.tf line 216, in resource "aws_acm_certificate" "acm-ssl-cdn":
│  216:   subject_alternative_names = local.cdn_ssl_san
│
╵

Expected Behavior

When count = 0 all checks for the resource should be disabled, because it will not be created.

Actual Behavior

TF tries to verify parameters even if resource was disabled.

Steps to Reproduce

  1. terraform plan/apply

Additional Context

Even more it is not clear not to disable for_each which refers that disabled resource:
I can not use count=0 with for_each:

│ Error: Invalid combination of "count" and "for_each"
│
│   on modules/private-cloud/ssl.tf line 257, in resource "aws_route53_record" "acm-ssl-cdn-validation":
│  257:   for_each = {
│
│ The "count" and "for_each" meta-arguments are mutually-exclusive, only one should be used to be explicit about the number
│ of resources to be created.
resource "aws_route53_record" "acm-ssl-cdn-validation" {
  count = 0
  for_each = {
    for dvo in aws_acm_certificate.acm-ssl-cdn[0].domain_validation_options : dvo.domain_name => {
      zone_id = lookup(local.cdn_hostedzone_ids, dvo.domain_name, data.aws_route53_zone.cdn_zones[0].zone_id)
      name    = dvo.resource_record_name
      type    = dvo.resource_record_type
      record  = dvo.resource_record_value
    }
    if !startswith(dvo.domain_name, "*.")
  }

  zone_id = each.value.zone_id
  name    = each.value.name
  type    = each.value.type
  records = [each.value.record]
  ttl     = 60
}

And If count=0 for for_each is removed then I receive the next error:

│ Error: Invalid index
│
│   on modules/private-cloud/ssl.tf line 257, in resource "aws_route53_record" "acm-ssl-cdn-validation":
│  257:     for dvo in aws_acm_certificate.acm-ssl-cdn[0].domain_validation_options : dvo.domain_name => {
│     ├────────────────
│     │ aws_acm_certificate.acm-ssl-cdn is empty tuple
│
│ The given key does not identify an element in this collection value: the collection has no elements.
╵

References

No response

Generative AI / LLM assisted development?

No response

@EugenKon EugenKon added bug new new issue not yet triaged labels Mar 26, 2025
@crw crw added the working as designed confirmed as reported and closed because the behavior is intended label Mar 26, 2025
@crw crw closed this as completed Mar 26, 2025
@crw crw reopened this Mar 26, 2025
@crw crw removed the working as designed confirmed as reported and closed because the behavior is intended label Mar 26, 2025
@jbardin jbardin added enhancement and removed bug labels Mar 27, 2025
@jbardin
Copy link
Member

jbardin commented Mar 27, 2025

Using a static count=0 like this is akin to attempting to comment out a resource block, though as you've seen Terraform will still require it to be valid, because it's part of the configuration and Terraform doesn't expect to find completely unused configuration. No, you can't use count and for_each at the same time, the concepts are mutually exclusive. Other than your example here which kind of makes sense, Terraform wouldn't be able to expand the resource into an ordered series of instances with integer keys and an unordered set of instances with string keys at the same time.

I feel like there is a duplicate of this somewhere, but likely quite old. The edge case of statically writing count=0 to disable a resource isn't really harder than selecting and commenting out that resource, and even then the references within the block are usually still correct and don't fail.

@jbardin jbardin changed the title [Bug]. Do not verify parameters if resource is disabled. Error: expected length of subject_alternative_names.0 to be in the range (1 - 253), got don't validate a resource block when there is a static count = 0 Mar 27, 2025
@EugenKon
Copy link
Author

EugenKon commented Mar 27, 2025

The real config is a bit more complex. I just simplified it here.

The block depends on the configuration and looks like:

  count = local.someconfig == "xxxx"? 1 : 0

Where local.someconfig depends on somconfig at file.yaml. Thus I can not just comment out it =(.

@jbardin
Copy link
Member

jbardin commented Mar 27, 2025

I think that shows why it's not possible to skip in general, which is why I assumed that we could reduce this to count=0. Validation happens statically, using unknown values for all inputs to make sure the configuration is as broadly valid as possible given any set of inputs. What this means is that expansion can't be taken into account during validation, and we treat it as an unknown value in order to validate the configuration block with the provider. If count were entirely static there might be a way to short-circuit that and skip validation (whether that's a good idea or not is a different matter), but in general we can't assume it's going to be possible to evaluate count there at all.

@EugenKon
Copy link
Author

EugenKon commented Apr 2, 2025

I tried different solution here without success. The idea was to move all these configuration files into separate module and disable it. Unfortunately this does not work. I expected that TF just skip TF files at the disabled module, but TF unfortunately still process them. Here is minimized part of configuration:

locals {
  enable_cdn = local.cluster.domain.cdn_ssl_domains == ""
}
module "cdn" {
  count  = local.enable_cdn ? 1 : 0
  source = "./modules/cdn"

  project_name = local.project_name
}

module "dns" {
  source = "./modules/dns"
  ...
  cloudfront_domain = local.enable_cdn ? module.cdn[0].cloudfront_domain : {}
}

The errors I faced:

│ Error: Invalid index
│
│   on main.tf line 100, in module "dns":
│  100:   cloudfront_domain = local.enable_cdn ? module.cdn[0].cloudfront_domain : {}
│     ├────────────────
│     │ module.cdn is empty tuple
│
│ The given key does not identify an element in this collection value: the collection has no
│ elements.

and for files inside module:

locals {
  cluster = yamldecode(file("${path.root}/../../cluster-config.yaml"))
}
locals {
  cdn_ssl_hostedzones    = compact(split(" ", local.cluster.domain.cdn_ssl_hostedzones))
  cdn_ssl_domains        = compact(split(" ", local.cluster.domain.cdn_ssl_domains))
  cdn_ssl_subject_domain = local.cdn_ssl_domains[0]
  cdn_ssl_san            = flatten([for domain in local.cdn_ssl_domains : [domain]])
}

This error happens when local.cluster.domain.cdn_ssl_domains = "".

│ Error: Invalid index
│
│   on modules/cdn/ssl.tf line 16, in locals:
│   16:   cdn_ssl_subject_domain = local.cdn_ssl_domains[0]
│     ├────────────────
│     │ local.cdn_ssl_domains is empty list of string
│
│ The given key does not identify an element in this collection value: the collection has no
│ elements.

It seems TF during static checks do some dynamic processing. Here we can see that TF sees that value is "". Thus configuration was read and thus configuration analysis is not completely static.

Expected result:

  • TF should not process files for disabled modules
  • TF should not process false branches for ?: the expressions (because TF sees values during static check it would be better to ignore false branches).

@jbardin
Copy link
Member

jbardin commented Apr 2, 2025

That is still the same fundamental issue, expansion is not handled during validation. Adding a module exposes a slightly different version of the situation though, because modules themselves are not a single entity within Terraform, they are really just a namespace for the resources they contain, so the configuration for the resources exists regardless of whether the module itself is expanded.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement new new issue not yet triaged
Projects
None yet
Development

No branches or pull requests

3 participants