Skip to content
Open
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
8 changes: 4 additions & 4 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"files": "go.sum|^.secrets.baseline$",
"lines": null
},
"generated_at": "2025-11-18T06:26:49Z",
"generated_at": "2025-11-20T15:49:11Z",
"plugins_used": [
{
"name": "AWSKeyDetector"
Expand Down Expand Up @@ -82,15 +82,15 @@
"hashed_secret": "ff9ee043d85595eb255c05dfe32ece02a53efbb2",
"is_secret": false,
"is_verified": false,
"line_number": 40,
"line_number": 41,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "a7c93faaa770c377154ea9d4d0d17a9056dbfa95",
"is_secret": false,
"is_verified": false,
"line_number": 193,
"line_number": 194,
"type": "Secret Keyword",
"verified_result": null
}
Expand Down Expand Up @@ -128,7 +128,7 @@
"hashed_secret": "3e4bdbe0b80e63c22b178576e906810777387b50",
"is_secret": false,
"is_verified": false,
"line_number": 272,
"line_number": 273,
"type": "Secret Keyword",
"verified_result": null
}
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ You can configure the following aspects of your instances:
* [Submodules](./modules)
* [buckets](./modules/buckets)
* [fscloud](./modules/fscloud)
* [lifecycle_rules](./modules/lifecycle_rules)
* [Examples](./examples)
* <div style="display: inline-block;"><a href="./examples/advanced">Advanced example</a></div> <div style="display: inline-block; vertical-align: middle;"><a href="https://cloud.ibm.com/schematics/workspaces/create?workspace_name=cos-advanced-example&repository=https://github.com/terraform-ibm-modules/terraform-ibm-cos/tree/main/examples/advanced" target="_blank"><img src="https://cloud.ibm.com/media/docs/images/icons/Deploy_to_cloud.svg" alt="Deploy to IBM Cloud button"></a></div>
* <div style="display: inline-block;"><a href="./examples/basic">Basic example</a></div> <div style="display: inline-block; vertical-align: middle;"><a href="https://cloud.ibm.com/schematics/workspaces/create?workspace_name=cos-basic-example&repository=https://github.com/terraform-ibm-modules/terraform-ibm-cos/tree/main/examples/basic" target="_blank"><img src="https://cloud.ibm.com/media/docs/images/icons/Deploy_to_cloud.svg" alt="Deploy to IBM Cloud button"></a></div>
Expand Down
77 changes: 77 additions & 0 deletions examples/lifecycle_rules/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
##############################################################################
# Resource Group
##############################################################################

module "resource_group" {
source = "terraform-ibm-modules/resource-group/ibm"
version = "1.4.0"
# if an existing resource group is not set (null) create a new one using prefix
resource_group_name = var.resource_group == null ? "${var.prefix}-resource-group" : null
existing_resource_group_name = var.resource_group
}

##############################################################################
# Create Cloud Object Storage instance and a bucket
##############################################################################

module "cos" {
source = "../../"
resource_group_id = module.resource_group.resource_group_id
region = var.region
cos_instance_name = "${var.prefix}-cos"
cos_tags = var.resource_tags
bucket_name = "${var.prefix}-bucket"
retention_enabled = false # disable retention for test environments - enable for stage/prod
kms_encryption_enabled = false
cos_plan = "cos-one-rate-plan"
bucket_storage_class = "onerate_active"
object_versioning_enabled = true
access_tags = var.access_tags
}


module "advance_lifecycle_rules" {
source = "../../modules/lifecycle_rules"
cos_region = var.region
bucket_crn = module.cos.bucket_crn
object_versioning_enabled = true
expiry_rules = [
{
rule_id = "expiry-info-7d"
days = 7
prefix = "info-"
},
{
rule_id = "expiry-error-30d"
days = 30
prefix = "error-"
}
]

noncurrent_expiry_rules = [
{
rule_id = "ncv-expire-45d"
noncurrent_days = 45
prefix = "data/"
},
{
rule_id = "ncv-expire-90d"
noncurrent_days = 90
prefix = "archive/"
}
]

abort_multipart_rules = [
{
rule_id = "abort-stale-7d"
days_after_initiation = 7
prefix = ""
},
{
rule_id = "abort-temp-3d"
days_after_initiation = 3
prefix = "tmp/"
}
]

}
14 changes: 14 additions & 0 deletions examples/lifecycle_rules/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
output "bucket_crn" {
value = module.advance_lifecycle_rules.bucket_crn
description = "Bucket CRN"
}

