serverless
Version:
Serverless Framework - Build web, mobile and IoT applications with serverless architectures using AWS Lambda, Azure Functions, Google CloudFunctions & more
90 lines (75 loc) • 3.13 kB
JavaScript
;
const BbPromise = require('bluebird');
const validate = require('./lib/validate');
const setBucketName = require('./lib/setBucketName');
const updateStack = require('./lib/updateStack');
const monitorStack = require('./lib/monitorStack');
const findAndGroupDeployments = require('./utils/findAndGroupDeployments');
class AwsRollback {
constructor(serverless, options) {
this.serverless = serverless;
this.options = options;
this.provider = this.serverless.getProvider('aws');
Object.assign(this, validate, setBucketName, updateStack, monitorStack);
this.hooks = {
'before:rollback:initialize': () => BbPromise.bind(this).then(this.validate),
'rollback:rollback': () => {
if (!this.options.timestamp) {
const command = this.serverless.pluginManager.spawn('deploy:list');
this.serverless.cli.log(
[
'Use a timestamp from the deploy list below to rollback to a specific version.',
'Run `sls rollback -t YourTimeStampHere`',
].join('\n')
);
return command;
}
return BbPromise.bind(this)
.then(this.setBucketName)
.then(this.setStackToUpdate)
.then(this.updateStack);
},
};
}
setStackToUpdate() {
const service = this.serverless.service;
const serviceName = this.serverless.service.service;
const stage = this.provider.getStage();
const deploymentPrefix = this.provider.getDeploymentPrefix();
const prefix = `${deploymentPrefix}/${serviceName}/${stage}`;
return this.provider
.request('S3', 'listObjectsV2', {
Bucket: this.bucketName,
Prefix: prefix,
})
.then((response) => {
const deployments = findAndGroupDeployments(response, deploymentPrefix, serviceName, stage);
if (deployments.length === 0) {
const msg = "Couldn't find any existing deployments.";
const hint = 'Please verify that stage and region are correct.';
return BbPromise.reject(`${msg} ${hint}`);
}
let date = new Date(this.options.timestamp);
// The if below is added due issues#5664 - Check it for more details
if (date instanceof Date === false || isNaN(date.valueOf())) {
date = new Date(Number(this.options.timestamp));
}
const dateString = `${date.getTime().toString()}-${date.toISOString()}`;
const exists = deployments.some((deployment) =>
deployment.some(
(item) =>
item.directory === dateString &&
item.file === this.provider.naming.getCompiledTemplateS3Suffix()
)
);
if (!exists) {
const msg = `Couldn't find a deployment for the timestamp: ${this.options.timestamp}.`;
const hint = 'Please verify that the timestamp, stage and region are correct.';
return BbPromise.reject(`${msg} ${hint}`);
}
service.package.artifactDirectoryName = `${prefix}/${dateString}`;
return BbPromise.resolve();
});
}
}
module.exports = AwsRollback;