Search code examples
terraformamazon-sqsterraform-provider-aws

Dynamically create AWS SQS DLQ


I am trying to alter my AWS SQS module:

This is the before:

resource "aws_sqs_queue" "main" {
  name      = var.queue_name
  
  redrive_policy         = jsonencode({
    deadletterTargetArn  = aws_sqs_queue.aws-sqs-deadletter-queue.arn
    maxReceiveCount      = 4
  })
  redrive_allow_policy   = jsonencode({
    redrivePermission    = "byQuery"
    sourceQueueArns      = [aws_sqs_queue.aws-sqs-deadletter-queue.arn]
  })
}

resource "aws_sqs_queue" "aws-sqs-deadletter-queue" {
  name      = var.deadletter_queue_name
}

This validates fine and works. However, I want to make the creation of the DLQ dynamic (may or may not want a DLQ), so I tried to add a dynamic block:

resource "aws_sqs_queue" "main" {
  name      = var.queue_name
  
  dynamic "enable_dlq" {
    for_each = var.enable_dlq ? [1] : []

    redrive_policy         = jsonencode({
      deadletterTargetArn  = aws_sqs_queue.aws-sqs-deadletter-queue[0].arn
      maxReceiveCount      = 4
    })
    redrive_allow_policy   = jsonencode({
      redrivePermission    = "byQuery"
      sourceQueueArns      = [aws_sqs_queue.aws-sqs-deadletter-queue[0].arn]
    })
  }
}

resource "aws_sqs_queue" "aws-sqs-deadletter-queue" {
  count     = var.enable_dlq ? 1 : 0
  name      = var.deadletter_queue_name
}

In this case var.enable_dlq is a boolean value passed in.

However, when I attempt to validate this, TF fails with a:

Error: Unsupported block type
  on main.tf line xx, in resource "aws_sqs_queue" "main":
  xx: dynamic "enable_dlq" {

Blocks of type "enable_dlq" are not expected here.

Can a dynamic block statement not be part of "aws_sqs_queue" or did I define it wrong?


Solution

  • Your code is trying to implement a dynamic block with the name "enable_dlq". In Terraform, a dynamic block is a dynamic version of a block property in a resource. Your code doesn't work because you are trying to invent a new block property for the aws_sqs_queue resource type.

    Further, the aws_sqs_queue resource type doesn't even have any block properties. So you won't be able to use the dynamic block syntax here for what you are trying to do. The redrive_policy and redrive_allow_policy properties expect JSON strings, not Terraform blocks. To set them dynamically you need to simply set them to a JSON string, or null. I would do something like this:

    resource "aws_sqs_queue" "main" {
      name      = var.queue_name
      
      redrive_policy         = var.enable_dlq ? jsonencode({
        deadletterTargetArn  = aws_sqs_queue.aws-sqs-deadletter-queue[0].arn
        maxReceiveCount      = 4
      }) : null
    
      redrive_allow_policy   = var.enable_dlq ? jsonencode({
        redrivePermission    = "byQuery"
        sourceQueueArns      = [aws_sqs_queue.aws-sqs-deadletter-queue[0].arn]
      }) : null
    }
    
    resource "aws_sqs_queue" "aws-sqs-deadletter-queue" {
      count     = var.enable_dlq ? 1 : 0
      name      = var.deadletter_queue_name
    }