I have multiple output variable, I want to make one parent out variable and then put other outputs into it. I have searched about it and found that we can user terraform object for it but can't get the syntax right.
Output.tf
output "public_subnet" {
value = "${module.my_vpc.public_subnets_ids}"
}
output "vpc_id" {
value = "${module.my_vpc.vpc_id}"
}
output "private_subnet" {
value = "${module.my_vpc.private_subnets_ids}"
}
I want my output to be in a object or you can say parent output variable that have all child output vales, I have come up with few line which I know is not right syntax wise but will get you a picture of what I am thinking of.
output "vpc" {
value = {
vpc_id = "${module.my_vpc.vpc_id}"
public_subnet = "${module.my_vpc.public_subnets_ids}"
private_subnet = "${module.my_vpc.private_subnets_ids}"
}
type = object({ vpc_id = string, public_subnet = string, private_subnet = string })
}
Terraform output does not have type. Therefore, your vpc should be:
output "vpc" {
value = {
vpc_id = "${module.my_vpc.vpc_id}"
public_subnet = "${module.my_vpc.public_subnets_ids}"
private_subnet = "${module.my_vpc.private_subnets_ids}"
}
}
But the issue is that a child module has no access to its parrent's outputs. Thus, I'm not exactly sure what do you want to achieve with your outputs. Normally, you would pass variables from parent to child using variable, and then you could make new output from those variables in the child module.
Update
Based on your previous questions, there is main.tf with
module "my_vpc" {
source = "./modules/vpc"
vpc_cidr = var.vpc_cidr
public_subnet = var.public_subnet
private_subnet = var.private_subnet
availability_zone = data.aws_availability_zones.azs.names
}
Therefore, you must have a folder ./modules/vpc. In the folder, there may be a file called ./modules/vpc/vpc.tf. The file will have something like this in it (variables could be in separate file as well):
variable "vpc_cidr" {}
variable "public_subnet" {}
variable "private_subnet" {}
variable "availability_zone" {}
# the rest of the VPC definition. Since the file is not given,
# i can only speculate on the exact details of the content
resource "aws_subnet" "public" {
count = length(var.public_subnet)
vpc_id = aws_vpc.my_vpc.id
# other attributes
}
resource "aws_subnet" "private" {
count = length(var.private_subnet)
vpc_id = aws_vpc.my_vpc.id
# other attributes
}
If so, then you can create a new file, called ./modules/vpc/output.tf with the content:
output "vpc" {
value = {
vpc_id = my_vpc.vpc_id
public_subnet = aws_subnet.public.*.id
private_subnet = aws_subnet.private.*.id
}
}
Related
variable.tf
variable "private_subnets" {
type = list
default = ["subnet-abc1,subnet-abc2"]
}
main.tf
resource "aws_db_subnet_group" "rds_subnet_group" {
name = var.cluster_name
subnet_ids = "${var.private_subnets}"
tags = {
Name = var.cluster_name,
environment = var.environment
}
}
This the present code i want use varable.tf for subnet this is way i want achive like this subnet-abc1,subnet-abc2
Considering that your variable has a wrongly defined default value, the first thing to fix is that:
variable "private_subnets" {
type = list(string)
default = ["subnet-abc1", "subnet-abc2"]
}
The way you are currently defining the default value, i.e, ["subnet-abc1,subnet-abc2"], is a list, however, it is a list with one element. Each element in a list of strings needs to start and end with double quotes, i.e. "some value". You can read more about lists in [1].
Then, you would just need to fix the code in the main.tf to look like this:
resource "aws_db_subnet_group" "rds_subnet_group" {
name = var.cluster_name
subnet_ids = var.private_subnets
tags = {
Name = var.cluster_name,
environment = var.environment
}
}
The syntax for subnets in the main.tf file is the old terraform syntax, so this will work without double quotes and ${}.
[1] https://developer.hashicorp.com/terraform/language/expressions/types#list
i have sort issue with split this is the answer
variable.tf
variable "private_subnets" {
default = "subnet-abc1,subnet-abc2"
}
main.tf
resource "aws_db_subnet_group" "rds_subnet_group" {
name = var.cluster_name
subnet_ids = "${split(",", var.private_subnets)}"
tags = {
Name = var.cluster_name,
environment = var.environment
}
I have a question about tags in Terrafrom. I have this variables, and I'd like to use the Transit variable description name as a tag in my main.tf file. How do I go about it?
#VPC CIDRs
variable "All_VPCs" {
type = map(any)
default = {
Dev_VPC = {
ip = "10.0.3.0/24"
instance_tenancy = "default"
}
Transit_VPC = {
ip = "10.0.4.0/23"
instance_tenancy = "default"
description = "Transit_VPC"
}
}
}
I used this, but it didn't work.
resource "aws_internet_gateway" "Transit_Internet_Gateway" {
vpc_id = var.All_VPCs.Transit_VPC
tags = {
Name = "${var.All_VPCs.Transit_VPC.description}" + " Internet_Gateway"
}
You can't concatenate strings in Terraform with a + operator. The correct method of doing this is to use string interpolation (which you are already partially doing):
tags = {
Name = "${var.All_VPCs.Transit_VPC.description} Internet_Gateway"
}
I want to override the value of root_volume_type to gp2 in https://github.com/terraform-aws-modules/terraform-aws-eks/blob/master/local.tf
This is the only file I created called main.tf in my terraform code. I want to override this in the code and not set it via the command line while running terraform apply
module "eks_example_basic" {
source = "terraform-aws-modules/eks/aws//examples/basic"
version = "14.0.0"
region = "us-east-1"
}
The error is correct because you are sourcing an example, which does not support such variables as workers_group_defaults. You can't overwrite it, unless you fork the example and modify it yourself.
workers_group_defaults is supported in the core module, for instance:
data "aws_vpc" "default" {
default = true
}
data "aws_subnet_ids" "default" {
vpc_id = data.aws_vpc.default.id
}
module "eks_example" {
source = "terraform-aws-modules/eks/aws"
version = "14.0.0"
cluster_name = "SomeEKSCluster"
cluster_version = "1.18"
subnets = data.aws_subnet_ids.default.ids
vpc_id = data.aws_vpc.default.id
workers_group_defaults = { root_volume_type = "gp2" }
}
When I trying to dynamically allocate subnet ids by running this tf file:
data "aws_availability_zones" "available" {}
resource "aws_vpc" "wpl_vpc" {
cidr_block = var.vpc_cidr
enable_dns_hostnames = true
tags = {
Name = "WPL-VPC"
CreatedBy = var.created_by
}
}
resource "aws_subnet" "wpl_public_subnet" {
for_each = { for index, az_name in data.aws_availability_zones.available.names : index => az_name }
vpc_id = aws_vpc.wpl_vpc.id
cidr_block = cidrsubnet(var.vpc_cidr, 8, each.key + 10)
availability_zone = data.aws_availability_zones.available.names[each.key]
map_public_ip_on_launch = true
tags = {
Name = "WPL-PublicSubnet"
CreatedBy = var.created_by
}
}
output "wpl_public_subnet_ids" {
value = [aws_subnet.wpl_public_subnet.*.id]
}
I get an error:
Error: Unsupported attribute
on ../modules/vpc/outputs.tf line 5, in output "wpl_public_subnet_ids":
5: value = [aws_subnet.wpl_public_subnet.*.id]
This object does not have an attribute named "id".
However, everything works like charm, if I replace the output with this one:
aws_subnet.wpl_public_subnet.0.id
How could I output all subnet ids values?
Since you are using for_each, you will have a map, not a list. Thus, you have to get values first, before getting the ids. Also you don't need extra square brackets:
output "wpl_public_subnet_ids" {
value = values(aws_subnet.wpl_public_subnet)[*].id
}
I am getting the following error:
The given value is not suitable for child module variable "subnets" defined at modules/efs/variables.tf:28,1-19: list of string required.
This is how I am calling my EFS module:
module "efs_media" {
source = "./modules/efs"
namespace = "eg"
stage = "test"
name = var.efs_names[1]
region = var.region
vpc_id = module.vpc.config.vpc_id
subnets = module.vpc.config.private_subnet_ids
security_groups = [module.cluster.config.node_security_group]
}
and below is the VPC output file:
output "config" {
value = {
vpc_id = aws_vpc.network.id
public_subnet_ids = { for az, subnet in aws_subnet.public : az => subnet.id }
private_subnet_ids = { for az, subnet in aws_subnet.private : az => subnet.id }
}
}
and this is the main output file:
output "vpc_config" {
value = module.vpc.config
}
output "iam_config" {
value = module.iam.config
}
output "cluster_config" {
value = module.cluster.config
}
output "odic_config" {
value = module.cluster.odic_config
}
In your module output private_subnet_ids is a map of az: subnet.id. Your efs_media module wants a list of subnet IDs only which is asking for a list of strings as shown by the error message in the question.
You can turn a map into a list of its values by using the values function. So in your case you could call your efs_media module like this:
module "efs_media" {
source = "./modules/efs"
namespace = "eg"
stage = "test"
name = var.efs_names[1]
region = var.region
vpc_id = module.vpc.config.vpc_id
subnets = values(module.vpc.config.private_subnet_ids)
security_groups = [module.cluster.config.node_security_group]
}