I am getting error when the module has a count condition within that is checking an input value. And the input value is dependent on the resource that is being created along with module.
resource "aws_kms_key" "this" {
}
module "service_secret" {
source = "./secret"
name = "foo-bar"
kms_arn = aws_kms_key.this.arn
tags = {}
}
in module secret
:
resource "aws_secretsmanager_secret" "this" {
name = var.name
kms_key_id = var.kms_arn == "" ? aws_kms_key.this[0].arn : var.kms_arn
}
resource "aws_kms_key" "this" {
count = var.kms_arn != "" ? 0 : 1
}
Error:
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. count = var.kms_arn != "" ? 0 : 1
The hashicorp/aws
provider is reporting that it doesn't yet know anything about the final value of the arn
attribute of aws_kms_key.this
, and so Terraform in turn cannot predict whether that value is different from ""
.
If you are using Terraform v1.8 or later then you can use the apparentlymart/assume
provider (disclosure: I wrote this provider) to tell Terraform to make some additional assumptions about this value, to compensate for the AWS provider's imprecise result.
First I'd suggest using null
instead of ""
to represent "no KMS ARN", because that's the idiomatic way to represent the absence of something in Terraform. In your ./secret
module, declare the variable and use it like this:
variable "kms_arn" {
type = string
default = null
}
resource "aws_kms_key" "this" {
count = var.kms_arn != null ? 0 : 1
}
This change alone will not improve the problem, because the current version of the AWS provider at the time I'm writing this also doesn't assure Terraform that the arn
attribute is never null. But you can use the apparentlymart/assume
provider in your root module to promise Terraform that this value cannot be null:
# (if you already have a file with a required_providers
# block in it, merge the extra "assume" entry into your
# existing block.)
terraform {
required_providers {
assume = {
source = "apparentlymart/assume"
}
}
}
resource "aws_kms_key" "this" {
}
module "service_secret" {
source = "./secret"
name = "foo-bar"
kms_arn = provider::assume::notnull(aws_kms_key.this.arn)
tags = {}
}
The expression provider::assume::notnull(aws_kms_key.this.arn)
uses the provider's notnull
function to promise Terraform that whatever final value this attribute takes it will definitely not be null
.
When Terraform evaluates var.kms_key != null
inside the module it will then assume the answer is true
, and thus the count
will be set to zero.
Hopefully in a future version of the hashicorp/aws
provider the provider itself will tell Terraform that the arn
attribute is never null, avoiding the need for this additional notnull
function.
Terraform's ability to track "not null", and some other constraints on unknown values, is a relatively new feature and so most providers are not updated to use it yet. I wrote the apparentlymart/assume
provider as an interim solution so that module authors don't need to wait for all providers to be updated.