hi all! so i've been having an issue, background, ...
# general
s
hi all! so i've been having an issue, background, we are using the s3 login provider and then deploying to multiple aws regions, i need to get a value from our outputs but cannot for the life of me figure out how to fetch it (cognito user pool id)... I am doing:
Copy code
const stackName = pulumi.getStack();
  const programName = pulumi.getProject();
  const idPrefix = `${programName
    .split('-')
    .map(p => p.charAt(0))
    .join('')}-${stackName}`;

const currentStack = new pulumi.StackReference(stackName);
  const cognitoUserPoolId = (
    currentStack.getOutput(
      `${idPrefix}-cognito-userPool`
    ) as pulumi.Output<aws.cognito.UserPool>
  ).apply(pool => {
    console.log({ pool });
    return pool?.id ?? 'us-east-2_DOQuLOIcm'
  });
however, the value is always undefined... do i need to pass arguments to the stack reference or a provider or is there anything i am doing wrong here? the docs are not very clear on things here and i've attempted quite a few things but still dumbfounded 😕
d
If the UserPool is part of the current stack, what's preventing you from using the resource directly?
s
circular dependency...
d
Hmm, you could split your resources between multiple files and do imports, or maybe use promises to defer the assignment. Can you provide the circular code?
s
@dry-keyboard-94795 so, the deal is you can't use promises to do it, i went all over the place attempting to figure it out, basically you have to deploy twice to get the configuration of it... basically here is the deal, i configure many lambdas the lambdas need to have an envVar of the cognito user pool id and user pool client id, there are realistically two options, i create two separate stacks OR i deploy twice and reference the output of the existing deploy.. there are several tickets surrounding doing this behavior in the future but if you deploy cognito with everything else, at the time that it is necessary it won't work (why this is also the case is that cognito is configured to talk to lambda with it's lambdaConfig property), so i have a chicken and egg problem
d
I took a look at the resource, and was worried you were going to say it's for the lambda config. I recall facing this issue in the past, even with a 2 stage deploy.
Did you work out setting outputs with
export
?
s
i have it working now 😄
d
the payload sent to lambda does container the
userPoolId
and
clientId
. Unsure if you need it just for referencing, or for extra validation of the data
s
Copy code
export default {
  cognito: {
    userPoolId: cognitoPool?.id,
    clientId: cognitoClient?.id,
    domainId: cognitoDomain?.id,
  },
};
and then can reference by using:
Copy code
const organizationName = pulumi.getOrganization();
  const stackName = pulumi.getStack();
  const programName = pulumi.getProject();

  const currentStack = new pulumi.StackReference(stackName, {
    name: `${organizationName}/${programName}/${stackName}`,
  });

  const cognitoOutputParams : {
    clientId: string;
    domainId: string;
    userPoolId: string;
  } | undefined = await currentStack.getOutputValue('cognito');
basically, first part creates the lambdas and configures the lambdaConfig for cognito, second deploy will fetch the cognito from the stack reference and assign in the associated env parameters.
now after nearly killing myself all week i have a fully functional deployment stack in pulumi, it has been a nightmare mainly because i couldn't utilize async and so many things i had to abstract out to allow for fetching the string values i provided (pulumi.Output is my arch nemesis)
likewise pulumi.Input 😕
things like this just why...
Copy code
export class Provider extends AWSProvider {
  regionName: string;

  constructor(name: string, args?: ProviderArgs, opts?: ResourceOptions) {
    super(name, args, opts);

    this.regionName = args!.region as string;
}
d
couldn't utilize async? I've not learned the JS pulumi runtime fully yet
s
nope, so basically anything wrapped in a pulumi.Output or pulumi.Input cannot be retrieved until after the end of the execution by the underlying engine so essentially at runtime all .Output and .Input values cannot be accessed
even if the values passed in were strings and are known
almost like a .isKnown property needs to be added so one can actually get the value without any issue
likewise, causes a ton of problems because there are situations where you cannot really use .apply (think domain names whereby records may utilize the same underlying certificate verification procedures... was a nightmare figuring that one out).
d
yeah, workarounds might be tougher in JS due to code mangling. I've workarounds for lifting Output values in python
s
yeah i had attempted a few things to workaround it, unfortunately, it's wrapped damn good and i couldn't get the values out... drove me insane.
d
Copy code
const foo = pulumi.Output.create("foo");
console.log(await (foo as any).isKnown as Promise<boolean>);
console.log(await (foo as any).promise());
This seems to work. Relies on Output being an alias to `OutputImpl`: https://github.com/pulumi/pulumi/blob/202491bfea6af05adc505d41a5166e7db9bbdee3/sdk/nodejs/output.ts#L952
it logs
true
then
foo
. However you probably shouldn't do this in any production code 🙂
s
hahaha 🙂
im going to keep a copy of that thing around