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

Terraform module to create AWS S3 resources 🇺🇦
https://registry.terraform.io/modules/terraform-aws-modules/s3-bucket/aws
Apache License 2.0
513 stars 3.59k forks source link

Accept null value for replication_configuration variable #285

Open trc-smoehn opened 1 month ago

trc-smoehn commented 1 month ago

Description

With the current setup it is not possible to conditionally configure an S3 Bucket with replication_configuration. The true and false result expressions can't have consistent types, because the module code is not designed for that.

If the condition is true (replication_configuration should be defined), then an empty object ({}) as false result is not accepted and raises a Terraform error The true and false result expressions must have consistent types. The 'true' value includes object attribute "role", which is absent in the 'false' value., only null is possible.

If the condition is false (replication_configuration should not be defined), null is not accepted by the module code, resulting in the error Invalid value for "inputMap" parameter: argument must not be null..

Versions

Reproduction Code [Required]

resource "random_integer" "random" {
  min = 1000
  max = 9999
}

locals {
  use_bucket_replication01 = true
  use_bucket_replication02 = false
}

module "s3_replication" {
  source  = "terraform-aws-modules/s3-bucket/aws"
  version = "4.1.2"

  # General
  bucket = "replication-${random_integer.random.id}"

  # Versioning
  versioning = {
    enabled = true
  }

  # Replication
  replication_configuration = local.use_bucket_replication01 ? {
    role = aws_iam_role.replication_dummy_role.arn

    rules = [
      {
        id       = "replicate"
        status   = true
        priority = 10

        delete_marker_replication = false

        source_selection_criteria = {
          replica_modifications = {
            status = "Enabled"
          }
          sse_kms_encrypted_objects = {
            enabled = true
          }
        }

        destination = {
          bucket = "arn:aws:s3:::target-${random_integer.random.id}"
        }
      }
    ]
  } : {}
}

module "s3_no_replication" {
  source  = "terraform-aws-modules/s3-bucket/aws"
  version = "4.1.2"

  # General
  bucket = "no-replication-${random_integer.random.id}"

  # Versioning
  versioning = {
    enabled = true
  }

  # Replication
  replication_configuration = local.use_bucket_replication02 ? {
    role = aws_iam_role.replication_dummy_role.arn

    rules = [
      {
        id       = "replicate"
        status   = true
        priority = 10

        delete_marker_replication = false

        source_selection_criteria = {
          replica_modifications = {
            status = "Enabled"
          }
          sse_kms_encrypted_objects = {
            enabled = true
          }
        }

        destination = {
          bucket = "arn:aws:s3:::target-${random_integer.random.id}"
        }
      }
    ]
  } : null
}

module "s3_target" {
  source  = "terraform-aws-modules/s3-bucket/aws"
  version = "4.1.2"

  # General
  bucket = "target-${random_integer.random.id}"

  # Versioning
  versioning = {
    enabled = true
  }
}

resource "aws_iam_role" "replication_dummy_role" {
  name = "s3-bucket-replication-${random_integer.random.id}"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Sid    = ""
        Principal = {
          Service = "s3.amazonaws.com"
        }
      },
    ]
  })

  inline_policy {
    name = "s3"

    policy = jsonencode({
      Version = "2012-10-17"
      Statement = [
        {
          Action   = ["s3:*"]
          Effect   = "Allow"
          Resource = "*"
        },
      ]
    })
  }
}

Steps to reproduce the behavior:

Expected behavior

The module should accept null as value for the replication_configuration variable and check if the variable is null on the resource aws_s3_bucket_replication_configuration. Also it should set null as default value for the variable instead of {}.

Actual behavior

The module checks for length(keys(var.replication_configuration)) > 0 on resource aws_s3_bucket_replication_configuration, but giving an empty object as variable input produces "inconsistent types" error

Terminal Output Screenshot(s)

Screenshot 2024-08-21 at 11 00 57
github-actions[bot] commented 1 week ago

This issue has been automatically marked as stale because it has been open 30 days with no activity. Remove stale label or comment or this issue will be closed in 10 days