Search code examples
foreachterraformterraform-provider-awsconditional-operator

Prevent a Terraform resource with for_each from being created depending on a condition


I'm using the following resources to create a DynamoDB table with items from a JSON file of objects.

module "dynamodb_label" {
  source = "./modules/labels"

  enabled = var.ENABLE_TABLE
  name    = var.dynamodb_name

  context = module.this.context
}

locals {
  json_data               = file("./items.json")
  items                 = jsondecode(local.json_data)
}

module "dynamodb_table" {
  source = "./aws-dynamodb"

  count = var.ENABLE_TABLE ? 1 : 0

  hash_key                      = "schema"
  hash_key_type                 = "S"
  autoscale_write_target        = 50
  autoscale_read_target         = 50
  autoscale_min_read_capacity   = 5
  autoscale_max_read_capacity   = 1000
  autoscale_min_write_capacity  = 5
  autoscale_max_write_capacity  = 1000
  enable_autoscaler             = true
  enable_encryption             = true
  enable_point_in_time_recovery = true
  ttl_enabled                   = false

  dynamodb_attributes = [
    {
      name = "schema"
      type = "S"
    }
  ]

  context = module.dynamodb_label.context
}

resource "aws_dynamodb_table_item" "dynamodb_table_item" {
  for_each   = var.ENABLE_TABLE ? local.items : {}
  table_name = module.dynamodb_table.table_name
  hash_key   = "schema"
  item       = jsonencode(each.value)

  depends_on = [module.dynamodb_table]

}

The JSON file

{
  "Item1": {
    "schema": {
      "S": "https://schema.org/government-documents#id-card"
    },
    "properties": {
      "S": "{\"documentName\":{\"type\":\"string\"},\"dateOfBirth\":{\"type\":\"string\"}}"
    }
  },
  "Item2": {
    "schema": {
      "S": "https://schema.org/government-documents#drivers-license"
    },
    "properties": {
      "S": "{\"documentName\":{\"type\":\"string\"},\"dateOfBirth\":{\"type\":\"string\"}}"
    }
  }
}

I'm getting the following error

Error: Inconsistent conditional result types

  on dynamodb-table.tf line 173, in resource "aws_dynamodb_table_item" "dynamodb_table_item":
 173:   for_each   = var.ENABLE_TABLE ? local.items : {}
    ├────────────────
    │ local.items is object with 13 attributes
    │ var.ENABLE_TABLE is a bool, known only after apply

The true and false result expressions must have consistent types. The given expressions are object and object, respectively.

I've tried many options to pass this error even change the variable type from bool to object. If I remove the condition in for_each and just pass local.items the aws_dynamodb_table_item tries to create regardless of the depends_on and it fails of course to create because table_name is returned empty because of count = module.dynamodb_label.enabled ? 1 : 0 in dynamodb_table module

I want the aws_dynamodb_table_item to be skipped if var.ENABLE_TABLE is set to false

What am I missing here? Any hint is highly appreciated.

EDIT: Tried the following so far all with same error;

for_each = var.ENABLE_TABLE == true ? local.schemas : {}
for_each = var.ENABLE_TABLE ? local.items : {}


Solution

  • After experimenting for 2 days around different types of expressions to get around this issue a kind sir on Reddit referred to this solution and it worked like a charm;

    for_each = { for k,v in local.items : k => v if var.ENABLE_TABLE }

    For anyone with a similar requirement this seems a gem that I have missed and recommend you to use it.