如何在 Terraform 变量的默认值中引用资源?

How to reference resources in the default value of a Terraform variable?

我从我的 AWS 上的网络 terraform 实施中获得了子网和 vpc id 的输出。 tfstate 存储在 s3 example/networking/terraform.tfstate.

public_subnets = [
  "subnet-0c1ed9933fxxxxxf",
  "subnet-0ee61aaa65xxxx3",
  "subnet-0b9bcf251ebxxxxx54",
]
vpc_id = "vpc-085b3d740xxxxxx"

我不想手动将输出 vpc 或子网放在 tf 代码中,而是动态调用它。但是在下面抛出了这个错误

| Error: Variables not allowed
│ 
│   on main.tf line 28, in variable "target_vpc":
│   28:   default     = "${data.terraform_remote_state.vpc.outputs.vpc_id}"
│ 
│ Variables may not be used here.
╵
╷
│ Error: Variables not allowed
│ 
│   on main.tf line 34, in variable "target_subnet":
│   34:   default     = "${data.terraform_remote_state.subnet.outputs.public_subnets[1]}"
│ 
│ Variables may not be used here.

代码:

provider "aws" {
  region = "eu-west-1"
}

data "terraform_remote_state" "vpc" {
  backend = "s3"
  config = {
    bucket = "example-comp"
    key    = "comp/networking/terraform.tfstate"
    region = "eu-west-1"
  }
}

data "terraform_remote_state" "subnet" {
  backend = "s3"
  config = {
    bucket = "example-comp"
    key    = "comp/networking/terraform.tfstate"
    region = "eu-west-1"
  }

} 

variable "target_vpc" { 
  default     = "${data.terraform_remote_state.vpc.outputs.vpc_id}"
  description = "Project Default VPC: aws acct as default"
}

variable "target_subnet" { 
  default     = "${data.terraform_remote_state.subnet.outputs.public_subnets[1]}"
  description = "Project Default VPC SN: eu-west-1"
}

variable "aws_ami" {
  type = string
  default = "ami-0b850cf02cc00fdc8"
}

variable "server_type" {
  type = string
  default = "t2.micro"
}   

variable "target_keypairs" {
  type = string
  default     = "EC2 Tutorial"
  description = "Project default keys:"
}   

variable "project" {
  default = "example-comp"
}

terraform {
  required_version = ">= 0.12.31"

  backend "s3" {
    bucket = "example-comp"
    key    = "comp/simple-instance/terraform.tfstate"
    region = "eu-west-1"
  }
}

resource "aws_security_group" "dm_sg_res" {
  name        = "${var.project}-server-sg"
  description = "multiple firewall rules"
  vpc_id      = var.target_vpc

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 3000
    to_port     = 3000
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_instance" "server_inst_res" {
  ami                    = var.aws_ami
  instance_type          = var.server_type
  vpc_security_group_ids = [aws_security_group.dm_sg_res.id]
  key_name               = var.target_keypairs
  subnet_id              = var.target_subnet

    connection {
      type        = "ssh"
      user        = "centos"
      private_key = "${file("EC2Tutorial.pem")}"
      timeout     = "3m"
      host        = "${self.public_ip}"
    }

    provisioner "remote-exec" {
      inline = [
        "sudo yum update -y",
        "sudo yum install git wget vim unzip -y",
        "sudo setenforce 0"
      ]
    }

    provisioner "local-exec" {
        command = "ANSIBLE_HOST_KEY_CHECKING=false ansible-playbook -u centos -i '${self.public_ip},' --private-key 'EC2Tutorial.pem' site.yaml"
    }

  tags = {
    Name = "${var.project}-server"
  }
}

output "pub_ip" {
  value = ["${aws_instance.server_inst_res.public_ip}"]
}

您正在为默认值 variable 引用数据资源,这是不允许的(请参阅 Terraform documentation on input variables):

variable "target_vpc" {
  default = data.terraform_remote_state.vpc.outputs.vpc_id
}

相反,使用 local 变量作为中间值:

locals {
  target_vpc = var.target_vpc == null ? data.terraform_remote_state.vpc.outputs.vpc_id : var.target_vpc
}

variable "target_vpc" {
  default = null
}

在其他资源中引用 VPC 时,请使用 local.target_vpc 而不是 var.target_vpc