循环中的 pulumi export 语句意外工作

pulumi export statement in a loop works unexpectedly

我使用 pulumi python 创建了多个 azure VM。

基本上,我只是将azure-py-webserver中的示例代码放入一个循环中,当然,每个资源都有其唯一的名称和循环索引。我希望循环结束时的 export 语句会显示所有虚拟机创建后的 public IP。

for i in range(2):
    vm_name = f"sol{i}"
    ...
    ...
    ...
    public_ip_addr = vm.id.apply(lambda _: network.get_public_ip_address_output(
        public_ip_address_name=public_ip.name,
        resource_group_name=resource_group.name))

    export(f"{vm_name} IP", public_ip_addr.ip_address)

所有资源均已成功创建,但导出输出始终显示所有 VM 的 相同 IP,如下所示。

    Type                                      Name            Status
 +   pulumi:pulumi:Stack                       azure-vms-dev   created
 +   ├─ azure-native:resources:ResourceGroup   resource_group  created
 +   ├─ azure-native:network:VirtualNetwork    sol_VNET        created
 +   ├─ azure-native:network:PublicIPAddress   sol0_PublicIP   created
 +   ├─ azure-native:network:PublicIPAddress   sol1_PublicIP   created
 +   ├─ azure-native:network:NetworkInterface  sol0_Nic        created
 +   ├─ azure-native:network:NetworkInterface  sol1_Nic        created
 +   ├─ azure-native:compute:VirtualMachine    sol1            created
 +   └─ azure-native:compute:VirtualMachine    sol0            created

Outputs:
    sol0 IP:: "20.239.154.16"
    sol1 IP:: "20.239.154.16"

Resources:
    + 9 created

Duration: 1m55s

我的问题是,如何导出所有虚拟机的 public IP?

导出只发生一次,在程序结束时。如果你想导出多个值,你可以简单地创建一个数组或字典,将值附加到该数据结构并导出它。例如:

public_ip_address = [] # create an array to store the information
for i in range(2):
    vm_name = f"sol{i}"
    ...
    ...
    ...
    public_ip_addr = vm.id.apply(lambda _: network.get_public_ip_address_output(
        public_ip_address_name=public_ip.name,
        resource_group_name=resource_group.name))
    public_ip_addresses.append(public_ip_addr)


export(f"addresses", public_ip_addresses)

我刚刚解决了这个问题。

正如@Frassle 所指出的,这个问题的根本原因是我直接在 lambda 表达式中使用了循环的局部变量。

学习了Pulumi的How to Use Python Lambda Functions and the Inputs and Outputs,我觉得应该从apply方法的参数中得到需要的变量。

修改后的代码如下:

for i in range(2):
    vm_name = f"sol{i}"
    ...
    ...
    ...
    # Get IP address as an output.
    combined_output = Output.all(
        vm_id=vm.id,
        public_ip_name=public_ip.name,
        resource_group_name=resource_group.name,
    )
    public_ip_addr = combined_output.apply(
        lambda args: network.get_public_ip_address_output(
            public_ip_address_name=args["public_ip_name"],
            resource_group_name=args["resource_group_name"],
        )
    )
    export(f"{vm_name} IP", public_ip_addr.ip_address)

现在我可以获得我想要的所有 Public 个 IP:

Outputs:
  - sol0 IP: "20.239.193.78"
  - sol1 IP: "20.239.195.132"