diff --git a/.gitignore b/.gitignore index 1a27768..863ca63 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,6 @@ state/ *.tfplan *.tfstate *.tfstate.backup + +# Test run files +spec/integration/test_runs/**/* diff --git a/CHANGELOG.md b/CHANGELOG.md index 2540dac..a0a8daa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,48 @@ ## Unreleased +BACKWARDS INCOMPATIBILITIES / NOTES: + +* `for_each` is used instead of `count` for creating resources for each + availability zone, so the availability zone will be used as the resource key, + not an index. + + As a consequence, if resources have been created with a + previous version of this module, they will need to be `moved` to avoid them + being destroyed and recreated. + + e.g. + + ```terraform + moved { + from = module.base-network.aws_subnet.public[0] + to = module.base-network.aws_subnet.public["eu-west-1a"] + } + + moved { + from = module.base-network.aws_subnet.private[0] + to = module.base-network.aws_subnet.private["eu-west-1a"] + } + + # etc.. + ``` + + +* The default value for the `private_subnets_offset` variable has been changed + from 0 to 128. This means that if the offsets are not provided, there will + be sufficient space between the private and public CIDR blocks such that new + availability_zones can be added without needing to destroy existing private + subnets. + +ENHANCEMENTS + +* As an alternative to the `availability_zones` variable, an + `availability_zone_configuration` variable is also supported, which takes a + list of objects with the keys `zone`, `public_subnet_cidr` and + `private_subnet_cidr`. This can be useful in cases where a new availability + zone is being added, but inference of the CIDR blocks could result in existing + subnets being destroyed and recreated, in which case the existing public and + private subnet CIDRs can be explicitly supplied to prevent this. + ## 5.1.0 (13th Feb 2023) ENHANCEMENTS diff --git a/defaults.tf b/defaults.tf index e25c0bb..fc8cef5 100644 --- a/defaults.tf +++ b/defaults.tf @@ -5,4 +5,27 @@ locals { private_subnets_offset = var.private_subnets_offset == null ? 0 : var.private_subnets_offset include_route53_zone_association = var.include_route53_zone_association == null ? "yes" : var.include_route53_zone_association include_nat_gateways = var.include_nat_gateways == null ? "yes" : var.include_nat_gateways + + # Validation: ensure only one of availability_zones or availability_zone_configurations is provided + _validate_az_input = ( + (var.availability_zones == null && var.availability_zone_configurations == null) || + (var.availability_zones != null && var.availability_zone_configurations != null) + ) ? tobool("ERROR: Exactly one of availability_zones or availability_zone_configurations must be specified.") : true + + # Normalize AZ configuration to a consistent format + # If availability_zone_configurations is provided, use it directly + # Otherwise, generate configurations from availability_zones list + az_configurations = var.availability_zone_configurations != null ? var.availability_zone_configurations : [ + for idx, az in var.availability_zones : { + zone = az + public_subnet_cidr = cidrsubnet(var.vpc_cidr, 8, idx + local.public_subnets_offset) + private_subnet_cidr = cidrsubnet(var.vpc_cidr, 8, idx + local.private_subnets_offset) + } + ] + + # Create a map keyed by AZ name for easy lookup in resources + az_map = { for config in local.az_configurations : config.zone => config } + + # List of AZ names for outputs and other references + availability_zones = [for config in local.az_configurations : config.zone] } diff --git a/examples/full/base_networking.tf b/examples/full/base_networking.tf index af4921a..e9dfc1a 100644 --- a/examples/full/base_networking.tf +++ b/examples/full/base_networking.tf @@ -4,9 +4,9 @@ module "base_networking" { component = var.component deployment_identifier = var.deployment_identifier - region = var.region + region = var.region availability_zones = var.availability_zones - vpc_cidr = var.vpc_cidr + vpc_cidr = var.vpc_cidr dependencies = ["other_vpc_1", "other_vpc_2"] diff --git a/examples/full/prerequisites.tf b/examples/full/prerequisites.tf index 2358614..0acf268 100644 --- a/examples/full/prerequisites.tf +++ b/examples/full/prerequisites.tf @@ -1,11 +1,11 @@ resource "aws_default_vpc" "default" {} module "dns_zones" { - source = "infrablocks/dns-zones/aws" + source = "infrablocks/dns-zones/aws" version = "2.0.0" - domain_name = var.domain_name - private_domain_name = var.domain_name - private_zone_vpc_id = aws_default_vpc.default.id + domain_name = var.domain_name + private_domain_name = var.domain_name + private_zone_vpc_id = aws_default_vpc.default.id private_zone_vpc_region = var.region } diff --git a/examples/full/terraform.tf b/examples/full/terraform.tf index 9631039..98aa83e 100644 --- a/examples/full/terraform.tf +++ b/examples/full/terraform.tf @@ -3,7 +3,7 @@ terraform { required_providers { aws = { - source = "hashicorp/aws" + source = "hashicorp/aws" version = "4.33" } } diff --git a/igw.tf b/igw.tf index 4bb0f9b..bcbb896 100644 --- a/igw.tf +++ b/igw.tf @@ -2,9 +2,9 @@ resource "aws_internet_gateway" "base_igw" { vpc_id = aws_vpc.base.id tags = { - Name = "igw-${var.component}-${var.deployment_identifier}" - Component = var.component + Name = "igw-${var.component}-${var.deployment_identifier}" + Component = var.component DeploymentIdentifier = var.deployment_identifier - Tier = "public" + Tier = "public" } } diff --git a/nat.tf b/nat.tf index 318b8df..65048cd 100644 --- a/nat.tf +++ b/nat.tf @@ -1,28 +1,28 @@ resource "aws_eip" "nat" { - count = local.include_nat_gateways == "yes" ? length(var.availability_zones) : 0 + for_each = local.include_nat_gateways == "yes" ? local.az_map : {} vpc = true tags = { - Name = "eip-nat-${var.component}-${var.deployment_identifier}-${element(var.availability_zones, count.index)}" - Component = var.component + Name = "eip-nat-${var.component}-${var.deployment_identifier}-${each.value.zone}" + Component = var.component DeploymentIdentifier = var.deployment_identifier } } resource "aws_nat_gateway" "base" { - count = local.include_nat_gateways == "yes" ? length(var.availability_zones) : 0 + for_each = local.include_nat_gateways == "yes" ? local.az_map : {} - allocation_id = element(aws_eip.nat.*.id, count.index) - subnet_id = element(aws_subnet.public.*.id, count.index) + allocation_id = aws_eip.nat[each.key].id + subnet_id = aws_subnet.public[each.key].id depends_on = [ aws_internet_gateway.base_igw ] tags = { - Name = "nat-${var.component}-${var.deployment_identifier}-${element(var.availability_zones, count.index)}" - Component = var.component + Name = "nat-${var.component}-${var.deployment_identifier}-${each.value.zone}" + Component = var.component DeploymentIdentifier = var.deployment_identifier } } diff --git a/outputs.tf b/outputs.tf index 191f666..5ee445f 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,59 +1,59 @@ output "vpc_id" { description = "The ID of the created VPC." - value = aws_vpc.base.id + value = aws_vpc.base.id } output "vpc_cidr" { description = "The CIDR of the created VPC." - value = aws_vpc.base.cidr_block + value = aws_vpc.base.cidr_block } output "availability_zones" { description = "The availability zones in which subnets were created." - value = var.availability_zones + value = local.availability_zones } output "number_of_availability_zones" { description = "The number of populated availability zones available." - value = length(var.availability_zones) + value = length(local.availability_zones) } output "public_subnet_ids" { description = "The IDs of the public subnets." - value = aws_subnet.public.*.id + value = [for az in local.availability_zones : aws_subnet.public[az].id] } output "public_subnet_cidr_blocks" { description = "The CIDRs of the public subnets." - value = aws_subnet.public.*.cidr_block + value = [for az in local.availability_zones : aws_subnet.public[az].cidr_block] } output "public_route_table_ids" { description = "The IDs of the public route tables." - value = aws_route_table.public.*.id + value = [for az in local.availability_zones : aws_route_table.public[az].id] } output "private_subnet_ids" { description = "The IDs of the private subnets." - value = aws_subnet.private.*.id + value = [for az in local.availability_zones : aws_subnet.private[az].id] } output "private_subnet_cidr_blocks" { description = "The CIDRs of the private subnets." - value = aws_subnet.private.*.cidr_block + value = [for az in local.availability_zones : aws_subnet.private[az].cidr_block] } output "private_route_table_ids" { description = "The IDs of the private route tables." - value = aws_route_table.private.*.id + value = [for az in local.availability_zones : aws_route_table.private[az].id] } output "nat_public_ips" { description = "The EIPs attached to the NAT gateways." - value = aws_eip.nat.*.public_ip + value = local.include_nat_gateways == "yes" ? [for az in local.availability_zones : aws_eip.nat[az].public_ip] : [] } output "internet_gateway_id" { description = "The ID of IGW attached to the VPC." - value = aws_internet_gateway.base_igw.id + value = aws_internet_gateway.base_igw.id } diff --git a/private_subnets.tf b/private_subnets.tf index 6156a97..9ce9f5c 100644 --- a/private_subnets.tf +++ b/private_subnets.tf @@ -1,38 +1,42 @@ resource "aws_subnet" "private" { - vpc_id = aws_vpc.base.id - count = length(var.availability_zones) - cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index + length(var.availability_zones) + local.private_subnets_offset) - availability_zone = element(var.availability_zones, count.index) + for_each = local.az_map + + vpc_id = aws_vpc.base.id + cidr_block = each.value.private_subnet_cidr + availability_zone = each.value.zone tags = { - Name = "private-subnet-${var.component}-${var.deployment_identifier}-${element(var.availability_zones, count.index)}" - Component = var.component + Name = "private-subnet-${var.component}-${var.deployment_identifier}-${each.value.zone}" + Component = var.component DeploymentIdentifier = var.deployment_identifier - Tier = "private" + Tier = "private" } } resource "aws_route_table" "private" { + for_each = local.az_map + vpc_id = aws_vpc.base.id - count = length(var.availability_zones) tags = { - Name = "private-routetable-${var.component}-${var.deployment_identifier}-${element(var.availability_zones, count.index)}" - Component = var.component + Name = "private-routetable-${var.component}-${var.deployment_identifier}-${each.value.zone}" + Component = var.component DeploymentIdentifier = var.deployment_identifier - Tier = "private" + Tier = "private" } } resource "aws_route" "private_internet" { - count = local.include_nat_gateways == "yes" ? length(var.availability_zones) : 0 - route_table_id = element(aws_route_table.private.*.id, count.index) - nat_gateway_id = element(aws_nat_gateway.base.*.id, count.index) + for_each = local.include_nat_gateways == "yes" ? local.az_map : {} + + route_table_id = aws_route_table.private[each.key].id + nat_gateway_id = aws_nat_gateway.base[each.key].id destination_cidr_block = "0.0.0.0/0" } resource "aws_route_table_association" "private" { - count = length(var.availability_zones) - subnet_id = element(aws_subnet.private.*.id, count.index) - route_table_id = element(aws_route_table.private.*.id, count.index) + for_each = local.az_map + + subnet_id = aws_subnet.private[each.key].id + route_table_id = aws_route_table.private[each.key].id } diff --git a/public_subnets.tf b/public_subnets.tf index e989be0..f1500a5 100644 --- a/public_subnets.tf +++ b/public_subnets.tf @@ -1,38 +1,42 @@ resource "aws_subnet" "public" { - vpc_id = aws_vpc.base.id - count = length(var.availability_zones) - cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index + local.public_subnets_offset) - availability_zone = element(var.availability_zones, count.index) + for_each = local.az_map + + vpc_id = aws_vpc.base.id + cidr_block = each.value.public_subnet_cidr + availability_zone = each.value.zone tags = { - Name = "public-subnet-${var.component}-${var.deployment_identifier}-${element(var.availability_zones, count.index)}" - Component = var.component + Name = "public-subnet-${var.component}-${var.deployment_identifier}-${each.value.zone}" + Component = var.component DeploymentIdentifier = var.deployment_identifier - Tier = "public" + Tier = "public" } } resource "aws_route_table" "public" { + for_each = local.az_map + vpc_id = aws_vpc.base.id - count = length(var.availability_zones) tags = { - Name = "public-routetable-${var.component}-${var.deployment_identifier}-${element(var.availability_zones, count.index)}" - Component = var.component + Name = "public-routetable-${var.component}-${var.deployment_identifier}-${each.value.zone}" + Component = var.component DeploymentIdentifier = var.deployment_identifier - Tier = "public" + Tier = "public" } } resource "aws_route" "public_internet" { - count = length(var.availability_zones) - route_table_id = element(aws_route_table.public.*.id, count.index) - gateway_id = aws_internet_gateway.base_igw.id + for_each = local.az_map + + route_table_id = aws_route_table.public[each.key].id + gateway_id = aws_internet_gateway.base_igw.id destination_cidr_block = "0.0.0.0/0" } resource "aws_route_table_association" "public" { - count = length(var.availability_zones) - subnet_id = element(aws_subnet.public.*.id, count.index) - route_table_id = element(aws_route_table.public.*.id, count.index) + for_each = local.az_map + + subnet_id = aws_subnet.public[each.key].id + route_table_id = aws_route_table.public[each.key].id } diff --git a/spec/integration/availability_zone_addition_spec.rb b/spec/integration/availability_zone_addition_spec.rb new file mode 100644 index 0000000..a98200f --- /dev/null +++ b/spec/integration/availability_zone_addition_spec.rb @@ -0,0 +1,207 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'json' + +# TODO +# extract function for executing terraform + +INITIAL_AVAILABILITY_ZONES = %w[eu-west-1a eu-west-1b].freeze +UPDATED_AVAILABILITY_ZONES = %w[eu-west-1a eu-west-1b eu-west-1c].freeze + +COMPONENT = 'test-component' +DEPLOYMENT_IDENTIFIER = 'test-deployment' +VPC_CIDR = '10.0.0.0/16' +REGION = 'eu-west-1' + +describe 'availability zone addition' do + describe 'adding a new availability zone' do + let(:initial_state) { @initial_state } + let(:resource_changes) { @resource_changes } + + before(:all) do + @test_dir = make_test_run_dir + + # Apply initial availability zones + apply_availability_zones(@test_dir, INITIAL_AVAILABILITY_ZONES) + Dir.chdir(@test_dir) do + @initial_state = get_terraform_state('applied.json') + end + + # Run plan with additional availability zone + plan_output = plan_with_azs(@test_dir, UPDATED_AVAILABILITY_ZONES) + plan_json = JSON.parse(plan_output) + @resource_changes = plan_json['resource_changes'] || [] + end + + after(:all) do + # Cleanup: destroy all resources created during the test + if @test_dir && Dir.exist?(@test_dir) + Dir.chdir(@test_dir) do + terraform_exec = from_root_directory('vendor/terraform/bin/terraform') + system("#{terraform_exec} destroy -auto-approve") + end + end + end + + it 'does not destroy existing subnets when adding new availability zone' do + # Get the initial subnet IDs + resource_ids = gather_resource_ids(initial_state) + + # Find any destroy actions for our existing resources + destroyed_resources = resource_changes.select do |change| + before_id = change.dig('change', 'before', 'id') + change['change']['actions'].include?('delete') && + (resource_ids['public_subnets'].values.include?(before_id) || + resource_ids['private_subnets'].values.include?(before_id) || + resource_ids['nat_gateways'].values.include?(before_id) || + resource_ids['eips'].values.include?(before_id)) + end + + # Assert no existing resources are being destroyed + destroyed_resource_str = destroyed_resources.map do |r| + "#{r['type']}.#{r['name']}" + end.join(', ') + expect(destroyed_resources).to( + be_empty, + 'Expected no resources to be destroyed, ' \ + "but found: #{destroyed_resource_str}" + ) + end + + it 'creates resources for new availability zone' do + # Check that only new resources are being created + created_resources = resource_changes.select do |change| + change['change']['actions'].include?('create') && + %w[aws_subnet aws_route_table aws_route_table_association aws_route + aws_nat_gateway aws_eip].include?(change['type']) + end + + # We expect exactly 1 new public subnet, 1 new private subnet, + # 2 new route tables, 2 new route table associations, + # 1 new NAT gateway, and 1 new EIP for the new AZ + expected_new_resources = { + 'aws_subnet' => 2, # 1 public + 1 private + 'aws_route_table' => 2, # 1 for public + 1 for private + 'aws_route_table_association' => 2, # 1 for public + 1 for private + # 1 for public internet route + 1 for private NAT route + 'aws_route' => 2, + 'aws_nat_gateway' => 1, + 'aws_eip' => 1 + } + + actual_new_resources = created_resources.group_by { |r| r['type'] } + .transform_values(&:count) + + expected_new_resources.each do |resource_type, expected_count| + actual_count = actual_new_resources[resource_type] || 0 + expect(actual_count).to( + eq(expected_count), + "Expected #{expected_count} new #{resource_type} resources, " \ + "but found #{actual_count}" + ) + end + end + end + + private + + def make_test_run_dir + dir = "spec/integration/test_runs/#{Time.now.to_i}" + FileUtils.mkdir_p(dir) + dir + end + + def apply_availability_zones(terraform_dir, availability_zones) + terraform_exec = from_root_directory('vendor/terraform/bin/terraform') + + # Write the terraform configuration + File.write("#{terraform_dir}/main.tf", + generate_terraform_config(availability_zones)) + + # Initialize and apply + Dir.chdir(terraform_dir) do + init_result = system("#{terraform_exec} init") + raise 'Terraform init failed' unless init_result + + apply_result = system("#{terraform_exec} apply -auto-approve") + raise 'Terraform apply failed' unless apply_result + end + end + + def get_terraform_state(state_file) + terraform_exec = from_root_directory('vendor/terraform/bin/terraform') + state_json = `#{terraform_exec} show -json` + File.write(state_file, state_json) + JSON.parse(state_json) + end + + def plan_with_azs(terraform_dir, availability_zones) + terraform_exec = from_root_directory('vendor/terraform/bin/terraform') + # Update the configuration with new AZs + File.write("#{terraform_dir}/main.tf", + generate_terraform_config(availability_zones)) + + # Run plan and capture output + Dir.chdir(terraform_dir) do + `#{terraform_exec} plan -out=tfplan -json` + `#{terraform_exec} show -json tfplan > tfplan.json` + `cat tfplan.json` + end + end + + def generate_terraform_config(availability_zones) + <<~HCL + terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.0" + } + } + } + + provider "aws" { + region = "#{REGION}" + } + + module "base_networking" { + source = "#{from_root_directory('')}" + + vpc_cidr = "#{VPC_CIDR}" + region = "#{REGION}" + availability_zones = #{availability_zones.inspect} + component = "#{COMPONENT}" + deployment_identifier = "#{DEPLOYMENT_IDENTIFIER}" + include_route53_zone_association = "no" + } + HCL + end + + def from_root_directory(dir) + "../../../../#{dir}" + end + + def gather_resource_ids(state) + { + public_subnets: get_resource_ids(state, 'aws_subnet', 'public'), + private_subnets: get_resource_ids(state, 'aws_subnet', 'private'), + nat_gateways: get_resource_ids(state, 'aws_nat_gateway', 'base'), + eips: get_resource_ids(state, 'aws_eip', 'nat') + } + end + + def get_resource_ids(state, resource_type, resource_name) + resources = state['values']['root_module']['child_modules'] + &.first&.[]('resources') || [] + + matching_resources = resources.select do |r| + r['type'] == resource_type && r['name'] == resource_name + end + + matching_resources.to_h do |r| + # For for_each resources, use the index key (AZ name) as the key + [r['index'].to_s, r['values']['id']] + end + end +end diff --git a/spec/unit/infra/prerequisites/main.tf b/spec/unit/infra/prerequisites/main.tf index 2358614..0acf268 100644 --- a/spec/unit/infra/prerequisites/main.tf +++ b/spec/unit/infra/prerequisites/main.tf @@ -1,11 +1,11 @@ resource "aws_default_vpc" "default" {} module "dns_zones" { - source = "infrablocks/dns-zones/aws" + source = "infrablocks/dns-zones/aws" version = "2.0.0" - domain_name = var.domain_name - private_domain_name = var.domain_name - private_zone_vpc_id = aws_default_vpc.default.id + domain_name = var.domain_name + private_domain_name = var.domain_name + private_zone_vpc_id = aws_default_vpc.default.id private_zone_vpc_region = var.region } diff --git a/spec/unit/infra/prerequisites/provider.tf b/spec/unit/infra/prerequisites/provider.tf index 66428ae..dc58d9a 100644 --- a/spec/unit/infra/prerequisites/provider.tf +++ b/spec/unit/infra/prerequisites/provider.tf @@ -1,3 +1,3 @@ provider "aws" { - region = var.region + region = var.region } diff --git a/spec/unit/infra/prerequisites/terraform.tf b/spec/unit/infra/prerequisites/terraform.tf index 9631039..98aa83e 100644 --- a/spec/unit/infra/prerequisites/terraform.tf +++ b/spec/unit/infra/prerequisites/terraform.tf @@ -3,7 +3,7 @@ terraform { required_providers { aws = { - source = "hashicorp/aws" + source = "hashicorp/aws" version = "4.33" } } diff --git a/spec/unit/infra/root/main.tf b/spec/unit/infra/root/main.tf index e35a7a2..25e3d5c 100644 --- a/spec/unit/infra/root/main.tf +++ b/spec/unit/infra/root/main.tf @@ -9,19 +9,19 @@ data "terraform_remote_state" "prerequisites" { module "base_network" { source = "../../../.." - vpc_cidr = var.vpc_cidr - region = var.region + vpc_cidr = var.vpc_cidr + region = var.region availability_zones = var.availability_zones - public_subnets_offset = var.public_subnets_offset + public_subnets_offset = var.public_subnets_offset private_subnets_offset = var.private_subnets_offset - component = var.component + component = var.component deployment_identifier = var.deployment_identifier - dependencies = var.dependencies + dependencies = var.dependencies private_zone_id = data.terraform_remote_state.prerequisites.outputs.private_zone_id include_route53_zone_association = var.include_route53_zone_association - include_nat_gateways = var.include_nat_gateways + include_nat_gateways = var.include_nat_gateways } diff --git a/spec/unit/infra/root/terraform.tf b/spec/unit/infra/root/terraform.tf index 9631039..98aa83e 100644 --- a/spec/unit/infra/root/terraform.tf +++ b/spec/unit/infra/root/terraform.tf @@ -3,7 +3,7 @@ terraform { required_providers { aws = { - source = "hashicorp/aws" + source = "hashicorp/aws" version = "4.33" } } diff --git a/spec/unit/infra/root/variables.tf b/spec/unit/infra/root/variables.tf index f732ca5..7cf0058 100644 --- a/spec/unit/infra/root/variables.tf +++ b/spec/unit/infra/root/variables.tf @@ -8,16 +8,16 @@ variable "component" {} variable "deployment_identifier" {} variable "public_subnets_offset" { - type = number + type = number default = null } variable "private_subnets_offset" { - type = number + type = number default = null } variable "dependencies" { - type = list(string) + type = list(string) default = null } diff --git a/variables.tf b/variables.tf index e48a48a..8187ea4 100644 --- a/variables.tf +++ b/variables.tf @@ -1,55 +1,74 @@ variable "vpc_cidr" { - type = string + type = string description = "The CIDR to use for the VPC." } variable "region" { - type = string + type = string description = "The region into which to deploy the VPC." } variable "availability_zones" { - type = list(string) - description = "The availability zones for which to add subnets." + type = list(string) + description = "The availability zones for which to add subnets. Mutually exclusive with availability_zone_configurations." + default = null +} + +variable "availability_zone_configurations" { + type = list(object({ + zone = string + public_subnet_cidr = string + private_subnet_cidr = string + })) + description = <<-DESC + Explicit availability zone configurations with CIDR blocks. Mutually exclusive with availability_zones. + Use this to specify exact CIDR blocks for each subnet, allowing you to add new AZs without + changing existing subnet CIDR allocations. Example: [{ + zone = "us-east-1a" + public_subnet_cidr = "10.0.0.0/24" + private_subnet_cidr = "10.0.10.0/24" + }] + DESC + default = null } variable "component" { - type = string + type = string description = "The component this network will contain." } variable "deployment_identifier" { - type = string + type = string description = "An identifier for this instantiation." } variable "dependencies" { description = "A comma separated list of components depended on my this component." - type = list(string) - default = [] + type = list(string) + default = [] } variable "public_subnets_offset" { description = "The number of /24s to offset the public subnets in the VPC CIDR." - type = number - default = 0 + type = number + default = 0 } variable "private_subnets_offset" { description = "The number of /24s to offset the private subnets in the VPC CIDR." - type = number - default = 0 + type = number + default = 128 } variable "include_route53_zone_association" { description = "Whether or not to associate the VPC with a zone id (\"yes\" or \"no\")." - type = string - default = "yes" + type = string + default = "yes" } variable "private_zone_id" { description = "The ID of the private Route 53 zone." - type = string - default = null + type = string + default = null } variable "include_nat_gateways" { description = "Whether or not to deploy NAT gateways in each availability zone for outbound Internet connectivity (\"yes\" or \"no\")." - type = string - default = "yes" + type = string + default = "yes" } diff --git a/vpc.tf b/vpc.tf index a87c287..ac289eb 100644 --- a/vpc.tf +++ b/vpc.tf @@ -1,17 +1,17 @@ resource "aws_vpc" "base" { - cidr_block = var.vpc_cidr + cidr_block = var.vpc_cidr enable_dns_hostnames = true tags = { - Name = "vpc-${var.component}-${var.deployment_identifier}" - Component = var.component + Name = "vpc-${var.component}-${var.deployment_identifier}" + Component = var.component DeploymentIdentifier = var.deployment_identifier - Dependencies = join(",", local.dependencies) + Dependencies = join(",", local.dependencies) } } resource "aws_route53_zone_association" "base" { - count = local.include_route53_zone_association == "yes" ? 1 : 0 + count = local.include_route53_zone_association == "yes" ? 1 : 0 zone_id = var.private_zone_id - vpc_id = aws_vpc.base.id + vpc_id = aws_vpc.base.id }