diff --git a/lib/Project.js b/lib/Project.js index f021aadbf..4f42039e5 100644 --- a/lib/Project.js +++ b/lib/Project.js @@ -171,17 +171,17 @@ class Project extends SerializerFileSystem { return _.flatten( _.map( this.getAllFunctions(), f => f.getAllEndpoints() ) ); } - getEndpoint( endpointPath, endpointMethod ){ + getEndpoint(endpointName){ return _.find( _.values( this.getAllEndpoints() ), e => - e.path === endpointPath && e.method === endpointMethod + e.getName() === endpointName ) } - getEndpointsByName(names) { + getEndpointsByNames(names) { let _this = this; let endpoints = []; names.forEach(function(name) { - let endpoint = _this.getEndpoint(name.split('~')[0], name.split('~')[1]); + let endpoint = _this.getEndpoint(name); if (!endpoint) throw new SError(`Endpoint "${name}" doesn't exist in your project`); endpoints.push(endpoint); }); diff --git a/lib/actions/EndpointBuildApiGateway.js b/lib/actions/EndpointBuildApiGateway.js index 267a7ae9b..234017cad 100644 --- a/lib/actions/EndpointBuildApiGateway.js +++ b/lib/actions/EndpointBuildApiGateway.js @@ -151,7 +151,7 @@ module.exports = function(SPlugin, serverlessPath) { _this.apiResources = null; // Get populated endpoint - _this.endpoint = _this.project.getEndpoint( _this.evt.options.endpointPath, _this.evt.options.endpointMethod ); + _this.endpoint = _this.project.getEndpoint(_this.evt.options.name); if (!_this.endpoint) BbPromise.reject(new SError(`Endpoint could not be found: ${_this.evt.options.endpointPath}#${_this.evt.options.endpointMethod}`)); diff --git a/lib/actions/EndpointDeploy.js b/lib/actions/EndpointDeploy.js index 1009dba84..535ea01ea 100644 --- a/lib/actions/EndpointDeploy.js +++ b/lib/actions/EndpointDeploy.js @@ -115,11 +115,11 @@ module.exports = function(SPlugin, serverlessPath) { .then(function() { // Display Successfully Deployed Endpoints, if any - if (_this.deployed) { + if (_this.evt.data.deployed) { SCli.log('Successfully deployed endpoints in "' + _this.evt.options.stage + '" to the following regions:'); - for (let i = 0; i < Object.keys(_this.deployed).length; i++) { - let region = _this.deployed[Object.keys(_this.deployed)[i]]; - SCli.log(Object.keys(_this.deployed)[i] + ' ------------------------'); + for (let i = 0; i < Object.keys(_this.evt.data.deployed).length; i++) { + let region = _this.evt.data.deployed[Object.keys(_this.evt.data.deployed)[i]]; + SCli.log(Object.keys(_this.evt.data.deployed)[i] + ' ------------------------'); for (let j = 0; j < region.length; j++) { SCli.log(' ' + region[j].endpointMethod + ' - ' + region[j].endpointPath + ' - ' + region[j].endpointUrl); } @@ -127,11 +127,11 @@ module.exports = function(SPlugin, serverlessPath) { } // Display Failed Deployed Endpoints, if any - if(_this.failed) { + if(_this.evt.data.failed) { SCli.log('Failed to deploy endpoints in "' + _this.evt.options.stage + '" to the following regions:'); - for (let i = 0; i < Object.keys(_this.failed).length; i++) { - let region = _this.failed[Object.keys(_this.failed)[i]]; - SCli.log(Object.keys(_this.failed)[i] + ' ------------------------'); + for (let i = 0; i < Object.keys(_this.evt.data.failed).length; i++) { + let region = _this.evt.data.failed[Object.keys(_this.evt.data.failed)[i]]; + SCli.log(Object.keys(_this.evt.data.failed)[i] + ' ------------------------'); for (let j = 0; j < region.length; j++) { SCli.log(' ' + region[j].endpointMethod + ' - ' + region[j].endpointPath + ': ' + region[j].message ); // Show Error Stacktrace if in debug mode @@ -146,8 +146,8 @@ module.exports = function(SPlugin, serverlessPath) { * Return EVT */ - _this.evt.data.deployed = _this.deployed; - _this.evt.data.failed = _this.failed; + _this.evt.data.deployed = _this.evt.data.deployed; + _this.evt.data.failed = _this.evt.data.failed; return _this.evt; }); @@ -170,7 +170,7 @@ module.exports = function(SPlugin, serverlessPath) { // Prepare endpoints if (_this.evt.options.names.length) { - _this.endpoints = _this.project.getEndpointsByName(_this.evt.options.names); + _this.endpoints = _this.project.getEndpointsByNames(_this.evt.options.names); } // If CLI and no endpoint names targeted, deploy from CWD @@ -211,6 +211,8 @@ module.exports = function(SPlugin, serverlessPath) { _processDeployment() { + let _this = this; + // Create new event object let newEvt = { options: { @@ -222,7 +224,11 @@ module.exports = function(SPlugin, serverlessPath) { } }; - return this.S.actions.endpointDeployApiGateway(newEvt); + return this.S.actions.endpointDeployApiGateway(newEvt) + .then(function(evt) { + _this.evt.data.deployed = evt.data.deployed; + _this.evt.data.failed = evt.data.failed; + }) } } diff --git a/lib/actions/EndpointDeployApiGateway.js b/lib/actions/EndpointDeployApiGateway.js index d33bbc877..a41b343d2 100644 --- a/lib/actions/EndpointDeployApiGateway.js +++ b/lib/actions/EndpointDeployApiGateway.js @@ -14,386 +14,388 @@ */ module.exports = function(SPlugin, serverlessPath) { - const path = require('path'), - SError = require(path.join(serverlessPath, 'Error')), - SCli = require('../utils/cli'), - BbPromise = require('bluebird'), - async = require('async'), - fs = require('fs'); - let SUtils; - - // Promisify fs module - BbPromise.promisifyAll(fs); - - class EndpointDeployApiGateway extends SPlugin { - - constructor(S, config) { - super(S, config); - SUtils = S.utils; - } - - static getName() { - return 'serverless.core.' + EndpointDeployApiGateway.name; - } - - registerActions() { - this.S.addAction(this.endpointDeployApiGateway.bind(this), { - handler: 'endpointDeployApiGateway', - description: 'Deploys a REST API to API Gateway in one or multiple regions' - }); - return Promise.resolve(); - } - - /** - * Handler - */ - - endpointDeployApiGateway(evt) { - - let _this = this; - _this.evt = evt; - _this.project = _this.S.getProject(); - _this.provider = _this.S.getProvider(); - _this.awsAccountNumber = _this.project.getRegion(_this.evt.options.stage, _this.evt.options.region).getVariables().iamRoleArnLambda.replace('arn:aws:iam::', '').split(':')[0]; - _this.regions = _this.evt.options.region ? [_this.evt.options.region] : _this.project.getAllRegionNames(_this.evt.options.stage); - _this.spinner = SCli.spinner(); - _this.endpoints = _this.project.getEndpointsByName(_this.evt.options.names); - - return _this._validateAndPrepare() - .bind(_this) - .then(_this._processDeployment) - .then(_this._createDeployment) - .then(function() { - - /** - * Return EVT - */ - - _this.evt.data.deploymentId = _this.deployment.id; - return _this.evt; - - }); - } - - /** - * Validate And Prepare - */ - - _validateAndPrepare() { - return BbPromise.resolve(); - } - - /** - * Process Deployment - */ - - _processDeployment() { - - let _this = this; - - // Status - console.log(''); - SCli.log('Deploying endpoints in "' + _this.evt.options.stage + '" to the following regions: ' + _this.regions.join(', ')); - _this.spinner.start(); - - return BbPromise.try(function() { - return _this.regions; - }) - .bind(_this) - .each(function(region) { - - // Process each Region - return _this._processRegionDeployment(region); - }) - .then(function() { - - // Stop Spinner - _this.spinner.stop(true); - }); - } - - /** - * Process Deployment In Region - */ - - _processRegionDeployment(region) { - - let _this = this; - - // Get or Create REST API for Region by name - let restApi; - if (_this.project.getRegion(_this.evt.options.stage, region).getVariables()['apiGatewayApi']) { - restApi = _this.project.getRegion(_this.evt.options.stage, region).getVariables()['apiGatewayApi']; - } else { - restApi = _this.project.name; - } - - return _this._findOrCreateRestApi( - restApi, - _this.evt.options.stage, - region) - .then(function(restApiData) { - - _this.restApiData = restApiData; - - let regionInstance = _this.project.getRegion(_this.evt.options.stage, region); - regionInstance.addVariables({ - apiGatewayApi: restApiData.name - }); - - return regionInstance.save(); - }) - .bind(_this) - .then(_this._createAuthorizers) - .then(function() { - return new BbPromise(function (resolve, reject) { - - // A function can have multiple endpoints. Process all endpoints for this Function - async.eachSeries(_this.endpoints, function (endpoint, eCb) { - - return BbPromise.try(function () { - - // Find authorizerId, if specified - let authorizerId; - if (endpoint.authorizerFunction) { - if (_this.authorizers[endpoint.authorizerFunction]) { - authorizerId = _this.authorizers[endpoint.authorizerFunction]; - } else { - throw new SError(`Endpoint ${endpoint.getName()} has an 'authorizerFunction' specified that does not exist in this project.`); - } - } - if (endpoint.authorizerId) { - authorizerId = endpoint.authorizerId; - } - - // Create new event object - let newEvt = { - options: { - stage: _this.evt.options.stage, - region: region, - name: endpoint.getName(), - authorizerId: authorizerId ? authorizerId : null, - aliasEndpoint: _this.evt.options.aliasEndpoint - } - }; - - return _this.S.actions.endpointBuildApiGateway(newEvt); - }) - .then(function (result) { - - // Stash deployed endpoints - if (!_this.deployed) _this.deployed = {}; - if (!_this.deployed[region]) _this.deployed[region] = []; - _this.deployed[region].push({ - endpointPath: endpoint.path, - endpointMethod: endpoint.method, - endpointUrl: result.data.url - }); - - }) - .catch(function (e) { - - // Stash Failed Endpoint - if (!_this.failed) _this.failed = {}; - if (!_this.failed[region]) _this.failed[region] = []; - _this.failed[region].push({ - endpointPath: endpoint ? endpoint.path : 'unknown', - endpointMethod: endpoint ? endpoint.method : 'unknown', - message: e.message, - stack: e.stack - }); - }) - .then(function() { - - // If no endpoints were successfully deployed, skip - if (!_this.deployed) return eCb(); - - // Deploy API Gateway Deployment in region - return _this._createDeployment() - .then(function() { - return eCb(); - }); - }); - }, function () { - return resolve(); - }); - }) - }); - } - - /** - * Find Or Create REST API - */ - - _findOrCreateRestApi(restApiName, stage, region) { - let _this = this; - - return _this.provider.getApiByName(restApiName, stage, region) - .then(function(restApi) { - - // Return, if found - if (restApi) return restApi; - - // Otherwise, create new REST API - let params = { - name: restApiName, /* required */ - description: 'A REST API for a Serverless project in region: ' + region - }; - - return _this.provider.request('APIGateway', 'createRestApi', params, stage, region) - .then(function (response) { - - SUtils.sDebug( - '"' - + stage - + ' - ' - + region - + '": created a new REST API on AWS API Gateway with name: ' - + response.name); - - return response; - }); - }); - } - - /** - * Create Authorizers - */ - - _createAuthorizers() { - - let _this = this; - let functions = _this.project.getAllFunctions(); - _this.authorizers = {}; - - return BbPromise.try(function() { - - // Delete pre-existing on authorizers deployed on API Gateway - let params = { - restApiId: _this.restApiData.id, - limit: 100 - }; - - return _this.provider.request('APIGateway', 'getAuthorizers', params, _this.evt.options.stage, _this.evt.options.region) - .then(function(a) { - return a.items; - }); - }) - .each(function(a) { - - // Otherwise, delete pre-existing on authorizers deployed on API Gateway - let params = { - restApiId: _this.restApiData.id, - authorizerId: a.id - }; - - return _this.provider.request('APIGateway', 'deleteAuthorizer', params, _this.evt.options.stage, _this.evt.options.region); - }) - .then(function() { - return functions; - }) - .each(function(fn) { - - // If no authorizer data, skip - if (!fn.authorizer || !Object.keys(fn.authorizer).length) return; - - let f = fn.toObjectPopulated({ stage: _this.evt.options.stage, region: _this.evt.options.region }); - - // Create new authorizer on API Gateway - - // Fetch Lambda - let params = { - FunctionName: fn.getDeployedName({ stage: _this.evt.options.stage, region: _this.evt.options.region }), - Qualifier: _this.evt.options.stage - }; - - return _this.provider.request('Lambda', 'getFunction', params, _this.evt.options.stage, _this.evt.options.region) - .then(function(l) { - // Validate required authorizer params - if (!f.authorizer.identitySource) throw new SError(`Authorizer is missing identitySource property in function ${f.name}`); - - // Create Authorizer params. Set defaults. - let authorizer = f.authorizer; - authorizer.restApiId = _this.restApiData.id; - authorizer.name = authorizer.name || fn.getDeployedName({ stage: _this.evt.options.stage, region: _this.evt.options.region }); - authorizer.type = authorizer.type || 'TOKEN'; - - let alias = '${stageVariables.functionAlias}'; - - // Construct authorizer URI - authorizer.authorizerUri = 'arn:aws:apigateway:' - + _this.evt.options.region - + ':lambda:path/2015-03-31/functions/arn:aws:lambda:' - + _this.evt.options.region - + ':' - + _this.awsAccountNumber - + ':function:' - + fn.getDeployedName({ stage: _this.evt.options.stage, region: _this.evt.options.region }) - + ':' - + alias - + '/invocations'; - - return _this.provider.request('APIGateway', 'createAuthorizer', authorizer, _this.evt.options.stage, _this.evt.options.region) - .then(function(a) { - _this.authorizers[fn.name] = a.id; - }); - }); - }); - } - - /** - * Create Deployment - */ - - _createDeployment() { - - let _this = this; - - return new BbPromise( function( resolve, reject ){ - - let doDeploy = function() { - - let params = { - restApiId: _this.restApiData.id, /* required */ - stageName: _this.evt.options.stage, /* required */ - //cacheClusterEnabled: false, TODO: Implement - //cacheClusterSize: '0.5 | 1.6 | 6.1 | 13.5 | 28.4 | 58.2 | 118 | 237', TODO: Implement - description: _this.evt.options.description || 'Serverless deployment', - stageDescription: _this.evt.options.stage, - variables: { - functionAlias: _this.evt.options.stage - } - }; - - _this.provider.request('APIGateway', 'createDeployment', params, _this.evt.options.stage, _this.evt.options.region) - .then(function(response) { - - _this.deployment = response; - - SUtils.sDebug( - '"' - + _this.evt.options.stage - + ' - ' - + _this.evt.options.region - + ' - REST API: ' - + 'created API Gateway deployment: ' - + response.id); - - return resolve(); - }) - .catch(function(error) { - if( error.statusCode == 429 ) { - SUtils.sDebug("'Too many requests' received, sleeping 5 seconds"); - setTimeout( doDeploy, 5000 ); - } else - reject( new SError(error.message) ); - }); - }; - - return doDeploy(); - }); - } + const path = require('path'), + SError = require(path.join(serverlessPath, 'Error')), + SCli = require('../utils/cli'), + BbPromise = require('bluebird'), + async = require('async'), + fs = require('fs'); + let SUtils; + + // Promisify fs module + BbPromise.promisifyAll(fs); + + class EndpointDeployApiGateway extends SPlugin { + + constructor(S, config) { + super(S, config); + SUtils = S.utils; } - return( EndpointDeployApiGateway ); + static getName() { + return 'serverless.core.' + EndpointDeployApiGateway.name; + } + + registerActions() { + this.S.addAction(this.endpointDeployApiGateway.bind(this), { + handler: 'endpointDeployApiGateway', + description: 'Deploys a REST API to API Gateway in one or multiple regions' + }); + return Promise.resolve(); + } + + /** + * Handler + */ + + endpointDeployApiGateway(evt) { + + let _this = this; + _this.evt = evt; + _this.project = _this.S.getProject(); + _this.provider = _this.S.getProvider(); + _this.awsAccountNumber = _this.project.getRegion(_this.evt.options.stage, _this.evt.options.region).getVariables().iamRoleArnLambda.replace('arn:aws:iam::', '').split(':')[0]; + _this.regions = _this.evt.options.region ? [_this.evt.options.region] : _this.project.getAllRegionNames(_this.evt.options.stage); + _this.spinner = SCli.spinner(); + _this.endpoints = _this.project.getEndpointsByNames(_this.evt.options.names); + + return _this._validateAndPrepare() + .bind(_this) + .then(_this._processDeployment) + .then(function() { + + /** + * Return EVT + */ + + return _this.evt; + }); + } + + /** + * Validate And Prepare + */ + + _validateAndPrepare() { + return BbPromise.resolve(); + } + + /** + * Process Deployment + */ + + _processDeployment() { + + let _this = this; + + // Status + console.log(''); + SCli.log('Deploying endpoints in "' + _this.evt.options.stage + '" to the following regions: ' + _this.regions.join(', ')); + _this.spinner.start(); + + return BbPromise.try(function() { + return _this.regions; + }) + .bind(_this) + .each(function(region) { + + // Process each Region + return _this._processRegionDeployment(region); + }) + .then(function() { + + // Stop Spinner + _this.spinner.stop(true); + + }); + } + + /** + * Process Deployment In Region + */ + + _processRegionDeployment(region) { + + let _this = this; + + // Get or Create REST API for Region by name + let restApi; + if (_this.project.getRegion(_this.evt.options.stage, region).getVariables()['apiGatewayApi']) { + restApi = _this.project.getRegion(_this.evt.options.stage, region).getVariables()['apiGatewayApi']; + } else { + restApi = _this.project.name; + } + + return _this._findOrCreateRestApi( + restApi, + _this.evt.options.stage, + region) + .then(function(restApiData) { + + _this.restApiData = restApiData; + + let regionInstance = _this.project.getRegion(_this.evt.options.stage, region); + regionInstance.addVariables({ + apiGatewayApi: restApiData.name + }); + + return regionInstance.save(); + }) + .bind(_this) + .then(_this._createAuthorizers) + .then(function() { + + // Build REST API Endpoints + + return new BbPromise(function (resolve, reject) { + + // A function can have multiple endpoints. Process all endpoints for this Function + async.eachSeries(_this.endpoints, function (endpoint, eCb) { + + return BbPromise.try(function () { + + // Find authorizerId, if specified + let authorizerId; + if (endpoint.authorizerFunction) { + if (_this.authorizers[endpoint.authorizerFunction]) { + authorizerId = _this.authorizers[endpoint.authorizerFunction]; + } else { + throw new SError(`Endpoint ${endpoint.getName()} has an 'authorizerFunction' specified that does not exist in this project.`); + } + } + if (endpoint.authorizerId) { + authorizerId = endpoint.authorizerId; + } + + // Create new event object + let newEvt = { + options: { + stage: _this.evt.options.stage, + region: region, + name: endpoint.getName(), + authorizerId: authorizerId ? authorizerId : null, + aliasEndpoint: _this.evt.options.aliasEndpoint + } + }; + + return _this.S.actions.endpointBuildApiGateway(newEvt); + }) + .then(function (result) { + + // Stash deployed endpoints + if (!_this.evt.data.deployed) _this.evt.data.deployed = {}; + if (!_this.evt.data.deployed[region]) _this.evt.data.deployed[region] = []; + _this.evt.data.deployed[region].push({ + endpointPath: endpoint.path, + endpointMethod: endpoint.method, + endpointUrl: result.data.url + }); + + return eCb(); + }) + .catch(function (e) { + + // Stash Failed Endpoint + if (!_this.evt.data.failed) _this.evt.data.failed = {}; + if (!_this.evt.data.failed[region]) _this.evt.data.failed[region] = []; + _this.evt.data.failed[region].push({ + endpointPath: endpoint ? endpoint.path : 'unknown', + endpointMethod: endpoint ? endpoint.method : 'unknown', + message: e.message, + stack: e.stack + }); + + return eCb(); + }); + + }, function () { + return resolve(); + }); + }) + }) + .then(function() { + + // If no endpoints were successfully deployed, skip + if (!_this.evt.data.deployed || !_this.evt.data.deployed[region]) return; + + // Deploy API Gateway Deployment in region + return _this._createDeployment(); + }); + } + + /** + * Find Or Create REST API + */ + + _findOrCreateRestApi(restApiName, stage, region) { + let _this = this; + + return _this.provider.getApiByName(restApiName, stage, region) + .then(function(restApi) { + + // Return, if found + if (restApi) return restApi; + + // Otherwise, create new REST API + let params = { + name: restApiName, /* required */ + description: 'A REST API for a Serverless project in region: ' + region + }; + + return _this.provider.request('APIGateway', 'createRestApi', params, stage, region) + .then(function (response) { + + SUtils.sDebug( + '"' + + stage + + ' - ' + + region + + '": created a new REST API on AWS API Gateway with name: ' + + response.name); + + return response; + }); + }); + } + + /** + * Create Authorizers + */ + + _createAuthorizers() { + + let _this = this; + let functions = _this.project.getAllFunctions(); + _this.authorizers = {}; + + return BbPromise.try(function() { + + // Delete pre-existing on authorizers deployed on API Gateway + let params = { + restApiId: _this.restApiData.id, + limit: 100 + }; + + return _this.provider.request('APIGateway', 'getAuthorizers', params, _this.evt.options.stage, _this.evt.options.region) + .then(function(a) { + return a.items; + }); + }) + .each(function(a) { + + // Otherwise, delete pre-existing on authorizers deployed on API Gateway + let params = { + restApiId: _this.restApiData.id, + authorizerId: a.id + }; + + return _this.provider.request('APIGateway', 'deleteAuthorizer', params, _this.evt.options.stage, _this.evt.options.region); + }) + .then(function() { + return functions; + }) + .each(function(fn) { + + // If no authorizer data, skip + if (!fn.authorizer || !Object.keys(fn.authorizer).length) return; + + let f = fn.toObjectPopulated({ stage: _this.evt.options.stage, region: _this.evt.options.region }); + + // Create new authorizer on API Gateway + + // Fetch Lambda + let params = { + FunctionName: fn.getDeployedName({ stage: _this.evt.options.stage, region: _this.evt.options.region }), + Qualifier: _this.evt.options.stage + }; + + return _this.provider.request('Lambda', 'getFunction', params, _this.evt.options.stage, _this.evt.options.region) + .then(function(l) { + // Validate required authorizer params + if (!f.authorizer.identitySource) throw new SError(`Authorizer is missing identitySource property in function ${f.name}`); + + // Create Authorizer params. Set defaults. + let authorizer = f.authorizer; + authorizer.restApiId = _this.restApiData.id; + authorizer.name = authorizer.name || fn.getDeployedName({ stage: _this.evt.options.stage, region: _this.evt.options.region }); + authorizer.type = authorizer.type || 'TOKEN'; + + let alias = '${stageVariables.functionAlias}'; + + // Construct authorizer URI + authorizer.authorizerUri = 'arn:aws:apigateway:' + + _this.evt.options.region + + ':lambda:path/2015-03-31/functions/arn:aws:lambda:' + + _this.evt.options.region + + ':' + + _this.awsAccountNumber + + ':function:' + + fn.getDeployedName({ stage: _this.evt.options.stage, region: _this.evt.options.region }) + + ':' + + alias + + '/invocations'; + + return _this.provider.request('APIGateway', 'createAuthorizer', authorizer, _this.evt.options.stage, _this.evt.options.region) + .then(function(a) { + _this.authorizers[fn.name] = a.id; + }); + }); + }); + } + + /** + * Create Deployment + */ + + _createDeployment() { + + let _this = this; + + return new BbPromise( function( resolve, reject ){ + + let doDeploy = function() { + + let params = { + restApiId: _this.restApiData.id, /* required */ + stageName: _this.evt.options.stage, /* required */ + //cacheClusterEnabled: false, TODO: Implement + //cacheClusterSize: '0.5 | 1.6 | 6.1 | 13.5 | 28.4 | 58.2 | 118 | 237', TODO: Implement + description: _this.evt.options.description || 'Serverless deployment', + stageDescription: _this.evt.options.stage, + variables: { + functionAlias: _this.evt.options.stage + } + }; + + _this.provider.request('APIGateway', 'createDeployment', params, _this.evt.options.stage, _this.evt.options.region) + .then(function(response) { + + _this.deployment = response; + + SUtils.sDebug( + '"' + + _this.evt.options.stage + + ' - ' + + _this.evt.options.region + + ' - REST API: ' + + 'created API Gateway deployment: ' + + response.id); + + return resolve(); + }) + .catch(function(error) { + if( error.statusCode == 429 ) { + SUtils.sDebug("'Too many requests' received, sleeping 5 seconds"); + setTimeout( doDeploy, 5000 ); + } else + reject( new SError(error.message) ); + }); + }; + + return doDeploy(); + }); + } + } + + return( EndpointDeployApiGateway ); }; \ No newline at end of file diff --git a/lib/actions/EndpointRemove.js b/lib/actions/EndpointRemove.js index 84f3c5237..85692e3ed 100644 --- a/lib/actions/EndpointRemove.js +++ b/lib/actions/EndpointRemove.js @@ -157,7 +157,7 @@ module.exports = function(SPlugin, serverlessPath) { this.regions = this.evt.options.region ? [this.evt.options.region] : this.project.getAllRegionNames(this.evt.options.stage); this.endpoints = _.map(this.evt.options.names, (name) => { - const endpoint = this.project.getEndpoint(name.split('#')[0], name.split('#')[1]); + const endpoint = this.project.getEndpoint(name); if (!endpoint) throw new SError(`Endpoint "${name}" doesn't exist in your project`); return endpoint; }); diff --git a/lib/templates/plugin/index.js b/lib/templates/plugin/index.js index 3734338a8..edf15d374 100644 --- a/lib/templates/plugin/index.js +++ b/lib/templates/plugin/index.js @@ -20,7 +20,7 @@ module.exports = function(ServerlessPlugin) { // Always pass in the ServerlessPlugin Class - const path = require('path'), + const path = require('path'), fs = require('fs'), BbPromise = require('bluebird'); // Serverless uses Bluebird Promises and we recommend you do to because they provide more than your average Promise :) diff --git a/tests/all.js b/tests/all.js index 5fb5b617d..97e4d61ed 100644 --- a/tests/all.js +++ b/tests/all.js @@ -7,7 +7,7 @@ describe('All Tests', function() { before(function() {}); after(function() {}); - // require('./tests/classes/Project'); + // require('./tests/classes/Project'); // require('./tests/classes/Function'); // require('./tests/classes/Endpoint'); // require('./tests/classes/Stage'); @@ -23,7 +23,7 @@ describe('All Tests', function() { // require('./tests/actions/ResourcesDeploy'); // require('./tests/actions/FunctionRun'); // require('./tests/actions/FunctionLogs'); - // require('./tests/actions/FunctionDeploy'); + require('./tests/actions/FunctionDeploy'); require('./tests/actions/EndpointDeploy'); // require('./tests/actions/EventDeploy'); // require('./tests/actions/ProjectInit'); diff --git a/tests/test-prj/functions/group1/function1/s-function.json b/tests/test-prj/functions/group1/function1/s-function.json index 08eddaaeb..7d5ca0bb8 100644 --- a/tests/test-prj/functions/group1/function1/s-function.json +++ b/tests/test-prj/functions/group1/function1/s-function.json @@ -44,6 +44,7 @@ "path": "group1/function1", "method": "GET", "authorizationType": "${endpointVariable}", + "authorizerFunction": "function4", "apiKeyRequired": false, "requestParameters": "$${endpointTemplate}", "requestTemplates": "$${apiRequestTemplate}", diff --git a/tests/test-prj/functions/group1/group2/function4/s-function.json b/tests/test-prj/functions/group1/group2/function4/s-function.json index b23201ed4..c8ff7d917 100644 --- a/tests/test-prj/functions/group1/group2/function4/s-function.json +++ b/tests/test-prj/functions/group1/group2/function4/s-function.json @@ -9,17 +9,17 @@ "handler": "group2/function4/handler.handler", "timeout": 6, "memorySize": 1024, + "runtime": "nodejs", "authorizer": { + "type": "TOKEN", "identitySource": "method.request.header.Authorization" }, - "runtime": "nodejs", "events": [], "endpoints": [ { "path": "group2/function4", "method": "GET", "authorizationType": "none", - "authorizerFunction": "function4", "apiKeyRequired": false, "requestParameters": {}, "requestTemplates": { diff --git a/tests/tests/actions/FunctionDeploy.js b/tests/tests/actions/FunctionDeploy.js index c9f8fcb6b..32da0a8f8 100644 --- a/tests/tests/actions/FunctionDeploy.js +++ b/tests/tests/actions/FunctionDeploy.js @@ -97,29 +97,29 @@ describe('Test Action: Function Deploy', function() { * Tests */ - // describe('Function Deploy: Specify One Path', function() { - // it('should deploy functions', function(done) { - // - // this.timeout(0); - // - // let options = { - // stage: config.stage, - // region: config.region, - // names: [ - // 'function1' - // ] - // }; - // - // serverless.actions.functionDeploy(options) - // .then(function(evt) { - // validateEvent(evt); - // done(); - // }) - // .catch(e => { - // done(e); - // }); - // }); - // }); + describe('Function Deploy: Specify One Path', function() { + it('should deploy functions', function(done) { + + this.timeout(0); + + let options = { + stage: config.stage, + region: config.region, + names: [ + 'function1' + ] + }; + + serverless.actions.functionDeploy(options) + .then(function(evt) { + validateEvent(evt); + done(); + }) + .catch(e => { + done(e); + }); + }); + }); describe('Function Deploy: Nested W/ Custom Name & Limited Parent Dir', function() { it('should deploy functions', function(done) { diff --git a/tests/tests/classes/Endpoint.js b/tests/tests/classes/Endpoint.js index 642ab626d..bfa9f64c5 100644 --- a/tests/tests/classes/Endpoint.js +++ b/tests/tests/classes/Endpoint.js @@ -30,7 +30,7 @@ describe('Test Serverless Endpoint Class', function() { return serverless.init() .then(function() { - instance = serverless.getProject().getEndpoint('group1/function1', 'GET'); + instance = serverless.getProject().getEndpoint('group1/function1~GET'); done(); }); diff --git a/tests/tests/classes/Project.js b/tests/tests/classes/Project.js index b0960d815..a569d6238 100644 --- a/tests/tests/classes/Project.js +++ b/tests/tests/classes/Project.js @@ -92,7 +92,7 @@ describe('Test Serverless Project Class', function() { }); it('Get endpoints by path and method', function() { - let endpoint = instance.getEndpoint('group1/function1', 'GET'); + let endpoint = instance.getEndpoint('group1/function1~GET'); assert.isDefined(endpoint); });