terraform do not get variable passed through modules - terraform

I want to provision a simple terraform vpc and subnet.
I created a module and declared all the variable required in the module variable.tf
and passed wrote all the needed values through terraform.tfvars
but when I run terraform apply I get a prompt to insert a value for avail_zone
main.tf
module "myapp-subnet" {
source = "./modules/subnet"
subnet_cidr_block = var.subnet_cidr_block
avail_zone = "us-east-1a"
env_prefix = "dev"
vpc_id = aws_vpc.myapp-vpc.id
default_route_table_id = aws_vpc.myapp-vpc.default_route_table_id
}
modules/subnet/main.tf
resource "aws_subnet" "myapp-subnet-1" {
vpc_id = var.vpc_id
cidr_block = var.subnet_cidr_block
availability_zone = var.avail_zone
tags = {
Name: "${var.env_prefix}-subnet-1"
}
}
resource "aws_internet_gateway" "myapp-igw"{
vpc_id = var.vpc_id
tags = {
Name: "${var.env_prefix}-igw"
}
}
# using existing route table
resource "aws_default_route_table" "default-rtb" {
default_route_table_id = var.default_route_table_id
route{
cidr_block = "0.0.0.0/10"
gateway_id = aws_internet_gateway.myapp-igw.id
}
tags = {
Name: "${var.env_prefix}-main-rtb"
}
}
module/subnet/variables.tf
variable vpc_cidr_blocks {}
variable subnet_cidr_block {}
variable avail_zone {}
variable env_prefix{}
variable vpc_id {}
variable default_route_table_id {}
terraform.tfvars
vpc_cidr_blocks = "xxxx"
subnet_cidr_block = "xxxx"
avail_zone = "xxxxxx"
env_prefix = "dev"
myip = "xxxxxxx"
instance_type="t2.micro"
public_key_location= "/home/xxxxxxxx/.ssh/id_rsa.pub"

Related

Terraform how to access resource local name as a variable inside the resource block itself

resource "aws_subnet" "goodsubnet" {
vpc_id = "VPCID"
cidr_block = "x.x.x.x/x"
availability_zone = "xyz"
tags =
{
tagname1 = "$something"
}
}
I want the tag "tagname1" to dynamically have the value of the resource local name i.e "goodsubnet" Is there a variable I can use?
Thanks
That is not possible the way you want to do it. However, Terraform has a concept of variables, which you can use to assign values to arguments. That could be either a local value [1] or an input variable [2]. For example, an input variable definition:
variable "subnet_name_tag" {
type = string
description = "Tag name for a subnet."
}
Then, in your code you would do:
resource "aws_subnet" "goodsubnet" {
vpc_id = "VPCID"
cidr_block = "x.x.x.x/x"
availability_zone = "xyz"
tags =
{
tagname1 = var.subnet_name_tag
}
}
Alternatively, you could define a local value:
locals {
subnet_tag_name = "goodsubnet"
}
Followed by:
resource "aws_subnet" "goodsubnet" {
vpc_id = "VPCID"
cidr_block = "x.x.x.x/x"
availability_zone = "xyz"
tags =
{
tagname1 = local.subnet_name_tag
}
}
[1] https://developer.hashicorp.com/terraform/language/values/locals
[2] https://developer.hashicorp.com/terraform/language/values/variables

Modules and Variables carrying over tfvar values

