Referencing a list of object in sub-module

I’m trying, but failing to reference a list of object in a s3 submodule where I use a dynamic transition block.

In vars.tf in the submodule

variable "transitions_list" {
  type = list(object({
    t_storage_class = string,
    t_days          = number
  }))
  default     = []
  description = "A list of transition classes and days for each transition"
}

In main.tf in the submodule

resource "aws_s3_bucket_lifecycle_configuration" "this" {
  bucket = aws_s3_bucket.this.id
  rule {
    id     = "transition_to_sc"
    status = var.transition_to_sc_enabled
    transition {
      days          = var.transition_to_sc_days
      storage_class = var.transition_to_sc
    }

    dynamic "transition" {
      for_each = var.transitions_list
        content {
          storage_class = transition.value["t_storage_class"]
          days          = transition.value["t_days"]
      }
    }

    abort_incomplete_multipart_upload {
      days_after_initiation = 7
    }
  }
  depends_on = [
    aws_s3_bucket.this,
  ]
}

In a var-file I have:

transitions_list = [
  { 
    t_storage_class = "GLACIER",
    t_days = 30 
  },
  { 
    t_storage_class = "DEEP_ARCHIVE",
    t_days = 190 
  }
]

When running plan against the submodule using -var-file I get the expected outcome, i.e. two transitions will be created:

  /* aws_s3_bucket_lifecycle_configuration.this must be replaced */
-/+ resource "aws_s3_bucket_lifecycle_configuration" "this" {
      ~ bucket = "drewtest60" -> (known after apply) # forces replacement
      ~ id     = "drewtest60" -> (known after apply)

      ~ rule {
            id     = "transition_to_sc"
            # (1 unchanged attribute hidden)

          - filter {
            }

          + transition {
              + days          = 190
              + storage_class = "DEEP_ARCHIVE"
            }
          + transition {
              + days          = 30
              + storage_class = "GLACIER"
            }

            # (2 unchanged blocks hidden)
        }
    }

Now I want to reference the dynamic transition from other terraform code. I use an s3.tf file that has:

locals {
  /* Configure buckets here. */
  buckets = {
    "drew-test-no-transitions8" = {
      billing = "test-lab"
      center  = "test"
      lab     = "test-lab"
    },
    "drew-test-one-transitions8" = {
      billing = "test-lab"
      center  = "test"
      lab     = "test-lab"

      transitions_l = [
        {
          t_storage_class = "GLACIER",
          t_days = 30
        }
      ]
    },
    "drew-test-multiple-transitions8" = {
      billing = "test-lab"
      center  = "test"
      lab     = "test-lab"

      transitions_l = [
        {
          t_storage_class = "GLACIER",
          t_days = 30
        },
        {
          t_storage_class = "DEEP_ARCHIVE",
          t_days = 180
        }
      ]
    }

  } # End buckets
}

In other terraform code s3-infra.tf I try to use a splat expression to set the transtions:

module "drew-lab-buckets" {
  source      = "../../s3-bucket/modules/s3_bucket/"
  for_each    = local.buckets
  bucket_name = each.key

  transitions_list = try(
    [
      for tran in [ each.key.transitions_l[*] ] :
        {
          storage_class = tran[*].t_storage_class,
          days = tran[*].t_days
        }
    ], []
  )

/*
This works, of course
  transitions_list = [
    for tran in transitions_l[*] :
      {
        t_storage_class = "GLACIER",
        t_days = 190
      }
  ]
*/
}

The syntax appears correct, as both plan and apply run without errors. However, the dynamic transitions are not set, the non-dynamic transition IS set, as expected…

  /* module.drew-lab-buckets["drew-test-one-transitions9"].aws_s3_bucket_lifecycle_configuration.this will be created */
  + resource "aws_s3_bucket_lifecycle_configuration" "this" {
      + bucket = (known after apply)
      + id     = (known after apply)

      + rule {
          + id     = "transition_to_sc"
          + status = "Enabled"

          + abort_incomplete_multipart_upload {
              + days_after_initiation = 7
            }

          + transition {
              + days          = 1
              + storage_class = "INTELLIGENT_TIERING"
            }
        }
    }

So I must be using [*] wrong in some way. Any ideas?
Thanks!

Your post is pretty unreadable, please refer to Welcome to the forum - please reformat your message

Done, hope that is better.

You’ve set yourself up for hard to debug problems by broad use of try():

The try() is swallowing at least one coding error in this code, and silently falling back to the [] case.

One of the errors is each.key.transitions_l - each.key is a string such as drew-test-multiple-transitions8 so trying to access .transitions_l on it fails. You want each.value.

tran[*] is also an error - that makes no sense, since tran is not a list-like thing.

transitions_l[*] is also an error - it makes no sense to use the [*] operator without further access/indexing operations after it.

This looks more reasonable:

  transitions_list = [
    for tran in try(each.value.transitions_l, []) :
      {
        storage_class = tran.t_storage_class,
        days          = tran.t_days
      }
  ]
  

@maxb you are a lifesaver!

Thanks so much.