skip to Main Content

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

2

Answers


  1. That’s correct. You can’t have count or for_each depend on apply-level variables such as aws_kms_key.this.arn. Everything must be known at plan time, which means you have explicitly pass how many instances you want for count to work, or use -target to first create aws_kms_key.this, and then run your code again to create other resources.

    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search