I am fairly new to TF and I have written some basic code. Enough to get a vpc up and running and add some subnets and deploy a simple ec2. I am starting to get to the point of wanting to use modules. I struggle with the "keeping generic" thing so I can reuse them over and over. I do not understand how values get passed into modules. For instance I have a module that deploys a vpc, within the same project I have a module that deploys a vpc endpoint. The questions becomes how do i get the value of the vpc_id created with vpc module into the vpc endpoint module? Does anyone have an example of this?
main.tf
provider "aws" {
region = var.aws_region
}
/*Module for VPC creation*/
module "vpc" {
source = "./modules/vpc"
vpc_cidr = var.vpc_cidr
environment = var.environment
tnt_public_subnets_cidr = var.tnt_public_subnets_cidr
availability_zones = var.availability_zones
}
/*Module for EC2 Webserver creation*/
module "webserver" {
source = "./modules/ec2/webserver"
count = var.instance_count
environment = var.environment
subnet_id = module.vpc.tnt_public_subnets_cidr.id
}
/*Module for VPC endpoint creation*/
module "s3-vpce"{
source = "git::https://github.com/tn-sts-cloudtn/sts-terraform-
modules.git//s3-vpce-module/modules//s3-vpce"
vpc_id = module.vpc.vpc_id
}
VPC Module TF File:
/*==== The VPC ======*/
resource "aws_vpc" "vpc" {
cidr_block = var.vpc_cidr
assign_generated_ipv6_cidr_block = true
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "${var.environment}_vpc"
Environment = var.environment
}
}
/*==== Internet Gateway for Public Subnets ======*/
/* Internet gateway for the public subnet */
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.vpc.id
tags = {
Name = "${var.environment}_igw"
Environment = var.environment
}
}
/* Elastic IP for NAT
resource "aws_eip" "instance_eip" {
count = 1
vpc = true
depends_on = [aws_internet_gateway.tnt_igw]
tags ={
Name = "sts_net_infra-mgmt_eip${count.index + 1}"
Environment = var.environment
}
}*/
/* Public subnet */
resource "aws_subnet" "public_subnets_cidr" {
vpc_id = aws_vpc.vpc.id
count = length(var.availability_zones)
cidr_block = var.public_subnets_cidr [count.index]
availability_zone = element(var.availability_zones, count.index)
map_public_ip_on_launch = true
tags ={
Name = "${var.environment}_mgmt_subnet_${count.index + 1}"
Environment = var.environment
}
}
/* Private subnet
resource "aws_subnet" "tnt_private_subnet" {
vpc_id = aws_vpc.tnt_vpc.id
count = length(var.tnt_private_subnets_cidr)
cidr_block = var.tnt_public_subnets_cidr [count.index]
availability_zone = element(var.availability_zones, count.index)
map_public_ip_on_launch = false
tags = {
#Name = var.environment-private-subnet
Environment = var.environment
}
*/
/* Routing table for private subnet
resource "aws_route_table" "tnt_private_rtb" {
vpc_id = aws_vpc.tnt_vpc.id
tags = {
Name = var.environment_private_route_table
Environment = var.environment
}
}*/
/* Routing table for public subnet */
resource "aws_route_table" "public_rtb" {
vpc_id = aws_vpc.vpc.id
tags = {
Name = "${var.environment}_public_route_table"
Environment = var.environment
}
}
resource "aws_route" "public_internet_gateway" {
route_table_id = aws_route_table.public_rtb.id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
/* Route table associations */
resource "aws_route_table_association" "public" {
count = length(var.public_subnets_cidr)
subnet_id = element(aws_subnet.public_subnets_cidr.*.id, count.index)
route_table_id = aws_route_table.public_rtb.id
}
So I need to output the VPC ID for the VPC endpoint, so I tried to use an output.
output.tf
output "vpc_cidr" {
value = aws_vpc.tnt_vpc.id
}
output "tnt_public_subnets_cidr"{
value = aws_subnet.tnt_public_subnets_cidr.*.id
}
output "vpc_id" {
description = "The ID of the VPC"
value = aws_vpc.vpc.id
}
output "vpc_arn" {
description = "The ARN of the VPC"
value = concat(aws_vpc.tnt_vpc.*.arn, [""])[0]
}
I know I am doing it incorrectly, but I am struggling to understand how outputs flow from module to module.
You can use one moule output into onether module by defining output in each module.

Is it possible to reference the resource name inside the resource itself

I'd like to use a resource name inside the resource itself to avoid string duplication and copy/paste errors.
resource "aws_instance" "bastion-euw3-infra-01" {
ami = "ami-078db6d55a16afc82"
instance_type = "t2.micro"
key_name = "sylvain"
user_data = templatefile("./scripts/cloudinit.yaml", {
hostname = "bastion-euw3-infra-01"
tailscale_authkey = var.tailscale_authkey
})
network_interface {
device_index = 0
network_interface_id = aws_network_interface.bastion-euw3-infra-01.id
}
tags = {
Name = "bastion-euw3-infra-01"
Environment = "infra"
}
lifecycle {
ignore_changes = [user_data]
}
}
Basically I'd like to replace "bastion-euw3-infra-01" inside the resource with some kind of var, e.g.:
resource "aws_instance" "bastion-euw3-infra-01" {
...
user_data = templatefile("./scripts/cloudinit.yaml", {
hostname = ___name___
tailscale_authkey = var.tailscale_authkey
})
...
tags = {
Name = ___name___
Environment = "infra"
}
...
}
Does terraform provide a way to do this ?

Value of 'count' cannot be computed in Terraform

Here I'm trying to create one subnet per availability zone and then associate the route table with each of them.
locals {
aws_region = "${var.aws_regions[var.profile]}"
base_name = "${var.product}-${local.aws_region}"
aws_avzones = {
pro = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
dev = ["eu-west-2a", "eu-west-2b", "eu-west-2c"]
}
}
# ---
# Create VPC
resource "aws_vpc" "default" {
cidr_block = "${var.vpc_cidr_block}"
tags = {
Name = "${local.base_name}-vpc"
}
}
# ---
# Create public subnets - each in a different AZ
resource "aws_subnet" "public" {
count = "${length(local.aws_avzones[var.profile])}"
vpc_id = "${aws_vpc.default.id}"
cidr_block = "${cidrsubnet(var.vpc_cidr_block, 8, count.index)}"
availability_zone = "${element(local.aws_avzones[var.profile], count.index)}"
map_public_ip_on_launch = 1
tags = {
"Name" = "Public subnet - ${element(local.aws_avzones[var.profile], count.index)}"
}
}
# ---
# Create Internet gateway for inbound-outbound connections
resource "aws_internet_gateway" "default" {
vpc_id = "${aws_vpc.default.id}"
tags = {
"Name" = "${local.base_name}-igw"
}
}
# ---
# Create Internet gateway routes table
resource "aws_route_table" "pub" {
vpc_id = "${aws_vpc.default.id}"
route {
cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.default.id}"
}
tags = {
Name = "${local.base_name}-rtb-igw"
}
}
# ---
# Associate public subnets with the public route table
resource "aws_route_table_association" "pub" {
count = "${length(aws_subnet.public.*.id)}"
subnet_id = "${element(aws_subnet.public.*.id, count.index)}"
route_table_id = "${aws_route_table.pub.id}"
}
Unfortunately terraform plan renders an error:
aws_route_table_association.pub: aws_route_table_association.pub: value of 'count' cannot be computed
Why it cannot be computed? Terraform did not complain about that when the infra. was all up and running, I discovered this error only after the destruction when attempting to to recreate the infra.
Currently my workaround is to comment out all the aws_route_table_association blocks, then terraform apply, uncomment and then finish the job. Obviously this is very far from ideal.
BTW, I also tried the explicit dependency declaration like so:
resource "aws_route_table_association" "pub" {
count = "${length(aws_subnet.public.*.id)}"
subnet_id = "${element(aws_subnet.public.*.id, count.index)}"
route_table_id = "${aws_route_table.pub.id}"
depends_on = ["aws_subnet.public"]
}
But it didn't help.
$ terraform --version
Terraform v0.11.11
+ provider.aws v1.52.0

