Hey All, I'm wondering if anyone here has a simple...
# general
q
Hey All, I'm wondering if anyone here has a simple solution to something I am trying to achieve. I am trying to get the results of an array from one provider, search the results and put each of the 5 items in the array into a variable i can use in another section of code. As the result is a pulumi output, i'm running into issues. I'm using Python to do this.
c
I imagine you already tried apply?
q
I've tried so many variations to try to get this to work i couldn't tell you. I'll try that an see what error comes out 🙂
So when adding an apply, its empty
Copy code
email_records = []
# Loop through the records and extract values
for i in range(3):
    email_config.sending_records_sets[i].apply(lambda value: email_records.append(value))
for i in range(2):
    email_config.receiving_records_sets[i].apply(lambda value: email_records.append(value))
pulumi.export("records", email_records)
c
i'm not familiar with the python sdk of pulumi (i use ts), but that looks right, any chance you could share how you get
email_config
?
this is I how get access to data in a different AWS provider:
Copy code
const awsUsEast1 = new aws.Provider('aws-provider-us-east-1', {
  region: 'us-east-1',
});
q
Yeah sure, its using the mailgun provider
Copy code
return mailgun.Domain(
        domain,
        name=domain,
        smtp_password=smtp_password,
        region=region,
        )
c
and then, i get the data like so:
Copy code
const certificate = new aws.acm.Certificate(
  'api-tls-cert',
  {
    domainName: apiDomainName,
    validationMethod: 'DNS',
  },
  {
    provider: awsUsEast1,
  }
);
q
I mean the apply has answered my question, its getting the values too late. I think i need a way to ensure it runs it before my next function kicks off
c
oh fair enough 😅
d
Something you could do is this:
Copy code
email_records = Output.all(email_config.sending_records_sets, email_config.receiving_records_sets).apply(lambda args: args[0] + args[1])
This will concat the lists within the apply once the values become available from the pulumi engine
If you specifically need the first 4 and 3 records respectively, you can use a slice as well:
args[0][0:3]
q
Hi Anthony, thanks for the reply. I think i'm a step closer as the output now has all the results, however my loop that is meant to search the list is erroring which makes me think its still running before the variable has data. Any ideas?
Copy code
eu_mailgun = ""
    rsa_mailgun = ""
    mxb_mailgun = ""
    mxa_mailgun = ""

    for record in email_records:
        if "eu." in record.value:
            eu_mailgun = record.value
        elif "k=rsa" in record.value:
            rsa_mailgun = record.value
        elif "mxb" in record.value:
            mxb_mailgun = record.value
        elif "mxa" in record.value:
            mxa_mailgun = record.value

    pulumi.export("eu_mailgun", eu_mailgun)
    pulumi.export("rsa_mailgun", rsa_mailgun)
    pulumi.export("mxb_mailgun", mxb_mailgun)
    pulumi.export("mxa_mailgun", mxa_mailgun)
error im getting: raise TypeError( TypeError: 'Output' object is not iterable, consider iterating the underlying value inside an 'apply'
d
You'd need to do those within the apply block also. Something like this could work:
Copy code
email_record_values = email_records.apply(lambda rs: [r.value for r in rs])
eu_domain = email_record_values.apply(lambda rvs: next(filter((lambda v: "eu." in v), rvs), ""))
q
Oh I kinda get it, so you cant just get away with telling it once that it has to run before anything else, you have to tell it each time you use the variable? I'm getting a lot of future.result errors that i've seen before when i attempted something similar but less elegant. return future.result() value = await self._future AttributeError: 'dict' object has no attribute 'value'
d
Exactly. Basically, apply runs after your script as run. Pulumi calls back to the functions once it begins creating resources that have been declared
Sometimes components of resources will be downcasted to plain dictionaries, so access it as a dictionary instead of as a namespace
q
First part makes sense, I unfortunately don't understand how to fix my latest error though, if i change it to just store the value it gives a similar error: AttributeError: 'list' object has no attribute 'value'
d
You can access a dictionary with key access syntax:
r["value"]
q
Yay! that was the last piece of the puzzle! Thank you so much. I struggled with that far longer than i'd like to admit
Copy code
email_records = []
    email_record_values = []
    email_records = pulumi.Output.all(email_config.sending_records_sets, email_config.receiving_records_sets).apply(lambda args: args[0] + args[1])
        
    # pulumi.export("records", email_records)
        
    email_record_values = email_records.apply(lambda rs: [r["value"] for r in rs])
    eu_domain = email_record_values.apply(lambda rvs: next(filter((lambda v: "eu." in v), rvs), ""))
    mxb_mailgun = email_record_values.apply(lambda rvs: next(filter((lambda v: "mxb" in v), rvs), ""))
    mxa_mailgun = email_record_values.apply(lambda rvs: next(filter((lambda v: "mxa" in v), rvs), ""))
    rsa_mailgun = email_record_values.apply(lambda rvs: next(filter((lambda v: "k=rsa" in v), rvs), ""))
    spf_mailgun = email_record_values.apply(lambda rvs: next(filter((lambda v: "v=spf1" in v), rvs), ""))
    
            
    pulumi.export("eu_domain", eu_domain)
    pulumi.export("rsa_mailgun", rsa_mailgun)
    pulumi.export("mxb_mailgun", mxb_mailgun)
    pulumi.export("mxa_mailgun", mxa_mailgun)  
    pulumi.export("spf_mailgun", spf_mailgun)