Why is my subnet data source returning a VPC? - amazon-web-services

I am using a module my coworker wrote, but for some reason, I am getting subnet not found -- and the identifier begins with vpc-. Why is this returning a VPC and not a subnet?
data "aws_subnet_ids" "app" {
vpc_id = "${data.aws_vpc.default.id}"
tags = {
SubnetType = "app"
}
}
Which is being passed through to the module as
private_subnets = "${data.aws_subnet_ids.app.*.id}"
and used here:
resource "aws_autoscaling_group" "default-alb" {
name = "${chomp(data.template_file.standard_name.rendered)}"
launch_configuration = tostring(element(aws_launch_configuration.default,count.index).name)
min_size = "${var.min_instances}"
max_size = "${var.min_instances}"
target_group_arns = [
tostring(element(aws_alb_target_group.default-http,count.index).arn),
]
vpc_zone_identifier = var.private_subnets
lifecycle {
create_before_destroy = true
}
}
But I get the error:
Error: Error creating AutoScaling Group: ValidationError: The subnet ID 'vpc-004[redacted]' does not exist
status code: 400, request id: 73e98545-975c-11e9-bd63-fd4915ceeabf
on .terraform/modules/core-api/alb.tf line 1, in resource "aws_autoscaling_group" "default-alb":
1: resource "aws_autoscaling_group" "default-alb" {
Shouldn't the subnet identifier begin with subnet-?

The aws_subnet_ids data source doesn't have an id argument or attribute so Terraform should throw an exception there and I'm a little surprised it isn't doing so.
Also you don't appear to be using a count on that so don't need the splat operator you have there.
So instead of:
private_subnets = "${data.aws_subnet_ids.app.*.id}"
You should be using the ids attribute to return a list of all the subnet IDs that match your filter:
private_subnets = "${data.aws_subnet_ids.app.ids}"

Related

How do I specify the filesystem_arn for the aws datasync module?

Edit: I just noticed the error seems to be about the filesystem arn I have specified and not the subnet arn so I've edited the question. Good grief.
I'm trying to define an aws_datasync_location_efs object in Terraform using the example here
The datasync location wants a efs_file_system_arn so this seems like it should work but why am I getting this error?
Error: creating DataSync Location EFS: ValidationException: 1
validation error detected: Value
'arn:aws:elasticfilesystem:us-east-1::file-system/fs-0d5b67a50ea988fb6'
at 'efsFilesystemArn' failed to satisfy constraint: Member must
satisfy regular expression pattern:
^arn:(aws|aws-cn|aws-us-gov|aws-iso|aws-iso-b):elasticfilesystem:[a-z-0-9]+:[0-9]{12}:file-system/fs-[0-9a-f]{8,40}$
status code: 400, request id:
e5f906d9-068b-4250-a9d7-63dd5dc813d1 with
aws_datasync_location_efs.example, on efs.tf line 71, in resource
"aws_datasync_location_efs" "example": 71: resource
"aws_datasync_location_efs" "example" {
private subnet variables in variables.tf
variable "my_private_subnets" {
type = list
description = "private subnet within vpc cidr block"
default = ["10.0.100.0/24", "10.0.102.0/24"]
}
the vpc in main.tf
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
name = "${var.my_project}-vpc"
cidr = "${var.my_cidr}"
azs = ["${var.my_region}a", "${var.my_region}b"]
private_subnets = [for subnet in var.my_private_subnets: subnet]
public_subnets = [for subnet in var.my_public_subnets: subnet]
enable_nat_gateway = true
enable_dns_hostnames = true
enable_dns_support = true
}
my datasync declaration in efs.tf
resource "aws_efs_mount_target" "my_target1" {
file_system_id = aws_efs_file_system.my_efs.id
subnet_id = module.vpc.private_subnets[0]
security_groups = [aws_security_group.my_efs-sg.id]
}
resource "aws_efs_mount_target" "my_target2" {
file_system_id = aws_efs_file_system.my_efs.id
subnet_id = module.vpc.private_subnets[1]
security_groups = [aws_security_group.my_efs-sg.id]
}
resource "aws_datasync_location_efs" "example" {
efs_file_system_arn = aws_efs_mount_target.my_target1.file_system_arn
ec2_config {
security_group_arns = [aws_security_group.my_efs-sg.arn]
subnet_arn = module.vpc.public_subnet_arns[0]
}
}

Terraform ENI Mapping error - does not fall within the subnet's address range

I am trying to map my ENI to my subnet and its throwing an error.
Because there is a for_each loop on the subnet the ENI pointing to it must also have a looped key/value added to it hence the problem
main.tf
# VPC
resource "aws_vpc" "main" {
cidr_block = local.json.vpc.cidr
tags = {
Name = "vpc"
}
}
# Subnet
resource "aws_subnet" "public" {
for_each = local.api
vpc_id = aws_vpc.main.id
cidr_block = each.value.subnet_cidr
availability_zone = each.value.subnet_az
}
# ENI
resource "aws_network_interface" "eni" {
for_each = local.api
subnet_id = aws_subnet.public[each.key].id
private_ips = ["172.16.10.100"] # Might need to add another IP
tags = {
Name = "primary_network_interface"
}
}
my locals look like this
locals {
json = jsondecode(file("API.json"))
api = merge([
for vpc in local.json : {
for subnet in vpc.subnets :
"${vpc.name}-${subnet.name}" => {
vpc_name = vpc.name
vpc_cidr = vpc.cidr
subnet_name = subnet.name
subnet_cidr = subnet.cidr
subnet_az = subnet.az
}
}
]...)
}
their output (local.api) from terraform console
{
"vpc-subnet-one" = {
"subnet_az" = "eu-central-1a"
"subnet_cidr" = "192.168.1.0/24"
"subnet_name" = "subnet-one"
"vpc_cidr" = "192.168.0.0/16"
"vpc_name" = "vpc"
}
"vpc-subnet-two" = {
"subnet_az" = "eu-central-1b"
"subnet_cidr" = "192.168.4.0/24"
"subnet_name" = "subnet-two"
"vpc_cidr" = "192.168.0.0/16"
"vpc_name" = "vpc"
}
}
error message
status code: 400, request id: 64e031e5-11ea-4f6d-a03c-9a36a1ff56af
with aws_network_interface.eni["vpc-subnet-one"],
on main.tf line 20, in resource "aws_network_interface" "eni":
20: resource "aws_network_interface" "eni" {
Error: creating EC2 Network Interface: InvalidParameterValue: Address does not fall within the subnet's address range
status code: 400, request id: 7842f089-08b4-4042-b928-7830a37ffe28
with aws_network_interface.eni["vpc-subnet-two"],
on main.tf line 20, in resource "aws_network_interface" "eni":
20: resource "aws_network_interface" "eni" {
I've followed this documenation and validated everything else is correct. I still can't seem to figure out what value should be set on subnet_id
Bonus cheeky points - I am trying to configure 2 EC2's, Should i give our eni a secondary private_ips?
The error means that your IP 172.16.10.100 is invalid for your subnet CIDR range 192.168.1.0/24 and 192.168.4.0/24. Obviously this is correct because your IP should be in the correct range. For example:
private_ips = ["192.168.1.100"] # for the first subnet
private_ips = ["192.168.4.100"] # for the second subnet

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?
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:
Redefine variables in the EC2 module (no need for depdends_on) and remove data sources (except possibly the one for the AMI)
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

Incorrect attribute value type. Inappropriate value for sttributes "subnets: set of string required."

I've passed subnet ids many times and haven't encountered this error before, I'm really not sure why or how to fix it.
I have my subnet resource block right here in my VPC module:
resource "aws_subnet" "subnet_1" {
vpc_id = aws_vpc.vpc_1.id
cidr_block = "10.0.0.0/24"
availability_zone = var.region_az
tags = {
Name = "pcp-subnet-1"
}
}
This is what the outputs file looks like for my subnet output:
output "subnet_1" {
value = aws_subnet.subnet_1.id
}
This is my root module calling the subnet id output
module "ecs" {
source = "./ecs"
service_subnets = module.vpc.subnet_1
pcp_service_sg = module.vpc.pcp_service_sg
}
In my ecs module I have the variable listed here in my variables file
variable "service_subnets" {
type = string
}
This is my ecs resource where the error is occurring
resource "aws_ecs_service" "ecs-service" {
name = "python-cloud-project"
cluster = aws_ecs_cluster.cluster.id
task_definition = aws_ecs_task_definition.pcp-ecs-task-definition.arn
launch_type = "FARGATE"
network_configuration {
subnets = var.service_subnets
security_groups = var.pcp_service_sg
assign_public_ip = true
}
desired_count = 1
}
network_configuration requires a list of subnets, you are passing only one subnet. What you can do is to create a list with one element:
module "ecs" {
source = "./ecs"
service_subnets = [module.vpc.subnet_1]
pcp_service_sg = module.vpc.pcp_service_sg
}

Retrieve Subnet ids for map variables

I have created subnet as map variable for availability zone and CIDR block and
variable "public_subnets_list" {
type = map(any)
description = "Public Subnets"
default = {
"ap-south-1a" = "10.0.1.0/24"
"ap-south-1b" = "10.0.2.0/24"
}
}
This works fine for creating subnets under my custom VPC with below code
resource "aws_subnet" "public_subnet" {
depends_on = [
aws_vpc.terraform_vpc
]
for_each = tomap(var.public_subnets_list)
availability_zone = each.key
cidr_block = each.value
vpc_id = aws_vpc.terraform_vpc.id
tags = {
Name = "Public_Subnet_${each.key}"
}
}
How do I retrieve and display the subnet id created for respective AZs from output which i get from aws_subnet.public_subnet[*]
From the Terraform documentation, splat expressions do not work with resources that use the for_each argument.
To retrieve a list of subnet IDs using your Terraform configuration, you can do the following:
output "subnet_ids" {
value = [for subnet in aws_subnet.public_subnet : subnet.id]
}