From 5c7ce5828693a1184d6fdad1a0378c4339fcad10 Mon Sep 17 00:00:00 2001 From: Eugene Selivanov Date: Fri, 19 Jan 2024 21:32:02 +0700 Subject: [PATCH] feat: Wrapper for terragrunt (#23) --- .pre-commit-config.yaml | 1 + wrappers/README.md | 100 ++++++++++++++++++++++++++++++++++++++++ wrappers/main.tf | 35 ++++++++++++++ wrappers/outputs.tf | 5 ++ wrappers/variables.tf | 11 +++++ wrappers/versions.tf | 3 ++ 6 files changed, 155 insertions(+) create mode 100644 wrappers/README.md create mode 100644 wrappers/main.tf create mode 100644 wrappers/outputs.tf create mode 100644 wrappers/variables.tf create mode 100644 wrappers/versions.tf diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 74b0a6b..61ef178 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,6 +3,7 @@ repos: rev: v1.86.0 hooks: - id: terraform_fmt + - id: terraform_wrapper_module_for_each - id: terraform_validate - id: terraform_docs args: diff --git a/wrappers/README.md b/wrappers/README.md new file mode 100644 index 0000000..d6a8537 --- /dev/null +++ b/wrappers/README.md @@ -0,0 +1,100 @@ +# Wrapper for the root module + +The configuration in this directory contains an implementation of a single module wrapper pattern, which allows managing several copies of a module in places where using the native Terraform 0.13+ `for_each` feature is not feasible (e.g., with Terragrunt). + +You may want to use a single Terragrunt configuration file to manage multiple resources without duplicating `terragrunt.hcl` files for each copy of the same module. + +This wrapper does not implement any extra functionality. + +## Usage with Terragrunt + +`terragrunt.hcl`: + +```hcl +terraform { + source = "tfr:///terraform-aws-modules/efs/aws//wrappers" + # Alternative source: + # source = "git::git@github.com:terraform-aws-modules/terraform-aws-efs.git//wrappers?ref=master" +} + +inputs = { + defaults = { # Default values + create = true + tags = { + Terraform = "true" + Environment = "dev" + } + } + + items = { + my-item = { + # omitted... can be any argument supported by the module + } + my-second-item = { + # omitted... can be any argument supported by the module + } + # omitted... + } +} +``` + +## Usage with Terraform + +```hcl +module "wrapper" { + source = "terraform-aws-modules/efs/aws//wrappers" + + defaults = { # Default values + create = true + tags = { + Terraform = "true" + Environment = "dev" + } + } + + items = { + my-item = { + # omitted... can be any argument supported by the module + } + my-second-item = { + # omitted... can be any argument supported by the module + } + # omitted... + } +} +``` + +## Example: Manage multiple S3 buckets in one Terragrunt layer + +`eu-west-1/s3-buckets/terragrunt.hcl`: + +```hcl +terraform { + source = "tfr:///terraform-aws-modules/s3-bucket/aws//wrappers" + # Alternative source: + # source = "git::git@github.com:terraform-aws-modules/terraform-aws-s3-bucket.git//wrappers?ref=master" +} + +inputs = { + defaults = { + force_destroy = true + + attach_elb_log_delivery_policy = true + attach_lb_log_delivery_policy = true + attach_deny_insecure_transport_policy = true + attach_require_latest_tls_policy = true + } + + items = { + bucket1 = { + bucket = "my-random-bucket-1" + } + bucket2 = { + bucket = "my-random-bucket-2" + tags = { + Secure = "probably" + } + } + } +} +``` diff --git a/wrappers/main.tf b/wrappers/main.tf new file mode 100644 index 0000000..f852eea --- /dev/null +++ b/wrappers/main.tf @@ -0,0 +1,35 @@ +module "wrapper" { + source = "../" + + for_each = var.items + + access_points = try(each.value.access_points, var.defaults.access_points, {}) + attach_policy = try(each.value.attach_policy, var.defaults.attach_policy, true) + availability_zone_name = try(each.value.availability_zone_name, var.defaults.availability_zone_name, null) + bypass_policy_lockout_safety_check = try(each.value.bypass_policy_lockout_safety_check, var.defaults.bypass_policy_lockout_safety_check, null) + create = try(each.value.create, var.defaults.create, true) + create_backup_policy = try(each.value.create_backup_policy, var.defaults.create_backup_policy, true) + create_replication_configuration = try(each.value.create_replication_configuration, var.defaults.create_replication_configuration, false) + create_security_group = try(each.value.create_security_group, var.defaults.create_security_group, true) + creation_token = try(each.value.creation_token, var.defaults.creation_token, null) + deny_nonsecure_transport = try(each.value.deny_nonsecure_transport, var.defaults.deny_nonsecure_transport, true) + enable_backup_policy = try(each.value.enable_backup_policy, var.defaults.enable_backup_policy, true) + encrypted = try(each.value.encrypted, var.defaults.encrypted, true) + kms_key_arn = try(each.value.kms_key_arn, var.defaults.kms_key_arn, null) + lifecycle_policy = try(each.value.lifecycle_policy, var.defaults.lifecycle_policy, {}) + mount_targets = try(each.value.mount_targets, var.defaults.mount_targets, {}) + name = try(each.value.name, var.defaults.name, "") + override_policy_documents = try(each.value.override_policy_documents, var.defaults.override_policy_documents, []) + performance_mode = try(each.value.performance_mode, var.defaults.performance_mode, null) + policy_statements = try(each.value.policy_statements, var.defaults.policy_statements, []) + provisioned_throughput_in_mibps = try(each.value.provisioned_throughput_in_mibps, var.defaults.provisioned_throughput_in_mibps, null) + replication_configuration_destination = try(each.value.replication_configuration_destination, var.defaults.replication_configuration_destination, {}) + security_group_description = try(each.value.security_group_description, var.defaults.security_group_description, null) + security_group_name = try(each.value.security_group_name, var.defaults.security_group_name, null) + security_group_rules = try(each.value.security_group_rules, var.defaults.security_group_rules, {}) + security_group_use_name_prefix = try(each.value.security_group_use_name_prefix, var.defaults.security_group_use_name_prefix, false) + security_group_vpc_id = try(each.value.security_group_vpc_id, var.defaults.security_group_vpc_id, null) + source_policy_documents = try(each.value.source_policy_documents, var.defaults.source_policy_documents, []) + tags = try(each.value.tags, var.defaults.tags, {}) + throughput_mode = try(each.value.throughput_mode, var.defaults.throughput_mode, null) +} diff --git a/wrappers/outputs.tf b/wrappers/outputs.tf new file mode 100644 index 0000000..ec6da5f --- /dev/null +++ b/wrappers/outputs.tf @@ -0,0 +1,5 @@ +output "wrapper" { + description = "Map of outputs of a wrapper." + value = module.wrapper + # sensitive = false # No sensitive module output found +} diff --git a/wrappers/variables.tf b/wrappers/variables.tf new file mode 100644 index 0000000..a6ea096 --- /dev/null +++ b/wrappers/variables.tf @@ -0,0 +1,11 @@ +variable "defaults" { + description = "Map of default values which will be used for each item." + type = any + default = {} +} + +variable "items" { + description = "Maps of items to create a wrapper from. Values are passed through to the module." + type = any + default = {} +} diff --git a/wrappers/versions.tf b/wrappers/versions.tf new file mode 100644 index 0000000..51cad10 --- /dev/null +++ b/wrappers/versions.tf @@ -0,0 +1,3 @@ +terraform { + required_version = ">= 0.13.1" +}