【问题标题】:Cycle Through External Data Source in terraform在 terraform 中循环访问外部数据源
【发布时间】:2019-01-16 18:11:46
【问题描述】:

我正在尝试在 terraform 中配置 n 个 VM(假设 n=5)。

要注意的是,对于分配给相应 VM 的每个 IP,我首先需要调用一个外部工具(一个 .exe)。该工具采用 2 个参数:要获取的 IP 的正则表达式模式和机器名称。然后,该工具会根据提供的正则表达式从充当 IPAM(IP 地址管理解决方案)的 Sharepoint Excel 文件中读取一个要使用的免费 IP 地址。该工具还会更新 Excel 文件,以便在返回的 IP 旁边标记提供的机器名称。

对于单个 VM,这工作得很好,一切都按预期完成,利用一个外部数据源和一个资源。机器名称是从输入文件中读取的,与 IP 的正则表达式相同,它使用自己的文件。然后调用外部工具:

data "external" "Machine_name" {
    program = ["cmd.exe", "/c type c:\\Users\\malbert\\Desktop\\Excel2VM\\MachineName.txt"]
}

data "external" "IPregexMatchPattern" {
    program = ["cmd.exe", "/c type c:\\Users\\malbert\\Desktop\\Excel2VM\\IPregexMatchPattern.txt"]
}

output "MachineName" {
  value = "${data.external.Machine_name.result.name}"
}

data "external" "NetworkObtainedData" {
      program = ["cmd.exe", "/c ExcelUpdateTool.exe ${data.external.IPregexMatchPattern.result.IPregex} ${data.external.Machine_name.result.name} available" ]
}

# Use as an output so the user can see the value as well
output "ip" {
    value = "${data.external.NetworkObtainedData.result.ip}"
}
output "netmask" {
    value = "${data.external.NetworkObtainedData.result.netmask}"
}

output "gw" {
    value = "${data.external.NetworkObtainedData.result.gw}"

接下来,根据输入文件命名虚拟机:

resource "vsphere_virtual_machine" "vm" {
  # Name the VM
  name             = "${data.external.Machine_name.result.name}"

  resource_pool_id = "${data.vsphere_resource_pool.pool.id}"
  datastore_id     = "${data.vsphere_datastore.datastore.id}"

但是,在尝试扩展 n 个 VM 时,我遇到了以下问题:我可以在资源部分中迭代 n 个项目,从而产生 n 个 VM; 但是我不知道如何对外部数据源做同样的事情,因为这个不支持为循环设计的结构(计数/长度(...))。到目前为止我所取得的成就如下。定义了一个新的 .tf 文件,因此它在一个列表中包含所有机器的名称:

variable machineNamesList {
        default = [ "terraform-firstMachine", "terraform-secondMachine"]
}

resource 部分下,列表循环显示:

resource "vsphere_virtual_machine" "vm" {
  count = "${length(var.machineNamesList)}"
  # We'll name the VM the same as the guest running inside
  name             = "${var.machineNamesList[count.index]}"

  resource_pool_id = "${data.vsphere_resource_pool.pool.id}"
  datastore_id     = "${data.vsphere_datastore.datastore.id}"

但是,每次处理一个新的 VM 时,我如何调用外部工具 n 次?

任何指向正确方向的指针都将不胜感激。

【问题讨论】:

  • 如果您可以展示到目前为止您已经尝试过的单个 VM 的工作代码和不适用于多个 VM 的代码以及为什么它不起作用(显示任何错误或解释它的作用以及与您想要的有何不同)。
  • @ydaetskcoR:你说得对——我的原帖是匆忙写的。我现在已经扩展了它,还插入了图片(不幸的是不是内联的,因为我还没有最低要求的声望)。
  • 请不要包含代码截图。而是将代码作为文本粘贴到问题中并将其格式化为代码(通过 UI 按钮,将所有内容缩进 4 个空格或突出显示所有内容并按 ctrl k)
  • @ydaetskcoR 谢谢。并完成:)

标签: terraform


【解决方案1】:

所有resourcedata 块都支持count 参数,因此您可以通过将各种对象上的count 设置为相同的表达式来实现此目的:

variable "machine_count" {
}

data "external" "machine_name" {
  count = "${var.machine_count}"

  # (presumably in practice you'll use count.index in here somewhere)
  program = ["cmd.exe", "/c", "type c:\\Users\\malbert\\Desktop\\Excel2VM\\MachineName.txt"]
}

resource "vsphere_virtual_machine" "vm" {
  count = "${var.machine_count}"

  name = "${data.external.machine_name.*.result.name[count.index]}"

  # ...etc...
}

Terraform 文档的using variables with count 部分提供了有关此机制的更多信息。尽管那里的示例讨论的是 resource 块,但 count 机制对于 resourcedata 块的工作方式相同。

【讨论】:

  • 谢谢,马丁。我遇到的问题是 NetworkObtainedData 外部数据源需要调用 machine_count 次。我在 NetworkObtainedData 中添加了count = "${var.machine_count}",就在要调用的程序的正上方。但是,当尝试分配返回给 VM 的每个 IP 地址时,在资源中使用 ipv4_address = "${data.external.NetworkObtainedData.result.*.ip[count.index]}",我在 terraform 计划的输出中得到 vsphere_virtual_machine.vm[0]: Resource 'data.external.NetworkObtainedData' not found for variable 'data.external.NetworkObtainedData.result.*.ip'
  • 就像您在github.com/hashicorp/terraform/issues/20037 中指出的那样,我使用的是...result.*.ip... 而不是...*.result.ip。更改后一切正常。
猜你喜欢
  • 2019-08-27
  • 2020-04-18
  • 2021-06-29
  • 2020-04-04
  • 1970-01-01
  • 2013-12-29
  • 1970-01-01
  • 2018-08-18
  • 2021-11-25
相关资源
最近更新 更多