jaws-framework
Version:
JAWS is the serverless framework powered by Amazon Web Services.
1,003 lines (812 loc) • 28.7 kB
JavaScript
;
/**
* JAWS Command: deploy endpoint <stage> <region>
* - Deploys project's API Gateway REST API to the specified stage and one or all regions
*/
// TODO: On completion, list API G routes not used within the project (all regions). Offer option to delete them.
var JawsError = require('../jaws-error'),
JawsCli = require('../utils/cli'),
Promise = require('bluebird'),
fs = require('fs'),
async = require('async'),
path = require('path'),
utils = require('../utils/index'),
AWSUtils = require('../utils/aws'),
CMDtag = require('./tag'),
JawsAPIClient = require('jaws-api-gateway-client');
Promise.promisifyAll(fs);
/**
* Run
* @param JAWS
* @param stage
* @param region
* @param allTagged
* @returns {*}
*/
module.exports.run = function(JAWS, stage, region, allTagged) {
var command = new CMD(JAWS, stage, region, allTagged);
return command.run();
};
/**
* CMD Class
* @param JAWS
* @param stage
* @param region
* @param allTagged
* @constructor
*/
function CMD(JAWS, stage, region, allTagged) {
var _this = this;
_this._stage = stage;
_this._allTagged = allTagged;
_this._JAWS = JAWS;
_this._prjJson = JAWS._meta.projectJson;
_this._prjRootPath = JAWS._meta.projectRootPath;
_this._prjCreds = JAWS._meta.credentials;
if (region && stage) {
_this._regions = _this._JAWS._meta.projectJson.stages[_this._stage].filter(function(r) {
return (r.region == region);
});
} else if (stage) {
_this._regions = _this._JAWS._meta.projectJson.stages[_this._stage];
}
}
/**
* CMD: Run
*/
CMD.prototype.run = Promise.method(function() {
var _this = this;
// Flow
return _this._JAWS.validateProject()
.bind(_this)
.then(function() {
// If !allTagged, tag current directory
if (!_this._allTagged) {
return CMDtag.tag('endpoint', null, false);
}
})
.then(_this._promptStage)
.then(_this._promptRegions)
.then(function() {
return _this._regions;
})
.each(function(regionJson) {
JawsCli.log('Endpoint Deployer: Deploying endpoint(s) to region "' + regionJson.region + '"...');
var deployer = new ApiDeployer(
_this._JAWS,
_this._stage,
regionJson,
_this._prjRootPath,
_this._prjJson,
_this._prjCreds
);
return deployer.deploy()
.then(function(url) {
JawsCli.log('Endpoint Deployer: Endpoints for stage "'
+ _this._stage
+ '" successfully deployed to API Gateway in the region "'
+ regionJson.region
+ '". Access them @ '
+ url);
});
})
.then(function() {
// Untag All tagged endpoints
return _this._allTagged ? CMDtag.tagAll(_this._JAWS, 'endpoint', true) : CMDtag.tag('endpoint', null, true);
});
});
/**
* CMD: Prompt Stage
*/
CMD.prototype._promptStage = Promise.method(function() {
var _this = this;
// If stage, skip
if (_this._stage) return;
var stages = Object.keys(_this._prjJson.stages);
if (!stages.length) {
throw new JawsError('You have no stages in this project');
}
// If project has only one stage, skip select
if (stages.length === 1) {
_this._stage = stages[0];
return;
}
var choices = [];
for (var i = 0; i < stages.length; i++) {
choices.push({
key: '',
value: stages[i],
label: stages[i]
});
}
return JawsCli.select('Select a stage to deploy to: ', choices, false);
});
/**
* CMD: Prompt Regions
*/
CMD.prototype._promptRegions = Promise.method(function() {
var _this = this;
// If regions, skip
if (_this._regions && _this._regions.length) return;
var regions = _this._JAWS._meta.projectJson.stages[_this._stage];
// If stage has only one region, skip select
if (regions.length === 1) {
_this._regions = regions;
return;
}
var choices = [];
for (var i = 0; i < regions.length; i++) {
choices.push({
key: '',
value: regions[i].region,
label: regions[i].region,
});
}
return JawsCli.select('Select a region in this stage to deploy to: ', choices, false);
});
/**
* Api Deployer
* @param JAWS
* @param stage
* @param region
* @param prjRootPath
* @param prjJson
* @param prjCreds
* @constructor
*/
function ApiDeployer(JAWS, stage, region, prjRootPath, prjJson, prjCreds) {
var _this = this;
_this._JAWS = JAWS;
_this._stage = stage;
_this._regionJson = region;
_this._prjJson = prjJson;
_this._prjRootPath = prjRootPath;
_this._prjCreds = prjCreds;
_this._endpoints = [];
_this._resources = [];
_this._awsAccountNumber = _this._regionJson.iamRoleArnApiGateway.replace('arn:aws:iam::', '').split(':')[0];
_this._restApiId = _this._regionJson.restApiId ? _this._regionJson.restApiId : null;
// Instantiate API Gateway Client
this.ApiClient = new JawsAPIClient({
accessKeyId: prjCreds.aws_access_key_id,
secretAccessKey: prjCreds.aws_secret_access_key,
region: region.region,
});
}
/**
* API Deployer: Deploy
*/
ApiDeployer.prototype.deploy = Promise.method(function() {
var _this = this;
return _this._findTaggedEndpoints()
.bind(_this)
.then(_this._validateAndSantizeTaggedEndpoints)
.then(_this._fetchDeployedLambdas)
.then(_this._findOrCreateApi)
.then(_this._saveApiId)
.then(_this._listApiResources)
.then(_this._buildEndpoints)
.then(_this._createDeployment)
.then(function() {
return 'https://'
+ _this._restApiId
+ '.execute-api.'
+ _this._regionJson.region
+ '.amazonaws.com/'
+ _this._stage
+ '/';
});
});
/**
* ApiDeployer: Find Tagged Endpoints
*/
ApiDeployer.prototype._findTaggedEndpoints = Promise.method(function() {
var _this = this;
return utils.findAllEndpoints(_this._prjRootPath)
.each(function(endpoint) {
var eJson = require(endpoint);
if (eJson.apiGateway.deploy) _this._endpoints.push(eJson);
}).then(function() {
if (!_this._endpoints.length) {
throw new JawsError(
'You have no tagged endpoints',
JawsError.errorCodes.UNKNOWN);
}
JawsCli.log(
'Endpoint Deployer: "'
+ _this._stage + ' - '
+ _this._regionJson.region
+ '": found '
+ _this._endpoints.length + ' endpoints to deploy');
});
});
/**
* ApiDeployer: Fetch Deployed Lambdas In CF Stack
*/
ApiDeployer.prototype._fetchDeployedLambdas = Promise.method(function() {
var _this = this;
_this._lambdas = [];
var moreResources = true;
var nextStackToken;
async.whilst(
function() {
return moreResources === true;
},
function(callback) {
AWSUtils.cfListStackResources(
_this._JAWS._meta.profile,
_this._regionJson.region,
_this._stage + '-' + _this._JAWS._meta.projectJson.name + '-l',
nextStackToken
)
.then(function(lambdaCfResources) {
// Add deployed lambdas
if (lambdaCfResources.StackResourceSummaries) {
_this._lambdas = _this._lambdas.concat(lambdaCfResources.StackResourceSummaries);
}
// Check if more resources are available
if (!lambdaCfResources.NextToken) {
moreResources = false;
}
return callback();
})
.catch(function(error) {
JawsCli.log('Warning: JAWS could not find a deployed Cloudformation '
+ 'template containing lambda functions.');
console.log(error);
moreResources = false;
return callback();
});
},
function() {
return;
}
);
});
/**
* API Deployer: Validate & Sanitize Tagged Endpoints
*/
ApiDeployer.prototype._validateAndSantizeTaggedEndpoints = Promise.method(function() {
var _this = this;
// Loop through tagged endpoints
for (var i = 0; i < _this._endpoints.length; i++) {
var e = _this._endpoints[i].apiGateway.cloudFormation;
// Validate attributes
if (!e.Type
|| !e.Path
|| !e.Method
|| !e.AuthorizationType
|| typeof e.ApiKeyRequired === 'undefined') {
throw new JawsError(
'Missing one of many required endpoint attributes: type, path, method, authorizationType, apiKeyRequired',
JawsError.errorCodes.UNKNOWN);
}
// Sanitize path
if (e.Path.charAt(0) === '/') e.Path = e.Path.substring(1);
// Sanitize method
e.Method = e.Method.toUpperCase();
}
});
/**
* API Deployer: Save API ID
*/
ApiDeployer.prototype._saveApiId = Promise.method(function() {
var _this = this;
// Attach API Gateway REST API ID
for (var i = 0; i < _this._prjJson.stages[_this._stage].length; i++) {
if (_this._prjJson.stages[_this._stage][i].region === _this._regionJson.region) {
_this._prjJson.stages[_this._stage][i].restApiId = _this._restApiId;
}
}
fs.writeFileSync(path.join(_this._prjRootPath, 'jaws.json'), JSON.stringify(_this._prjJson, null, 2));
});
/**
* API Deployer: Find Or Create API
*/
ApiDeployer.prototype._findOrCreateApi = Promise.method(function() {
var _this = this;
// Check Project's jaws.json for restApiId, otherwise create an api
if (_this._restApiId) {
// Show existing REST API
return _this.ApiClient.showRestApi(_this._restApiId)
.then(function(response) {
_this._restApiId = response.id;
JawsCli.log(
'Endpoint Deployer: "'
+ _this._stage + ' - '
+ _this._regionJson.region
+ '": found existing REST API on AWS API Gateway with ID: '
+ response.id);
});
} else {
// Create REST API
var apiName = _this._prjJson.name + '-' + _this._stage;
apiName = apiName.substr( 0, 1023 ); // keep the name length below the limits
return _this.ApiClient.createRestApi({
name: apiName,
description: _this._prjJson.description ? _this._prjJson.description : 'A REST API for a JAWS project.',
}).then(function(response) {
_this._restApiId = response.id;
JawsCli.log(
'Endpoint Deployer: "'
+ _this._stage + ' - '
+ _this._regionJson.region
+ '": created a new REST API on AWS API Gateway with ID: '
+ response.id);
});
}
});
/**
* API Deployer: List API Resources
*/
ApiDeployer.prototype._listApiResources = Promise.method(function() {
var _this = this;
// List all Resources for this REST API
return _this.ApiClient.listResources(_this._restApiId)
.then(function(response) {
// Parse API Gateway's HAL response
_this._resources = response._embedded.item;
if (!Array.isArray(_this._resources)) _this._resources = [_this._resources];
// Get Parent Resource ID
for (var i = 0; i < _this._resources.length; i++) {
if (_this._resources[i].path === '/') {
_this._parentResourceId = _this._resources[i].id;
}
}
JawsCli.log(
'Endpoint Deployer: "'
+ _this._stage + ' - '
+ _this._regionJson.region
+ '": found '
+ _this._resources.length
+ ' existing resources on API Gateway');
});
});
/**
* API Deployer: Build Endpoints
*/
ApiDeployer.prototype._buildEndpoints = Promise.method(function() {
var _this = this;
return Promise.try(function() {
return _this._endpoints;
}).each(function(endpoint) {
return _this._createEndpointResources(endpoint)
.bind(_this)
.then(_this._createEndpointMethod)
.then(_this._createEndpointIntegration)
.then(_this._manageLambdaAccessPolicy)
.then(_this._createEndpointMethodResponses)
.then(_this._createEndpointMethodIntegResponses)
.then(function() {
// Clean-up hack
// TODO figure out how "apig" temp property is being written to the awsm's json and remove that
if (endpoint.apiGateway.apig) delete endpoint.apiGateway.apig;
});
});
});
/**
* API Deployer: Create Endpoint Resources
*/
ApiDeployer.prototype._createEndpointResources = Promise.method(function(endpoint) {
var _this = this;
var eResources = endpoint.apiGateway.cloudFormation.Path.split('/');
/**
* Private Function to find resource
* @param resource
* @param parent
* @returns {*}
*/
var findEndpointResource = function(resource, parent) {
// Replace slashes in resource
resource = resource.replace(/\//g, '');
var index = eResources.indexOf(resource);
if (parent) {
index = index - 1;
resource = eResources[index];
}
if (index < 0) {
resourcePath = '/';
} else {
var resourceIndex = endpoint.apiGateway.cloudFormation.Path.indexOf(resource);
var resourcePath = '/' + endpoint.apiGateway.cloudFormation.Path.substring(0, resourceIndex + resource.length);
}
// If resource has already been created, skip it
for (var i = 0; i < _this._resources.length; i++) {
// Check if path matches, in case there are duplicate resources (users/list, org/list)
if (_this._resources[i].path === resourcePath) {
return _this._resources[i];
}
}
};
// Create temp property for saving state information
endpoint.apiGateway.apig = {};
return Promise.try(function() {
return eResources;
}).each(function(eResource) {
// Remove slashes in resource
eResource = eResource.replace(/\//g, '');
// If resource exists, skip it
var resource = findEndpointResource(eResource);
if (resource) return resource;
// Get Parent Resource
endpoint.apiGateway.apig.parentResourceId = findEndpointResource(eResource, true).id;
// Create Resource
return _this.ApiClient.createResource(
_this._restApiId,
endpoint.apiGateway.apig.parentResourceId,
eResource)
.then(function(response) {
// Add resource to _this.resources and callback
_this._resources.push(response);
JawsCli.log(
'Endpoint Deployer: "' +
_this._stage + ' - '
+ _this._regionJson.region
+ ' - ' + endpoint.apiGateway.cloudFormation.Path + '": '
+ 'created resource: '
+ response.pathPart);
});
}).then(function() {
// Attach the last resource to endpoint for later use
var endpointResource = endpoint.apiGateway.cloudFormation.Path.split('/').pop().replace(/\//g, '');
endpoint.apiGateway.apig.resource = findEndpointResource(endpointResource);
return endpoint;
});
});
/**
* API Deployer: Create Endpoint Method
*/
ApiDeployer.prototype._createEndpointMethod = Promise.method(function(endpoint) {
var _this = this;
// Create Method
var methodBody = {
authorizationType: endpoint.apiGateway.cloudFormation.AuthorizationType,
};
// If Request Params, add them
if (endpoint.apiGateway.cloudFormation.RequestParameters) {
methodBody.requestParameters = {};
// Format them per APIG API's Expectations
for (var prop in endpoint.apiGateway.cloudFormation.RequestParameters) {
var requestParam = endpoint.apiGateway.cloudFormation.RequestParameters[prop];
methodBody.requestParameters[requestParam] = true;
}
}
return _this.ApiClient.showMethod(
_this._restApiId,
endpoint.apiGateway.apig.resource.id,
endpoint.apiGateway.cloudFormation.Method)
.then(function() {
return _this.ApiClient.deleteMethod(
_this._restApiId,
endpoint.apiGateway.apig.resource.id,
endpoint.apiGateway.cloudFormation.Method)
.then(function() {
_this.ApiClient.putMethod(
_this._restApiId,
endpoint.apiGateway.apig.resource.id,
endpoint.apiGateway.cloudFormation.Method,
methodBody);
});
}, function() {
return _this.ApiClient.putMethod(
_this._restApiId,
endpoint.apiGateway.apig.resource.id,
endpoint.apiGateway.cloudFormation.Method,
methodBody);
})
.delay(250) // API Gateway takes time to delete Methods. Might have to increase this.
.then(function(response) {
JawsCli.log(
'Endpoint Deployer: "'
+ _this._stage + ' - '
+ _this._regionJson.region
+ ' - ' + endpoint.apiGateway.cloudFormation.Path + '": '
+ 'created method: '
+ endpoint.apiGateway.cloudFormation.Method);
return endpoint;
});
});
/**
* API Deployer: Create Endpoint Integration
*/
ApiDeployer.prototype._createEndpointIntegration = Promise.method(function(endpoint) {
var _this = this;
// Create Integration
if (endpoint.type === 'lambda' || typeof endpoint.lambda !== 'undefined') {
// Find Deployed Lambda and its function name
var cfLogicalResourceId = utils.generateLambdaName(endpoint);
var lambda = null;
for (var i = 0; i < _this._lambdas.length; i++) {
if (_this._lambdas[i].LogicalResourceId === cfLogicalResourceId) {
lambda = _this._lambdas[i];
}
}
// If no deployed lambda found, throw error
if (!lambda) {
throw new JawsError('Could not find a lambda deployed in this stage/region with this function name: '
+ cfLogicalResourceId);
}
endpoint.apiGateway.apig.lambda = lambda;
// Create integration body
var integrationBody = {
type: 'AWS',
httpMethod: 'POST', // Must be post for lambda
authorizationType: 'none',
uri: 'arn:aws:apigateway:' // Make ARN for apigateway - lambda
+ _this._regionJson.region
+ ':lambda:path/2015-03-31/functions/arn:aws:lambda:'
+ _this._regionJson.region
+ ':'
+ _this._awsAccountNumber
+ ':function:'
+ lambda.PhysicalResourceId
+ '/invocations',
// Due to a bug in API Gateway reported here: https://github.com/awslabs/aws-apigateway-swagger-importer/issues/41
// Specifying credentials within API Gateway causes extra latency (~500ms)
// Until API Gateway is fixed, we need to make a seperate call to Lambda to add credentials to API Gateway
// Once API Gateway is fixed, we can use this in credentials:
// _this._regionJson.iamRoleArnApiGateway
credentials: null,
requestParameters: endpoint.apiGateway.cloudFormation.RequestParameters || {},
requestTemplates: endpoint.apiGateway.cloudFormation.RequestTemplates || {},
cacheNamespace: endpoint.apiGateway.cloudFormation.CacheNamespace || null,
cacheKeyParameters: endpoint.apiGateway.cloudFormation.CacheKeyParameters || [],
};
} else {
throw new JawsError('JAWS API Gateway integration currently works with Lambdas only.');
}
// Create Integration
return _this.ApiClient.putIntegration(
_this._restApiId,
endpoint.apiGateway.apig.resource.id,
endpoint.apiGateway.cloudFormation.Method,
integrationBody)
.then(function(response) {
// Save integration to apig property
endpoint.apiGateway.apig.integration = response;
JawsCli.log(
'Endpoint Deployer: "'
+ _this._stage + ' - '
+ _this._regionJson.region
+ ' - ' + endpoint.apiGateway.cloudFormation.Path + '": '
+ 'created integration with the type: '
+ endpoint.apiGateway.cloudFormation.Type);
return endpoint;
})
.catch(function(error) {
throw new JawsError(
error.message,
JawsError.errorCodes.UNKNOWN);
});
});
/**
* API Deployer: Create Endpoint Method Responses
*/
ApiDeployer.prototype._createEndpointMethodResponses = Promise.method(function(endpoint) {
var _this = this;
return Promise.try(function() {
// Collect Response Keys
if (endpoint.apiGateway.cloudFormation.Responses) return Object.keys(endpoint.apiGateway.cloudFormation.Responses);
else return [];
})
.each(function(responseKey) {
var thisResponse = endpoint.apiGateway.cloudFormation.Responses[responseKey];
var methodResponseBody = {};
// If Request Params, add them
if (thisResponse.responseParameters) {
methodResponseBody.responseParameters = {};
// Format Response Parameters per APIG API's Expectations
for (var prop in thisResponse.responseParameters) {
methodResponseBody.responseParameters[prop] = true;
}
}
// If Request models, add them
if (thisResponse.responseModels) {
methodResponseBody.responseModels = {};
// Format Response Models per APIG API's Expectations
for (var name in thisResponse.responseModels) {
var value = thisResponse.responseModels[ name ];
methodResponseBody.responseModels[name] = value;
}
}
// Create Method Response
return _this.ApiClient.putMethodResponse(
_this._restApiId,
endpoint.apiGateway.apig.resource.id,
endpoint.apiGateway.cloudFormation.Method,
thisResponse.statusCode,
methodResponseBody)
.then(function() {
JawsCli.log(
'Endpoint Deployer: "'
+ _this._stage
+ ' - '
+ _this._regionJson.region
+ ' - '
+ endpoint.apiGateway.cloudFormation.Path
+ '": '
+ 'created method response');
})
.catch(function(error) {
throw new JawsError(
error.message,
JawsError.errorCodes.UNKNOWN);
});
})
.then(function() {
return endpoint;
});
});
/**
* API Deployer: Create Endpoint Method Integration Responses
*/
ApiDeployer.prototype._createEndpointMethodIntegResponses = Promise.method(function(endpoint) {
var _this = this;
return Promise.try(function() {
// Collect Response Keys
if (endpoint.apiGateway.cloudFormation.Responses) return Object.keys(endpoint.apiGateway.cloudFormation.Responses);
else return [];
})
.each(function(responseKey) {
var thisResponse = endpoint.apiGateway.cloudFormation.Responses[responseKey];
var integrationResponseBody = {};
// Add Response Parameters
integrationResponseBody.responseParameters = thisResponse.responseParameters || {};
// Add Response Templates
integrationResponseBody.responseTemplates = thisResponse.responseTemplates || {};
// Add SelectionPattern
integrationResponseBody.selectionPattern = thisResponse.selectionPattern || (responseKey === 'default' ? null : responseKey);
// Create Integration Response
return _this.ApiClient.putIntegrationResponse(
_this._restApiId,
endpoint.apiGateway.apig.resource.id,
endpoint.apiGateway.cloudFormation.Method,
thisResponse.statusCode,
integrationResponseBody)
.then(function() {
JawsCli.log(
'Endpoint Deployer: "'
+ _this._stage
+ ' - '
+ _this._regionJson.region
+ ' - '
+ endpoint.apiGateway.cloudFormation.Path
+ '": '
+ 'created method integration response');
}).catch(function(error) {
throw new JawsError(
error.message,
JawsError.errorCodes.UNKNOWN);
});
});
});
ApiDeployer.prototype._manageLambdaAccessPolicy = Promise.method(function(endpoint) {
var _this = this;
// If method integration is not for a lambda, skip
if (!endpoint.apiGateway.apig.lambda) return endpoint;
return _this._getLambdaAccessPolicy(endpoint)
.bind(_this)
.then(_this._removeLambdaAccessPolicy)
.then(_this._updateLambdaAccessPolicy);
});
/**
* API Deployer: Get Lambda Access Policy
* - Since specifying credentials when creating the Method Integration results in ~500ms
* - of extra latency, this function updates the lambda's access policy instead
* - to grant API Gateway permission. This is how the API Gateway console does it.
* - But this is not finished and the "getPolicy" method in the SDK is broken, so this
* - is currently impossible to implement.
*/
ApiDeployer.prototype._getLambdaAccessPolicy = Promise.method(function(endpoint) {
var _this = this;
return AWSUtils.lambdaGetPolicy(
_this._JAWS._meta.profile,
_this._regionJson.region,
endpoint.apiGateway.apig.lambda.PhysicalResourceId)
.then(function(data) {
endpoint.apiGateway.apig.lambda.Policy = JSON.parse(data.Policy);
return endpoint;
})
.catch(function(error) {
return endpoint;
});
});
/**
* Remove Lambda Access Policy
*/
ApiDeployer.prototype._removeLambdaAccessPolicy = Promise.method(function(endpoint) {
var _this = this;
var statement;
if (endpoint.apiGateway.apig.lambda.Policy) {
var policy = endpoint.apiGateway.apig.lambda.Policy;
for (var i = 0; i < policy.Statement.length; i++) {
statement = policy.Statement[i];
if (statement.Sid && statement.Sid === 'jaws-apigateway-access') continue;
}
}
if (!statement) return endpoint;
return AWSUtils.lambdaRemovePermission(
_this._JAWS._meta.profile,
_this._regionJson.region,
endpoint.apiGateway.apig.lambda.PhysicalResourceId,
'jaws-apigateway-access')
.then(function(data) {
JawsCli.log(
'Endpoint Deployer: "'
+ _this._stage
+ ' - '
+ _this._regionJson.region
+ ' - '
+ endpoint.apiGateway.cloudFormation.Path
+ '": removed existing lambda access policy statement');
return endpoint;
})
.catch(function(error) {
console.log(error);
return endpoint;
});
});
/**
* Update Lambda Access Policy
*/
ApiDeployer.prototype._updateLambdaAccessPolicy = Promise.method(function(endpoint) {
var _this = this;
// Sanitize Path - Remove first and last slashes, if any
endpoint.apiGateway.cloudFormation.Path = endpoint.apiGateway.cloudFormation.Path.split('/');
endpoint.apiGateway.cloudFormation.Path = endpoint.apiGateway.cloudFormation.Path.join('/');
// Create new access policy statement
var statement = {};
statement.Action = 'lambda:InvokeFunction';
statement.FunctionName = endpoint.apiGateway.apig.lambda.PhysicalResourceId;
statement.Principal = 'apigateway.amazonaws.com';
statement.StatementId = 'jaws-apigateway-access';
statement.SourceArn = 'arn:aws:execute-api:'
+ _this._regionJson.region
+ ':'
+ _this._awsAccountNumber
+ ':'
+ _this._restApiId
+ '/*/'
+ endpoint.apiGateway.cloudFormation.Method
+ '/'
+ endpoint.apiGateway.cloudFormation.Path;
return AWSUtils.lambdaAddPermission(
_this._JAWS._meta.profile,
_this._regionJson.region,
statement)
.then(function(data) {
JawsCli.log(
'Endpoint Deployer: "'
+ _this._stage
+ ' - '
+ _this._regionJson.region
+ ' - '
+ endpoint.apiGateway.cloudFormation.Path
+ '": created new lambda access policy statement');
return endpoint;
})
.catch(function(error) {
console.log(error);
return endpoint;
});
});
/**
* API Deployer: Create Deployment
*/
ApiDeployer.prototype._createDeployment = Promise.method(function() {
var _this = this;
var deployment = {
stageName: _this._stage,
stageDescription: _this._stage,
description: 'JAWS deployment',
};
return _this.ApiClient.createDeployment(_this._restApiId, deployment)
.then(function(response) {
return response;
})
.catch(function(error) {
throw new JawsError(
error.message,
JawsError.errorCodes.UNKNOWN);
});
});