Update from a previous post- looks like there may ...
# general
d
Update from a previous post- looks like there may be a bug with the pulumi aws-classic package. I create an aws classic provider, then create a resource extending the pulumi.ComponentResource class with a dependsOn option specifying that aws provider. This should (to my understanding) require that the provider be provisioned before the componentResource. However, when I subsequently call aws.ec2.getAmi within a function of that resource class (explicitly specifying the provider I've defined), I get an
Unhandled exception: Error: Invoke: Default provider for 'aws' disabled. 'aws:ec2/getAmi:getAmi' must use an explicit provider
. It appears that the provider has not been created at this point, causing the getAmi call to fail because it attempts to use a default provider (which I've disabled). Has anyone else observed behavior like this, and if so is there some sort of workaround ?
l
Providers aren't provisioned. You don't dependOn a provider. Also, that error is about the default provider: the one you created is not the default provider, it's an explicit one. To use the provider you created, pass it to the
provider
opt, not the
dependsOn
opt.
d
Ah okay. And I did try passing the provider I created to the provider opt- I get the same error
const commonProviderArgs = {
accessKey: this.awsConfig.AWS_ACCESS_KEY,
secretKey: pulumi.secret(this.awsConfig.AWS_SECRET_KEY),
assumeRole: {
externalId: this.awsConfig.EXTERNAL_ID,
roleArn: this.awsConfig.ROLE_ARN,
},
};
const awsClassicProvider = new awsClassic.Provider("aws-classic-test", {
...commonProviderArgs,
region: 'us-east-2',
});
const awsFix = new AwsFixtureComponent(fix.baseName, fix, configuration, awsConfig, awsClassicProvider, {providers: [awsClassicProvider]});
awsFix
.initialize()
.then((fix) => {
return fix;
})
.catch((err) => {
log.error(err);
});
return awsFix;
const fixtureAmi = await aws.ec2
.getAmi({
filters: [
{
name: "name",
values: ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"],
},
],
mostRecent: true,
},
{ provider: this.provider }
)
.then((invoke) => invoke.id);
The first chunk of code is creating the resource (i.e. AwsFixtureComponent), and in that constructor I set its provider to the one passed in. The second chunk is within a function (initialize) in that class, and that's where I see the error
l
This is still your error?
Default provider for 'aws' disabled. 'awsec2/getAmigetAmi' must use an explicit provider
If you're getting this error, then the problem is the call to
getAmi()
. Since you have disabled default providers (which is good imo), you need to pass a provider to every call to AWS. This error is saying you haven't passed the provider to the call to
getAmi()
.
d
Yea that's still my error- and I pass the provider to the getAmi call, which is why I'm confused
l
Are you calling getAmi elsewhere?
d
No that's the only place
l
Where are you setting
this.provider
? Could it be null or undefined?
I have a few other questions too...
Copy code
const awsFix = new AwsFixtureComponent(fix.baseName, fix, configuration, awsConfig, awsClassicProvider, {providers: [awsClassicProvider]});
The question here is: ?!?
This is pretty weird too:
.then((invoke) => invoke.id);
Happy to help translate to more idiomatic code, if that'd be useful?
d
I set it in the constructor.. And yea that call is a little messy because I've been oscillating between passing the provider directly and trying to set it by passing it as the providers opt. And the
.then((invoke) => invoke.id)
I pulled from a pulumi template (https://github.com/pulumi/templates/blob/master/vm-aws-typescript/index.ts)
And sure, thank you. I can also tidy it up real quick and re-send
l
Ah. I think that template code predates
getAmiOutput()
. You can now use
getAmiOutput(...).id
, which is more idiomatic. Also, you might store the AMI object in the variable (since that's more flexible) and get the id only when you need it (passing it into the EC2 constructor).
Re: the messy constructor: use ComponentResource. Follow the Pulumi model. Providers get passed only via the
provider
or
providers
opts.
d
gotcha, okay thanks! I just implemented those changes (and removed the invoke for now), and I'm still getting the same error. I assume it's because that provider is still undefined by the time the getAmi call is made. Is there a way to ensure that provider is created before the getAmi call is made? Maybe an apply?
I tried an apply and it didn't work- maybe I'm not implementing it correctly.. here's the call
pulumi.all([awsClassicProvider]).apply(([awsProvider]) => {
const awsFix = new AwsFixtureComponent(fix.baseName, fix, {provider: awsProvider});
awsFix
.initialize()
.then((fix) => {
return fix;
})
.catch((err) => {
log.error(err);
});
return awsFix;
});
and the constructor:
export class AwsFixtureComponent extends pulumi.ComponentResource {
public readonly fixture: AwsFixture;
public readonly provider: aws.Provider;
public readonly opts: pulumi.ComponentResourceOptions | undefined;
constructor(name: string, fixture: AwsFixture, opts?: pulumi.ComponentResourceOptions) {
super("fixtures:awsFixture", name, {}, opts);
this.fixture = fixture;
this.provider = this.opts?.provider as aws.Provider;
this.opts=opts;
}
l
No. Providers are simple objects: they aren't in any way async.
d
ah
okay nevermind
So why would it be undefined a few times then defined ?
l
This looks problematic:
this.provider = this.opts?.provider as aws.Provider;
You're not detecting a missing provider.
Replace the
?
with
!
, see where it's undefined.
And ensure the definition for provider is
const provider: aws.Provider;
. That'll barf sooner, too.
d
It's undefined in the constructor
When I had the
?
there, it was undefined twice before being defined
(I've been console.logging the values of
provider
and
opts
right before making the getAmi call)
Screenshot from 2023-05-24 18-36-45.png
I'm not sure how that's happening though, since there shouldn't be any async behavior
When I replace with
!
it fails in the constructor ('trying to read properties of undefined')
l
That's weird. It shouldn't. Can you post an MCVE somewhere so that I can try it?
d
Do you have aws creds you can use?
l
Yep