【问题标题】:Terraform: How to set variables in a module based on a conditional?Terraform:如何根据条件在模块中设置变量?
【发布时间】:2020-07-16 01:14:58
【问题描述】:

我想传递一个变量,允许我为 AWS 实例指定 VPC 和子网设置列表。有固定的 VPC 和子网设置是有意义的,所以我只想允许用户使用单个变量选择一个,即使用 A 或 B。

例如,假设我有两个可用的 VPC,它们在 variables.tf 文件中为模块 my_instance 指定:

variable "a_vpc_cidr_block" { default = "105.191.44.0/22" }
variable "a_vpc_id" { default = "id_a"}
variable "a_vpc_name" { default = "vpc_a" }
variable "a_subnet_availability_zone"  { default = "us-east-1a" }
variable "a_subnet_cidr_block" { default = "105.191.25.0/25" }
variable "a_subnet_name" { default = "instance_A" }

variable "b_vpc_cidr_block" { default = "105.191.45.0/22" }
variable "b_vpc_id" { default = "id_b"}
variable "b_vpc_name" { default = "vpc_b" }
variable "b_subnet_availability_zone"  { default = "us-east-1a" }
variable "b_subnet_cidr_block" { default = "105.191.35.0/25" }
variable "b_subnet_name" { default = "instance_B" }

my_instance 模块将采用环境将指定的单个输入变量,其值为“A”或“B”(有没有办法将变量的选项限制为值列表,例如options=['A', 'B']?),并且将在 terraform.tf 中这样调用,用于具有单个实例的 Terraform 配置:

module "my_instance" {
    source = "../../modules/my_instance"
    option = "A"
}

我现在想在模块的主文件 (modules/my_instance/my_instance.tf) 中实现一些逻辑,在该文件中它决定应该使用 modules/my_instance/variables.tf 中的 VPC 和子网设置的两个集合中的哪一个。我想要这样的东西(伪代码):

if var.option == 'A'
    vpc_cidr_block           = var.a_vpc_cidr_block
    vpc_id                   = var.a_vpc_id
    vpc_name                 = var.a_vpc_name
    subnet_availability_zone = var.a_subnet_availability_zone
    subnet_cidr_block        = var.a_subnet_cidr_block
    subnet_name              = var.a_subnet_name
else if var.option == 'B'
    vpc_cidr_block           = var.b_vpc_cidr_block
    vpc_id                   = var.b_vpc_id
    vpc_name                 = var.b_vpc_name
    subnet_availability_zone = var.b_subnet_availability_zone
    subnet_cidr_block        = var.b_subnet_cidr_block
    subnet_name              = var.b_subnet_name
else
    raise an error

# get a data resource identified by the VPC variables
data "aws_vpc" "instance_vpc" {
  cidr_block = var.vpc_cidr_block

  tags = {
    Name = var.vpc_name
  }
}

# get a data resource identified by the VPC variables
data "aws_subnet" "instance_subnet" {
  vpc_id             = var.vpc_id
  cidr_block         = var.subnet_cidr_block
  availability_zone  = var.subnet_availability_zone

  tags = {
    Name = var.subnet_name
  }
}

# create an AWS key pair resource
resource "aws_key_pair" "instance_aws_key_pair" {
  key_name    = "component_key_${terraform.workspace}"
  public_key  = file("~/.ssh/terraform.pub")
}

# create the AWS EC2 instance
resource "aws_instance" "my_aws_instance" {
  key_name        = aws_key_pair.instance_aws_key_pair.key_name
  ami             = "ami-b12345"
  instance_type   = "t2.micro"
  subnet_id       = data.aws_subnet.instance_subnet.id

  connection {
    type        = "ssh"
    user        = "terraform"
    private_key = file("~/.ssh/terraform")
    host        = self.public_ip
  }

  tags = {
    "Name"      : "my_instance_name"
    "Terraform" : "true"
  }
}

这是以某种方式使用计数的问题吗,像这样:

count = var.option == 'A'? 1 : 0

有没有办法做到这一点,或者有更好的方法吗?我对 Terraform 很陌生,所以我可能会遗漏一些明显的东西。

【问题讨论】:

  • 您应该将 variables.tf 拆分为两个文件,变量集在两者之间拆分,并有条件地将文件传递给 terraform plan。管道让这一切变得简单。

标签: terraform terraform-provider-aws


【解决方案1】:

您有几个问题。

首先,您应该能够使用较新的实验性custom validation rules 来断言某个值位于特定的值列表中。

其次,为了确定要使用哪组变量,我建议在本地值中使用旧的 map

例如,

locals {
  vpc_info = {
    "A" = {
      vpc_cidr_block           = var.a_vpc_cidr_block
      vpc_id                   = var.a_vpc_id
      vpc_name                 = var.a_vpc_name
      subnet_availability_zone = var.a_subnet_availability_zone
      subnet_cidr_block        = var.a_subnet_cidr_block
      subnet_name              = var.a_subnet_name
    }
    "B" = {
      vpc_cidr_block           = var.b_vpc_cidr_block
      vpc_id                   = var.b_vpc_id
      vpc_name                 = var.b_vpc_name
      subnet_availability_zone = var.b_subnet_availability_zone
      subnet_cidr_block        = var.b_subnet_cidr_block
      subnet_name              = var.b_subnet_name
    }
  }
}

然后您应该能够在选择的选项中引用特定字段,如下所示

  local.vpc_info[var.option].vpc_name

如果这符合您的所有问题,请告诉我。

【讨论】:

  • 感谢@mjgpy3,这非常有帮助/有用。
猜你喜欢
  • 2018-10-06
  • 1970-01-01
  • 2020-12-14
  • 1970-01-01
  • 2021-11-20
  • 1970-01-01
  • 2020-12-12
  • 2022-07-30
  • 1970-01-01
相关资源
最近更新 更多