To avoid creating multiple aws_route resources. I am trying to add multiple destination_cidr_block from a map to multiple route tables. I think I am in the right direction, however, it is only adding a few cidr blocks from the list to each route table and not all cidr blocks to each route table.
variable "destination_cidr_block" {
type = map
default = {
destination_cidr_block = {
private = [
"0.0.0.0/0",
"0.0.0.0/0",
"0.0.0.0/0",
"0.0.0.0/0",]
private1 = [
"0.0.0.0/0",
"0.0.0.0/0"]
resource "aws_route" "private" {
count = local.length_of_rt_cnt
route_table_id = element(module.private.private_route_tables_id, count.index)
destination_cidr_block = element(var.destination_cidr_block["private1"], count.index)
gateway_id = module.vpc.id
}
How can I get all routes from private1 to the the multiple route tables that are already created from this module.
I apologize, everything has been destroyed and I did not saved the error. I know accomplishing multiple route tables with on destination cidr block which would look like this.
resource "aws_route" "private" {
count = local.length_of_rt_cnt
route_table_id = element(module.private.private_route_tables_id, count.index)
destination_cidr_block = 0.0.0.0/0
gateway_id = module.vpc.id
}
In this case 4 route tables will receive this cidr block. Now the question is how can I add a list of cidr block to a list of route tables
Related
I try to create nat gateway on terraform, on each public subnets that I created.
I create the public subntes like that:
resource "aws_subnet" "public_subnet" {
count = length(var.vpc.public_subnets)
vpc_id = aws_vpc.vpc.id
availability_zone = var.vpc.public_subnets[count.index].availability_zone
cidr_block = var.vpc.public_subnets[count.index].cidr_block
tags = var.vpc.public_subnets[count.index].tags
}
I create all elastic ip like that:
resource "aws_eip" "eip" {
for_each = { for eip in var.vpc.eip : eip.name => eip }
vpc = true
tags = each.value.tags
}
And finally I have a resource block to create 3 nat gateways. Each nat gateway have to use a subnet and an eip:
resource "aws_nat_gateway" "ngw" {
count = length(var.vpc.public_subnets)
allocation_id = element(aws_eip.eip.*.allocation_id, count.index)
subnet_id = element(aws_subnet.public_subnet.*.id, count.index)
}
results ==> This object does not have an attribute named "allocation_id"
How should I iterate over 2 resources to create the nat gateay for each pair of subnet/eip ?
thanks.
Since you are using for_each for eip it will be a map, not a list. Thus to access its values you can use values:
allocation_id = element(values(aws_eip.eip)[*].allocation_id, count.index)
I need help with the following error on Terraform, when i ran terraform apply, everything seemed to have worked when I checked aws console but then I get the following error at the end:
Error: error reading Main Route Table Association (subnet-09b6d028942d15d8e): empty result
│
│ with aws_main_route_table_association.a,
│ on main.tf line 55, in resource "aws_main_route_table_association" "a":
│ 55: resource "aws_main_route_table_association" "a"{
The below is the code for the route table portion
#3. create custom route table
resource "aws_route_table" "prod-route-table" {
vpc_id = aws_vpc.prod-vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.gw.id
}
route {
ipv6_cidr_block = "::/0"
gateway_id = aws_internet_gateway.gw.id
}
tags = {
Name = "Prod"
}
}
This is the associate subnet with route table
#5. associate subnet with route table
resource "aws_main_route_table_association" "a"{
vpc_id = aws_subnet.subnet-1.id
route_table_id = aws_route_table.prod-route-table.id
}
This is the subnet portion
#4. create a subnet
resource "aws_subnet" "subnet-1" {
vpc_id = aws_vpc.prod-vpc.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-east-1a"
tags = {
Name = "Prod-subnet"
}
}
Your help will be kindly appreciated. What am i doing wrong?
Thank you.
egress_only_gateway_id applies to only aws_egress_only_internet_gateway, not to aws_internet_gateway. So you have to create aws_egress_only_internet_gateway.
You're setting the attribute egress_only_gateway_id to an internet gateway resource, while it must be using an egress internet gateway resource [1].
References:
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/egress_only_internet_gateway
I am new to terraform development, trying to create simple loop of variable that can be used later, some thing like below:
This perfectly worked for me and creates two subnet as expected.
variable "availability_zones" {
description = "Available Availability Zones"
type = "list"
default = [ "us-east-1a", "us-east-1b" ]
}
variable "public_subnet_cidr" {
description = "CIDR for Public Subnets"
type = "list"
default = [ "10.240.32.0/26", "10.240.32.64/26" ]
# Define Public Subnet
resource "aws_subnet" "public-subnets" {
count = 2
vpc_id = "${aws_vpc.default.id}"
cidr_block = "${element(var.public_subnet_cidr, count.index)}"
availability_zone = "${element(var.availability_zones, count.index)}"
tags {
Name = "${element(var.availability_zones, count.index)}_${element(var.public_subnet_cidr, count.index)}"
}
}
But while trying to associate those subnets to default route, I am not able to figure out how to fetch individual subnet id from those subnets created earlier. And ended up with below code. Is there a way to fetch subnet.id of individual subnets?
# Assign Default Public Route Table to Public Subnet
resource "aws_route_table_association" "default_public_route" {
subnet_id = "${aws_subnet.public-subnets.id}" <<-- This is the line I am trying to figure out
route_table_id = "${aws_route_table.default_public_route_table.id}"
}
Thanks in advance.
Sam
You're close on how to use it. Here's a walk through that can help you.
resource "aws_route_table_association" "default_public_route" {
count = 2
subnet_id = "${element(aws_subnet.public-subnets.*.id, count.index)}"
route_table_id = "${aws_route_table.default_public_route_table.id}"
}
When you create an AWS VPC in terraform, it will be assigned a default route table that will route traffic just within the CIDR block of the VPC.
I want to add a default route to this to send all other traffic to the Internet.
This can be done by using the aws_route to add the default route to the existing VPC route table. For example:
resource "aws_vpc" "vpc" {
cidr_block = "${var.classb}.0.0/16"
}
resource "aws_intenet_gateway" "ig" {
vpc_id = "${aws_vpc.vpc.id}"
}
resource "aws_route" "simulation_default_route" {
route_table_id = "${aws_vpc.vpc.default_route_table_id}"
destination_cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.ig.id}"
}
This should also work if you prefer to use route table way.
resource "aws_default_route_table" "rtb-default" {
default_route_table_id = aws_vpc.main.default_route_table_id
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.ngw-main.id
}
}
Using terraform-0.7.7. I'm following, more or less, the Best Practices repo, the AWS part:
https://github.com/hashicorp/best-practices/tree/master/terraform
I am trying to come up with a general template for building VPCs. The idea is to have a network module with several sub-modules (vpc, private_subnet, etc), and just plug into it different variables from terraform.tfvars files, in order to build different environments.
Let's say in the .tfvars file for one environment I have a list of availability zones, and another list with the IP blocks for the private subnets:
azs = "us-west-2a,us-west-2b,us-west-2c"
private_subnets = "10.XXX.1.0/24,10.XXX.2.0/24,10.XXX.3.0/24"
The network/private_subnets module will happily create subnets, route tables, and associations based on those lists:
resource "aws_subnet" "private" {
vpc_id = "${var.vpc_id}"
cidr_block = "${element(split(",", var.cidrs), count.index)}"
availability_zone = "${element(split(",", var.azs), count.index)}"
count = "${length(split(",", var.cidrs))}"
tags { Name = "${var.name}-${element(split(",", var.azs), count.index)}-private" }
lifecycle { create_before_destroy = true }
}
resource "aws_route_table" "private" {
vpc_id = "${var.vpc_id}"
count = "${length(split(",", var.cidrs))}"
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = "${element(split(",", var.nat_gateway_ids), count.index)}"
}
tags { Name = "${var.name}-${element(split(",", var.azs), count.index)}-private" }
lifecycle { create_before_destroy = true }
}
resource "aws_route_table_association" "private" {
count = "${length(split(",", var.cidrs))}"
subnet_id = "${element(aws_subnet.private.*.id, count.index)}"
route_table_id = "${element(aws_route_table.private.*.id, count.index)}"
lifecycle { create_before_destroy = true }
}
That works well. For each environment, I have different azs and private_subnets lists, and the VPC is created correctly. The NAT gateways are created prior to that in a different module. I have one NAT gateway, one private subnet, and one private routing table, per AZ.
But now I'm trying to create VPC peering connections in the same way.
peer_vpc_ids = "vpc-XXXXXXXX, vpc-YYYYYYYY"
peer_vpc_blocks = "10.XXX.0.0/16, 10.YYY.0.0/16"
So now I need to write Terraform code that goes into the private route tables and adds routes for each VPC peering connection.
The problem is, I need to iterate by two variables: the list of AZs, and the list of peering connections, and Terraform does not seem to allow that. AFAICT, you cannot do nested loops in Terraform.
Am I missing something? Is there a better way to solve this problem?
Of course I could write by hand some custom spaghetti code that would build the VPC no matter what, but the goal here is to keep the code composable and maintainable, and separate the logic from the attributes.
You can potentially achieve this with some math on the element interpolation method:
resource "aws_vpc_peering_connection" {
peer_vpc_ids = "${element(var.vpc_ids, count.index)}"
peer_vpc_blocks = "${element(var.vpc_blocks,floor(count.index / length(var.vpc_ids))}"
count = "${length(var.vpc_ids) * length(var.vpc_blocks)}"
}
Specifically the element(var.vpc_blocks,floor(count.index / length(var.vpc_ids)) call will make VPC blocks increment 1 for each of the var.vpc_ids values.