当资源 for_each 需要从有计数的数据源中获取数据时如何控制流程

How to control flow when resource for_each need to fetch data from data source which is having count

当资源for_each需要从有计数的数据源获取数据时如何控制流程

我的要求是只从数据源读取数据,所以我构建了类似的代码

我在下面一行遇到问题:

command = "echo ${data.null_data_source.values.*.outputs}"

我得到的错误是:

╷ │ Error: Invalid template interpolation value │ │ on foreachloop.tf line 79, in resource "null_resource" "null_resource_simple": │ 79: command = "echo ${data.null_data_source.values.*.outputs}" │ ├──────────────── │
│ data.null_data_source.values is tuple with 2 elements │ │ Cannot include the given value in a string template: string required.


│ Error: Invalid template interpolation value │ │ on foreachloop.tf line 79, in resource "null_resource" "null_resource_simple": │ 79:
command = "echo ${data.null_data_source.values.*.outputs}" │
├──────────────── │ │ data.null_data_source.values is tuple with 2 elements │ │ Cannot include the given value in a string template: string required.


示例代码如下:

variable "create_access_only" {
  default = true
  //default = false
}

locals {
  test1 = "new value db"
  test2 = "new value web"
  string_values = "${local.test1},${local.test2}"
  list_test_data = "${split(",", local.string_values)}"
}

output "testlist" {
  value = local.list_test_data
}

variable "data_source_key" {
    default = "test"
}


data "null_data_source" "values" {
  count = "${length(local.list_test_data)}"    
  inputs = {
    data_source_key = "${local.list_test_data[count.index]}"
  }
}

resource "null_resource" "null_resource_simple" {
   for_each = var.create_access_only ? toset(local.list_test_data) : []

    provisioner "local-exec" {
       command = "echo ${data.null_data_source.values.*.outputs}"



      // command = "echo ${data.null_data_source.values}"
      // command = "echo ${each.key} ${each.value.name1} ${each.value.name2}"
      // command = "echo ${each.key}"
      // command = "echo ${data.null_data_source.values["${each.key}"]}"
      // command = "echo ${data.null_data_source.values["${count.index}"]}"
      // command = "echo ${local.list_test_data}"
    }
}

实际上我需要从数据源响应中获取数据。 我的要求是数据源的第一个值将反映在资源第一个循环中,依此类推

此外,我需要从数据源的响应中获取 ID,我知道我在这里使用 null_data_source 但我的实际脚本数据源会给我 ID 和其他响应

示例:data.datasourcename.varaiablename.namespace[0].id

解决此问题的一种方法是同时使用 for_eachnull_data_source。但是,当 运行 代码时,这里有一个警告:

╷
│ Warning: Deprecated Resource
│ 
│   with data.null_data_source.values,
│   on data.tf line 105, in data "null_data_source" "values":
│  105: data "null_data_source" "values" {
│ 
│ The null_data_source was historically used to construct intermediate values to re-use elsewhere in configuration, the same can now be achieved using locals
│ 
│ (and 2 more similar warnings elsewhere)
╵

正如您在输出中看到的那样,使用局部变量也可以实现相同的目的。这是有效的代码:

resource "null_resource" "null_resource_simple" {
  for_each = var.create_access_only ? toset(local.list_test_data) : []

  provisioner "local-exec" {
    command = "echo ${data.null_data_source.values[each.key].outputs["data_source_key"]}"
  }
}

data "null_data_source" "values" {
  for_each = toset(local.list_test_data)
  inputs = {
    data_source_key = each.key
  }
}

variable "create_access_only" {
  default = true
  //default = false
}

variable "data_source_key" {
  default = "test"
}

output "testlist" {
  value = local.list_test_data
}

请注意,当使用 toset 时,each.keyeach.value 将是相同的 [1]。

这里是 terraform plan 命令的输出:

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # null_resource.null_resource_simple["new value db"] will be created
  + resource "null_resource" "null_resource_simple" {
      + id = (known after apply)
    }

  # null_resource.null_resource_simple["new value web"] will be created
  + resource "null_resource" "null_resource_simple" {
      + id = (known after apply)
    }

Plan: 2 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + testlist = [
      + "new value db",
      + "new value web",
    ]


[1] https://www.terraform.io/language/meta-arguments/for_each#the-each-object