Introduce AwsProvider plugin

This commit is contained in:
Philipp Muens 2016-10-14 18:14:30 -07:00
parent ca45eb4eb8
commit df7692ac80
34 changed files with 297 additions and 232 deletions

View File

@ -20,6 +20,8 @@ class Serverless {
let configObject = config;
configObject = configObject || {};
this.providers = {};
this.version = Version;
this.yamlParser = new YamlParser(this);
@ -90,6 +92,14 @@ class Serverless {
return this.pluginManager.run(this.processedInput.commands);
}
setProvider(name, provider) {
this.providers[name] = provider;
}
getProvider(name) {
return this.providers[name] ? this.providers[name] : false;
}
getVersion() {
return this.version;
}

View File

@ -1,18 +1,18 @@
'use strict';
const expect = require('chai').expect;
const Serverless = require('../../lib/Serverless');
const Serverless = require('./Serverless');
const semverRegex = require('semver-regex');
const path = require('path');
const YAML = require('js-yaml');
const YamlParser = require('../../lib/classes/YamlParser');
const PluginManager = require('../../lib/classes/PluginManager');
const Utils = require('../../lib/classes/Utils');
const Service = require('../../lib/classes/Service');
const CLI = require('../../lib/classes/CLI');
const Error = require('../../lib/classes/Error').SError;
const testUtils = require('../../tests/utils');
const YamlParser = require('../lib/classes/YamlParser');
const PluginManager = require('../lib/classes/PluginManager');
const Utils = require('../lib/classes/Utils');
const Service = require('../lib/classes/Service');
const CLI = require('../lib/classes/CLI');
const Error = require('../lib/classes/Error').SError;
const testUtils = require('../tests/utils');
describe('Serverless', () => {
let serverless;
@ -37,6 +37,10 @@ describe('Serverless', () => {
expect(Object.keys(serverless.config)).to.include('servicePath');
});
it('should set an empty providers object', () => {
expect(serverless.providers).to.deep.equal({});
});
it('should set the Serverless version', () => {
expect(serverless.version.length).to.be.at.least(1);
});
@ -194,6 +198,34 @@ describe('Serverless', () => {
});
});
describe('#setProvider()', () => {
class ProviderMock {}
it('should set the provider object in the provider object', () => {
const myProvider = new ProviderMock();
serverless.setProvider('myProvider', myProvider);
expect(serverless.providers.myProvider).to.equal(myProvider);
});
});
describe('#getProvider()', () => {
class ProviderMock {}
let myProvider;
beforeEach(() => {
myProvider = new ProviderMock();
serverless.setProvider('myProvider', myProvider);
});
it('should return the provider object', () => {
const retrivedProvider = serverless.getProvider('myProvider');
expect(retrivedProvider).to.deep.equal(myProvider);
});
});
describe('#getVersion()', () => {
it('should get the correct Serverless version', () => {
expect(semverRegex().test(serverless.getVersion())).to.equal(true);

View File

@ -9,6 +9,7 @@
"./logs/logs.js",
"./remove/remove.js",
"./slstats/slstats.js",
"./awsProvider/awsProvider.js",
"./aws/deploy/index.js",
"./aws/invoke/index.js",
"./aws/info/index.js",

View File

@ -12,14 +12,12 @@ const uploadArtifacts = require('./lib/uploadArtifacts');
const updateStack = require('./lib/updateStack');
const configureStack = require('./lib/configureStack');
const SDK = require('../');
class AwsDeploy {
constructor(serverless, options) {
this.serverless = serverless;
this.options = options;
this.provider = 'aws';
this.sdk = new SDK(serverless);
this.aws = this.serverless.getProvider(this.provider);
Object.assign(
this,

View File

@ -9,7 +9,7 @@ module.exports = {
const directoriesToKeepCount = 4;
const serviceStage = `${this.serverless.service.service}/${this.options.stage}`;
return this.sdk.request('S3',
return this.aws.request('S3',
'listObjectsV2',
{
Bucket: this.bucketName,
@ -62,7 +62,7 @@ module.exports = {
if (objectsToRemove && objectsToRemove.length) {
this.serverless.cli.log('Removing old service versions...');
return this.sdk.request('S3',
return this.aws.request('S3',
'deleteObjects',
{
Bucket: this.bucketName,

View File

@ -79,7 +79,7 @@ module.exports = {
if (bucketName) {
return BbPromise.bind(this)
.then(() => this.validateS3BucketName(bucketName))
.then(() => this.sdk.request('S3',
.then(() => this.aws.request('S3',
'getBucketLocation',
{
Bucket: bucketName,

View File

@ -27,7 +27,7 @@ module.exports = {
Tags: Object.keys(stackTags).map((key) => ({ Key: key, Value: stackTags[key] })),
};
return this.sdk.request('CloudFormation',
return this.aws.request('CloudFormation',
'createStack',
params,
this.options.stage,
@ -55,7 +55,7 @@ module.exports = {
return BbPromise.resolve();
}
return this.sdk.request('CloudFormation',
return this.aws.request('CloudFormation',
'describeStackResources',
{ StackName: stackName },
this.options.stage,

View File

@ -12,7 +12,7 @@ module.exports = {
return BbPromise.resolve();
}
return this.sdk.getServerlessDeploymentBucketName(this.options.stage, this.options.region)
return this.aws.getServerlessDeploymentBucketName(this.options.stage, this.options.region)
.then((bucketName) => {
this.bucketName = bucketName;
});

View File

@ -39,7 +39,7 @@ module.exports = {
});
}
return this.sdk.request('CloudFormation',
return this.aws.request('CloudFormation',
'updateStack',
params,
this.options.stage,

View File

@ -19,7 +19,7 @@ module.exports = {
ContentType: 'application/json',
};
return this.sdk.request('S3',
return this.aws.request('S3',
'putObject',
params,
this.options.stage,
@ -42,7 +42,7 @@ module.exports = {
ContentType: 'application/zip',
};
return this.sdk.request('S3',
return this.aws.request('S3',
'putObject',
params,
this.options.stage,

View File

@ -3,6 +3,7 @@
const sinon = require('sinon');
const BbPromise = require('bluebird');
const expect = require('chai').expect;
const AwsProvider = require('../../../awsProvider/awsProvider');
const AwsDeploy = require('../index');
const Serverless = require('../../../../Serverless');
@ -13,6 +14,7 @@ describe('cleanupS3Bucket', () => {
beforeEach(() => {
serverless = new Serverless();
serverless.setProvider('aws', new AwsProvider(serverless));
serverless.service.service = 'cleanupS3Bucket';
const options = {
stage: 'dev',
@ -31,7 +33,7 @@ describe('cleanupS3Bucket', () => {
};
const listObjectsStub = sinon
.stub(awsDeploy.sdk, 'request').returns(BbPromise.resolve(serviceObjects));
.stub(awsDeploy.aws, 'request').returns(BbPromise.resolve(serviceObjects));
return awsDeploy.getObjectsToRemove().then(() => {
expect(listObjectsStub.calledOnce).to.be.equal(true);
@ -40,7 +42,7 @@ describe('cleanupS3Bucket', () => {
expect(listObjectsStub.args[0][2].Bucket).to.be.equal(awsDeploy.bucketName);
expect(listObjectsStub.args[0][2].Prefix).to.be.equal(`${s3Key}`);
expect(listObjectsStub.calledWith(awsDeploy.options.stage, awsDeploy.options.region));
awsDeploy.sdk.request.restore();
awsDeploy.aws.request.restore();
});
});
@ -63,7 +65,7 @@ describe('cleanupS3Bucket', () => {
};
const listObjectsStub = sinon
.stub(awsDeploy.sdk, 'request').returns(BbPromise.resolve(serviceObjects));
.stub(awsDeploy.aws, 'request').returns(BbPromise.resolve(serviceObjects));
return awsDeploy.getObjectsToRemove().then((objectsToRemove) => {
expect(objectsToRemove).to.not
@ -104,7 +106,7 @@ describe('cleanupS3Bucket', () => {
expect(listObjectsStub.args[0][2].Bucket).to.be.equal(awsDeploy.bucketName);
expect(listObjectsStub.args[0][2].Prefix).to.be.equal(`${s3Key}`);
expect(listObjectsStub.calledWith(awsDeploy.options.stage, awsDeploy.options.region));
awsDeploy.sdk.request.restore();
awsDeploy.aws.request.restore();
});
});
@ -121,7 +123,7 @@ describe('cleanupS3Bucket', () => {
};
const listObjectsStub = sinon
.stub(awsDeploy.sdk, 'request').returns(BbPromise.resolve(serviceObjects));
.stub(awsDeploy.aws, 'request').returns(BbPromise.resolve(serviceObjects));
return awsDeploy.getObjectsToRemove().then((objectsToRemove) => {
expect(objectsToRemove.length).to.equal(0);
@ -131,7 +133,7 @@ describe('cleanupS3Bucket', () => {
expect(listObjectsStub.args[0][2].Bucket).to.be.equal(awsDeploy.bucketName);
expect(listObjectsStub.args[0][2].Prefix).to.be.equal(`${s3Key}`);
expect(listObjectsStub.calledWith(awsDeploy.options.stage, awsDeploy.options.region));
awsDeploy.sdk.request.restore();
awsDeploy.aws.request.restore();
});
});
@ -150,7 +152,7 @@ describe('cleanupS3Bucket', () => {
};
const listObjectsStub = sinon
.stub(awsDeploy.sdk, 'request').returns(BbPromise.resolve(serviceObjects));
.stub(awsDeploy.aws, 'request').returns(BbPromise.resolve(serviceObjects));
return awsDeploy.getObjectsToRemove().then((objectsToRemove) => {
expect(objectsToRemove.length).to.equal(0);
@ -160,7 +162,7 @@ describe('cleanupS3Bucket', () => {
expect(listObjectsStub.args[0][2].Bucket).to.be.equal(awsDeploy.bucketName);
expect(listObjectsStub.args[0][2].Prefix).to.be.equal(`${s3Key}`);
expect(listObjectsStub.calledWith(awsDeploy.options.stage, awsDeploy.options.region));
awsDeploy.sdk.request.restore();
awsDeploy.aws.request.restore();
});
});
});
@ -170,13 +172,13 @@ describe('cleanupS3Bucket', () => {
beforeEach(() => {
deleteObjectsStub = sinon
.stub(awsDeploy.sdk, 'request').returns(BbPromise.resolve());
.stub(awsDeploy.aws, 'request').returns(BbPromise.resolve());
});
it('should resolve if no service objects are found in the S3 bucket', () => awsDeploy
.removeObjects().then(() => {
expect(deleteObjectsStub.calledOnce).to.be.equal(false);
awsDeploy.sdk.request.restore();
awsDeploy.aws.request.restore();
})
);
@ -195,7 +197,7 @@ describe('cleanupS3Bucket', () => {
expect(deleteObjectsStub.args[0][2].Bucket).to.be.equal(awsDeploy.bucketName);
expect(deleteObjectsStub.args[0][2].Delete.Objects).to.be.equal(objectsToRemove);
expect(deleteObjectsStub.calledWith(awsDeploy.options.stage, awsDeploy.options.region));
awsDeploy.sdk.request.restore();
awsDeploy.aws.request.restore();
});
});
});

View File

@ -4,34 +4,37 @@ const sinon = require('sinon');
const BbPromise = require('bluebird');
const path = require('path');
const expect = require('chai').expect;
const AwsProvider = require('../../../awsProvider/awsProvider');
const Serverless = require('../../../../Serverless');
const AwsSdk = require('../');
const validate = require('../../lib/validate');
const configureStack = require('../lib/configureStack');
describe('#configureStack', () => {
let awsSdk;
let serverless;
const awsPlugin = {};
beforeEach(() => {
serverless = new Serverless();
const options = {
awsPlugin.serverless = serverless;
awsPlugin.aws = new AwsProvider(serverless);
awsPlugin.options = {
stage: 'dev',
region: 'us-east-1',
};
awsSdk = new AwsSdk(serverless, options);
awsSdk.serverless.cli = new serverless.classes.CLI();
Object.assign(awsPlugin, configureStack, validate);
});
it('should validate the region for the given S3 bucket', () => {
const bucketName = 'com.serverless.deploys';
const getBucketLocationStub = sinon
.stub(awsSdk.sdk, 'request').returns(
BbPromise.resolve({ LocationConstraint: awsSdk.options.region })
.stub(awsPlugin.aws, 'request').returns(
BbPromise.resolve({ LocationConstraint: awsPlugin.options.region })
);
awsSdk.serverless.service.provider.deploymentBucket = bucketName;
return awsSdk.configureStack()
awsPlugin.serverless.service.provider.deploymentBucket = bucketName;
return awsPlugin.configureStack()
.then(() => {
expect(getBucketLocationStub.args[0][0]).to.equal('S3');
expect(getBucketLocationStub.args[0][1]).to.equal('getBucketLocation');
@ -43,12 +46,12 @@ describe('#configureStack', () => {
const bucketName = 'com.serverless.deploys';
const createStackStub = sinon
.stub(awsSdk.sdk, 'request').returns(
.stub(awsPlugin.aws, 'request').returns(
BbPromise.resolve({ LocationConstraint: 'us-west-1' })
);
awsSdk.serverless.service.provider.deploymentBucket = 'com.serverless.deploys';
return awsSdk.configureStack()
awsPlugin.serverless.service.provider.deploymentBucket = 'com.serverless.deploys';
return awsPlugin.configureStack()
.catch((err) => {
expect(createStackStub.args[0][0]).to.equal('S3');
expect(createStackStub.args[0][1]).to.equal('getBucketLocation');
@ -60,7 +63,7 @@ describe('#configureStack', () => {
it('should merge the IamRoleLambdaExecution template into the CloudFormation template', () => {
const IamRoleLambdaExecutionTemplate = awsSdk.serverless.utils.readFileSync(
const IamRoleLambdaExecutionTemplate = awsPlugin.serverless.utils.readFileSync(
path.join(
__dirname,
'..',
@ -69,55 +72,55 @@ describe('#configureStack', () => {
)
);
return awsSdk.configureStack()
return awsPlugin.configureStack()
.then(() => {
expect(awsSdk.serverless.service.provider.compiledCloudFormationTemplate
expect(awsPlugin.serverless.service.provider.compiledCloudFormationTemplate
.Resources.IamRoleLambdaExecution
).to.deep.equal(IamRoleLambdaExecutionTemplate.IamRoleLambdaExecution);
});
});
it('should merge IamPolicyLambdaExecution template into the CloudFormation template', () =>
awsSdk.configureStack()
awsPlugin.configureStack()
.then(() => {
// we check for the type here because a deep equality check will error out due to
// the updates which are made after the merge (they are tested in a separate test)
expect(awsSdk.serverless.service.provider.compiledCloudFormationTemplate
expect(awsPlugin.serverless.service.provider.compiledCloudFormationTemplate
.Resources.IamPolicyLambdaExecution.Type
).to.deep.equal('AWS::IAM::Policy');
})
);
it('should update the necessary variables for the IamPolicyLambdaExecution', () =>
awsSdk.configureStack()
awsPlugin.configureStack()
.then(() => {
expect(awsSdk.serverless.service.provider.compiledCloudFormationTemplate
expect(awsPlugin.serverless.service.provider.compiledCloudFormationTemplate
.Resources
.IamPolicyLambdaExecution
.Properties
.PolicyName
).to.equal(
`${
awsSdk.options.stage
awsPlugin.options.stage
}-${
awsSdk.serverless.service.service
awsPlugin.serverless.service.service
}-lambda`
);
expect(awsSdk.serverless.service.provider.compiledCloudFormationTemplate
expect(awsPlugin.serverless.service.provider.compiledCloudFormationTemplate
.Resources
.IamPolicyLambdaExecution
.Properties
.PolicyDocument
.Statement[0]
.Resource
).to.equal(`arn:aws:logs:${awsSdk.options.region}:*:*`);
).to.equal(`arn:aws:logs:${awsPlugin.options.region}:*:*`);
})
);
it('should add custom IAM policy statements', () => {
awsSdk.serverless.service.provider.name = 'aws';
awsSdk.serverless.service.provider.iamRoleStatements = [
awsPlugin.serverless.service.provider.name = 'aws';
awsPlugin.serverless.service.provider.iamRoleStatements = [
{
Effect: 'Allow',
Action: [
@ -128,20 +131,20 @@ describe('#configureStack', () => {
];
return awsSdk.configureStack()
return awsPlugin.configureStack()
.then(() => {
expect(awsSdk.serverless.service.provider.compiledCloudFormationTemplate
expect(awsPlugin.serverless.service.provider.compiledCloudFormationTemplate
.Resources.IamPolicyLambdaExecution.Properties.PolicyDocument.Statement[1]
).to.deep.equal(awsSdk.serverless.service.provider.iamRoleStatements[0]);
).to.deep.equal(awsPlugin.serverless.service.provider.iamRoleStatements[0]);
});
});
it('should use a custom bucket if specified', () => {
const bucketName = 'com.serverless.deploys';
awsSdk.serverless.service.provider.deploymentBucket = bucketName;
awsPlugin.serverless.service.provider.deploymentBucket = bucketName;
const coreCloudFormationTemplate = awsSdk.serverless.utils.readFileSync(
const coreCloudFormationTemplate = awsPlugin.serverless.utils.readFileSync(
path.join(
__dirname,
'..',
@ -149,44 +152,44 @@ describe('#configureStack', () => {
'core-cloudformation-template.json'
)
);
awsSdk.serverless.service.provider
awsPlugin.serverless.service.provider
.compiledCloudFormationTemplate = coreCloudFormationTemplate;
sinon
.stub(awsSdk.sdk, 'request')
.returns(BbPromise.resolve({ LocationConstraint: awsSdk.options.region }));
.stub(awsPlugin.aws, 'request')
.returns(BbPromise.resolve({ LocationConstraint: awsPlugin.options.region }));
return awsSdk.configureStack()
return awsPlugin.configureStack()
.then(() => {
expect(
awsSdk.serverless.service.provider.compiledCloudFormationTemplate
awsPlugin.serverless.service.provider.compiledCloudFormationTemplate
.Outputs.ServerlessDeploymentBucketName.Value
).to.equal(bucketName);
// eslint-disable-next-line no-unused-expressions
expect(
awsSdk.serverless.service.provider.compiledCloudFormationTemplate
awsPlugin.serverless.service.provider.compiledCloudFormationTemplate
.Resources.ServerlessDeploymentBucket
).to.not.exist;
});
});
it('should not add IamPolicyLambdaExecution', () => {
awsSdk.serverless.service.provider.iamRoleARN = 'some:aws:arn:xxx:*:*';
awsPlugin.serverless.service.provider.iamRoleARN = 'some:aws:arn:xxx:*:*';
return awsSdk.configureStack()
return awsPlugin.configureStack()
.then(() => expect(
awsSdk.serverless.service.provider.compiledCloudFormationTemplate
awsPlugin.serverless.service.provider.compiledCloudFormationTemplate
.Resources.IamPolicyLambdaExecution
).to.not.exist);
});
it('should not add IamRole', () => {
awsSdk.serverless.service.provider.iamRoleARN = 'some:aws:arn:xxx:*:*';
awsPlugin.serverless.service.provider.iamRoleARN = 'some:aws:arn:xxx:*:*';
return awsSdk.configureStack()
return awsPlugin.configureStack()
.then(() => expect(
awsSdk.serverless.service.provider.compiledCloudFormationTemplate
awsPlugin.serverless.service.provider.compiledCloudFormationTemplate
.Resources.IamRoleLambdaExecution
).to.not.exist);
});

View File

@ -4,6 +4,7 @@ const expect = require('chai').expect;
const sinon = require('sinon');
const path = require('path');
const BbPromise = require('bluebird');
const AwsProvider = require('../../../awsProvider/awsProvider');
const AwsDeploy = require('../index');
const Serverless = require('../../../../Serverless');
const testUtils = require('../../../../../tests/utils');
@ -25,6 +26,7 @@ describe('createStack', () => {
beforeEach(() => {
const serverless = new Serverless();
serverless.setProvider('aws', new AwsProvider(serverless));
serverless.utils.writeFileSync(serverlessYmlPath, serverlessYml);
serverless.config.servicePath = tmpDirPath;
const options = {
@ -49,7 +51,7 @@ describe('createStack', () => {
.compiledCloudFormationTemplate = coreCloudFormationTemplate;
const createStackStub = sinon
.stub(awsDeploy.sdk, 'request').returns(BbPromise.resolve());
.stub(awsDeploy.aws, 'request').returns(BbPromise.resolve());
return awsDeploy.create().then(() => {
expect(createStackStub.args[0][0]).to.equal('CloudFormation');
@ -69,7 +71,7 @@ describe('createStack', () => {
awsDeploy.serverless.service.provider.stackTags = { STAGE: 'overridden', tag1: 'value1' };
const createStackStub = sinon
.stub(awsDeploy.sdk, 'request').returns(BbPromise.resolve());
.stub(awsDeploy.aws, 'request').returns(BbPromise.resolve());
return awsDeploy.create().then(() => {
expect(createStackStub.args[0][2].Tags)
@ -77,14 +79,14 @@ describe('createStack', () => {
{ Key: 'STAGE', Value: 'overridden' },
{ Key: 'tag1', Value: 'value1' },
]);
awsDeploy.sdk.request.restore();
awsDeploy.aws.request.restore();
});
});
});
describe('#createStack()', () => {
it('should store the core CloudFormation template in the provider object', () => {
sinon.stub(awsDeploy.sdk, 'request').returns(BbPromise.resolve());
sinon.stub(awsDeploy.aws, 'request').returns(BbPromise.resolve());
const coreCloudFormationTemplate = awsDeploy.serverless.utils.readFileSync(
path.join(__dirname,
@ -110,7 +112,7 @@ describe('createStack', () => {
const createStub = sinon
.stub(awsDeploy, 'create').returns(BbPromise.resolve());
sinon.stub(awsDeploy.sdk, 'request').returns(BbPromise.resolve());
sinon.stub(awsDeploy.aws, 'request').returns(BbPromise.resolve());
return awsDeploy.createStack().then(() => {
expect(createStub.called).to.be.equal(false);
@ -136,11 +138,11 @@ describe('createStack', () => {
const writeCreateTemplateToDiskStub = sinon
.stub(awsDeploy, 'writeCreateTemplateToDisk').returns(BbPromise.resolve());
sinon.stub(awsDeploy.sdk, 'request').returns(BbPromise.resolve());
sinon.stub(awsDeploy.aws, 'request').returns(BbPromise.resolve());
return awsDeploy.createStack().then((res) => {
expect(writeCreateTemplateToDiskStub.calledOnce).to.be.equal(true);
expect(awsDeploy.sdk.request.called).to.be.equal(true);
expect(awsDeploy.aws.request.called).to.be.equal(true);
expect(res).to.equal('alreadyCreated');
});
});
@ -150,7 +152,7 @@ describe('createStack', () => {
message: 'Something went wrong.',
};
sinon.stub(awsDeploy.sdk, 'request').returns(BbPromise.reject(errorMock));
sinon.stub(awsDeploy.aws, 'request').returns(BbPromise.reject(errorMock));
const createStub = sinon
.stub(awsDeploy, 'create').returns(BbPromise.resolve());
@ -167,7 +169,7 @@ describe('createStack', () => {
message: 'does not exist',
};
sinon.stub(awsDeploy.sdk, 'request').returns(BbPromise.reject(errorMock));
sinon.stub(awsDeploy.aws, 'request').returns(BbPromise.reject(errorMock));
const createStub = sinon
.stub(awsDeploy, 'create').returns(BbPromise.resolve());

View File

@ -2,6 +2,7 @@
const expect = require('chai').expect;
const sinon = require('sinon');
const AwsProvider = require('../../../awsProvider/awsProvider');
const AwsDeploy = require('../index');
const Serverless = require('../../../../Serverless');
const BbPromise = require('bluebird');
@ -13,6 +14,7 @@ describe('#setBucketName()', () => {
beforeEach(() => {
serverless = new Serverless();
serverless.setProvider('aws', new AwsProvider(serverless));
const options = {
stage: 'dev',
region: 'us-east-1',
@ -20,7 +22,7 @@ describe('#setBucketName()', () => {
awsDeploy = new AwsDeploy(serverless, options);
getServerlessDeploymentBucketNameStub = sinon
.stub(awsDeploy.sdk, 'getServerlessDeploymentBucketName')
.stub(awsDeploy.aws, 'getServerlessDeploymentBucketName')
.returns(BbPromise.resolve('bucket-name'));
});
@ -30,7 +32,7 @@ describe('#setBucketName()', () => {
expect(getServerlessDeploymentBucketNameStub.calledOnce).to.be.equal(true);
expect(getServerlessDeploymentBucketNameStub
.calledWith(awsDeploy.options.stage, awsDeploy.options.region));
awsDeploy.sdk.getServerlessDeploymentBucketName.restore();
awsDeploy.aws.getServerlessDeploymentBucketName.restore();
})
);
@ -39,7 +41,7 @@ describe('#setBucketName()', () => {
return awsDeploy.setBucketName().then(() => {
expect(getServerlessDeploymentBucketNameStub.calledOnce).to.be.equal(false);
awsDeploy.sdk.getServerlessDeploymentBucketName.restore();
awsDeploy.aws.getServerlessDeploymentBucketName.restore();
});
});

View File

@ -4,6 +4,7 @@ const expect = require('chai').expect;
const sinon = require('sinon');
const path = require('path');
const BbPromise = require('bluebird');
const AwsProvider = require('../../../awsProvider/awsProvider');
const AwsDeploy = require('../index');
const Serverless = require('../../../../Serverless');
const testUtils = require('../../../../../tests/utils');
@ -15,6 +16,7 @@ describe('updateStack', () => {
beforeEach(() => {
serverless = new Serverless();
serverless.setProvider('aws', new AwsProvider(serverless));
const options = {
stage: 'dev',
region: 'us-east-1',
@ -34,7 +36,7 @@ describe('updateStack', () => {
beforeEach(() => {
updateStackStub = sinon
.stub(awsDeploy.sdk, 'request').returns(BbPromise.resolve());
.stub(awsDeploy.aws, 'request').returns(BbPromise.resolve());
});
it('should update the stack', () => awsDeploy.update()
@ -51,7 +53,7 @@ describe('updateStack', () => {
.to.deep.equal([{ Key: 'STAGE', Value: awsDeploy.options.stage }]);
expect(updateStackStub.calledWith(awsDeploy.options.stage, awsDeploy.options.region));
awsDeploy.sdk.request.restore();
awsDeploy.aws.request.restore();
})
);
@ -74,7 +76,7 @@ describe('updateStack', () => {
.to.equal(
'{"Statement":[{"Effect":"Allow","Principal":"*","Action":"Update:*","Resource":"*"}]}'
);
awsDeploy.sdk.request.restore();
awsDeploy.aws.request.restore();
});
});
});

View File

@ -4,6 +4,7 @@ const sinon = require('sinon');
const path = require('path');
const BbPromise = require('bluebird');
const expect = require('chai').expect;
const AwsProvider = require('../../../awsProvider/awsProvider');
const AwsDeploy = require('../index');
const Serverless = require('../../../../Serverless');
const testUtils = require('../../../../../tests/utils');
@ -14,6 +15,7 @@ describe('uploadArtifacts', () => {
beforeEach(() => {
serverless = new Serverless();
serverless.setProvider('aws', new AwsProvider(serverless));
const options = {
stage: 'dev',
region: 'us-east-1',
@ -29,7 +31,7 @@ describe('uploadArtifacts', () => {
awsDeploy.serverless.service.provider.compiledCloudFormationTemplate = { key: 'value' };
const putObjectStub = sinon
.stub(awsDeploy.sdk, 'request').returns(BbPromise.resolve());
.stub(awsDeploy.aws, 'request').returns(BbPromise.resolve());
return awsDeploy.uploadCloudFormationFile().then(() => {
expect(putObjectStub.calledOnce).to.be.equal(true);
@ -44,19 +46,19 @@ describe('uploadArtifacts', () => {
.provider.compiledCloudFormationTemplate));
expect(putObjectStub.calledWith(awsDeploy.options.stage, awsDeploy.options.region));
awsDeploy.sdk.request.restore();
awsDeploy.aws.request.restore();
});
});
});
describe('#uploadZipFile()', () => {
it('should throw for null artifact paths', () => {
sinon.stub(awsDeploy.sdk, 'request').returns(BbPromise.resolve());
sinon.stub(awsDeploy.aws, 'request').returns(BbPromise.resolve());
expect(() => awsDeploy.uploadZipFile(null)).to.throw(Error);
});
it('should throw for empty artifact paths', () => {
sinon.stub(awsDeploy.sdk, 'request').returns(BbPromise.resolve());
sinon.stub(awsDeploy.aws, 'request').returns(BbPromise.resolve());
expect(() => awsDeploy.uploadZipFile('')).to.throw(Error);
});
@ -68,7 +70,7 @@ describe('uploadArtifacts', () => {
const artifactFileBuffer = serverless.utils.readFileSync(artifactFilePath);
const putObjectStub = sinon
.stub(awsDeploy.sdk, 'request').returns(BbPromise.resolve());
.stub(awsDeploy.aws, 'request').returns(BbPromise.resolve());
return awsDeploy.uploadZipFile(artifactFilePath).then(() => {
expect(putObjectStub.calledOnce).to.be.equal(true);
@ -82,7 +84,7 @@ describe('uploadArtifacts', () => {
.to.be.equal(artifactFileBuffer.toString());
expect(putObjectStub.calledWith(awsDeploy.options.stage, awsDeploy.options.region));
awsDeploy.sdk.request.restore();
awsDeploy.aws.request.restore();
});
});
});

View File

@ -2,7 +2,6 @@
const BbPromise = require('bluebird');
const fs = require('fs');
const SDK = require('../');
const validate = require('../lib/validate');
// The Package plugin which is used to zip the service
@ -13,7 +12,7 @@ class AwsDeployFunction {
this.serverless = serverless;
this.options = options || {};
this.provider = 'aws';
this.sdk = new SDK(serverless);
this.aws = this.serverless.getProvider(this.provider);
this.pkg = new Package(this.serverless, this.options);
@ -38,7 +37,7 @@ class AwsDeployFunction {
FunctionName: this.options.functionObj.name,
};
this.sdk.request(
this.aws.request(
'Lambda',
'getFunction',
params,
@ -69,7 +68,7 @@ class AwsDeployFunction {
ZipFile: data,
};
return this.sdk.request(
return this.aws.request(
'Lambda',
'updateFunctionCode',
params,

View File

@ -5,7 +5,8 @@ const sinon = require('sinon');
const path = require('path');
const fs = require('fs');
const Package = require('../../../package');
const AwsDeployFunction = require('../');
const AwsProvider = require('../../../awsProvider/awsProvider');
const AwsDeployFunction = require('../index');
const Serverless = require('../../../../Serverless');
const BbPromise = require('bluebird');
const testUtils = require('../../../../../tests/utils');
@ -44,6 +45,7 @@ describe('AwsDeployFunction', () => {
},
};
serverless.init();
serverless.setProvider('aws', new AwsProvider(serverless));
awsDeployFunction = new AwsDeployFunction(serverless, options);
});
@ -60,6 +62,8 @@ describe('AwsDeployFunction', () => {
});
it('should run promise chain in order', () => {
const validateStub = sinon
.stub(awsDeployFunction, 'validate').returns(BbPromise.resolve());
const checkIfFunctionExistsStub = sinon
.stub(awsDeployFunction, 'checkIfFunctionExists').returns(BbPromise.resolve());
const zipFunctionStub = sinon
@ -70,13 +74,15 @@ describe('AwsDeployFunction', () => {
.stub(awsDeployFunction, 'cleanup').returns(BbPromise.resolve());
return awsDeployFunction.hooks['deploy:function:deploy']().then(() => {
expect(checkIfFunctionExistsStub.calledOnce).to.be.equal(true);
expect(validateStub.calledOnce).to.equal(true);
expect(checkIfFunctionExistsStub.calledAfter(validateStub))
.to.equal(true);
expect(zipFunctionStub.calledAfter(checkIfFunctionExistsStub))
.to.be.equal(true);
.to.equal(true);
expect(deployFunctionStub.calledAfter(zipFunctionStub))
.to.be.equal(true);
.to.equal(true);
expect(cleanupStub.calledAfter(deployFunctionStub))
.to.be.equal(true);
.to.equal(true);
awsDeployFunction.checkIfFunctionExists.restore();
awsDeployFunction.zipFunction.restore();
@ -94,7 +100,7 @@ describe('AwsDeployFunction', () => {
it('should check if the function is deployed', () => {
const getFunctionStub = sinon
.stub(awsDeployFunction.sdk, 'request').returns(BbPromise.resolve());
.stub(awsDeployFunction.aws, 'request').returns(BbPromise.resolve());
awsDeployFunction.serverless.service.functions = {
first: {
@ -111,7 +117,7 @@ describe('AwsDeployFunction', () => {
expect(getFunctionStub.args[0][0]).to.be.equal('Lambda');
expect(getFunctionStub.args[0][1]).to.be.equal('getFunction');
expect(getFunctionStub.args[0][2].FunctionName).to.be.equal('first');
awsDeployFunction.sdk.request.restore();
awsDeployFunction.aws.request.restore();
});
});
});
@ -145,7 +151,7 @@ describe('AwsDeployFunction', () => {
awsDeployFunction.options.functionObj.artifact = artifactFilePath;
const updateFunctionCodeStub = sinon
.stub(awsDeployFunction.sdk, 'request').returns(BbPromise.resolve());
.stub(awsDeployFunction.aws, 'request').returns(BbPromise.resolve());
return awsDeployFunction.deployFunction().then(() => {
const data = fs.readFileSync(artifactFilePath);
@ -158,7 +164,7 @@ describe('AwsDeployFunction', () => {
expect(updateFunctionCodeStub.args[0][1]).to.be.equal('updateFunctionCode');
expect(updateFunctionCodeStub.args[0][2].FunctionName).to.be.equal('first');
expect(updateFunctionCodeStub.args[0][2].ZipFile).to.deep.equal(data);
awsDeployFunction.sdk.request.restore();
awsDeployFunction.aws.request.restore();
});
});
});

View File

@ -2,16 +2,15 @@
const BbPromise = require('bluebird');
const validate = require('../lib/validate');
const SDK = require('../');
const chalk = require('chalk');
const _ = require('lodash');
class AwsInfo {
constructor(serverless, options) {
this.serverless = serverless;
this.options = options || {};
this.provider = 'aws';
this.sdk = new SDK(serverless);
this.aws = this.serverless.getProvider(this.provider);
this.options = options || {};
Object.assign(this, validate);
this.hooks = {
@ -37,7 +36,7 @@ class AwsInfo {
* Gather information about the service
*/
gather() {
const stackName = this.sdk.getStackName(this.options.stage);
const stackName = this.aws.getStackName(this.options.stage);
const info = {
service: this.serverless.service.service,
stage: this.options.stage,
@ -45,7 +44,7 @@ class AwsInfo {
};
// Get info from CloudFormation Outputs
return this.sdk.request('CloudFormation',
return this.aws.request('CloudFormation',
'describeStacks',
{ StackName: stackName },
this.options.stage,
@ -113,7 +112,7 @@ class AwsInfo {
const apiKeyNames = this.serverless.service.provider.apiKeys || [];
if (apiKeyNames.length) {
return this.sdk.request('APIGateway',
return this.aws.request('APIGateway',
'getApiKeys',
{ includeValues: true },
this.options.stage,

View File

@ -3,6 +3,7 @@
const expect = require('chai').expect;
const sinon = require('sinon');
const AwsInfo = require('../');
const AwsProvider = require('../../../awsProvider/awsProvider');
const Serverless = require('../../../../Serverless');
const CLI = require('../../../../classes/CLI');
const BbPromise = require('bluebird');
@ -10,6 +11,7 @@ const chalk = require('chalk');
describe('AwsInfo', () => {
const serverless = new Serverless();
serverless.setProvider('aws', new AwsProvider(serverless));
serverless.service.functions = {
function1: {
events: [
@ -158,7 +160,7 @@ describe('AwsInfo', () => {
],
};
const describeStackStub = sinon.stub(awsInfo.sdk, 'request')
const describeStackStub = sinon.stub(awsInfo.aws, 'request')
.returns(BbPromise.resolve(describeStacksResponse));
it('should gather with correct params', () => awsInfo.gather()
@ -167,7 +169,7 @@ describe('AwsInfo', () => {
expect(describeStackStub.args[0][0]).to.equal('CloudFormation');
expect(describeStackStub.args[0][1]).to.equal('describeStacks');
expect(describeStackStub.args[0][2].StackName)
.to.equal(awsInfo.sdk.getStackName(awsInfo.options.stage));
.to.equal(awsInfo.aws.getStackName(awsInfo.options.stage));
expect(describeStackStub
.calledWith(awsInfo.options.stage, awsInfo.options.region));
})
@ -219,7 +221,7 @@ describe('AwsInfo', () => {
});
it("should provide only general info when stack doesn't exist (ValidationError)", () => {
awsInfo.sdk.request.restore();
awsInfo.aws.request.restore();
serverless.service.service = 'my-first';
const validationError = {
@ -227,7 +229,7 @@ describe('AwsInfo', () => {
message: 'Stack with id not-created-service does not exist',
};
sinon.stub(awsInfo.sdk, 'request').returns(BbPromise.reject(validationError));
sinon.stub(awsInfo.aws, 'request').returns(BbPromise.reject(validationError));
const expectedInfo = {
service: 'my-first',
@ -241,8 +243,8 @@ describe('AwsInfo', () => {
});
it('should throw a ServerlessError when AWS sdk throws an error', () => {
awsInfo.sdk.request.restore();
sinon.stub(awsInfo.sdk, 'request').returns(BbPromise.reject(Error));
awsInfo.aws.request.restore();
sinon.stub(awsInfo.aws, 'request').returns(BbPromise.reject(Error));
return awsInfo.gather().catch((e) => {
expect(e.name).to.equal('ServerlessError');
@ -253,7 +255,7 @@ describe('AwsInfo', () => {
describe('#getApiKeyValues()', () => {
it('should return the api keys in the info object', () => {
// TODO: implement a pattern for stub restoring to get rid of this
awsInfo.sdk.request.restore();
awsInfo.aws.request.restore();
// set the API Keys for the service
awsInfo.serverless.service.provider.apiKeys = ['foo', 'bar'];
@ -295,14 +297,14 @@ describe('AwsInfo', () => {
};
const getApiKeysStub = sinon
.stub(awsInfo.sdk, 'request')
.stub(awsInfo.aws, 'request')
.returns(BbPromise.resolve(apiKeyItems));
return awsInfo.getApiKeyValues(gatheredData).then((result) => {
expect(getApiKeysStub.calledOnce).to.equal(true);
expect(result.info.apiKeys).to.deep.equal(gatheredDataAfterKeyLookup.info.apiKeys);
awsInfo.sdk.request.restore();
awsInfo.aws.request.restore();
});
});
@ -317,14 +319,14 @@ describe('AwsInfo', () => {
};
const getApiKeysStub = sinon
.stub(awsInfo.sdk, 'request')
.stub(awsInfo.aws, 'request')
.returns(BbPromise.resolve());
return awsInfo.getApiKeyValues(gatheredData).then((result) => {
expect(getApiKeysStub.calledOnce).to.equal(false);
expect(result).to.deep.equal(gatheredData);
awsInfo.sdk.request.restore();
awsInfo.aws.request.restore();
});
});
});

View File

@ -3,7 +3,6 @@
const BbPromise = require('bluebird');
const chalk = require('chalk');
const path = require('path');
const SDK = require('../');
const moment = require('moment');
const validate = require('../lib/validate');
@ -12,7 +11,7 @@ class AwsInvoke {
this.serverless = serverless;
this.options = options || {};
this.provider = 'aws';
this.sdk = new SDK(serverless);
this.aws = this.serverless.getProvider(this.provider);
Object.assign(this, validate);
@ -58,7 +57,7 @@ class AwsInvoke {
Payload: new Buffer(JSON.stringify(this.options.data || {})),
};
return this.sdk.request('Lambda', 'invoke', params, this.options.stage, this.options.region);
return this.aws.request('Lambda', 'invoke', params, this.options.stage, this.options.region);
}
log(invocationReply) {

View File

@ -4,12 +4,14 @@ const expect = require('chai').expect;
const sinon = require('sinon');
const path = require('path');
const AwsInvoke = require('../');
const AwsProvider = require('../../../awsProvider/awsProvider');
const Serverless = require('../../../../Serverless');
const BbPromise = require('bluebird');
const testUtils = require('../../../../../tests/utils');
describe('AwsInvoke', () => {
const serverless = new Serverless();
serverless.setProvider('aws', new AwsProvider(serverless));
const options = {
stage: 'dev',
region: 'us-east-1',
@ -136,7 +138,7 @@ describe('AwsInvoke', () => {
describe('#invoke()', () => {
let invokeStub;
beforeEach(() => {
invokeStub = sinon.stub(awsInvoke.sdk, 'request').returns(BbPromise.resolve());
invokeStub = sinon.stub(awsInvoke.aws, 'request').returns(BbPromise.resolve());
awsInvoke.serverless.service.service = 'new-service';
awsInvoke.options = {
stage: 'dev',
@ -155,7 +157,7 @@ describe('AwsInvoke', () => {
expect(invokeStub.args[0][2].InvocationType).to.be.equal('RequestResponse');
expect(invokeStub.args[0][2].LogType).to.be.equal('None');
expect(typeof invokeStub.args[0][2].Payload).to.not.be.equal('undefined');
awsInvoke.sdk.request.restore();
awsInvoke.aws.request.restore();
})
);
@ -169,7 +171,7 @@ describe('AwsInvoke', () => {
expect(invokeStub.args[0][2].InvocationType).to.be.equal('RequestResponse');
expect(invokeStub.args[0][2].LogType).to.be.equal('Tail');
expect(typeof invokeStub.args[0][2].Payload).to.not.be.equal('undefined');
awsInvoke.sdk.request.restore();
awsInvoke.aws.request.restore();
});
});
@ -183,7 +185,7 @@ describe('AwsInvoke', () => {
expect(invokeStub.args[0][2].InvocationType).to.be.equal('OtherType');
expect(invokeStub.args[0][2].LogType).to.be.equal('None');
expect(typeof invokeStub.args[0][2].Payload).to.not.be.equal('undefined');
awsInvoke.sdk.request.restore();
awsInvoke.aws.request.restore();
});
});
});

View File

@ -35,7 +35,7 @@ module.exports = {
const params = {
StackName: cfData.StackId,
};
return this.sdk.request('CloudFormation',
return this.aws.request('CloudFormation',
'describeStackEvents',
params,
this.options.stage,

View File

@ -3,7 +3,6 @@
const BbPromise = require('bluebird');
const chalk = require('chalk');
const _ = require('lodash');
const SDK = require('../');
const os = require('os');
const moment = require('moment');
const validate = require('../lib/validate');
@ -13,7 +12,7 @@ class AwsLogs {
this.serverless = serverless;
this.options = options || {};
this.provider = 'aws';
this.sdk = new SDK(serverless);
this.aws = this.serverless.getProvider(this.provider);
Object.assign(this, validate);
@ -45,7 +44,7 @@ class AwsLogs {
orderBy: 'LastEventTime',
};
return this.sdk
return this.aws
.request('CloudWatchLogs',
'describeLogStreams',
params,
@ -120,7 +119,7 @@ class AwsLogs {
}
}
return this.sdk
return this.aws
.request('CloudWatchLogs',
'filterLogEvents',
params,

View File

@ -2,6 +2,7 @@
const expect = require('chai').expect;
const sinon = require('sinon');
const AwsProvider = require('../../../awsProvider/awsProvider');
const AwsLogs = require('../');
const Serverless = require('../../../../Serverless');
const BbPromise = require('bluebird');
@ -17,6 +18,7 @@ describe('AwsLogs', () => {
function: 'first',
};
serverless = new Serverless();
serverless.setProvider('aws', new AwsProvider(serverless));
awsLogs = new AwsLogs(serverless, options);
});
@ -114,7 +116,7 @@ describe('AwsLogs', () => {
},
],
};
const getLogStreamsStub = sinon.stub(awsLogs.sdk, 'request').returns(
const getLogStreamsStub = sinon.stub(awsLogs.aws, 'request').returns(
BbPromise.resolve(replyMock)
);
@ -137,20 +139,20 @@ describe('AwsLogs', () => {
expect(logStreamNames[1])
.to.be.equal('2016/07/28/[$LATEST]83f5206ab2a8488290349b9c1fbfe2ba');
awsLogs.sdk.request.restore();
awsLogs.aws.request.restore();
});
});
it('should throw error if no log streams found', () => {
sinon.stub(awsLogs.sdk, 'request').returns(BbPromise.resolve());
sinon.stub(awsLogs.aws, 'request').returns(BbPromise.resolve());
return awsLogs.getLogStreams()
.then(() => {
expect(1).to.equal(2);
awsLogs.sdk.request.restore();
awsLogs.aws.request.restore();
}).catch(e => {
expect(e.name).to.be.equal('ServerlessError');
awsLogs.sdk.request.restore();
awsLogs.aws.request.restore();
});
});
});
@ -175,7 +177,7 @@ describe('AwsLogs', () => {
'2016/07/28/[$LATEST]83f5206ab2a8488290349b9c1fbfe2ba',
'2016/07/28/[$LATEST]83f5206ab2a8488290349b9c1fbfe2ba',
];
const filterLogEventsStub = sinon.stub(awsLogs.sdk, 'request').returns(
const filterLogEventsStub = sinon.stub(awsLogs.aws, 'request').returns(
BbPromise.resolve(replyMock)
);
awsLogs.serverless.service.service = 'new-service';
@ -201,7 +203,7 @@ describe('AwsLogs', () => {
expect(filterLogEventsStub.args[0][2].logStreamNames).to.deep.equal(logStreamNamesMock);
expect(filterLogEventsStub.args[0][2].filterPattern).to.be.equal('error');
expect(typeof filterLogEventsStub.args[0][2].startTime).to.be.equal('number');
awsLogs.sdk.request.restore();
awsLogs.aws.request.restore();
});
});
@ -224,7 +226,7 @@ describe('AwsLogs', () => {
'2016/07/28/[$LATEST]83f5206ab2a8488290349b9c1fbfe2ba',
'2016/07/28/[$LATEST]83f5206ab2a8488290349b9c1fbfe2ba',
];
const filterLogEventsStub = sinon.stub(awsLogs.sdk, 'request').returns(
const filterLogEventsStub = sinon.stub(awsLogs.aws, 'request').returns(
BbPromise.resolve(replyMock)
);
awsLogs.serverless.service.service = 'new-service';
@ -250,7 +252,7 @@ describe('AwsLogs', () => {
expect(filterLogEventsStub.args[0][2].logStreamNames).to.deep.equal(logStreamNamesMock);
expect(filterLogEventsStub.args[0][2].filterPattern).to.be.equal('error');
expect(typeof filterLogEventsStub.args[0][2].startTime).to.be.equal('number');
awsLogs.sdk.request.restore();
awsLogs.aws.request.restore();
});
});
});

View File

@ -6,14 +6,12 @@ const monitorStack = require('../lib/monitorStack');
const emptyS3Bucket = require('./lib/bucket');
const removeStack = require('./lib/stack');
const SDK = require('../');
class AwsRemove {
constructor(serverless, options) {
this.serverless = serverless;
this.options = options || {};
this.provider = 'aws';
this.sdk = new SDK(serverless);
this.aws = this.serverless.getProvider(this.provider);
Object.assign(this, validate, emptyS3Bucket, removeStack, monitorStack);

View File

@ -4,7 +4,7 @@ const BbPromise = require('bluebird');
module.exports = {
setServerlessDeploymentBucketName() {
return this.sdk.getServerlessDeploymentBucketName(this.options.stage, this.options.region)
return this.aws.getServerlessDeploymentBucketName(this.options.stage, this.options.region)
.then((bucketName) => {
this.bucketName = bucketName;
});
@ -15,7 +15,7 @@ module.exports = {
this.serverless.cli.log('Getting all objects in S3 bucket...');
const serviceStage = `${this.serverless.service.service}/${this.options.stage}`;
return this.sdk.request('S3', 'listObjectsV2', {
return this.aws.request('S3', 'listObjectsV2', {
Bucket: this.bucketName,
Prefix: `serverless/${serviceStage}`,
}, this.options.stage, this.options.region).then((result) => {
@ -33,7 +33,7 @@ module.exports = {
deleteObjects() {
this.serverless.cli.log('Removing objects in S3 bucket...');
if (this.objectsInBucket.length) {
return this.sdk.request('S3', 'deleteObjects', {
return this.aws.request('S3', 'deleteObjects', {
Bucket: this.bucketName,
Delete: {
Objects: this.objectsInBucket,

View File

@ -13,7 +13,7 @@ module.exports = {
StackId: stackName,
};
return this.sdk.request('CloudFormation',
return this.aws.request('CloudFormation',
'deleteStack',
params,
this.options.stage,

View File

@ -2,12 +2,14 @@
const expect = require('chai').expect;
const sinon = require('sinon');
const AwsProvider = require('../../../awsProvider/awsProvider');
const AwsRemove = require('../index');
const Serverless = require('../../../../Serverless');
const BbPromise = require('bluebird');
describe('emptyS3Bucket', () => {
const serverless = new Serverless();
serverless.setProvider('aws', new AwsProvider(serverless));
let awsRemove;
@ -23,7 +25,7 @@ describe('emptyS3Bucket', () => {
describe('#setServerlessDeploymentBucketName()', () => {
it('should store the name of the Serverless deployment bucket in the "this" variable', () => {
const getServerlessDeploymentBucketNameStub = sinon
.stub(awsRemove.sdk, 'getServerlessDeploymentBucketName')
.stub(awsRemove.aws, 'getServerlessDeploymentBucketName')
.returns(BbPromise.resolve('new-service-dev-us-east-1-12345678'));
return awsRemove.setServerlessDeploymentBucketName().then(() => {
@ -31,14 +33,14 @@ describe('emptyS3Bucket', () => {
expect(getServerlessDeploymentBucketNameStub.calledOnce).to.be.equal(true);
expect(getServerlessDeploymentBucketNameStub
.calledWith(awsRemove.options.stage, awsRemove.options.region));
awsRemove.sdk.getServerlessDeploymentBucketName.restore();
awsRemove.aws.getServerlessDeploymentBucketName.restore();
});
});
});
describe('#listObjects()', () => {
it('should resolve if no objects are present', () => {
const listObjectsStub = sinon.stub(awsRemove.sdk, 'request')
const listObjectsStub = sinon.stub(awsRemove.aws, 'request')
.returns(BbPromise.resolve());
return awsRemove.listObjects().then(() => {
@ -49,12 +51,12 @@ describe('emptyS3Bucket', () => {
expect(listObjectsStub.args[0][2].Bucket)
.to.be.equal(awsRemove.bucketName);
expect(awsRemove.objectsInBucket.length).to.equal(0);
awsRemove.sdk.request.restore();
awsRemove.aws.request.restore();
});
});
it('should push objects to the array if present', () => {
const listObjectsStub = sinon.stub(awsRemove.sdk, 'request')
const listObjectsStub = sinon.stub(awsRemove.aws, 'request')
.returns(BbPromise.resolve({
Contents: [
{ Key: 'object1' },
@ -71,7 +73,7 @@ describe('emptyS3Bucket', () => {
.to.be.equal(awsRemove.bucketName);
expect(awsRemove.objectsInBucket[0]).to.deep.equal({ Key: 'object1' });
expect(awsRemove.objectsInBucket[1]).to.deep.equal({ Key: 'object2' });
awsRemove.sdk.request.restore();
awsRemove.aws.request.restore();
});
});
});
@ -80,7 +82,7 @@ describe('emptyS3Bucket', () => {
it('should delete all objects in the S3 bucket', () => {
awsRemove.objectsInBucket = [{ Key: 'foo' }];
const deleteObjectsStub = sinon.stub(awsRemove.sdk, 'request')
const deleteObjectsStub = sinon.stub(awsRemove.aws, 'request')
.returns(BbPromise.resolve());
return awsRemove.deleteObjects().then(() => {
@ -90,7 +92,7 @@ describe('emptyS3Bucket', () => {
.to.be.equal(awsRemove.bucketName);
expect(deleteObjectsStub.args[0][2].Delete.Objects)
.to.be.equal(awsRemove.objectsInBucket);
awsRemove.sdk.request.restore();
awsRemove.aws.request.restore();
});
});

View File

@ -2,12 +2,14 @@
const expect = require('chai').expect;
const sinon = require('sinon');
const AwsProvider = require('../../../awsProvider/awsProvider');
const AwsRemove = require('../index');
const Serverless = require('../../../../Serverless');
const BbPromise = require('bluebird');
describe('removeStack', () => {
const serverless = new Serverless();
serverless.setProvider('aws', new AwsProvider(serverless));
let awsRemove;
@ -23,12 +25,12 @@ describe('removeStack', () => {
describe('#remove()', () => {
it('should remove a stack', () => {
const removeStackStub = sinon
.stub(awsRemove.sdk, 'request').returns(BbPromise.resolve());
.stub(awsRemove.aws, 'request').returns(BbPromise.resolve());
return awsRemove.remove().then(() => {
expect(removeStackStub.calledOnce).to.be.equal(true);
expect(removeStackStub.calledWith(awsRemove.options.stage, awsRemove.options.region));
awsRemove.sdk.request.restore();
awsRemove.aws.request.restore();
});
});
});

View File

@ -4,7 +4,7 @@ const expect = require('chai').expect;
const sinon = require('sinon');
const BbPromise = require('bluebird');
const Serverless = require('../../../Serverless');
const SDK = require('../index');
const AwsProvider = require('../../awsProvider/awsProvider');
const CLI = require('../../../classes/CLI');
const monitorStack = require('../lib/monitorStack');
@ -14,7 +14,7 @@ describe('monitorStack', () => {
beforeEach(() => {
awsPlugin.serverless = serverless;
awsPlugin.sdk = new SDK(serverless);
awsPlugin.aws = new AwsProvider(serverless);
awsPlugin.serverless.cli = new CLI(serverless);
awsPlugin.options = {
stage: 'dev',
@ -27,28 +27,28 @@ describe('monitorStack', () => {
describe('#monitorStack()', () => {
it('should skip monitoring if the --noDeploy option is specified', () => {
awsPlugin.options.noDeploy = true;
const describeStackEventsStub = sinon.stub(awsPlugin.sdk, 'request');
const describeStackEventsStub = sinon.stub(awsPlugin.aws, 'request');
const cfDataMock = {
StackId: 'new-service-dev',
};
return awsPlugin.monitorStack('update', cfDataMock, 10).then(() => {
expect(describeStackEventsStub.callCount).to.be.equal(0);
awsPlugin.sdk.request.restore();
awsPlugin.aws.request.restore();
});
});
it('should skip monitoring if the stack was already created', () => {
const describeStackEventsStub = sinon.stub(awsPlugin.sdk, 'request');
const describeStackEventsStub = sinon.stub(awsPlugin.aws, 'request');
return awsPlugin.monitorStack('update', 'alreadyCreated', 10).then(() => {
expect(describeStackEventsStub.callCount).to.be.equal(0);
awsPlugin.sdk.request.restore();
awsPlugin.aws.request.restore();
});
});
it('should keep monitoring until CREATE_COMPLETE stack status', () => {
const describeStackEventsStub = sinon.stub(awsPlugin.sdk, 'request');
const describeStackEventsStub = sinon.stub(awsPlugin.aws, 'request');
const cfDataMock = {
StackId: 'new-service-dev',
};
@ -87,12 +87,12 @@ describe('monitorStack', () => {
awsPlugin.options.region
));
expect(stackStatus).to.be.equal('CREATE_COMPLETE');
awsPlugin.sdk.request.restore();
awsPlugin.aws.request.restore();
});
});
it('should keep monitoring until UPDATE_COMPLETE stack status', () => {
const describeStackEventsStub = sinon.stub(awsPlugin.sdk, 'request');
const describeStackEventsStub = sinon.stub(awsPlugin.aws, 'request');
const cfDataMock = {
StackId: 'new-service-dev',
};
@ -131,12 +131,12 @@ describe('monitorStack', () => {
awsPlugin.options.region
));
expect(stackStatus).to.be.equal('UPDATE_COMPLETE');
awsPlugin.sdk.request.restore();
awsPlugin.aws.request.restore();
});
});
it('should keep monitoring until DELETE_COMPLETE stack status', () => {
const describeStackEventsStub = sinon.stub(awsPlugin.sdk, 'request');
const describeStackEventsStub = sinon.stub(awsPlugin.aws, 'request');
const cfDataMock = {
StackId: 'new-service-dev',
};
@ -175,12 +175,12 @@ describe('monitorStack', () => {
awsPlugin.options.region
));
expect(stackStatus).to.be.equal('DELETE_COMPLETE');
awsPlugin.sdk.request.restore();
awsPlugin.aws.request.restore();
});
});
it('should keep monitoring until DELETE_COMPLETE or stack not found catch', () => {
const describeStackEventsStub = sinon.stub(awsPlugin.sdk, 'request');
const describeStackEventsStub = sinon.stub(awsPlugin.aws, 'request');
const cfDataMock = {
StackId: 'new-service-dev',
};
@ -211,13 +211,13 @@ describe('monitorStack', () => {
awsPlugin.options.region
));
expect(stackStatus).to.be.equal('DELETE_COMPLETE');
awsPlugin.sdk.request.restore();
awsPlugin.aws.request.restore();
});
});
it('should output all stack events information with the --verbose option', () => {
awsPlugin.options.verbose = true;
const describeStackEventsStub = sinon.stub(awsPlugin.sdk, 'request');
const describeStackEventsStub = sinon.stub(awsPlugin.aws, 'request');
const cfDataMock = {
StackId: 'new-service-dev',
};
@ -283,12 +283,12 @@ describe('monitorStack', () => {
awsPlugin.options.stage,
awsPlugin.options.region
));
awsPlugin.sdk.request.restore();
awsPlugin.aws.request.restore();
});
});
it('should catch describeStackEvents error if stack was not in deleting state', () => {
const describeStackEventsStub = sinon.stub(awsPlugin.sdk, 'request');
const describeStackEventsStub = sinon.stub(awsPlugin.aws, 'request');
const cfDataMock = {
StackId: 'new-service-dev',
};
@ -307,12 +307,12 @@ describe('monitorStack', () => {
awsPlugin.options.stage,
awsPlugin.options.region
));
awsPlugin.sdk.request.restore();
awsPlugin.aws.request.restore();
});
});
it('should throw an error and exit immediataley if statck status is *_FAILED', () => {
const describeStackEventsStub = sinon.stub(awsPlugin.sdk, 'request');
const describeStackEventsStub = sinon.stub(awsPlugin.aws, 'request');
const cfDataMock = {
StackId: 'new-service-dev',
};
@ -380,7 +380,7 @@ describe('monitorStack', () => {
awsPlugin.options.stage,
awsPlugin.options.region
));
awsPlugin.sdk.request.restore();
awsPlugin.aws.request.restore();
});
});
});

View File

@ -70,11 +70,12 @@ const impl = {
},
};
class SDK {
class AwsProvider {
constructor(serverless) {
// Defaults
this.sdk = AWS;
this.serverless = serverless;
this.sdk = AWS;
this.serverless.setProvider('aws', this);
// Use HTTPS Proxy (Optional)
const proxy = process.env.proxy
@ -187,4 +188,4 @@ class SDK {
}
}
module.exports = SDK;
module.exports = AwsProvider;

View File

@ -3,12 +3,12 @@
const sinon = require('sinon');
const BbPromise = require('bluebird');
const expect = require('chai').expect;
const Serverless = require('../../../Serverless');
const AwsSdk = require('../');
const Serverless = require('../../Serverless');
const AwsProvider = require('./awsProvider');
const proxyquire = require('proxyquire');
describe('AWS SDK', () => {
let awsSdk;
describe('AwsProvider', () => {
let awsProvider;
let serverless;
beforeEach(() => {
@ -17,24 +17,24 @@ describe('AWS SDK', () => {
region: 'us-east-1',
};
serverless = new Serverless(options);
awsSdk = new AwsSdk(serverless, options);
awsSdk.serverless.cli = new serverless.classes.CLI();
awsProvider = new AwsProvider(serverless, options);
awsProvider.serverless.cli = new serverless.classes.CLI();
});
describe('#constructor()', () => {
it('should set AWS instance', () => {
expect(typeof awsSdk.sdk).to.not.equal('undefined');
expect(typeof awsProvider.sdk).to.not.equal('undefined');
});
it('should set Serverless instance', () => {
expect(typeof awsSdk.serverless).to.not.equal('undefined');
expect(typeof awsProvider.serverless).to.not.equal('undefined');
});
it('should set AWS proxy', () => {
process.env.proxy = 'http://a.b.c.d:n';
const newAwsSdk = new AwsSdk(serverless);
const newAwsProvider = new AwsProvider(serverless);
expect(typeof newAwsSdk.sdk.config.httpOptions.agent).to.not.equal('undefined');
expect(typeof newAwsProvider.sdk.config.httpOptions.agent).to.not.equal('undefined');
// clear env
delete process.env.proxy;
@ -42,9 +42,9 @@ describe('AWS SDK', () => {
it('should set AWS timeout', () => {
process.env.AWS_CLIENT_TIMEOUT = '120000';
const newAwsSdk = new AwsSdk(serverless);
const newAwsProvider = new AwsProvider(serverless);
expect(typeof newAwsSdk.sdk.config.httpOptions.timeout).to.not.equal('undefined');
expect(typeof newAwsProvider.sdk.config.httpOptions.timeout).to.not.equal('undefined');
// clear env
delete process.env.AWS_CLIENT_TIMEOUT;
@ -65,10 +65,10 @@ describe('AWS SDK', () => {
};
}
}
awsSdk.sdk = {
awsProvider.sdk = {
S3: FakeS3,
};
awsSdk.serverless.service.environment = {
awsProvider.serverless.service.environment = {
vars: {},
stages: {
dev: {
@ -80,7 +80,7 @@ describe('AWS SDK', () => {
},
};
return awsSdk.request('S3', 'putObject', {}, 'dev', 'us-east-1').then(data => {
return awsProvider.request('S3', 'putObject', {}, 'dev', 'us-east-1').then(data => {
expect(data.called).to.equal(true);
});
});
@ -110,10 +110,10 @@ describe('AWS SDK', () => {
};
}
}
awsSdk.sdk = {
awsProvider.sdk = {
S3: FakeS3,
};
awsSdk.request('S3', 'error', {}, 'dev', 'us-east-1')
awsProvider.request('S3', 'error', {}, 'dev', 'us-east-1')
.then(data => {
// eslint-disable-next-line no-unused-expressions
expect(data).to.exist;
@ -142,10 +142,10 @@ describe('AWS SDK', () => {
};
}
}
awsSdk.sdk = {
awsProvider.sdk = {
S3: FakeS3,
};
awsSdk.request('S3', 'error', {}, 'dev', 'us-east-1')
awsProvider.request('S3', 'error', {}, 'dev', 'us-east-1')
.then(() => done('Should not succeed'))
.catch(() => done());
});
@ -168,10 +168,10 @@ describe('AWS SDK', () => {
};
}
}
awsSdk.sdk = {
awsProvider.sdk = {
S3: FakeS3,
};
awsSdk.request('S3', 'error', {}, 'dev', 'us-east-1')
awsProvider.request('S3', 'error', {}, 'dev', 'us-east-1')
.then(() => done('Should not succeed'))
.catch((err) => {
expect(err.message).to.contain('https://git.io/viZAC');
@ -188,36 +188,36 @@ describe('AWS SDK', () => {
return config;
};
const awsStub = sinon.stub().returns();
const AwsSdkProxyquired = proxyquire('../index.js', {
const AwsProviderProxyquired = proxyquire('./awsProvider.js', {
'aws-sdk': awsStub,
});
let newAwsSdk;
let newAwsProvider;
beforeEach(() => {
newAwsSdk = new AwsSdkProxyquired(serverless);
newAwsProvider = new AwsProviderProxyquired(serverless);
});
it('should set region for credentials', () => {
const credentials = newAwsSdk.getCredentials('teststage', 'testregion');
const credentials = newAwsProvider.getCredentials('teststage', 'testregion');
expect(credentials.region).to.equal('testregion');
});
it('should get credentials from provider', () => {
serverless.service.provider.profile = 'notDefault';
const credentials = newAwsSdk.getCredentials();
const credentials = newAwsProvider.getCredentials();
expect(credentials.credentials.profile).to.equal('notDefault');
});
it('should not set credentials if empty profile is set', () => {
serverless.service.provider.profile = '';
const credentials = mockCreds(newAwsSdk.getCredentials('teststage', 'testregion'));
const credentials = mockCreds(newAwsProvider.getCredentials('teststage', 'testregion'));
expect(credentials).to.eql({ region: 'testregion' });
});
it('should not set credentials if credentials is an empty object', () => {
serverless.service.provider.credentials = {};
const credentials = mockCreds(newAwsSdk.getCredentials('teststage', 'testregion'));
const credentials = mockCreds(newAwsProvider.getCredentials('teststage', 'testregion'));
expect(credentials).to.eql({ region: 'testregion' });
});
@ -227,7 +227,7 @@ describe('AWS SDK', () => {
secretAccessKey: undefined,
sessionToken: undefined,
};
const credentials = mockCreds(newAwsSdk.getCredentials('teststage', 'testregion'));
const credentials = mockCreds(newAwsProvider.getCredentials('teststage', 'testregion'));
expect(credentials).to.eql({ region: 'testregion' });
});
@ -237,7 +237,7 @@ describe('AWS SDK', () => {
secretAccessKey: '',
sessionToken: '',
};
const credentials = mockCreds(newAwsSdk.getCredentials('teststage', 'testregion'));
const credentials = mockCreds(newAwsProvider.getCredentials('teststage', 'testregion'));
expect(credentials).to.eql({ region: 'testregion' });
});
@ -255,7 +255,7 @@ describe('AWS SDK', () => {
secretAccessKey: 'secretAccessKey',
sessionToken: 'sessionToken',
};
const credentials = newAwsSdk.getCredentials('teststage', 'testregion');
const credentials = newAwsProvider.getCredentials('teststage', 'testregion');
expect(credentials.credentials).to.deep.eql(serverless.service.provider.credentials);
process.env.AWS_ACCESS_KEY_ID = tmpAccessKeyID;
@ -277,7 +277,7 @@ describe('AWS SDK', () => {
process.env.AWS_ACCESS_KEY_ID = testVal.accessKeyId;
process.env.AWS_SECRET_ACCESS_KEY = testVal.secretAccessKey;
process.env.AWS_SESSION_TOKEN = testVal.sessionToken;
const credentials = newAwsSdk.getCredentials('teststage', 'testregion');
const credentials = newAwsProvider.getCredentials('teststage', 'testregion');
process.env.AWS_ACCESS_KEY_ID = prevVal.accessKeyId;
process.env.AWS_SECRET_ACCESS_KEY = prevVal.secretAccessKey;
process.env.AWS_SESSION_TOKEN = prevVal.sessionToken;
@ -298,7 +298,7 @@ describe('AWS SDK', () => {
process.env.AWS_TESTSTAGE_ACCESS_KEY_ID = testVal.accessKeyId;
process.env.AWS_TESTSTAGE_SECRET_ACCESS_KEY = testVal.secretAccessKey;
process.env.AWS_TESTSTAGE_SESSION_TOKEN = testVal.sessionToken;
const credentials = newAwsSdk.getCredentials('teststage', 'testregion');
const credentials = newAwsProvider.getCredentials('teststage', 'testregion');
process.env.AWS_TESTSTAGE_ACCESS_KEY_ID = prevVal.accessKeyId;
process.env.AWS_TESTSTAGE_SECRET_ACCESS_KEY = prevVal.secretAccessKey;
process.env.AWS_TESTSTAGE_SESSION_TOKEN = prevVal.sessionToken;
@ -307,26 +307,26 @@ describe('AWS SDK', () => {
it('should not set credentials if profile is not set', () => {
serverless.service.provider.profile = undefined;
const credentials = mockCreds(newAwsSdk.getCredentials('teststage', 'testregion'));
const credentials = mockCreds(newAwsProvider.getCredentials('teststage', 'testregion'));
expect(credentials).to.eql({ region: 'testregion' });
});
it('should not set credentials if empty profile is set', () => {
serverless.service.provider.profile = '';
const credentials = mockCreds(newAwsSdk.getCredentials('teststage', 'testregion'));
const credentials = mockCreds(newAwsProvider.getCredentials('teststage', 'testregion'));
expect(credentials).to.eql({ region: 'testregion' });
});
it('should get credentials from provider declared profile', () => {
serverless.service.provider.profile = 'notDefault';
const credentials = newAwsSdk.getCredentials();
const credentials = newAwsProvider.getCredentials();
expect(credentials.credentials.profile).to.equal('notDefault');
});
it('should get credentials from environment declared for-all-stages profile', () => {
const prevVal = process.env.AWS_PROFILE;
process.env.AWS_PROFILE = 'notDefault';
const credentials = newAwsSdk.getCredentials();
const credentials = newAwsProvider.getCredentials();
process.env.AWS_PROFILE = prevVal;
expect(credentials.credentials.profile).to.equal('notDefault');
});
@ -334,7 +334,7 @@ describe('AWS SDK', () => {
it('should get credentials from environment declared stage-specific profile', () => {
const prevVal = process.env.AWS_TESTSTAGE_PROFILE;
process.env.AWS_TESTSTAGE_PROFILE = 'notDefault';
const credentials = newAwsSdk.getCredentials('teststage', 'testregion');
const credentials = newAwsProvider.getCredentials('teststage', 'testregion');
process.env.AWS_TESTSTAGE_PROFILE = prevVal;
expect(credentials.credentials.profile).to.equal('notDefault');
});
@ -348,25 +348,25 @@ describe('AWS SDK', () => {
};
const describeStackResourcesStub = sinon
.stub(awsSdk, 'request')
.stub(awsProvider, 'request')
.returns(BbPromise.resolve({
StackResourceDetail: {
PhysicalResourceId: 'serverlessDeploymentBucketName',
},
}));
return awsSdk.getServerlessDeploymentBucketName(options.stage, options.region)
return awsProvider.getServerlessDeploymentBucketName(options.stage, options.region)
.then((bucketName) => {
expect(describeStackResourcesStub.calledOnce).to.be.equal(true);
expect(describeStackResourcesStub.calledWith(options.stage, options.region));
expect(describeStackResourcesStub.args[0][0]).to.equal('CloudFormation');
expect(describeStackResourcesStub.args[0][1]).to.equal('describeStackResource');
expect(describeStackResourcesStub.args[0][2].StackName)
.to.equal(`${awsSdk.serverless.service.service}-${options.stage}`);
.to.equal(`${awsProvider.serverless.service.service}-${options.stage}`);
expect(bucketName).to.equal('serverlessDeploymentBucketName');
awsSdk.request.restore();
awsProvider.request.restore();
});
});
});
@ -375,7 +375,7 @@ describe('AWS SDK', () => {
it('should return the stack name', () => {
serverless.service.service = 'myservice';
expect(awsSdk.getStackName('dev')).to.equal('myservice-dev');
expect(awsProvider.getStackName('dev')).to.equal('myservice-dev');
});
});
});

View File

@ -1,7 +1,7 @@
'use strict';
// Serverless Core Tests
require('./classes/Serverless');
require('../lib/Serverless.test');
require('./classes/PluginManager');
require('./classes/Utils');
require('./classes/Config');
@ -22,7 +22,7 @@ require('../lib/plugins/package/tests/all');
require('../lib/plugins/slstats/tests/slstats');
// AWS Plugins Tests
require('../lib/plugins/aws/tests');
require('../lib/plugins/awsProvider/awsProvider.test');
require('../lib/plugins/aws/tests/validate');
require('../lib/plugins/aws/tests/monitorStack');
require('../lib/plugins/aws/info/tests');