Terraform - populate variable values from same script

I'm very green to terraform; infact this is part of my training.
I'm wondering; is there a way to get terraform to store a specific value (as variable) from the previous command within the same file.
Example:
resource "aws_vpc" "TestVPC"{
cidr_block = "192.168.0.0/16"
instance_tenancy = "default"
enable_dns_hostnames="True"
tags{
Name="TestVpc"
}
}
resource "aws_subnet" "TestSubnet"{
vpc_id = "${var.aws_vpc_id}" ##This is where I'd like to populate the aws_vpc_id from the VPC creation step above.
cidr_block = "192.168.0.0/24"
map_public_ip_on_launch="True"
availability_zone = "us-east-2a"
tags{
Name="TestSubnet"
}
}
Help is greatly appreciated.
Thanks.
You can use the output from the creation of the VPC, ${aws_vpc.TestVPC.id}
Like so:
resource "aws_vpc" "TestVPC" {
cidr_block = "192.168.0.0/16"
instance_tenancy = "default"
enable_dns_hostnames = "True"
tags {
Name = "TestVpc"
}
}
resource "aws_subnet" "TestSubnet" {
vpc_id = "${aws_vpc.TestVPC.id}"
cidr_block = "192.168.0.0/24"
map_public_ip_on_launch = "True"
availability_zone = "us-east-2a"
tags {
Name = "TestSubnet"
}
}

Resources