-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore: parallelize integ tests across regions #10269
Conversation
When `AWS_REGIONS=region1,region2,region3` is set, the CLI integration tests are going to parallelize themselves across those regions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not looked into the PR itself yet, but can we make it very clear in the logs which region the stack is going to (if not already). I'd rather not clickity-click across 10 different regions to find the stack.
@@ -42,6 +42,13 @@ To run regression tests in the source tree: | |||
$ test/integ/test-cli-regression-against-current-code.sh [-t '...'] | |||
``` | |||
|
|||
Integ tests can run in parallel across multiple regions. Set the `AWS_REGIONS` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a bit more about what the striping strategy will be, or how tests get assigned to regions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also state which region will be picked by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also state which region will be picked by default.
All of them?
Why do you care? If you care, then you shouldn't be passing all of them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also state which region will be picked by default.
All of them?
Why do you care? If you care, then you shouldn't be passing all of them.
Not what I meant. Which region will be picked if AWS_REGIONS
is not specified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In relation, It might be good for debugging if each test prints out the region its running in
} finally { | ||
this.regionLease.dispose(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bit hard to follow since the lease is taken in a different scope, (prepareAppFixture()
I think).
Keep the take()
and dispose()
calls in the same block so it's easier to reason about.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's fine, but I'm going to have to change everything to use higher-order functions. Not sure that's going to make things more readable, but it's definitely fun for me! :)
* forever before the user notices a simple misconfiguration. | ||
* | ||
* We can't check for the presence of environment variables since credentials could come from | ||
* anywyere, so do simple account retrieval. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* anywyere, so do simple account retrieval. | |
* anywhere, so do simple account retrieval. |
* If there are multiple consumers waiting for a resource, consumers are serviced | ||
* in FIFO order for most fairness. | ||
*/ | ||
export class ResourcePool<A> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unit tests for the leasing logic. A regression here (now or in the future) would be hard to catch/debug, esp one that works partially causing the logic to skew but not fail.
@@ -42,6 +42,13 @@ To run regression tests in the source tree: | |||
$ test/integ/test-cli-regression-against-current-code.sh [-t '...'] | |||
``` | |||
|
|||
Integ tests can run in parallel across multiple regions. Set the `AWS_REGIONS` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also state which region will be picked by default.
All of them?
Why do you care? If you care, then you shouldn't be passing all of them.
Not what I meant. Which region will be picked if AWS_REGIONS
is not specified.
if (resources.length === 0) { | ||
throw new Error('Must have at least one resource in the pool'); | ||
} | ||
this.resources = [...resources]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dedup maybe? To avoid any funky unexpected repititions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you mean here. I'm making a copy so we don't have accidental sharing of arrays.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean that AWS_REGIONS
might be configured as ['us-east-1', 'us-east-1', 'us-east-1']
, effectively causing three tests to run in parallel on us-east-1
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm. Seems that's the caller's responsibility. Maybe they want to weight certain regions differently? I could see that...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree as far as this generic pool is concerned.
But if we want to make sure tests don't run in parallel in the same region then I would add the deduplication on the caller side when you read the AWS_REGIONS
env variable. Maybe even throw if len(array) != len(set)
.
I actually don't mind not deduping, just mentioning it because there is an edge case here that might break the intended functionality.
*/ | ||
async function ensureBootstrapped(fixture: TestFixture) { | ||
// Old-style bootstrap stack with default name | ||
if (await fixture.aws.stackStatus('CDKToolkit') === undefined) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure this is necessary? just running bootstrap
will no-op if no changes are detected, and if there are changes, shouldn't we bootstrap them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess, just cutting down on the duration (since that's the whole goal of this). It's still pretty expensive to do a no-op bootstrap.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, i'm still wondering about the need to re-bootstrap when changes are introduced. But thats for a later discussion.
const regionLease = await REGION_POOL.take(); | ||
|
||
context.output.write(` Stack prefix: ${stackNamePrefix}\n`); | ||
context.output.write(` Test directory: ${integTestDir}\n`); | ||
context.output.write(` Region: ${regionLease.value}\n`); | ||
|
||
await cloneDirectory(path.join(__dirname, 'app'), integTestDir, context.output); | ||
const fixture = new TestFixture( | ||
integTestDir, | ||
stackNamePrefix, | ||
context.output, | ||
regionLease, | ||
context.aws); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why take the lease here if it's going to be released within the dispose()
method? As mentioned previously, would be nice to see take()
and dispose()
in the same block/scope, making it easier to reason about.
Would it make more sense to take the least as part of the TextFixture
constructor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh wait. You are correct that i left a bug.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make more sense to take the least as part of the
TextFixture
constructor?
Can't. It's async.
/** | ||
* Higher order function to execute a block with a CDK app fixture | ||
* | ||
* Requires an AWS client to be passed in. | ||
* | ||
* For backwards compatibility with existing tests (so we don't have to change | ||
* too much) the inner block is expecte to take a `TestFixture` object. | ||
*/ | ||
export function withCdkApp<A extends TestContext & AwsContext>(block: (context: TestFixture) => Promise<void>) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very minor: Not just "with cdk app" but also "with region-based leases".
Could maybe split that into its own higher order function chain-link, or move that within withDefaultFixture()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well this wrapper doesn't ADD a region based lease, it adds a cdk fixture.
It does REQUIRE a region lease to do that, but that's not what the name means.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea being that these wrappers should be freely composeable to add more setup and teardown.
Thank you for contributing! Your pull request will be updated from master and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
@rix0rrr Added |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
Thank you for contributing! Your pull request will be updated from master and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
When
AWS_REGIONS=region1,region2,region3
is set, the CLI integrationtests are going to parallelize themselves across those regions.
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license