25

I am new to terraform and trying to build an infrastructure with two subnets and VPC. I have created two modules

  • VPC
  • subnet

The VPC module will create a VPC and will return vpc_id as output, the same return vpc_id I am trying to use in the subnet module, but when I run the terraform plan, it asks me for the enter vpc_id input.

I want the vpc_id from the output value of the VPC module, can anyone please help me on the same.

Below is the code,

root tf file,

 provider "aws" {
  shared_credentials_file = var.shared_cred
  profile                 = "default" 
  region                  = var.aws_region
}

module "vpc" {
  source = "./vpc"
  name   = "terraformVPC"
  cidr   = "10.50.40.0/27"
}

module "private_subnet" {
  source      = "./subnet"
  subnet_name = "private_subnet"
  subnet_cidr = "10.50.40.16/28"
  #VPC_id = aws_vpc.moduleVPC.id
  VPCid = module.vpc.outvpc_id # this is the issue
}

module "public_subnet" {
  source      = "./subnet"
  subnet_name = "public_subnet"
  subnet_cidr = "10.50.40.0/28"
  VPCid      = module.vpc.outvpc_id
}

Subnet resource

resource "aws_subnet" "module_subnet" {
  cidr_block = var.subnet_cidr
  vpc_id     = var.VPCid

  tags = {
    Name = var.subnet_name
  }
}

Subnet module variable declaration

variable "subnet_name" {
  description = " define th subnet name"
}

variable "subnet_cidr" {
  description = "define th subnet cidr block"
}

variable "VPCid" {
  description = "Assign VPC id to subnet"
}

VPC output

output "outvpc_id" {
  value = "${aws_vpc.moduleVPC.id}"
}
Mahesh
  • 296
  • 1
  • 3
  • 4
  • should be `value = aws_vpc.moduleVPC.id` not `value = "${aws_vpc.moduleVPC.id}"`. You should have an error message I think that tells you this? – Liam Sep 25 '20 at 13:58
  • Hi Liam, I don't get an error, but asks for the input variable for vpc_id and I thnk both perform the same action value = aws_vpc.moduleVPC.id and value = "${aws_vpc.moduleVPC.id}" – Mahesh Sep 26 '20 at 12:26
  • I have use same flow my project with this module composition. But when every time particular module get imported from another module only for referencing variables from that module. But instead of that Terraform plan showing same recourse to be create (duplicate) again. Can anyone know how to prevent that? – CodeMind Jul 23 '23 at 04:10

4 Answers4

30

This is called "Module Composition". The important thing to remember is that you reference outputs of another module.

The format is: module.<object-name>.<output-name>

module "network" {
  source = "./modules/aws-network"

  base_cidr_block = "10.0.0.0/8"
}

module "consul_cluster" {
  source = "./modules/aws-consul-cluster"

  vpc_id     = module.network.vpc_id       # < output of module.network
  subnet_ids = module.network.subnet_ids   # < output of module.network
}
Amir Mehler
  • 4,140
  • 3
  • 27
  • 36
1

I think this can help you better achieve what you are trying to do:

Root.tf

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "3.14.0"

  name = var.vpc_name
  cidr = var.vpc_cidr

  azs             = var.vpc_azs
  private_subnets = var.vpc_private_subnets
  public_subnets  = var.vpc_public_subnets

  enable_nat_gateway = var.vpc_enable_nat_gateway

  tags = var.vpc_tags
}

module "ec2_instances" {
  source  = "terraform-aws-modules/ec2-instance/aws"
  version = "3.5.0"
  count   = 2

  name = "my-ec2-cluster"

  ami                    = "ami-0c5204531f799e0c6"
  instance_type          = "t2.micro"
  vpc_security_group_ids = [module.vpc.default_security_group_id]
  subnet_id              = module.vpc.public_subnets[0]

  tags = {
    Terraform   = "true"
    Environment = "dev"
  }
}

var.tf

variable "vpc_name" {
  description = "Name of VPC"
  type        = string
  default     = "example-vpc"
}

variable "vpc_cidr" {
  description = "CIDR block for VPC"
  type        = string
  default     = "10.0.0.0/16"
}

variable "vpc_azs" {
  description = "Availability zones for VPC"
  type        = list(string)
  default     = ["us-west-2a", "us-west-2b", "us-west-2c"]
}

variable "vpc_private_subnets" {
  description = "Private subnets for VPC"
  type        = list(string)
  default     = ["10.0.1.0/24", "10.0.2.0/24"]
}

variable "vpc_public_subnets" {
  description = "Public subnets for VPC"
  type        = list(string)
  default     = ["10.0.101.0/24", "10.0.102.0/24"]
}

variable "vpc_enable_nat_gateway" {
  description = "Enable NAT gateway for VPC"
  type        = bool
  default     = true
}

variable "vpc_tags" {
  description = "Tags to apply to resources created by VPC module"
  type        = map(string)
  default = {
    Terraform   = "true"
    Environment = "dev"
  }
}

You can get more info from https://learn.hashicorp.com/tutorials/terraform/module-use

0

When I use terraform for aws... My module name it's "network.ts" I don't think you need two tf files to manage your vpc and the subnets of that VPC.

network.tf

resource "aws_vpc" "vpc" {
  cidr_block           = "10.50.40.0/27"
  enable_dns_hostnames = true // only if you need
  tags                 = {
    Name = "desa-vpc-spotify" //Use your own name
  }
}

resource "aws_subnet" "private_subnet" {
  vpc_id            = aws_vpc.vpc.id
  availability_zone = "us-east-1a" //your own region
  cidr_block        = "10.50.40.16/28"
  tags = {
    Name = "desa-subnet-private-spotify"
  }
}

resource "aws_subnet" "public_subnet" {
  vpc_id            = aws_vpc.vpc.id
  availability_zone = "us-east-1a"//your own region
  cidr_block        = "10.50.40.0/28"
  tags = {
    Name = "desa-subnet-public-spotify"
  }
}

if you want vpc on another tf

(and if you want to have two files... only call the vpc like this)

another.tf

data "aws_vpc" "vpcs" {
  tags = {
    Name = "desa-vpc-spotify" //only put the name of the vpc of the network tf
  }
}


Derek Menénedez
  • 2,003
  • 11
  • 20
  • 1
    Thank you, Derek. I was just testing how to call variables between modules but looks like I am calling them in wrong way. – Mahesh Sep 26 '20 at 12:28
  • 1
    @Mahesh - would you mind posting the answer for everyone's benefit? I have this same scenario where I need help in passing output from 1 module to another. If you could publish the full code that does this that'd be really helpful. Thanks! – Biju Apr 06 '22 at 08:04
0

I notice that you have listed "VPCid =". When you run terraform validate does it throw an error? I would trying changing it to "vpc_id" instead and see if that works.

Keimille
  • 345
  • 2
  • 11
  • This does not provide an answer to the question. Once you have sufficient [reputation](/help/whats-reputation) you will be able to [comment on any post](/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). – Yunnosch Nov 19 '20 at 16:46