Skip to content

Commit 1e4241a

Browse files
authored
feat: Add Terragrunt wrappers (#52)
1 parent c420285 commit 1e4241a

File tree

16 files changed

+499
-1
lines changed

16 files changed

+499
-1
lines changed

.pre-commit-config.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
repos:
22
- repo: https://github.com/antonbabenko/pre-commit-terraform
3-
rev: v1.100.0
3+
rev: v1.100.1
44
hooks:
55
- id: terraform_fmt
6+
- id: terraform_wrapper_module_for_each
67
- id: terraform_docs
78
args:
89
- '--args=--lockfile=false'

wrappers/README.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Wrapper for the root module
2+
3+
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).
4+
5+
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.
6+
7+
This wrapper does not implement any extra functionality.
8+
9+
## Usage with Terragrunt
10+
11+
`terragrunt.hcl`:
12+
13+
```hcl
14+
terraform {
15+
source = "tfr:///terraform-aws-modules/elasticache/aws//wrappers"
16+
# Alternative source:
17+
# source = "git::[email protected]:terraform-aws-modules/terraform-aws-elasticache.git//wrappers?ref=master"
18+
}
19+
20+
inputs = {
21+
defaults = { # Default values
22+
create = true
23+
tags = {
24+
Terraform = "true"
25+
Environment = "dev"
26+
}
27+
}
28+
29+
items = {
30+
my-item = {
31+
# omitted... can be any argument supported by the module
32+
}
33+
my-second-item = {
34+
# omitted... can be any argument supported by the module
35+
}
36+
# omitted...
37+
}
38+
}
39+
```
40+
41+
## Usage with Terraform
42+
43+
```hcl
44+
module "wrapper" {
45+
source = "terraform-aws-modules/elasticache/aws//wrappers"
46+
47+
defaults = { # Default values
48+
create = true
49+
tags = {
50+
Terraform = "true"
51+
Environment = "dev"
52+
}
53+
}
54+
55+
items = {
56+
my-item = {
57+
# omitted... can be any argument supported by the module
58+
}
59+
my-second-item = {
60+
# omitted... can be any argument supported by the module
61+
}
62+
# omitted...
63+
}
64+
}
65+
```
66+
67+
## Example: Manage multiple S3 buckets in one Terragrunt layer
68+
69+
`eu-west-1/s3-buckets/terragrunt.hcl`:
70+
71+
```hcl
72+
terraform {
73+
source = "tfr:///terraform-aws-modules/s3-bucket/aws//wrappers"
74+
# Alternative source:
75+
# source = "git::[email protected]:terraform-aws-modules/terraform-aws-s3-bucket.git//wrappers?ref=master"
76+
}
77+
78+
inputs = {
79+
defaults = {
80+
force_destroy = true
81+
82+
attach_elb_log_delivery_policy = true
83+
attach_lb_log_delivery_policy = true
84+
attach_deny_insecure_transport_policy = true
85+
attach_require_latest_tls_policy = true
86+
}
87+
88+
items = {
89+
bucket1 = {
90+
bucket = "my-random-bucket-1"
91+
}
92+
bucket2 = {
93+
bucket = "my-random-bucket-2"
94+
tags = {
95+
Secure = "probably"
96+
}
97+
}
98+
}
99+
}
100+
```

