https://pulumi.com logo
#general
Title
# general
w

wet-noon-14291

01/11/2022, 9:48 PM
What is the correct way of retrieving "async" values in a custom
ComponentResource
? We struggle with having a stack hanging if the async requests fails. We are doing something like this:
Copy code
export class Team extends pulumi.ComponentResource {
    teamId: pulumi.Output<string>

    constructor(name: string, teamSpec: types.TeamSpec) {
        super("something", name, {});
        const azureAdConfig = azuread.getClientConfig({})

        const usersIds = pulumi.output(getUsers(teamSpec.members)); // getUsers is something that returns a promise

        const adGroup = new azuread.Group(`${teamSpec.teamName}-ad-group`, {
            displayName:  teamSpec.teamName,
            owners: [azureAdConfig.then(c => c.objectId)],
            description: "Created and managed by Automation",
            securityEnabled: true,
            members: usersIds
        });
   ....
if the call to
getUsers
fails everything will just hang. I would expect pulumi to catch that and fail the whole process. Am I doing something wrong or is this a bug?
l

little-cartoon-10569

01/11/2022, 9:53 PM
Generally, async stuff is either 1) done in the provider, not the resource, or 2) is not resolved (then/apply) in the constructor, but left as a property with an Output value.
Can you expose userIds as a property, rather than a local variable?
The dependency on it in adGroup is fine, since Pulumi will handle that. Are there any other dependencies on it further down?
w

wet-noon-14291

01/11/2022, 9:55 PM
We need it when creating the adGroup, which we do want to do in the constructor (I think) since we do want a concept of a team that has a set of "children"
nope, that is the only dependency
so you're saying I can just depend directly on the promise and not resolve it?
l

little-cartoon-10569

01/11/2022, 9:56 PM
Since that's the only use of it, I don't think it should be causing a problem. Does the code inside
getUsers()
resolve anything outside of the Promise? If everything is deferred until the Pulumi engine is doing its thing, you should be okay.
w

wet-noon-14291

01/11/2022, 9:58 PM
It is quite simple:
Copy code
const getUsers = async (members: string[]) => {
    const users = await azuread.getUsers(
        {
            userPrincipalNames: members
        }
    )
    return users.objectIds;
}
l

little-cartoon-10569

01/11/2022, 9:58 PM
Heh, that was exactly the example I was coming up with πŸ™‚
That won't work, since you're awaiting before the engine gets involved.
Try doing the work inside a
then()
instead of an async/await block.
Same thing effectively, but I think Pulumi handles it better because it's close to Output/apply?
w

wet-noon-14291

01/11/2022, 9:59 PM
got it, so it is the async/await stuff that is causing the problem. "Promise style" will work (last famous words)
l

little-cartoon-10569

01/11/2022, 10:00 PM
That's my understanding, yes.
Plus you can skip the extra function πŸ™‚
w

wet-noon-14291

01/11/2022, 10:00 PM
yes
l

little-cartoon-10569

01/11/2022, 10:01 PM
pulumi.output(azuread.getUsers({ userPrincipalNames: members}).then(u => u.objectIds))
Or equivalently
pulumi.output(azuread.getUsers({ userPrincipalNames: members})).apply(u => u.objectIds)
I would go with the 2nd one, since then the Pulumi dependency-resolution logic gets involved earlier and maybe can make better decisions?
w

wet-noon-14291

01/11/2022, 10:05 PM
ok, so I still need to put it in an output?
hm... still same issue. I know I can work my way around it by validating the input (it is an automation application), but I do want to understand why it isn't working and failing as expected.
so the correct way to do it is to move all the async calls out from the constructor I think. Then I got it behaving like I expected.
πŸŽ‰ 1
One question I have though is how should one go about getting values async if they depend on the output from another resource? Does that also have to be done outside of a constructor, or maybe pulumi knows how to deal with that properly since it is a resource creating the output?
l

little-cartoon-10569

01/12/2022, 7:32 PM
I was under the impression that if the value is to be passed into a resource constructor, it would be fine to retrieve the value inside an apply, and pass the returned output to the constructor. But that didn't work for you yesterday, so I'm at a loss to explain this.
πŸ‘ 1
w

wet-noon-14291

01/12/2022, 9:59 PM
Maybe @broad-dog-22463 can help explain? Or can point to someone. It isn't urgent by any means, but it would be nice to understand what the β€œright” way is.
474 Views