I've read and re-read about Output types but it's ...
# general
c
I've read and re-read about Output types but it's still not clicking for me. I'm trying to create an array, but keep getting the error about o.apply.
Copy code
let vpcList = vpcConfig.map(entry => {
        return new aws.ec2.Vpc(entry.name, {cidrBlock: entry.cidrBlock, tags: {Name: entry.name}});
    });

    let vpcNameToId: { [index: string]: any } = {};
    for (let vpc of vpcList) {
        // create a lookup
        const vpcName = vpc.tags.apply(v => v?.Name ?? null);
        vpcName.apply(theName => {
            console.log("Applying " + theName + "=" + vpc.id.apply(v => `${v}`));
            // vpcNameToId[theName] = vpcId;
        });
    }
Results in:
Copy code
Applying vpc0=Calling [toString] on an [Output<T>] is not supported.
    To get the value of an Output<T> as an Output<string> consider either:
    1: o.apply(v => `prefix${v}suffix`)
    2: pulumi.interpolate `prefix${v}suffix`
    See <https://pulumi.io/help/outputs> for more details.
    This function may throw in a future version of @pulumi/pulumi.
g
The logging logic belongs inside the apply. You can use
pulumi.all
to resolve all the outputs. (not tested, but should be close)
Copy code
pulumi.all([vpcName, vpc.id]).apply(([name, id]) => console.log(`Applying ${name} = ${id}`))
c
Ah! So I was missing the equivalent of Promise.all. That works. Thanks so much!
👍 1
Related question: what's the mechanism to wait for everything to resolve? Calling await doesn't seem to do much.
Copy code
let vpcNameToId: { [index: string]: any } = {};
for (let vpc of vpcList) {
    // create a lookup table
    const vpcName = vpc.tags.apply(v => v?.Name ?? null);
    const vpcId = vpc.id;
    pulumi.all([vpcName, vpcId]).apply(([name, id]) => {
        vpcNameToId[name] = id;
    });
}

console.log("" + Object.keys(vpcNameToId).length);
Here the console output is zero items.
g
Easiest would probably be making
vpmNameToId
into an Output and passing it into the
pulumi.all
. At that point, you can resolve that output as usual like
Copy code
vpcNameToId.apply(map => console.log(Object.keys(map).length))
c
I'm still new to this, but it seems like we're missing the equivalent of the await functionality. As I puzzle through this, I end up with "apply" inside "apply" statements just to ensure everything is resolved.
Is there an equivalent to Promise.resolve for apply()?
g
@white-balloon-205?
w
Yes -
pulumi.output(x)
is effectively
Promise.resolve(x)
but for outputs.
As I puzzle through this, I end up with "apply" inside "apply" statements just to ensure everything is resolved.
This should not be the case in general - though depends a bit on specific code you are trying to write.
See https://www.pulumi.com/docs/intro/concepts/programming-model/#frominput as well (and that whole section more generally).
c
I'm tripping over the lack of an await syntax. I just want to pull the value out.
Get the string from an Output<string>
w
Yeah - for better or worse - you really just can't do that. You do need to use
apply
. TypeScript doesn't provide any way to offer generalized
await
-style syntax (in a pleasent way) over non-promises.
c
I'm finding it's not as simply as calling variable_name.apply()
I'm finding I have to call pulumi.all(variable).apply()
w
Yes - one layer of -
pulumi.all(var).apply()
is reasonably commonly needed.
c
It feels like I'm so close but keep hitting walls. I cannot figure out how to turn "OutputInstance<Input<RouteTableRoute>[]>" into just "Input<RouteTableRoute>[]"
It turns out the issue was that array objects don't play well with standard array objects. For example, an Input<RouteTableRoute> object cannot be used with syntax like "[...myObj, ...anotherObj]" when defining routes in aws.ec2.RouteTable. I had to call apply(v => v.forEach(e => someVar.push(e))). It would be awesome to have some additional documentation around this.