mirror of
https://github.com/serverless/serverless.git
synced 2026-01-25 15:07:39 +00:00
Merge pull request #648 from minibikini/master
updates the actions to use ProviderAws
This commit is contained in:
commit
5393e32bc8
@ -123,18 +123,6 @@ module.exports = function(SPlugin, serverlessPath) {
|
||||
|
||||
this.spinner = SCli.spinner();
|
||||
|
||||
this.CWL = require('../utils/aws/CloudWatch')({
|
||||
region: this.evt.options.region,
|
||||
accessKeyId: this.S.config.awsAdminKeyId,
|
||||
secretAccessKey: this.S.config.awsAdminSecretKey
|
||||
});
|
||||
|
||||
this.Lambda = require('../utils/aws/Lambda')({
|
||||
region: this.evt.options.region,
|
||||
accessKeyId: this.S.config.awsAdminKeyId,
|
||||
secretAccessKey: this.S.config.awsAdminSecretKey
|
||||
});
|
||||
|
||||
const func = this.S.getProject().getFunction( this.evt.options.path ),
|
||||
duration = this.evt.options.duration;
|
||||
|
||||
@ -146,14 +134,30 @@ module.exports = function(SPlugin, serverlessPath) {
|
||||
this.evt.data.lambdaName = lambdaName;
|
||||
}
|
||||
|
||||
_getLogStreams() {
|
||||
let params = {
|
||||
logGroupName: this.evt.data.logGroupName,
|
||||
descending: true,
|
||||
limit: 50,
|
||||
orderBy: 'LastEventTime'
|
||||
};
|
||||
|
||||
return this.S.getProvider('aws')
|
||||
.request('CloudWatchLogs', 'describeLogStreams', params, this.evt.options.stage, this.evt.options.region)
|
||||
.error(error => BbPromise.reject(new SError(error.message, SError.errorCodes.UNKNOWN)))
|
||||
.then(reply => reply.logStreams);
|
||||
}
|
||||
|
||||
_getLogStreamNames() {
|
||||
return this.Lambda.getAliasPromised({
|
||||
const params = {
|
||||
FunctionName: this.evt.data.lambdaName,
|
||||
Name: this.evt.options.stage
|
||||
})
|
||||
};
|
||||
|
||||
return this.S.getProvider('aws')
|
||||
.request('Lambda', 'getAlias', params, this.evt.options.stage, this.evt.options.region);
|
||||
.then(reply => this.evt.data.version = reply.FunctionVersion)
|
||||
.then(() => this.CWL.sGetLogStreams(this.evt.data.logGroupName, 50))
|
||||
.then(reply => reply.logStreams)
|
||||
.then(this._getLogStreams)
|
||||
.then( logStreams => {
|
||||
if (logStreams.length === 0) return BbPromise.reject(new SError('No existing streams for the function'));
|
||||
|
||||
@ -186,7 +190,8 @@ module.exports = function(SPlugin, serverlessPath) {
|
||||
if (this.evt.options.filter) params.filterPattern = this.evt.options.filter;
|
||||
if (this.evt.data.nextToken) params.nextToken = this.evt.data.nextToken;
|
||||
|
||||
return this.CWL.filterLogEventsAsync(params)
|
||||
return this.S.getProvider('aws')
|
||||
.request('CloudWatchLogs', 'filterLogEvents', params, this.evt.options.stage, this.evt.options.region)
|
||||
.then(results => {
|
||||
|
||||
if (this.S.config.interactive && results.events) {
|
||||
|
||||
@ -177,12 +177,6 @@ module.exports = function(SPlugin, serverlessPath) {
|
||||
|
||||
// Invoke Lambda
|
||||
|
||||
_this.Lambda = require('../utils/aws/Lambda')({
|
||||
region: _this.evt.options.region,
|
||||
accessKeyId: _this.S.config.awsAdminKeyId,
|
||||
secretAccessKey: _this.S.config.awsAdminSecretKey
|
||||
});
|
||||
|
||||
let params = {
|
||||
FunctionName: _this.function.getDeployedName({ stage: _this.evt.options.stage, region: _this.evt.options.region }),
|
||||
// ClientContext: new Buffer(JSON.stringify({x: 1, y: [3,4]})).toString('base64'),
|
||||
@ -192,7 +186,8 @@ module.exports = function(SPlugin, serverlessPath) {
|
||||
Qualifier: _this.evt.options.stage
|
||||
};
|
||||
|
||||
return _this.Lambda.invokePromised(params)
|
||||
return this.S.getProvider('aws')
|
||||
.request('Lambda', 'invoke', params, _this.evt.options.stage, _this.evt.options.region);
|
||||
.then( reply => {
|
||||
|
||||
let color = !reply.FunctionError ? 'white' : 'red';
|
||||
|
||||
@ -20,16 +20,7 @@
|
||||
|
||||
module.exports = function(SPlugin, serverlessPath) {
|
||||
|
||||
const path = require('path'),
|
||||
SError = require( path.join( serverlessPath, 'ServerlessError' ) ),
|
||||
SCli = require( path.join( serverlessPath, 'utils/cli' ) ),
|
||||
SUtils = require( path.join( serverlessPath, 'utils' ) ),
|
||||
os = require('os'),
|
||||
fs = require('fs'),
|
||||
BbPromise = require('bluebird'),
|
||||
awsMisc = require( path.join( serverlessPath, 'utils/aws/Misc' ) );
|
||||
|
||||
BbPromise.promisifyAll(fs);
|
||||
const BbPromise = require('bluebird');
|
||||
|
||||
/**
|
||||
* ProjectInstall Class
|
||||
|
||||
@ -22,13 +22,10 @@ module.exports = function(SPlugin, serverlessPath) {
|
||||
SError = require( path.join( serverlessPath, 'ServerlessError' ) ),
|
||||
SCli = require( path.join( serverlessPath, 'utils/cli' ) ),
|
||||
SUtils = require( path.join( serverlessPath, 'utils' ) ),
|
||||
os = require('os'),
|
||||
fs = require('fs'),
|
||||
fse = require('fs-extra'),
|
||||
BbPromise = require('bluebird'),
|
||||
awsMisc = require( path.join( serverlessPath, 'utils/aws/Misc' ) );
|
||||
os = require('os'),
|
||||
fs = BbPromise.promisifyAll(require('fs'));
|
||||
|
||||
BbPromise.promisifyAll(fs);
|
||||
|
||||
/**
|
||||
* ProjectInit Class
|
||||
@ -91,44 +88,38 @@ module.exports = function(SPlugin, serverlessPath) {
|
||||
|
||||
projectInit(evt) {
|
||||
|
||||
let _this = this;
|
||||
this.evt = evt;
|
||||
|
||||
// Check for AWS Profiles
|
||||
let profilesList = awsMisc.profilesMap();
|
||||
let profilesList = this.S.getProvider('aws').getAllProfiles();
|
||||
this.profiles = Object.keys(profilesList);
|
||||
|
||||
// Set Stage default
|
||||
if (!_this.evt.options.stage) _this.evt.options.stage = 'dev';
|
||||
if (!this.evt.options.stage) this.evt.options.stage = 'dev';
|
||||
|
||||
// Greet
|
||||
if (_this.S.config.interactive && !_this.evt.options.noGreeting) SCli.asciiGreeting();
|
||||
if (this.S.config.interactive && !this.evt.options.noGreeting) SCli.asciiGreeting();
|
||||
|
||||
console.log('');
|
||||
SCli.log('Initializing Serverless Project...');
|
||||
/**
|
||||
* Control Flow
|
||||
*/
|
||||
|
||||
return BbPromise.try(function() {
|
||||
console.log('');
|
||||
SCli.log('Initializing Serverless Project...');
|
||||
})
|
||||
.bind(_this)
|
||||
.then(_this._prompt)
|
||||
.then(_this._validateAndPrepare)
|
||||
.then(_this._scaffold)
|
||||
.then(_this._createStageAndRegion)
|
||||
.then(_this._installComponentDeps)
|
||||
.then(function() {
|
||||
|
||||
SCli.log('Successfully initialized project "'
|
||||
+ _this.evt.options.name
|
||||
+ '"');
|
||||
return this._prompt()
|
||||
.bind(this)
|
||||
.then(this._validateAndPrepare)
|
||||
.then(this._scaffold)
|
||||
.then(this._createStageAndRegion)
|
||||
.then(this._installComponentDeps)
|
||||
.then(() => {
|
||||
SCli.log(`Successfully initialized project "${this.evt.options.name}"`);
|
||||
|
||||
/**
|
||||
* Return EVT
|
||||
*/
|
||||
|
||||
return _this.evt;
|
||||
return this.evt;
|
||||
});
|
||||
}
|
||||
|
||||
@ -235,11 +226,14 @@ module.exports = function(SPlugin, serverlessPath) {
|
||||
_this.evt.options.domain = answers.domain;
|
||||
_this.evt.options.notificationEmail = answers.notificationEmail;
|
||||
|
||||
// init AWS with the provided keys
|
||||
_this.S.initProviders();
|
||||
|
||||
// Show region prompt
|
||||
if (!_this.evt.options.region) {
|
||||
|
||||
// Prompt: region select
|
||||
let choices = awsMisc.validLambdaRegions.map(r => {
|
||||
let choices = _this.S.getProvider('aws').validLambdaRegions.map(r => {
|
||||
return {
|
||||
key: '',
|
||||
value: r,
|
||||
@ -285,13 +279,12 @@ module.exports = function(SPlugin, serverlessPath) {
|
||||
|
||||
_validateAndPrepare() {
|
||||
|
||||
// Initialize AWS Misc Service
|
||||
this.AwsMisc = require('../utils/aws/Misc');
|
||||
this.S.getProvider('aws').getProfile(this.evt.options.profile)
|
||||
|
||||
// If Profile, extract API Keys
|
||||
if (this.evt.options.profile) {
|
||||
this.S.config.awsAdminKeyId = this.AwsMisc.profilesGet(this.evt.options.profile)[this.evt.options.profile].aws_access_key_id;
|
||||
this.S.config.awsAdminSecretKey = this.AwsMisc.profilesGet(this.evt.options.profile)[this.evt.options.profile].aws_secret_access_key;
|
||||
this.S.config.awsAdminKeyId = this.S.getProvider('aws').getProfile(this.evt.options.profile).aws_access_key_id;
|
||||
this.S.config.awsAdminSecretKey = this.S.getProvider('aws').getProfile(this.evt.options.profile).aws_secret_access_key;
|
||||
}
|
||||
|
||||
// Validate API Keys
|
||||
@ -299,15 +292,6 @@ module.exports = function(SPlugin, serverlessPath) {
|
||||
return BbPromise.reject(new SError('Missing AWS API Key and/or AWS Secret Key'));
|
||||
}
|
||||
|
||||
// Initialize Other AWS Services
|
||||
let awsConfig = {
|
||||
region: this.evt.options.region,
|
||||
accessKeyId: this.S.config.awsAdminKeyId,
|
||||
secretAccessKey: this.S.config.awsAdminSecretKey
|
||||
};
|
||||
this.S3 = require('../utils/aws/S3')(awsConfig);
|
||||
this.CF = require('../utils/aws/CloudFormation')(awsConfig);
|
||||
|
||||
// Validate Name - AWS only allows Alphanumeric and - in name
|
||||
let nameOk = /^([a-zA-Z0-9-]+)$/.exec(this.evt.options.name);
|
||||
if (!nameOk) {
|
||||
@ -327,7 +311,7 @@ module.exports = function(SPlugin, serverlessPath) {
|
||||
}
|
||||
|
||||
// Validate Region
|
||||
if (awsMisc.validLambdaRegions.indexOf(this.evt.options.region) == -1) {
|
||||
if (this.S.getProvider('aws').validLambdaRegions.indexOf(this.evt.options.region) == -1) {
|
||||
return BbPromise.reject(new SError('Invalid region. Lambda not supported in ' + this.evt.options.region, SError.errorCodes.UNKNOWN));
|
||||
}
|
||||
|
||||
|
||||
@ -19,13 +19,9 @@ module.exports = function(SPlugin, serverlessPath) {
|
||||
const path = require('path'),
|
||||
SError = require(path.join(serverlessPath, 'ServerlessError')),
|
||||
SCli = require(path.join(serverlessPath, 'utils/cli')),
|
||||
fs = require('fs'),
|
||||
BbPromise = require('bluebird'),
|
||||
awsMisc = require(path.join(serverlessPath, 'utils/aws/Misc')),
|
||||
SUtils = require(path.join(serverlessPath, 'utils'));
|
||||
|
||||
BbPromise.promisifyAll(fs);
|
||||
|
||||
/**
|
||||
* RegionCreate Class
|
||||
*/
|
||||
@ -107,24 +103,13 @@ usage: serverless region create`,
|
||||
*/
|
||||
|
||||
_prompt() {
|
||||
|
||||
let _this = this;
|
||||
|
||||
// Skip if non-interactive or stage is provided
|
||||
if (!_this.S.config.interactive || (_this.evt.options.stage && _this.evt.options.region)) return BbPromise.resolve();
|
||||
if (!this.S.config.interactive || (this.evt.options.stage && this.evt.options.region)) return BbPromise.resolve();
|
||||
|
||||
return _this.cliPromptSelectStage('Select an existing stage for your new region: ', _this.evt.options.stage, false)
|
||||
.then(stage => {
|
||||
_this.evt.options.stage = stage;
|
||||
BbPromise.resolve();
|
||||
})
|
||||
.then(function() {
|
||||
return _this.cliPromptSelectRegion('Select a new region for your existing stage: ', false, false, _this.evt.options.region, _this.evt.options.stage)
|
||||
.then(region => {
|
||||
_this.evt.options.region = region;
|
||||
BbPromise.resolve();
|
||||
});
|
||||
});
|
||||
return this.cliPromptSelectStage('Select an existing stage for your new region: ', this.evt.options.stage, false)
|
||||
.then(stage => this.evt.options.stage = stage;)
|
||||
.then(() => this.cliPromptSelectRegion('Select a new region for your existing stage: ', false, false, this.evt.options.region, this.evt.options.stage));
|
||||
.then(region => this.evt.options.region = region);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -148,7 +133,7 @@ usage: serverless region create`,
|
||||
}
|
||||
|
||||
// Validate region: make sure Lambda is supported in that region
|
||||
if (awsMisc.validLambdaRegions.indexOf(_this.evt.options.region) == -1) {
|
||||
if (this.S.getProvider('aws').validLambdaRegions.indexOf(_this.evt.options.region) == -1) {
|
||||
return BbPromise.reject(new SError('Invalid region. Lambda not supported in ' + _this.evt.options.region));
|
||||
}
|
||||
|
||||
@ -175,13 +160,6 @@ usage: serverless region create`,
|
||||
|
||||
_createProjectBucket() {
|
||||
|
||||
let awsConfig = {
|
||||
region: this.evt.options.region,
|
||||
accessKeyId: this.S.config.awsAdminKeyId,
|
||||
secretAccessKey: this.S.config.awsAdminSecretKey
|
||||
};
|
||||
this.S3 = require('../utils/aws/S3')(awsConfig);
|
||||
|
||||
if (this.evt.options.noExeCf) {
|
||||
|
||||
// If no CloudFormation is set, skip project bucket creation
|
||||
@ -189,11 +167,39 @@ usage: serverless region create`,
|
||||
SCli.log('Notice -- Skipping project bucket creation. Don\'t forget to point this project to your existing project bucket in _meta/s-variables-common.json. You will also need to manually create the file structure on the bucket and add a .env file to the tour first stage folder (e.g., "dev").');
|
||||
return BbPromise.resolve();
|
||||
|
||||
} else {
|
||||
|
||||
// Create bucket, or skip if already exists
|
||||
return this.S3.sCreateBucket(this.S.state.getMeta().variables.projectBucket);
|
||||
}
|
||||
|
||||
// Create bucket, or skip if already exists
|
||||
|
||||
const stage = this.evt.options.stage,
|
||||
region = this.evt.options.region,
|
||||
bucketName = this.S.state.getMeta().variables.projectBucket;
|
||||
|
||||
return this.S.getProvider('aws')
|
||||
.request('S3', 'getBucketAcl', { Bucket: bucketName }, stage, region)
|
||||
.then(() => SUtils.sDebug(`Project bucket already exists: ${bucketName}`))
|
||||
.catch(function(err) {
|
||||
|
||||
if (err.code == 'AccessDenied') {
|
||||
|
||||
throw new SError(
|
||||
`S3 Bucket "${bucketName}" already exists and you do not have permissions to use it`,
|
||||
SError.errorCodes.ACCESS_DENIED
|
||||
);
|
||||
|
||||
} else if (err.code == 'NoSuchBucket') {
|
||||
|
||||
SCli.log('Creating your project bucket on S3: ' + bucketName + '...');
|
||||
|
||||
return this.S.getProvider('aws')
|
||||
.request('S3', 'createBucket', {Bucket: bucketName, ACL: 'private'}, stage, region);
|
||||
|
||||
} else {
|
||||
|
||||
// Otherwise throw error
|
||||
throw new SError(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -202,29 +208,29 @@ usage: serverless region create`,
|
||||
*/
|
||||
|
||||
_putEnvFile() {
|
||||
const projectName = this.S.getProject().name,
|
||||
stage = this.evt.options.stage,
|
||||
region = this.evt.options.region,
|
||||
key = ['serverless', projectName, stage, region, 'envVars', '.env'].join('/');
|
||||
|
||||
// If noExeCf option, skip
|
||||
if (this.evt.options.noExeCf) return BbPromise.resolve();
|
||||
|
||||
// Init AWS S3
|
||||
let awsConfig = {
|
||||
region: this.evt.options.region,
|
||||
accessKeyId: this.S.config.awsAdminKeyId,
|
||||
secretAccessKey: this.S.config.awsAdminSecretKey
|
||||
};
|
||||
this.S3 = require('../utils/aws/S3')(awsConfig);
|
||||
|
||||
// Create ENV file in new region
|
||||
let envFileContents = `SERVERLESS_STAGE=${this.evt.options.stage}
|
||||
SERVERLESS_DATA_MODEL_STAGE=${this.evt.options.stage}
|
||||
SERVERLESS_PROJECT_NAME=${this.S.getProject().name}`;
|
||||
let envFileContents = `SERVERLESS_STAGE=${stage}
|
||||
SERVERLESS_DATA_MODEL_STAGE=${stage}
|
||||
SERVERLESS_PROJECT_NAME=${projectName}`;
|
||||
|
||||
return this.S3.sPutEnvFile(
|
||||
this.S.state.getMeta().variables.projectBucket,
|
||||
this.S.getProject().name,
|
||||
this.evt.options.stage,
|
||||
this.evt.options.region,
|
||||
envFileContents);
|
||||
let params = {
|
||||
Bucket: this.S.state.getMeta().variables.projectBucket,
|
||||
Key: key,
|
||||
ACL: 'private',
|
||||
ContentType: 'text/plain',
|
||||
Body: envFileContents
|
||||
};
|
||||
|
||||
return this.S.getProvider('aws')
|
||||
.request('S3', 'putObject', params, stage, region);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -241,7 +247,10 @@ SERVERLESS_PROJECT_NAME=${this.S.getProject().name}`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
return( RegionCreate );
|
||||
};
|
||||
|
||||
@ -20,7 +20,6 @@ module.exports = function(SPlugin, serverlessPath) {
|
||||
SCli = require(path.join(serverlessPath, 'utils/cli')),
|
||||
BbPromise = require('bluebird'),
|
||||
fs = BbPromise.promisifyAll(require('fs')),
|
||||
awsMisc = require(path.join(serverlessPath, 'utils/aws/Misc')),
|
||||
SUtils = require(path.join(serverlessPath, 'utils')),
|
||||
_ = require('lodash');
|
||||
|
||||
@ -83,7 +82,6 @@ usage: serverless region remove`,
|
||||
.bind(this)
|
||||
.then(this._validateAndPrepare)
|
||||
.then(() => { SCli.log(`Removing region "${this.evt.options.region}" in stage "${this.evt.options.stage}"...`); })
|
||||
.then(this._initS3)
|
||||
.then(this._listS3Objects)
|
||||
.then(this._removeS3Objects)
|
||||
.then(this._removeResources)
|
||||
@ -137,7 +135,7 @@ usage: serverless region remove`,
|
||||
}
|
||||
|
||||
// Validate region: make sure Lambda is supported in that region
|
||||
if (awsMisc.validLambdaRegions.indexOf(this.evt.options.region) == -1) {
|
||||
if (this.S.getProvider('aws').validLambdaRegions.indexOf(this.evt.options.region) == -1) {
|
||||
return BbPromise.reject(new SError('Invalid region. Lambda not supported in ' + this.evt.options.region));
|
||||
}
|
||||
|
||||
@ -148,16 +146,6 @@ usage: serverless region remove`,
|
||||
|
||||
}
|
||||
|
||||
_initS3() {
|
||||
let awsConfig = {
|
||||
region: SUtils.getProjectBucketRegion(this.S.state.getMeta().variables),
|
||||
accessKeyId: this.S.config.awsAdminKeyId,
|
||||
secretAccessKey: this.S.config.awsAdminSecretKey
|
||||
};
|
||||
|
||||
this.S3 = require('../utils/aws/S3')(awsConfig);
|
||||
}
|
||||
|
||||
_listS3Objects() {
|
||||
SUtils.sDebug("List related S3 objects");
|
||||
|
||||
@ -166,8 +154,7 @@ usage: serverless region remove`,
|
||||
Bucket: this.S.state.getMeta().variables.projectBucket,
|
||||
Prefix: prefix
|
||||
};
|
||||
|
||||
return this.S3.listObjectsPromised(params)
|
||||
return this.S.getProvider('aws').request('S3', 'listObjects', params, stage, region);
|
||||
.then(reply => {return _.map(reply.Contents, (item) => ({Key: item.Key}) )});
|
||||
}
|
||||
|
||||
@ -181,7 +168,7 @@ usage: serverless region remove`,
|
||||
Objects: objects
|
||||
}
|
||||
};
|
||||
return this.S3.deleteObjectsPromised(params)
|
||||
return this.S.getProvider('aws').request('S3', 'deleteObjects', params, stage, region);
|
||||
} else {
|
||||
SUtils.sDebug("S3 objects are not found. Skipping.");
|
||||
return BbPromise.resolve();
|
||||
|
||||
@ -13,6 +13,7 @@ module.exports = function(SPlugin, serverlessPath) {
|
||||
SCli = require(path.join(serverlessPath, 'utils/cli')),
|
||||
BbPromise = require('bluebird'),
|
||||
_ = require('lodash'),
|
||||
async = require('async'),
|
||||
SUtils = require(path.join(serverlessPath, 'utils/index'));
|
||||
|
||||
class ResourcesDeploy extends SPlugin {
|
||||
@ -189,15 +190,6 @@ usage: serverless resources deploy`,
|
||||
return;
|
||||
}
|
||||
|
||||
// Config AWS Services
|
||||
let awsConfig = {
|
||||
region: _this.evt.options.region,
|
||||
accessKeyId: _this.S.config.awsAdminKeyId,
|
||||
secretAccessKey: _this.S.config.awsAdminSecretKey
|
||||
};
|
||||
_this.CF = require('../utils/aws/CloudFormation')(awsConfig);
|
||||
_this.S3 = require('../utils/aws/S3')(awsConfig);
|
||||
|
||||
// Otherwise, deploy to CloudFormation
|
||||
SCli.log('Deploying resources to stage "'
|
||||
+ _this.evt.options.stage
|
||||
@ -210,59 +202,46 @@ usage: serverless resources deploy`,
|
||||
_this._spinner.start();
|
||||
|
||||
// Upload to S3 Bucket
|
||||
return _this.S3.sPutCfFile(
|
||||
_this.S.state.getMeta().variables.projectBucket,
|
||||
_this.S.getProject().getName(),
|
||||
_this.evt.options.stage,
|
||||
_this.evt.options.region,
|
||||
_this.cfTemplate
|
||||
)
|
||||
.then(function(templateUrl) {
|
||||
return _this._putCfFile(_this.cfTemplate)
|
||||
.bind(_this)
|
||||
.then(_this._createOrUpdateResourcesStack)
|
||||
.then(cfData => {
|
||||
|
||||
// Trigger CF Stack Create/Update
|
||||
return _this.CF.sCreateOrUpdateResourcesStack(
|
||||
_this.S.getProject().getName(),
|
||||
_this.evt.options.stage,
|
||||
_this.evt.options.region,
|
||||
regionVars.resourcesStackName ? regionVars.resourcesStackName : null,
|
||||
templateUrl)
|
||||
.then(cfData => {
|
||||
// If string, log output
|
||||
if (typeof cfData === 'string') {
|
||||
_this._spinner.stop(true);
|
||||
SCli.log(cfData);
|
||||
return;
|
||||
}
|
||||
|
||||
// If string, log output
|
||||
if (typeof cfData === 'string') {
|
||||
_this._spinner.stop(true);
|
||||
SCli.log(cfData);
|
||||
return;
|
||||
// Monitor CF Status
|
||||
return _monitorCf(cfData)
|
||||
.then(cfStackData => {
|
||||
|
||||
// Save stack name
|
||||
regionVars.resourcesStackName = cfStackData.StackName;
|
||||
|
||||
// Save allowed (exported) CF output variables for Project Lambdas
|
||||
for (let i = 0; i < cfStackData.Outputs.length; i++) {
|
||||
let varName = _.lowerFirst(cfStackData.Outputs[i].OutputKey);
|
||||
if (resourceVars.indexOf(varName) !== -1) {
|
||||
regionVars[varName] = cfStackData.Outputs[i].OutputValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Monitor CF Status
|
||||
return _this.CF.sMonitorCf(cfData)
|
||||
.then(cfStackData => {
|
||||
|
||||
// Save stack name
|
||||
regionVars.resourcesStackName = cfStackData.StackName;
|
||||
|
||||
// Save allowed (exported) CF output variables for Project Lambdas
|
||||
for (let i = 0; i < cfStackData.Outputs.length; i++) {
|
||||
let varName = _.lowerFirst(cfStackData.Outputs[i].OutputKey);
|
||||
if (resourceVars.indexOf(varName) !== -1) {
|
||||
regionVars[varName] = cfStackData.Outputs[i].OutputValue;
|
||||
}
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
|
||||
// Stop Spinner
|
||||
_this._spinner.stop(true);
|
||||
|
||||
// Save State
|
||||
_this.S.state.save();
|
||||
|
||||
// Status
|
||||
SCli.log('Successfully deployed "' + _this.evt.options.stage + '" resources to "' + _this.evt.options.region + '"');
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
|
||||
// Stop Spinner
|
||||
_this._spinner.stop(true);
|
||||
|
||||
// Save State
|
||||
_this.S.state.save();
|
||||
|
||||
// Status
|
||||
SCli.log('Successfully deployed "' + _this.evt.options.stage + '" resources to "' + _this.evt.options.region + '"');
|
||||
});
|
||||
})
|
||||
|
||||
.catch(function(e) {
|
||||
|
||||
// Stop Spinner
|
||||
@ -272,7 +251,149 @@ usage: serverless resources deploy`,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Or Update Resources Stack
|
||||
* moved from lib/utils/aws/CloudFormation.js
|
||||
*/
|
||||
|
||||
_createOrUpdateResourcesStack(templateUrl) {
|
||||
const projectName = this.S.getProject().getName(),
|
||||
stage = this.evt.options.stage,
|
||||
region = this.evt.options.region,
|
||||
aws = this.S.getProvider('aws'),
|
||||
stackName = this.S.state.getMeta().stages[stage].regions[region].variables.resourcesStackName || aws.getLambdasStackName(stage, projectName);
|
||||
|
||||
// CF Params
|
||||
let params = {
|
||||
Capabilities: [
|
||||
'CAPABILITY_IAM'
|
||||
],
|
||||
Parameters: [],
|
||||
TemplateURL: templateUrl
|
||||
};
|
||||
|
||||
// Helper function to create Stack
|
||||
let createStack = () => {
|
||||
|
||||
params.Tags = [{
|
||||
Key: 'STAGE',
|
||||
Value: stage
|
||||
}];
|
||||
|
||||
params.StackName = stackName
|
||||
params.OnFailure = 'DELETE';
|
||||
return aws.request('CloudFormation', 'createStack', params, stage, region);
|
||||
};
|
||||
|
||||
// Check to see if Stack Exists
|
||||
return aws.request('CloudFormation', 'describeStackResources', {StackName: stackName}, stage, region);
|
||||
.then(function(data) {
|
||||
|
||||
params.StackName = stackName;
|
||||
// Update stack
|
||||
return aws.request('CloudFormation', 'updateStack', params, stage, region)
|
||||
})
|
||||
.catch(function(e) {
|
||||
|
||||
// No updates are to be performed
|
||||
if (e.cause.message == 'No updates are to be performed.') {
|
||||
return 'No resource updates are to be performed.';
|
||||
}
|
||||
|
||||
// If does not exist, create stack
|
||||
if (e.cause.message.indexOf('does not exist') > -1) {
|
||||
return createStack();
|
||||
}
|
||||
|
||||
// Otherwise throw another error
|
||||
throw new SError(e.cause.message);
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Monitor CF Stack Status (Create/Update)
|
||||
* moved from lib/utils/aws/CloudFormation.js
|
||||
*/
|
||||
|
||||
_monitorCf(cfData, checkFreq) {
|
||||
|
||||
let _this = this,
|
||||
stackStatusComplete;
|
||||
|
||||
let validStatuses = ['CREATE_COMPLETE', 'CREATE_IN_PROGRESS', 'UPDATE_COMPLETE', 'UPDATE_IN_PROGRESS', 'UPDATE_COMPLETE_CLEANUP_IN_PROGRESS'];
|
||||
|
||||
return new BbPromise(function(resolve, reject) {
|
||||
|
||||
let stackStatus = null,
|
||||
stackData = null;
|
||||
|
||||
async.whilst(
|
||||
function() {
|
||||
return (stackStatus !== 'UPDATE_COMPLETE' && stackStatus !== 'CREATE_COMPLETE');
|
||||
},
|
||||
|
||||
function(callback) {
|
||||
setTimeout(function() {
|
||||
|
||||
let params = {
|
||||
StackName: cfData.StackId
|
||||
};
|
||||
_this.S.getProvider('aws')
|
||||
.request('CloudFormation', 'describeStacks', params, _this.evt.options.stage, _this.evt.options.region)
|
||||
.then(function(data) {
|
||||
|
||||
stackData = data;
|
||||
stackStatus = stackData.Stacks[0].StackStatus;
|
||||
|
||||
SUtils.sDebug('CF stack status: ', stackStatus);
|
||||
|
||||
if (!stackStatus || validStatuses.indexOf(stackStatus) === -1) {
|
||||
return reject(new SError(`An error occurred while provisioning your cloudformation: ${stackData.Stacks[0].StackStatusReason}`));
|
||||
} else {
|
||||
return callback();
|
||||
}
|
||||
});
|
||||
}, checkFreq ? checkFreq : 5000);
|
||||
},
|
||||
|
||||
function() {
|
||||
return resolve(stackData.Stacks[0]);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Put CF File On S3
|
||||
* moved from lib/utils/aws/S3.js
|
||||
*/
|
||||
|
||||
_putCfFile = function(cfTemplate) {
|
||||
const time = new Date().getTime(),
|
||||
stage = this.evt.options.stage,
|
||||
region = this.evt.options.region,
|
||||
projectName = this.S.getProject().getName(),
|
||||
bucketName = this.S.state.getMeta().variables.projectBucket,
|
||||
key = ['serverless', projectName, stage, region, 'resources/' + 's-resources-cf'].join('/') + '@' + time + '.json',
|
||||
params = {
|
||||
Bucket: bucketName,
|
||||
Key: key,
|
||||
ACL: 'private',
|
||||
ContentType: 'application/json',
|
||||
Body: JSON.stringify(cfTemplate)
|
||||
};
|
||||
|
||||
return this.S.getProvider('aws')
|
||||
.request('S3', 'putObject', params, stage, region)
|
||||
.then(function() {
|
||||
const hostname = new require('aws-sdk').S3().endpoint.hostname;
|
||||
return `https://${hostname}/${bucketName}/${key}`;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
return( ResourcesDeploy );
|
||||
};
|
||||
};
|
||||
@ -141,13 +141,6 @@ module.exports = function(SPlugin, serverlessPath) {
|
||||
return BbPromise.reject(new SError('Region "' + this.evt.options.region + '" does not exists in stage "' + this.evt.options.stage + '"'));
|
||||
}
|
||||
|
||||
const awsConfig = {
|
||||
region: this.evt.options.region,
|
||||
accessKeyId: this.S.config.awsAdminKeyId,
|
||||
secretAccessKey: this.S.config.awsAdminSecretKey
|
||||
};
|
||||
|
||||
this.CloudFormation = require('../utils/aws/CloudFormation')(awsConfig);
|
||||
}
|
||||
|
||||
_getLocalTemplate() {
|
||||
@ -173,7 +166,9 @@ module.exports = function(SPlugin, serverlessPath) {
|
||||
// const StackName = this.CloudFormation.sGetResourcesStackName(this.evt.options.stage, this.S.getProject().getName());
|
||||
const StackName = this.S.state.getMeta().stages[this.evt.options.stage].regions[this.evt.options.region].variables.resourcesStackName;
|
||||
|
||||
return this.CloudFormation.getTemplatePromised({StackName})
|
||||
return this.S
|
||||
.getProvider('aws')
|
||||
.request('CloudFormation', 'getTemplate', {StackName}, this.evt.options.stage, this.evt.options.region)
|
||||
.then((reply) => JSON.parse(reply.TemplateBody));
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,26 +159,16 @@ usage: serverless resources remove`,
|
||||
region = _this.evt.options.region,
|
||||
regionVars = _this.S.state.getMeta().stages[stage].regions[region].variables,
|
||||
projectBucket = _this.S.state.getMeta().variables.projectBucket,
|
||||
projectName = _this.S.getProject().getName();
|
||||
projectName = _this.S.getProject().getName(),
|
||||
aws = _this.S.getProvider('aws');
|
||||
|
||||
// Config AWS Services
|
||||
let awsConfig = {
|
||||
region: region,
|
||||
accessKeyId: _this.S.config.awsAdminKeyId,
|
||||
secretAccessKey: _this.S.config.awsAdminSecretKey
|
||||
};
|
||||
|
||||
_this.CF = require('../utils/aws/CloudFormation')(awsConfig);
|
||||
_this.S3 = require('../utils/aws/S3')(awsConfig);
|
||||
_this.S3.sSetProjectBucketConfig(projectBucket);
|
||||
|
||||
let stackName = (regionVars.resourcesStackName || _this.CF.sGetResourcesStackName(stage, projectName));
|
||||
let stackName = (regionVars.resourcesStackName || aws.getLambdasStackName(stage, projectName));
|
||||
|
||||
SCli.log(`Removing resources from stage "${stage}" in region "${region}" via Cloudformation (~3 minutes)...`);
|
||||
|
||||
let removeCfStack = function() {
|
||||
SUtils.sDebug(`Removing "${stackName}" CF stack`);
|
||||
return _this.CF.deleteStackPromised({StackName: stackName});
|
||||
return aws.request('CloudFormation', 'deleteStack', {StackName: stackName}, stage, region);
|
||||
};
|
||||
|
||||
let removeLocalResourceFile = function() {
|
||||
|
||||
@ -19,7 +19,6 @@ module.exports = function(SPlugin, serverlessPath) {
|
||||
os = require('os'),
|
||||
fs = require('fs'),
|
||||
BbPromise = require('bluebird'),
|
||||
awsMisc = require(path.join(serverlessPath, 'utils/aws/Misc')),
|
||||
SUtils = require(path.join(serverlessPath, 'utils'));
|
||||
|
||||
BbPromise.promisifyAll(fs);
|
||||
@ -171,7 +170,7 @@ usage: serverless stage create`,
|
||||
}
|
||||
|
||||
// Validate region
|
||||
if (awsMisc.validLambdaRegions.indexOf(this.evt.options.region) == -1) {
|
||||
if (this.S.getProvider('aws').validLambdaRegions.indexOf(this.evt.options.region) == -1) {
|
||||
return BbPromise.reject(new SError('Invalid region. Lambda not supported in ' + this.evt.options.region));
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user