0
votes

I'm trying to use a vpc module i made for aws in a top module. My tree is as follows:

.
├── dev.vars.json
├── modules
│   └── vpc
│       ├── README.md
│       ├── main.tf
│       ├── outputs.tf
│       ├── variables.tf
│       └── versions.tf
├── outputs.tf
├── variables.tf
└── main.tf

the "vpc" module works fine, I'm trying to use that module in my main.tf file on the root folder like this:

$ cat main.tf
module "dev_vpc" {
  source                = "./modules/vpc"
}

my variables:

variable "vpc" {
    type = object({
        name = string
    })
}

my outputs.tf


# VPC
output "vpc_id" {
  description = "The ID of the VPC"
  value       = module.vpc.vpc_id
}
...

and my dev.vars.json:

{
    "vpc": {
        "name": "development-vpc"
    },
}

Once i got the vpc in "modules/vpc" working, I want to use it on the top main.tf file, but when i run apply (after init) i get:

$ terraform plan -var-file dev.vars.json 
╷
│ Error: Missing required argument
│ 
│   on main.tf line 1, in module "dev_vpc":
│    1: module "dev_vpc" {
│ 
│ The argument "vpc" is required, but no definition was found.

the main.tf in modules/vpc:

provider "aws" {
  region = local.region
}

locals {
  region = "us-east-1"
}

################################################################################
# VPC Module
################################################################################

resource "aws_vpc" "dev_vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "2.66.0"

  name = var.vpc.name
  cidr = "10.0.0.0/16"

  azs             = ["${local.region}a", "${local.region}b", "${local.region}c"]
  private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
  public_subnets  = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]

  enable_ipv6 = true

  enable_nat_gateway = false
  single_nat_gateway = true

  public_subnet_tags = {
    Name = "overridden-name-public"
  }

  tags = {
    Owner       = "user"
    Environment = "dev"
  }

  vpc_tags = {
    Name = "vpc-name"
  }
}

I haven't been able to figure out how to fix this.

Many thanks!

davidcsi

1
You've declared a VPC "object" as an input variable of your module, you don't appear to have declared a default value for that input variable, and you aren't setting the variable when you try to use the module in your main.tf file. - Mark B

1 Answers

0
votes

It ended up being that i used a terraform from terraform's github, and there's a lot of dependencies that wouldn't work.

my final vpc code is:

$ cat main.tf

provider "aws" {
  region  = "${var.region}"
}

/*==== The VPC ======*/
resource "aws_vpc" "vpc" {
  cidr_block           = "${var.vpc_cidr}"
  enable_dns_hostnames = true
  enable_dns_support   = true
  tags = {
    Name        = "${var.environment}-vpc"
    Environment = "${var.environment}"
  }
}

$ cat subnets.tf

/* Internet gateway for the public subnet */
resource "aws_internet_gateway" "ig" {
  vpc_id = "${aws_vpc.vpc.id}"
  tags = {
    Name        = "${var.environment}-igw"
    Environment = "${var.environment}"
  }
}

/* Elastic IP for NAT */
resource "aws_eip" "nat_eip" {
  vpc        = true
  depends_on = [aws_internet_gateway.ig]
}

/* NAT */
resource "aws_nat_gateway" "nat" {
  allocation_id = "${aws_eip.nat_eip.id}"
  subnet_id     = "${element(aws_subnet.public_subnet.*.id, 0)}"
  depends_on    = [aws_internet_gateway.ig]
  tags = {
    Name        = "nat"
    Environment = "${var.environment}"
  }
}

/* Public subnet */
resource "aws_subnet" "public_subnet" {
  vpc_id                  = "${aws_vpc.vpc.id}"
  count                   = "${length(var.public_subnets_cidr)}"
  cidr_block              = "${element(var.public_subnets_cidr,   count.index)}"
  availability_zone       = "${element(var.availability_zones,   count.index)}"
  map_public_ip_on_launch = true
  tags = {
    Name        = "${var.environment}-${element(var.availability_zones, count.index)}-      public-subnet"
    Environment = "${var.environment}"
  }
}

/* Private subnet */
resource "aws_subnet" "private_subnet" {
  vpc_id                  = "${aws_vpc.vpc.id}"
  count                   = "${length(var.private_subnets_cidr)}"
  cidr_block              = "${element(var.private_subnets_cidr, count.index)}"
  availability_zone       = "${element(var.availability_zones,   count.index)}"
  map_public_ip_on_launch = false
  tags = {
    Name        = "${var.environment}-${element(var.availability_zones, count.index)}-private-subnet"
    Environment = "${var.environment}"
  }
}

/* Routing table for private subnet */
resource "aws_route_table" "private" {
  vpc_id = "${aws_vpc.vpc.id}"
  tags = {
    Name        = "${var.environment}-private-route-table"
    Environment = "${var.environment}"
  }
}

/* Routing table for public subnet */
resource "aws_route_table" "public" {
  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.id}"
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = "${aws_internet_gateway.ig.id}"
}

resource "aws_route" "private_nat_gateway" {
  route_table_id         = "${aws_route_table.private.id}"
  destination_cidr_block = "0.0.0.0/0"
  nat_gateway_id         = "${aws_nat_gateway.nat.id}"
}

/* Route table associations */
resource "aws_route_table_association" "public" {
  count          = "${length(var.public_subnets_cidr)}"
  subnet_id      = "${element(aws_subnet.public_subnet.*.id, count.index)}"
  route_table_id = "${aws_route_table.public.id}"
}

resource "aws_route_table_association" "private" {
  count          = "${length(var.private_subnets_cidr)}"
  subnet_id      = "${element(aws_subnet.private_subnet.*.id, count.index)}"
  route_table_id = "${aws_route_table.private.id}"

$ cat security_groups.tf

/*==== VPC's Default Security Group ======*/
resource "aws_security_group" "default" {
  name        = "${var.environment}-default-sg"
  description = "Default security group to allow inbound/outbound from the VPC"
  vpc_id      = "${aws_vpc.vpc.id}"
  depends_on  = [aws_vpc.vpc]
  ingress {
    from_port = "0"
    to_port   = "0"
    protocol  = "-1"
    self      = true
  }
  
  egress {
    from_port = "0"
    to_port   = "0"
    protocol  = "-1"
    self      = "true"
  }
  tags = {
    Environment = "${var.environment}"
  }
}

$ cat outputs.tf

output "vpc_id" {
  value = "${aws_vpc.vpc.id}"
}

cat variables.tf

variable "region" {
  description = "AWS Deployment region.."
  default = "us-east-1"
}

variable "vpc_cidr" {
    description = "CIDR to assign to this VPC"
    default = "10.0.0.0/16"
}

variable "environment" {
    description = "On what environment is this running?"
    default = "dev"
}

variable "availability_zones" {
    description = "On what environment is this running?"
    default = [ 
        "us-east-1a", 
        "us-east-1b", 
        "us-east-1c"
    ] 
}

variable "public_subnets_cidr" {
    description = "public_subnets_cidr"
    default = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
}

variable "private_subnets_cidr" {
    description = "On what environment is this running?"
    default = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
}

This doesn't give me any issues when using it as a module.