I am trying to refactor some terraform code when doing an upgrade.
I'm using some S3 module that takes some lifecycle configuration rules:
module "s3_bucket" {
source = "../modules/s3"
lifecycle_rule = [
{
id = "id_name"
enabled = true
abort_incomplete_multipart_upload = 7
expiration = {
days = 7
}
noncurrent_version_expiration = {
days = 7
}
}
]
}
Here is how the resource inside the model looks like:
resource "aws_s3_bucket_lifecycle_configuration" "main" {
count = length(var.lifecycle_rule) > 0 ? 1 : 0
bucket = aws_s3_bucket.main.id
dynamic "rule" {
for_each = var.lifecycle_rule
content {
id = lookup(lifecycle_rule.value, "id", null)
enabled = lookup(lifecycle_rule.value, "enabled", null)
abort_incomplete_multipart_upload = lookup(lifecycle_rule.value, "abort_incomplete_multipart_upload", null)
filter {
and {
prefix = lookup(lifecycle_rule.value, "prefix", null)
tags = lookup(lifecycle_rule.value, "tags", null)
}
}
}
}
}
Running plan gives me the following error:
on ../modules/s3/main.tf line 73, in resource "aws_s3_bucket_lifecycle_configuration" "main":
73: id = lookup(lifecycle_rule.id, null)
A managed resource "lifecycle_rule" "id" has not been declared in
module.s3_bucket.
2 questions:
1 - Looks like I'm not reaching the lifecycle_rule.value attribute in the list for the module, any help with the syntax?
2 - How to access the nested expiration.days value inside the module also?
Thanks!
CodePudding user response:
The first part of your question: you need to use the rule
and not lifecycle_rule
[1]. Make sure you understand this part:
The iterator argument (optional) sets the name of a temporary variable that represents the current element of the complex value. If omitted, the name of the variable defaults to the label of the dynamic block.
To complete the answer, accessing expiration.days
is possible if you define a corresponding argument in the module. In other words, you need to add expiration
block to the module code [2].
There are a couple more issues with the code you currently have:
- The
abort_incomplete_multipart_upload
is a configuration block, the same asexpiration
- The expiration date should not be set in number of days, rather an RFC3339 format [3]
- The
enabled
value cannot be a bool, it has to be eitherEnabled
orDisabled
(mind the first capital letter) and the name of the argument isstatus
[4] notenabled
To sum up, here's what the code in the module should look like:
resource "aws_s3_bucket_lifecycle_configuration" "main" {
count = length(var.lifecycle_rule) > 0 ? 1 : 0
bucket = aws_s3_bucket.main.id
dynamic "rule" {
for_each = var.lifecycle_rule
content {
id = lookup(rule.value, "id", null)
status = lookup(rule.value, "enabled", null)
abort_incomplete_multipart_upload {
days_after_initiation = lookup(rule.value, "abort_incomplete_multipart_upload", null)
}
filter {
and {
prefix = lookup(rule.value, "prefix", null)
tags = lookup(rule.value, "tags", null)
}
}
expiration {
date = lookup(rule.value.expiration, "days", null)
}
}
}
}
The module should be called with the following variable values:
module "s3_bucket" {
source = "../modules/s3"
lifecycle_rule = [
{
id = "id_name"
enabled = "Enabled" # Mind the value
abort_incomplete_multipart_upload = 7
expiration = {
days = "2022-08-28T15:04:05Z" # RFC3339 format
}
noncurrent_version_expiration = {
days = 7
}
}
[1] https://www.terraform.io/language/expressions/dynamic-blocks