wrappers/main.tf

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
module "wrapper" {
2+
source = "../"
3+
4+
for_each = var.items
5+
6+
apply_immediately = try(each.value.apply_immediately, var.defaults.apply_immediately, null)
7+
at_rest_encryption_enabled = try(each.value.at_rest_encryption_enabled, var.defaults.at_rest_encryption_enabled, true)
8+
auth_token = try(each.value.auth_token, var.defaults.auth_token, null)
9+
auth_token_update_strategy = try(each.value.auth_token_update_strategy, var.defaults.auth_token_update_strategy, null)
10+
auto_minor_version_upgrade = try(each.value.auto_minor_version_upgrade, var.defaults.auto_minor_version_upgrade, null)
11+
automatic_failover_enabled = try(each.value.automatic_failover_enabled, var.defaults.automatic_failover_enabled, null)
12+
availability_zone = try(each.value.availability_zone, var.defaults.availability_zone, null)
13+
az_mode = try(each.value.az_mode, var.defaults.az_mode, null)
14+
cluster_id = try(each.value.cluster_id, var.defaults.cluster_id, "")
15+
cluster_mode = try(each.value.cluster_mode, var.defaults.cluster_mode, null)
16+
cluster_mode_enabled = try(each.value.cluster_mode_enabled, var.defaults.cluster_mode_enabled, false)
17+
create = try(each.value.create, var.defaults.create, true)
18+
create_cluster = try(each.value.create_cluster, var.defaults.create_cluster, false)
19+
create_parameter_group = try(each.value.create_parameter_group, var.defaults.create_parameter_group, false)
20+
create_primary_global_replication_group = try(each.value.create_primary_global_replication_group, var.defaults.create_primary_global_replication_group, false)
21+
create_replication_group = try(each.value.create_replication_group, var.defaults.create_replication_group, true)
22+
create_secondary_global_replication_group = try(each.value.create_secondary_global_replication_group, var.defaults.create_secondary_global_replication_group, false)
23+
create_security_group = try(each.value.create_security_group, var.defaults.create_security_group, true)
24+
create_subnet_group = try(each.value.create_subnet_group, var.defaults.create_subnet_group, true)
25+
data_tiering_enabled = try(each.value.data_tiering_enabled, var.defaults.data_tiering_enabled, null)
26+
description = try(each.value.description, var.defaults.description, null)
27+
engine = try(each.value.engine, var.defaults.engine, "redis")
28+
engine_version = try(each.value.engine_version, var.defaults.engine_version, null)
29+
final_snapshot_identifier = try(each.value.final_snapshot_identifier, var.defaults.final_snapshot_identifier, null)
30+
global_replication_group_id = try(each.value.global_replication_group_id, var.defaults.global_replication_group_id, null)
31+
global_replication_group_id_suffix = try(each.value.global_replication_group_id_suffix, var.defaults.global_replication_group_id_suffix, null)
32+
ip_discovery = try(each.value.ip_discovery, var.defaults.ip_discovery, null)
33+
kms_key_arn = try(each.value.kms_key_arn, var.defaults.kms_key_arn, null)
34+
log_delivery_configuration = try(each.value.log_delivery_configuration, var.defaults.log_delivery_configuration, {
35+
slow-log = {
36+
destination_type = "cloudwatch-logs"
37+
log_format = "json"
38+
}
39+
})
40+
maintenance_window = try(each.value.maintenance_window, var.defaults.maintenance_window, null)
41+
multi_az_enabled = try(each.value.multi_az_enabled, var.defaults.multi_az_enabled, false)
42+
network_type = try(each.value.network_type, var.defaults.network_type, null)
43+
node_type = try(each.value.node_type, var.defaults.node_type, null)
44+
notification_topic_arn = try(each.value.notification_topic_arn, var.defaults.notification_topic_arn, null)
45+
num_cache_clusters = try(each.value.num_cache_clusters, var.defaults.num_cache_clusters, null)
46+
num_cache_nodes = try(each.value.num_cache_nodes, var.defaults.num_cache_nodes, 1)
47+
num_node_groups = try(each.value.num_node_groups, var.defaults.num_node_groups, null)
48+
outpost_mode = try(each.value.outpost_mode, var.defaults.outpost_mode, null)
49+
parameter_group_description = try(each.value.parameter_group_description, var.defaults.parameter_group_description, null)
50+
parameter_group_family = try(each.value.parameter_group_family, var.defaults.parameter_group_family, "")
51+
parameter_group_name = try(each.value.parameter_group_name, var.defaults.parameter_group_name, null)
52+
parameters = try(each.value.parameters, var.defaults.parameters, [])
53+
port = try(each.value.port, var.defaults.port, null)
54+
preferred_availability_zones = try(each.value.preferred_availability_zones, var.defaults.preferred_availability_zones, [])
55+
preferred_cache_cluster_azs = try(each.value.preferred_cache_cluster_azs, var.defaults.preferred_cache_cluster_azs, [])
56+
preferred_outpost_arn = try(each.value.preferred_outpost_arn, var.defaults.preferred_outpost_arn, null)
57+
replicas_per_node_group = try(each.value.replicas_per_node_group, var.defaults.replicas_per_node_group, null)
58+
replication_group_id = try(each.value.replication_group_id, var.defaults.replication_group_id, null)
59+
security_group_description = try(each.value.security_group_description, var.defaults.security_group_description, null)
60+
security_group_ids = try(each.value.security_group_ids, var.defaults.security_group_ids, [])
61+
security_group_name = try(each.value.security_group_name, var.defaults.security_group_name, null)
62+
security_group_names = try(each.value.security_group_names, var.defaults.security_group_names, [])
63+
security_group_rules = try(each.value.security_group_rules, var.defaults.security_group_rules, {})
64+
security_group_tags = try(each.value.security_group_tags, var.defaults.security_group_tags, {})
65+
security_group_use_name_prefix = try(each.value.security_group_use_name_prefix, var.defaults.security_group_use_name_prefix, true)
66+
snapshot_arns = try(each.value.snapshot_arns, var.defaults.snapshot_arns, [])
67+
snapshot_name = try(each.value.snapshot_name, var.defaults.snapshot_name, null)
68+
snapshot_retention_limit = try(each.value.snapshot_retention_limit, var.defaults.snapshot_retention_limit, null)
69+
snapshot_window = try(each.value.snapshot_window, var.defaults.snapshot_window, null)
70+
subnet_group_description = try(each.value.subnet_group_description, var.defaults.subnet_group_description, null)
71+
subnet_group_name = try(each.value.subnet_group_name, var.defaults.subnet_group_name, null)
72+
subnet_ids = try(each.value.subnet_ids, var.defaults.subnet_ids, [])
73+
tags = try(each.value.tags, var.defaults.tags, {})
74+
timeouts = try(each.value.timeouts, var.defaults.timeouts, {})
75+
transit_encryption_enabled = try(each.value.transit_encryption_enabled, var.defaults.transit_encryption_enabled, true)
76+
transit_encryption_mode = try(each.value.transit_encryption_mode, var.defaults.transit_encryption_mode, null)
77+
user_group_ids = try(each.value.user_group_ids, var.defaults.user_group_ids, null)
78+
vpc_id = try(each.value.vpc_id, var.defaults.vpc_id, null)
79+
}

