Terraform: S3 bucket with lifecycle rule will return as list and not as a map

Created on 21 Mar 2018  ยท  7Comments  ยท  Source: hashicorp/terraform

Hi there,

I am having an issue modifying an s3 bucket with a lifecycle_rule

Terraform Version

terraform -v
Terraform v0.11.5

Terraform Configuration Files

The config below is directly from the terraform docs, I have been testing with various values etc.

# Vars

variable "lifecycle_rule" {
  description = "lifecycle"
  type = "map"
  default = {}
}

# s3 module

  lifecycle_rule {
    id      = "log"
    enabled = true

    prefix  = "log/"
    tags {
      "rule"      = "log"
      "autoclean" = "true"
    }

    transition {
      days          = 30
      storage_class = "STANDARD_IA"
    }

    transition {
      days          = 60
      storage_class = "GLACIER"
    }

    expiration {
      days = 90
    }
  }

Expected Behavior

The bucket to be modified with a lifecycle rule

Actual Behavior

lifecycle_rule: should be a list

Steps to Reproduce

  1. terraform init
  2. terraform plan/apply
waiting-response

Most helpful comment

We are using this approach in several other areas, its really quite useful!

Would definitely love to know if this is going to cause us some stress in the future
Being able to pass complex data structures like this around allow our modules to be much more expressive without worrying about the minutiae of the platform too much

All 7 comments

Hi @Boojs,

I assume from the snippet that you're trying to put the lifecycle rule block into a map variable?

The lifecycle_rule attribute on an aws_s3_bucket is a list of schema resources. Complex types like this cannot be assigned to a variable.

Hi @jbardin

Thanks for getting back to me. I have in the end figured out what I was doing wrong with the help of a colleague.

For reference for anyone else:

lifecycle_rule = [
    {
      enabled = true
      id = "retire exports after 7 days"
      prefix = "surveys/export"

      noncurrent_version_expiration = [
        {
          days = 7
        },
      ]

      expiration = [
        {
          days = 7
        },
      ]
    },
  ]

Module here:

lifecycle_rule = "${var.lifecycle_rule}"

variable "lifecycle_rule" {
  description = "lifecycle"
  default = []
}

Hi @Boojs,

Just to let you know, that is not valid configuration. It works due to some coincidence in the configuration handler, but will break in various situations with modules.

Hey @jbardin

Would you possibly be able to elaborate a bit on why/when it would break?

Just to give you a quick break down what we are doing.

  1. We write out our individual modules, in this case S3 and define each attribute to a variable
  2. Once we are happy with our module, then we build out our spec and pull that module to build it

We are using this approach in several other areas, its really quite useful!

Would definitely love to know if this is going to cause us some stress in the future
Being able to pass complex data structures like this around allow our modules to be much more expressive without worrying about the minutiae of the platform too much

Sorry, I don't have much for specific failure modes, but I have seen this attempted before, and currently it can result in perpetual diffs or mysterious type errors when changing values in the nested structures.

In reality, it's not something that was meant to work, and won't work in future versions of terraform. We are however working on tooling to help fix up configurations like this when we reach that point.

Since we know the root cause here, and you have a workaround for the time being, I'm going to close this out, but feel free to reply here if you have any more questions!

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.

Was this page helpful?
0 / 5 - 0 ratings