Skip to content

Commit e98f459

Browse files
authored
Merge pull request #184 from clopca/release/v4.8
v4.8: BYOIP NAT support, role-based outputs, Cloud WAN & IPAM fixes, CI
2 parents 6991e6d + b03c810 commit e98f459

28 files changed

Lines changed: 1056 additions & 28 deletions

.github/workflows/ci.yml

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
name: CI - Lint & Validate
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
push:
7+
branches: [main]
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
lint:
14+
name: Lint
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Checkout
18+
uses: actions/checkout@v4
19+
20+
- name: Setup Terraform
21+
uses: hashicorp/setup-terraform@v3
22+
with:
23+
terraform_wrapper: false
24+
25+
- name: Terraform Format Check
26+
run: terraform fmt -check -recursive
27+
28+
- name: Setup TFLint
29+
uses: terraform-linters/setup-tflint@v4
30+
with:
31+
tflint_version: v0.53.0
32+
tflint_wrapper: false
33+
34+
- name: Init TFLint
35+
run: tflint --init --config .tflint.hcl
36+
37+
- name: Run TFLint
38+
run: tflint --config "$GITHUB_WORKSPACE/.tflint.hcl" --recursive
39+
40+
- name: Setup terraform-docs
41+
uses: jaxxstorm/action-install-gh-release@v2.1.0
42+
with:
43+
repo: terraform-docs/terraform-docs
44+
tag: v0.19.0
45+
46+
- name: Check docs are up to date
47+
run: |
48+
terraform-docs --config .terraform-docs.yaml .
49+
if ! git diff --exit-code README.md; then
50+
echo "::error::README.md is out of date. Run 'terraform-docs .' locally and commit."
51+
exit 1
52+
fi
53+
54+
validate:
55+
name: Validate (${{ matrix.target }})
56+
runs-on: ubuntu-latest
57+
strategy:
58+
fail-fast: false
59+
matrix:
60+
target:
61+
- root
62+
- examples/basic
63+
- examples/advanced
64+
- examples/ipam
65+
- examples/transit_gateway
66+
- examples/cloud_wan
67+
- examples/vpc_lattice
68+
steps:
69+
- name: Checkout
70+
uses: actions/checkout@v4
71+
72+
- name: Setup Terraform
73+
uses: hashicorp/setup-terraform@v3
74+
with:
75+
terraform_wrapper: false
76+
77+
- name: Terraform Init
78+
working-directory: ${{ matrix.target == 'root' && '.' || matrix.target }}
79+
run: terraform init -backend=false
80+
81+
- name: Terraform Validate
82+
working-directory: ${{ matrix.target == 'root' && '.' || matrix.target }}
83+
run: terraform validate

.header.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,63 @@ Terraform Plan:
247247
...
248248
```
249249

250+
# BYOIP (Bring Your Own IP) for NAT Gateway EIPs
251+
252+
You can control how Elastic IPs are sourced for NAT Gateways using the `nat_gateway_eip_configuration` variable. Three modes are available:
253+
254+
## Default (create)
255+
256+
When `nat_gateway_eip_configuration` is not set (or `mode = "create"`), EIPs are allocated from Amazon's default pool. This is the existing behaviour — no changes required for current users.
257+
258+
## BYOIP Pool
259+
260+
Allocate EIPs from a customer-owned public IPv4 address pool:
261+
262+
```hcl
263+
module "vpc" {
264+
source = "aws-ia/vpc/aws"
265+
version = ">= 4.6.0"
266+
267+
name = "byoip-vpc"
268+
cidr_block = "10.0.0.0/16"
269+
az_count = 3
270+
271+
subnets = {
272+
public = {
273+
netmask = 24
274+
nat_gateway_configuration = "all_azs"
275+
}
276+
private = {
277+
netmask = 24
278+
connect_to_public_natgw = true
279+
}
280+
}
281+
282+
nat_gateway_eip_configuration = {
283+
mode = "byoip_pool"
284+
public_ipv4_pool = "ipv4pool-ec2-xxxxxxxxxxxxxxxxx"
285+
}
286+
}
287+
```
288+
289+
## Existing EIPs
290+
291+
Use pre-allocated EIP allocation IDs (e.g., managed outside this module):
292+
293+
```hcl
294+
nat_gateway_eip_configuration = {
295+
mode = "existing"
296+
allocation_ids = {
297+
"us-east-1a" = "eipalloc-0123456789abcdef0"
298+
"us-east-1b" = "eipalloc-0123456789abcdef1"
299+
}
300+
}
301+
```
302+
303+
When `mode = "existing"`, the module does **not** create `aws_eip` resources — it attaches the provided allocation IDs directly to the NAT Gateways. Keys must match the AZ names where NAT Gateways will be deployed.
304+
305+
Credit: Inspired by community PR#179 ([@hminaee-tc](https://github.com/hminaee-tc)).
306+
250307
# Common Errors and their Fixes
251308

252309
## Error creating routes to Core Network
@@ -297,6 +354,28 @@ subnets = {
297354

298355
* Alternatively, you can also not configure any subnet route (`var.core_network_routes`) to the Core Network until the attachment gets accepted.
299356

357+
## Production Recommendation: Explicit `cidrs` over `netmask`
358+
359+
For production deployments, prefer explicit `cidrs` over calculated `netmask` to avoid subnet replacement on changes.
360+
361+
When using `netmask`, CIDRs are calculated positionally based on lexicographic ordering of subnet key names. Adding or removing a subnet type (e.g., adding `database = { netmask = 26 }`) can shift CIDRs assigned to existing subnets — causing Terraform to destroy and recreate them, resulting in downtime.
362+
363+
```hcl
364+
# ⚠️ Development only — CIDRs shift if you add/remove subnet types
365+
subnets = {
366+
private = { netmask = 24 }
367+
public = { netmask = 24 }
368+
}
369+
370+
# ✅ Production-safe — CIDRs are pinned regardless of key changes
371+
subnets = {
372+
private = { cidrs = ["10.0.0.0/24", "10.0.1.0/24", "10.0.2.0/24"] }
373+
public = { cidrs = ["10.0.3.0/24", "10.0.4.0/24", "10.0.5.0/24"] }
374+
}
375+
```
376+
377+
This is particularly important when using multiple private subnet roles (e.g., `private`, `isolated`, `database`) since alphabetical ordering determines CIDR allocation.
378+
300379
# Contributing
301380

302381
Please see our [developer documentation](https://github.com/aws-ia/terraform-aws-vpc/blob/main/contributing.md) for guidance on contributing to this module.

0 commit comments

Comments
 (0)