terraform-aws-modules / terraform-aws-s3-bucket

Terraform module to create AWS S3 resources πŸ‡ΊπŸ‡¦

Home Page:https://registry.terraform.io/modules/terraform-aws-modules/s3-bucket/aws

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Error S3-Notification module when Create is conditional

crackmac opened this issue Β· comments

Description

When using a conditional for the 'create' parameter in the S3-Notification module you will get errors Error: invalid value for function_name and Error: "source_arn" (arn:aws:s3:::) is an invalid ARN: missing resource value.

Example of error

β”‚ Error: invalid value for function_name (must be valid function name or function ARN)
β”‚ 
β”‚   with module.develop_bucket_notify.aws_lambda_permission.allow["content_data_sync_lambda"],
β”‚   on .terraform/modules/develop_bucket_notify/modules/notification/main.tf line 67, in resource "aws_lambda_permission" "allow":
β”‚   function_name       = each.value.function_name

I have/will submit a PR with the proposed fix.

  • [βœ… ] βœ‹ I have searched the open/closed issues and my issue is not listed.

Versions

  • Module version [Required]:
    3.6.1

  • Terraform version:

    Terraform v1.2.7

  • Provider version(s):

    • provider registry.terraform.io/hashicorp/aws v4.54.0
    • provider registry.terraform.io/hashicorp/external v2.2.3
    • provider registry.terraform.io/hashicorp/local v2.3.0
    • provider registry.terraform.io/hashicorp/null v3.2.1
    • provider registry.terraform.io/hashicorp/random v3.4.3

Reproduction Code [Required]

module "develop_bucket_notify" {
  source  = "terraform-aws-modules/s3-bucket/aws//modules/notification"
  version = "3.6.1"

  create = var.environment == "develop" ? true : false

  bucket = module.bucket.s3_bucket_id

  lambda_notifications = {
    content_data_sync_lambda = {
      function_arn  = module.lambda.lambda_function_arn
      function_name = module.lambda.lambda_function_name
      events        = ["s3:ObjectCreated:Put"]
      filter_prefix = "test"
    }
  }
}

Expected behavior

We expect all module resources to not execute if the create flag is set to false

Actual behavior

The aws_s3_bucket_notification module resource works as expected.
The aws_lambda_permission module resource still examines the var.lambda_notifications object which, in our use case, does not resolve with valid values (function name and arn are only created during certain conditions)

Terminal Output Screenshot(s)

β”‚ Error: invalid value for function_name (must be valid function name or function ARN)
β”‚ 
β”‚   with module.develop_bucket_notify.aws_lambda_permission.allow["content_data_sync_lambda"],
β”‚   on .terraform/modules/develop_bucket_notify/modules/notification/main.tf line 67, in resource "aws_lambda_permission" "allow":
β”‚   function_name       = each.value.function_name

Additional context

We use the same Terraform plan for multiple environments and we only create the lambda and hence the S3-Notifications in one environment and not the others.

To do this, you can specify lambda_notifications conditionally. Like you already do with the create argument.

Please re-open this issue... we should discuss.


True that you can conditionally set lambda_notifications, but that would mean setting two conditionals in the same code block and it hurts the readability of the code. This is that mine would look like.

module "develop_bucket_notify" {
  source  = "terraform-aws-modules/s3-bucket/aws//modules/notification"
  version = "3.6.1"

  create = var.environment == "develop" ? true : false

  bucket = module.develop_bucket.s3_bucket_id != "" ? module.develop_bucket.s3_bucket_id : local.bucket_name

  lambda_notifications = var.environment == "develop" ? {
    content_data_sync_lambda = {
      function_arn  = module.lambda.lambda_function_arn
      function_name = module.lambda.lambda_function_name
      events        = ["s3:ObjectCreated:Put"]
      filter_prefix = "test"
    } : {}
  }
}

IMO The create parameter implies setting it to false should be all you need to do to disable the modele.

I understand that create is usually a super-argument which controls creation of all-or-nothing, but in this case, a user may want to create resources a bit more independently.

You can also do this:

module "develop_bucket_notify" {
  source  = "terraform-aws-modules/s3-bucket/aws//modules/notification"
  version = "3.6.1"

  count = var.environment == "develop" ? 1 : 0

  bucket = module.develop_bucket.s3_bucket_id

  lambda_notifications = {
    content_data_sync_lambda = {
      function_arn  = module.lambda.lambda_function_arn
      function_name = module.lambda.lambda_function_name
      events        = ["s3:ObjectCreated:Put"]
      filter_prefix = "test"
    }
  }
}

module "prod_bucket_notify" {
  source  = "terraform-aws-modules/s3-bucket/aws//modules/notification"
  version = "3.6.1"

  count = var.environment == "develop" ? 0 : 1

  bucket = local.bucket_name
}

output "bucket_id" {
  value = try(module.prod_bucket_notify[0].bucket_id, module.develop_bucket_notify[0].bucket_id, "")
}

That was my initial approach which failed because even though count = var.environment == "develop" ? 1 : 0 would be false, the module's for_each loop still tries to render module.lambda.lambda_function_arn and module.lambda.lambda_function_name which only exist in the develop environment. That's exactly why I submitted the fix I did.

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.