Make coreBucket name unique

This commit is contained in:
Philipp Muens 2016-07-12 09:48:15 +02:00
parent c6de6a87d5
commit eeee34fa5b
11 changed files with 104 additions and 38 deletions

View File

@ -25,7 +25,7 @@ class AwsCompileFunctions {
"Type": "AWS::Lambda::Function",
"Properties": {
"Code": {
"S3Bucket": "S3Bucket",
"S3Bucket": { "Ref": "coreBucket" },
"S3Key": "S3Key"
},
"FunctionName": "FunctionName",
@ -42,9 +42,6 @@ class AwsCompileFunctions {
const newFunction = JSON.parse(functionTemplate);
const functionObject = this.serverless.service.getFunction(functionName);
newFunction.Properties.Code
.S3Bucket =
`${this.serverless.service.service}-${this.options.stage}-${this.options.region}`;
newFunction.Properties.Code
.S3Key = this.serverless.service.package.artifact.split(path.sep).pop();

View File

@ -39,7 +39,7 @@ describe('AwsCompileFunctions', () => {
Type: 'AWS::Lambda::Function',
Properties: {
Code: {
S3Bucket: 'new-service-dev-us-east-1',
S3Bucket: { Ref: 'coreBucket' },
S3Key: 'artifact.zip',
},
FunctionName: 'new-service-dev-first',
@ -54,7 +54,7 @@ describe('AwsCompileFunctions', () => {
Type: 'AWS::Lambda::Function',
Properties: {
Code: {
S3Bucket: 'new-service-dev-us-east-1',
S3Bucket: { Ref: 'coreBucket' },
S3Key: 'artifact.zip',
},
FunctionName: 'new-service-dev-second',

View File

@ -12,12 +12,6 @@ module.exports = {
);
// set the necessary variables before creating stack
coreCFTemplate
.Resources
.coreBucket
.Properties
.BucketName =
`${this.serverless.service.service}-${this.options.stage}-${this.options.region}`;
coreCFTemplate
.Resources
.IamPolicyLambda

View File

@ -6,16 +6,20 @@ const BbPromise = require('bluebird');
const _ = require('lodash');
module.exports = {
getServiceObjectsFromS3Bucket() {
const bucketName =
`${this.serverless.service.service}-${this.options.stage}-${this.options.region}`;
setCoreBucketName() {
return this.sdk.getCoreBucketName(this.options.stage, this.options.region)
.then((bucketName) => {
this.bucketName = bucketName;
});
},
getServiceObjectsFromS3Bucket() {
// 4 old ones + the one which will be uploaded after the cleanup = 5
const objectsToKeepCount = 4;
return this.sdk.request('S3',
'listObjectsV2',
{ Bucket: bucketName },
{ Bucket: this.bucketName },
this.options.stage,
this.options.region)
.then((result) => {
@ -45,13 +49,10 @@ module.exports = {
if (objectsToRemove && objectsToRemove.length) {
this.serverless.cli.log('Removing old service versions...');
const bucketName =
`${this.serverless.service.service}-${this.options.stage}-${this.options.region}`;
return this.sdk.request('S3',
'deleteObjects',
{
Bucket: bucketName,
Bucket: this.bucketName,
Delete: { Objects: objectsToRemove },
},
this.options.stage,
@ -64,13 +65,10 @@ module.exports = {
uploadZipFileToS3Bucket() {
this.serverless.cli.log('Uploading .zip file to S3...');
const bucketName =
`${this.serverless.service.service}-${this.options.stage}-${this.options.region}`;
const body = fs.readFileSync(this.serverless.service.package.artifact);
const params = {
Bucket: bucketName,
Bucket: this.bucketName,
Key: this.serverless.service.package.artifact.split(path.sep).pop(),
Body: body,
};
@ -84,6 +82,7 @@ module.exports = {
uploadDeploymentPackage() {
return BbPromise.bind(this)
.then(this.setCoreBucketName)
.then(this.getServiceObjectsFromS3Bucket)
.then(this.cleanupS3Bucket)
.then(this.uploadZipFileToS3Bucket);

View File

@ -22,6 +22,22 @@ describe('uploadDeploymentPackage', () => {
awsDeploy.serverless.cli = new serverless.classes.CLI();
});
describe('#setCoreBucketName()', () => {
it('should store the name of the core bucket in the "this" variable', () => {
const getCoreBucketNameStub = sinon
.stub(awsDeploy.sdk, 'getCoreBucketName')
.returns(BbPromise.resolve('new-service-dev-us-east-1-12345678'));
return awsDeploy.setCoreBucketName().then(() => {
expect(awsDeploy.bucketName).to.equal('new-service-dev-us-east-1-12345678');
expect(getCoreBucketNameStub.calledOnce).to.be.equal(true);
expect(getCoreBucketNameStub
.calledWith(awsDeploy.options.stage, awsDeploy.options.region));
awsDeploy.sdk.getCoreBucketName.restore();
});
});
});
describe('#getServiceObjectsFromS3Bucket()', () => {
it('should resolve if no service objects are found', () => {
const serviceObjects = {

View File

@ -4,6 +4,7 @@ const BbPromise = require('bluebird');
const HttpsProxyAgent = require('https-proxy-agent');
const url = require('url');
const AWS = require('aws-sdk');
const _ = require('lodash');
class SDK {
constructor(serverless) {
@ -86,6 +87,18 @@ class SDK {
return credentials;
}
getCoreBucketName(stage, region) {
const stackName = `${this.serverless.service.service}-${stage}`;
return this.request('CloudFormation',
'describeStacks',
{ StackName: stackName },
stage,
region
).then((result) => _.find(result.Stacks[0].Outputs,
{ OutputKey: 'CoreBucketName' }).OutputValue);
}
}
module.exports = SDK;

View File

@ -17,10 +17,10 @@ class AwsRemove {
this.hooks = {
'remove:remove': () => BbPromise.bind(this)
.then(this.validate)
.then(this.emptyS3Bucket)
.then(this.removeStack)
.then(() => this.serverless.cli.log('Resource removal successful!')),
.then(this.validate)
.then(this.emptyS3Bucket)
.then(this.removeStack)
.then(() => this.serverless.cli.log('Resource removal successful!')),
};
}
}

View File

@ -3,14 +3,19 @@
const BbPromise = require('bluebird');
module.exports = {
setCoreBucketName() {
return this.sdk.getCoreBucketName(this.options.stage, this.options.region)
.then((bucketName) => {
this.bucketName = bucketName;
});
},
listObjects() {
this.objectsInBucket = [];
const bucketName = `${this.serverless.service.service}-${
this.options.stage}-${this.options.region}`;
this.serverless.cli.log('Getting all objects in S3 bucket...');
return this.sdk.request('S3', 'listObjectsV2', {
Bucket: bucketName,
Bucket: this.bucketName,
}, this.options.stage, this.options.region).then((result) => {
if (result) {
result.Contents.forEach((object) => {
@ -24,12 +29,10 @@ module.exports = {
},
deleteObjects() {
const bucketName = `${this.serverless.service.service}-${
this.options.stage}-${this.options.region}`;
this.serverless.cli.log('Removing objects in S3 bucket...');
if (this.objectsInBucket.length) {
return this.sdk.request('S3', 'deleteObjects', {
Bucket: bucketName,
Bucket: this.bucketName,
Delete: {
Objects: this.objectsInBucket,
},
@ -41,6 +44,7 @@ module.exports = {
emptyS3Bucket() {
return BbPromise.bind(this)
.then(this.setCoreBucketName)
.then(this.listObjects)
.then(this.deleteObjects);
},

View File

@ -20,6 +20,22 @@ describe('emptyS3Bucket', () => {
awsRemove.serverless.cli = new serverless.classes.CLI();
});
describe('#setCoreBucketName()', () => {
it('should store the name of the core bucket in the "this" variable', () => {
const getCoreBucketNameStub = sinon
.stub(awsRemove.sdk, 'getCoreBucketName')
.returns(BbPromise.resolve('new-service-dev-us-east-1-12345678'));
return awsRemove.setCoreBucketName().then(() => {
expect(awsRemove.bucketName).to.equal('new-service-dev-us-east-1-12345678');
expect(getCoreBucketNameStub.calledOnce).to.be.equal(true);
expect(getCoreBucketNameStub
.calledWith(awsRemove.options.stage, awsRemove.options.region));
awsRemove.sdk.getCoreBucketName.restore();
});
});
});
describe('#listObjects()', () => {
it('should list all objects in the S3 bucket', () => {
const listObjectsStub = sinon.stub(awsRemove.sdk, 'request')

View File

@ -1,5 +1,7 @@
'use strict';
const sinon = require('sinon');
const BbPromise = require('bluebird');
const expect = require('chai').expect;
const Serverless = require('../../../Serverless');
const AwsSdk = require('../');
@ -127,4 +129,27 @@ describe('AWS SDK', () => {
expect(credentials.profile).to.deep.equal('default');
});
});
describe('#getCoreBucketName', () => {
it('should return the name of the core bucket', () => {
const serverless = new Serverless();
const awsSdk = new AwsSdk(serverless);
const options = {
stage: 'dev',
region: 'us-east-1',
};
const getCoreBucketNameStub = sinon
.stub(awsSdk, 'getCoreBucketName')
.returns(BbPromise.resolve('new-service-dev-us-east-1-12345678'));
return awsSdk.getCoreBucketName(options.stage, options.region).then((bucketName) => {
expect(bucketName).to.equal('new-service-dev-us-east-1-12345678');
expect(getCoreBucketNameStub.calledOnce).to.be.equal(true);
expect(getCoreBucketNameStub
.calledWith(options.stage, options.region));
awsSdk.getCoreBucketName.restore();
});
});
});
});

View File

@ -3,10 +3,7 @@
"Description": "The AWS CloudFormation template for this Serverless application's resources outside of Lambdas and Api Gateway",
"Resources": {
"coreBucket": {
"Type" : "AWS::S3::Bucket",
"Properties": {
"BucketName": ""
}
"Type" : "AWS::S3::Bucket"
},
"IamRoleLambda": {
"Type": "AWS::IAM::Role",
@ -65,6 +62,11 @@
"Arn"
]
}
},
"CoreBucketName": {
"Value": {
"Ref": "coreBucket"
}
}
}
}