Terraform 访问 count 和 for_each 输出中的值

问题描述 投票:0回答:1

我有一个用于部署服务器的模块代码,带有网络的动态块,如下所示

resource "hcloud_server" "this" {
  count               = var.instance_count
  name                = "${local.instance_prefix}.${var.instance_name}${format("%02d", count.index + 1)}"
  image               = data.hcloud_image.image.id
  server_type         = var.flavour
  datacenter          = var.datacenter
  ssh_keys            = var.sshkeys
  placement_group_id  = hcloud_placement_group.this.id
  labels              = local.labels_default
  firewall_ids        = var.firewall_ids

  lifecycle {
    ignore_changes = [
      ssh_keys,
      image,
    ]
  }

  public_net {
    ipv4_enabled = var.public_ipv4
    ipv6_enabled = var.public_ipv6
  }

  dynamic "network" {
    for_each = var.network
    content {
      network_id = lookup(network.value, "network_id")
      ip         = lookup(network.value, "private_ip", null)
      # https://github.com/hetznercloud/terraform-provider-hcloud/issues/650#issuecomment-1497160625
      alias_ips = []
    }
  }
}

根据文档,

network
块有一个名为 ip 的属性,它保存分配的IP,请参阅https://registry.terraform.io/providers/hetznercloud/hcloud/latest/docs/resources/server#network

我想在模块输出中访问这个私有IP,但我无法到达那里。我的输出现在看起来像这样

output "private_ip" {
  description = "List with public IPv4 IPs of the instances"
  value       = hcloud_server.this.*.network[*].ip
}

并产生以下错误

╷
│ Error: Unsupported attribute
│ 
│   on .terraform/modules/testserver/outputs.tf line 18, in output "private_ip":
│   18:   value       = hcloud_server.this.*.network[*].ip
│ 
│ Can't access attributes on a set of objects. Did you mean to access an attribute across all elements of the set?

如何访问输出中的 ip 属性(最好与实例名称结合使用)?

我尝试使用

*
 [count.index]
但我没有成功。

感谢您的帮助!

terraform hetzner-cloud
1个回答
0
投票

表达式

hcloud_server.this.*.network[*].ip
包含嵌套的splat表达式,这意味着一个“splat”的结果正在被另一个“splat”消耗。因此,了解 Terraform 如何评估这些非常重要。

hcloud_server.this.*.network
生成一个列表,其长度与
hcloud_server.this
的实例数量匹配(在您的情况下为
var.instance_count
),其中每个元素都是相应实例的
network
属性的值。从错误消息中我推断
network
是一组对象,因此
hcloud_server.this.*.network
的结果是对象集的列表。

然后,

[*].ip

 部分尝试访问该列表中每个元素的 
ip
 属性。但该列表的元素是对象集而不是单个对象,因此 
.ip
 访问失败。正如错误消息所述,集合没有任何属性。


如果您的目的是收集资源所有实例中所有

ip

 块中的所有 
network
 属性——而不保留有关每个 IP 地址属于哪个实例的任何信息——那么一种合理的方法是使用 
flatten 函数
 将对象集列表转换为对象列表,然后将 
[*]
运算符应用于该结果:
flatten(hcloud_server.this.*.network)[*].ip

flatten(hcloud_server.this.*.network)

的结果是一个对象列表,丢弃嵌套集合并将所有元素收集到一个列表中。因此,

[*].ip
部分现在可以工作,因为现在可以针对该列表中的每个对象评估
.ip

请注意,
.*

是一个

旧版(仅属性)splat表达式
,支持向后兼容旧版本的Terraform,但在本例中不需要,因为现代的[*]运算符与我上面写的表达:
flatten(hcloud_server.this[*].network)[*].ip

这个修改是不需要的——这个表达式与上面的结果完全相同——但是现代的 splat 运算符对于最近学习 Terraform 的人来说更熟悉,所以我个人更喜欢使用它,除了极少数情况下,我实际上
需要

传统运营商的行为略有不同。 (这种情况并不经常发生;这就是为什么它有一个更普遍适用的替代品!)

© www.soinside.com 2019 - 2024. All rights reserved.