From 8ac280f4761a41061b1044aea5449a05296d9713 Mon Sep 17 00:00:00 2001 From: Andriy Kopachevskyy Date: Mon, 4 Nov 2019 14:44:43 +0200 Subject: [PATCH] * Fix #17 Added support for lifecycle rules Updated tests and lints Updated variables and readme files --- README.md | 1 + examples/simple_example/README.md | 1 + examples/simple_example/main.tf | 11 ++++++ examples/simple_example/variables.tf | 11 ++++++ main.tf | 18 ++++++++++ test/fixtures/simple_example/main.tf | 11 ++++++ test/fixtures/simple_example/variables.tf | 11 ++++++ .../simple_example/controls/gsutil.rb | 35 +++++++++++++++++++ variables.tf | 11 ++++++ 9 files changed, 110 insertions(+) diff --git a/README.md b/README.md index b01e75a7..aafc1225 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,7 @@ Functional examples are included in the | creators | IAM-style members who will be granted roles/storage.objectCreators on all buckets. | list | `` | no | | force\_destroy | Optional map of lowercase unprefixed name => boolean, defaults to false. | map | `` | no | | labels | Labels to be attached to the buckets | map | `` | no | +| lifecycle\_rules | List of lifecycle rules to configure. Format is the same as described in provider documentation https://www.terraform.io/docs/providers/google/r/storage_bucket.html#lifecycle_rule except condition.matches_storage_class should be a comma delimited string. | object | `` | no | | location | Bucket location. | string | `"EU"` | no | | names | Bucket name suffixes. | list(string) | n/a | yes | | prefix | Prefix used to generate the bucket name. | string | n/a | yes | diff --git a/examples/simple_example/README.md b/examples/simple_example/README.md index ca6d4a35..55b1d55e 100644 --- a/examples/simple_example/README.md +++ b/examples/simple_example/README.md @@ -8,6 +8,7 @@ This example illustrates how to use the `cloud-storage` module. | Name | Description | Type | Default | Required | |------|-------------|:----:|:-----:|:-----:| | bucket\_policy\_only | Disable ad-hoc ACLs on specified buckets. Defaults to true. Map of lowercase unprefixed name => boolean | map(string) | n/a | yes | +| lifecycle\_rules | List of lifecycle rules to configure. Format is the same as described in provider documentation https://www.terraform.io/docs/providers/google/r/storage_bucket.html#lifecycle_rule except condition.matches_storage_class should be a comma delimited string. | object | `` | no | | names | Names of the buckets to create. | list(string) | n/a | yes | | prefix | Prefix used to generate bueckt names. | string | n/a | yes | | project\_id | The ID of the project in which to provision resources. | string | n/a | yes | diff --git a/examples/simple_example/main.tf b/examples/simple_example/main.tf index 540ec043..6b4e6c5f 100644 --- a/examples/simple_example/main.tf +++ b/examples/simple_example/main.tf @@ -24,5 +24,16 @@ module "cloud_storage" { prefix = var.prefix names = var.names bucket_policy_only = var.bucket_policy_only + + lifecycle_rules = [{ + action = { + type = "SetStorageClass" + storage_class = "NEARLINE" + } + condition = { + age = "10" + matches_storage_class = "MULTI_REGIONAL,STANDARD,DURABLE_REDUCED_AVAILABILITY" + } + }] } diff --git a/examples/simple_example/variables.tf b/examples/simple_example/variables.tf index e6d05d54..1dd26353 100644 --- a/examples/simple_example/variables.tf +++ b/examples/simple_example/variables.tf @@ -34,3 +34,14 @@ variable "bucket_policy_only" { type = map(string) } +variable "lifecycle_rules" { + type = set(object({ + action = object({ + type = string + storage_class = string + }) + condition = map(string) + })) + default = [] + description = "List of lifecycle rules to configure. Format is the same as described in provider documentation https://www.terraform.io/docs/providers/google/r/storage_bucket.html#lifecycle_rule except condition.matches_storage_class should be a comma delimited string." +} diff --git a/main.tf b/main.tf index dd9f8d71..1c51a034 100644 --- a/main.tf +++ b/main.tf @@ -42,6 +42,24 @@ resource "google_storage_bucket" "buckets" { false, ) } + dynamic "lifecycle_rule" { + for_each = var.lifecycle_rules + content { + action { + type = lifecycle_rule.value.action.type + storage_class = lifecycle_rule.value.action.storage_class + } + condition { + age = lookup(lifecycle_rule.value.condition, "age", null) + created_before = lookup(lifecycle_rule.value.condition, "created_before", null) + with_state = lookup(lifecycle_rule.value.condition, "with_state", null) + is_live = lookup(lifecycle_rule.value.condition, "is_live", null) + matches_storage_class = contains(keys(lifecycle_rule.value.condition), "matches_storage_class") ? split(",", lifecycle_rule.value.condition["matches_storage_class"]) : null + num_newer_versions = lookup(lifecycle_rule.value.condition, "num_newer_versions", null) + } + } + } + } resource "google_storage_bucket_iam_binding" "admins" { diff --git a/test/fixtures/simple_example/main.tf b/test/fixtures/simple_example/main.tf index c464176f..750f68a0 100644 --- a/test/fixtures/simple_example/main.tf +++ b/test/fixtures/simple_example/main.tf @@ -34,5 +34,16 @@ module "example" { "one" = true "two" = false } + + lifecycle_rules = [{ + action = { + type = "SetStorageClass" + storage_class = "NEARLINE" + } + condition = { + age = "10" + matches_storage_class = "MULTI_REGIONAL,STANDARD,DURABLE_REDUCED_AVAILABILITY" + } + }] } diff --git a/test/fixtures/simple_example/variables.tf b/test/fixtures/simple_example/variables.tf index 1f95eaaf..b36a2fb6 100644 --- a/test/fixtures/simple_example/variables.tf +++ b/test/fixtures/simple_example/variables.tf @@ -19,3 +19,14 @@ variable "project_id" { type = string } +variable "lifecycle_rules" { + type = set(object({ + action = object({ + type = string + storage_class = string + }) + condition = map(string) + })) + default = [] + description = "List of lifecycle rules to configure. Format is the same as described in provider documentation https://www.terraform.io/docs/providers/google/r/storage_bucket.html#lifecycle_rule except condition.matches_storage_class should be a comma delimited string." +} diff --git a/test/integration/simple_example/controls/gsutil.rb b/test/integration/simple_example/controls/gsutil.rb index 1074674f..4dd7cc54 100644 --- a/test/integration/simple_example/controls/gsutil.rb +++ b/test/integration/simple_example/controls/gsutil.rb @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +require 'json' + control "gsutil" do title "gsutil" @@ -33,4 +35,37 @@ its(:stderr) { should eq "" } its(:stdout) { should include "Enabled: False" } end + + get_lifecycle_0_out = command("gsutil lifecycle get gs://#{attribute("names_list")[0]}") + rule = JSON.parse(get_lifecycle_0_out.stdout)['rule'][0] + + describe get_lifecycle_0_out do + let(:action) { rule['action'] } + let(:condition) { rule['condition'] } + + its(:exit_status) { should eq 0 } + its(:stderr) { should eq "" } + it { expect(action['storageClass']).to eq("NEARLINE") } + it { expect(action['type']).to eq("SetStorageClass") } + it { expect(condition['age']).to eq(10) } + it { expect(condition['isLive']).to eq(false) } + it { expect(condition['matchesStorageClass']).to eq(%w(MULTI_REGIONAL STANDARD DURABLE_REDUCED_AVAILABILITY)) } + end + + get_lifecycle_1_out = command("gsutil lifecycle get gs://#{attribute("names_list")[1]}") + rule_1 = JSON.parse(get_lifecycle_1_out.stdout)['rule'][0] + + describe command("gsutil lifecycle get gs://#{attribute("names_list")[1]}") do + let(:action) { rule_1['action'] } + let(:condition) { rule_1['condition'] } + + its(:exit_status) { should eq 0 } + its(:stderr) { should eq "" } + it { expect(action['storageClass']).to eq("NEARLINE") } + it { expect(action['type']).to eq("SetStorageClass") } + it { expect(condition['age']).to eq(10) } + it { expect(condition['isLive']).to eq(false) } + it { expect(condition['matchesStorageClass']).to eq(%w(MULTI_REGIONAL STANDARD DURABLE_REDUCED_AVAILABILITY)) } + end + end diff --git a/variables.tf b/variables.tf index 5a001968..cc8a0b76 100644 --- a/variables.tf +++ b/variables.tf @@ -104,3 +104,14 @@ variable "set_viewer_roles" { default = false } +variable "lifecycle_rules" { + type = set(object({ + action = object({ + type = string + storage_class = string + }) + condition = map(string) + })) + default = [] + description = "List of lifecycle rules to configure. Format is the same as described in provider documentation https://www.terraform.io/docs/providers/google/r/storage_bucket.html#lifecycle_rule except condition.matches_storage_class should be a comma delimited string." +}