wrappers/outputs.tf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
output "wrapper" {
2+
description = "Map of outputs of a wrapper."
3+
value = module.wrapper
4+
# sensitive = false # No sensitive module output found
5+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Wrapper for module: `modules/serverless-cache`
2+
3+
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).
4+
5+
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.
6+
7+
This wrapper does not implement any extra functionality.
8+
9+
## Usage with Terragrunt
10+
11+
`terragrunt.hcl`:
12+
13+
```hcl
14+
terraform {
15+
source = "tfr:///terraform-aws-modules/elasticache/aws//wrappers/serverless-cache"
16+
# Alternative source:
17+
# source = "git::[email protected]:terraform-aws-modules/terraform-aws-elasticache.git//wrappers/serverless-cache?ref=master"
18+
}
19+
20+
inputs = {
21+
defaults = { # Default values
22+
create = true
23+
tags = {
24+
Terraform = "true"
25+
Environment = "dev"
26+
}
27+
}
28+
29+
items = {
30+
my-item = {
31+
# omitted... can be any argument supported by the module
32+
}
33+
my-second-item = {
34+
# omitted... can be any argument supported by the module
35+
}
36+
# omitted...
37+
}
38+
}
39+
```
40+
41+
## Usage with Terraform
42+
43+
```hcl
44+
module "wrapper" {
45+
source = "terraform-aws-modules/elasticache/aws//wrappers/serverless-cache"
46+
47+
defaults = { # Default values
48+
create = true
49+
tags = {
50+
Terraform = "true"
51+
Environment = "dev"
52+
}
53+
}
54+
55+
items = {
56+
my-item = {
57+
# omitted... can be any argument supported by the module
58+
}
59+
my-second-item = {
60+
# omitted... can be any argument supported by the module
61+
}
62+
# omitted...
63+
}
64+
}
65+
```
66+
67+
## Example: Manage multiple S3 buckets in one Terragrunt layer
68+
69+
`eu-west-1/s3-buckets/terragrunt.hcl`:
70+
71+
```hcl
72+
terraform {
73+
source = "tfr:///terraform-aws-modules/s3-bucket/aws//wrappers"
74+
# Alternative source:
75+
# source = "git::[email protected]:terraform-aws-modules/terraform-aws-s3-bucket.git//wrappers?ref=master"
76+
}
77+
78+
inputs = {
79+
defaults = {
80+
force_destroy = true
81+
82+
attach_elb_log_delivery_policy = true
83+
attach_lb_log_delivery_policy = true
84+
attach_deny_insecure_transport_policy = true
85+
attach_require_latest_tls_policy = true
86+
}
87+
88+
items = {
89+
bucket1 = {
90+
bucket = "my-random-bucket-1"
91+
}
92+
bucket2 = {
93+
bucket = "my-random-bucket-2"
94+
tags = {
95+
Secure = "probably"
96+
}
97+
}
98+
}
99+
}
100+
```

