Search code examples
amazon-web-servicesaws-lambdaterraformamazon-sqsterraform-provider-aws

AWS multiple dynamic blocks in teraform aws_s3_bucket_notification


I am trying to get work s3 notifications with dynamic blocks in terraform. One of them should to be lambda and the second one must to be SQS.

For now I have code like this and it doesn't work.

I am getting this kind of error:

Error: Unsupported attribute
  on triggers.tf line 51, in resource "aws_s3_bucket_notification" "s3_lambda_sqs_trigger":
  51:       prefix = i.queue_prefix
This object does not have an attribute named "queue_prefix".
Error: Unsupported attribute
  on triggers.tf line 51, in resource "aws_s3_bucket_notification" "s3_lambda_sqs_trigger":
  51:       prefix = i.queue_prefix
This object does not have an attribute named "queue_prefix".
Error: Unsupported attribute
  on triggers.tf line 51, in resource "aws_s3_bucket_notification" "s3_lambda_sqs_trigger":
  51:       prefix = i.queue_prefix
This object does not have an attribute named "queue_prefix".
Error: Unsupported attribute
  on triggers.tf line 51, in resource "aws_s3_bucket_notification" "s3_lambda_sqs_trigger":
  51:       prefix = i.queue_prefix
This object does not have an attribute named "queue_prefix".

Is possible to have 2 dynamic blocks for one s3 bucket, please?

Could you help me, please?

Thanks in advance.

tfvars

create_s3_notifications_lambda_sqs = true
s3_notifications_lambda = {
    bucket = {
        name            = "dev-example-dev-149087"
        filters = [
            {
                events          = ["s3:ObjectCreated:*"]
                name            = "filter1"
                filter_prefix   = "appointment/input/"
                filter_suffix   = ".json"
            },
            {
                events          = ["s3:ObjectCreated:*"]
                name            = "filter2"
                filter_prefix   = "operator/input/"
                filter_suffix   = ".json"
            },
            {
                events          = ["s3:ObjectCreated:*"]
                name            = "filter3"
                filter_prefix   = "sa/input/"
                filter_suffix   = ".json"
            },
            {
                events          = ["s3:ObjectCreated:*"]
                name            = "filter4"
                filter_prefix   = "team/input/"
                filter_suffix   = ".json"
            }
        ]
        queue = [
            {
                events          = ["s3:ObjectCreated:*"]
                name            = "filter5"
                filter_prefix   = "appointment/status/"
            },
            {
                events          = ["s3:ObjectCreated:*"]
                name            = "filter6"
                filter_prefix   = "operator/status/"
            },
            {
                events          = ["s3:ObjectCreated:*"]
                name            = "filter7"
                filter_prefix   = "team/status/"
            },
            {
                events          = ["s3:ObjectCreated:*"]
                name            = "filter8"
                filter_prefix   = "sa/status/"
            }
        ]
    }
}

manifest

resource "aws_s3_bucket_notification" "s3_lambda_sqs_trigger" {
  for_each                         = {for item in var.s3_notifications_lambda:  item.name => item if var.create_s3_notifications_lambda_sqs}
  bucket                           = each.value.name

  dynamic "lambda_function" {
    for_each = [for item in each.value.filters: {
      suffix = item.filter_suffix
      prefix = item.filter_prefix
      events = item.events
    }]

    content {
      lambda_function_arn = "arn:aws:lambda:${var.region}:${var.arn_project}:function:${var.lambda_function_name}-${var.irn}-${var.sia}-${var.env}"
      events              = lambda_function.value.events
      filter_prefix       = lambda_function.value.prefix
      filter_suffix       = lambda_function.value.suffix
    }
  }

  dynamic "queue" {
    for_each = [for i in each.value.queue: {
      prefix = i.queue_prefix
      events = i.events
    }]

    content {
      queue_arn           = "arn:aws:sqs:${var.region}:${var.arn_project}:${var.sia}-${var.ecs_service}-${var.env}.fifo"
      events              = queue.value.events
      filter_prefix       = queue.value.prefix
    }
  }    
}

Solution

  • Here is the error message:

    prefix = i.queue_prefix This object does not have an attribute named "queue_prefix".

    So let's take that error message and look at the code:

    for i in each.value.queue: {
          prefix = i.queue_prefix
          events = i.events
        }
    

    So you are trying to reference an attribute named queue_prefix there, but if you look at the objects you are iterating over:

    queue = [
                {
                    events          = ["s3:ObjectCreated:*"]
                    name            = "filter5"
                    filter_prefix   = "appointment/status/"
                },
                {
                    events          = ["s3:ObjectCreated:*"]
                    name            = "filter6"
                    filter_prefix   = "operator/status/"
                },
                {
                    events          = ["s3:ObjectCreated:*"]
                    name            = "filter7"
                    filter_prefix   = "team/status/"
                },
                {
                    events          = ["s3:ObjectCreated:*"]
                    name            = "filter8"
                    filter_prefix   = "sa/status/"
                }
            ]
    

    There is nothing named queue_prefix. Exactly as the error message is telling you. There is however an attribute named filter_prefix which is almost certainly what you are trying to reference. So you need to change your code to this:

    for i in each.value.queue: {
          prefix = i.filter_prefix
          events = i.events
        }