output "bucket_location" {
value = module.advance_lifecycle_rules.bucket_location
description = "Bucket location"
}

output "bucket_id" {
value = module.advance_lifecycle_rules.bucket_id
description = "Bucket ID"
}
3 changes: 3 additions & 0 deletions examples/lifecycle_rules/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
provider "ibm" {
ibmcloud_api_key = var.ibmcloud_api_key
}
33 changes: 33 additions & 0 deletions examples/lifecycle_rules/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
variable "ibmcloud_api_key" {
type = string
description = "The IBM Cloud API Token"
sensitive = true
}

variable "prefix" {
type = string
description = "Prefix name for all related resources"
}

variable "resource_tags" {
type = list(string)
description = "Optional list of tags to be added to created resources"
default = []
}

variable "access_tags" {
type = list(string)
description = "Optional list of access tags to be added to the created resources"
default = []
}

variable "region" {
description = "Region where resources will be created"
type = string
}

variable "resource_group" {
type = string
description = "An existing resource group name to use for this example, if unset a new resource group will be created"
default = null
}
12 changes: 12 additions & 0 deletions examples/lifecycle_rules/version.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
terraform {
required_version = ">= 1.9.0"

# Ensure that there is always 1 example locked into the lowest provider version of the range defined in the main
# module's version.tf (this example), and 1 example that will always use the latest provider version (advanced and fscloud examples).
required_providers {
ibm = {
source = "ibm-cloud/ibm"
version = "1.79.2"
}
}
}
97 changes: 97 additions & 0 deletions modules/lifecycle_rules/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Cloud Object Storage lifecycle_rules module

You can use this submodule to configure multiple lifecycle rules to existing IBM [Cloud Object Storage](https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-getting-started-cloud-object-storage) buckets.

