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

Allow for numeric/string comparisons in count, or change resulting error message from '"cannot" to "will not" be determined' #34726

Closed
jaffel-lc opened this issue Feb 23, 2024 · 7 comments
Labels
enhancement new new issue not yet triaged

Comments

@jaffel-lc
Copy link

jaffel-lc commented Feb 23, 2024

Terraform Version

Terraform v1.7.4                                                                                                                                                                                                                                                   on linux_amd64                                                                                                                                                                                                                                                     + provider registry.terraform.io/hashicorp/aws v5.38.0                                                                                                                                                                                                             + provider registry.terraform.io/hashicorp/random v3.6.0

Use Cases

count allows for a ?: operator as long as the left side is a Boolean variable or a comparison of of that variables state.
for example:

count = var.create_resource ? 1 : 0
count = var.create_resource == true ? 1 : 0

But a string comparison in the same place generates an error.
For example:

   count       = var.kms_key == "AWSOwnedKey" ? 1 : 0 

Generates this error:

 Error: Invalid count argument                                                                                                                                                                                                                                    │                                                                                                                                                                                                                                                                  │   on ../main.tf line 28, in resource "aws_opensearchserverless_security_policy" "encryption_policy_aws_kms":                                                                                                                                                     │   28:   count       = var.kms_key == "AWSOwnedKey" ? 1 : 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.                               

In this case, the value of the variable absolutely can be determined at plan time. The values of all variables are known at plan time. Data blocks that rely on variables run at plan time, so they must therefore be available within resource block.

Attempted Solutions

The only way to solve the error error message is to rely on strictly Boolean values for count

Proposal

Terraform should, at plan-time, perform variable-base calculations and comparisons to that resource counts can rely on the truthiness of non-Boolean values - many languages consider 0 and "" to be false - in direct comparisons or including some calculations of function calls.

Or change the error message to say "will not be determined until apply time".

References

No response

@jaffel-lc jaffel-lc added enhancement new new issue not yet triaged labels Feb 23, 2024
@jaffel-lc jaffel-lc changed the title allow for numeric/string comparisons in count, or change resulting error message from '"cannot" to "will not" be determined' Allow for numeric/string comparisons in count, or change resulting error message from '"cannot" to "will not" be determined' Feb 23, 2024
@apparentlymart
Copy link
Contributor

apparentlymart commented Feb 24, 2024

Hi @jaffel-lc! Thanks for sharing this.

I want to pick out one part of what you said to start:

The values of all variables are known at plan time.

This statement is incorrect. It's true that the values of all root module input variables are known at plan time -- because they are specified directly as -var arguments, in .tfvars files, etc -- but that is not true for input variables in a child module. For example:

resource "aws_subnet" "example" {
  # ...
}

module "example" {
  # ...

  subnet_id = aws_subnet.example.id
}

aws_subnet populates its id attribute with an identifier chosen by the EC2 API only after the subnet has been created, and therefore it is unknown during the plan phase. Therefore, when viewed from inside module.example, var.subnet_id can be unknown during the plan phase. This is true regardless of the type of the value, but it tends to be most common with strings because that's the most likely type for an identifier chosen by the remote API.

I'm not sure whether that applies to your situation, though: your writeup doesn't show where the value of var.kms_key was taken from. If this expression is in your root module and you are setting kms_key as a root input variable from a .tfvars file (or equivalent), then what you've found here is a strange bug, which we could investigate further.

However, if what you have here is another example of the situation I illustrated above, where the input variable is derived from something that's unknown during planning, then I think this issue is essentially a subset of the existing #30937, for which some work has already been done and further work is happening right now.

@jaffel-lc
Copy link
Author

jaffel-lc commented Feb 26, 2024

In this case, the value of var.kms_key is a string variable , with a default value - not a value derived from a not-yet-existent resource.

variable "kms_key" {
  type        = string
  default     = "AWSOwnedKey"
}

@apparentlymart
Copy link
Contributor

Thanks for that extra context.

Can you also show me how you are setting the value for this variable? The caller of a module is the one that decides if a given variable value is known or not, so that's the more important thing to consider when figuring out what happened here.

@jaffel-lc
Copy link
Author

I already have.
The root module either passes nothing, letting the submodule use its default, or the root module passes the KMS Key's ARN in the kms_key parameter.

@jbardin
Copy link
Member

jbardin commented Feb 28, 2024

@jaffel-lc, We would need to see the kms_key assignment in the module call from within the root module to know for certain what you are doing. I'm assuming however that you mean you are assigning the arn attribute from an aws_kms_key resource. If that's the case, because the arn attribute cannot be known until after apply, it seems the error was accurate. If var.kms_key is unknown, then the entire expression of var.kms_key == "AWSOwnedKey" ? 1 : 0 is unknown, preventing Terraform from being able to plan that resource.

@jaffel-lc
Copy link
Author

I appreciate your patience and perseverance.

It took several readings, but I finally understood what you were trying to tell me.

I've rearranged my tests so that the KMS key is build in a tf apply before the apply that creates resource that tries to use it, and I am passing it from a data block instead of a module block. And it works, just like you said it would.

Thank you very much.

Copy link
Contributor

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 Apr 15, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement new new issue not yet triaged
Projects
None yet
Development

No branches or pull requests

3 participants