From 317c5a5678e1f2cc7914d9a6f5633d18caaf3358 Mon Sep 17 00:00:00 2001 From: Andriy Kopachevskyy Date: Mon, 4 Nov 2019 14:44:43 +0200 Subject: [PATCH 1/2] * Fix #17 Added support for lifecycle rules Updated tests and lints Updated variables and readme files --- README.md | 1 + examples/simple_example/main.tf | 13 ++++++- examples/simple_example/variables.tf | 1 - main.tf | 18 ++++++++++ test/fixtures/simple_example/main.tf | 1 - test/fixtures/simple_example/variables.tf | 1 - .../simple_example/controls/gsutil.rb | 35 +++++++++++++++++++ test/setup/main.tf | 4 +++ variables.tf | 11 ++++++ 9 files changed, 81 insertions(+), 4 deletions(-) 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/main.tf b/examples/simple_example/main.tf index 540ec043..60214d20 100644 --- a/examples/simple_example/main.tf +++ b/examples/simple_example/main.tf @@ -15,7 +15,7 @@ */ provider "google" { - version = "~> 2.0" + version = "~> 2.18.0" } module "cloud_storage" { @@ -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..4c08f092 100644 --- a/examples/simple_example/variables.tf +++ b/examples/simple_example/variables.tf @@ -33,4 +33,3 @@ variable "bucket_policy_only" { description = "Disable ad-hoc ACLs on specified buckets. Defaults to true. Map of lowercase unprefixed name => boolean" type = map(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..e34c2a3b 100644 --- a/test/fixtures/simple_example/main.tf +++ b/test/fixtures/simple_example/main.tf @@ -35,4 +35,3 @@ module "example" { "two" = false } } - diff --git a/test/fixtures/simple_example/variables.tf b/test/fixtures/simple_example/variables.tf index 1f95eaaf..c1a5c773 100644 --- a/test/fixtures/simple_example/variables.tf +++ b/test/fixtures/simple_example/variables.tf @@ -18,4 +18,3 @@ variable "project_id" { description = "The ID of the project in which to provision resources." type = 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/test/setup/main.tf b/test/setup/main.tf index 4f5f65c9..b81f8046 100644 --- a/test/setup/main.tf +++ b/test/setup/main.tf @@ -14,6 +14,10 @@ * limitations under the License. */ +provider "google" { + version = "~> 2.18.0" +} + module "project" { source = "terraform-google-modules/project-factory/google" version = "~> 3.0" 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." +} From 5b9f29825987f1f5399c34de86effb30cea2ce0f Mon Sep 17 00:00:00 2001 From: Andriy Kopachevskyy Date: Wed, 20 Nov 2019 18:09:24 +0200 Subject: [PATCH 2/2] Fixed provider for test setup --- test/setup/main.tf | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/setup/main.tf b/test/setup/main.tf index b81f8046..4f5f65c9 100644 --- a/test/setup/main.tf +++ b/test/setup/main.tf @@ -14,10 +14,6 @@ * limitations under the License. */ -provider "google" { - version = "~> 2.18.0" -} - module "project" { source = "terraform-google-modules/project-factory/google" version = "~> 3.0"