Skip to content

Commit 6e8c541

Browse files
authored
feat: Added wrappers automatically generated via pre-commit hook (#271)
1 parent 64d9932 commit 6e8c541

File tree

8 files changed

+193
-2
lines changed

8 files changed

+193
-2
lines changed

.github/workflows/pre-commit.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,14 @@ jobs:
7171
id: minMax
7272
uses: clowdhaus/terraform-min-max@v1.0.3
7373

74+
- name: Install hcledit (for terraform_wrapper_module_for_each hook)
75+
shell: bash
76+
run: |
77+
curl -L "$(curl -s https://api.github.com/repos/minamijoyo/hcledit/releases/latest | grep -o -E -m 1 "https://.+?_linux_amd64.tar.gz")" > hcledit.tgz
78+
sudo tar -xzf hcledit.tgz -C /usr/bin/ hcledit
79+
rm -f hcledit.tgz 2> /dev/null
80+
hcledit version
81+
7482
- name: Pre-commit Terraform ${{ steps.minMax.outputs.maxVersion }}
7583
uses: clowdhaus/terraform-composite-actions/pre-commit@v1.3.0
7684
with:

.pre-commit-config.yaml

Lines changed: 3 additions & 2 deletions
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.64.0
3+
rev: v1.71.0
44
hooks:
55
- id: terraform_fmt
6+
- id: terraform_wrapper_module_for_each
67
- id: terraform_validate
78
- id: terraform_docs
89
args:
@@ -23,7 +24,7 @@ repos:
2324
- '--args=--only=terraform_standard_module_structure'
2425
- '--args=--only=terraform_workspace_remote'
2526
- repo: https://github.com/pre-commit/pre-commit-hooks
26-
rev: v4.1.0
27+
rev: v4.2.0
2728
hooks:
2829
- id: check-merge-conflict
2930
- id: end-of-file-fixer

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ module "ec2_instance" {
8181
}
8282
```
8383

84+
## Module wrappers
85+
86+
Users of this Terraform module can create multiple similar resources by using [`for_each` meta-argument within `module` block](https://www.terraform.io/language/meta-arguments/for_each) which became available in Terraform 0.13.
87+
88+
Users of Terragrunt can achieve similar results by using modules provided in the [wrappers](https://github.com/terraform-aws-modules/terraform-aws-ec2-instance/tree/master/wrappers) directory, if they prefer to reduce amount of configuration files.
89+
8490
## Examples
8591

8692
- [Complete EC2 instance](https://github.com/terraform-aws-modules/terraform-aws-ec2-instance/tree/master/examples/complete)

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/ec2-instance/aws//wrappers"
16+
# Alternative source:
17+
# source = "git::git@github.com:terraform-aws-modules/terraform-aws-ec2-instance.git?ref=master//wrappers"
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/ec2-instance/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::git@github.com:terraform-aws-modules/terraform-aws-s3-bucket.git?ref=master//wrappers"
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: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
module "wrapper" {
2+
source = "../"
3+
4+
for_each = var.items
5+
6+
create = try(each.value.create, var.defaults.create, true)
7+
name = try(each.value.name, var.defaults.name, "")
8+
ami = try(each.value.ami, var.defaults.ami, "")
9+
associate_public_ip_address = try(each.value.associate_public_ip_address, var.defaults.associate_public_ip_address, null)
10+
availability_zone = try(each.value.availability_zone, var.defaults.availability_zone, null)
11+
capacity_reservation_specification = try(each.value.capacity_reservation_specification, var.defaults.capacity_reservation_specification, null)
12+
cpu_credits = try(each.value.cpu_credits, var.defaults.cpu_credits, null)
13+
disable_api_termination = try(each.value.disable_api_termination, var.defaults.disable_api_termination, null)
14+
ebs_block_device = try(each.value.ebs_block_device, var.defaults.ebs_block_device, [])
15+
ebs_optimized = try(each.value.ebs_optimized, var.defaults.ebs_optimized, null)
16+
enclave_options_enabled = try(each.value.enclave_options_enabled, var.defaults.enclave_options_enabled, null)
17+
ephemeral_block_device = try(each.value.ephemeral_block_device, var.defaults.ephemeral_block_device, [])
18+
get_password_data = try(each.value.get_password_data, var.defaults.get_password_data, null)
19+
hibernation = try(each.value.hibernation, var.defaults.hibernation, null)
20+
host_id = try(each.value.host_id, var.defaults.host_id, null)
21+
iam_instance_profile = try(each.value.iam_instance_profile, var.defaults.iam_instance_profile, null)
22+
instance_initiated_shutdown_behavior = try(each.value.instance_initiated_shutdown_behavior, var.defaults.instance_initiated_shutdown_behavior, null)
23+
instance_type = try(each.value.instance_type, var.defaults.instance_type, "t3.micro")
24+
ipv6_address_count = try(each.value.ipv6_address_count, var.defaults.ipv6_address_count, null)
25+
ipv6_addresses = try(each.value.ipv6_addresses, var.defaults.ipv6_addresses, null)
26+
key_name = try(each.value.key_name, var.defaults.key_name, null)
27+
launch_template = try(each.value.launch_template, var.defaults.launch_template, null)
28+
metadata_options = try(each.value.metadata_options, var.defaults.metadata_options, {})
29+
monitoring = try(each.value.monitoring, var.defaults.monitoring, false)
30+
network_interface = try(each.value.network_interface, var.defaults.network_interface, [])
31+
placement_group = try(each.value.placement_group, var.defaults.placement_group, null)
32+
private_ip = try(each.value.private_ip, var.defaults.private_ip, null)
33+
root_block_device = try(each.value.root_block_device, var.defaults.root_block_device, [])
34+
secondary_private_ips = try(each.value.secondary_private_ips, var.defaults.secondary_private_ips, null)
35+
source_dest_check = try(each.value.source_dest_check, var.defaults.source_dest_check, true)
36+
subnet_id = try(each.value.subnet_id, var.defaults.subnet_id, null)
37+
tags = try(each.value.tags, var.defaults.tags, {})
38+
tenancy = try(each.value.tenancy, var.defaults.tenancy, null)
39+
user_data = try(each.value.user_data, var.defaults.user_data, null)
40+
user_data_base64 = try(each.value.user_data_base64, var.defaults.user_data_base64, null)
41+
volume_tags = try(each.value.volume_tags, var.defaults.volume_tags, {})
42+
enable_volume_tags = try(each.value.enable_volume_tags, var.defaults.enable_volume_tags, true)
43+
vpc_security_group_ids = try(each.value.vpc_security_group_ids, var.defaults.vpc_security_group_ids, null)
44+
timeouts = try(each.value.timeouts, var.defaults.timeouts, {})
45+
cpu_core_count = try(each.value.cpu_core_count, var.defaults.cpu_core_count, null)
46+
cpu_threads_per_core = try(each.value.cpu_threads_per_core, var.defaults.cpu_threads_per_core, null)
47+
create_spot_instance = try(each.value.create_spot_instance, var.defaults.create_spot_instance, false)
48+
spot_price = try(each.value.spot_price, var.defaults.spot_price, null)
49+
spot_wait_for_fulfillment = try(each.value.spot_wait_for_fulfillment, var.defaults.spot_wait_for_fulfillment, null)
50+
spot_type = try(each.value.spot_type, var.defaults.spot_type, null)
51+
spot_launch_group = try(each.value.spot_launch_group, var.defaults.spot_launch_group, null)
52+
spot_block_duration_minutes = try(each.value.spot_block_duration_minutes, var.defaults.spot_block_duration_minutes, null)
53+
spot_instance_interruption_behavior = try(each.value.spot_instance_interruption_behavior, var.defaults.spot_instance_interruption_behavior, null)
54+
spot_valid_until = try(each.value.spot_valid_until, var.defaults.spot_valid_until, null)
55+
spot_valid_from = try(each.value.spot_valid_from, var.defaults.spot_valid_from, null)
56+
putin_khuylo = try(each.value.putin_khuylo, var.defaults.putin_khuylo, true)
57+
}

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+
}

wrappers/variables.tf

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+
}

wrappers/versions.tf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
terraform {
2+
required_version = ">= 0.13.1"
3+
}

0 commit comments

Comments
 (0)