Terraform - 如何在条件运算符中使用条件创建的资源的输出?

Sha*_*nde 29 terraform terraform-provider-aws

我有一个情况,如果用户不提供 vpc id,我必须创建 aws_vpc 资源。之后,我应该使用该 VPC 创建资源。

现在,我在创建资源时应用条件aws_vpc。例如,仅当existing_vpc为 false 时才创建 VPC:

count                = "${var.existing_vpc ? 0 : 1}"
Run Code Online (Sandbox Code Playgroud)

接下来,例如,我必须在 VPC 中创建节点。如果existing_vpc为 true,则使用var.vpc_id,否则使用从资源计算出的 VPC ID aws_vpc。

但是,问题是,如果existing_vpc为 true,aws_vpc则不会创建新资源,并且三元条件无论如何都会尝试检查资源是否aws_vpc正在创建。如果没有创建,terraform 就会出错。

在 上使用条件运算符时出现错误的示例aws_subnet:

Resource 'aws_subnet.xyz-subnet' not found for variable 'aws_subnet.xyz-subnet.id'
Run Code Online (Sandbox Code Playgroud)

导致错误的代码是:

subnet_id = "${var.existing_vpc ? var.subnet_id : aws_subnet.xyz-subnet.id}"
Run Code Online (Sandbox Code Playgroud)

如果两者相互依赖,我们如何创建条件资源并根据它们为其他配置分配值?

小智 36

您可以按如下方式访问动态创建的模块和资源

output "vpc_id" {
  value = length(module.vpc) > 0 ? module.vpc[*].id : null
}
Run Code Online (Sandbox Code Playgroud)
  • 如果计数 = 0,则输出为空
  • 如果 count > 0,则输出为 vpc id 列表

如果count = 1并且您想要接收单个 vpc id,您可以指定:

output "vpc_id" {
  value = length(module.vpc) > 0 ? one(module.vpc).id : null
}
Run Code Online (Sandbox Code Playgroud)


P B*_*rke 5

以下示例演示如何有选择地指定是否创建资源(使用条件运算符),并演示如何在未创建资源时处理返回输出。这恰好是使用模块完成的,并使用object变量的元素作为标志来指示是否应该创建资源。

但要具体回答您的问题,您可以使用条件运算符,如下所示:


    output "module_id" {
       value = var.module_config.skip == true ? null : format("%v",null_resource.null.*.id)
    }

Run Code Online (Sandbox Code Playgroud)

并访问调用 main.tf 中的输出:

module "use_conditionals" {
    source = "../../scratch/conditionals-modules/m2" # << Change to your directory
    a = module.skipped_module.module_id # Doesn't exist, so might need to handle that.
    b = module.notskipped_module.module_id
    c = module.default_module.module_id
}
Run Code Online (Sandbox Code Playgroud)

完整示例如下。注意:这是使用 terraform v0.14.2


# root/main.tf
provider "null" {}

module "skipped_module" {
    source = "../../scratch/conditionals-modules/m1" # << Change to your directory
    module_config = { 
        skip = true         # explicitly skip this module.
        name = "skipped" 
    }
}

module "notskipped_module" {
    source = "../../scratch/conditionals-modules/m1" # << Change to your directory
    module_config = { 
        skip = false        # explicitly don't skip this module.
        name = "notskipped"
    }
}

module "default_module" {
    source = "../../scratch/conditionals-modules/m1" # << Change to your directory
    # The default position is, don't skip. see m1/variables.tf
}

module "use_conditionals" {
    source = "../../scratch/conditionals-modules/m2" # << Change to your directory
    a = module.skipped_module.module_id
    b = module.notskipped_module.module_id
    c = module.default_module.module_id
}

# root/outputs.tf
output skipped_module_name_and_id {
    value = module.skipped_module.module_name_and_id
}

output notskipped_module_name_and_id {
    value = module.notskipped_module.module_name_and_id
}

output default_module_name_and_id {
    value = module.default_module.module_name_and_id
}
Run Code Online (Sandbox Code Playgroud)

模块


# m1/main.tf
resource "null_resource" "null" {
    count = var.module_config.skip ? 0 : 1 # If skip == true, then don't create the resource.

    provisioner "local-exec" {
        command = <<EOT
        #!/usr/bin/env bash
        echo "null resource, var.module_config.name: ${var.module_config.name}"
EOT
    }
}

# m1/variables.tf
variable "module_config" {
    type = object ({ 
        skip = bool, 
        name = string 
    })
    default = {
        skip = false
        name = "<NAME>"
        }
}

# m1/outputs.tf
output "module_name_and_id" {
   value = var.module_config.skip == true ? "SKIPPED" : format(
      "%s id:%v",
      var.module_config.name, 
      null_resource.null.*.id
   )
}

output "module_id" {
      value = var.module_config.skip == true ? null : format("%v",null_resource.null.*.id)
}
Run Code Online (Sandbox Code Playgroud)