Terraform:基于 .tfvars 中的变量有条件地创建资源

Joe*_*rra 22 terraform terraform-provider-cloudflare

我在.tf多个应用程序通用的文件中定义了资源。我通过.tfvars文件填充了许多字段。我需要完全基于.tfvars.

例如,如果我有这样的资源:

resource "cloudflare_record" "record" {
  zone_id = "${data.cloudflare_zones.domain.zones[0].id}"
  name    = "${var.subdomain}"
  value   = "${var.origin_server}"
  type    = "CNAME"
  ttl     = 1
  proxied = true
}
Run Code Online (Sandbox Code Playgroud)

但是后来我cloudflare = false在我的.tfvars文件中声明了类似的东西,我希望能够做这样的事情:

if var.cloudflare {
  resource "cloudflare_record" "record" {
    zone_id = "${data.cloudflare_zones.domain.zones[0].id}"
    name    = "${var.subdomain}"
    value   = "${var.origin_server}"
    type    = "CNAME"
    ttl     = 1
    proxied = true
 }
}
Run Code Online (Sandbox Code Playgroud)

我看过动态块,但看起来您只能使用它们来编辑资源中的字段和块。我需要能够忽略整个资源。

Tra*_*umi 39

扩展@Joel Guerra的答案,在使用count确定是否部署资源后,您可以使用该one()函数来引用没有索引的资源(即不必使用[0])。

例如,定义如下资源后

resource "cloudflare_record" "record" {
  count = var.cloudflare ? 1 : 0
}
Run Code Online (Sandbox Code Playgroud)

定义一个局部变量,如下所示

locals {
  cloudflare_record_somefield = one(cloudflare_record.record[*].some_field)
}
Run Code Online (Sandbox Code Playgroud)

现在cloudflare_record.record[0].some_field您可以使用

local.cloudflare_record_somefield
Run Code Online (Sandbox Code Playgroud)

如果计数为 0(例如var.cloudflare,为false0 并且未创建资源),local.cloudflare_record_somefield则将返回null(而不是在使用索引时返回错误[0])。

参考: https: //developer.hashicorp.com/terraform/language/functions/one


Joe*_*rra 34

这实际上非常简单。count使用如下声明的变量添加具有三元条件的参数.tfvars

resource "cloudflare_record" "record" {
  count = var.cloudflare ? 1 : 0
  zone_id = "${data.cloudflare_zones.domain.zones[0].id}"
  name    = "${var.subdomain}"
  value   = "${var.origin_server}"
  type    = "CNAME"
  ttl     = 1
  proxied = true
}
Run Code Online (Sandbox Code Playgroud)

在这个例子中var.cloudflare是一个在.tfvars文件中声明的布尔值。如果为真,record则将创建计数为 1 。如果为 false,record则将创建计数为 0 。

countapply之后资源就变成了一个组,所以后面在参考使用0-index这个组:

cloudflare_record.record[0].some_field
Run Code Online (Sandbox Code Playgroud)

  • 有没有一种方法可以允许在不使用索引的情况下引用此资源?例如“cloudflare_record.record[0].name”? (5认同)
  • 如果使用计数功能,则需要索引。如果您不想硬编码 0,可以使用 count.index。请参阅:https://www.terraform.io/docs/language/meta-arguments/count.html (4认同)
  • 如果由于计数字段而未创建资源,那么下面的行将失败。```cloudflare_record.record[0].some_field```。那么如何输出这个值 (2认同)

小智 8

我看到的一个问题是,如果您尝试创建的资源已经使用 for_each 那么您不能在资源中同时使用 count 和 for_each 。我仍在尝试寻找答案,如果我找到更好的东西,我会更新。

  • 使用“for_each”,您可以执行“for_each = var.condition”?变量列表:[]` (24认同)
  • 如果我只想跳过 for_each 的一个资源而不是全部资源的创建,该怎么办? (2认同)

Shi*_*and 6

示例场景:您可能想要创建或不创建(切换/使用标志/有条件创建)VM。但除了虚拟机之外,您可能还必须创建/不创建其负载均衡器、目标组和安全组等。

互联网上其他答案的问题是,当您在资源上使用三元运算符时,并且当您尝试在其他资源上引用它时,您总是会收到引用错误或索引错误或空元组错误。

要在指向条件资源时解决此问题,您可以使用以下try语法

resource "aws_vpc" "main" {
  count = var.test_flag ? 1 : 0
  cidr_block       = var.vpc_cidr
  instance_tenancy = var.vpc_instance_tenancy

  tags = {
     Name = "${var.cluster_name}-vpc"
  }

}

resource "aws_internet_gateway" "gw" {
  count =   try(var.test_flag ? 1 : 0, 0) // try block is important here because it has a dependency, here the VPC, but VPC might not need a try block because it is the parent.

  vpc_id = aws_vpc.main[0].id

  tags = {
    Name = "${var.cluster_name}-IG"
  }
}
Run Code Online (Sandbox Code Playgroud)