Aws sg and instance creation

Hi all, I’d appreciate the help.

My goal is to create a complete VPC in a one shot.

I configured a setup where I read a YAML file and then according to a loop I’ve created, it creates the security groups with the name I wanted:

groups:                                                                                                                                                       
  a:                        
  - open_port: ssh             
    to_group: bastion1 
  - open_port: ping            
    to_group: bastion2         

  b:
  - open_port: ssh
    to_group: bastion           
  - open_port: ping
    to_group: bastion           

  c:
  - open_port: ssh
    to_group: bastion           
  - open_port: ping            
    to_group: bastion3
locals {
  sg_file         = yamldecode(file("${path.module}/../security_groups.yml"))
  security_groups = [for group, rules in local.sg_file.groups : group]
}
resource "aws_security_group" "service_sg" {
    count       = length(local.security_groups)
    name        = "${var.env}-${element(local.security_groups, count.index)}"
    description = "${var.env}-${element(local.security_groups, count.index)}"
    vpc_id      = var.vpc_id
  
    tags = {
      Name = "${var.env}-${element(local.security_groups, count.index)}"
      env  = var.env
+     role = element(local.security_groups, count.index)
    }
  }

This is the main module:

module "security_group" {
 source = "./modules/aws/security_group/create_sg" 
 env = var.accounts[terraform.workspace].env
 vpc_id = module.vpc.vpc_id
}
 
module "services" {
 source         = "./modules/services"       
 env         = var.accounts[terraform.workspace].env
 services       = var.services
 public_ids  = module.subnet.public_subnets_ids
 private_ids = module.subnet.private_subnets_ids
  }

This is the line I use in aws_instance resource to choose the proper sg and the data resources I use:

vpc_security_group_ids = [for id, name in local.sg_list : id if name == "${var.env}-${each.value.service_name}"]
data "aws_security_groups" "sgs" {
   tags = {
     env = var.env
   }   
 }     
   
data "aws_security_group" "selected" {
  for_each = { for sg in local.sg_ids : sg => sg } 
  id       = each.value      
}   
     
locals {
  sg_ids          = data.aws_security_groups.sgs.ids
  sg_list         = { for group, group_info in data.aws_security_group.selected : group => group_info.name }
}

However, when I run this setup with terraform apply, I get the following error:

Error: Your query returned no results. Please change your search criteria and try again.

  on modules/services/variables.tf line 35, in data "aws_security_groups" "sgs":
  35: data "aws_security_groups" "sgs" {

When I run the module seperately, I do get the results of of the security groups that were created.

You should not use a data source to refer to a resource in the same config. It’s a chicken and egg thing, you can’t refer to something before it exists.

Thank you for the reply.
They are different modules.

Can I use “depends_on” to solve this or any other way so it will run in the same terraform apply command ??

Found a solution.

Wanted to share it so others can use it.

I created the security groups using the resource I mentioned above + the yaml file.
I then configured an output

output "security_groups_info" {                                                                                                                               
  value = { for sg, sg_info in aws_security_group.service_sg : sg_info.id => sg_info.name }
}

Basically, I used a for loop to go over the exported info(all the information per security group) that the resource provides. I then extracted the Security Group ID and the Security Group name and created a map.

I edited the aws_instance and resource to use the following line:

vpc_security_group_ids = [for id, name in var.security_groups_info : id if name == "${var.bp_env}-${each.value.service_name}"]

Hope someone will find it useful.