How to add lifecycle rules to an S3 bucket using terraform?
Lets first break down whats happening and how we can overcome this issue. Each time you define a resource "aws_s3_bucket"
, terraform will attempt to create a bucket with the parameters specified. If you want to attach a lifecycle policy to a bucket, do it where you define the bucket, e.g.:
resource "aws_s3_bucket" "quarterly" {
bucket = "quarterly_bucket_name"
#bucket = "${var.bucket_id}"
acl = "private"
lifecycle_rule {
id = "quarterly_retention"
prefix = "folder/"
enabled = true
expiration {
days = 92
}
}
}
resource "aws_s3_bucket" "permanent" {
bucket = "perm_bucket_name"
acl = "private"
lifecycle_rule {
id = "permanent_retention"
enabled = true
prefix = "permanent/"
transition {
days = 1
storage_class = "GLACIER"
}
}
}
A bucket can have multiple lifecycle_rule
blocks on it.
If you want to define the lifecycle rules as external blocks, you can do it in this way:
// example of what the variable would look like:
variable "lifecycle_rules" {
type = "list"
default = []
}
// example of what the assignment would look like:
lifecycle_rules = [{
id = "cleanup"
prefix = ""
enabled = true
expiration = [{
days = 1
}]
}, {...}, {...} etc...]
// example what the usage would look like
resource "aws_s3_bucket" "quarterly" {
bucket = "quarterly_bucket_name"
#bucket = "${var.bucket_id}"
acl = "private"
source = "/dev/null"
lifecycle_rule = [ "${var.lifecycle_rules}" ]
}
Note: the implementation above of having an external lifecycle policy isn't really the best way to do it, but the only way. You pretty much trick terraform into accepting the list of maps, which happens to be the same type as lifecycle_rule, so it works. Ideally, Terraform should have it's own resource
block for lifecycle rules, but it doesn't.
Edit: why have separate resource blocks when we now have dynamic blocks! Woohoo
Related videos on Youtube
prowla
Updated on June 04, 2022Comments
-
prowla almost 2 years
I am using Terraform to create a bucket in S3 and I want to add "folders" and lifecycle rules to it.
I can create the bucket (using an "aws_s3_bucket" resource).
I can create the bucket and define my lifecycle rules within the same "aws_s3_bucket" resource, ie. at creation time.
I can add "folders" to the bucket (I know they aren't really folders, but they are presented to the client systems as if they were... :-) ), using an "aws_s3_bucket_object" resource, ie. after bucket creation.
All good...
But I want to be able to add lifecycle rules AFTER I've created the bucket, but I get an error telling me the bucket already exists. (Actually I want to be able to subsequently add folders and corresponding lifecycle rules as and when required.)
Now, I can add lifecycle rules to an existing bucket in the AWS GUI, so I know it is a reasonable thing to want to do.
But is there a way of doing it with Terraform?
Am I missing something?
resource "aws_s3_bucket" "bucket" { bucket = "${replace(var.tags["Name"],"/_/","-")}" region = "${var.aws_region}" #tags = "${merge(var.tags, map("Name", "${var.tags["Name"]}"))}" tags = "${merge(var.tags, map("Name", "${replace(var.tags["Name"],"/_/","-")}"))}" } resource "aws_s3_bucket" "bucket_quarterly" { bucket = "${aws_s3_bucket.bucket.id}" #region = "${var.aws_region}" lifecycle_rule { id = "quarterly_retention" prefix = "quarterly/" enabled = true expiration { days = 92 } } } resource "aws_s3_bucket" "bucket_permanent" { bucket = "${aws_s3_bucket.bucket.id}" #region = "${var.aws_region}" lifecycle_rule { id = "permanent_retention" enabled = true prefix = "permanent/" transition { days = 1 storage_class = "GLACIER" } } } resource "aws_s3_bucket_object" "quarterly" { bucket = "${aws_s3_bucket.bucket.id}" #bucket = "${var.bucket_id}" acl = "private" key = "quarterly" source = "/dev/null" } resource "aws_s3_bucket_object" "permanent" { bucket = "${aws_s3_bucket.bucket.id}" #bucket = "${var.bucket_id}" acl = "private" key = "permanent" source = "/dev/null" }
I expect to have a bucket with 2 lifecycle rules, but I get the following error:
Error: Error applying plan:
2 error(s) occurred: * module.s3.aws_s3_bucket.bucket_quarterly: 1 error(s) occurred: * aws_s3_bucket.bucket_quarterly: Error creating S3 bucket: BucketAlreadyOwnedByYou: Your previous request to create the named bucket succeeded and you already own it. status code: 409, request id: EFE9C62B25341478, host id: hcsCNracNrpTJZ4QdU0AV2wNm/FqhYSEY4KieQ+zSHNsj6AUR69XvPF+0BiW4ZOpfgIoqwFoXkI= * module.s3.aws_s3_bucket.bucket_permanent: 1 error(s) occurred: * aws_s3_bucket.bucket_permanent: Error creating S3 bucket: BucketAlreadyOwnedByYou: Your previous request to create the named bucket succeeded and you already own it. status code: 409, request id: 7DE1B1A36138A614, host id: 8jB6l7d6Hc6CZFgQSLQRMJg4wtvnrSL6Yp5R4RScq+GtuMW+6rkN39bcTUwQhzxeI7jRStgLXSc= Terraform does not automatically rollback in the face of errors. Instead, your Terraform state file has been partially updated with any resources that successfully completed. Please address the error above and apply again to incrementally change your infrastructure.
-
char about 5 yearsLooks like a recurring bug (see github here and here).
-
-
Mendhak almost 4 years> Blocks of type "lifecycle_rule" are not expected here. There doesn't seem to be a
lifecycle_rule
foraws_s3_bucket_object
-
Moe almost 4 yearsThank you for pointing that out. I've updated the resource names to be correct now.
-
Serhii Popov over 3 years@Moe, What do you mean with
dynamic blocks
? -
Moe over 3 yearsgoogle "dynamic blocks terraform" and the first result explains it in detail: github.com/hashicorp/terraform-guides/tree/master/…