cloudposse / terraform-aws-s3-bucket

Terraform module that creates an S3 bucket with an optional IAM user for external CI/CD systems
https://cloudposse.com/accelerate
Apache License 2.0
168 stars 838 forks source link

Support multiple locals for configuration rules #242

Closed AnonymousWP closed 3 months ago

AnonymousWP commented 3 months ago

Describe the Feature

I'd like the module to support multiple locals. For example, a solution like this would be sufficient:

  1. Create a locals.tf where you define your lifecycle
  2. Use the locals in the same file as where the module is

locals.tf:

locals {
  s3_redacted_backup_rules = [
    {
      enabled = true
      id      = "redactedlifecyclerule"

      abort_incomplete_multipart_upload_days = 1

      filter_and = null
      expiration = {
        days = 360
      }
      noncurrent_version_expiration = {
        newer_noncurrent_versions = 3
        noncurrent_days           = 60
      }
      transition = [
        {
          days          = 15
          storage_class = "GLACIER"
        }
      ]
      noncurrent_version_transition = [{
        newer_noncurrent_versions = 3
        noncurrent_days           = 30
        storage_class             = "GLACIER"
      }]
    }
  ]

  s3_redacted1_backup_rules = [
    {
      enabled                                = true
      id                                     = "v2rule"
      abort_incomplete_multipart_upload_days = 1
      filter_and                             = null
      expiration = {
        days = 365
      }
      transition = [
        {
          days          = 90
          storage_class = "GLACIER_IR"
        }
      ]
      noncurrent_version_transition = [
        {
          noncurrent_days = 180
          storage_class   = "DEEP_ARCHIVE"
        }
      ]
    }
  ]
}

redacted1_backup.tf:

module "s3_redacted1_backup" {
  source  = "cloudposse/s3-bucket/aws"
  version = "4.5.0"

  name                    = "redacted1backup"
  stage                   = var.tags["environment"]
  namespace               = var.tags["company"]
  enabled                 = true
  user_enabled            = true
  versioning_enabled      = true
  block_public_acls       = false
  block_public_policy     = false
  ignore_public_acls      = false
  restrict_public_buckets = false
  allowed_bucket_actions = [
    "s3:AbortMultipartUpload",
    "s3:GetBucketAcl",
    "s3:GetBucketLocation",
    "s3:ListBucketMultipartUploads",
    "s3:PutObject",
    "s3:PutObjectAcl"
  ]
}

locals {
  lifecycle_configuration_rules = local.s3_redacted1_backup_rules
}

redacted_backup.tf:

module "s3_redacted_backup" {
  source                  = "cloudposse/s3-bucket/aws"
  version                 = "3.0.0"
  name                    = "redactedbackup"
  stage                   = var.tags["environment"]
  namespace               = var.tags["company"]
  enabled                 = true
  user_enabled            = true
  versioning_enabled      = true
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
  allowed_bucket_actions = [
    "s3:AbortMultipartUpload",
    "s3:GetBucketAcl",
    "s3:GetBucketLocation",
    "s3:ListBucket",
    "s3:GetObject",
    "s3:ListBucketMultipartUploads",
    "s3:PutObject",
    "s3:PutObjectAcl"
  ]
}

locals {
  lifecycle_configuration_rules = local.s3_redacted_backup_rules
}

Expected Behavior

I expect the module to support multiple locals in any form.

Use Case

Currently, the module doesn't support having multiple locals. For example, I have one stack for S3 with buckets. Each bucket can require different configuration rules, so I defined two locals (for two different buckets). But because the module expects something like lifecycle_configuration_rules, it complains that there are duplicate local names:

Error: Duplicate local value definition
│
│   on s3-redacted1-backup.tf line 26, in locals:
│   26:   lifecycle_configuration_rules = local.s3_redacted1_backup_rules
│
│ A local value named "lifecycle_configuration_rules" was already defined at s3-redacted-backup.tf:27,3-63. Local value names must be unique within a module.

Describe Ideal Solution

The above (see "Describe the Feature"), where I can define multiple locals in a file, then call them in the files where I am using the module.

Alternatives Considered

Different solution would be to fork this repo and support it, but preferably not. Another one is to use separate resources. I guess another alternative is to continue using the deprecated input lifecycle_rules, but that's far from ideal, as its configuration is longer (it expects you to explicitly define whether transition etc. is enabled or not).

Additional Context

No response

AnonymousWP commented 3 months ago

Hmmm, after all it doesn't seem to be needed. Solution is to use a custom variable, like so:

variables.tf:

variable "lifecycle_configuration_rules_redacted1" {
  type            = list(any)
  description = "Lifecycle configuration for redacted1"
}

variable "lifecycle_configuration_rules_redacted" {
  type           = list(any)
  description = "Lifecycle configuration for redacted"
}

And then within the module block use

lifecycle_configuration_rules = var.lifecycle_configuration_rules_redacted. However, VSC still complains that it's not expected there, yet it does work for some reason. Perhaps a VSC Terraform extension bug or something related to the module/provider/deps/whatever.