-
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
fix(cli): failure if account cache is malformed #10887
Conversation
Because of concurrent running of integration tests, the account cache (which is supposed to be a JSON file) can be read in a state where it's empty or incompletely written, which fails the JSON parse. If that happens, ignore the error and pretend the cache is empty. Fixes sporadic concurrency issues in the integration tests.
packages/aws-cdk/bin/cdk.ts
Outdated
console.log(configuration.context); | ||
console.log(configuration.context.all); | ||
console.log(configuration.context.get(cxapi.ENABLE_DIFF_NO_FAIL)); |
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 assume these were for diagnostic purposes and should be removed.
packages/aws-cdk/bin/cdk.ts
Outdated
@@ -229,6 +229,9 @@ async function initCommandLine() { | |||
return cli.list(args.STACKS, { long: args.long }); | |||
|
|||
case 'diff': | |||
console.log(configuration.context); |
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.
Intentional...?
@@ -83,6 +83,9 @@ export class AccountAccessKeyCache { | |||
// File doesn't exist or is not readable. This is a cache, | |||
// pretend we successfully loaded an empty map. | |||
if (e.code === 'ENOENT' || e.code === 'EACCES') { return {}; } | |||
// File is not JSON, could be corrupted because of concurrent writes. | |||
// Again, an empty cache is fine. | |||
if (e instanceof SyntaxError) { return {}; } |
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.
Im actually not sure this is because of the parallelism of the integ tests, i remember @rix0rrr and I encountered this issue a few months ago and ended up in a rabbit hole of sdk code.
What if we set the CDK_HOME
env variable to be unique per execution before we resort to this? I'm not strictly opposed to it but i feel like we are doing it for the wrong reasons now and we might be missing something else.
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.
This specifically has nothing to do with the SDK. This file is completely under our control, written and read by us only.
I can't imagine it being anything other than the parallelism we introduced recently, given that I haven't seen this error crop up before that.
I'm open to another explanation of the available facts if you have them, and I'll agree it breaks my mental model of how I thought NodeJS worked as well. Even concurrency isn't the ultimate root cause, I'm not concerned about this fix too much, which is why I'm hesitant to do more complicated workarounds.
This is all to say: I say we ship it :).
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.
Uh umm. It might also be this:
aws-cdk/packages/aws-cdk/lib/api/aws-auth/account-cache.ts
Lines 92 to 93 in ddff369
await fs.ensureFile(this.cacheFile); | |
await fs.writeJson(this.cacheFile, map, { spaces: 2 }); |
But even given that I don't mind too much to put this workaround in. It will also catch malformed caches for other reasons (outside our control).
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.
Ship and may the force be with you 👍
For future reference, I wrote a script to test assumptions, running Result:
About 25% of the reads read a broken file. var fs = require('fs-extra');
const filename = 'bla.json';
function bigObject(n) {
if (n === 0) { return {}; }
return {
[`a${n}`]: bigObject(n-1),
[`b${n}`]: bigObject(n-1),
};
}
let running = true;
new Promise(async (ok) => {
const bo = bigObject(10);
while (running) {
try {
await fs.writeJson(filename, bo, { spaces: 2 });
} catch(e) {
console.log(e.message);
}
}
}).then(console.log);
const counters = {};
function countHit(message) {
if (message in counters)
counters[message] += 1;
else
counters[message] = 1;
}
new Promise(async (ok) => {
for (let i = 0; i < 1000; i++) {
try {
await fs.readJson(filename);
countHit('read ok');
} catch(e) {
countHit(e.message);
}
}
ok();
}).then(() => {
running = false;
// Print a summary
for (const [k, v] of Object.entries(counters)) {
console.log(`${k}: ${v}`);
}
}); |
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). |
Because of concurrent running of integration tests, the account
cache (which is supposed to be a JSON file) can be read in a state
where it's empty or incompletely written, which fails the JSON parse.
If that happens, ignore the error and pretend the cache is empty.
Fixes sporadic concurrency issues in the integration tests.
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license