简体   繁体   中英

How i get any value from the tuple in output of module in Terraform?

I create three modules in Terraform one for EC2, VPC, and security groups. I run full stack for the three modules and I use the output of security groups and the VPC module in the EC2 module but I get that error:

creating EC2 Instance: InvalidSubnetID.NotFound: The subnet ID 'module.vpc_main.primary_private_subnets_id.value[0]' does not exist
        status code: 400, request id: d94befb9-a846-47f9-a7c2-c588996a723c

  on .terraform/modules/main_ec2/main.tf line 66, in resource "aws_instance" "create_instance":
  66: resource "aws_instance" "create_instance" {

the output of the VPC module:

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

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

the output in the state file

outputs": {
    "primary_private_subnets_id": {
      "value": [
        "subnet-098d3aab6a102656c",
        "subnet-073699d0e266072d6",
        "subnet-07755f92e02ca8756",
        "subnet-0a2f21a6e9b80d91e"
      ],
      "type": [
        "tuple",
        [
          "string",
          "string",
          "string",
          "string"
        ]
      ]
    },
    "primary_public_subnets_id": {
      "value": [
        "subnet-0aea672a2f19cee51",
        "subnet-0a014df85bc56acd3"
      ],
      "type": [
        "tuple",
        [
          "string",
          "string"
        ]
      ]
    },

the variables

variable "subnet_id" {
  type = list(string)
  default = [ "module.vpc_main.primary_public_subnets_id[0]", "module.vpc_main.primary_private_subnets_id[1]" ]
}

the part of EC2 module:

resource "aws_instance" "create_instance" {

  ami = "${element(data.aws_ami.ami_id.*.id, count.index)}"

  instance_type = var.EC2_Type[count.index]

  subnet_id = var.subnet_id[count.index]

  associate_public_ip_address = var.associate_public_ip_address[count.index]

  vpc_security_group_ids = [ var.vpc_security_group_ids[count.index] ]

  key_name = "${local.name}-KP-${var.Server_Name[count.index]}"

  iam_instance_profile = aws_iam_instance_profile.iam_profile.name

  private_ip = var.EC2_IP[count.index]
  count = length(var.ami_name)

}

the EC2 calling module:

module "main_ec2" {
    source  = "/home/reham/Data/projectes/terraform/modules/EC2Module"
    EC2_Type = var.EC2_Type
    EC2_IP = var.EC2_IP
    subnet_id = var.subnet_id
    associate_public_ip_address = var.associate_public_ip_address
    vpc_security_group_ids = var.vpc_security_group_ids
}

please note any of the modules work separately in a good way. please how do I get any value from the tuple in the output of the module in Terraform?

If we consider the VPC module is being called as well, you don't have to add the default values to the variable subnet_id . Instead, you can leave the variable definition without any values:

variable "subnet_id" {
  type = list(string)
}

Take a note here that you are using a variable of type list(string) while the argument for the EC2 instance expects only one value, so it is of type string . Furthermore, in the EC2 module, you are setting the count meta-argument to depend on the length of variable ami_name . So even if you were to make correct value assignments I think you would get a lot of unexpected results. Prior to making any calls to the EC2 module, I suggest fixing this to look more like:

resource "aws_instance" "create_instance" {
  count                       = length(var.subnet_id)
  ami                         = element(data.aws_ami.ami_id.*.id, count.index)
  instance_type               = var.EC2_Type[count.index]
  subnet_id                   = var.subnet_id[count.index]
  associate_public_ip_address = var.associate_public_ip_address[count.index]
  vpc_security_group_ids      = [var.vpc_security_group_ids[count.index]]
  key_name                    = "${local.name}-KP-${var.Server_Name[count.index]}"
  iam_instance_profile        = aws_iam_instance_profile.iam_profile.name
  private_ip                  = var.EC2_IP[count.index]
}

It is also a good practice to move the meta-arguments to the top of the resource block because it's more visible to the reader. I have set the count to use the length of the subnet_id variable as I am guessing you want an EC2 instance in each of the subnets.

Another thing that is unclear is if you want to have EC2 instances in private subnets, public subnets, or both. For the sake of simplicity, let's say you want them in the public subnet (since you have the associate_public_ip_address argument defined. Here you made another mistake, which is trying to set a bool argument (which can have only true or false value) to use a variable with count.index ( var.associate_public_ip_address[count.index] ). That also will not work unless your associate_public_ip_address is a list of boolean values. If so, that code can stay as such. Last, but not the least, since the VPC module is providing outputs you want, the way to use those outputs is as follows:

module "vpc" {
 ... your module call goes here ...
}

module "main_ec2" {
  source                      = "/home/reham/Data/projectes/terraform/modules/EC2Module"
  EC2_Type                    = var.EC2_Type
  EC2_IP                      = var.EC2_IP
  subnet_id                   = module.vpc.primary_public_subnets_id
  associate_public_ip_address = var.associate_public_ip_address
  vpc_security_group_ids      = var.vpc_security_group_ids
}

Also, if there are other outputs provided by the VPC module (eg, the Security Group IDs), you would call it the same as for the subnet IDs:

module.vpc.<name of the output>

Even with the details from my answer there is no guarantee it will work. A lot of refactoring is required for the code to work. Additionally, I strongly suggest understanding types [1] of values arguments in a resource expect ( string , list(string) , bool , etc.). You also need to make sure you understand how to reference module outputs [2].


[1] https://www.terraform.io/language/expressions/types

[2] https://www.terraform.io/language/expressions/references#child-module-outputs

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM