Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ repos:
rev: v1.96.1
hooks:
- id: terraform_fmt
args:
- --args=-recursive
- id: terraform_wrapper_module_for_each
- id: terraform_docs
args:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ No modules.
| <a name="input_inventory_self_source_destination"></a> [inventory\_self\_source\_destination](#input\_inventory\_self\_source\_destination) | Whether or not the inventory source bucket is also the destination bucket. | `bool` | `false` | no |
| <a name="input_inventory_source_account_id"></a> [inventory\_source\_account\_id](#input\_inventory\_source\_account\_id) | The inventory source account id. | `string` | `null` | no |
| <a name="input_inventory_source_bucket_arn"></a> [inventory\_source\_bucket\_arn](#input\_inventory\_source\_bucket\_arn) | The inventory source bucket ARN. | `string` | `null` | no |
| <a name="input_lifecycle_rule"></a> [lifecycle\_rule](#input\_lifecycle\_rule) | List of maps containing configuration of object lifecycle management. | `any` | `[]` | no |
| <a name="input_lifecycle_rule"></a> [lifecycle\_rule](#input\_lifecycle\_rule) | List of maps containing configuration of object lifecycle management. Each lifecycle rule must contain 'id' and either 'enabled' or 'status', and may contain: 'filter', 'abort\_incomplete\_multipart\_upload\_days', 'expiration', 'transition', 'noncurrent\_version\_expiration', or 'noncurrent\_version\_transition'. | `any` | `[]` | no |
| <a name="input_logging"></a> [logging](#input\_logging) | Map containing access bucket logging configuration. | `any` | `{}` | no |
| <a name="input_metric_configuration"></a> [metric\_configuration](#input\_metric\_configuration) | Map containing bucket metric configuration. | `any` | `[]` | no |
| <a name="input_object_lock_configuration"></a> [object\_lock\_configuration](#input\_object\_lock\_configuration) | Map containing S3 object locking configuration. | `any` | `{}` | no |
Expand Down
151 changes: 151 additions & 0 deletions tests/test_lifecycle_rules.tftest.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# Default AWS provider configuration
mock_provider "aws" {
}

# Default required test variables
variables {
bucket_name = "test-bucket"
kms_key_arn = "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
readonly_iam_role_arns = []
readwrite_iam_role_arns = []
backup_enabled = false
}

# Test 1
run "verify_valid_lifecycle_rules" {
command = plan

variables {
lifecycle_rules = [
{
id = "log"
enabled = true
filter = {
tags = {
some = "value"
another = "value2"
}
}
transition = [
{
days = 30
storage_class = "ONEZONE_IA"
},
{
days = 60
storage_class = "GLACIER"
}
]
},
{
id = "log1"
enabled = true
abort_incomplete_multipart_upload_days = 7
noncurrent_version_transition = [
{
days = 30
storage_class = "STANDARD_IA"
}
]
noncurrent_version_expiration = {
days = 300
}
},
{
id = "expire_all_objects"
status = "Enabled"
expiration = {
days = 7
}
noncurrent_version_expiration = {
noncurrent_days = 3
}
abort_incomplete_multipart_upload_days = 1
}
]
}

assert {
condition = length(var.lifecycle_rules) == 3
error_message = "Expected 3 lifecycle rules"
}

assert {
condition = alltrue([
for rule in var.lifecycle_rules : contains(keys(rule), "id")
])
error_message = "All rules must have an id"
}

assert {
condition = alltrue([
for rule in var.lifecycle_rules :
anytrue([contains(keys(rule), "enabled"), contains(keys(rule), "status")])
])
error_message = "All rules must have either enabled or status field"
}

assert {
condition = alltrue([
for rule in var.lifecycle_rules :
anytrue([
!contains(keys(rule), "abort_incomplete_multipart_upload_days"),
can(tonumber(rule.abort_incomplete_multipart_upload_days))
])
])
error_message = "abort_incomplete_multipart_upload_days must be a number"
}
}

# Test 2
run "fail_invalid_lifecycle_rules" {
command = plan

variables {
lifecycle_rules = [
{
id = "log1"
enabled = true
abort_incomplete_multipart_upload = {
days_after_initiation = "1"
}
noncurrent_version_transition = [
{
days = 30
storage_class = "STANDARD_IA"
}
]
noncurrent_version_expiration = {
days = 300
}
}
]
}

expect_failures = [
var.lifecycle_rules
]

assert {
condition = !alltrue([
for rule in var.lifecycle_rules : (
contains(keys(rule), "id") &&
(contains(keys(rule), "enabled") || contains(keys(rule), "status")) &&
alltrue([
for key in keys(rule) : contains([
"id",
"enabled",
"status",
"filter",
"abort_incomplete_multipart_upload_days",
"expiration",
"transition",
"noncurrent_version_expiration",
"noncurrent_version_transition"
], key)
])
)
])
error_message = "Each lifecycle rule must contain 'id' and either 'enabled' or 'status', and may contain: 'filter', 'abort_incomplete_multipart_upload_days', 'expiration', 'transition', 'noncurrent_version_expiration', or 'noncurrent_version_transition'."
}
}
25 changes: 24 additions & 1 deletion variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,32 @@ variable "transition_default_minimum_object_size" {
}

variable "lifecycle_rule" {
description = "List of maps containing configuration of object lifecycle management."
description = "List of maps containing configuration of object lifecycle management. Each lifecycle rule must contain 'id' and either 'enabled' or 'status', and may contain: 'filter', 'abort_incomplete_multipart_upload_days', 'expiration', 'transition', 'noncurrent_version_expiration', or 'noncurrent_version_transition'."
type = any
default = []

validation {
condition = alltrue([
for rule in var.lifecycle_rule : (
contains(keys(rule), "id") &&
(contains(keys(rule), "enabled") || contains(keys(rule), "status")) &&
alltrue([
for key in keys(rule) : contains([
"id",
"enabled",
"status",
"filter",
"abort_incomplete_multipart_upload_days",
"expiration",
"transition",
"noncurrent_version_expiration",
"noncurrent_version_transition"
], key)
])
)
])
error_message = "Each lifecycle rule must contain 'id' and either 'enabled' or 'status', and may contain: 'filter', 'abort_incomplete_multipart_upload_days', 'expiration', 'transition', 'noncurrent_version_expiration', or 'noncurrent_version_transition'."
}
}

variable "replication_configuration" {
Expand Down
Loading