You can configure the following multiple rules to your buckets:
- [expiration](https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-expiry)
- [noncurrent version expiration](https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-expiry#noncurrentversionexpiration)
- [abort incomplete multipart](https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-lifecycle-cleanup-mpu)

### Usage
```hcl
module "advance_lifecycle_rules" {
source = "terraform-ibm-modules/cos/ibm//modules/lifecycle_rules"
cos_region = "region of the existing bucket"
bucket_crn = "crn:v1:bluemix:public:cloud-object-storage:global:a/xxXXxxXXxXxXXXXxxXxxxXXXXxXXXXX:bucket:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx" # existing bucket crn
object_versioning_enabled = false # False by default , must be set to true for noncurrent version expiration lifecycle rule
expiry_rules = [
{
rule_id = "expiry-info-7d"
days = 7
prefix = "info-"
},
{
rule_id = "expiry-error-30d"
days = 30
prefix = "error-"
}
]

noncurrent_expiry_rules = [
{
rule_id = "ncv-expire-45d"
noncurrent_days = 45
prefix = "data/"
},
{
rule_id = "ncv-expire-90d"
noncurrent_days = 90
prefix = "archive/"
}
]

abort_multipart_rules = [
{
rule_id = "abort-stale-7d"
days_after_initiation = 7
prefix = ""
},
{
rule_id = "abort-temp-3d"
days_after_initiation = 3
prefix = "tmp/"
}
]

}
```


<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
### Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.9.0 |
| <a name="requirement_ibm"></a> [ibm](#requirement\_ibm) | >= 1.79.2, < 2.0.0 |

### Modules

No modules.

### Resources

| Name | Type |
|------|------|
| [ibm_cos_bucket_lifecycle_configuration.advance_bucket_lifecycle](https://registry.terraform.io/providers/ibm-cloud/ibm/latest/docs/resources/cos_bucket_lifecycle_configuration) | resource |

### Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_abort_multipart_rules"></a> [abort\_multipart\_rules](#input\_abort\_multipart\_rules) | List of abort incomplete multipart upload rules | <pre>list(object({<br/> rule_id = optional(string)<br/> status = optional(string, "enable")<br/> days_after_initiation = number<br/> prefix = optional(string, "")<br/> }))</pre> | `[]` | no |
| <a name="input_bucket_crn"></a> [bucket\_crn](#input\_bucket\_crn) | The CRN of an existing Cloud Object Storage bucket. | `string` | n/a | yes |
| <a name="input_cos_region"></a> [cos\_region](#input\_cos\_region) | The region of existing Cloud Object Storage bucket. | `string` | n/a | yes |
| <a name="input_expiry_rules"></a> [expiry\_rules](#input\_expiry\_rules) | List of expiry rules | <pre>list(object({<br/> rule_id = optional(string)<br/> status = optional(string, "enable")<br/> days = number<br/> prefix = optional(string, "")<br/> }))</pre> | `[]` | no |
| <a name="input_management_endpoint_type_for_bucket"></a> [management\_endpoint\_type\_for\_bucket](#input\_management\_endpoint\_type\_for\_bucket) | The type of endpoint for the IBM terraform provider to manage the bucket. Possible values are `public`, `private`, or `direct`. | `string` | `"public"` | no |
| <a name="input_noncurrent_expiry_rules"></a> [noncurrent\_expiry\_rules](#input\_noncurrent\_expiry\_rules) | List of noncurrent version expiration rules | <pre>list(object({<br/> rule_id = optional(string)<br/> status = optional(string, "enable")<br/> noncurrent_days = number<br/> prefix = optional(string, "")<br/> }))</pre> | `[]` | no |
| <a name="input_object_versioning_enabled"></a> [object\_versioning\_enabled](#input\_object\_versioning\_enabled) | Whether to enable object versioning to keep multiple versions of an object in a bucket. | `bool` | `false` | no |

### Outputs

| Name | Description |
|------|-------------|
| <a name="output_bucket_crn"></a> [bucket\_crn](#output\_bucket\_crn) | Bucket CRN |
| <a name="output_bucket_id"></a> [bucket\_id](#output\_bucket\_id) | Bucket ID |
| <a name="output_bucket_location"></a> [bucket\_location](#output\_bucket\_location) | Bucket location |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
74 changes: 74 additions & 0 deletions modules/lifecycle_rules/main.tf
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we not adding archive rule as well?

Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
locals {
# Assign deterministic rule IDs if not provided
expiry_rules = [
for idx, r in var.expiry_rules : merge(r, {
rule_id = coalesce(try(r.rule_id, null), "expiry-rule-${idx}")
})
]

noncurrent_expiry_rules = [
for idx, r in var.noncurrent_expiry_rules : merge(r, {
rule_id = coalesce(try(r.rule_id, null), "noncurrent-expiry-rule-${idx}")
})
]

abort_multipart_rules = [
for idx, r in var.abort_multipart_rules : merge(r, {
rule_id = coalesce(try(r.rule_id, null), "abort-multipart-rule-${idx}")
})
]
}


resource "ibm_cos_bucket_lifecycle_configuration" "advance_bucket_lifecycle" {
bucket_crn = var.bucket_crn
bucket_location = var.cos_region
endpoint_type = var.management_endpoint_type_for_bucket

# Expiration rules
dynamic "lifecycle_rule" {
for_each = local.expiry_rules
content {
expiration {
days = lifecycle_rule.value.days
}
filter {
prefix = lifecycle_rule.value.prefix
}
rule_id = lifecycle_rule.value.rule_id
status = lifecycle_rule.value.status
}
}


# Noncurrent version expiration rules
dynamic "lifecycle_rule" {
for_each = local.noncurrent_expiry_rules
content {
noncurrent_version_expiration {
noncurrent_days = lifecycle_rule.value.noncurrent_days
}
filter {
prefix = lifecycle_rule.value.prefix
}
rule_id = lifecycle_rule.value.rule_id
status = lifecycle_rule.value.status
}
}

# Abort multipart rules
dynamic "lifecycle_rule" {
for_each = local.abort_multipart_rules
content {
abort_incomplete_multipart_upload {
days_after_initiation = lifecycle_rule.value.days_after_initiation
}
filter {
prefix = lifecycle_rule.value.prefix
}
rule_id = lifecycle_rule.value.rule_id
status = lifecycle_rule.value.status
}
}

}
14 changes: 14 additions & 0 deletions modules/lifecycle_rules/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
output "bucket_crn" {
value = ibm_cos_bucket_lifecycle_configuration.advance_bucket_lifecycle.bucket_crn
description = "Bucket CRN"
}

output "bucket_location" {
value = ibm_cos_bucket_lifecycle_configuration.advance_bucket_lifecycle.bucket_location
description = "Bucket location"
}

output "bucket_id" {
value = ibm_cos_bucket_lifecycle_configuration.advance_bucket_lifecycle.id
description = "Bucket ID"
}
Loading