freezing-electrician-6256
11/14/2023, 9:05 PMgetResource
type of operation? is it run at the beginning of the up
operation or is it deferred until the value is actually needed?
in this scenario, we are calling aws.iam.getRolesOutput
after a thing that creates an IAM role so that we can use that role in an IAM policy, but we get [null]
the first time we run Pulumi which makes the IAM policy invalid. unfortunately, the role is created as a side effect of the aws.ssoadmin.AccountAssignment resource and that resource does not return info about the role created, so we don't have an explicit way to get the role. we tried adding an explicit dependsOn
for the policy to depend on the AccountAssignment, and it does end up updating the policy after the AccountAssignment is created, but it still ends up trying to use the null
value and fails. a second pulumi up
fixes the issue but it's annoying and feels wrong to have to do this. I would expect if the query is deferred until it's actually used, then this should succeed on the first try given that there is an explicit dependency, but it also could be that the role is created asynchronously some time after the AccountAssignment so it might just be unreliable in general.[null]
right away, which makes me think that it's not waiting to compute the value until it's neededdry-keyboard-94795
11/14/2023, 9:34 PMgetRole
, and keep retrying until you end up with a non-null response.
Let me setup an environment so I can provide an example quicklygetRolesOutput
usage, which will help with doing an example hereasync function getRoleAsync(nameRegex: string): Promise<aws.iam.GetRoleResult> {
let roleName: string | null = null;
const maxRetries = 10;
let attempts = 0;
const sleepTime = 1000;
do {
attempts++;
let rolesResult = await aws.iam.getRoles({
nameRegex: nameRegex,
});
if (rolesResult.names.length > 0) {
roleName = rolesResult.names[0];
}
if (roleName == null) {
console.log("retrying!", rolesResult);
await new Promise(r => setTimeout(r, sleepTime));
}
} while (roleName == null && attempts < maxRetries);
if (roleName == null) {
throw new Error("Failed to find role");
}
return aws.iam.getRole({
name: roleName,
});
}
// These are for demo purposes to show how to unrole a promise in Pulumi
const roleDependingOnResource = stubResource.id.apply(_ => getRoleAsync("NEVER_EXISTS"));
const roleNonDependent = pulumi.output(getRoleAsync("NEVER_EXISTS"));
import { retryDecorator } from "ts-retry-promise";
const getRole = (nameRegex: string) => aws.iam.getRoles({
nameRegex: nameRegex,
}).then(roles => {
if (roles.names.length <= 0) {
throw new Error("Failed to find role");
}
return aws.iam.getRole({
name: roles.names[0],
});
});
const retryGetRole = retryDecorator(getRole, { retries: 10, delay: 1000 });
// These are for demo purposes to show how to unrole a promise in Pulumi
const roleDependingOnResource = stubResource.id.apply(_ => retryGetRole("NEVER_EXISTS"));
const roleNonDependent = pulumi.output(retryGetRole("NEVER_EXISTS"));
freezing-electrician-6256
11/14/2023, 11:07 PMpolicy: pulumi.jsonStringify({
Version: "2012-10-17",
Statement: [
{
Sid: "Foo",
Effect: "Allow",
Principal: {
AWS: [
aws.iam.getRoleOutput(params),
]
},
(the getRoleOutput is technically wrapped in a function but effectively ends up like that)