wrappers/serverless-cache/main.tf

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
module "wrapper" {
2+
source = "../../modules/serverless-cache"
3+
4+
for_each = var.items
5+
6+
cache_name = try(each.value.cache_name, var.defaults.cache_name, null)
7+
cache_usage_limits = try(each.value.cache_usage_limits, var.defaults.cache_usage_limits, {})
8+
create = try(each.value.create, var.defaults.create, true)
9+
daily_snapshot_time = try(each.value.daily_snapshot_time, var.defaults.daily_snapshot_time, null)
10+
description = try(each.value.description, var.defaults.description, null)
11+
engine = try(each.value.engine, var.defaults.engine, "redis")
12+
kms_key_id = try(each.value.kms_key_id, var.defaults.kms_key_id, null)
13+
major_engine_version = try(each.value.major_engine_version, var.defaults.major_engine_version, null)
14+
security_group_ids = try(each.value.security_group_ids, var.defaults.security_group_ids, [])
15+
snapshot_arns_to_restore = try(each.value.snapshot_arns_to_restore, var.defaults.snapshot_arns_to_restore, null)
16+
snapshot_retention_limit = try(each.value.snapshot_retention_limit, var.defaults.snapshot_retention_limit, null)
17+
subnet_ids = try(each.value.subnet_ids, var.defaults.subnet_ids, [])
18+
tags = try(each.value.tags, var.defaults.tags, {})
19+
timeouts = try(each.value.timeouts, var.defaults.timeouts, {})
20+
user_group_id = try(each.value.user_group_id, var.defaults.user_group_id, null)
21+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
output "wrapper" {
2+
description = "Map of outputs of a wrapper."
3+
value = module.wrapper
4+
# sensitive = false # No sensitive module output found
5+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
variable "defaults" {
2+
description = "Map of default values which will be used for each item."
3+
type = any
4+
default = {}
5+
}
6+
7+
variable "items" {
8+
description = "Maps of items to create a wrapper from. Values are passed through to the module."
9+
type = any
10+
default = {}
11+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
terraform {
2+
required_version = ">= 1.0"
3+
4+
required_providers {
5+
aws = {
6+
source = "hashicorp/aws"
7+
version = ">= 5.73"
8+
}
9+
}
10+
}

0 commit comments

Comments
 (0)