From e38f22585f0bca4e29a6737f326866d94dd85ca5 Mon Sep 17 00:00:00 2001 From: "Eslam A. Hefnawy" Date: Thu, 9 Mar 2017 23:01:45 +0800 Subject: [PATCH] seperated packaging and deployment --- lib/classes/Service.js | 1 + lib/plugins/Plugins.json | 23 +++--- lib/plugins/aws/deploy/index.js | 47 ++++++------ lib/plugins/aws/deploy/lib/cleanupS3Bucket.js | 4 - lib/plugins/aws/deploy/lib/createStack.js | 30 +------- .../aws/deploy/lib/extendedValidate.js | 75 +++++++++++++++++++ lib/plugins/aws/deploy/lib/runPackage.js | 18 +++++ lib/plugins/aws/deploy/lib/uploadArtifacts.js | 41 ++++++---- lib/plugins/aws/deployFunction/index.js | 13 +++- lib/plugins/aws/lib/monitorStack.js | 2 - lib/plugins/aws/lib/naming.js | 16 ++++ lib/plugins/aws/lib/setBucketName.js | 4 - lib/plugins/aws/lib/updateStack.js | 33 ++------ .../compile/events/alexaSkill/index.js | 2 +- .../compile/events/alexaSkill/index.test.js | 0 .../compile/events/apiGateway/index.js | 2 +- .../compile/events/apiGateway/index.test.js | 0 .../compile/events/apiGateway/lib/apiKeys.js | 0 .../events/apiGateway/lib/apiKeys.test.js | 0 .../events/apiGateway/lib/authorizers.js | 0 .../events/apiGateway/lib/authorizers.test.js | 0 .../compile/events/apiGateway/lib/cors.js | 0 .../events/apiGateway/lib/cors.test.js | 0 .../events/apiGateway/lib/deployment.js | 0 .../events/apiGateway/lib/deployment.test.js | 0 .../apiGateway/lib/method/authorization.js | 0 .../events/apiGateway/lib/method/index.js | 0 .../apiGateway/lib/method/index.test.js | 0 .../apiGateway/lib/method/integration.js | 0 .../events/apiGateway/lib/method/responses.js | 0 .../events/apiGateway/lib/permissions.js | 0 .../events/apiGateway/lib/permissions.test.js | 0 .../events/apiGateway/lib/resources.js | 0 .../events/apiGateway/lib/resources.test.js | 0 .../compile/events/apiGateway/lib/restApi.js | 0 .../events/apiGateway/lib/restApi.test.js | 0 .../compile/events/apiGateway/lib/validate.js | 0 .../events/apiGateway/lib/validate.test.js | 0 .../compile/events/cloudWatchEvent/index.js | 2 +- .../events/cloudWatchEvent/index.test.js | 0 .../compile/events/iot/index.js | 2 +- .../compile/events/iot/index.test.js | 0 .../compile/events/s3/index.js | 2 +- .../compile/events/s3/index.test.js | 0 .../compile/events/schedule/index.js | 2 +- .../compile/events/schedule/index.test.js | 0 .../compile/events/sns/index.js | 2 +- .../compile/events/sns/index.test.js | 0 .../compile/events/stream/index.js | 2 +- .../compile/events/stream/index.test.js | 0 .../compile/functions/index.js | 15 +++- .../compile/functions/index.test.js | 0 lib/plugins/aws/package/index.js | 57 ++++++++++++++ lib/plugins/{ => aws}/package/lib/cleanup.js | 0 .../{ => aws}/package/lib/cleanup.test.js | 0 .../lib/core-cloudformation-template.json | 0 .../lib/generateArtifactDirectoryName.js | 0 .../lib/generateArtifactDirectoryName.test.js | 0 .../package/lib/generateCompiledTemplate.js | 18 +++++ .../lib/generateCoreTemplate.js} | 15 +++- .../lib/generateCoreTemplate.test.js} | 2 +- .../iam-role-lambda-execution-template.json | 0 .../lib/mergeCustomProviderResources.js | 0 .../lib/mergeCustomProviderResources.test.js | 0 .../lib/mergeIamTemplates.js | 2 +- .../lib/mergeIamTemplates.test.js | 0 .../{ => aws}/package/lib/packageService.js | 44 +++-------- .../package/lib/packageService.test.js | 0 .../{ => aws}/package/lib/zipService.js | 10 +-- .../{ => aws}/package/lib/zipService.test.js | 0 lib/plugins/deploy/deploy.js | 12 +-- lib/plugins/package/index.js | 33 -------- lib/plugins/package/lib/validate.js | 14 ---- lib/plugins/package/lib/validate.test.js | 25 ------- lib/plugins/package/package.js | 39 ++++++++++ .../{index.test.js => package.test.js} | 3 +- 76 files changed, 361 insertions(+), 251 deletions(-) create mode 100644 lib/plugins/aws/deploy/lib/extendedValidate.js create mode 100644 lib/plugins/aws/deploy/lib/runPackage.js rename lib/plugins/aws/{deploy => package}/compile/events/alexaSkill/index.js (96%) rename lib/plugins/aws/{deploy => package}/compile/events/alexaSkill/index.test.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/index.js (97%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/index.test.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/lib/apiKeys.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/lib/apiKeys.test.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/lib/authorizers.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/lib/authorizers.test.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/lib/cors.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/lib/cors.test.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/lib/deployment.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/lib/deployment.test.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/lib/method/authorization.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/lib/method/index.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/lib/method/index.test.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/lib/method/integration.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/lib/method/responses.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/lib/permissions.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/lib/permissions.test.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/lib/resources.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/lib/resources.test.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/lib/restApi.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/lib/restApi.test.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/lib/validate.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/apiGateway/lib/validate.test.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/cloudWatchEvent/index.js (98%) rename lib/plugins/aws/{deploy => package}/compile/events/cloudWatchEvent/index.test.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/iot/index.js (98%) rename lib/plugins/aws/{deploy => package}/compile/events/iot/index.test.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/s3/index.js (99%) rename lib/plugins/aws/{deploy => package}/compile/events/s3/index.test.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/schedule/index.js (98%) rename lib/plugins/aws/{deploy => package}/compile/events/schedule/index.test.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/sns/index.js (98%) rename lib/plugins/aws/{deploy => package}/compile/events/sns/index.test.js (100%) rename lib/plugins/aws/{deploy => package}/compile/events/stream/index.js (99%) rename lib/plugins/aws/{deploy => package}/compile/events/stream/index.test.js (100%) rename lib/plugins/aws/{deploy => package}/compile/functions/index.js (93%) rename lib/plugins/aws/{deploy => package}/compile/functions/index.test.js (100%) create mode 100644 lib/plugins/aws/package/index.js rename lib/plugins/{ => aws}/package/lib/cleanup.js (100%) rename lib/plugins/{ => aws}/package/lib/cleanup.test.js (100%) rename lib/plugins/aws/{deploy => package}/lib/core-cloudformation-template.json (100%) rename lib/plugins/aws/{deploy => package}/lib/generateArtifactDirectoryName.js (100%) rename lib/plugins/aws/{deploy => package}/lib/generateArtifactDirectoryName.test.js (100%) create mode 100644 lib/plugins/aws/package/lib/generateCompiledTemplate.js rename lib/plugins/aws/{deploy/lib/configureStack.js => package/lib/generateCoreTemplate.js} (79%) rename lib/plugins/aws/{deploy/lib/configureStack.test.js => package/lib/generateCoreTemplate.test.js} (98%) rename lib/plugins/aws/{deploy => package}/lib/iam-role-lambda-execution-template.json (100%) rename lib/plugins/aws/{deploy => package}/lib/mergeCustomProviderResources.js (100%) rename lib/plugins/aws/{deploy => package}/lib/mergeCustomProviderResources.test.js (100%) rename lib/plugins/aws/{deploy => package}/lib/mergeIamTemplates.js (99%) rename lib/plugins/aws/{deploy => package}/lib/mergeIamTemplates.test.js (100%) rename lib/plugins/{ => aws}/package/lib/packageService.js (63%) rename lib/plugins/{ => aws}/package/lib/packageService.test.js (100%) rename lib/plugins/{ => aws}/package/lib/zipService.js (88%) rename lib/plugins/{ => aws}/package/lib/zipService.test.js (100%) delete mode 100644 lib/plugins/package/index.js delete mode 100644 lib/plugins/package/lib/validate.js delete mode 100644 lib/plugins/package/lib/validate.test.js create mode 100644 lib/plugins/package/package.js rename lib/plugins/package/{index.test.js => package.test.js} (94%) diff --git a/lib/classes/Service.js b/lib/classes/Service.js index d835733f3..5a487232c 100644 --- a/lib/classes/Service.js +++ b/lib/classes/Service.js @@ -103,6 +103,7 @@ class Service { if (serverlessFile.package) { that.package.individually = serverlessFile.package.individually; + that.package.path = serverlessFile.package.path; that.package.artifact = serverlessFile.package.artifact; that.package.exclude = serverlessFile.package.exclude; that.package.include = serverlessFile.package.include; diff --git a/lib/plugins/Plugins.json b/lib/plugins/Plugins.json index 32229ad35..4a7e3c007 100644 --- a/lib/plugins/Plugins.json +++ b/lib/plugins/Plugins.json @@ -3,7 +3,7 @@ "./config/config.js", "./create/create.js", "./install/install.js", - "./package/index.js", + "./package/package.js", "./deploy/deploy.js", "./invoke/invoke.js", "./info/info.js", @@ -15,22 +15,23 @@ "./aws/configCredentials/awsConfigCredentials.js", "./aws/provider/awsProvider.js", "./aws/deploy/index.js", + "./aws/package/index.js", "./aws/invoke/index.js", "./aws/info/index.js", "./aws/logs/index.js", "./aws/metrics/awsMetrics.js", "./aws/remove/index.js", "./aws/rollback/index.js", - "./aws/deploy/compile/functions/index.js", - "./aws/deploy/compile/events/schedule/index.js", - "./aws/deploy/compile/events/s3/index.js", - "./aws/deploy/compile/events/apiGateway/index.js", - "./aws/deploy/compile/events/sns/index.js", - "./aws/deploy/compile/events/stream/index.js", - "./aws/deploy/compile/events/alexaSkill/index.js", - "./aws/deploy/compile/events/iot/index.js", - "./aws/deploy/compile/events/cloudWatchEvent/index.js", - "./aws/deploy/compile/events/cloudWatchLog/index.js", + "./aws/package/compile/functions/index.js", + "./aws/package/compile/events/schedule/index.js", + "./aws/package/compile/events/s3/index.js", + "./aws/package/compile/events/apiGateway/index.js", + "./aws/package/compile/events/sns/index.js", + "./aws/package/compile/events/stream/index.js", + "./aws/package/compile/events/alexaSkill/index.js", + "./aws/package/compile/events/iot/index.js", + "./aws/package/compile/events/cloudWatchEvent/index.js", + "./aws/package/compile/events/cloudWatchLog/index.js", "./aws/deployFunction/index.js", "./aws/deployList/index.js", "./aws/invokeLocal/index.js" diff --git a/lib/plugins/aws/deploy/index.js b/lib/plugins/aws/deploy/index.js index f8d50bba7..6506437c6 100644 --- a/lib/plugins/aws/deploy/index.js +++ b/lib/plugins/aws/deploy/index.js @@ -1,17 +1,23 @@ 'use strict'; +/* + * serverless package => package in default .serverless dir + * serverless package --package => package in custom path + * + * serverless deploy => package in default .serverless & deploy from default .serverless + * serverless deploy --package => deploy from custom path + */ + const BbPromise = require('bluebird'); const validate = require('../lib/validate'); +const runPackage = require('./lib/runPackage'); +const extendedValidate = require('./lib/extendedValidate'); const monitorStack = require('../lib/monitorStack'); const createStack = require('./lib/createStack'); -const mergeCustomProviderResources = require('./lib/mergeCustomProviderResources'); -const generateArtifactDirectoryName = require('./lib/generateArtifactDirectoryName'); const setBucketName = require('../lib/setBucketName'); const cleanupS3Bucket = require('./lib/cleanupS3Bucket'); const uploadArtifacts = require('./lib/uploadArtifacts'); const updateStack = require('../lib/updateStack'); -const configureStack = require('./lib/configureStack'); -const mergeIamTemplates = require('./lib/mergeIamTemplates'); class AwsDeploy { constructor(serverless, options) { @@ -22,41 +28,30 @@ class AwsDeploy { Object.assign( this, validate, + runPackage, + extendedValidate, createStack, - generateArtifactDirectoryName, - mergeCustomProviderResources, setBucketName, cleanupS3Bucket, uploadArtifacts, updateStack, - monitorStack, - configureStack, - mergeIamTemplates + monitorStack ); this.hooks = { - 'before:deploy:initialize': () => BbPromise.bind(this) - .then(this.validate), - 'deploy:initialize': () => BbPromise.bind(this) - .then(this.configureStack), - - 'deploy:setupProviderConfiguration': () => BbPromise.bind(this) - .then(this.createStack) - .then(this.mergeIamTemplates), - - 'before:deploy:compileFunctions': () => BbPromise.bind(this) - .then(this.generateArtifactDirectoryName), + .then(this.validate) + .then(this.runPackage) + .then(this.extendedValidate), 'deploy:deploy': () => BbPromise.bind(this) - .then(this.mergeCustomProviderResources) + .then(this.createStack) .then(this.setBucketName) .then(this.uploadArtifacts) - .then(this.updateStack) - .then(this.cleanupS3Bucket) - .then(() => { - if (this.options.noDeploy) this.serverless.cli.log('Did not deploy due to --noDeploy'); - }), + .then(this.updateStack), + + 'deploy:finalize': () => BbPromise.bind(this) + .then(this.cleanupS3Bucket), }; } } diff --git a/lib/plugins/aws/deploy/lib/cleanupS3Bucket.js b/lib/plugins/aws/deploy/lib/cleanupS3Bucket.js index 55789cd8b..daebbc879 100644 --- a/lib/plugins/aws/deploy/lib/cleanupS3Bucket.js +++ b/lib/plugins/aws/deploy/lib/cleanupS3Bucket.js @@ -51,10 +51,6 @@ module.exports = { }, cleanupS3Bucket() { - if (this.options.noDeploy) { - return BbPromise.resolve(); - } - return BbPromise.bind(this) .then(this.getObjectsToRemove) .then(this.removeObjects); diff --git a/lib/plugins/aws/deploy/lib/createStack.js b/lib/plugins/aws/deploy/lib/createStack.js index 6409d2a19..b6f9bbca0 100644 --- a/lib/plugins/aws/deploy/lib/createStack.js +++ b/lib/plugins/aws/deploy/lib/createStack.js @@ -1,7 +1,6 @@ 'use strict'; const _ = require('lodash'); -const path = require('path'); const BbPromise = require('bluebird'); module.exports = { @@ -9,6 +8,7 @@ module.exports = { // Note: using three dots instead of ellipsis to support non uni-code consoles. this.serverless.cli.log('Creating Stack...'); const stackName = this.provider.naming.getStackName(); + let stackTags = { STAGE: this.options.stage }; // Merge additional stack tags @@ -24,8 +24,7 @@ module.exports = { 'CAPABILITY_NAMED_IAM', ], Parameters: [], - TemplateBody: JSON.stringify(this.serverless.service.provider - .compiledCloudFormationTemplate), + TemplateBody: JSON.stringify(this.coreTemplateFileBody), Tags: Object.keys(stackTags).map((key) => ({ Key: key, Value: stackTags[key] })), }; @@ -56,19 +55,12 @@ module.exports = { } return BbPromise.bind(this) - // always write the template to disk, whether we are deploying or not - .then(this.writeCreateTemplateToDisk) - .then(() => { - if (this.options.noDeploy) { - return BbPromise.resolve(); - } - return this.provider.request('CloudFormation', + .then(() => this.provider.request('CloudFormation', 'describeStackResources', { StackName: stackName }, this.options.stage, this.options.region) - .then(() => BbPromise.resolve('alreadyCreated')); - }) + .then(() => BbPromise.resolve('alreadyCreated'))) .catch((e) => { if (e.message.indexOf('does not exist') > -1) { if (this.serverless.service.provider.deploymentBucket) { @@ -82,18 +74,4 @@ module.exports = { throw new this.serverless.classes.Error(e); }); }, - - // helper methods - writeCreateTemplateToDisk() { - if (this.serverless.service.provider.deploymentBucket) { - return BbPromise.resolve(); - } - const cfTemplateFilePath = path.join(this.serverless.config.servicePath, - '.serverless', 'cloudformation-template-create-stack.json'); - - this.serverless.utils.writeFileSync(cfTemplateFilePath, - this.serverless.service.provider.compiledCloudFormationTemplate); - - return BbPromise.resolve(); - }, }; diff --git a/lib/plugins/aws/deploy/lib/extendedValidate.js b/lib/plugins/aws/deploy/lib/extendedValidate.js new file mode 100644 index 000000000..39ee9a1d8 --- /dev/null +++ b/lib/plugins/aws/deploy/lib/extendedValidate.js @@ -0,0 +1,75 @@ +'use strict'; + +const path = require('path'); +const BbPromise = require('bluebird'); +const _ = require('lodash'); + +module.exports = { + getArtifactS3Key() { + const getArtifactS3KeysArray = function (obj, key) { + if (_.has(obj, key)) { + return obj[key]; + } + + return _.flatten(_ + .map(obj, (v) => typeof v === 'object' ? getArtifactS3KeysArray(v, key) : false), true); + }; + + return getArtifactS3KeysArray(this.compiledTemplateFileBody, 'S3Key') + .find(item => item !== false); + }, + + extendedValidate() { + this.packagePath = this.options.package || + this.serverless.service.package.path || + path.join(this.serverless.config.servicePath, '.serverless'); + + if (this.serverless.service.package.individually) { + // artifact file validation (multiple function artifacts) + this.serverless.service.getAllFunctions().forEach(functionName => { + const artifactFileName = this.provider.naming.getFunctionArtifactName(functionName); + const artifactFilePath = path.join(this.packagePath, artifactFileName); + if (!this.serverless.utils.fileExistsSync(artifactFilePath)) { + throw new this.serverless.classes + .Error(`No ${artifactFileName} file found in the package path you provided.`); + } + }); + } else { + // artifact file validation (single service artifact) + const artifactFileName = this.provider.naming.getServiceArtifactName(); + const artifactFilePath = path.join(this.packagePath, artifactFileName); + if (!this.serverless.utils.fileExistsSync(artifactFilePath)) { + throw new this.serverless.classes + .Error(`No ${artifactFileName} file found in the package path you provided.`); + } + } + + // compiled template file validation + const compiledTemplateFileName = this.provider.naming.getCompiledTemplateFileName(); + this.compiledTemplateFilePath = path.join(this.packagePath, compiledTemplateFileName); + if (!this.serverless.utils.fileExistsSync(this.compiledTemplateFilePath)) { + throw new this.serverless.classes + .Error(`No ${compiledTemplateFileName} file found in the package path you provided.`); + } + this.compiledTemplateFileBody = this.serverless + .utils.readFileSync(this.compiledTemplateFilePath); + + if (!this.serverless.service.deploymentBucket) { + // core template file validation + const coreTemplateFileName = this.provider.naming.getCoreTemplateFileName(); + this.coreTemplateFilePath = path.join(this.packagePath, coreTemplateFileName); + if (!this.serverless.utils.fileExistsSync(this.coreTemplateFilePath)) { + throw new this.serverless.classes + .Error(`No ${coreTemplateFileName} file found in the package path you provided.`); + } + this.coreTemplateFileBody = this.serverless + .utils.readFileSync(this.coreTemplateFilePath); + } + + this.packageS3DirKey = this.getArtifactS3Key().split(path.sep); + this.packageS3DirKey.pop(); + this.packageS3DirKey = this.packageS3DirKey.join(path.sep); + + return BbPromise.resolve(); + }, +}; diff --git a/lib/plugins/aws/deploy/lib/runPackage.js b/lib/plugins/aws/deploy/lib/runPackage.js new file mode 100644 index 000000000..0edf6ae64 --- /dev/null +++ b/lib/plugins/aws/deploy/lib/runPackage.js @@ -0,0 +1,18 @@ +'use strict'; + +const path = require('path'); +const BbPromise = require('bluebird'); +const execSync = require('child_process').execSync; + +module.exports = { + runPackage() { + const serverlessExec = path.join(this.serverless.config + .serverlessPath, '..', 'bin', 'serverless'); + + if (!this.options.package) { + execSync(`${serverlessExec} package`, { stdio: 'inherit' }); + } + + return BbPromise.resolve(); + }, +}; diff --git a/lib/plugins/aws/deploy/lib/uploadArtifacts.js b/lib/plugins/aws/deploy/lib/uploadArtifacts.js index 3c9bb3d3b..70b531b45 100644 --- a/lib/plugins/aws/deploy/lib/uploadArtifacts.js +++ b/lib/plugins/aws/deploy/lib/uploadArtifacts.js @@ -1,21 +1,21 @@ 'use strict'; const fs = require('fs'); -const path = require('path'); const BbPromise = require('bluebird'); const filesize = require('filesize'); +const path = require('path'); module.exports = { uploadCloudFormationFile() { this.serverless.cli.log('Uploading CloudFormation file to S3...'); - const body = JSON.stringify(this.serverless.service.provider.compiledCloudFormationTemplate); + const compiledTemplateFileName = this.provider.naming.getCompiledTemplateFileName(); - const fileName = 'compiled-cloudformation-template.json'; + const body = JSON.stringify(this.compiledTemplateFileBody); const params = { Bucket: this.bucketName, - Key: `${this.serverless.service.package.artifactDirectoryName}/${fileName}`, + Key: `${this.packageS3DirKey}/${compiledTemplateFileName}`, Body: body, ContentType: 'application/json', }; @@ -27,17 +27,17 @@ module.exports = { this.options.region); }, - uploadZipFile(artifactFilePath) { - if (!artifactFilePath) { - throw new this.serverless.classes.Error('artifactFilePath was not supplied'); + uploadZipFile(functionName) { + let fileName = this.provider.naming.getServiceArtifactName(); + + if (functionName) { + fileName = this.provider.naming.getFunctionArtifactName(functionName); } - - - const fileName = artifactFilePath.split(path.sep).pop(); + const artifactFilePath = path.join(this.packagePath, fileName); const params = { Bucket: this.bucketName, - Key: `${this.serverless.service.package.artifactDirectoryName}/${fileName}`, + Key: `${this.packageS3DirKey}/${fileName}`, Body: fs.createReadStream(artifactFilePath), ContentType: 'application/zip', }; @@ -72,13 +72,24 @@ module.exports = { } return BbPromise.resolve(); }); + if (this.serverless.service.package.individually) { + this.serverless.cli.log('Uploading function .zip files to S3...'); + + const functionNames = this.serverless.service.getAllFunctions(); + const uploadPromises = functionNames.map(name => this.uploadZipFile(name)); + + return BbPromise.all(uploadPromises); + } + + const fileName = this.provider.naming.getServiceArtifactName(); + const artifactFilePath = path.join(this.packagePath, fileName); + + const stats = fs.statSync(artifactFilePath); + this.serverless.cli.log(`Uploading service .zip file to S3 (${filesize(stats.size)})...`); + return this.uploadZipFile(); }, uploadArtifacts() { - if (this.options.noDeploy) { - return BbPromise.resolve(); - } - return BbPromise.bind(this) .then(this.uploadCloudFormationFile) .then(this.uploadFunctions); diff --git a/lib/plugins/aws/deployFunction/index.js b/lib/plugins/aws/deployFunction/index.js index c01bee123..8c88342a8 100644 --- a/lib/plugins/aws/deployFunction/index.js +++ b/lib/plugins/aws/deployFunction/index.js @@ -1,17 +1,21 @@ 'use strict'; const BbPromise = require('bluebird'); +const path = require('path'); const fs = require('fs'); const validate = require('../lib/validate'); const filesize = require('filesize'); // The Package plugin which is used to zip the service -const Package = require('../../package'); +const Package = require('../package'); class AwsDeployFunction { constructor(serverless, options) { this.serverless = serverless; this.options = options || {}; + this.packagePath = this.options.package || + this.serverless.service.package.path || + path.join(this.serverless.config.servicePath, '.serverless'); this.provider = this.serverless.getProvider('aws'); this.pkg = new Package(this.serverless, this.options); @@ -72,7 +76,10 @@ class AwsDeployFunction { } deployFunction() { - const data = fs.readFileSync(this.options.functionObj.artifact); + const artifactFileName = this.provider.naming + .getFunctionArtifactName(this.options.function); + const artifactFilePath = path.join(this.packagePath, artifactFileName); + const data = fs.readFileSync(artifactFilePath); const params = { FunctionName: this.options.functionObj.name, @@ -80,7 +87,7 @@ class AwsDeployFunction { }; // Get function stats - const stats = fs.statSync(this.options.functionObj.artifact); + const stats = fs.statSync(artifactFilePath); this.serverless.cli.log( `Uploading function: ${this.options.function} (${filesize(stats.size)})...` ); diff --git a/lib/plugins/aws/lib/monitorStack.js b/lib/plugins/aws/lib/monitorStack.js index 9721559c9..26c06132b 100644 --- a/lib/plugins/aws/lib/monitorStack.js +++ b/lib/plugins/aws/lib/monitorStack.js @@ -6,8 +6,6 @@ const chalk = require('chalk'); module.exports = { monitorStack(action, cfData, frequency) { - // Skip monitoring if a deployment should not be performed - if (this.options.noDeploy) return BbPromise.bind(this).then(BbPromise.resolve()); // Skip monitoring if stack was already created if (cfData === 'alreadyCreated') return BbPromise.bind(this).then(BbPromise.resolve()); diff --git a/lib/plugins/aws/lib/naming.js b/lib/plugins/aws/lib/naming.js index 1bd18d7da..aa792f782 100644 --- a/lib/plugins/aws/lib/naming.js +++ b/lib/plugins/aws/lib/naming.js @@ -49,6 +49,22 @@ module.exports = { return `${this.provider.serverless.service.service}-${this.provider.getStage()}`; }, + getServiceArtifactName() { + return `${this.provider.serverless.service.service}.zip`; + }, + + getFunctionArtifactName(functionName) { + return `${functionName}.zip`; + }, + + getCompiledTemplateFileName() { + return 'cf-compiled-template.json'; + }, + + getCoreTemplateFileName() { + return 'cf-core-template.json'; + }, + // Role getRolePath() { return '/'; diff --git a/lib/plugins/aws/lib/setBucketName.js b/lib/plugins/aws/lib/setBucketName.js index 8765ac656..47810cdd3 100644 --- a/lib/plugins/aws/lib/setBucketName.js +++ b/lib/plugins/aws/lib/setBucketName.js @@ -8,10 +8,6 @@ module.exports = { return BbPromise.resolve(this.bucketName); } - if (this.options.noDeploy) { - return BbPromise.resolve(); - } - return this.provider.getServerlessDeploymentBucketName(this.options.stage, this.options.region) .then((bucketName) => { this.bucketName = bucketName; diff --git a/lib/plugins/aws/lib/updateStack.js b/lib/plugins/aws/lib/updateStack.js index bae4285dc..c78bb2a12 100644 --- a/lib/plugins/aws/lib/updateStack.js +++ b/lib/plugins/aws/lib/updateStack.js @@ -13,11 +13,9 @@ module.exports = { const stackName = this.provider.naming.getStackName(); let stackTags = { STAGE: this.options.stage }; - const templateUrl = `https://s3.amazonaws.com/${ - this.bucketName - }/${ - this.serverless.service.package.artifactDirectoryName - }/compiled-cloudformation-template.json`; + const compiledTemplateFileName = this.provider.naming.getCompiledTemplateFileName(); + const templateUrl = `https://s3.amazonaws.com/${this.bucketName}/${this.packageS3DirKey}/${compiledTemplateFileName}`; + // Merge additional stack tags if (typeof this.serverless.service.provider.stackTags === 'object') { stackTags = _.extend(stackTags, this.serverless.service.provider.stackTags); @@ -44,11 +42,8 @@ module.exports = { }, update() { - const templateUrl = `https://s3.amazonaws.com/${ - this.bucketName - }/${ - this.serverless.service.package.artifactDirectoryName - }/compiled-cloudformation-template.json`; + const compiledTemplateFileName = this.provider.naming.getCompiledTemplateFileName(); + const templateUrl = `https://s3.amazonaws.com/${this.bucketName}/${this.packageS3DirKey}/${compiledTemplateFileName}`; this.serverless.cli.log('Updating Stack...'); const stackName = this.provider.naming.getStackName(); @@ -97,13 +92,9 @@ module.exports = { }, updateStack() { - // just write the template to disk if a deployment should not be performed return BbPromise.bind(this) - .then(this.writeUpdateTemplateToDisk) .then(() => { - if (this.options.noDeploy) { - return BbPromise.resolve(); - } else if (this.createLater) { + if (this.createLater) { return BbPromise.bind(this) .then(this.createFallback); } @@ -111,16 +102,4 @@ module.exports = { .then(this.update); }); }, - - // helper methods - writeUpdateTemplateToDisk() { - const updateOrCreate = this.createLater ? 'create' : 'update'; - const cfTemplateFilePath = path.join(this.serverless.config.servicePath, - '.serverless', `cloudformation-template-${updateOrCreate}-stack.json`); - - this.serverless.utils.writeFileSync(cfTemplateFilePath, - this.serverless.service.provider.compiledCloudFormationTemplate); - - return BbPromise.resolve(); - }, }; diff --git a/lib/plugins/aws/deploy/compile/events/alexaSkill/index.js b/lib/plugins/aws/package/compile/events/alexaSkill/index.js similarity index 96% rename from lib/plugins/aws/deploy/compile/events/alexaSkill/index.js rename to lib/plugins/aws/package/compile/events/alexaSkill/index.js index b836c7c88..ecc32cb44 100644 --- a/lib/plugins/aws/deploy/compile/events/alexaSkill/index.js +++ b/lib/plugins/aws/package/compile/events/alexaSkill/index.js @@ -8,7 +8,7 @@ class AwsCompileAlexaSkillEvents { this.provider = this.serverless.getProvider('aws'); this.hooks = { - 'deploy:compileEvents': this.compileAlexaSkillEvents.bind(this), + 'package:compileEvents': this.compileAlexaSkillEvents.bind(this), }; } diff --git a/lib/plugins/aws/deploy/compile/events/alexaSkill/index.test.js b/lib/plugins/aws/package/compile/events/alexaSkill/index.test.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/alexaSkill/index.test.js rename to lib/plugins/aws/package/compile/events/alexaSkill/index.test.js diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/index.js b/lib/plugins/aws/package/compile/events/apiGateway/index.js similarity index 97% rename from lib/plugins/aws/deploy/compile/events/apiGateway/index.js rename to lib/plugins/aws/package/compile/events/apiGateway/index.js index a8c5bcdad..6e8a1b9ec 100644 --- a/lib/plugins/aws/deploy/compile/events/apiGateway/index.js +++ b/lib/plugins/aws/package/compile/events/apiGateway/index.js @@ -38,7 +38,7 @@ class AwsCompileApigEvents { ); this.hooks = { - 'deploy:compileEvents': () => { + 'package:compileEvents': () => { this.validated = this.validate(); if (this.validated.events.length === 0) { diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/index.test.js b/lib/plugins/aws/package/compile/events/apiGateway/index.test.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/apiGateway/index.test.js rename to lib/plugins/aws/package/compile/events/apiGateway/index.test.js diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/apiKeys.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/apiKeys.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/apiGateway/lib/apiKeys.js rename to lib/plugins/aws/package/compile/events/apiGateway/lib/apiKeys.js diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/apiKeys.test.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/apiKeys.test.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/apiGateway/lib/apiKeys.test.js rename to lib/plugins/aws/package/compile/events/apiGateway/lib/apiKeys.test.js diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/authorizers.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/authorizers.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/apiGateway/lib/authorizers.js rename to lib/plugins/aws/package/compile/events/apiGateway/lib/authorizers.js diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/authorizers.test.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/authorizers.test.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/apiGateway/lib/authorizers.test.js rename to lib/plugins/aws/package/compile/events/apiGateway/lib/authorizers.test.js diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/cors.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/cors.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/apiGateway/lib/cors.js rename to lib/plugins/aws/package/compile/events/apiGateway/lib/cors.js diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/cors.test.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/cors.test.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/apiGateway/lib/cors.test.js rename to lib/plugins/aws/package/compile/events/apiGateway/lib/cors.test.js diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/deployment.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/deployment.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/apiGateway/lib/deployment.js rename to lib/plugins/aws/package/compile/events/apiGateway/lib/deployment.js diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/deployment.test.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/deployment.test.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/apiGateway/lib/deployment.test.js rename to lib/plugins/aws/package/compile/events/apiGateway/lib/deployment.test.js diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/method/authorization.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/method/authorization.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/apiGateway/lib/method/authorization.js rename to lib/plugins/aws/package/compile/events/apiGateway/lib/method/authorization.js diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/method/index.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/method/index.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/apiGateway/lib/method/index.js rename to lib/plugins/aws/package/compile/events/apiGateway/lib/method/index.js diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/method/index.test.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/method/index.test.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/apiGateway/lib/method/index.test.js rename to lib/plugins/aws/package/compile/events/apiGateway/lib/method/index.test.js diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/method/integration.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/method/integration.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/apiGateway/lib/method/integration.js rename to lib/plugins/aws/package/compile/events/apiGateway/lib/method/integration.js diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/method/responses.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/method/responses.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/apiGateway/lib/method/responses.js rename to lib/plugins/aws/package/compile/events/apiGateway/lib/method/responses.js diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/permissions.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/permissions.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/apiGateway/lib/permissions.js rename to lib/plugins/aws/package/compile/events/apiGateway/lib/permissions.js diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/permissions.test.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/permissions.test.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/apiGateway/lib/permissions.test.js rename to lib/plugins/aws/package/compile/events/apiGateway/lib/permissions.test.js diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/resources.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/resources.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/apiGateway/lib/resources.js rename to lib/plugins/aws/package/compile/events/apiGateway/lib/resources.js diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/resources.test.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/resources.test.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/apiGateway/lib/resources.test.js rename to lib/plugins/aws/package/compile/events/apiGateway/lib/resources.test.js diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/restApi.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/restApi.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/apiGateway/lib/restApi.js rename to lib/plugins/aws/package/compile/events/apiGateway/lib/restApi.js diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/restApi.test.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/restApi.test.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/apiGateway/lib/restApi.test.js rename to lib/plugins/aws/package/compile/events/apiGateway/lib/restApi.test.js diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/validate.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/validate.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/apiGateway/lib/validate.js rename to lib/plugins/aws/package/compile/events/apiGateway/lib/validate.js diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/validate.test.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/validate.test.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/apiGateway/lib/validate.test.js rename to lib/plugins/aws/package/compile/events/apiGateway/lib/validate.test.js diff --git a/lib/plugins/aws/deploy/compile/events/cloudWatchEvent/index.js b/lib/plugins/aws/package/compile/events/cloudWatchEvent/index.js similarity index 98% rename from lib/plugins/aws/deploy/compile/events/cloudWatchEvent/index.js rename to lib/plugins/aws/package/compile/events/cloudWatchEvent/index.js index 0009ccacc..c816a81c5 100644 --- a/lib/plugins/aws/deploy/compile/events/cloudWatchEvent/index.js +++ b/lib/plugins/aws/package/compile/events/cloudWatchEvent/index.js @@ -8,7 +8,7 @@ class AwsCompileCloudWatchEventEvents { this.provider = this.serverless.getProvider('aws'); this.hooks = { - 'deploy:compileEvents': this.compileCloudWatchEventEvents.bind(this), + 'package:compileEvents': this.compileCloudWatchEventEvents.bind(this), }; } diff --git a/lib/plugins/aws/deploy/compile/events/cloudWatchEvent/index.test.js b/lib/plugins/aws/package/compile/events/cloudWatchEvent/index.test.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/cloudWatchEvent/index.test.js rename to lib/plugins/aws/package/compile/events/cloudWatchEvent/index.test.js diff --git a/lib/plugins/aws/deploy/compile/events/iot/index.js b/lib/plugins/aws/package/compile/events/iot/index.js similarity index 98% rename from lib/plugins/aws/deploy/compile/events/iot/index.js rename to lib/plugins/aws/package/compile/events/iot/index.js index 2c56cedd0..64633ebc7 100644 --- a/lib/plugins/aws/deploy/compile/events/iot/index.js +++ b/lib/plugins/aws/package/compile/events/iot/index.js @@ -8,7 +8,7 @@ class AwsCompileIoTEvents { this.provider = this.serverless.getProvider('aws'); this.hooks = { - 'deploy:compileEvents': this.compileIoTEvents.bind(this), + 'package:compileEvents': this.compileIoTEvents.bind(this), }; } diff --git a/lib/plugins/aws/deploy/compile/events/iot/index.test.js b/lib/plugins/aws/package/compile/events/iot/index.test.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/iot/index.test.js rename to lib/plugins/aws/package/compile/events/iot/index.test.js diff --git a/lib/plugins/aws/deploy/compile/events/s3/index.js b/lib/plugins/aws/package/compile/events/s3/index.js similarity index 99% rename from lib/plugins/aws/deploy/compile/events/s3/index.js rename to lib/plugins/aws/package/compile/events/s3/index.js index 0db67be13..6ad7b7c36 100644 --- a/lib/plugins/aws/deploy/compile/events/s3/index.js +++ b/lib/plugins/aws/package/compile/events/s3/index.js @@ -8,7 +8,7 @@ class AwsCompileS3Events { this.provider = this.serverless.getProvider('aws'); this.hooks = { - 'deploy:compileEvents': this.compileS3Events.bind(this), + 'package:compileEvents': this.compileS3Events.bind(this), }; } diff --git a/lib/plugins/aws/deploy/compile/events/s3/index.test.js b/lib/plugins/aws/package/compile/events/s3/index.test.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/s3/index.test.js rename to lib/plugins/aws/package/compile/events/s3/index.test.js diff --git a/lib/plugins/aws/deploy/compile/events/schedule/index.js b/lib/plugins/aws/package/compile/events/schedule/index.js similarity index 98% rename from lib/plugins/aws/deploy/compile/events/schedule/index.js rename to lib/plugins/aws/package/compile/events/schedule/index.js index 02344a25d..b115262af 100644 --- a/lib/plugins/aws/deploy/compile/events/schedule/index.js +++ b/lib/plugins/aws/package/compile/events/schedule/index.js @@ -8,7 +8,7 @@ class AwsCompileScheduledEvents { this.provider = this.serverless.getProvider('aws'); this.hooks = { - 'deploy:compileEvents': this.compileScheduledEvents.bind(this), + 'package:compileEvents': this.compileScheduledEvents.bind(this), }; } diff --git a/lib/plugins/aws/deploy/compile/events/schedule/index.test.js b/lib/plugins/aws/package/compile/events/schedule/index.test.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/schedule/index.test.js rename to lib/plugins/aws/package/compile/events/schedule/index.test.js diff --git a/lib/plugins/aws/deploy/compile/events/sns/index.js b/lib/plugins/aws/package/compile/events/sns/index.js similarity index 98% rename from lib/plugins/aws/deploy/compile/events/sns/index.js rename to lib/plugins/aws/package/compile/events/sns/index.js index 4f46adad5..32cb99bb2 100644 --- a/lib/plugins/aws/deploy/compile/events/sns/index.js +++ b/lib/plugins/aws/package/compile/events/sns/index.js @@ -8,7 +8,7 @@ class AwsCompileSNSEvents { this.provider = this.serverless.getProvider('aws'); this.hooks = { - 'deploy:compileEvents': this.compileSNSEvents.bind(this), + 'package:compileEvents': this.compileSNSEvents.bind(this), }; } diff --git a/lib/plugins/aws/deploy/compile/events/sns/index.test.js b/lib/plugins/aws/package/compile/events/sns/index.test.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/sns/index.test.js rename to lib/plugins/aws/package/compile/events/sns/index.test.js diff --git a/lib/plugins/aws/deploy/compile/events/stream/index.js b/lib/plugins/aws/package/compile/events/stream/index.js similarity index 99% rename from lib/plugins/aws/deploy/compile/events/stream/index.js rename to lib/plugins/aws/package/compile/events/stream/index.js index 1b6d44e33..a0bb4ab36 100644 --- a/lib/plugins/aws/deploy/compile/events/stream/index.js +++ b/lib/plugins/aws/package/compile/events/stream/index.js @@ -8,7 +8,7 @@ class AwsCompileStreamEvents { this.provider = this.serverless.getProvider('aws'); this.hooks = { - 'deploy:compileEvents': this.compileStreamEvents.bind(this), + 'package:compileEvents': this.compileStreamEvents.bind(this), }; } diff --git a/lib/plugins/aws/deploy/compile/events/stream/index.test.js b/lib/plugins/aws/package/compile/events/stream/index.test.js similarity index 100% rename from lib/plugins/aws/deploy/compile/events/stream/index.test.js rename to lib/plugins/aws/package/compile/events/stream/index.test.js diff --git a/lib/plugins/aws/deploy/compile/functions/index.js b/lib/plugins/aws/package/compile/functions/index.js similarity index 93% rename from lib/plugins/aws/deploy/compile/functions/index.js rename to lib/plugins/aws/package/compile/functions/index.js index d20de6322..c856530fa 100644 --- a/lib/plugins/aws/deploy/compile/functions/index.js +++ b/lib/plugins/aws/package/compile/functions/index.js @@ -9,6 +9,11 @@ class AwsCompileFunctions { constructor(serverless, options) { this.serverless = serverless; this.options = options; + + this.packagePath = this.options.package || + this.serverless.service.package.path || + path.join(this.serverless.config.servicePath, '.serverless'); + this.provider = this.serverless.getProvider('aws'); this.compileFunctions = this.compileFunctions.bind(this); @@ -20,7 +25,7 @@ class AwsCompileFunctions { } this.hooks = { - 'deploy:compileFunctions': this.compileFunctions, + 'package:compileFunctions': this.compileFunctions, }; } @@ -74,6 +79,14 @@ class AwsCompileFunctions { } else { artifactFilePath = this.serverless.service.package.artifact; } + const serviceArtifactFileName = this.provider.naming.getServiceArtifactName(); + const functionArtifactFileName = this.provider.naming.getFunctionArtifactName(functionName); + + const artifactFileName = this.serverless.service.package.individually ? + functionArtifactFileName : + serviceArtifactFileName; + + const artifactFilePath = path.join(this.packagePath, artifactFileName); if (!artifactFilePath) { throw new Error(`No artifact path is set for function: "${functionName}"`); diff --git a/lib/plugins/aws/deploy/compile/functions/index.test.js b/lib/plugins/aws/package/compile/functions/index.test.js similarity index 100% rename from lib/plugins/aws/deploy/compile/functions/index.test.js rename to lib/plugins/aws/package/compile/functions/index.test.js diff --git a/lib/plugins/aws/package/index.js b/lib/plugins/aws/package/index.js new file mode 100644 index 000000000..cc3db9ae6 --- /dev/null +++ b/lib/plugins/aws/package/index.js @@ -0,0 +1,57 @@ +'use strict'; + +const BbPromise = require('bluebird'); +const path = require('path'); +const validate = require('../lib/validate'); +const mergeCustomProviderResources = require('./lib/mergeCustomProviderResources'); +const generateArtifactDirectoryName = require('./lib/generateArtifactDirectoryName'); +const generateCoreTemplate = require('./lib/generateCoreTemplate'); +const generateCompiledTemplate = require('./lib/generateCompiledTemplate'); +const mergeIamTemplates = require('./lib/mergeIamTemplates'); +const zipService = require('./lib/zipService'); +const packageService = require('./lib/packageService'); +const cleanup = require('./lib/cleanup'); + +class AwsPackage { + constructor(serverless, options) { + this.serverless = serverless; + this.options = options; + this.packagePath = this.options.package || + this.serverless.service.package.path || + path.join(this.serverless.config.servicePath, '.serverless'); + this.provider = this.serverless.getProvider('aws'); + + Object.assign( + this, + cleanup, + validate, + packageService, + zipService, + generateCoreTemplate, + mergeIamTemplates, + generateArtifactDirectoryName, + mergeCustomProviderResources, + generateCompiledTemplate + ); + + this.hooks = { + 'package:cleanup': () => BbPromise.bind(this) + .then(this.cleanup), + + 'package:createDeploymentArtifacts': () => BbPromise.bind(this) + .then(this.validate) + .then(this.packageService), + + 'package:initialize': () => BbPromise.bind(this) + .then(this.generateCoreTemplate) + .then(this.mergeIamTemplates) + .then(this.generateArtifactDirectoryName), + + 'package:finalize': () => BbPromise.bind(this) + .then(this.mergeCustomProviderResources) + .then(this.generateCompiledTemplate), + }; + } +} + +module.exports = AwsPackage; diff --git a/lib/plugins/package/lib/cleanup.js b/lib/plugins/aws/package/lib/cleanup.js similarity index 100% rename from lib/plugins/package/lib/cleanup.js rename to lib/plugins/aws/package/lib/cleanup.js diff --git a/lib/plugins/package/lib/cleanup.test.js b/lib/plugins/aws/package/lib/cleanup.test.js similarity index 100% rename from lib/plugins/package/lib/cleanup.test.js rename to lib/plugins/aws/package/lib/cleanup.test.js diff --git a/lib/plugins/aws/deploy/lib/core-cloudformation-template.json b/lib/plugins/aws/package/lib/core-cloudformation-template.json similarity index 100% rename from lib/plugins/aws/deploy/lib/core-cloudformation-template.json rename to lib/plugins/aws/package/lib/core-cloudformation-template.json diff --git a/lib/plugins/aws/deploy/lib/generateArtifactDirectoryName.js b/lib/plugins/aws/package/lib/generateArtifactDirectoryName.js similarity index 100% rename from lib/plugins/aws/deploy/lib/generateArtifactDirectoryName.js rename to lib/plugins/aws/package/lib/generateArtifactDirectoryName.js diff --git a/lib/plugins/aws/deploy/lib/generateArtifactDirectoryName.test.js b/lib/plugins/aws/package/lib/generateArtifactDirectoryName.test.js similarity index 100% rename from lib/plugins/aws/deploy/lib/generateArtifactDirectoryName.test.js rename to lib/plugins/aws/package/lib/generateArtifactDirectoryName.test.js diff --git a/lib/plugins/aws/package/lib/generateCompiledTemplate.js b/lib/plugins/aws/package/lib/generateCompiledTemplate.js new file mode 100644 index 000000000..f8089e45f --- /dev/null +++ b/lib/plugins/aws/package/lib/generateCompiledTemplate.js @@ -0,0 +1,18 @@ +'use strict'; + +const BbPromise = require('bluebird'); +const path = require('path'); + +module.exports = { + generateCompiledTemplate() { + const compiledTemplateFileName = this.provider.naming.getCompiledTemplateFileName(); + + const compiledTemplateFilePath = path.join(this.packagePath, compiledTemplateFileName); + + this.serverless.utils.writeFileSync(compiledTemplateFilePath, + this.serverless.service.provider.compiledCloudFormationTemplate); + + return BbPromise.resolve(); + }, + +}; diff --git a/lib/plugins/aws/deploy/lib/configureStack.js b/lib/plugins/aws/package/lib/generateCoreTemplate.js similarity index 79% rename from lib/plugins/aws/deploy/lib/configureStack.js rename to lib/plugins/aws/package/lib/generateCoreTemplate.js index 393c3d9e2..13375b8c9 100644 --- a/lib/plugins/aws/deploy/lib/configureStack.js +++ b/lib/plugins/aws/package/lib/generateCoreTemplate.js @@ -4,13 +4,13 @@ const BbPromise = require('bluebird'); const path = require('path'); module.exports = { - configureStack() { + generateCoreTemplate() { this.serverless.service.provider .compiledCloudFormationTemplate = this.serverless.utils.readFileSync( path.join(this.serverless.config.serverlessPath, 'plugins', 'aws', - 'deploy', + 'package', 'lib', 'core-cloudformation-template.json') ); @@ -47,6 +47,17 @@ module.exports = { }); } + if (this.serverless.service.provider.deploymentBucket) { + return BbPromise.resolve(); + } + + const coreTemplateFileName = this.provider.naming.getCoreTemplateFileName(); + + const coreTemplateFilePath = path.join(this.packagePath, coreTemplateFileName); + + this.serverless.utils.writeFileSync(coreTemplateFilePath, + this.serverless.service.provider.compiledCloudFormationTemplate); + return BbPromise.resolve(); }, diff --git a/lib/plugins/aws/deploy/lib/configureStack.test.js b/lib/plugins/aws/package/lib/generateCoreTemplate.test.js similarity index 98% rename from lib/plugins/aws/deploy/lib/configureStack.test.js rename to lib/plugins/aws/package/lib/generateCoreTemplate.test.js index 82b06b865..5bb857905 100644 --- a/lib/plugins/aws/deploy/lib/configureStack.test.js +++ b/lib/plugins/aws/package/lib/generateCoreTemplate.test.js @@ -6,7 +6,7 @@ const expect = require('chai').expect; const AwsProvider = require('../../provider/awsProvider'); const Serverless = require('../../../../Serverless'); const validate = require('../../lib/validate'); -const configureStack = require('../lib/configureStack'); +const configureStack = require('generateStackCreateTemplate'); describe('#configureStack', () => { let serverless; diff --git a/lib/plugins/aws/deploy/lib/iam-role-lambda-execution-template.json b/lib/plugins/aws/package/lib/iam-role-lambda-execution-template.json similarity index 100% rename from lib/plugins/aws/deploy/lib/iam-role-lambda-execution-template.json rename to lib/plugins/aws/package/lib/iam-role-lambda-execution-template.json diff --git a/lib/plugins/aws/deploy/lib/mergeCustomProviderResources.js b/lib/plugins/aws/package/lib/mergeCustomProviderResources.js similarity index 100% rename from lib/plugins/aws/deploy/lib/mergeCustomProviderResources.js rename to lib/plugins/aws/package/lib/mergeCustomProviderResources.js diff --git a/lib/plugins/aws/deploy/lib/mergeCustomProviderResources.test.js b/lib/plugins/aws/package/lib/mergeCustomProviderResources.test.js similarity index 100% rename from lib/plugins/aws/deploy/lib/mergeCustomProviderResources.test.js rename to lib/plugins/aws/package/lib/mergeCustomProviderResources.test.js diff --git a/lib/plugins/aws/deploy/lib/mergeIamTemplates.js b/lib/plugins/aws/package/lib/mergeIamTemplates.js similarity index 99% rename from lib/plugins/aws/deploy/lib/mergeIamTemplates.js rename to lib/plugins/aws/package/lib/mergeIamTemplates.js index b240607b0..7276853b0 100644 --- a/lib/plugins/aws/deploy/lib/mergeIamTemplates.js +++ b/lib/plugins/aws/package/lib/mergeIamTemplates.js @@ -53,7 +53,7 @@ module.exports = { path.join(this.serverless.config.serverlessPath, 'plugins', 'aws', - 'deploy', + 'package', 'lib', 'iam-role-lambda-execution-template.json') ); diff --git a/lib/plugins/aws/deploy/lib/mergeIamTemplates.test.js b/lib/plugins/aws/package/lib/mergeIamTemplates.test.js similarity index 100% rename from lib/plugins/aws/deploy/lib/mergeIamTemplates.test.js rename to lib/plugins/aws/package/lib/mergeIamTemplates.test.js diff --git a/lib/plugins/package/lib/packageService.js b/lib/plugins/aws/package/lib/packageService.js similarity index 63% rename from lib/plugins/package/lib/packageService.js rename to lib/plugins/aws/package/lib/packageService.js index 0843bcba1..506e34be8 100644 --- a/lib/plugins/package/lib/packageService.js +++ b/lib/plugins/aws/package/lib/packageService.js @@ -26,14 +26,6 @@ module.exports = { return _.union(this.defaultExcludes, packageExcludes, exclude); }, - getServiceArtifactName() { - return `${this.serverless.service.service}.zip`; - }, - - getFunctionArtifactName(functionObject) { - return `${functionObject.name}.zip`; - }, - packageService() { // check if the user has specified an own artifact if (this.serverless.service.package.artifact) { @@ -42,6 +34,13 @@ module.exports = { let shouldPackageService = false; + this.serverless.cli.log('Packaging service...'); + + if (this.serverless.service.package.individually) { + const allFunctions = this.serverless.service.getAllFunctions(); + const packagePromises = _.map(allFunctions, functionName => + this.packageFunction(functionName)); + this.serverless.cli.log('Packaging service...'); const allFunctions = this.serverless.service.getAllFunctions(); const packagePromises = _.map(allFunctions, functionName => { @@ -65,42 +64,21 @@ module.exports = { }, packageAll() { - const servicePath = this.serverless.config.servicePath; - const exclude = this.getExcludes(); const include = this.getIncludes(); - const zipFileName = this.getServiceArtifactName(); + const zipFileName = this.provider.naming.getServiceArtifactName(); - return this.zipDirectory(servicePath, exclude, include, zipFileName).then(filePath => { - this.serverless.service.package.artifact = filePath; - return filePath; - }); + return this.zipDirectory(exclude, include, zipFileName); }, packageFunction(functionName) { const functionObject = this.serverless.service.getFunction(functionName); const funcPackageConfig = functionObject.package || {}; - functionObject.artifact = null; // reset the current artifact - - if (funcPackageConfig.artifact) { - if (process.env.SLS_DEBUG) { - this.serverless.cli.log('package.artifact is defined, skipping packaging'); - } - - functionObject.artifact = funcPackageConfig.artifact; - return BbPromise.resolve(funcPackageConfig.artifact); - } - - const servicePath = this.serverless.config.servicePath; - const exclude = this.getExcludes(funcPackageConfig.exclude); const include = this.getIncludes(funcPackageConfig.include); - const zipFileName = this.getFunctionArtifactName(functionObject); + const zipFileName = this.provider.naming.getFunctionArtifactName(functionName); - return this.zipDirectory(servicePath, exclude, include, zipFileName).then((artifactPath) => { - functionObject.artifact = artifactPath; - return artifactPath; - }); + return this.zipDirectory(exclude, include, zipFileName); }, }; diff --git a/lib/plugins/package/lib/packageService.test.js b/lib/plugins/aws/package/lib/packageService.test.js similarity index 100% rename from lib/plugins/package/lib/packageService.test.js rename to lib/plugins/aws/package/lib/packageService.test.js diff --git a/lib/plugins/package/lib/zipService.js b/lib/plugins/aws/package/lib/zipService.js similarity index 88% rename from lib/plugins/package/lib/zipService.js rename to lib/plugins/aws/package/lib/zipService.js index 7efe9b484..bc59786ff 100644 --- a/lib/plugins/package/lib/zipService.js +++ b/lib/plugins/aws/package/lib/zipService.js @@ -7,7 +7,7 @@ const fs = require('fs'); const globby = require('globby'); module.exports = { - zipDirectory(servicePath, exclude, include, zipFileName) { + zipDirectory(exclude, include, zipFileName) { const patterns = ['**']; exclude.forEach((pattern) => { @@ -26,9 +26,7 @@ module.exports = { const zip = archiver.create('zip'); - const artifactFilePath = path.join( - servicePath, - '.serverless', + const artifactFilePath = path.join(this.packagePath, zipFileName ); @@ -40,7 +38,7 @@ module.exports = { zip.pipe(output); const files = globby.sync(patterns, { - cwd: servicePath, + cwd: this.serverless.config.servicePath, dot: true, silent: true, follow: true, @@ -48,7 +46,7 @@ module.exports = { files.forEach((filePath) => { const fullPath = path.resolve( - servicePath, + this.serverless.config.servicePath, filePath ); diff --git a/lib/plugins/package/lib/zipService.test.js b/lib/plugins/aws/package/lib/zipService.test.js similarity index 100% rename from lib/plugins/package/lib/zipService.test.js rename to lib/plugins/aws/package/lib/zipService.test.js diff --git a/lib/plugins/deploy/deploy.js b/lib/plugins/deploy/deploy.js index a2993648f..a8769d5b9 100644 --- a/lib/plugins/deploy/deploy.js +++ b/lib/plugins/deploy/deploy.js @@ -8,13 +8,9 @@ class Deploy { deploy: { usage: 'Deploy a Serverless service', lifecycleEvents: [ - 'cleanup', 'initialize', - 'setupProviderConfiguration', - 'createDeploymentArtifacts', - 'compileFunctions', - 'compileEvents', 'deploy', + 'finalize', ], options: { stage: { @@ -25,9 +21,9 @@ class Deploy { usage: 'Region of the service', shortcut: 'r', }, - noDeploy: { - usage: 'Build artifacts without deploying', - shortcut: 'n', + package: { + usage: 'Path of the deployment package', + shortcut: 'p', }, verbose: { usage: 'Show all stack events during deployment', diff --git a/lib/plugins/package/index.js b/lib/plugins/package/index.js deleted file mode 100644 index af8caf5be..000000000 --- a/lib/plugins/package/index.js +++ /dev/null @@ -1,33 +0,0 @@ -'use strict'; - -const BbPromise = require('bluebird'); -const validate = require('./lib/validate'); -const zipService = require('./lib/zipService'); -const packageService = require('./lib/packageService'); -const cleanup = require('./lib/cleanup'); - -class Package { - constructor(serverless, options) { - this.serverless = serverless; - this.options = options; - - Object.assign( - this, - validate, - zipService, - packageService, - cleanup - ); - - this.hooks = { - 'deploy:cleanup': () => BbPromise.bind(this) - .then(this.cleanup), - - 'deploy:createDeploymentArtifacts': () => BbPromise.bind(this) - .then(this.validate) - .then(this.packageService), - }; - } -} - -module.exports = Package; diff --git a/lib/plugins/package/lib/validate.js b/lib/plugins/package/lib/validate.js deleted file mode 100644 index cbccb4cd4..000000000 --- a/lib/plugins/package/lib/validate.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; - -const BbPromise = require('bluebird'); - -module.exports = { - validate() { - if (!this.serverless.config.servicePath) { - throw new this.serverless.classes - .Error('This command can only be run inside a service directory'); - } - - return BbPromise.resolve(); - }, -}; diff --git a/lib/plugins/package/lib/validate.test.js b/lib/plugins/package/lib/validate.test.js deleted file mode 100644 index 05b96578c..000000000 --- a/lib/plugins/package/lib/validate.test.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict'; - -const expect = require('chai').expect; -const Package = require('../index'); -const Serverless = require('../../../../lib/Serverless'); - -describe('#validate()', () => { - let serverless; - let packageService; - - beforeEach(() => { - serverless = new Serverless(); - packageService = new Package(serverless); - }); - - it('should throw error if not inside service (servicePath not defined)', () => { - packageService.serverless.config.servicePath = false; - expect(() => packageService.validate()).to.throw(Error); - }); - - it('should resolve if servicePath is given', (done) => { - packageService.serverless.config.servicePath = true; - packageService.validate().then(() => done()); - }); -}); diff --git a/lib/plugins/package/package.js b/lib/plugins/package/package.js new file mode 100644 index 000000000..7466a082d --- /dev/null +++ b/lib/plugins/package/package.js @@ -0,0 +1,39 @@ +'use strict'; + +class Package { + constructor(serverless, options) { + this.serverless = serverless; + this.options = options; + + + this.commands = { + package: { + usage: 'Packages a Serverless service', + lifecycleEvents: [ + 'cleanup', + 'createDeploymentArtifacts', + 'initialize', + 'compileFunctions', + 'compileEvents', + 'finalize', + ], + options: { + stage: { + usage: 'Stage of the service', + shortcut: 's', + }, + region: { + usage: 'Region of the service', + shortcut: 'r', + }, + package: { + usage: 'Output path for the package', + shortcut: 'p', + }, + }, + }, + }; + } +} + +module.exports = Package; diff --git a/lib/plugins/package/index.test.js b/lib/plugins/package/package.test.js similarity index 94% rename from lib/plugins/package/index.test.js rename to lib/plugins/package/package.test.js index 9faca2617..b0dc66af3 100644 --- a/lib/plugins/package/index.test.js +++ b/lib/plugins/package/package.test.js @@ -2,7 +2,8 @@ const expect = require('chai').expect; const sinon = require('sinon'); -const Package = require('./index'); +const BbPromise = require('bluebird'); +const Package = require('./package'); const Serverless = require('../../../lib/Serverless'); describe('#constructor()', () => {