Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
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