diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a6cd369..424b371 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,8 +1,9 @@ repos: - repo: https://github.com/antonbabenko/pre-commit-terraform - rev: v1.96.1 + rev: v1.98.0 hooks: - id: terraform_fmt + - id: terraform_wrapper_module_for_each - id: terraform_docs args: - '--args=--lockfile=false' diff --git a/wrappers/README.md b/wrappers/README.md new file mode 100644 index 0000000..d6fed17 --- /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/redshift/aws//wrappers" + # Alternative source: + # source = "git::git@github.com:terraform-aws-modules/terraform-aws-redshift.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/redshift/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..d04f14b --- /dev/null +++ b/wrappers/main.tf @@ -0,0 +1,88 @@ +module "wrapper" { + source = "../" + + for_each = var.items + + allow_version_upgrade = try(each.value.allow_version_upgrade, var.defaults.allow_version_upgrade, null) + apply_immediately = try(each.value.apply_immediately, var.defaults.apply_immediately, null) + aqua_configuration_status = try(each.value.aqua_configuration_status, var.defaults.aqua_configuration_status, null) + authentication_profiles = try(each.value.authentication_profiles, var.defaults.authentication_profiles, {}) + automated_snapshot_retention_period = try(each.value.automated_snapshot_retention_period, var.defaults.automated_snapshot_retention_period, null) + availability_zone = try(each.value.availability_zone, var.defaults.availability_zone, null) + availability_zone_relocation_enabled = try(each.value.availability_zone_relocation_enabled, var.defaults.availability_zone_relocation_enabled, null) + cloudwatch_log_group_kms_key_id = try(each.value.cloudwatch_log_group_kms_key_id, var.defaults.cloudwatch_log_group_kms_key_id, null) + cloudwatch_log_group_retention_in_days = try(each.value.cloudwatch_log_group_retention_in_days, var.defaults.cloudwatch_log_group_retention_in_days, 0) + cloudwatch_log_group_skip_destroy = try(each.value.cloudwatch_log_group_skip_destroy, var.defaults.cloudwatch_log_group_skip_destroy, null) + cloudwatch_log_group_tags = try(each.value.cloudwatch_log_group_tags, var.defaults.cloudwatch_log_group_tags, {}) + cluster_identifier = try(each.value.cluster_identifier, var.defaults.cluster_identifier, "") + cluster_timeouts = try(each.value.cluster_timeouts, var.defaults.cluster_timeouts, {}) + cluster_version = try(each.value.cluster_version, var.defaults.cluster_version, null) + create = try(each.value.create, var.defaults.create, true) + create_cloudwatch_log_group = try(each.value.create_cloudwatch_log_group, var.defaults.create_cloudwatch_log_group, false) + create_endpoint_access = try(each.value.create_endpoint_access, var.defaults.create_endpoint_access, false) + create_parameter_group = try(each.value.create_parameter_group, var.defaults.create_parameter_group, true) + create_random_password = try(each.value.create_random_password, var.defaults.create_random_password, true) + create_scheduled_action_iam_role = try(each.value.create_scheduled_action_iam_role, var.defaults.create_scheduled_action_iam_role, false) + create_snapshot_schedule = try(each.value.create_snapshot_schedule, var.defaults.create_snapshot_schedule, false) + create_subnet_group = try(each.value.create_subnet_group, var.defaults.create_subnet_group, true) + database_name = try(each.value.database_name, var.defaults.database_name, null) + default_iam_role_arn = try(each.value.default_iam_role_arn, var.defaults.default_iam_role_arn, null) + elastic_ip = try(each.value.elastic_ip, var.defaults.elastic_ip, null) + encrypted = try(each.value.encrypted, var.defaults.encrypted, true) + endpoint_name = try(each.value.endpoint_name, var.defaults.endpoint_name, "") + endpoint_resource_owner = try(each.value.endpoint_resource_owner, var.defaults.endpoint_resource_owner, null) + endpoint_subnet_group_name = try(each.value.endpoint_subnet_group_name, var.defaults.endpoint_subnet_group_name, "") + endpoint_vpc_security_group_ids = try(each.value.endpoint_vpc_security_group_ids, var.defaults.endpoint_vpc_security_group_ids, []) + enhanced_vpc_routing = try(each.value.enhanced_vpc_routing, var.defaults.enhanced_vpc_routing, null) + final_snapshot_identifier = try(each.value.final_snapshot_identifier, var.defaults.final_snapshot_identifier, null) + iam_role_arns = try(each.value.iam_role_arns, var.defaults.iam_role_arns, []) + iam_role_description = try(each.value.iam_role_description, var.defaults.iam_role_description, null) + iam_role_name = try(each.value.iam_role_name, var.defaults.iam_role_name, null) + iam_role_path = try(each.value.iam_role_path, var.defaults.iam_role_path, null) + iam_role_permissions_boundary = try(each.value.iam_role_permissions_boundary, var.defaults.iam_role_permissions_boundary, null) + iam_role_tags = try(each.value.iam_role_tags, var.defaults.iam_role_tags, {}) + iam_role_use_name_prefix = try(each.value.iam_role_use_name_prefix, var.defaults.iam_role_use_name_prefix, true) + kms_key_arn = try(each.value.kms_key_arn, var.defaults.kms_key_arn, null) + logging = try(each.value.logging, var.defaults.logging, {}) + maintenance_track_name = try(each.value.maintenance_track_name, var.defaults.maintenance_track_name, null) + manage_master_password = try(each.value.manage_master_password, var.defaults.manage_master_password, false) + manage_master_password_rotation = try(each.value.manage_master_password_rotation, var.defaults.manage_master_password_rotation, false) + manual_snapshot_retention_period = try(each.value.manual_snapshot_retention_period, var.defaults.manual_snapshot_retention_period, null) + master_password = try(each.value.master_password, var.defaults.master_password, null) + master_password_rotate_immediately = try(each.value.master_password_rotate_immediately, var.defaults.master_password_rotate_immediately, null) + master_password_rotation_automatically_after_days = try(each.value.master_password_rotation_automatically_after_days, var.defaults.master_password_rotation_automatically_after_days, null) + master_password_rotation_duration = try(each.value.master_password_rotation_duration, var.defaults.master_password_rotation_duration, null) + master_password_rotation_schedule_expression = try(each.value.master_password_rotation_schedule_expression, var.defaults.master_password_rotation_schedule_expression, null) + master_password_secret_kms_key_id = try(each.value.master_password_secret_kms_key_id, var.defaults.master_password_secret_kms_key_id, null) + master_username = try(each.value.master_username, var.defaults.master_username, "awsuser") + multi_az = try(each.value.multi_az, var.defaults.multi_az, null) + node_type = try(each.value.node_type, var.defaults.node_type, "") + number_of_nodes = try(each.value.number_of_nodes, var.defaults.number_of_nodes, 1) + owner_account = try(each.value.owner_account, var.defaults.owner_account, null) + parameter_group_description = try(each.value.parameter_group_description, var.defaults.parameter_group_description, null) + parameter_group_family = try(each.value.parameter_group_family, var.defaults.parameter_group_family, "redshift-1.0") + parameter_group_name = try(each.value.parameter_group_name, var.defaults.parameter_group_name, null) + parameter_group_parameters = try(each.value.parameter_group_parameters, var.defaults.parameter_group_parameters, {}) + parameter_group_tags = try(each.value.parameter_group_tags, var.defaults.parameter_group_tags, {}) + port = try(each.value.port, var.defaults.port, null) + preferred_maintenance_window = try(each.value.preferred_maintenance_window, var.defaults.preferred_maintenance_window, "sat:10:00-sat:10:30") + publicly_accessible = try(each.value.publicly_accessible, var.defaults.publicly_accessible, false) + random_password_length = try(each.value.random_password_length, var.defaults.random_password_length, 16) + scheduled_actions = try(each.value.scheduled_actions, var.defaults.scheduled_actions, {}) + skip_final_snapshot = try(each.value.skip_final_snapshot, var.defaults.skip_final_snapshot, true) + snapshot_cluster_identifier = try(each.value.snapshot_cluster_identifier, var.defaults.snapshot_cluster_identifier, null) + snapshot_copy = try(each.value.snapshot_copy, var.defaults.snapshot_copy, {}) + snapshot_identifier = try(each.value.snapshot_identifier, var.defaults.snapshot_identifier, null) + snapshot_schedule_definitions = try(each.value.snapshot_schedule_definitions, var.defaults.snapshot_schedule_definitions, []) + snapshot_schedule_description = try(each.value.snapshot_schedule_description, var.defaults.snapshot_schedule_description, null) + snapshot_schedule_force_destroy = try(each.value.snapshot_schedule_force_destroy, var.defaults.snapshot_schedule_force_destroy, null) + snapshot_schedule_identifier = try(each.value.snapshot_schedule_identifier, var.defaults.snapshot_schedule_identifier, null) + subnet_group_description = try(each.value.subnet_group_description, var.defaults.subnet_group_description, null) + subnet_group_name = try(each.value.subnet_group_name, var.defaults.subnet_group_name, null) + subnet_group_tags = try(each.value.subnet_group_tags, var.defaults.subnet_group_tags, {}) + subnet_ids = try(each.value.subnet_ids, var.defaults.subnet_ids, []) + tags = try(each.value.tags, var.defaults.tags, {}) + usage_limits = try(each.value.usage_limits, var.defaults.usage_limits, {}) + use_snapshot_identifier_prefix = try(each.value.use_snapshot_identifier_prefix, var.defaults.use_snapshot_identifier_prefix, true) + vpc_security_group_ids = try(each.value.vpc_security_group_ids, var.defaults.vpc_security_group_ids, []) +} 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..512dd2c --- /dev/null +++ b/wrappers/versions.tf @@ -0,0 +1,15 @@ +terraform { + required_version = ">= 1.3" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.45" + } + + random = { + source = "hashicorp/random" + version = ">= 3.0" + } + } +}