Skip to content

Commit e6bd087

Browse files
Benbentwoclaude
andauthored
Remove hardcoded providers to enable for_each/count (#118)
* feat: remove hardcoded providers to enable for_each/count/depends_on Remove hardcoded provider blocks from the module and use configuration_aliases instead. This allows the module to be used with for_each, count, and depends_on. Callers now pass in pre-configured providers via the providers argument. BREAKING: Removes variables requester_region, accepter_region, requester_aws_assume_role_arn, accepter_aws_assume_role_arn, requester_aws_profile, accepter_aws_profile, requester_aws_access_key, accepter_aws_access_key, requester_aws_secret_key, accepter_aws_secret_key, requester_aws_token, accepter_aws_token, and skip_metadata_api_check. Callers must define aws providers with these configs and pass them in via the providers block. Closes #48 Closes #108 Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> * docs: add migration guide and update README for v2.0 Update usage examples in README.yaml and README.md to show the new provider-passing pattern. Remove deleted variables from the inputs table. Add MIGRATION.md with step-by-step upgrade instructions from v1.x to v2.0. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
1 parent a91401e commit e6bd087

File tree

8 files changed

+203
-141
lines changed

8 files changed

+203
-141
lines changed

MIGRATION.md

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# Migration Guide: v1.x to v2.0
2+
3+
## Breaking Change: Provider Configuration
4+
5+
In v2.0, the module no longer contains hardcoded `provider "aws"` blocks. Instead, it uses `configuration_aliases` and expects providers to be passed in by the caller. This enables the module to be used with `for_each`, `count`, and `depends_on`.
6+
7+
## Removed Variables
8+
9+
The following variables have been removed. Provider configuration (region, credentials, assume role) is now handled by defining providers in your root module.
10+
11+
| Removed Variable | Previously Used For |
12+
|---|---|
13+
| `requester_aws_assume_role_arn` | IAM role to assume for the requester account |
14+
| `requester_region` | AWS region of the requester |
15+
| `requester_aws_profile` | AWS CLI profile for the requester |
16+
| `requester_aws_access_key` | Access key for the requester |
17+
| `requester_aws_secret_key` | Secret key for the requester |
18+
| `requester_aws_token` | Session token for the requester |
19+
| `accepter_aws_assume_role_arn` | IAM role to assume for the accepter account |
20+
| `accepter_region` | AWS region of the accepter |
21+
| `accepter_aws_profile` | AWS CLI profile for the accepter |
22+
| `accepter_aws_access_key` | Access key for the accepter |
23+
| `accepter_aws_secret_key` | Secret key for the accepter |
24+
| `accepter_aws_token` | Session token for the accepter |
25+
| `skip_metadata_api_check` | Skip EC2 metadata API check on providers |
26+
27+
## Migration Steps
28+
29+
### Before (v1.x)
30+
31+
```hcl
32+
module "vpc_peering" {
33+
source = "cloudposse/vpc-peering-multi-account/aws"
34+
version = "~> 1.0"
35+
36+
requester_aws_assume_role_arn = "arn:aws:iam::111111111111:role/peering-role"
37+
requester_region = "us-west-2"
38+
requester_vpc_id = "vpc-xxxxxxxx"
39+
requester_allow_remote_vpc_dns_resolution = true
40+
41+
accepter_aws_assume_role_arn = "arn:aws:iam::222222222222:role/peering-role"
42+
accepter_region = "us-east-1"
43+
accepter_vpc_id = "vpc-yyyyyyyy"
44+
accepter_allow_remote_vpc_dns_resolution = true
45+
}
46+
```
47+
48+
### After (v2.0)
49+
50+
```hcl
51+
# 1. Define providers in your root module
52+
provider "aws" {
53+
alias = "requester"
54+
region = "us-west-2"
55+
56+
assume_role {
57+
role_arn = "arn:aws:iam::111111111111:role/peering-role"
58+
}
59+
}
60+
61+
provider "aws" {
62+
alias = "accepter"
63+
region = "us-east-1"
64+
65+
assume_role {
66+
role_arn = "arn:aws:iam::222222222222:role/peering-role"
67+
}
68+
}
69+
70+
# 2. Pass providers explicitly and remove deleted variable arguments
71+
module "vpc_peering" {
72+
source = "cloudposse/vpc-peering-multi-account/aws"
73+
version = "~> 2.0"
74+
75+
providers = {
76+
aws.requester = aws.requester
77+
aws.accepter = aws.accepter
78+
}
79+
80+
requester_vpc_id = "vpc-xxxxxxxx"
81+
requester_allow_remote_vpc_dns_resolution = true
82+
83+
accepter_vpc_id = "vpc-yyyyyyyy"
84+
accepter_allow_remote_vpc_dns_resolution = true
85+
}
86+
```
87+
88+
### Key Differences
89+
90+
1. **Define providers externally** -- Create `provider "aws"` blocks with `alias = "requester"` and `alias = "accepter"` in your root module, including region, assume_role, and any credential configuration.
91+
2. **Pass providers to the module** -- Add a `providers` block to the module call mapping `aws.requester` and `aws.accepter`.
92+
3. **Remove deleted arguments** -- Delete `requester_region`, `requester_aws_assume_role_arn`, `accepter_region`, `accepter_aws_assume_role_arn`, and all other removed variables from the module call.
93+
94+
## Using `for_each` (New Capability)
95+
96+
With v2.0, you can now loop over the module:
97+
98+
```hcl
99+
locals {
100+
peering_configs = {
101+
"dev-to-shared" = {
102+
requester_vpc_id = "vpc-aaa"
103+
accepter_vpc_id = "vpc-bbb"
104+
}
105+
"dev-to-prod" = {
106+
requester_vpc_id = "vpc-aaa"
107+
accepter_vpc_id = "vpc-ccc"
108+
}
109+
}
110+
}
111+
112+
module "vpc_peering" {
113+
source = "cloudposse/vpc-peering-multi-account/aws"
114+
for_each = local.peering_configs
115+
116+
providers = {
117+
aws.requester = aws.requester
118+
aws.accepter = aws.accepter
119+
}
120+
121+
requester_vpc_id = each.value.requester_vpc_id
122+
accepter_vpc_id = each.value.accepter_vpc_id
123+
}
124+
```
125+
126+
## State Migration
127+
128+
Since only provider configuration was removed (no resources changed), upgrading should not require state manipulation. However, we recommend running `terraform plan` after upgrading to confirm no unexpected changes before applying.

README.md

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,24 @@ However, Terraform only allows the VPC Peering Connection to be deleted from the
6666
For a complete example, see [examples/complete](examples/complete)
6767

6868
```hcl
69+
provider "aws" {
70+
alias = "requester"
71+
region = "us-west-2"
72+
73+
assume_role {
74+
role_arn = "arn:aws:iam::XXXXXXXX:role/cross-account-vpc-peering-test"
75+
}
76+
}
77+
78+
provider "aws" {
79+
alias = "accepter"
80+
region = "us-east-1"
81+
82+
assume_role {
83+
role_arn = "arn:aws:iam::YYYYYYYY:role/cross-account-vpc-peering-test"
84+
}
85+
}
86+
6987
module "vpc_peering_cross_account" {
7088
source = "cloudposse/vpc-peering-multi-account/aws"
7189
# Cloud Posse recommends pinning every module to a specific version
@@ -74,13 +92,14 @@ module "vpc_peering_cross_account" {
7492
stage = "dev"
7593
name = "cluster"
7694
77-
requester_aws_assume_role_arn = "arn:aws:iam::XXXXXXXX:role/cross-account-vpc-peering-test"
78-
requester_region = "us-west-2"
95+
providers = {
96+
aws.requester = aws.requester
97+
aws.accepter = aws.accepter
98+
}
99+
79100
requester_vpc_id = "vpc-xxxxxxxx"
80101
requester_allow_remote_vpc_dns_resolution = true
81102
82-
accepter_aws_assume_role_arn = "arn:aws:iam::YYYYYYYY:role/cross-account-vpc-peering-test"
83-
accepter_region = "us-east-1"
84103
accepter_vpc_id = "vpc-yyyyyyyy"
85104
accepter_allow_remote_vpc_dns_resolution = true
86105
}
@@ -324,13 +343,7 @@ For more information on IAM policies and permissions for VPC peering, see [Creat
324343
| Name | Description | Type | Default | Required |
325344
|------|-------------|------|---------|:--------:|
326345
| <a name="input_accepter_allow_remote_vpc_dns_resolution"></a> [accepter\_allow\_remote\_vpc\_dns\_resolution](#input\_accepter\_allow\_remote\_vpc\_dns\_resolution) | Allow accepter VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the requester VPC | `bool` | `true` | no |
327-
| <a name="input_accepter_aws_access_key"></a> [accepter\_aws\_access\_key](#input\_accepter\_aws\_access\_key) | Access key id to use in accepter account | `string` | `null` | no |
328-
| <a name="input_accepter_aws_assume_role_arn"></a> [accepter\_aws\_assume\_role\_arn](#input\_accepter\_aws\_assume\_role\_arn) | Accepter AWS Assume Role ARN | `string` | `null` | no |
329-
| <a name="input_accepter_aws_profile"></a> [accepter\_aws\_profile](#input\_accepter\_aws\_profile) | Profile used to assume accepter\_aws\_assume\_role\_arn | `string` | `""` | no |
330-
| <a name="input_accepter_aws_secret_key"></a> [accepter\_aws\_secret\_key](#input\_accepter\_aws\_secret\_key) | Secret access key to use in accepter account | `string` | `null` | no |
331-
| <a name="input_accepter_aws_token"></a> [accepter\_aws\_token](#input\_accepter\_aws\_token) | Session token for validating temporary credentials | `string` | `null` | no |
332346
| <a name="input_accepter_enabled"></a> [accepter\_enabled](#input\_accepter\_enabled) | Flag to enable/disable the accepter side of the peering connection | `bool` | `true` | no |
333-
| <a name="input_accepter_region"></a> [accepter\_region](#input\_accepter\_region) | Accepter AWS region | `string` | n/a | yes |
334347
| <a name="input_accepter_subnet_tags"></a> [accepter\_subnet\_tags](#input\_accepter\_subnet\_tags) | Only add peer routes to accepter VPC route tables of subnets matching these tags | `map(string)` | `{}` | no |
335348
| <a name="input_accepter_vpc_id"></a> [accepter\_vpc\_id](#input\_accepter\_vpc\_id) | Accepter VPC ID filter | `string` | `""` | no |
336349
| <a name="input_accepter_vpc_tags"></a> [accepter\_vpc\_tags](#input\_accepter\_vpc\_tags) | Accepter VPC Tags filter | `map(string)` | `{}` | no |
@@ -354,16 +367,9 @@ For more information on IAM policies and permissions for VPC peering, see [Creat
354367
| <a name="input_namespace"></a> [namespace](#input\_namespace) | ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique | `string` | `null` | no |
355368
| <a name="input_regex_replace_chars"></a> [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.<br/>Characters matching the regex will be removed from the ID elements.<br/>If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no |
356369
| <a name="input_requester_allow_remote_vpc_dns_resolution"></a> [requester\_allow\_remote\_vpc\_dns\_resolution](#input\_requester\_allow\_remote\_vpc\_dns\_resolution) | Allow requester VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the accepter VPC | `bool` | `true` | no |
357-
| <a name="input_requester_aws_access_key"></a> [requester\_aws\_access\_key](#input\_requester\_aws\_access\_key) | Access key id to use in requester account | `string` | `null` | no |
358-
| <a name="input_requester_aws_assume_role_arn"></a> [requester\_aws\_assume\_role\_arn](#input\_requester\_aws\_assume\_role\_arn) | Requester AWS Assume Role ARN | `string` | n/a | yes |
359-
| <a name="input_requester_aws_profile"></a> [requester\_aws\_profile](#input\_requester\_aws\_profile) | Profile used to assume requester\_aws\_assume\_role\_arn | `string` | `""` | no |
360-
| <a name="input_requester_aws_secret_key"></a> [requester\_aws\_secret\_key](#input\_requester\_aws\_secret\_key) | Secret access key to use in requester account | `string` | `null` | no |
361-
| <a name="input_requester_aws_token"></a> [requester\_aws\_token](#input\_requester\_aws\_token) | Session token for validating temporary credentials | `string` | `null` | no |
362-
| <a name="input_requester_region"></a> [requester\_region](#input\_requester\_region) | Requester AWS region | `string` | n/a | yes |
363370
| <a name="input_requester_subnet_tags"></a> [requester\_subnet\_tags](#input\_requester\_subnet\_tags) | Only add peer routes to requester VPC route tables of subnets matching these tags | `map(string)` | `{}` | no |
364371
| <a name="input_requester_vpc_id"></a> [requester\_vpc\_id](#input\_requester\_vpc\_id) | Requester VPC ID filter | `string` | `""` | no |
365372
| <a name="input_requester_vpc_tags"></a> [requester\_vpc\_tags](#input\_requester\_vpc\_tags) | Requester VPC Tags filter | `map(string)` | `{}` | no |
366-
| <a name="input_skip_metadata_api_check"></a> [skip\_metadata\_api\_check](#input\_skip\_metadata\_api\_check) | Don't use the credentials of EC2 instance profile | `bool` | `false` | no |
367373
| <a name="input_stage"></a> [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no |
368374
| <a name="input_tags"></a> [tags](#input\_tags) | Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).<br/>Neither the tag keys nor the tag values will be modified by this module. | `map(string)` | `{}` | no |
369375
| <a name="input_tenant"></a> [tenant](#input\_tenant) | ID element \_(Rarely used, not included by default)\_. A customer identifier, indicating who this instance of a resource is for | `string` | `null` | no |

README.yaml

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,24 @@ usage: |2-
7373
For a complete example, see [examples/complete](examples/complete)
7474
7575
```hcl
76+
provider "aws" {
77+
alias = "requester"
78+
region = "us-west-2"
79+
80+
assume_role {
81+
role_arn = "arn:aws:iam::XXXXXXXX:role/cross-account-vpc-peering-test"
82+
}
83+
}
84+
85+
provider "aws" {
86+
alias = "accepter"
87+
region = "us-east-1"
88+
89+
assume_role {
90+
role_arn = "arn:aws:iam::YYYYYYYY:role/cross-account-vpc-peering-test"
91+
}
92+
}
93+
7694
module "vpc_peering_cross_account" {
7795
source = "cloudposse/vpc-peering-multi-account/aws"
7896
# Cloud Posse recommends pinning every module to a specific version
@@ -81,13 +99,14 @@ usage: |2-
8199
stage = "dev"
82100
name = "cluster"
83101
84-
requester_aws_assume_role_arn = "arn:aws:iam::XXXXXXXX:role/cross-account-vpc-peering-test"
85-
requester_region = "us-west-2"
102+
providers = {
103+
aws.requester = aws.requester
104+
aws.accepter = aws.accepter
105+
}
106+
86107
requester_vpc_id = "vpc-xxxxxxxx"
87108
requester_allow_remote_vpc_dns_resolution = true
88109
89-
accepter_aws_assume_role_arn = "arn:aws:iam::YYYYYYYY:role/cross-account-vpc-peering-test"
90-
accepter_region = "us-east-1"
91110
accepter_vpc_id = "vpc-yyyyyyyy"
92111
accepter_allow_remote_vpc_dns_resolution = true
93112
}

accepter.tf

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,3 @@
1-
# Accepter's credentials
2-
provider "aws" {
3-
alias = "accepter"
4-
region = var.accepter_region
5-
profile = var.accepter_aws_profile
6-
skip_metadata_api_check = var.skip_metadata_api_check
7-
8-
dynamic "assume_role" {
9-
for_each = var.accepter_aws_assume_role_arn != "" ? ["true"] : []
10-
content {
11-
role_arn = var.accepter_aws_assume_role_arn
12-
}
13-
}
14-
15-
access_key = var.accepter_aws_access_key
16-
secret_key = var.accepter_aws_secret_key
17-
token = var.accepter_aws_token
18-
}
19-
201
module "accepter" {
212
source = "cloudposse/label/null"
223
version = "0.25.0"

examples/complete/main.tf

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,39 @@ provider "aws" {
22
region = var.region
33
}
44

5+
provider "aws" {
6+
alias = "requester"
7+
region = var.requester_region
8+
9+
assume_role {
10+
role_arn = var.requester_aws_assume_role_arn
11+
}
12+
}
13+
14+
provider "aws" {
15+
alias = "accepter"
16+
region = var.accepter_region
17+
18+
dynamic "assume_role" {
19+
for_each = var.accepter_aws_assume_role_arn != null ? [var.accepter_aws_assume_role_arn] : []
20+
content {
21+
role_arn = assume_role.value
22+
}
23+
}
24+
}
25+
526
module "vpc_peering_cross_account" {
627
source = "../../"
728

8-
requester_aws_assume_role_arn = var.requester_aws_assume_role_arn
9-
requester_region = var.requester_region
29+
providers = {
30+
aws.requester = aws.requester
31+
aws.accepter = aws.accepter
32+
}
33+
1034
requester_vpc_id = var.requester_vpc_id
1135
requester_allow_remote_vpc_dns_resolution = var.requester_allow_remote_vpc_dns_resolution
1236

1337
accepter_enabled = var.accepter_enabled
14-
accepter_aws_assume_role_arn = var.accepter_aws_assume_role_arn
15-
accepter_region = var.accepter_region
1638
accepter_vpc_id = var.accepter_vpc_id
1739
accepter_allow_remote_vpc_dns_resolution = var.accepter_allow_remote_vpc_dns_resolution
1840

requester.tf

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,3 @@
1-
variable "requester_aws_profile" {
2-
description = "Profile used to assume requester_aws_assume_role_arn"
3-
type = string
4-
default = ""
5-
}
6-
7-
variable "requester_aws_access_key" {
8-
description = "Access key id to use in requester account"
9-
type = string
10-
default = null
11-
}
12-
13-
variable "requester_aws_assume_role_arn" {
14-
description = "Requester AWS Assume Role ARN"
15-
type = string
16-
}
17-
18-
variable "requester_aws_secret_key" {
19-
description = "Secret access key to use in requester account"
20-
type = string
21-
default = null
22-
}
23-
24-
variable "requester_aws_token" {
25-
description = "Session token for validating temporary credentials"
26-
type = string
27-
default = null
28-
}
29-
30-
variable "requester_region" {
31-
type = string
32-
description = "Requester AWS region"
33-
}
34-
351
variable "requester_subnet_tags" {
362
type = map(string)
373
description = "Only add peer routes to requester VPC route tables of subnets matching these tags"
@@ -56,26 +22,6 @@ variable "requester_allow_remote_vpc_dns_resolution" {
5622
description = "Allow requester VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the accepter VPC"
5723
}
5824

59-
# Requestors's credentials
60-
provider "aws" {
61-
alias = "requester"
62-
region = var.requester_region
63-
profile = var.requester_aws_profile
64-
skip_metadata_api_check = var.skip_metadata_api_check
65-
66-
dynamic "assume_role" {
67-
for_each = var.requester_aws_assume_role_arn != "" ? ["true"] : []
68-
content {
69-
role_arn = var.requester_aws_assume_role_arn
70-
}
71-
}
72-
73-
access_key = var.requester_aws_access_key
74-
secret_key = var.requester_aws_secret_key
75-
token = var.requester_aws_token
76-
77-
}
78-
7925
module "requester" {
8026
source = "cloudposse/label/null"
8127
version = "0.25.0"

0 commit comments

Comments
 (0)