mirror of
https://github.com/serverless/serverless.git
synced 2026-02-01 16:07:28 +00:00
basic deployCore functionality
This commit is contained in:
parent
0a1c19b02a
commit
26f534f481
@ -1,55 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
const AWS = require('aws-sdk');
|
||||
const BbPromise = require('bluebird');
|
||||
const Zip = require('node-zip');
|
||||
const deployCore = require('./lib/deployCore');
|
||||
|
||||
class Deploy {
|
||||
constructor(serverless) {
|
||||
class awsDeploy {
|
||||
constructor(serverless, options) {
|
||||
this.serverless = serverless;
|
||||
this.commands = {
|
||||
deploy: {
|
||||
usage: 'deploy lambda zip.',
|
||||
lifecycleEvents: [
|
||||
'deploy',
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
this.hooks = {
|
||||
'deploy:deploy': this.deploy,
|
||||
};
|
||||
|
||||
const config = {
|
||||
region: 'us-east-1',
|
||||
};
|
||||
this.Lambda = new AWS.Lambda(config);
|
||||
BbPromise.promisifyAll(this.Lambda, { suffix: 'Promised' });
|
||||
}
|
||||
|
||||
deploy(options) {
|
||||
this.options = options;
|
||||
const allPromises = [];
|
||||
this.serverless.service.getAllFunctions().forEach((f) => {
|
||||
const fConfig = this.serverless.service.getFunction(f);
|
||||
|
||||
const configParams = {
|
||||
FunctionName: `${this.serverless.service.service}-${f}`,
|
||||
Description: fConfig.description,
|
||||
Handler: fConfig.handler,
|
||||
MemorySize: fConfig.memory_size,
|
||||
Timeout: fConfig.timeout,
|
||||
};
|
||||
|
||||
allPromises.push(this.Lambda.updateFunctionConfigurationPromised(configParams));
|
||||
const codeParams = {
|
||||
FunctionName: `${this.serverless.service.service}-${f}`,
|
||||
ZipFile: new Zip(),
|
||||
};
|
||||
allPromises.push(this.Lambda.updateFunctionCodePromised(codeParams));
|
||||
});
|
||||
return BbPromise.all(allPromises);
|
||||
Object.assign(this, deployCore);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Deploy;
|
||||
module.exports = awsDeploy;
|
||||
|
||||
@ -1 +1,124 @@
|
||||
//
|
||||
'use strict';
|
||||
/*
|
||||
* check if stack already exists. resolve if it is.
|
||||
* get core cf template and add variables
|
||||
* create stack
|
||||
* monitor stack
|
||||
* add output vars
|
||||
*
|
||||
* TO MOCK:
|
||||
* this.options.region
|
||||
* this.options.stage
|
||||
* service name
|
||||
* serverlessEnvYaml
|
||||
*/
|
||||
|
||||
|
||||
const BbPromise = require('bluebird');
|
||||
const path = require('path');
|
||||
const _ = require('lodash');
|
||||
const async = require('async');
|
||||
const AWS = require('aws-sdk');
|
||||
|
||||
module.exports = {
|
||||
createStack() {
|
||||
const config = {
|
||||
region: this.options.region,
|
||||
};
|
||||
this.CloudFormation = new AWS.CloudFormation(config);
|
||||
BbPromise.promisifyAll(this.CloudFormation, { suffix: 'Promised' });
|
||||
|
||||
const stackName = `${this.serverless.service.service}-${this.options.stage}`;
|
||||
const coreCFTemplate = this.serverless.utils.readFileSync(
|
||||
path.join(this.serverless.config.serverlessPath, 'templates', 'core-cf.json')
|
||||
);
|
||||
|
||||
// set the necessary variables before creating stack
|
||||
coreCFTemplate
|
||||
.Resources
|
||||
.coreBucket
|
||||
.Properties
|
||||
.BucketName = `${this.serverless.service.service}-${this.options.region}`;
|
||||
coreCFTemplate
|
||||
.Resources
|
||||
.IamPolicyLambda
|
||||
.Properties
|
||||
.PolicyName = `${this.options.stage}-${this.serverless.service.service}-lambda`;
|
||||
coreCFTemplate
|
||||
.Resources
|
||||
.IamPolicyLambda
|
||||
.Properties
|
||||
.PolicyDocument
|
||||
.Statement[0]
|
||||
.Resource = `arn:aws:logs:${this.options.region}:*:*`;
|
||||
|
||||
const params = {
|
||||
StackName: stackName,
|
||||
OnFailure: 'DELETE',
|
||||
Capabilities: [
|
||||
'CAPABILITY_IAM',
|
||||
],
|
||||
Parameters: [],
|
||||
TemplateBody: JSON.stringify(coreCFTemplate),
|
||||
Tags: [{
|
||||
Key: 'STAGE',
|
||||
Value: this.options.stage,
|
||||
}],
|
||||
};
|
||||
|
||||
return this.CloudFormation.createStackPromised(params);
|
||||
},
|
||||
monitor(cfData, frequency) {
|
||||
const validStatuses = [
|
||||
'CREATE_COMPLETE',
|
||||
'CREATE_IN_PROGRESS',
|
||||
];
|
||||
|
||||
return new BbPromise((resolve, reject) => {
|
||||
let stackStatus = null;
|
||||
let stackData = null;
|
||||
|
||||
async.whilst(() => (stackStatus !== 'CREATE_COMPLETE'),
|
||||
(callback) => {
|
||||
setTimeout(() => {
|
||||
const params = {
|
||||
StackName: cfData.StackId,
|
||||
};
|
||||
return this.CloudFormation.describeStacksPromised(params)
|
||||
.then((data) => {
|
||||
stackData = data;
|
||||
stackStatus = stackData.Stacks[0].StackStatus;
|
||||
|
||||
if (!stackStatus || validStatuses.indexOf(stackStatus) === -1) {
|
||||
return reject(new this.serverless.classes
|
||||
.Error(`An error occurred while provisioning your cloudformation: ${stackData
|
||||
.Stacks[0].StackStatusReason}`));
|
||||
}
|
||||
return callback();
|
||||
});
|
||||
}, frequency || 5000);
|
||||
}, () => resolve(stackData.Stacks[0]));
|
||||
});
|
||||
},
|
||||
addOutputVars() {
|
||||
const serverlessEnvYamlPath = path
|
||||
.join(this.serverless.config.servicePath, 'serverless.env.yaml');
|
||||
return this.serverless.yamlParser.parse(serverlessEnvYamlPath).then(parsedServerlessEnvYaml => {
|
||||
const serverlessEnvYaml = parsedServerlessEnvYaml;
|
||||
cfData.Outputs.forEach((output) => {
|
||||
const varName = _.lowerFirst(output.OutputKey);
|
||||
serverlessEnvYaml.stages[this.options.stage]
|
||||
.regions[this.options.region].vars[varName] = output.OutputValue;
|
||||
});
|
||||
this.serverless.utils.writeFileSync(serverlessEnvYamlPath, serverlessEnvYaml);
|
||||
return BbPromise.resolve();
|
||||
});
|
||||
},
|
||||
deployCore() {
|
||||
// check if stack exists
|
||||
return BbPromise.bind(this)
|
||||
.then(this.createStack)
|
||||
.then(this.monitor)
|
||||
.then(this.addOutputVars);
|
||||
},
|
||||
};
|
||||
|
||||
12
lib/plugins/awsDeploy/tests/awsDeploy.js
Normal file
12
lib/plugins/awsDeploy/tests/awsDeploy.js
Normal file
@ -0,0 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
const AwsDeploy = require('../awsDeploy');
|
||||
const Serverless = require('../../../Serverless');
|
||||
|
||||
const awsDeploy = new AwsDeploy();
|
||||
|
||||
describe('test', () => {
|
||||
it('test case', () => {
|
||||
awsDeploy.deployCore();
|
||||
});
|
||||
});
|
||||
@ -1,93 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const expect = require('chai').expect;
|
||||
const sinon = require('sinon');
|
||||
const Deploy = require('../deploy');
|
||||
const Serverless = require('../../../Serverless');
|
||||
const serverless = new Serverless();
|
||||
|
||||
describe('Deploy', () => {
|
||||
let deploy;
|
||||
let configStub;
|
||||
let codeStub;
|
||||
|
||||
beforeEach(() => {
|
||||
deploy = new Deploy(serverless);
|
||||
configStub = sinon.stub(deploy.Lambda, 'updateFunctionConfigurationPromised');
|
||||
codeStub = sinon.stub(deploy.Lambda, 'updateFunctionCodePromised');
|
||||
serverless.service.service = 'myService';
|
||||
serverless.service.functions = {
|
||||
create: {
|
||||
handler: 'users.create',
|
||||
description: 'fake function',
|
||||
memory_size: 512,
|
||||
timeout: 6,
|
||||
},
|
||||
list: {
|
||||
handler: 'users.list',
|
||||
description: 'fake function',
|
||||
memory_size: 1024,
|
||||
timeout: 6,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
deploy.Lambda.updateFunctionConfigurationPromised.restore();
|
||||
deploy.Lambda.updateFunctionCodePromised.restore();
|
||||
});
|
||||
|
||||
describe('#constructor()', () => {
|
||||
it('should have commands', () => expect(deploy.commands).to.be.not.empty);
|
||||
|
||||
it('should have hooks', () => expect(deploy.hooks).to.be.not.empty);
|
||||
});
|
||||
|
||||
describe('#deploy()', () => {
|
||||
it('should update lambda', () => {
|
||||
deploy.deploy().then(() => {
|
||||
// both config calls
|
||||
expect(configStub.calledTwice).to.be.equal(true);
|
||||
|
||||
// first config call args
|
||||
expect(configStub.args[0][0].FunctionName)
|
||||
.to.be.equal('myService-create');
|
||||
expect(configStub.args[0][0].Description)
|
||||
.to.be.equal(serverless.service.functions.create.description);
|
||||
expect(configStub.args[0][0].Handler)
|
||||
.to.be.equal(serverless.service.functions.create.handler);
|
||||
expect(configStub.args[0][0].MemorySize)
|
||||
.to.be.equal(serverless.service.functions.create.memory_size);
|
||||
expect(configStub.args[0][0].Timeout)
|
||||
.to.be.equal(serverless.service.functions.create.timeout);
|
||||
|
||||
// second config call args
|
||||
expect(configStub.args[1][0].FunctionName)
|
||||
.to.be.equal('myService-list');
|
||||
expect(configStub.args[1][0].Description)
|
||||
.to.be.equal(serverless.service.functions.list.description);
|
||||
expect(configStub.args[1][0].Handler)
|
||||
.to.be.equal(serverless.service.functions.list.handler);
|
||||
expect(configStub.args[1][0].MemorySize)
|
||||
.to.be.equal(serverless.service.functions.list.memory_size);
|
||||
expect(configStub.args[1][0].Timeout)
|
||||
.to.be.equal(serverless.service.functions.list.timeout);
|
||||
|
||||
// both code calls
|
||||
expect(codeStub.calledTwice).to.be.equal(true);
|
||||
|
||||
// first code call args
|
||||
expect(codeStub.args[0][0].FunctionName)
|
||||
.to.be.equal('myService-create');
|
||||
expect(typeof codeStub.args[0][0].ZipFile)
|
||||
.to.not.be.equal('undefined');
|
||||
|
||||
// second code call args
|
||||
expect(codeStub.args[1][0].FunctionName)
|
||||
.to.be.equal('myService-list');
|
||||
expect(typeof codeStub.args[1][0].ZipFile)
|
||||
.to.not.be.equal('undefined');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -2,6 +2,12 @@
|
||||
"AWSTemplateFormatVersion": "2010-09-09",
|
||||
"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": ""
|
||||
}
|
||||
},
|
||||
"IamRoleLambda": {
|
||||
"Type": "AWS::IAM::Role",
|
||||
"Properties": {
|
||||
|
||||
35
tests/all.js
35
tests/all.js
@ -3,20 +3,21 @@
|
||||
process.env.DEBUG = '*';
|
||||
require('./config');
|
||||
|
||||
// Serverless Core Tests
|
||||
require('./classes/Serverless');
|
||||
require('./classes/PluginManager');
|
||||
require('./classes/Utils');
|
||||
require('./classes/Config');
|
||||
require('./classes/Service');
|
||||
require('./classes/YamlParser');
|
||||
require('./classes/CLI');
|
||||
|
||||
// Integration Tests
|
||||
require('./integration/Serverless');
|
||||
|
||||
// Core Plugins Tests
|
||||
require('../lib/plugins/create/tests/create');
|
||||
require('../lib/plugins/deploy/tests/deploy');
|
||||
require('../lib/plugins/awsResourcesDeploy/tests/awsResourcesDeploy');
|
||||
require('../lib/plugins/awsCompileFunctionsToResources/tests/awsCompileFunctionsToResources');
|
||||
// // Serverless Core Tests
|
||||
// require('./classes/Serverless');
|
||||
// require('./classes/PluginManager');
|
||||
// require('./classes/Utils');
|
||||
// require('./classes/Config');
|
||||
// require('./classes/Service');
|
||||
// require('./classes/YamlParser');
|
||||
// require('./classes/CLI');
|
||||
//
|
||||
// // Integration Tests
|
||||
// require('./integration/Serverless');
|
||||
//
|
||||
// // Core Plugins Tests
|
||||
// require('../lib/plugins/create/tests/create');
|
||||
// require('../lib/plugins/deploy/tests/deploy');
|
||||
// require('../lib/plugins/awsResourcesDeploy/tests/awsResourcesDeploy');
|
||||
// require('../lib/plugins/awsCompileFunctionsToResources/tests/awsCompileFunctionsToResources');
|
||||
require('../lib/plugins/awsDeploy/tests/awsDeploy');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user