Search code examples
amazon-web-servicesamazon-ec2terraformterraform-provider-aws

no matching EC2 Security Group found


I create modules for creating AWS vpc, security group and EC2. I make EC2 module depend on vpc and the security group module. but I get that error:

no matching EC2 Security Group found
  on .terraform/modules/main_ec2/modules/EC2Module/main.tf line 26, in data "aws_security_group" "security_group_id":
  26: data "aws_security_group" "security_group_id" {

EC2 module

data "aws_subnet" "subnet_id" {
  vpc_id = var.vpc_id
  count = length(var.subnet_name)
  depends_on = [var.subnet_id_depends_on]
  filter {
    name = "tag:Name"
    values = ["VPC0${var.vpc_number}-${element(var.subnet_name, count.index)}"]
  }
}

data "aws_security_group" "security_group_id" {
  count = length(var.Server_Group_Name)
  depends_on = [var.security_group_depends_on]
  filter {
    name   = "tag:Name"
    values = ["${local.name}-SG-${var.Server_Group_Name[count.index]}-${format("%02d", count.index + 1)}"]
  }
}

resource "aws_instance" "create_instance" {
  ami = "${element(data.aws_ami_ids.ami_id.*.id, count.index)}"
  instance_type = var.EC2_Type[count.index]
  subnet_id = "${element(data.aws_subnet.subnet_id.*.id, count.index)}"
  associate_public_ip_address = "true"
  vpc_security_group_ids = [ data.aws_security_group.security_group_id[count.index].id ]
  key_name = "${local.name}-KP-${var.Server_Name[count.index]}"
  depends_on = [var.EC2_depends_on]
}
  

sg module

resource "aws_security_group" "SGS" {
  count       = length(var.Server_Group_Name)
  name        = "${local.name}-SG-${var.Server_Group_Name[count.index]}-${format("%02d", count.index + 1)}"
  description = "${local.name}-SG-${var.Server_Group_Name[count.index]}-${format("%02d", count.index + 1)}"
  vpc_id      = var.vpc_id
  tags = {
    name   = "tag:Name"
    values = "${local.name}-SG-${var.Server_Group_Name[count.index]}-${format("%02d", count.index + 1)}"
  }

varibles.tf

variable "subnet_id_depends_on" {
  type = list(string)
  default = ["module.vpc_main"]
  
}

variable "security_group_depends_on" {
  type = list(string)
  default = ["module.sg"]
  
}
variable "EC2_depends_on" {
  type = list(string)
  default = [ "module.vpc_main", "module.sg", "module.key_pair" ]
}

for example, I call modules like that:

module "main_ec2" { 
  source = "/home/reham/Data/projectes/terraform//modules/EC2Module" 
  subnet_id_depends_on = var.subnet_id_depends_on 
  security_group_depends_on = var.security_group_depends_on 
  ami_name = var.ami_name 
  EC2_depends_on = var.EC2_depends_on
} 

Outputs defined in the sg module:

output "vpc_id" {
  description = "VPC ID"
  value = aws_vpc.vpc.id
}

output "primary_public_subnets_id" {
  description = "public subnet ID"
  value = aws_subnet.primary_public_subnets.*.id
}

output "secondary_public_subnets_id" {
  description = "public subnet ID"
  value = aws_subnet.secondary_public_subnets.*.id
} 

output "primary_private_subnets_id" {
  description = "public subnet ID"
  value = aws_subnet.primary_private_subnets.*.id
}

output "security-groups" {
  value = aws_security_group.SGS[*].id
}

what must I do to solve this problem?


Solution

  • There is more than one issue with the code and it is a result of probably not understanding how the module outputs work [1]. The second part of the issue is that there are many explicit dependencies defined with depends_on which are not required to be there since implicit dependencies are good enough [2]. Furthermore, as per comments, data sources in the EC2 module are not required as information about VPC, subnets and security groups can be provided with the outputs. Additionally, the EC2 instance resource is using count, but there is no count meta-argument there, so it will not work even if all the inputs are fixed. So here are my suggestions:

    1. Redefine variables in the EC2 module (no need for depdends_on) and remove data sources (except possibly the one for the AMI)
    2. Decide which variable you are going to use for the count meta-argument in the EC2 instance resource

    I am going to give you an example with one subnet and security groups and then you can build from there. The EC2 module fixes:

    resource "aws_instance" "create_instance" {
      ami                         = data.aws_ami_ids.ami_id[0].id
      instance_type               = var.EC2_Type
      subnet_id                   = var.subnet_id
      associate_public_ip_address = "true"
      vpc_security_group_ids      = var.security_group_ids
      key_name                    = "${local.name}-KP-${var.Server_Name[0]}"
    }
    

    In EC2 module, the variables would have to be changed to:

    variable "subnet_id" {}
    variable "security_group_ids" {}
    

    Then, in the root module:

    module "main_ec2" { 
      source             = "/home/reham/Data/projectes/terraform//modules/EC2Module" 
      subnet_id          = module.sg.primary_public_subnets_id[0] 
      security_group_ids = module.sg.security-groups
      ami_name           = var.ami_name 
    } 
    

    Referencing the module outputs in the EC2 module will make sure that the SG module is created first (that is an implicit dependency). At best this should give you a result for one EC2 instance as it seems there are many resources that rely on using the count meta-argument and that code is not in the question.


    [1] https://www.terraform.io/language/values/outputs#accessing-child-module-outputs

    [2] https://www.terraform.io/language/resources/behavior#resource-dependencies