diff --git a/README.md b/README.md index bff6b27..3ddf3fa 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ A [Terraform](https://www.terraform.io) module to create a [Google Cloud Storage](https://cloud.google.com/storage) on [Google Cloud Services (GCP)](https://cloud.google.com/). **_This module supports Terraform version 1 -and is compatible with the Terraform Google Provider version 4._** and 5._** +and is compatible with the Terraform Google Provider version >= 5.10 This module is part of our Infrastructure as Code (IaC) framework that enables our users and customers to easily deploy and manage reusable, @@ -104,9 +104,12 @@ See [variables.tf] and [examples/] for details and use-cases. } condition = { age = 60 + no_age = false created_before = "2018-08-20" with_state = "LIVE" matches_storage_class = ["REGIONAL"] + matches_prefix = ["bucket"] + matches_suffix = [] num_newer_versions = 10 custom_time_before = "1970-01-01" days_since_custom_time = 1 @@ -142,6 +145,10 @@ See [variables.tf] and [examples/] for details and use-cases. Minimum age of an object in days to satisfy this condition. + - [**`no_age`**](#attr-lifecycle_rules-condition-no_age): *(Optional `bool`)* + + While set true, age value will be omitted. Required to set true when age is unset in the config file. + - [**`created_before`**](#attr-lifecycle_rules-condition-created_before): *(Optional `string`)* A date in the RFC 3339 format YYYY-MM-DD. This condition is satisfied when an object is created before midnight of the specified date in UTC. @@ -154,6 +161,14 @@ See [variables.tf] and [examples/] for details and use-cases. Storage Class of objects to satisfy this condition. Supported values include: `STANDARD`, `MULTI_REGIONAL`, `REGIONAL`, `NEARLINE`, `COLDLINE`, `ARCHIVE`, `DURABLE_REDUCED_AVAILABILITY`. + - [**`matches_prefix`**](#attr-lifecycle_rules-condition-matches_prefix): *(Optional `string`)* + + One or more matching name prefixes to satisfy this condition. + + - [**`matches_suffix`**](#attr-lifecycle_rules-condition-matches_suffix): *(Optional `string`)* + + One or more matching name suffixes to satisfy this condition. + - [**`num_newer_versions`**](#attr-lifecycle_rules-condition-num_newer_versions): *(Optional `number`)* Relevant only for versioned objects. The number of newer versions of an object to satisfy this condition. @@ -203,6 +218,33 @@ See [variables.tf] and [examples/] for details and use-cases. The custom object to return when a requested resource is not found. +- [**`autoclass`**](#var-autoclass): *(Optional `object(website)`)* + + The bucket's Autoclass configuration. + + Example: + + ```hcl + autoclass = { + enabled = true + terminal_storage_class = "NEARLINE" + } + ``` + + The `website` object accepts the following attributes: + + - [**`enabled`**](#attr-autoclass-enabled): *(**Required** `string`)* + + While set to true, autoclass automatically transitions + objects in your bucket to appropriate storage classes + based on each object's access pattern. + + - [**`terminal_storage_class`**](#attr-autoclass-terminal_storage_class): *(Optional `string`)* + + The storage class that objects in the bucket eventually + transition to if they are not read for a certain length of time. + Supported values include: NEARLINE, ARCHIVE. + - [**`cors`**](#var-cors): *(Optional `list(cors)`)* The bucket's Cross-Origin Resource Sharing (CORS) configuration. @@ -240,6 +282,16 @@ See [variables.tf] and [examples/] for details and use-cases. The id of a Cloud KMS key that will be used to encrypt objects inserted into this bucket, if no encryption method is specified. You must pay attention to whether the crypto key is available in the location that this bucket is created in. +- [**`custom_placement_config`**](#var-custom_placement_config): *(Optional `object(custom_placement_config)`)* + + The bucket's custom location configuration, which specifies the individual regions that comprise a dual-region bucket. If the bucket is designated a single or multi-region, the parameters are empty. + + The `custom_placement_config` object accepts the following attributes: + + - [**`data_locations`**](#attr-custom_placement_config-data_locations): *(**Required** `list(string)`)* + + The list of individual regions that comprise a dual-region bucket. If any of the data_locations changes, it will recreate the bucket. + - [**`logging`**](#var-logging): *(Optional `object(logging)`)* The bucket's Access & Storage Logs configuration. @@ -304,6 +356,37 @@ See [variables.tf] and [examples/] for details and use-cases. Default is `true`. +- [**`default_event_based_hold`**](#var-default_event_based_hold): *(Optional `bool`)* + + Whether or not to automatically apply an eventBasedHold to new objects added to the bucket. + + Default is `false`. + +- [**`enable_object_retention`**](#var-enable_object_retention): *(Optional `bool`)* + + Enables object retention on a storage bucket. + + Default is `false`. + +- [**`public_access_prevention`**](#var-public_access_prevention): *(Optional `string`)* + + Prevents public access to a bucket. Acceptable values are "inherited" or "enforced". + If "inherited", the bucket uses public access prevention. only if the bucket is subject + to the public access prevention organization policy constraint. Defaults to "inherited". + + Default is `"inherited"`. + +- [**`rpo`**](#var-rpo): *(Optional `string`)* + + The recovery point objective for cross-region replication of the bucket. + Applicable only for dual and multi-region buckets. + "DEFAULT" sets default replication. + "ASYNC_TURBO" value enables turbo replication, valid for dual-region buckets only. + If rpo is not specified at bucket creation, it defaults to "DEFAULT" for dual and multi-region buckets. + NOTE If used with single-region bucket, It will throw an error. + + Default is `null`. + - [**`object_creators`**](#var-object_creators): *(Optional `set(string)`)* A set of identities that will be able to create objects inside the bucket. diff --git a/README.tfdoc.hcl b/README.tfdoc.hcl index 5bbed29..857fc0f 100644 --- a/README.tfdoc.hcl +++ b/README.tfdoc.hcl @@ -40,7 +40,7 @@ section { A [Terraform](https://www.terraform.io) module to create a [Google Cloud Storage](https://cloud.google.com/storage) on [Google Cloud Services (GCP)](https://cloud.google.com/). **_This module supports Terraform version 1 - and is compatible with the Terraform Google Provider version 4._** and 5._** + and is compatible with the Terraform Google Provider version >= 5.10 This module is part of our Infrastructure as Code (IaC) framework that enables our users and customers to easily deploy and manage reusable, @@ -136,9 +136,12 @@ section { } condition = { age = 60 + no_age = false created_before = "2018-08-20" with_state = "LIVE" matches_storage_class = ["REGIONAL"] + matches_prefix = ["bucket"] + matches_suffix = [] num_newer_versions = 10 custom_time_before = "1970-01-01" days_since_custom_time = 1 @@ -184,6 +187,13 @@ section { END } + attribute "no_age" { + type = bool + description = <<-END + While set true, age value will be omitted. Required to set true when age is unset in the config file. + END + } + attribute "created_before" { type = string description = <<-END @@ -205,6 +215,20 @@ section { END } + attribute "matches_prefix" { + type = string + description = <<-END + One or more matching name prefixes to satisfy this condition. + END + } + + attribute "matches_suffix" { + type = string + description = <<-END + One or more matching name suffixes to satisfy this condition. + END + } + attribute "num_newer_versions" { type = number description = <<-END @@ -277,6 +301,38 @@ section { } } + variable "autoclass" { + type = object(website) + description = <<-END + The bucket's Autoclass configuration. + END + readme_example = <<-END + autoclass = { + enabled = true + terminal_storage_class = "NEARLINE" + } + END + + attribute "enabled" { + required = true + type = string + description = <<-END + While set to true, autoclass automatically transitions + objects in your bucket to appropriate storage classes + based on each object's access pattern. + END + } + + attribute "terminal_storage_class" { + type = string + description = <<-END + The storage class that objects in the bucket eventually + transition to if they are not read for a certain length of time. + Supported values include: NEARLINE, ARCHIVE. + END + } + } + variable "cors" { type = list(cors) description = <<-END @@ -327,6 +383,21 @@ section { END } + variable "custom_placement_config" { + type = object(custom_placement_config) + description = <<-END + The bucket's custom location configuration, which specifies the individual regions that comprise a dual-region bucket. If the bucket is designated a single or multi-region, the parameters are empty. + END + + attribute "data_locations" { + required = true + type = list(string) + description = <<-END + The list of individual regions that comprise a dual-region bucket. If any of the data_locations changes, it will recreate the bucket. + END + } + } + variable "logging" { type = object(logging) description = <<-END @@ -407,6 +478,45 @@ section { END } + variable "default_event_based_hold" { + type = bool + default = false + description = <<-END + Whether or not to automatically apply an eventBasedHold to new objects added to the bucket. + END + } + + variable "enable_object_retention" { + type = bool + default = false + description = <<-END + Enables object retention on a storage bucket. + END + } + + variable "public_access_prevention" { + type = string + default = "inherited" + description = <<-END + Prevents public access to a bucket. Acceptable values are "inherited" or "enforced". + If "inherited", the bucket uses public access prevention. only if the bucket is subject + to the public access prevention organization policy constraint. Defaults to "inherited". + END + } + + variable "rpo" { + type = string + default = null + description = <<-END + The recovery point objective for cross-region replication of the bucket. + Applicable only for dual and multi-region buckets. + "DEFAULT" sets default replication. + "ASYNC_TURBO" value enables turbo replication, valid for dual-region buckets only. + If rpo is not specified at bucket creation, it defaults to "DEFAULT" for dual and multi-region buckets. + NOTE If used with single-region bucket, It will throw an error. + END + } + variable "object_creators" { type = set(string) default = [] diff --git a/main.tf b/main.tf index d346634..1c1ca23 100644 --- a/main.tf +++ b/main.tf @@ -11,6 +11,10 @@ resource "google_storage_bucket" "bucket" { labels = var.labels requester_pays = var.requester_pays uniform_bucket_level_access = var.uniform_bucket_level_access + default_event_based_hold = var.default_event_based_hold + enable_object_retention = var.enable_object_retention + public_access_prevention = try(var.public_access_prevention, "inherited") + rpo = var.rpo dynamic "lifecycle_rule" { for_each = var.lifecycle_rules @@ -22,9 +26,12 @@ resource "google_storage_bucket" "bucket" { } condition { age = try(lifecycle_rule.value.condition.age, null) + no_age = try(lifecycle_rule.value.condition.no_age, null) created_before = try(lifecycle_rule.value.condition.created_before, null) with_state = try(lifecycle_rule.value.condition.with_state, null) matches_storage_class = try(lifecycle_rule.value.condition.matches_storage_class, null) + matches_prefix = try(lifecycle_rule.value.condition.matches_prefix, null) + matches_suffix = try(lifecycle_rule.value.condition.matches_suffix, null) num_newer_versions = try(lifecycle_rule.value.condition.num_newer_versions, null) custom_time_before = try(lifecycle_rule.value.condition.custom_time_before, null) days_since_custom_time = try(lifecycle_rule.value.condition.days_since_custom_time, null) @@ -42,6 +49,15 @@ resource "google_storage_bucket" "bucket" { } } + dynamic "autoclass" { + for_each = var.autoclass != null ? ["autoclass"] : [] + + content { + enabled = var.autoclass.enabled + terminal_storage_class = var.autoclass.terminal_storage_class + } + } + dynamic "website" { for_each = var.website != null ? ["website"] : [] @@ -87,6 +103,14 @@ resource "google_storage_bucket" "bucket" { default_kms_key_name = var.encryption_default_kms_key_name } } + + dynamic "custom_placement_config" { + for_each = var.custom_placement_config != null ? ["custom_placement_config"] : [] + + content { + data_locations = var.custom_placement_config.data_locations + } + } } resource "google_storage_bucket_iam_member" "viewer" { diff --git a/test/unit-complete/_generated_google.tf b/test/unit-complete/_generated_google.tf index afb5c2b..94de2d2 100644 --- a/test/unit-complete/_generated_google.tf +++ b/test/unit-complete/_generated_google.tf @@ -24,11 +24,11 @@ terraform { required_providers { google = { source = "hashicorp/google" - version = ">= 4.0, <6" + version = ">= 5.10, <6" } google-beta = { source = "hashicorp/google-beta" - version = ">= 4.0, <6" + version = ">= 5.10, <6" } random = { source = "hashicorp/random" diff --git a/test/unit-complete/main.tf b/test/unit-complete/main.tf index b23f4fc..fe96ed1 100644 --- a/test/unit-complete/main.tf +++ b/test/unit-complete/main.tf @@ -1,5 +1,5 @@ module "test-sa" { - source = "github.com/mineiros-io/terraform-google-service-account?ref=v0.0.12" + source = "github.com/mineiros-io/terraform-google-service-account?ref=v0.2.1" account_id = "service-account-id-${local.random_suffix}" } @@ -114,7 +114,10 @@ module "test1" { location = "EU" project = local.project_id storage_class = "NEARLINE" + public_access_prevention = "enforced" uniform_bucket_level_access = true + enable_object_retention = true + default_event_based_hold = true requester_pays = true object_creators = ["user:member@example.com"] object_viewers = ["user:member@example.com"] @@ -129,9 +132,12 @@ module "test1" { } condition = { age = 60 + no_age = false created_before = "2021-08-20" with_state = "LIVE" matches_storage_class = ["STANDARD"] + matches_prefix = ["pre", "bucket"] + matches_suffix = ["suff"] num_newer_versions = 10 custom_time_before = "1970-01-01" days_since_custom_time = 1 @@ -165,6 +171,11 @@ module "test1" { retention_period = 200000 } + autoclass = { + enabled = true + terminal_storage_class = "ARCHIVE" + } + labels = { label0 = "foo" label1 = "bar" @@ -216,3 +227,16 @@ module "testPolicy" { } ] } + +module "testDualRegionBucket" { + source = "../.." + + name = "unit-complete-policy" + + force_destroy = true + + rpo = "ASYNC_TURBO" + custom_placement_config = { + data_locations = ["EUROPE-WEST1", "EUROPE-WEST3"] + } +} diff --git a/test/unit-disabled/_generated_google.tf b/test/unit-disabled/_generated_google.tf index baff3fe..bde9c35 100644 --- a/test/unit-disabled/_generated_google.tf +++ b/test/unit-disabled/_generated_google.tf @@ -24,11 +24,11 @@ terraform { required_providers { google = { source = "hashicorp/google" - version = ">= 4.0, <6" + version = ">= 5.10, <6" } google-beta = { source = "hashicorp/google-beta" - version = ">= 4.0, <6" + version = ">= 5.10, <6" } random = { source = "hashicorp/random" diff --git a/test/unit-minimal/_generated_google.tf b/test/unit-minimal/_generated_google.tf index 48fb18a..f3658b6 100644 --- a/test/unit-minimal/_generated_google.tf +++ b/test/unit-minimal/_generated_google.tf @@ -24,11 +24,11 @@ terraform { required_providers { google = { source = "hashicorp/google" - version = "4.0" + version = "5.10" } google-beta = { source = "hashicorp/google-beta" - version = "4.0" + version = "5.10" } random = { source = "hashicorp/random" diff --git a/variables.tf b/variables.tf index 7f45795..bc46e3d 100644 --- a/variables.tf +++ b/variables.tf @@ -54,12 +54,48 @@ variable "versioning_enabled" { default = false } +variable "rpo" { + description = "(Optional) The recovery point objective for cross-region replication of the bucket. Applicable only for dual and multi-region buckets." + type = string + default = null +} + +variable "default_event_based_hold" { + description = "(Optional) Whether or not to automatically apply an eventBasedHold to new objects added to the bucket." + type = bool + default = false +} + +variable "enable_object_retention" { + description = "(Optional) Enables object retention on a storage bucket." + type = bool + default = false +} + +variable "public_access_prevention" { + description = "Prevents public access to a bucket." + type = string + default = "inherited" +} + variable "website" { description = "(Optional) Configuration if the bucket acts as a website." type = any default = null } +variable "autoclass" { + description = "(Optional) Autoclass configuration" + type = any + default = null +} + +variable "custom_placement_config" { + description = "(Optional) The bucket's custom location configuration, which specifies the individual regions that comprise a dual-region bucket. If the bucket is designated a single or multi-region, the parameters are empty." + type = any + default = null +} + variable "cors" { description = "(Optional) The bucket's Cross-Origin Resource Sharing (CORS) configuration." type = any diff --git a/versions.tf b/versions.tf index a263e7c..9cfd381 100644 --- a/versions.tf +++ b/versions.tf @@ -5,7 +5,7 @@ terraform { required_providers { google = { source = "hashicorp/google" - version = ">= 4.0, <6" + version = ">= 5.10, <6" } } } diff --git a/versions.tm.hcl b/versions.tm.hcl index 12f5183..049bd71 100644 --- a/versions.tm.hcl +++ b/versions.tm.hcl @@ -2,7 +2,7 @@ globals { minimum_terraform_version = "1.0" provider = "google" - minimum_provider_version = "4.0" + minimum_provider_version = "5.10" provider_version_constraint = ">= ${global.minimum_provider_version}, <6" terraform_version_constraint = "~> ${global.minimum_terraform_version}, != 1.1.0, != 1.1.1"