aws-cdk
Version:
CDK Toolkit, the command line tool for CDK apps
110 lines • 16.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
const fs = require("fs-extra");
const account_cache_1 = require("../../../lib/api/aws-auth/account-cache");
const util_1 = require("../../util");
async function makeCache() {
const dir = await fs.mkdtemp('/tmp/account-cache-test');
const file = path.join(dir, 'cache.json');
return {
cacheDir: dir,
cacheFile: file,
cache: new account_cache_1.AccountAccessKeyCache(file),
};
}
async function nukeCache(cacheDir) {
await fs.remove(cacheDir);
}
test('default account cache uses CDK_HOME', () => {
process.env.CDK_HOME = '/banana';
const cache = new account_cache_1.AccountAccessKeyCache();
expect(cache.cacheFile).toContain('/banana/');
});
test('account cache does not fail when given a nonwritable directory', async () => {
const accessError = new Error('Oh no');
accessError.code = 'EACCES';
return (0, util_1.withMocked)(fs, 'mkdirs', async (mkdirs) => {
// Have to do this because mkdirs has 2 overloads and it confuses TypeScript
mkdirs.mockRejectedValue(accessError);
const cache = new account_cache_1.AccountAccessKeyCache('/abc/xyz');
await cache.fetch('xyz', () => Promise.resolve({ accountId: 'asdf', partition: 'swa' }));
// No exception
});
});
test('get(k) when cache is empty', async () => {
const { cacheDir, cacheFile, cache } = await makeCache();
try {
expect(await cache.get('foo')).toBeUndefined();
expect(await fs.pathExists(cacheFile)).toBeFalsy();
}
finally {
await nukeCache(cacheDir);
}
});
test('put(k,v) and then get(k)', async () => {
const { cacheDir, cacheFile, cache } = await makeCache();
try {
await cache.put('key', { accountId: 'value', partition: 'aws' });
await cache.put('boo', { accountId: 'bar', partition: 'aws' });
expect(await cache.get('key')).toEqual({ accountId: 'value', partition: 'aws' });
// create another cache instance on the same file, should still work
const cache2 = new account_cache_1.AccountAccessKeyCache(cacheFile);
expect(await cache2.get('boo')).toEqual({ accountId: 'bar', partition: 'aws' });
// whitebox: read the file
expect(await fs.readJson(cacheFile)).toEqual({
key: { accountId: 'value', partition: 'aws' },
boo: { accountId: 'bar', partition: 'aws' },
});
}
finally {
await nukeCache(cacheDir);
}
});
test('fetch(k, resolver) can be used to "atomically" get + resolve + put', async () => {
const { cacheDir, cache } = await makeCache();
try {
expect(await cache.get('foo')).toBeUndefined();
expect(await cache.fetch('foo', async () => ({ accountId: 'bar', partition: 'aws' }))).toEqual({ accountId: 'bar', partition: 'aws' });
expect(await cache.get('foo')).toEqual({ accountId: 'bar', partition: 'aws' });
}
finally {
await nukeCache(cacheDir);
}
});
test(`cache is nuked if it exceeds ${account_cache_1.AccountAccessKeyCache.MAX_ENTRIES} entries`, async () => {
const { cacheDir, cacheFile, cache } = await makeCache();
try {
for (let i = 0; i < account_cache_1.AccountAccessKeyCache.MAX_ENTRIES; ++i) {
await cache.put(`key${i}`, { accountId: `value${i}`, partition: 'aws' });
}
// verify all values are on disk
const otherCache = new account_cache_1.AccountAccessKeyCache(cacheFile);
for (let i = 0; i < account_cache_1.AccountAccessKeyCache.MAX_ENTRIES; ++i) {
expect(await otherCache.get(`key${i}`)).toEqual({ accountId: `value${i}`, partition: 'aws' });
}
// add another value
await cache.put('nuke-me', { accountId: 'genesis', partition: 'aws' });
// now, we expect only `nuke-me` to exist on disk
expect(await otherCache.get('nuke-me')).toEqual({ accountId: 'genesis', partition: 'aws' });
for (let i = 0; i < account_cache_1.AccountAccessKeyCache.MAX_ENTRIES; ++i) {
expect(await otherCache.get(`key${i}`)).toBeUndefined();
}
}
finally {
await nukeCache(cacheDir);
}
},
// This makes a lot of promises, so it can queue for a while...
30000);
test('cache pretends to be empty if cache file does not contain JSON', async () => {
const { cacheDir, cacheFile, cache } = await makeCache();
try {
await fs.writeFile(cacheFile, '');
await expect(cache.get('abc')).resolves.toEqual(undefined);
}
finally {
await nukeCache(cacheDir);
}
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWNjb3VudC1jYWNoZS50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiYWNjb3VudC1jYWNoZS50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsNkJBQTZCO0FBQzdCLCtCQUErQjtBQUMvQiwyRUFBZ0Y7QUFDaEYscUNBQXdDO0FBRXhDLEtBQUssVUFBVSxTQUFTO0lBQ3RCLE1BQU0sR0FBRyxHQUFHLE1BQU0sRUFBRSxDQUFDLE9BQU8sQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO0lBQ3hELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLFlBQVksQ0FBQyxDQUFDO0lBQzFDLE9BQU87UUFDTCxRQUFRLEVBQUUsR0FBRztRQUNiLFNBQVMsRUFBRSxJQUFJO1FBQ2YsS0FBSyxFQUFFLElBQUkscUNBQXFCLENBQUMsSUFBSSxDQUFDO0tBQ3ZDLENBQUM7QUFDSixDQUFDO0FBRUQsS0FBSyxVQUFVLFNBQVMsQ0FBQyxRQUFnQjtJQUN2QyxNQUFNLEVBQUUsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDNUIsQ0FBQztBQUVELElBQUksQ0FBQyxxQ0FBcUMsRUFBRSxHQUFHLEVBQUU7SUFDL0MsT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEdBQUcsU0FBUyxDQUFDO0lBQ2pDLE1BQU0sS0FBSyxHQUFHLElBQUkscUNBQXFCLEVBQUUsQ0FBQztJQUMxQyxNQUFNLENBQUUsS0FBYSxDQUFDLFNBQVMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsQ0FBQztBQUN6RCxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxnRUFBZ0UsRUFBRSxLQUFLLElBQUksRUFBRTtJQUNoRixNQUFNLFdBQVcsR0FBRyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN0QyxXQUFtQixDQUFDLElBQUksR0FBRyxRQUFRLENBQUM7SUFFckMsT0FBTyxJQUFBLGlCQUFVLEVBQUMsRUFBRSxF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QUksQ0FBQztRQUNILE1BQU0sRUFBRSxDQUFDLFNBQVMsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFbEMsTUFBTSxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDN0QsQ0FBQztZQUFTLENBQUM7UUFDVCxNQUFNLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM1QixDQUFDO0FBQ0gsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMtZXh0cmEnO1xuaW1wb3J0IHsgQWNjb3VudEFjY2Vzc0tleUNhY2hlIH0gZnJvbSAnLi4vLi4vLi4vbGliL2FwaS9hd3MtYXV0aC9hY2NvdW50LWNhY2hlJztcbmltcG9ydCB7IHdpdGhNb2NrZWQgfSBmcm9tICcuLi8uLi91dGlsJztcblxuYXN5bmMgZnVuY3Rpb24gbWFrZUNhY2hlKCkge1xuICBjb25zdCBkaXIgPSBhd2FpdCBmcy5ta2R0ZW1wKCcvdG1wL2FjY291bnQtY2FjaGUtdGVzdCcpO1xuICBjb25zdCBmaWxlID0gcGF0aC5qb2luKGRpciwgJ2NhY2hlLmpzb24nKTtcbiAgcmV0dXJuIHtcbiAgICBjYWNoZURpcjogZGlyLFxuICAgIGNhY2hlRmlsZTogZmlsZSxcbiAgICBjYWNoZTogbmV3IEFjY291bnRBY2Nlc3NLZXlDYWNoZShmaWxlKSxcbiAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gbnVrZUNhY2hlKGNhY2hlRGlyOiBzdHJpbmcpIHtcbiAgYXdhaXQgZnMucmVtb3ZlKGNhY2hlRGlyKTtcbn1cblxudGVzdCgnZGVmYXVsdCBhY2NvdW50IGNhY2hlIHVzZXMgQ0RLX0hPTUUnLCAoKSA9PiB7XG4gIHByb2Nlc3MuZW52LkNES19IT01FID0gJy9iYW5hbmEnO1xuICBjb25zdCBjYWNoZSA9IG5ldyBBY2NvdW50QWNjZXNzS2V5Q2FjaGUoKTtcbiAgZXhwZWN0KChjYWNoZSBhcyBhbnkpLmNhY2hlRmlsZSkudG9Db250YWluKCcvYmFuYW5hLycpO1xufSk7XG5cbnRlc3QoJ2FjY291bnQgY2FjaGUgZG9lcyBub3QgZmFpbCB3aGVuIGdpdmVuIGEgbm9ud3JpdGFibGUgZGlyZWN0b3J5JywgYXN5bmMgKCkgPT4ge1xuICBjb25zdCBhY2Nlc3NFcnJvciA9IG5ldyBFcnJvcignT2ggbm8nKTtcbiAgKGFjY2Vzc0Vycm9yIGFzIGFueSkuY29kZSA9ICdFQUNDRVMnO1xuXG4gIHJldHVybiB3aXRoTW9ja2VkKGZzLCAnbWtkaXJzJywgYXN5bmMgKG1rZGlycykgPT4ge1xuICAgIC8vIEhhdmUgdG8gZG8gdGhpcyBiZWNhdXNlIG1rZGlycyBoYXMgMiBvdmVybG9hZHMgYW5kIGl0IGNvbmZ1c2VzIFR5cGVTY3JpcHRcbiAgICAobWtkaXJzIGFzIHVua25vd24gYXMgamVzdC5Nb2NrPFByb21pc2U8dm9pZD4sIFthbnldPikubW9ja1JlamVjdGVkVmFsdWUoYWNjZXNzRXJyb3IpO1xuXG4gICAgY29uc3QgY2FjaGUgPSBuZXcgQWNjb3VudEFjY2Vzc0tleUNhY2hlKCcvYWJjL3h5eicpO1xuICAgIGF3YWl0IGNhY2hlLmZldGNoKCd4eXonLCAoKSA9PiBQcm9taXNlLnJlc29sdmUoeyBhY2NvdW50SWQ6ICdhc2RmJywgcGFydGl0aW9uOiAnc3dhJyB9KSk7XG5cbiAgICAvLyBObyBleGNlcHRpb25cbiAgfSk7XG59KTtcblxudGVzdCgnZ2V0KGspIHdoZW4gY2FjaGUgaXMgZW1wdHknLCBhc3luYyAoKSA9PiB7XG4gIGNvbnN0IHsgY2FjaGVEaXIsIGNhY2hlRmlsZSwgY2FjaGUgfSA9IGF3YWl0IG1ha2VDYWNoZSgpO1xuICB0cnkge1xuICAgIGV4cGVjdChhd2FpdCBjYWNoZS5nZXQoJ2ZvbycpKS50b0JlVW5kZWZpbmVkKCk7XG4gICAgZXhwZWN0KGF3YWl0IGZzLnBhdGhFeGlzdHMoY2FjaGVGaWxlKSkudG9CZUZhbHN5KCk7XG4gIH0gZmluYWxseSB7XG4gICAgYXdhaXQgbnVrZUNhY2hlKGNhY2hlRGlyKTtcbiAgfVxufSk7XG5cbnRlc3QoJ3B1dChrLHYpIGFuZCB0aGVuIGdldChrKScsIGFzeW5jICgpID0+IHtcbiAgY29uc3QgeyBjYWNoZURpciwgY2FjaGVGaWxlLCBjYWNoZSB9ID0gYXdhaXQgbWFrZUNhY2hlKCk7XG5cbiAgdHJ5IHtcbiAgICBhd2FpdCBjYWNoZS5wdXQoJ2tleScsIHsgYWNjb3VudElkOiAndmFsdWUnLCBwYXJ0aXRpb246ICdhd3MnIH0pO1xuICAgIGF3YWl0IGNhY2hlLnB1dCgnYm9vJywgeyBhY2NvdW50SWQ6ICdiYXInLCBwYXJ0aXRpb246ICdhd3MnIH0pO1xuICAgIGV4cGVjdChhd2FpdCBjYWNoZS5nZXQoJ2tleScpKS50b0VxdWFsKHsgYWNjb3VudElkOiAndmFsdWUnLCBwYXJ0aXRpb246ICdhd3MnIH0pO1xuXG4gICAgLy8gY3JlYXRlIGFub3RoZXIgY2FjaGUgaW5zdGFuY2Ugb24gdGhlIHNhbWUgZmlsZSwgc2hvdWxkIHN0aWxsIHdvcmtcbiAgICBjb25zdCBjYWNoZTIgPSBuZXcgQWNjb3VudEFjY2Vzc0tleUNhY2hlKGNhY2hlRmlsZSk7XG4gICAgZXhwZWN0KGF3YWl0IGNhY2hlMi5nZXQoJ2JvbycpKS50b0VxdWFsKHsgYWNjb3VudElkOiAnYmFyJywgcGFydGl0aW9uOiAnYXdzJyB9KTtcblxuICAgIC8vIHdoaXRlYm94OiByZWFkIHRoZSBmaWxlXG4gICAgZXhwZWN0KGF3YWl0IGZzLnJlYWRKc29uKGNhY2hlRmlsZSkpLnRvRXF1YWwoe1xuICAgICAga2V5OiB7IGFjY291bnRJZDogJ3ZhbHVlJywgcGFydGl0aW9uOiAnYXdzJyB9LFxuICAgICAgYm9vOiB7IGFjY291bnRJZDogJ2JhcicsIHBhcnRpdGlvbjogJ2F3cycgfSxcbiAgICB9KTtcbiAgfSBmaW5hbGx5IHtcbiAgICBhd2FpdCBudWtlQ2FjaGUoY2FjaGVEaXIpO1xuICB9XG59KTtcblxudGVzdCgnZmV0Y2goaywgcmVzb2x2ZXIpIGNhbiBiZSB1c2VkIHRvIFwiYXRvbWljYWxseVwiIGdldCArIHJlc29sdmUgKyBwdXQnLCBhc3luYyAoKSA9PiB7XG4gIGNvbnN0IHsgY2FjaGVEaXIsIGNhY2hlIH0gPSBhd2FpdCBtYWtlQ2FjaGUoKTtcblxuICB0cnkge1xuICAgIGV4cGVjdChhd2FpdCBjYWNoZS5nZXQoJ2ZvbycpKS50b0JlVW5kZWZpbmVkKCk7XG4gICAgZXhwZWN0KGF3YWl0IGNhY2hlLmZldGNoKCdmb28nLCBhc3luYyAoKSA9PiAoeyBhY2NvdW50SWQ6ICdiYXInLCBwYXJ0aXRpb246ICdhd3MnIH0pKSkudG9FcXVhbCh7IGFjY291bnRJZDogJ2JhcicsIHBhcnRpdGlvbjogJ2F3cycgfSk7XG4gICAgZXhwZWN0KGF3YWl0IGNhY2hlLmdldCgnZm9vJykpLnRvRXF1YWwoeyBhY2NvdW50SWQ6ICdiYXInLCBwYXJ0aXRpb246ICdhd3MnIH0pO1xuICB9IGZpbmFsbHkge1xuICAgIGF3YWl0IG51a2VDYWNoZShjYWNoZURpcik7XG4gIH1cbn0pO1xuXG50ZXN0KGBjYWNoZSBpcyBudWtlZCBpZiBpdCBleGNlZWRzICR7QWNjb3VudEFjY2Vzc0tleUNhY2hlLk1BWF9FTlRSSUVTfSBlbnRyaWVzYCwgYXN5bmMgKCkgPT4ge1xuXG4gIGNvbnN0IHsgY2FjaGVEaXIsIGNhY2hlRmlsZSwgY2FjaGUgfSA9IGF3YWl0IG1ha2VDYWNoZSgpO1xuXG4gIHRyeSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBBY2NvdW50QWNjZXNzS2V5Q2FjaGUuTUFYX0VOVFJJRVM7ICsraSkge1xuICAgICAgYXdhaXQgY2FjaGUucHV0KGBrZXkke2l9YCwgeyBhY2NvdW50SWQ6IGB2YWx1ZSR7aX1gLCBwYXJ0aXRpb246ICdhd3MnIH0pO1xuICAgIH1cblxuICAgIC8vIHZlcmlmeSBhbGwgdmFsdWVzIGFyZSBvbiBkaXNrXG4gICAgY29uc3Qgb3RoZXJDYWNoZSA9IG5ldyBBY2NvdW50QWNjZXNzS2V5Q2FjaGUoY2FjaGVGaWxlKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IEFjY291bnRBY2Nlc3NLZXlDYWNoZS5NQVhfRU5UUklFUzsgKytpKSB7XG4gICAgICBleHBlY3QoYXdhaXQgb3RoZXJDYWNoZS5nZXQoYGtleSR7aX1gKSkudG9FcXVhbCh7IGFjY291bnRJZDogYHZhbHVlJHtpfWAsIHBhcnRpdGlvbjogJ2F3cycgfSk7XG4gICAgfVxuXG4gICAgLy8gYWRkIGFub3RoZXIgdmFsdWVcbiAgICBhd2FpdCBjYWNoZS5wdXQoJ251a2UtbWUnLCB7IGFjY291bnRJZDogJ2dlbmVzaXMnLCBwYXJ0aXRpb246ICdhd3MnIH0pO1xuXG4gICAgLy8gbm93LCB3ZSBleHBlY3Qgb25seSBgbnVrZS1tZWAgdG8gZXhpc3Qgb24gZGlza1xuICAgIGV4cGVjdChhd2FpdCBvdGhlckNhY2hlLmdldCgnbnVrZS1tZScpKS50b0VxdWFsKHsgYWNjb3VudElkOiAnZ2VuZXNpcycsIHBhcnRpdGlvbjogJ2F3cycgfSk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBBY2NvdW50QWNjZXNzS2V5Q2FjaGUuTUFYX0VOVFJJRVM7ICsraSkge1xuICAgICAgZXhwZWN0KGF3YWl0IG90aGVyQ2FjaGUuZ2V0KGBrZXkke2l9YCkpLnRvQmVVbmRlZmluZWQoKTtcbiAgICB9XG4gIH0gZmluYWxseSB7XG4gICAgYXdhaXQgbnVrZUNhY2hlKGNhY2hlRGlyKTtcbiAgfVxufSxcbi8vIFRoaXMgbWFrZXMgYSBsb3Qgb2YgcHJvbWlzZXMsIHNvIGl0IGNhbiBxdWV1ZSBmb3IgYSB3aGlsZS4uLlxuMzBfMDAwKTtcblxudGVzdCgnY2FjaGUgcHJldGVuZHMgdG8gYmUgZW1wdHkgaWYgY2FjaGUgZmlsZSBkb2VzIG5vdCBjb250YWluIEpTT04nLCBhc3luYygpID0+IHtcbiAgY29uc3QgeyBjYWNoZURpciwgY2FjaGVGaWxlLCBjYWNoZSB9ID0gYXdhaXQgbWFrZUNhY2hlKCk7XG4gIHRyeSB7XG4gICAgYXdhaXQgZnMud3JpdGVGaWxlKGNhY2hlRmlsZSwgJycpO1xuXG4gICAgYXdhaXQgZXhwZWN0KGNhY2hlLmdldCgnYWJjJykpLnJlc29sdmVzLnRvRXF1YWwodW5kZWZpbmVkKTtcbiAgfSBmaW5hbGx5IHtcbiAgICBhd2FpdCBudWtlQ2FjaGUoY2FjaGVEaXIpO1xuICB9XG59KTtcbiJdfQ==