Skip to content

Commit

Permalink
Merge branch 'main' into fix-ses-actions-restrain-s3-perms
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Apr 19, 2024
2 parents 2c8ca6a + 9eb21bd commit 02be0ee
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 10 deletions.
42 changes: 42 additions & 0 deletions packages/@aws-cdk-testing/cli-integ/lib/eventually.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* @param maxAttempts the maximum number of attempts
* @param interval interval in milliseconds to observe between attempts
*/
export type EventuallyOptions = {
maxAttempts?: number;
interval?: number;
};

const wait = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));
const DEFAULT_INTERVAL = 1000;
const DEFAULT_MAX_ATTEMPTS = 10;

/**
* Runs a function on an interval until the maximum number of attempts has
* been reached.
*
* Default interval = 1000 milliseconds
* Default maxAttempts = 10
*
* @param fn function to run
* @param options EventuallyOptions
*/
const eventually = async <T>(call: () => Promise<T>, options?: EventuallyOptions): Promise<T> => {
const opts = {
interval: options?.interval ? options.interval : DEFAULT_INTERVAL,
maxAttempts: options?.maxAttempts ? options.maxAttempts : DEFAULT_MAX_ATTEMPTS,
};

while (opts.maxAttempts-- >= 0) {
try {
return await call();
} catch (err) {
if (opts.maxAttempts <= 0) throw err;
}
await wait(opts.interval);
}

throw new Error('An unexpected error has occurred.');
};

export default eventually;
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as fs from 'fs';
import * as path from 'path';
import * as yaml from 'yaml';
import { integTest, randomString, withoutBootstrap } from '../../lib';
import eventually from '../../lib/eventually';

jest.setTimeout(2 * 60 * 60_000); // Includes the time to acquire locks, worst-case single-threaded runtime

Expand Down Expand Up @@ -283,17 +284,25 @@ integTest('can remove customPermissionsBoundary', withoutBootstrap(async (fixtur
}),
});
policyArn = policy.Policy?.Arn;
await fixture.cdkBootstrapModern({
// toolkitStackName doesn't matter for this particular invocation
toolkitStackName: bootstrapStackName,
customPermissionsBoundary: policyName,
});

const response = await fixture.aws.cloudFormation('describeStacks', { StackName: bootstrapStackName });
expect(
response.Stacks?.[0].Parameters?.some(
param => (param.ParameterKey === 'InputPermissionsBoundary' && param.ParameterValue === policyName),
)).toEqual(true);
// Policy creation and consistency across regions is "almost immediate"
// See: https://docs.aws.amazon.com/IAM/latest/UserGuide/troubleshoot_general.html#troubleshoot_general_eventual-consistency
// We will put this in an `eventually` block to retry stack creation with a reasonable timeout
const createStackWithPermissionBoundary = async (): Promise<void> => {
await fixture.cdkBootstrapModern({
// toolkitStackName doesn't matter for this particular invocation
toolkitStackName: bootstrapStackName,
customPermissionsBoundary: policyName,
});

const response = await fixture.aws.cloudFormation('describeStacks', { StackName: bootstrapStackName });
expect(
response.Stacks?.[0].Parameters?.some(
param => (param.ParameterKey === 'InputPermissionsBoundary' && param.ParameterValue === policyName),
)).toEqual(true);
};

await eventually(createStackWithPermissionBoundary, { maxAttempts: 3 });

await fixture.cdkBootstrapModern({
// toolkitStackName doesn't matter for this particular invocation
Expand Down

0 comments on commit 02be0ee

Please sign in to comment.