serverless/lib/plugins/aws/deploy/lib/updateStack.js
2016-10-19 16:50:41 +07:00

113 lines
3.5 KiB
JavaScript

'use strict';
const _ = require('lodash');
const path = require('path');
const BbPromise = require('bluebird');
module.exports = {
createFallback() {
this.createLater = false;
this.serverless.cli.log('Creating Stack...');
const stackName = `${this.serverless.service.service}-${this.options.stage}`;
let stackTags = { STAGE: this.options.stage };
const templateUrl = `https://s3.amazonaws.com/${
this.bucketName
}/${
this.serverless.service.package.artifactDirectoryName
}/compiled-cloudformation-template.json`;
// Merge additional stack tags
if (typeof this.serverless.service.provider.stackTags === 'object') {
stackTags = _.extend(stackTags, this.serverless.service.provider.stackTags);
}
const params = {
StackName: stackName,
OnFailure: 'ROLLBACK',
Capabilities: [
'CAPABILITY_IAM',
],
Parameters: [],
TemplateURL: templateUrl,
Tags: Object.keys(stackTags).map((key) => ({ Key: key, Value: stackTags[key] })),
};
return this.provider.request('CloudFormation',
'createStack',
params,
this.options.stage,
this.options.region)
.then((cfData) => this.monitorStack('create', cfData));
},
update() {
const templateUrl = `https://s3.amazonaws.com/${
this.bucketName
}/${
this.serverless.service.package.artifactDirectoryName
}/compiled-cloudformation-template.json`;
this.serverless.cli.log('Updating Stack…');
const stackName = `${this.serverless.service.service}-${this.options.stage}`;
let stackTags = { STAGE: this.options.stage };
// Merge additional stack tags
if (typeof this.serverless.service.provider.stackTags === 'object') {
stackTags = _.extend(stackTags, this.serverless.service.provider.stackTags);
}
const params = {
StackName: stackName,
Capabilities: [
'CAPABILITY_IAM',
],
Parameters: [],
TemplateURL: templateUrl,
Tags: Object.keys(stackTags).map((key) => ({ Key: key, Value: stackTags[key] })),
};
// Policy must have at least one statement, otherwise no updates would be possible at all
if (this.serverless.service.provider.stackPolicy &&
this.serverless.service.provider.stackPolicy.length) {
params.StackPolicyBody = JSON.stringify({
Statement: this.serverless.service.provider.stackPolicy,
});
}
return this.provider.request('CloudFormation',
'updateStack',
params,
this.options.stage,
this.options.region)
.then((cfData) => this.monitorStack('update', cfData));
},
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) {
return BbPromise.bind(this)
.then(this.createFallback);
}
return BbPromise.bind(this)
.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();
},
};