From d72fa128b962a86eaa501e8225a9707892afc7d9 Mon Sep 17 00:00:00 2001 From: Jonathan Kovarik Date: Fri, 29 Jun 2018 08:40:29 -0600 Subject: [PATCH 01/10] Add zip archive validation method to zipLambda We need to be sure there isn't an invalid package file left over from a previous aborted kes run - as the hash is generated and written as the filestream is opened in kes.utils.zip, and kes is capable of async calling process.exit, it's possible to have truncated/0 byte zip files. This validator ensures that the file is a legitimate zip archive in addition to a matching hash filename. --- packages/deployment/lib/lambda.js | 39 +++++++++++++++--- packages/deployment/test/test_lambda.js | 55 ++++++++++++++++++++----- 2 files changed, 79 insertions(+), 15 deletions(-) diff --git a/packages/deployment/lib/lambda.js b/packages/deployment/lib/lambda.js index 5f49cb443ba..a481b987d92 100644 --- a/packages/deployment/lib/lambda.js +++ b/packages/deployment/lib/lambda.js @@ -7,6 +7,8 @@ const path = require('path'); const utils = require('kes').utils; const { Lambda } = require('kes'); +const yauzl = require('yauzl'); + /** * A sub-class of the Kes Lambda class that changes * how kes handles Lambda function compression and @@ -27,6 +29,28 @@ class UpdatedLambda extends Lambda { super(config); this.config = config; } + + /** + * Makes use of yauzl.open's verification + * to validate the file referenced in lambda.local + * is a valid zip archive + * + * @param {Object} lambda - the lambda object + * + * @returns {Promise} promise resolution indicates success, will reject if + * zipfile cannot be opened + **/ + validateZipFile(lambda) { + return new Promise((resolve, reject) => { + yauzl.open(lambda.local, (err, _zipfile) => { + if (err) { + reject(err); + } + resolve(); + }); + }); + } + /** * Copies the source code of a given lambda function, zips it, calculates * the hash of the source code and updates the lambda object with @@ -35,14 +59,20 @@ class UpdatedLambda extends Lambda { * @param {Object} lambda - the lambda object * @returns {Promise} returns the updated lambda object */ - zipLambda(lambda) { + async zipLambda(lambda) { let msg = `Zipping ${lambda.local}`; // skip if the file with the same hash is zipped + // and is a valid zip file if (fs.existsSync(lambda.local)) { - return Promise.resolve(lambda); + try { + await this.validateZipFile(lambda); + return Promise.resolve(lambda); + } + catch (e) { + console.log(`${lambda.local} appears to be an invalid zip file, and will be re-built`); + } } const fileList = [lambda.source]; - if (lambda.useMessageAdapter) { const kesFolder = path.join(this.config.kesFolder, 'build', 'adapter'); fileList.push(kesFolder); @@ -50,8 +80,7 @@ class UpdatedLambda extends Lambda { } console.log(`${msg} for ${lambda.name}`); - - return utils.zip(lambda.local, fileList).then(() => lambda); + return utils.zip(lambda.local, fileList).then(() => lambda).catch((e) => console.log(`Error zipping ${e}`)); } /** diff --git a/packages/deployment/test/test_lambda.js b/packages/deployment/test/test_lambda.js index 24d7d2df31c..7077b20fa8e 100644 --- a/packages/deployment/test/test_lambda.js +++ b/packages/deployment/test/test_lambda.js @@ -25,7 +25,7 @@ test.beforeEach(async (t) => { bucket: 'testbucket', stack: 'teststack' }; - + t.context.fixturedir = 'test/fixtures'; t.context.lambda = { handler: 'index.handler', name: 'lambda-example', @@ -62,7 +62,7 @@ test.serial('zipLambda: works for lambda not using message adapter', async (t) = t.context.lambda.useMessageAdapter = false; const lambdaLocalOrigin = t.context.lambda.local; const lambdaRemoteOrigin = t.context.lambda.remote; - const l = new Lambda(t.context.config) + const l = new Lambda(t.context.config); await l.zipLambda(l.buildS3Path(t.context.lambda)); t.truthy(fs.statSync(t.context.lambda.local)); t.is(t.context.lambda.local, lambdaLocalOrigin); @@ -73,7 +73,7 @@ test.serial('zipLambda: works for lambda using message adapter', async (t) => { t.context.lambda.useMessageAdapter = true; const lambdaLocalOrigin = t.context.lambda.local; const lambdaRemoteOrigin = t.context.lambda.remote; - const l = new Lambda(t.context.config) + const l = new Lambda(t.context.config); await l.zipLambda(l.buildS3Path(t.context.lambda)); t.truthy(fs.statSync(t.context.lambda.local)); t.is( @@ -87,7 +87,42 @@ test.serial('zipLambda: works for lambda using message adapter', async (t) => { }); test.serial( - `zipLambda: for lambda using message adapter, no new file is generated + `zipLambda: given an invalid zip file generated from a previous run, + a new valid lambda file is generated`, + async (t) => { + t.context.lambda.useMessageAdapter = true; + const lambdaLocalOrigin = t.context.lambda.local; + const lambdaRemoteOrigin = t.context.lambda.remote; + + // put an empty lambda zip file there as the result of the previous run + const existingLambdaLocal = path.join( + path.dirname(t.context.lambda.local), + `${Lambda.messageAdapterZipFileHash}-${path.basename(t.context.lambda.local)}` + ); + + fs.writeFileSync(existingLambdaLocal, 'hello'); + t.is(fs.statSync(existingLambdaLocal).size, 5); + + const l = new Lambda(t.context.config); + await l.zipLambda(l.buildS3Path(t.context.lambda)); + t.truthy(fs.statSync(t.context.lambda.local)); + t.true(fs.statSync(t.context.lambda.local).size > 5); + t.is(t.context.lambda.local, existingLambdaLocal); + + t.is( + path.basename(t.context.lambda.local), + `${Lambda.messageAdapterZipFileHash}-${path.basename(lambdaLocalOrigin)}` + ); + t.is( + path.basename(t.context.lambda.remote), + `${Lambda.messageAdapterZipFileHash}-${path.basename(lambdaRemoteOrigin)}` + ); + } +); + + +test.serial( + `zipLambda: for lambda using message adapter, no new file is generated if the task and message adapter are not updated`, async (t) => { t.context.lambda.useMessageAdapter = true; @@ -103,20 +138,20 @@ test.serial( `${Lambda.messageAdapterZipFileHash}-${path.basename(t.context.lambda.remote)}` ); - fs.writeFileSync(existingLambdaLocal, 'hello'); - t.is(fs.statSync(existingLambdaLocal).size, 5); + fs.copySync(`${t.context.fixturedir}/zipfile-fixture.zip`, existingLambdaLocal); + t.is(fs.statSync(existingLambdaLocal).size, 180); - const l = new Lambda(t.context.config) + const l = new Lambda(t.context.config); await l.zipLambda(l.buildS3Path(t.context.lambda)); t.truthy(fs.statSync(t.context.lambda.local)); - t.is(fs.statSync(t.context.lambda.local).size, 5); + t.is(fs.statSync(t.context.lambda.local).size, 180); t.is(t.context.lambda.local, existingLambdaLocal); t.is(t.context.lambda.remote, existingLambdaRemote); } ); test.serial( - `zipLambda: for lambda using message adapter, a new file is created + `zipLambda: for lambda using message adapter, a new file is created if the message adapter is updated`, async (t) => { t.context.lambda.useMessageAdapter = true; @@ -136,7 +171,7 @@ test.serial( const adapterHashOrigin = Lambda.messageAdapterZipFileHash; Lambda.messageAdapterZipFileHash = `${adapterHashOrigin}123`; - const l = new Lambda(t.context.config) + const l = new Lambda(t.context.config); await l.zipLambda(l.buildS3Path(t.context.lambda)); t.truthy(fs.statSync(t.context.lambda.local)); t.true(fs.statSync(t.context.lambda.local).size > 5); From b45a71c3e4fa7cf646446e07709d8c89ab4c1905 Mon Sep 17 00:00:00 2001 From: Jonathan Kovarik Date: Fri, 29 Jun 2018 08:45:01 -0600 Subject: [PATCH 02/10] Update CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cfaa0cd0c16..92cb5514ae4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - update the StreamSpecification DynamoDB tables to have StreamViewType: "NEW_AND_OLD_IMAGES" - delete granule files in s3 - **CUMULUS-398** - Fix not able to filter executions bu workflow +- **CUMULUS-748** - Fix invalid lambda .zip files being validaed/uploaded to AWS ## [v1.6.0] - 2018-06-06 @@ -353,4 +354,3 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. [v1.1.0]: https://github.com/cumulus-nasa/cumulus/compare/v1.0.1...v1.1.0 [v1.0.1]: https://github.com/cumulus-nasa/cumulus/compare/v1.0.0...v1.0.1 [v1.0.0]: https://github.com/cumulus-nasa/cumulus/compare/pre-v1-release...v1.0.0 - From fb25317d8d9777b15c47d09d42c76aebc0801383 Mon Sep 17 00:00:00 2001 From: Jonathan Kovarik Date: Fri, 29 Jun 2018 08:48:12 -0600 Subject: [PATCH 03/10] Add test fixture --- .../deployment/test/fixtures/zipfile-fixture.zip | Bin 0 -> 180 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 packages/deployment/test/fixtures/zipfile-fixture.zip diff --git a/packages/deployment/test/fixtures/zipfile-fixture.zip b/packages/deployment/test/fixtures/zipfile-fixture.zip new file mode 100644 index 0000000000000000000000000000000000000000..7b4da6593c52800ce82cda8fb15afedeb9c8e8d8 GIT binary patch literal 180 zcmWIWW@h1H0D;-9`+dL+D8bJl!;q7ho0O8Mn_7{WTac5g9~#2R!2GmIAlk&0FuZjHF)<8gg&2%sC@ULCIU^8;0%=bWhXDXj C!5#_# literal 0 HcmV?d00001 From 5000f71b8c7772c0daaf2d80cf036f2cb7640bee Mon Sep 17 00:00:00 2001 From: Jonathan Kovarik Date: Fri, 29 Jun 2018 09:15:49 -0600 Subject: [PATCH 04/10] Fix CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92cb5514ae4..a7ca53a2e16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - update the StreamSpecification DynamoDB tables to have StreamViewType: "NEW_AND_OLD_IMAGES" - delete granule files in s3 - **CUMULUS-398** - Fix not able to filter executions bu workflow -- **CUMULUS-748** - Fix invalid lambda .zip files being validaed/uploaded to AWS +- **CUMULUS-748** - Fix invalid lambda .zip files being validated/uploaded to AWS ## [v1.6.0] - 2018-06-06 From aa3fa5749f980bfc760dcd4624cbc067a98f1a8e Mon Sep 17 00:00:00 2001 From: Jonathan Kovarik Date: Fri, 29 Jun 2018 09:54:21 -0600 Subject: [PATCH 05/10] Updating ratchet This is a fairly large number, however that seems to also be the case on master --- .eslint-ratchet-high-water-mark | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslint-ratchet-high-water-mark b/.eslint-ratchet-high-water-mark index 51ea4a54f90..5873851d327 100644 --- a/.eslint-ratchet-high-water-mark +++ b/.eslint-ratchet-high-water-mark @@ -1 +1 @@ -670 +467 From 7fe3b3878f646468f32c43345847a1099da33cc2 Mon Sep 17 00:00:00 2001 From: Jonathan Kovarik Date: Mon, 2 Jul 2018 22:34:24 -0600 Subject: [PATCH 06/10] Address PR commentary - --- packages/deployment/lib/lambda.js | 37 ++++++++----------------- packages/deployment/test/test_lambda.js | 34 ++++++++++++----------- 2 files changed, 30 insertions(+), 41 deletions(-) diff --git a/packages/deployment/lib/lambda.js b/packages/deployment/lib/lambda.js index a481b987d92..20ffcab3276 100644 --- a/packages/deployment/lib/lambda.js +++ b/packages/deployment/lib/lambda.js @@ -4,10 +4,12 @@ const fs = require('fs-extra'); const path = require('path'); +const util = require('util'); const utils = require('kes').utils; +const yauzl = require('yauzl'); + const { Lambda } = require('kes'); -const yauzl = require('yauzl'); /** * A sub-class of the Kes Lambda class that changes @@ -30,42 +32,22 @@ class UpdatedLambda extends Lambda { this.config = config; } - /** - * Makes use of yauzl.open's verification - * to validate the file referenced in lambda.local - * is a valid zip archive - * - * @param {Object} lambda - the lambda object - * - * @returns {Promise} promise resolution indicates success, will reject if - * zipfile cannot be opened - **/ - validateZipFile(lambda) { - return new Promise((resolve, reject) => { - yauzl.open(lambda.local, (err, _zipfile) => { - if (err) { - reject(err); - } - resolve(); - }); - }); - } - /** * Copies the source code of a given lambda function, zips it, calculates * the hash of the source code and updates the lambda object with - * the hash, local and remote locations of the code + * the hash, local and remote locations of the code. * * @param {Object} lambda - the lambda object * @returns {Promise} returns the updated lambda object */ + async zipLambda(lambda) { let msg = `Zipping ${lambda.local}`; // skip if the file with the same hash is zipped // and is a valid zip file if (fs.existsSync(lambda.local)) { try { - await this.validateZipFile(lambda); + await (util.promisify(yauzl.open))(lambda.local); // Verify yauzl can open the .zip file return Promise.resolve(lambda); } catch (e) { @@ -80,7 +62,12 @@ class UpdatedLambda extends Lambda { } console.log(`${msg} for ${lambda.name}`); - return utils.zip(lambda.local, fileList).then(() => lambda).catch((e) => console.log(`Error zipping ${e}`)); + return utils.zip(lambda.local, fileList) + .then(() => lambda) + .catch((e) => { + console.log(`Error zipping ${e}`); + throw (e); + }); } /** diff --git a/packages/deployment/test/test_lambda.js b/packages/deployment/test/test_lambda.js index 7077b20fa8e..539e7d6b107 100644 --- a/packages/deployment/test/test_lambda.js +++ b/packages/deployment/test/test_lambda.js @@ -3,14 +3,17 @@ 'use strict'; -const os = require('os'); const fs = require('fs-extra'); +const os = require('os'); const path = require('path'); const test = require('ava'); + const Lambda = require('../lib/lambda'); const { fetchMessageAdapter } = require('../lib/adapter'); const gitPath = 'cumulus-nasa/cumulus-message-adapter'; +const zipFixturePath = 'test/fixtures/zipfile-fixture.zip'; +const zipFixtureSize = fs.statSync(zipFixturePath).size; test.beforeEach(async (t) => { t.context.temp = fs.mkdtempSync(`${os.tmpdir()}${path.sep}`); @@ -25,7 +28,6 @@ test.beforeEach(async (t) => { bucket: 'testbucket', stack: 'teststack' }; - t.context.fixturedir = 'test/fixtures'; t.context.lambda = { handler: 'index.handler', name: 'lambda-example', @@ -62,8 +64,8 @@ test.serial('zipLambda: works for lambda not using message adapter', async (t) = t.context.lambda.useMessageAdapter = false; const lambdaLocalOrigin = t.context.lambda.local; const lambdaRemoteOrigin = t.context.lambda.remote; - const l = new Lambda(t.context.config); - await l.zipLambda(l.buildS3Path(t.context.lambda)); + const testLambda = new Lambda(t.context.config); + await testLambda.zipLambda(testLambda.buildS3Path(t.context.lambda)); t.truthy(fs.statSync(t.context.lambda.local)); t.is(t.context.lambda.local, lambdaLocalOrigin); t.is(t.context.lambda.remote, lambdaRemoteOrigin); @@ -73,8 +75,8 @@ test.serial('zipLambda: works for lambda using message adapter', async (t) => { t.context.lambda.useMessageAdapter = true; const lambdaLocalOrigin = t.context.lambda.local; const lambdaRemoteOrigin = t.context.lambda.remote; - const l = new Lambda(t.context.config); - await l.zipLambda(l.buildS3Path(t.context.lambda)); + const testLambda = new Lambda(t.context.config); + await testLambda.zipLambda(testLambda.buildS3Path(t.context.lambda)); t.truthy(fs.statSync(t.context.lambda.local)); t.is( path.basename(t.context.lambda.local), @@ -103,8 +105,8 @@ test.serial( fs.writeFileSync(existingLambdaLocal, 'hello'); t.is(fs.statSync(existingLambdaLocal).size, 5); - const l = new Lambda(t.context.config); - await l.zipLambda(l.buildS3Path(t.context.lambda)); + const testLambda = new Lambda(t.context.config); + await testLambda.zipLambda(testLambda.buildS3Path(t.context.lambda)); t.truthy(fs.statSync(t.context.lambda.local)); t.true(fs.statSync(t.context.lambda.local).size > 5); t.is(t.context.lambda.local, existingLambdaLocal); @@ -138,13 +140,13 @@ test.serial( `${Lambda.messageAdapterZipFileHash}-${path.basename(t.context.lambda.remote)}` ); - fs.copySync(`${t.context.fixturedir}/zipfile-fixture.zip`, existingLambdaLocal); - t.is(fs.statSync(existingLambdaLocal).size, 180); + await fs.copy(zipFixturePath, existingLambdaLocal); + t.is(fs.statSync(existingLambdaLocal).size, zipFixtureSize); - const l = new Lambda(t.context.config); - await l.zipLambda(l.buildS3Path(t.context.lambda)); + const testLambda = new Lambda(t.context.config); + await testLambda.zipLambda(testLambda.buildS3Path(t.context.lambda)); t.truthy(fs.statSync(t.context.lambda.local)); - t.is(fs.statSync(t.context.lambda.local).size, 180); + t.is(fs.statSync(t.context.lambda.local).size, zipFixtureSize); t.is(t.context.lambda.local, existingLambdaLocal); t.is(t.context.lambda.remote, existingLambdaRemote); } @@ -164,15 +166,15 @@ test.serial( `${Lambda.messageAdapterZipFileHash}-${path.basename(t.context.lambda.local)}` ); - fs.writeFileSync(existingLambdaLocal, 'hello'); + await fs.writeFile(existingLambdaLocal, 'hello'); t.is(fs.statSync(existingLambdaLocal).size, 5); // message adapter is updated, a new lambda zip file is generated const adapterHashOrigin = Lambda.messageAdapterZipFileHash; Lambda.messageAdapterZipFileHash = `${adapterHashOrigin}123`; - const l = new Lambda(t.context.config); - await l.zipLambda(l.buildS3Path(t.context.lambda)); + const testLambda = new Lambda(t.context.config); + await testLambda.zipLambda(testLambda.buildS3Path(t.context.lambda)); t.truthy(fs.statSync(t.context.lambda.local)); t.true(fs.statSync(t.context.lambda.local).size > 5); t.not(t.context.lambda.local, existingLambdaLocal); From 56b83fc40bdc164f6545a9b3842a2e71b7ee72f1 Mon Sep 17 00:00:00 2001 From: Jonathan Kovarik Date: Mon, 2 Jul 2018 23:06:12 -0600 Subject: [PATCH 07/10] re-ratchet post PR changes --- .eslint-ratchet-high-water-mark | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslint-ratchet-high-water-mark b/.eslint-ratchet-high-water-mark index 5873851d327..f27d46f4017 100644 --- a/.eslint-ratchet-high-water-mark +++ b/.eslint-ratchet-high-water-mark @@ -1 +1 @@ -467 +466 From dd789e01bc5a113486cee6777d8bb4dc58173e74 Mon Sep 17 00:00:00 2001 From: Jonathan Kovarik Date: Tue, 3 Jul 2018 10:40:56 -0600 Subject: [PATCH 08/10] Add uncommited hunk/update from PR changes --- packages/deployment/test/test_lambda.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/deployment/test/test_lambda.js b/packages/deployment/test/test_lambda.js index 539e7d6b107..1c6a920e327 100644 --- a/packages/deployment/test/test_lambda.js +++ b/packages/deployment/test/test_lambda.js @@ -102,7 +102,7 @@ test.serial( `${Lambda.messageAdapterZipFileHash}-${path.basename(t.context.lambda.local)}` ); - fs.writeFileSync(existingLambdaLocal, 'hello'); + await fs.writeFile(existingLambdaLocal, 'hello'); t.is(fs.statSync(existingLambdaLocal).size, 5); const testLambda = new Lambda(t.context.config); From c77310d688ae1c82e46f42b59d32fff1906125b7 Mon Sep 17 00:00:00 2001 From: Marc Huffnagle Date: Thu, 5 Jul 2018 09:52:43 -0400 Subject: [PATCH 09/10] CUMULUS-748 PR feedback changes --- packages/deployment/lib/lambda.js | 24 +-- packages/deployment/test/test_lambda.js | 190 +++++++++++------------- 2 files changed, 103 insertions(+), 111 deletions(-) diff --git a/packages/deployment/lib/lambda.js b/packages/deployment/lib/lambda.js index 20ffcab3276..3877bd1d07d 100644 --- a/packages/deployment/lib/lambda.js +++ b/packages/deployment/lib/lambda.js @@ -10,7 +10,6 @@ const yauzl = require('yauzl'); const { Lambda } = require('kes'); - /** * A sub-class of the Kes Lambda class that changes * how kes handles Lambda function compression and @@ -42,18 +41,19 @@ class UpdatedLambda extends Lambda { */ async zipLambda(lambda) { - let msg = `Zipping ${lambda.local}`; // skip if the file with the same hash is zipped // and is a valid zip file - if (fs.existsSync(lambda.local)) { + if (await fs.pathExists(lambda.local)) { try { await (util.promisify(yauzl.open))(lambda.local); // Verify yauzl can open the .zip file return Promise.resolve(lambda); } catch (e) { - console.log(`${lambda.local} appears to be an invalid zip file, and will be re-built`); + console.log(`${lambda.local} is valid and will be rebuilt`); } } + + let msg = `Zipping ${lambda.local}`; const fileList = [lambda.source]; if (lambda.useMessageAdapter) { const kesFolder = path.join(this.config.kesFolder, 'build', 'adapter'); @@ -62,12 +62,16 @@ class UpdatedLambda extends Lambda { } console.log(`${msg} for ${lambda.name}`); - return utils.zip(lambda.local, fileList) - .then(() => lambda) - .catch((e) => { - console.log(`Error zipping ${e}`); - throw (e); - }); + + try { + await utils.zip(lambda.local, fileList); + } + catch (e) { + console.log(`Error zipping ${e}`); + throw e; + } + + return lambda; } /** diff --git a/packages/deployment/test/test_lambda.js b/packages/deployment/test/test_lambda.js index 1c6a920e327..54d66d4fcb0 100644 --- a/packages/deployment/test/test_lambda.js +++ b/packages/deployment/test/test_lambda.js @@ -88,104 +88,92 @@ test.serial('zipLambda: works for lambda using message adapter', async (t) => { ); }); -test.serial( - `zipLambda: given an invalid zip file generated from a previous run, - a new valid lambda file is generated`, - async (t) => { - t.context.lambda.useMessageAdapter = true; - const lambdaLocalOrigin = t.context.lambda.local; - const lambdaRemoteOrigin = t.context.lambda.remote; - - // put an empty lambda zip file there as the result of the previous run - const existingLambdaLocal = path.join( - path.dirname(t.context.lambda.local), - `${Lambda.messageAdapterZipFileHash}-${path.basename(t.context.lambda.local)}` - ); - - await fs.writeFile(existingLambdaLocal, 'hello'); - t.is(fs.statSync(existingLambdaLocal).size, 5); - - const testLambda = new Lambda(t.context.config); - await testLambda.zipLambda(testLambda.buildS3Path(t.context.lambda)); - t.truthy(fs.statSync(t.context.lambda.local)); - t.true(fs.statSync(t.context.lambda.local).size > 5); - t.is(t.context.lambda.local, existingLambdaLocal); - - t.is( - path.basename(t.context.lambda.local), - `${Lambda.messageAdapterZipFileHash}-${path.basename(lambdaLocalOrigin)}` - ); - t.is( - path.basename(t.context.lambda.remote), - `${Lambda.messageAdapterZipFileHash}-${path.basename(lambdaRemoteOrigin)}` - ); - } -); - - -test.serial( - `zipLambda: for lambda using message adapter, no new file is generated - if the task and message adapter are not updated`, - async (t) => { - t.context.lambda.useMessageAdapter = true; - - // put a lambda zip file there as the result of the previous run - const existingLambdaLocal = path.join( - path.dirname(t.context.lambda.local), - `${Lambda.messageAdapterZipFileHash}-${path.basename(t.context.lambda.local)}` - ); - - const existingLambdaRemote = path.join( - path.dirname(t.context.lambda.remote), - `${Lambda.messageAdapterZipFileHash}-${path.basename(t.context.lambda.remote)}` - ); - - await fs.copy(zipFixturePath, existingLambdaLocal); - t.is(fs.statSync(existingLambdaLocal).size, zipFixtureSize); - - const testLambda = new Lambda(t.context.config); - await testLambda.zipLambda(testLambda.buildS3Path(t.context.lambda)); - t.truthy(fs.statSync(t.context.lambda.local)); - t.is(fs.statSync(t.context.lambda.local).size, zipFixtureSize); - t.is(t.context.lambda.local, existingLambdaLocal); - t.is(t.context.lambda.remote, existingLambdaRemote); - } -); - -test.serial( - `zipLambda: for lambda using message adapter, a new file is created - if the message adapter is updated`, - async (t) => { - t.context.lambda.useMessageAdapter = true; - const lambdaLocalOrigin = t.context.lambda.local; - const lambdaRemoteOrigin = t.context.lambda.remote; - - // put an empty lambda zip file there as the result of the previous run - const existingLambdaLocal = path.join( - path.dirname(t.context.lambda.local), - `${Lambda.messageAdapterZipFileHash}-${path.basename(t.context.lambda.local)}` - ); - - await fs.writeFile(existingLambdaLocal, 'hello'); - t.is(fs.statSync(existingLambdaLocal).size, 5); - - // message adapter is updated, a new lambda zip file is generated - const adapterHashOrigin = Lambda.messageAdapterZipFileHash; - Lambda.messageAdapterZipFileHash = `${adapterHashOrigin}123`; - - const testLambda = new Lambda(t.context.config); - await testLambda.zipLambda(testLambda.buildS3Path(t.context.lambda)); - t.truthy(fs.statSync(t.context.lambda.local)); - t.true(fs.statSync(t.context.lambda.local).size > 5); - t.not(t.context.lambda.local, existingLambdaLocal); - - t.is( - path.basename(t.context.lambda.local), - `${Lambda.messageAdapterZipFileHash}-${path.basename(lambdaLocalOrigin)}` - ); - t.is( - path.basename(t.context.lambda.remote), - `${Lambda.messageAdapterZipFileHash}-${path.basename(lambdaRemoteOrigin)}` - ); - } -); +test.serial('zipLambda: given an invalid zip file generated from a previous run, a new valid lambda file is generated', async (t) => { // eslint-disable-line max-len + t.context.lambda.useMessageAdapter = true; + const lambdaLocalOrigin = t.context.lambda.local; + const lambdaRemoteOrigin = t.context.lambda.remote; + + // put an empty lambda zip file there as the result of the previous run + const existingLambdaLocal = path.join( + path.dirname(t.context.lambda.local), + `${Lambda.messageAdapterZipFileHash}-${path.basename(t.context.lambda.local)}` + ); + + await fs.writeFile(existingLambdaLocal, 'hello'); + t.is(fs.statSync(existingLambdaLocal).size, 5); + + const testLambda = new Lambda(t.context.config); + await testLambda.zipLambda(testLambda.buildS3Path(t.context.lambda)); + t.truthy(fs.statSync(t.context.lambda.local)); + t.true(fs.statSync(t.context.lambda.local).size > 5); + t.is(t.context.lambda.local, existingLambdaLocal); + + t.is( + path.basename(t.context.lambda.local), + `${Lambda.messageAdapterZipFileHash}-${path.basename(lambdaLocalOrigin)}` + ); + t.is( + path.basename(t.context.lambda.remote), + `${Lambda.messageAdapterZipFileHash}-${path.basename(lambdaRemoteOrigin)}` + ); +}); + + +test.serial('zipLambda: for lambda using message adapter, no new file is generated if the task and message adapter are not updated', async (t) => { // eslint-disable-line max-len + t.context.lambda.useMessageAdapter = true; + + // put a lambda zip file there as the result of the previous run + const existingLambdaLocal = path.join( + path.dirname(t.context.lambda.local), + `${Lambda.messageAdapterZipFileHash}-${path.basename(t.context.lambda.local)}` + ); + + const existingLambdaRemote = path.join( + path.dirname(t.context.lambda.remote), + `${Lambda.messageAdapterZipFileHash}-${path.basename(t.context.lambda.remote)}` + ); + + await fs.copy(zipFixturePath, existingLambdaLocal); + t.is(fs.statSync(existingLambdaLocal).size, zipFixtureSize); + + const testLambda = new Lambda(t.context.config); + await testLambda.zipLambda(testLambda.buildS3Path(t.context.lambda)); + t.truthy(fs.statSync(t.context.lambda.local)); + t.is(fs.statSync(t.context.lambda.local).size, zipFixtureSize); + t.is(t.context.lambda.local, existingLambdaLocal); + t.is(t.context.lambda.remote, existingLambdaRemote); +}); + +test.serial('zipLambda: for lambda using message adapter, a new file is created if the message adapter is updated', async (t) => { // eslint-disable-line max-len + t.context.lambda.useMessageAdapter = true; + const lambdaLocalOrigin = t.context.lambda.local; + const lambdaRemoteOrigin = t.context.lambda.remote; + + // put an empty lambda zip file there as the result of the previous run + const existingLambdaLocal = path.join( + path.dirname(t.context.lambda.local), + `${Lambda.messageAdapterZipFileHash}-${path.basename(t.context.lambda.local)}` + ); + + await fs.writeFile(existingLambdaLocal, 'hello'); + t.is(fs.statSync(existingLambdaLocal).size, 5); + + // message adapter is updated, a new lambda zip file is generated + const adapterHashOrigin = Lambda.messageAdapterZipFileHash; + Lambda.messageAdapterZipFileHash = `${adapterHashOrigin}123`; + + const testLambda = new Lambda(t.context.config); + await testLambda.zipLambda(testLambda.buildS3Path(t.context.lambda)); + t.truthy(fs.statSync(t.context.lambda.local)); + t.true(fs.statSync(t.context.lambda.local).size > 5); + t.not(t.context.lambda.local, existingLambdaLocal); + + t.is( + path.basename(t.context.lambda.local), + `${Lambda.messageAdapterZipFileHash}-${path.basename(lambdaLocalOrigin)}` + ); + t.is( + path.basename(t.context.lambda.remote), + `${Lambda.messageAdapterZipFileHash}-${path.basename(lambdaRemoteOrigin)}` + ); +}); From bb3973b2f0490dd979bc40f0165de45e97b7fa3c Mon Sep 17 00:00:00 2001 From: Marc Date: Thu, 5 Jul 2018 09:53:45 -0400 Subject: [PATCH 10/10] Fix typo --- packages/deployment/lib/lambda.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/deployment/lib/lambda.js b/packages/deployment/lib/lambda.js index 3877bd1d07d..29f4f9a5960 100644 --- a/packages/deployment/lib/lambda.js +++ b/packages/deployment/lib/lambda.js @@ -49,7 +49,7 @@ class UpdatedLambda extends Lambda { return Promise.resolve(lambda); } catch (e) { - console.log(`${lambda.local} is valid and will be rebuilt`); + console.log(`${lambda.local} is invalid and will be rebuilt`); } }