'pulumi export statement in a loop works unexpectedly
I used pulumi python to create multiple azure VMs.
Basically, I just put the example code from azure-py-webserver into a loop, of course, each resource has its unique name with the index of the loop. I expected the export
statement at the end of the loop would show me the public IPs of all VMs after they were created.
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)
All resources were created successfully, but the export output always showed a same IP for all VMs as below.
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
My question is, how could I export the public IPs of all VMs?
Solution 1:[1]
I just fixed this issue.
As @Frassle pointed out, the root cause of this issue is that I used the loop's local variable in the lambda expression directly.
After I studied How to Use Python Lambda Functions and the Inputs and Outputs of Pulumi, I think I should get the required variable from the argument of the apply method.
Here is the modified code:
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)
Now I can get all the Public IPs I want:
Outputs:
- sol0 IP: "20.239.193.78"
- sol1 IP: "20.239.195.132"
Solution 2:[2]
Exports only happen once, at the end of a program. If you want to export more than one value, you can simply create an array or dict, append the values to that data structure and export that. So for example:
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)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | flyisland |
Solution 2 | jaxxstorm |