From 3df7a13a7ddc36c6b4bbd1bb84bceb478f100b75 Mon Sep 17 00:00:00 2001 From: Soren Martius Date: Mon, 3 Jan 2022 16:27:10 -0300 Subject: [PATCH 1/5] refactor!: remove support for terraform < 1.0 --- CHANGELOG.md | 4 ++++ iam.tf | 4 ++-- versions.tf | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a35e89..374d057 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Breaking + +- Removed support for Terraform `< 1.0` + ## [0.0.5] ### Added diff --git a/iam.tf b/iam.tf index 99c81cb..3c44997 100644 --- a/iam.tf +++ b/iam.tf @@ -1,11 +1,11 @@ locals { - iam_map = var.policy_bindings == null ? { for iam in var.iam : iam.role => iam } : tomap({}) + iam_map = var.policy_bindings == null ? { for iam in var.iam : iam.role => iam } : {} policy_bindings = var.policy_bindings != null ? { iam_policy = { policy_bindings = var.policy_bindings } - } : tomap({}) + } : {} } module "iam" { diff --git a/versions.tf b/versions.tf index 67cf6f1..992fa22 100644 --- a/versions.tf +++ b/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 0.14, < 2.0" + required_version = ">= 1.0, < 2.0" required_providers { google = { From 862e4f9e62ff656cf64ad48e38815447db3ec99b Mon Sep 17 00:00:00 2001 From: Soren Martius Date: Mon, 3 Jan 2022 16:29:46 -0300 Subject: [PATCH 2/5] chore: prepare v0.0.6 release --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 374d057..dd5ee86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.0.6] + ### Breaking - Removed support for Terraform `< 1.0` @@ -45,7 +47,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Initial Implementation -[unreleased]: https://github.com/mineiros-io/terraform-google-storage-bucket/compare/v0.0.5...HEAD +[unreleased]: https://github.com/mineiros-io/terraform-google-storage-bucket/compare/v0.0.6...HEAD +[0.0.6]: https://github.com/mineiros-io/terraform-google-storage-bucket/compare/v0.0.5...v0.0.6 [0.0.5]: https://github.com/mineiros-io/terraform-google-storage-bucket/compare/v0.0.4...v0.0.5 [0.0.4]: https://github.com/mineiros-io/terraform-google-storage-bucket/compare/v0.0.3...v0.0.4 [0.0.3]: https://github.com/mineiros-io/terraform-google-storage-bucket/compare/v0.0.2...v0.0.3 From 2615364c1be26b040154e7b2c0dc456b606948c3 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 3 Jan 2022 21:05:48 +0100 Subject: [PATCH 3/5] fix: work around weird terraform typing --- CHANGELOG.md | 6 ++++- iam.tf | 34 +++++++++++++++++--------- outputs.tf | 5 ++++ test/unit-disabled/main.tf | 50 ++++++++++++++++++++++++++++++++++++++ versions.tf | 2 +- 5 files changed, 83 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd5ee86..1a91d14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Breaking -- Removed support for Terraform `< 1.0` +- Removed support for Terraform `< 1.1.2` + +### Fixed + +- Fix a bug that is based on terraform type system issue ## [0.0.5] diff --git a/iam.tf b/iam.tf index 3c44997..c298c77 100644 --- a/iam.tf +++ b/iam.tf @@ -1,24 +1,34 @@ locals { - iam_map = var.policy_bindings == null ? { for iam in var.iam : iam.role => iam } : {} - - policy_bindings = var.policy_bindings != null ? { - iam_policy = { - policy_bindings = var.policy_bindings - } - } : {} + iam_map = { for iam in var.iam : iam.role => iam } } module "iam" { source = "github.com/mineiros-io/terraform-google-storage-bucket-iam.git?ref=v0.0.2" - for_each = var.policy_bindings != null ? local.policy_bindings : local.iam_map + for_each = var.policy_bindings == null ? local.iam_map : {} + + module_enabled = var.module_enabled + module_depends_on = var.module_depends_on + + bucket = try(google_storage_bucket.bucket[0].name, null) + role = try(each.value.role, null) + members = try(each.value.members, null) + authoritative = try(each.value.authoritative, true) +} + +moved { + from = module.iam["iam_policy"] + to = module.policy_bindings[0] +} + +module "policy_bindings" { + source = "github.com/mineiros-io/terraform-google-storage-bucket-iam.git?ref=v0.0.2" + + count = var.policy_bindings != null ? 1 : 0 module_enabled = var.module_enabled module_depends_on = var.module_depends_on bucket = try(google_storage_bucket.bucket[0].name, null) - role = try(each.value.role, null) - members = try(each.value.members, null) - authoritative = try(each.value.authoritative, true) - policy_bindings = try(each.value.policy_bindings, null) + policy_bindings = var.policy_bindings } diff --git a/outputs.tf b/outputs.tf index 87f1dc0..b0956c8 100644 --- a/outputs.tf +++ b/outputs.tf @@ -17,6 +17,11 @@ output "bucket" { value = try(google_storage_bucket.bucket[0], null) } +output "policy_binding" { + description = "All attributes of the created policy_bindings mineiros-io/storage-bucket-iam/google module." + value = module.policy_bindings +} + # ---------------------------------------------------------------------------------------------------------------------- # OUTPUT MODULE CONFIGURATION # ---------------------------------------------------------------------------------------------------------------------- diff --git a/test/unit-disabled/main.tf b/test/unit-disabled/main.tf index 4ecfef7..01ade57 100644 --- a/test/unit-disabled/main.tf +++ b/test/unit-disabled/main.tf @@ -36,6 +36,15 @@ module "test" { # add all required arguments name = "unit-disabled" +} + +module "testA" { + source = "../.." + + module_enabled = false + + # add all required arguments + name = "unit-disabled" # add all optional arguments that create additional resources iam = [ @@ -46,6 +55,47 @@ module "test" { ] } +module "testB" { + source = "../.." + + module_enabled = false + + # add all required arguments + name = "unit-disabled" + + # add all optional arguments that create additional resources + policy_bindings = [ + { + role = "roles/storage.objectAdmin" + members = ["serviceAccount:noneExistingServiceAccount"] + } + ] +} + +module "testC" { + source = "../.." + + module_enabled = false + + # add all required arguments + name = "unit-disabled" + + # add all optional arguments that create additional resources + policy_bindings = [ + { + role = "roles/storage.objectAdmin" + members = ["serviceAccount:noneExistingServiceAccount"] + } + ] + + iam = [ + { + role = "roles/storage.objectAdmin" + members = ["serviceAccount:noneExistingServiceAccount"] + } + ] +} + # outputs generate non-idempotent terraform plans so we disable them for now unless we need them. # output "all" { # description = "All outputs of the module." diff --git a/versions.tf b/versions.tf index 992fa22..b235fab 100644 --- a/versions.tf +++ b/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.0, < 2.0" + required_version = ">= 1.1.2, < 2.0" required_providers { google = { From 244d9b5946f923ee2bb9e48a61a7a4c3b140a05c Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 3 Jan 2022 22:11:05 +0100 Subject: [PATCH 4/5] chore: add iam and policy_bindings tests --- test/unit-complete/main.tf | 39 +++++++++++++++++++++++++++++++++++++- test/unit-disabled/main.tf | 20 ++++++++++++------- 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/test/unit-complete/main.tf b/test/unit-complete/main.tf index 18f7492..d78a4fe 100644 --- a/test/unit-complete/main.tf +++ b/test/unit-complete/main.tf @@ -28,6 +28,13 @@ provider "google" { project = var.gcp_project } +data "google_project" "project" {} + +resource "random_id" "suffix" { + byte_length = 16 +} + + # DO NOT RENAME MODULE NAME module "test" { source = "../.." @@ -35,7 +42,7 @@ module "test" { module_enabled = true # add all required arguments - name = "unit-complete" + name = "unit-complete-${random_id.suffix.hex}" # add all optional arguments that create additional resources force_destroy = true @@ -78,6 +85,36 @@ module "test" { module_depends_on = ["nothing"] } +module "testIAM" { + source = "../.." + + name = "unit-complete-iam-${random_id.suffix.hex}" + + force_destroy = true + + iam = [ + { + role = "roles/storage.objectViewer" + members = ["projectOwner:${data.google_project.project.project_id}"] + } + ] +} + +module "testPolicy" { + source = "../.." + + name = "unit-complete-policy-${random_id.suffix.hex}" + + force_destroy = true + + policy_bindings = [ + { + role = "roles/storage.objectViewer" + members = ["projectOwner:${data.google_project.project.project_id}"] + } + ] +} + # outputs generate non-idempotent terraform plans so we disable them for now unless we need them. # output "all" { # description = "All outputs of the module." diff --git a/test/unit-disabled/main.tf b/test/unit-disabled/main.tf index 01ade57..13d1950 100644 --- a/test/unit-disabled/main.tf +++ b/test/unit-disabled/main.tf @@ -28,6 +28,8 @@ provider "google" { project = var.gcp_project } +data "google_project" "project" {} + # DO NOT RENAME MODULE NAME module "test" { source = "../.." @@ -49,8 +51,8 @@ module "testA" { # add all optional arguments that create additional resources iam = [ { - role = "roles/storage.objectAdmin" - members = ["serviceAccount:noneExistingServiceAccount"] + role = "roles/storage.objectViewer" + members = ["projectOwner:${data.google_project.project.project_id}"] } ] } @@ -66,8 +68,8 @@ module "testB" { # add all optional arguments that create additional resources policy_bindings = [ { - role = "roles/storage.objectAdmin" - members = ["serviceAccount:noneExistingServiceAccount"] + role = "roles/storage.objectViewer" + members = ["projectOwner:${data.google_project.project.project_id}"] } ] } @@ -83,15 +85,19 @@ module "testC" { # add all optional arguments that create additional resources policy_bindings = [ { - role = "roles/storage.objectAdmin" - members = ["serviceAccount:noneExistingServiceAccount"] + role = "roles/storage.objectViewer" + members = ["projectOwner:${data.google_project.project.project_id}"] } ] iam = [ + { + role = "roles/storage.objectViewer" + members = ["projectOwner:${data.google_project.project.project_id}"] + }, { role = "roles/storage.objectAdmin" - members = ["serviceAccount:noneExistingServiceAccount"] + members = ["projectOwner:${data.google_project.project.project_id}"] } ] } From 4fe95aa3a3beea9cdff7d087310ce5d79ea1ec52 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 3 Jan 2022 23:14:35 +0100 Subject: [PATCH 5/5] chore: add validations for iam and policy_bindings --- iam.tf | 4 ++-- variables.tf | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/iam.tf b/iam.tf index c298c77..14044fc 100644 --- a/iam.tf +++ b/iam.tf @@ -11,8 +11,8 @@ module "iam" { module_depends_on = var.module_depends_on bucket = try(google_storage_bucket.bucket[0].name, null) - role = try(each.value.role, null) - members = try(each.value.members, null) + role = each.value.role + members = each.value.members authoritative = try(each.value.authoritative, true) } diff --git a/variables.tf b/variables.tf index 6d2dc67..47abe39 100644 --- a/variables.tf +++ b/variables.tf @@ -138,12 +138,36 @@ variable "iam" { description = "(Optional) A list of IAM access." type = any default = [] + + # validate required keys in each object + validation { + condition = alltrue([for x in var.iam : length(setintersection(keys(x), ["role", "members"])) == 2]) + error_message = "Each object in var.iam must specify a role and a set of members." + } + + # validate no invalid keys are in each object + validation { + condition = alltrue([for x in var.iam : length(setsubtract(keys(x), ["role", "members", "authoritative"])) == 0]) + error_message = "Each object in var.iam does only support role, members and authoritative attributes." + } } variable "policy_bindings" { description = "(Optional) A list of IAM policy bindings." type = any default = null + + # validate required keys in each object + validation { + condition = var.policy_bindings == null ? true : alltrue([for x in var.policy_bindings : length(setintersection(keys(x), ["role", "members"])) == 2]) + error_message = "Each object in var.policy_bindings must specify a role and a set of members." + } + + # validate no invalid keys are in each object + validation { + condition = var.policy_bindings == null ? true : alltrue([for x in var.policy_bindings : length(setsubtract(keys(x), ["role", "members", "condition"])) == 0]) + error_message = "Each object in var.policy_bindings does only support role, members and condition attributes." + } } # ------------------------------------------------------------------------------