This message was deleted.
# general
s
This message was deleted.
l
Hey Robert!
i'd def like to help you out with this. I am goign home for the day, but i can try to look back later (and definitely tomorrow)
It's a little unclear to me exactly what you're trying to do, so it would help if i can get clarity on something
Specifically, this part:
and after pulumi has created/updated the API Gateway in the AWS cloud, the downloader would fetch the generated SDK
it's not clear to me waht you mean by "the generated SDK"
Oh. Actually, i think i see what you're referring to:
Yes. The way you would normally represent this in a pulumi program would be to take the Resource you've created (i.e. an apigateway.RestApi), then take one of its 'output' properties and then do a .apply on that property
You can think of .apply as being similar to .then on a promise
you'll pass .apply the code you want to run. in this case that would be: https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/APIGateway.html#getSdk-property
The reason this will work (where your previous attempt had problems) is that .apply does not run during a preview. because there is no real value for it to use. but it will run during a normal 'update'
Let me know if that's enough information to go off of, or if you have any more questions. Thanks!
m
Thanks for the response, Cyrus. Sorry if I wasn't perfectly clear with my intentions, but it seems that you caught on to what I was doing.
l
not a problem!
i just got thrown off by the "download sdk" part
i wasn't aware that was something you could do!
so you helped teach me something new today!
m
I actually was doing everything that you suggested. In fact, here's my code:
Copy code
typescript
export class SdkDownloader extends pulumi.ComponentResource {
    public constructor(name: string, args: SdkDownloader.Args, options?: pulumi.ResourceOptions) {
        super('custom:SdkDownloader', name, args, options);

        this.sdkFilePaths = this.downloadAndExtractSdkFiles(args);
        this.registerOutputs({ sdkFilePaths: this.sdkFilePaths });
    }

    public readonly sdkFilePaths: pulumi.Output<string[]>;

    private downloadAndExtractSdkFiles(args: SdkDownloader.Args): pulumi.Output<string[]> {
        return pulumi.all([
            args.destinationDirPath,
            args.restApiId,
            args.sdkType,
            args.stageName
        ]).apply(([
            destinationDirPath,
            restApiId,
            sdkType,
            stageName
        ]) => {
            const client = new AWS.APIGateway({
                apiVersion: '2015-07-09',
                region: new pulumi.Config('aws').require('region')
            });

            const getSdkRequest: AWS.APIGateway.GetSdkRequest = {
                restApiId,
                sdkType,
                stageName
            };

            const sdkFilePathsPromise: Promise<string[]> = client.getSdk(getSdkRequest).promise()
                .then((getSdkResponse: AWS.APIGateway.SdkResponse) => {
                    if (!Buffer.isBuffer(getSdkResponse.body)) {
                        throw new Error(`Unexpected AWS.APIGateway.getSdk() response body: ${getSdkResponse.body}`);
                    }
                    return extractZippedBufferToFiles(getSdkResponse.body, destinationDirPath);
                });

            return pulumi.output(sdkFilePathsPromise);
        });
    }
}

export namespace SdkDownloader {
    export interface Args {
        destinationDirPath: pulumi.Input<string>;
        restApiId: pulumi.Input<string>;
        sdkType: pulumi.Input<string>;
        stageName: pulumi.Input<string>;
    }
}
l
give me a couple of moments to read through
ok. so here's what i would suggest changing
i don't think you'll be able to do this per-se:
this.sdkFilePaths = this.downloadAndExtractSdkFiles(args); this.registerOutputs({ sdkFilePaths: this.sdkFilePaths });
because, effectively, you're saying 'an output of this object depends on this object being completed'
which isn't really a concept that works here
there are two alternative approaches i can see right off the bat
but before i proceed, let me know if you have any questions/thoughts
sorry, that's a bit of mispeaking on my part
m
Ok. Well, I guess where I'm getting stuck in my understanding is that downloadAndExtractSdkFiles() doesn't actually do any work, but instead returns the Output<> of work to be performed when necessary.
l
so... let me step back for a second... why do you want a Resource here?
why note just have a helper function that takes in those inputs, and then produces the pulumi.Output<string[]>?
give me a second to write that up
m
Yes, that would be an alternative. And it would work.
No need to write it up.
l
ok 🙂
m
I guess I was thinking it would be nice to see the SDK as a resource in the dependency tree that is output by preview/update.
l
hrmm.. i am a bit confused though why your code doesn't work...
i'm actually surprised it breaks during preview...
so ignore a lot of what i said above 🙂
you may be doing this in a way that should be fine.. but is broken for some other reason
any chance you can give me a compilable repro?
if so, i can investigate tomorrow!
(it's almost 8pm here :))
m
I'm kind of surprised too. And it's functionally equivalent to a, uh, function. So perhaps the fact that I'm implementing it as a Resource is the reason.
This is one small piece of a large repo. So I can't supply it easily. And it's almost 10pm here, so I hear ya!
l
yeah. i think the registerOutputs might be part of the problem... but i'm not sure...
m
I'll try making it just a function next. One more thought, tho. What about .apply() vs .get()? I've never used .get() before, and I'm guessing that's not applicable here, but...
l
for the purposes of learning a bit more, what happens if you put this in a helper, then take the result of tha thelper in as an argument to the resource
and
when you call "super(...)"
pass hte new value along in the "args" spot
m
All good suggestions. I'll give them a try tomorrow. I'm very appreciative of your time. Thank you very kindly!
After converting the code to just a helper function, it still runs during the preview stage of an
pulumi update
command. But it also runs during the update stage. That may have been the case before and I just didn't notice.
l
i think i see what's going on
so you are passing in simple values to this function yes?
Effectively, if you are passing simple values, then we will eagerly perform this computation.
however, if one of the values was hte actual output of a real resource you created (i.e. a RestAPI instance), then that shouldn't happen.
m
Two arguments are simple values and two are
pulumi.Output<string>
originating from
aws.apigateway.RestApi.id
and
aws.apigateway.Stage.stageName
.
I'll make a small repro repo if you still want to take a look. It's the next logical troubleshooting step anyway. Not sure exactly when I'll get around to it, but hopefully today or tomorrow.