sparse-intern-71089
07/08/2018, 1:24 PMstocky-spoon-28903
07/08/2018, 1:24 PMstocky-spoon-28903
07/08/2018, 1:25 PMbig-piano-35669
getAvailabilityZones
function returns a Promise<number>
, so you'll need to either await
its value or use a callback to access it. I prefer await
, especially if you're using TypeScript, but it does come with one unfortunate "catch": in JS, you cannot await
at the top level (yet, there is a proposal to enable this).
So, this example code will fetch the AZs and simply print them out. From there you can create a subnet-per-AZ, etc.
import * as aws from "@pulumi/aws";
(async () => {
const zones = (await aws.getAvailabilityZones()).names;
console.log(`${zones.length} AZs found:`);
for (const zone of zones) {
console.log(`\t${zone}`);
}
})();
If you're creating these in a function, you won't need the cumbersome (async () => { ... })()
stuff. Instead, it'd just be something like async function createSubnets() { ... }
.
We do have an example of this in the AWS repo, but it's fairly buried and largely only there to serve as a test case: https://github.com/pulumi/pulumi-aws/tree/master/examples/webserver/variants/zones.stocky-spoon-28903
07/08/2018, 4:30 PMstocky-spoon-28903
07/08/2018, 4:31 PMstocky-spoon-28903
07/08/2018, 4:32 PMbig-piano-35669
async function main() {
// all the things happen here
}
main();
We don't await the promise returned from main here, but that's okay, since Node.js keeps the program alive until the event loop quiesces.
Another approach is to try to scope the places where you need to do this. For instance, in the subnets case, you might have something like
async function createSubnets() {
const zones = (await aws.getAvailabilityZones()).names;
const subnets = [];
... create them ...
return subnets;
}
This can just "push the problem around", because of course the returned subnets array will be wrapped in a promise, but for some cases this is more appropriate. Because our Input<T>
type accepts promises, doing it like this can sometimes let you achieve a more dataflow style rather than needing to await all over the place.big-piano-35669
stocky-spoon-28903
07/08/2018, 4:39 PMstocky-spoon-28903
07/08/2018, 4:41 PMasync function main()
, exporting anything becomes difficult as far as I can tellstocky-spoon-28903
07/08/2018, 4:41 PMstocky-spoon-28903
07/08/2018, 4:51 PMbig-piano-35669
async function createResources() {
// do everything here, including awaiting
return {
a: ...,
b: ...,
};
}
let outputs = createResources();
export let a = outputs.then(out => out.a);
export let b = outputs.then(out => out.b);
I'm personally not happy with all this ceremony, but as you note, most of this comes from standard JS/TS promises stuff. @lemon-spoon-91807 and @white-balloon-205 had been exploring how to do data sources without needing promises, but I've lost track of where we landed (Node.js makes it hard, by design, to block the message loop).big-piano-35669
Is there a way to create a stack output by allocating something rather than by exporting it from the TS module?Not at the moment, but in principle there's no reason we couldn't. This is all implemented in https://github.com/pulumi/pulumi/blob/015344ab0693ca433d211698eddc6a6a85588bf0/sdk/nodejs/runtime/stack.ts#L27, as called by https://github.com/pulumi/pulumi/blob/015344ab0693ca433d211698eddc6a6a85588bf0/sdk/nodejs/cmd/run/index.ts#L248, by the way, if you were interested in poking around.
stocky-spoon-28903
07/08/2018, 5:01 PMbig-piano-35669
stocky-spoon-28903
07/08/2018, 5:04 PMstocky-spoon-28903
07/08/2018, 5:05 PMstocky-spoon-28903
07/08/2018, 5:15 PMbig-piano-35669
big-piano-35669
big-piano-35669
stocky-spoon-28903
07/08/2018, 9:04 PMstocky-spoon-28903
07/09/2018, 12:53 AMbig-piano-35669
lemon-spoon-91807
07/09/2018, 1:18 AMlemon-spoon-91807
07/09/2018, 1:18 AMlemon-spoon-91807
07/09/2018, 1:19 AMlemon-spoon-91807
07/09/2018, 1:19 AMlemon-spoon-91807
07/09/2018, 1:20 AMbig-piano-35669
white-balloon-205
await
in JavaScript. https://github.com/tc39/ecmascript-asyncawait/issues/9#issuecomment-39000615stocky-spoon-28903
07/09/2018, 7:28 AMasync function(): Promise<any>
from the (user-facing) entry-point module of a Pulumi stack, and if that is what you get back call it from the runtime and use the returned object as the outputs? That way the majority of the ceremony in the pattern above could be removed and replaced with:
interface StackOutputs {
subnetIds: pulumi.Output<string>[]
}
export default async function(): Promise<StackOutputs> {
// Do everything here including awaiting
return {
subnetIds: someSubnets.map(subnet => subnet.id)
};
}
big-piano-35669
stocky-spoon-28903
07/09/2018, 5:16 PMstocky-spoon-28903
07/09/2018, 9:18 PM