Error: Reference to undeclared module

Hello guys,
I am getting an error :
Error: Reference to undeclared module

on modules\security\security.tf line 6, in resource “aws_security_group” “Web-sg”:
6: vpc_id = module.networking.vpcid

No module call named “networking” is declared in security.

This is directory structure that I am following currently,
│   main.tf
│   provider.tf
│   terraform.tfstate
│   terraform.tfstate.backup
│   variables.tf
│
└───modules
    ├───networking
    │       networking.tf
    │       outputs.tf
    │       variables.tf
    │
    └───security
            security.tf
            variables.tf

main.tf
module “networking” {

    source = "./modules/networking"
   }

module "security" {
    source = "./modules/security"
}

I created a module named networking where I created all network resources:

resource "aws_vpc" "vpc" {

    cidr_block = var.cidr_block

        tags = {

        Name = var.vpc_name
    }
    }

#Creating Public Subnets

  resource "aws_subnet" "public" {
  count = var.subnet_count
  cidr_block = element(var.subnet_cidr_public,count.index)
  availability_zone = element(var.azs,count.index)
  vpc_id = aws_vpc.vpc.id
  map_public_ip_on_launch = var.map_public_ip_on_launch

  tags =  {
      Name = "Subnet-Public-${element(var.subnet_cidr_public,count.index)}"
  }    
  }

# Creating and Associating to the VPC the Internet Gateway

resource "aws_internet_gateway" "IGW-VPC" {

   vpc_id = aws_vpc.vpc.id 

   tags = {

     Name = var.igw-name

   }

}

# Creating Route Table - Public

# Creating Public Route Table 

resource "aws_route_table" "public-route" { 

  vpc_id = aws_vpc.vpc.id

  route { 

    cidr_block = var.cidr_block_route 

    gateway_id = aws_internet_gateway.IGW-VPC.id 

  }

    tags = {

      Name = var.public_route_name

    }

    

}

# Associating Subnet Public-1a to the Public Route Table

resource "aws_route_table_association" "association-public1a" {

  subnet_id = var.subnet_public_1a

  route_table_id = aws_route_table.public-route.id

}

resource "aws_route_table_association" "association-public1b" {

  subnet_id = var.subnet_public_1b

  route_table_id = aws_route_table.public-route.id

}

I created a module security.tf
resource “aws_security_group” “Web-sg” {

      name = var.web-sg_name

      description = var.web-sg_description

      vpc_id = module.networking.vpcid

      ingress { 

        description = var.description22

        from_port = var.port22

        to_port  = var.port22

        protocol = var.protocol 

        cidr_blocks = var.cidr000

      }

      ingress { 

        description =  var.description80 

        from_port = var.port80

        to_port  = var.port80

        protocol = var.protocol 

        cidr_blocks = var.cidr000 

      }

      ingress { 

        description = var.description443

        from_port = var.port443

        to_port  = var.port443

        protocol = var.protocol 

        cidr_blocks = var.cidr000 

      }

      egress {

        from_port   = var.port0 

        to_port     = var.port0 

        protocol    = var.protocol0

        cidr_blocks = var.cidr000 

      }

      tags = {

        "Name" = var.web-sg_name

      }

    }

As you can see I created in the resource “aws_security_group” “Web-sg” { vpc_id = module.networking.vpcid
vpc_id = module.networking.vpcid

and an outputs.tf file
output “vpcid” {

    value = aws_vpc.vpc.id

}

What I am doing wrong ? How can I fix it ?

Hi @mvsnogueira,

From what you’ve shared it seems that module "networking" and module "security" are both declared in your root module, and so they cannot access each other’s outputs directly.

Instead, you must declare an input variable in modules/security/variables.tf to accept the VPC ID that module needs as an argument:

variable "vpc_id" {
  type = string
}

Then in your root main.tf you’ll pass the output value from the networking module into the input variable of the security module:

module "networking" {
  source = "./modules/networking"
}

module "security" {
  source = "./modules/security"

  vpc_id = module.networking.vpc_id
}

This is an example of module composition: the security module doesn’t depend directly on the networking module, but rather it declares that it needs a VPC ID in order to perform its function and then it’s the job of the root module to decide where that VPC ID will be taken from.

2 Likes