If I pass output form one stack to another, can I ...
# python
l
If I pass output form one stack to another, can I create resources based on that output? e.g stak1
Copy code
instances =[]
instances.append(pulumi.Output.all(instance.name,instance.id).apply(lambda args: f"{args[0]}:{args[1]}") )
pulumi.export('my_vms', {f"VM_{i}": vm for i,vm in enumerate(self.instances)})

so I get something like {'VM_1': 'vmname:id', 'VM_0': 'vmname:id'}
stack2
Copy code
stack_ref = pulumi.StackReference("stack1")
my_vms= stack_ref.outputs['my_vms']

some code that for each vm creates other resources
f
Yes 🙂
l
I do something wrong then ;/ I use apply for 'my_vms' and call function that loops over 'my_vms' to create port and attach it to vm. resources are created only for first element. I guess this part is incorrect stack2
Copy code
stack_ref = pulumi.StackReference("stack1")
my_vms= stack_ref.outputs['my_vms']
myinstance=mypackage.myresource('somename',my_vms)
myinstance.start()

class myresource(pulumi.ComponentResource): #removed other code lines
    def __init__(self,name,vms, opts = None):
        super().__init__('abc:service:vmsstuff',name, None,opts)
        self.child_opts = pulumi.ResourceOptions(parent=self)
        self.vms: pulumi.Output = vms

    def start(self):
        self.vms.apply(lambda my_vms:  self.vms_loop(my_vms,sec_group_backend))

   def vms_loop(self,vms,sec_group_backend):
        for vm in vms:
            vm_name = vms[vm].split(":")[0]
            id =  vms[vm].split(":")[1]
            self.attach_port(vm_name,id,sec_group_backend)

    def attach_port(self,vm_name,vm_id,sec_group_backend):
        cross_subnet_port=self.create_port(vm_name,sec_group_backend)
        interface = openstack.compute.InterfaceAttach(vm_name,
            instance_id=vm_id,
            port_id=cross_subnet_port.id,
            opts = pulumi.ResourceOptions(parent=cross_subnet_port,deleted_with=cross_subnet_port))

    def create_port(self,vm_name: str,sec_group_backend) -> openstack.networking.Port :
        port = openstack.networking.Port(f"{vm_name}_cross_subnet_port",
            network_id=openstack.networking.get_network(name=self.existing_network).id, 
            admin_state_up=True,
            security_group_ids=[sec_group_backend.id],
            opts = self.child_opts)
        return port
I removed other lines from the code
f
I've a meeting right now but will take a look in ~30m or so if no one else has replied; keep giving details :D
alright, back. 1st thing:
pulumi.StackReference("stack1")
should be "fully qualified" i.e.
{org}/{program}/{stack}
for your very first example (stack1 / the "source" stack), you wouldn't necessarily have to append + Output.all + apply; if you build up a
[]
of
aws.ec2.Instance
you could
pulumi.export('instances', instances)
i digress though - the point is you can do this 🙂 quick example: stack 1 is
rob/stack1/dev
Copy code
import pulumi

# hardcode some instance data
instances = [
    "web:ami-03e31863b8e1f70a5",
    "api:ami-03e31863b8e1f70a5",
    "db:ami-03e31863b8e1f70a5",
]
# export
pulumi.export('instances', {f"VM_{i}": vm for i, vm in enumerate(instances)})
stack 2 is
rob/stack2/dev
Copy code
import pulumi

stack1_ref = pulumi.StackReference("rob/stack1/dev")

myinstance=network.Network('somename', stack1_ref.get_output('instances'))
myinstance.start()

### in network.py

import pulumi

class Network(pulumi.ComponentResource):  #removed other code lines
    def __init__(self, name, vms, opts=None):
        super().__init__('abc:service:vmsstuff', name, None, opts)
        self.child_opts = pulumi.ResourceOptions(parent=self)
        self.vms: pulumi.Output = vms

    def start(self):
        self.vms.apply(lambda my_vms: self.vms_loop(my_vms))

    def vms_loop(self, vms):
        for vm in vms:
            vm_name = vms[vm].split(":")[0]
            id = vms[vm].split(":")[1]
            print(vm_name)
            print(id)
l
thanks for the tips, fixed StackReference I use append + Output.all + apply cuz I want to pass only required information, not all instance details print in loop works properly, problem occurs when I try to call pulumi methods in loop however I fixed it by changing the code to:
Copy code
def start(my_vms):
    myinstance = mypackage.myresource('somename',my_vms)
    myinstance.start()
project = pulumi.get_project()
org = pulumi.get_organization()
stack_ref = pulumi.StackReference(f"{org}/{project}/stack1")
my_vms= stack_ref.outputs['my_vms']
my_vms.apply(lambda my_vms: start(my_vms))

class myresource(pulumi.ComponentResource):

    def __init__(self, name, vms, opts=None):
        self.vms: dict = vms
    def start(self):
        self.vms_loop(sec_group_backend)
    def vms_loop(self,sec_group_backend):
        for vm in self.vms:
          port = openstack.networking.Port(args)
f
ah, understood! glad you got it working! 🎉 note I don't think you'd need the
apply
if you used ``get_output()``
my_vms = stack_ref.get_output('my_vms')
instead of
my_vms = stack_ref.outputs['my_vms']
l
When I use get_output() with single value it works without apply for other part of code but when I try to use get_output() for 'my_vms' I get:
Copy code
in vms_loop
        for vm in self.vms:
      File ".venv/lib/python3.10/site-packages/pulumi/output.py", line 273, in __iter__
        raise TypeError(
    TypeError: 'Output' object is not iterable, consider iterating the underlying value inside an 'apply'