mirror of
https://github.com/serverless/serverless.git
synced 2026-01-18 14:58:43 +00:00
Merge pull request #2679 from serverless/naming-js
Added logical ids in centralized file
This commit is contained in:
commit
7095f22b50
@ -17,8 +17,11 @@ module.exports = {
|
||||
throw new this.serverless.classes.Error('API Keys must be strings');
|
||||
}
|
||||
|
||||
const apiKeyLogicalId = this.provider.naming
|
||||
.getApiKeyLogicalId(apiKeyNumber);
|
||||
|
||||
_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources, {
|
||||
[`ApiGatewayApiKey${apiKeyNumber}`]: {
|
||||
[apiKeyLogicalId]: {
|
||||
Type: 'AWS::ApiGateway::ApiKey',
|
||||
Properties: {
|
||||
Enabled: true,
|
||||
|
||||
@ -31,10 +31,10 @@ module.exports = {
|
||||
});
|
||||
}
|
||||
|
||||
const normalizedAuthorizerName = _.capitalize(authorizer.name);
|
||||
const authorizerLogicalId = this.provider.naming.getAuthorizerLogicalId(authorizer.name);
|
||||
|
||||
_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources, {
|
||||
[`${normalizedAuthorizerName}ApiGatewayAuthorizer`]: {
|
||||
[authorizerLogicalId]: {
|
||||
Type: 'AWS::ApiGateway::Authorizer',
|
||||
Properties: authorizerProperties,
|
||||
},
|
||||
|
||||
@ -9,6 +9,8 @@ module.exports = {
|
||||
_.forEach(this.validated.corsPreflight, (config, path) => {
|
||||
const resourceName = this.getResourceName(path);
|
||||
const resourceRef = this.getResourceId(path);
|
||||
const corsMethodLogicalId = this.provider.naming
|
||||
.getMethodLogicalId(resourceName, 'options');
|
||||
|
||||
const preflightHeaders = {
|
||||
'Access-Control-Allow-Origin': `'${config.origins.join(',')}'`,
|
||||
@ -17,7 +19,7 @@ module.exports = {
|
||||
};
|
||||
|
||||
_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources, {
|
||||
[`ApiGatewayMethod${resourceName}Options`]: {
|
||||
[corsMethodLogicalId]: {
|
||||
Type: 'AWS::ApiGateway::Method',
|
||||
Properties: {
|
||||
AuthorizationType: 'NONE',
|
||||
|
||||
@ -5,7 +5,8 @@ const BbPromise = require('bluebird');
|
||||
|
||||
module.exports = {
|
||||
compileDeployment() {
|
||||
this.apiGatewayDeploymentLogicalId = `ApiGatewayDeployment${(new Date()).getTime().toString()}`;
|
||||
this.apiGatewayDeploymentLogicalId = this.provider.naming
|
||||
.generateApiGatewayDeploymentLogicalId();
|
||||
|
||||
_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources, {
|
||||
[this.apiGatewayDeploymentLogicalId]: {
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
|
||||
module.exports = {
|
||||
getMethodAuthorization(http) {
|
||||
if (http.authorizer) {
|
||||
const normalizedAuthorizerName = _.capitalize(http.authorizer.name);
|
||||
const authorizerLogicalId = `${normalizedAuthorizerName}ApiGatewayAuthorizer`;
|
||||
const authorizerLogicalId = this.provider.naming
|
||||
.getAuthorizerLogicalId(http.authorizer.name);
|
||||
|
||||
return {
|
||||
Properties: {
|
||||
|
||||
@ -33,8 +33,8 @@ module.exports = {
|
||||
this.getMethodResponses(event.http)
|
||||
);
|
||||
|
||||
const methodName = _.capitalize(event.http.method);
|
||||
const methodLogicalId = `ApiGatewayMethod${resourceName}${methodName}`;
|
||||
const methodLogicalId = this.provider.naming
|
||||
.getMethodLogicalId(resourceName, event.http.method);
|
||||
|
||||
this.apiGatewayMethodLogicalIds.push(methodLogicalId);
|
||||
|
||||
|
||||
@ -4,7 +4,8 @@ const _ = require('lodash');
|
||||
|
||||
module.exports = {
|
||||
getMethodIntegration(http, functionName) {
|
||||
const normalizedFunctionName = _.capitalize(functionName);
|
||||
const lambdaLogicalId = this.provider.naming
|
||||
.getLambdaLogicalId(functionName);
|
||||
const integration = {
|
||||
IntegrationHttpMethod: 'POST',
|
||||
Type: http.integration,
|
||||
@ -14,7 +15,7 @@ module.exports = {
|
||||
'arn:aws:apigateway:',
|
||||
{ Ref: 'AWS::Region' },
|
||||
':lambda:path/2015-03-31/functions/',
|
||||
{ 'Fn::GetAtt': [`${normalizedFunctionName}LambdaFunction`, 'Arn'] },
|
||||
{ 'Fn::GetAtt': [lambdaLogicalId, 'Arn'] },
|
||||
'/invocations',
|
||||
],
|
||||
],
|
||||
|
||||
@ -7,14 +7,17 @@ module.exports = {
|
||||
|
||||
compilePermissions() {
|
||||
this.validated.events.forEach((event) => {
|
||||
const normalizedFunctionName = _.capitalize(event.functionName);
|
||||
const lambdaPermissionLogicalId = this.provider.naming
|
||||
.getLambdaApiGatewayPermissionLogicalId(event.functionName);
|
||||
const lambdaLogicalId = this.provider.naming
|
||||
.getLambdaLogicalId(event.functionName);
|
||||
|
||||
_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources, {
|
||||
[`${normalizedFunctionName}LambdaPermissionApiGateway`]: {
|
||||
[lambdaPermissionLogicalId]: {
|
||||
Type: 'AWS::Lambda::Permission',
|
||||
Properties: {
|
||||
FunctionName: {
|
||||
'Fn::GetAtt': [`${normalizedFunctionName}LambdaFunction`, 'Arn'],
|
||||
'Fn::GetAtt': [lambdaLogicalId, 'Arn'],
|
||||
},
|
||||
Action: 'lambda:InvokeFunction',
|
||||
Principal: 'apigateway.amazonaws.com',
|
||||
@ -24,10 +27,11 @@ module.exports = {
|
||||
|
||||
if (event.http.authorizer) {
|
||||
const authorizer = event.http.authorizer;
|
||||
const normalizedAuthorizerName = _.capitalize(authorizer.name);
|
||||
const authorizerPermissionLogicalId = this.provider.naming
|
||||
.getLambdaApiGatewayPermissionLogicalId(authorizer.name);
|
||||
|
||||
_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources, {
|
||||
[`${normalizedAuthorizerName}LambdaPermissionApiGateway`]: {
|
||||
[authorizerPermissionLogicalId]: {
|
||||
Type: 'AWS::Lambda::Permission',
|
||||
Properties: {
|
||||
FunctionName: authorizer.arn,
|
||||
|
||||
@ -14,8 +14,8 @@ module.exports = {
|
||||
// ['users', 'users/create', 'users/create/something']
|
||||
resourcePaths.forEach(path => {
|
||||
const pathArray = path.split('/');
|
||||
const resourceName = pathArray.map(this.capitalizeAlphaNumericPath).join('');
|
||||
const resourceLogicalId = `ApiGatewayResource${resourceName}`;
|
||||
const resourceName = this.provider.naming.normalizePath(path);
|
||||
const resourceLogicalId = this.provider.naming.getResourceLogicalId(path);
|
||||
const pathPart = pathArray.pop();
|
||||
const parentPath = pathArray.join('/');
|
||||
const parentRef = this.getResourceId(parentPath);
|
||||
@ -56,15 +56,6 @@ module.exports = {
|
||||
return _.sortBy(paths, path => path.split('/').length);
|
||||
},
|
||||
|
||||
capitalizeAlphaNumericPath(path) {
|
||||
return _.upperFirst(
|
||||
_.capitalize(path)
|
||||
.replace(/-/g, 'Dash')
|
||||
.replace(/\{(.*)\}/g, '$1Var')
|
||||
.replace(/[^0-9A-Za-z]/g, '')
|
||||
);
|
||||
},
|
||||
|
||||
getResourceId(path) {
|
||||
if (path === '') {
|
||||
return { 'Fn::GetAtt': [this.apiGatewayRestApiLogicalId, 'RootResourceId'] };
|
||||
|
||||
@ -5,7 +5,7 @@ const BbPromise = require('bluebird');
|
||||
|
||||
module.exports = {
|
||||
compileRestApi() {
|
||||
this.apiGatewayRestApiLogicalId = 'ApiGatewayRestApi';
|
||||
this.apiGatewayRestApiLogicalId = this.provider.naming.getRestApiLogicalId();
|
||||
|
||||
_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources, {
|
||||
[this.apiGatewayRestApiLogicalId]: {
|
||||
|
||||
@ -192,12 +192,12 @@ module.exports = {
|
||||
arn = this.getLambdaArn(authorizer);
|
||||
} else {
|
||||
arn = authorizer;
|
||||
name = this.getLambdaName(arn);
|
||||
name = this.provider.naming.extractAuthorizerNameFromArn(arn);
|
||||
}
|
||||
} else if (typeof authorizer === 'object') {
|
||||
if (authorizer.arn) {
|
||||
arn = authorizer.arn;
|
||||
name = this.getLambdaName(arn);
|
||||
name = this.provider.naming.extractAuthorizerNameFromArn(arn);
|
||||
} else if (authorizer.name) {
|
||||
name = authorizer.name;
|
||||
arn = this.getLambdaArn(name);
|
||||
@ -375,8 +375,8 @@ module.exports = {
|
||||
|
||||
getLambdaArn(name) {
|
||||
this.serverless.service.getFunction(name);
|
||||
const normalizedName = _.capitalize(name);
|
||||
return { 'Fn::GetAtt': [`${normalizedName}LambdaFunction`, 'Arn'] };
|
||||
const lambdaLogicalId = this.provider.naming.getLambdaLogicalId(name);
|
||||
return { 'Fn::GetAtt': [lambdaLogicalId, 'Arn'] };
|
||||
},
|
||||
|
||||
getLambdaName(arn) {
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
const expect = require('chai').expect;
|
||||
const AwsCompileApigEvents = require('../index');
|
||||
const Serverless = require('../../../../../../../Serverless');
|
||||
const AwsProvider = require('../../../../../provider/awsProvider');
|
||||
|
||||
describe('#compileApiKeys()', () => {
|
||||
let serverless;
|
||||
@ -10,6 +11,7 @@ describe('#compileApiKeys()', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
serverless = new Serverless();
|
||||
serverless.setProvider('aws', new AwsProvider(serverless));
|
||||
serverless.service.service = 'first-service';
|
||||
serverless.service.provider = {
|
||||
name: 'aws',
|
||||
|
||||
@ -3,12 +3,15 @@
|
||||
const expect = require('chai').expect;
|
||||
const AwsCompileApigEvents = require('../index');
|
||||
const Serverless = require('../../../../../../../Serverless');
|
||||
const AwsProvider = require('../../../../../provider/awsProvider');
|
||||
|
||||
|
||||
describe('#compileAuthorizers()', () => {
|
||||
let awsCompileApigEvents;
|
||||
|
||||
beforeEach(() => {
|
||||
const serverless = new Serverless();
|
||||
serverless.setProvider('aws', new AwsProvider(serverless));
|
||||
serverless.service.service = 'first-service';
|
||||
serverless.service.provider.compiledCloudFormationTemplate = { Resources: {} };
|
||||
awsCompileApigEvents = new AwsCompileApigEvents(serverless);
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
const expect = require('chai').expect;
|
||||
const AwsCompileApigEvents = require('../index');
|
||||
const Serverless = require('../../../../../../../Serverless');
|
||||
const AwsProvider = require('../../../../../provider/awsProvider');
|
||||
|
||||
describe('#compileCors()', () => {
|
||||
let serverless;
|
||||
@ -10,6 +11,7 @@ describe('#compileCors()', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
serverless = new Serverless();
|
||||
serverless.setProvider('aws', new AwsProvider(serverless));
|
||||
serverless.service.service = 'first-service';
|
||||
serverless.service.provider.compiledCloudFormationTemplate = { Resources: {} };
|
||||
serverless.service.environment = {
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
const expect = require('chai').expect;
|
||||
const AwsCompileApigEvents = require('../index');
|
||||
const Serverless = require('../../../../../../../Serverless');
|
||||
const AwsProvider = require('../../../../../provider/awsProvider');
|
||||
|
||||
describe('#compileDeployment()', () => {
|
||||
let serverless;
|
||||
@ -10,6 +11,7 @@ describe('#compileDeployment()', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
serverless = new Serverless();
|
||||
serverless.setProvider('aws', new AwsProvider(serverless));
|
||||
serverless.service.provider.compiledCloudFormationTemplate = {
|
||||
Resources: {},
|
||||
Outputs: {},
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
const expect = require('chai').expect;
|
||||
const AwsCompileApigEvents = require('../index');
|
||||
const Serverless = require('../../../../../../../Serverless');
|
||||
const AwsProvider = require('../../../../../provider/awsProvider');
|
||||
|
||||
describe('#compileMethods()', () => {
|
||||
let serverless;
|
||||
@ -10,6 +11,7 @@ describe('#compileMethods()', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
serverless = new Serverless();
|
||||
serverless.setProvider('aws', new AwsProvider(serverless));
|
||||
serverless.service.service = 'first-service';
|
||||
serverless.service.provider.compiledCloudFormationTemplate = { Resources: {} };
|
||||
serverless.service.environment = {
|
||||
|
||||
@ -3,12 +3,14 @@
|
||||
const expect = require('chai').expect;
|
||||
const AwsCompileApigEvents = require('../index');
|
||||
const Serverless = require('../../../../../../../Serverless');
|
||||
const AwsProvider = require('../../../../../provider/awsProvider');
|
||||
|
||||
describe('#awsCompilePermissions()', () => {
|
||||
let awsCompileApigEvents;
|
||||
|
||||
beforeEach(() => {
|
||||
const serverless = new Serverless();
|
||||
serverless.setProvider('aws', new AwsProvider(serverless));
|
||||
serverless.service.provider.compiledCloudFormationTemplate = { Resources: {} };
|
||||
|
||||
awsCompileApigEvents = new AwsCompileApigEvents(serverless);
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
const expect = require('chai').expect;
|
||||
const AwsCompileApigEvents = require('../index');
|
||||
const Serverless = require('../../../../../../../Serverless');
|
||||
const AwsProvider = require('../../../../../provider/awsProvider');
|
||||
|
||||
describe('#compileResources()', () => {
|
||||
let serverless;
|
||||
@ -10,6 +11,7 @@ describe('#compileResources()', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
serverless = new Serverless();
|
||||
serverless.setProvider('aws', new AwsProvider(serverless));
|
||||
serverless.service.provider.compiledCloudFormationTemplate = { Resources: {} };
|
||||
awsCompileApigEvents = new AwsCompileApigEvents(serverless);
|
||||
awsCompileApigEvents.apiGatewayRestApiLogicalId = 'ApiGatewayRestApi';
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
const expect = require('chai').expect;
|
||||
const AwsCompileApigEvents = require('../index');
|
||||
const Serverless = require('../../../../../../../Serverless');
|
||||
const AwsProvider = require('../../../../../provider/awsProvider');
|
||||
|
||||
describe('#compileRestApi()', () => {
|
||||
let serverless;
|
||||
@ -21,6 +22,7 @@ describe('#compileRestApi()', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
serverless = new Serverless();
|
||||
serverless.setProvider('aws', new AwsProvider(serverless));
|
||||
serverless.service.provider.compiledCloudFormationTemplate = { Resources: {} };
|
||||
const options = {
|
||||
stage: 'dev',
|
||||
|
||||
@ -4,6 +4,7 @@ const expect = require('chai').expect;
|
||||
const sinon = require('sinon');
|
||||
const AwsCompileApigEvents = require('../index');
|
||||
const Serverless = require('../../../../../../../Serverless');
|
||||
const AwsProvider = require('../../../../../provider/awsProvider');
|
||||
|
||||
describe('#validate()', () => {
|
||||
let serverless;
|
||||
@ -11,6 +12,7 @@ describe('#validate()', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
serverless = new Serverless();
|
||||
serverless.setProvider('aws', new AwsProvider(serverless));
|
||||
const options = {
|
||||
stage: 'dev',
|
||||
region: 'us-east-1',
|
||||
|
||||
@ -78,8 +78,8 @@ class AwsCompileS3Events {
|
||||
.Error(errorMessage);
|
||||
}
|
||||
|
||||
const normalizedFunctionName = functionName[0].toUpperCase() +
|
||||
functionName.substr(1);
|
||||
const lambdaLogicalId = this.provider.naming
|
||||
.getLambdaLogicalId(functionName);
|
||||
|
||||
// check if the bucket already defined
|
||||
// in another S3 event in the service
|
||||
@ -88,7 +88,7 @@ class AwsCompileS3Events {
|
||||
Event: notificationEvent,
|
||||
Function: {
|
||||
'Fn::GetAtt': [
|
||||
`${normalizedFunctionName}LambdaFunction`,
|
||||
lambdaLogicalId,
|
||||
'Arn',
|
||||
],
|
||||
},
|
||||
@ -107,7 +107,7 @@ class AwsCompileS3Events {
|
||||
Event: notificationEvent,
|
||||
Function: {
|
||||
'Fn::GetAtt': [
|
||||
`${normalizedFunctionName}LambdaFunction`,
|
||||
lambdaLogicalId,
|
||||
'Arn',
|
||||
],
|
||||
},
|
||||
@ -138,13 +138,10 @@ class AwsCompileS3Events {
|
||||
},
|
||||
};
|
||||
|
||||
let normalizedBucketName = bucketName.replace(/[^0-9A-Za-z]/g, '');
|
||||
normalizedBucketName = normalizedBucketName[0].toUpperCase() +
|
||||
normalizedBucketName.substr(1);
|
||||
|
||||
const bucketLogicalID = `S3Bucket${normalizedBucketName}`;
|
||||
const bucketLogicalId = this.provider.naming
|
||||
.getBucketLogicalId(bucketName);
|
||||
const bucketCFResource = {
|
||||
[bucketLogicalID]: bucketTemplate,
|
||||
[bucketLogicalId]: bucketTemplate,
|
||||
};
|
||||
_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources,
|
||||
bucketCFResource);
|
||||
@ -154,14 +151,14 @@ class AwsCompileS3Events {
|
||||
// and give S3 permission to invoke them all
|
||||
// by adding Lambda::Permission resource for each
|
||||
s3EnabledFunctions.forEach(functionName => {
|
||||
const normalizedFunctionName = functionName[0].toUpperCase() +
|
||||
functionName.substr(1);
|
||||
const lambdaLogicalId = this.provider.naming
|
||||
.getLambdaLogicalId(functionName);
|
||||
const permissionTemplate = {
|
||||
Type: 'AWS::Lambda::Permission',
|
||||
Properties: {
|
||||
FunctionName: {
|
||||
'Fn::GetAtt': [
|
||||
`${normalizedFunctionName}LambdaFunction`,
|
||||
lambdaLogicalId,
|
||||
'Arn',
|
||||
],
|
||||
},
|
||||
@ -169,10 +166,10 @@ class AwsCompileS3Events {
|
||||
Principal: 's3.amazonaws.com',
|
||||
},
|
||||
};
|
||||
|
||||
const permissionLogicalID = `${normalizedFunctionName}LambdaPermissionS3`;
|
||||
const lambdaPermissionLogicalId = this.provider.naming
|
||||
.getLambdaS3PermissionLogicalId(functionName);
|
||||
const permissionCFResource = {
|
||||
[permissionLogicalID]: permissionTemplate,
|
||||
[lambdaPermissionLogicalId]: permissionTemplate,
|
||||
};
|
||||
_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources,
|
||||
permissionCFResource);
|
||||
|
||||
@ -74,7 +74,13 @@ class AwsCompileScheduledEvents {
|
||||
.Error(errorMessage);
|
||||
}
|
||||
|
||||
const normalizedFunctionName = functionName[0].toUpperCase() + functionName.substr(1);
|
||||
const lambdaLogicalId = this.provider.naming
|
||||
.getLambdaLogicalId(functionName);
|
||||
const scheduleLogicalId = this.provider.naming
|
||||
.getScheduleLogicalId(functionName, scheduleNumberInFunction);
|
||||
const lambdaPermissionLogicalId = this.provider.naming
|
||||
.getLambdaSchedulePermissionLogicalId(functionName, scheduleNumberInFunction);
|
||||
const scheduleId = this.provider.naming.getScheduleId(functionName);
|
||||
|
||||
const scheduleTemplate = `
|
||||
{
|
||||
@ -85,8 +91,8 @@ class AwsCompileScheduledEvents {
|
||||
"Targets": [{
|
||||
${Input ? `"Input": "${Input}",` : ''}
|
||||
${InputPath ? `"InputPath": "${InputPath}",` : ''}
|
||||
"Arn": { "Fn::GetAtt": ["${normalizedFunctionName}LambdaFunction", "Arn"] },
|
||||
"Id": "${functionName}Schedule"
|
||||
"Arn": { "Fn::GetAtt": ["${lambdaLogicalId}", "Arn"] },
|
||||
"Id": "${scheduleId}"
|
||||
}]
|
||||
}
|
||||
}
|
||||
@ -97,23 +103,20 @@ class AwsCompileScheduledEvents {
|
||||
"Type": "AWS::Lambda::Permission",
|
||||
"Properties": {
|
||||
"FunctionName": { "Fn::GetAtt": ["${
|
||||
normalizedFunctionName}LambdaFunction", "Arn"] },
|
||||
lambdaLogicalId}", "Arn"] },
|
||||
"Action": "lambda:InvokeFunction",
|
||||
"Principal": "events.amazonaws.com",
|
||||
"SourceArn": { "Fn::GetAtt": ["${
|
||||
normalizedFunctionName}EventsRuleSchedule${scheduleNumberInFunction}", "Arn"] }
|
||||
"SourceArn": { "Fn::GetAtt": ["${scheduleLogicalId}", "Arn"] }
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const newScheduleObject = {
|
||||
[`${normalizedFunctionName}EventsRuleSchedule${
|
||||
scheduleNumberInFunction}`]: JSON.parse(scheduleTemplate),
|
||||
[scheduleLogicalId]: JSON.parse(scheduleTemplate),
|
||||
};
|
||||
|
||||
const newPermissionObject = {
|
||||
[`${normalizedFunctionName}LambdaPermissionEventsRuleSchedule${
|
||||
scheduleNumberInFunction}`]: JSON.parse(permissionTemplate),
|
||||
[lambdaPermissionLogicalId]: JSON.parse(permissionTemplate),
|
||||
};
|
||||
|
||||
_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources,
|
||||
|
||||
@ -50,12 +50,12 @@ class AwsCompileSNSEvents {
|
||||
.Error(errorMessage);
|
||||
}
|
||||
|
||||
|
||||
const normalizedFunctionName = functionName[0].toUpperCase() +
|
||||
functionName.substr(1);
|
||||
let normalizedTopicName = topicName.replace(/[^0-9A-Za-z]/g, '');
|
||||
normalizedTopicName = normalizedTopicName[0].toUpperCase() +
|
||||
normalizedTopicName.substr(1);
|
||||
const lambdaLogicalId = this.provider.naming
|
||||
.getLambdaLogicalId(functionName);
|
||||
const topicLogicalId = this.provider.naming
|
||||
.getTopicLogicalId(topicName);
|
||||
const lambdaPermissionLogicalId = this.provider.naming
|
||||
.getLambdaSnsPermissionLogicalId(functionName, topicName);
|
||||
|
||||
const snsTemplate = `
|
||||
{
|
||||
@ -65,8 +65,7 @@ class AwsCompileSNSEvents {
|
||||
"DisplayName": "${displayName}",
|
||||
"Subscription": [
|
||||
{
|
||||
"Endpoint": { "Fn::GetAtt": ["${
|
||||
normalizedFunctionName}LambdaFunction", "Arn"] },
|
||||
"Endpoint": { "Fn::GetAtt": ["${lambdaLogicalId}", "Arn"] },
|
||||
"Protocol": "lambda"
|
||||
}
|
||||
]
|
||||
@ -78,8 +77,7 @@ class AwsCompileSNSEvents {
|
||||
{
|
||||
"Type": "AWS::Lambda::Permission",
|
||||
"Properties": {
|
||||
"FunctionName": { "Fn::GetAtt": ["${
|
||||
normalizedFunctionName}LambdaFunction", "Arn"] },
|
||||
"FunctionName": { "Fn::GetAtt": ["${lambdaLogicalId}", "Arn"] },
|
||||
"Action": "lambda:InvokeFunction",
|
||||
"Principal": "sns.amazonaws.com"
|
||||
}
|
||||
@ -87,12 +85,11 @@ class AwsCompileSNSEvents {
|
||||
`;
|
||||
|
||||
const newSNSObject = {
|
||||
[`SNSTopic${normalizedTopicName}`]: JSON.parse(snsTemplate),
|
||||
[topicLogicalId]: JSON.parse(snsTemplate),
|
||||
};
|
||||
|
||||
const newPermissionObject = {
|
||||
[`${normalizedFunctionName}LambdaPermission${
|
||||
normalizedTopicName}`]: JSON.parse(permissionTemplate),
|
||||
[lambdaPermissionLogicalId]: JSON.parse(permissionTemplate),
|
||||
};
|
||||
|
||||
// create new topic only if not created before
|
||||
@ -106,13 +103,13 @@ class AwsCompileSNSEvents {
|
||||
Protocol: 'lambda',
|
||||
Endpoint: {
|
||||
'Fn::GetAtt': [
|
||||
`${normalizedFunctionName}LambdaFunction`,
|
||||
lambdaLogicalId,
|
||||
'Arn',
|
||||
],
|
||||
},
|
||||
};
|
||||
this.serverless.service.provider.compiledCloudFormationTemplate
|
||||
.Resources[`SNSTopic${normalizedTopicName}`]
|
||||
.Resources[topicLogicalId]
|
||||
.Properties.Subscription.push(newSubscription);
|
||||
}
|
||||
|
||||
|
||||
@ -57,7 +57,13 @@ class AwsCompileStreamEvents {
|
||||
.Error(errorMessage);
|
||||
}
|
||||
|
||||
const normalizedFunctionName = functionName[0].toUpperCase() + functionName.substr(1);
|
||||
const streamType = EventSourceArn.split(':')[2];
|
||||
const streamName = EventSourceArn.split('/')[1];
|
||||
|
||||
const lambdaLogicalId = this.provider.naming
|
||||
.getLambdaLogicalId(functionName);
|
||||
const streamLogicalId = this.provider.naming
|
||||
.getStreamLogicalId(functionName, streamType, streamName);
|
||||
|
||||
const streamTemplate = `
|
||||
{
|
||||
@ -68,7 +74,7 @@ class AwsCompileStreamEvents {
|
||||
"EventSourceArn": "${EventSourceArn}",
|
||||
"FunctionName": {
|
||||
"Fn::GetAtt": [
|
||||
"${normalizedFunctionName}LambdaFunction",
|
||||
"${lambdaLogicalId}",
|
||||
"Arn"
|
||||
]
|
||||
},
|
||||
@ -78,15 +84,6 @@ class AwsCompileStreamEvents {
|
||||
}
|
||||
`;
|
||||
|
||||
// get the type (DynamoDB or Kinesis) of the stream
|
||||
const streamType = EventSourceArn.split(':')[2];
|
||||
const normalizedStreamType = streamType[0].toUpperCase() + streamType.substr(1);
|
||||
|
||||
// get the name of the stream (and remove any non-alphanumerics in it)
|
||||
const streamName = EventSourceArn.split('/')[1];
|
||||
const normalizedStreamName = streamName[0].toUpperCase()
|
||||
+ streamName.substr(1).replace(/[^A-Za-z0-9]/g, '');
|
||||
|
||||
// create type specific PolicyDocument statements
|
||||
let streamStatement = {};
|
||||
if (streamType === 'dynamodb') {
|
||||
@ -132,8 +129,7 @@ class AwsCompileStreamEvents {
|
||||
}
|
||||
|
||||
const newStreamObject = {
|
||||
[`${normalizedFunctionName}EventSourceMapping${
|
||||
normalizedStreamType}${normalizedStreamName}`]: JSON.parse(streamTemplate),
|
||||
[streamLogicalId]: JSON.parse(streamTemplate),
|
||||
};
|
||||
|
||||
_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources,
|
||||
|
||||
@ -103,8 +103,10 @@ class AwsCompileFunctions {
|
||||
delete newFunction.Properties.VpcConfig;
|
||||
}
|
||||
|
||||
const normalizedFunctionName = functionName[0].toUpperCase() + functionName.substr(1);
|
||||
const functionLogicalId = `${normalizedFunctionName}LambdaFunction`;
|
||||
const functionLogicalId = this.provider.naming
|
||||
.getLambdaLogicalId(functionName);
|
||||
const functionOutputLogicalId = this.provider.naming
|
||||
.getLambdaOutputLogicalId(functionName);
|
||||
const newFunctionObject = {
|
||||
[functionLogicalId]: newFunction,
|
||||
};
|
||||
@ -117,7 +119,7 @@ class AwsCompileFunctions {
|
||||
newOutput.Value = { 'Fn::GetAtt': [functionLogicalId, 'Arn'] };
|
||||
|
||||
const newOutputObject = {
|
||||
[`${functionLogicalId}Arn`]: newOutput,
|
||||
[functionOutputLogicalId]: newOutput,
|
||||
};
|
||||
|
||||
_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Outputs,
|
||||
|
||||
@ -7,7 +7,7 @@ const BbPromise = require('bluebird');
|
||||
module.exports = {
|
||||
create() {
|
||||
this.serverless.cli.log('Creating Stack…');
|
||||
const stackName = `${this.serverless.service.service}-${this.options.stage}`;
|
||||
const stackName = this.provider.naming.getStackName();
|
||||
let stackTags = { STAGE: this.options.stage };
|
||||
|
||||
// Merge additional stack tags
|
||||
@ -38,7 +38,7 @@ module.exports = {
|
||||
},
|
||||
|
||||
createStack() {
|
||||
const stackName = `${this.serverless.service.service}-${this.options.stage}`;
|
||||
const stackName = this.provider.naming.getStackName();
|
||||
if (/^[^a-zA-Z].+|.*[^a-zA-Z0-9-].*/.test(stackName) || stackName.length > 128) {
|
||||
const errorMessage = [
|
||||
`The stack service name "${stackName}" is not valid. `,
|
||||
|
||||
@ -79,10 +79,11 @@ module.exports = {
|
||||
} else {
|
||||
this.serverless.service.getAllFunctions().forEach((functionName) => {
|
||||
const functionObject = this.serverless.service.getFunction(functionName);
|
||||
const normalizedFunctionName = functionName[0].toUpperCase() + functionName.substr(1);
|
||||
const logGroupLogicalId = this.provider.naming
|
||||
.getLogGroupLogicalId(functionName);
|
||||
const logGroupTemplate = `
|
||||
{
|
||||
"${normalizedFunctionName}LogGroup": {
|
||||
"${logGroupLogicalId}": {
|
||||
"Type" : "AWS::Logs::LogGroup",
|
||||
"Properties" : {
|
||||
"LogGroupName" : "/aws/lambda/${functionObject.name}"
|
||||
@ -101,7 +102,7 @@ module.exports = {
|
||||
.PolicyDocument
|
||||
.Statement[0]
|
||||
.Resource
|
||||
.push({ 'Fn::GetAtt': [`${normalizedFunctionName}LogGroup`, 'Arn'] });
|
||||
.push({ 'Fn::GetAtt': [`${logGroupLogicalId}`, 'Arn'] });
|
||||
|
||||
this.serverless.service.provider.compiledCloudFormationTemplate
|
||||
.Resources
|
||||
@ -114,7 +115,7 @@ module.exports = {
|
||||
'Fn::Join': [
|
||||
':',
|
||||
[
|
||||
{ 'Fn::GetAtt': [`${normalizedFunctionName}LogGroup`, 'Arn'] },
|
||||
{ 'Fn::GetAtt': [`${logGroupLogicalId}`, 'Arn'] },
|
||||
'*',
|
||||
],
|
||||
],
|
||||
|
||||
@ -4,6 +4,7 @@ const path = require('path');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
const Serverless = require('../../../../Serverless');
|
||||
const AwsProvider = require('../../provider/awsProvider');
|
||||
const AwsDeploy = require('../');
|
||||
|
||||
describe('#mergeIamTemplates()', () => {
|
||||
@ -17,6 +18,7 @@ describe('#mergeIamTemplates()', () => {
|
||||
stage: 'dev',
|
||||
region: 'us-east-1',
|
||||
};
|
||||
serverless.setProvider('aws', new AwsProvider(serverless));
|
||||
awsDeploy = new AwsDeploy(serverless, options);
|
||||
awsDeploy.serverless.cli = new serverless.classes.CLI();
|
||||
awsDeploy.serverless.service.provider.compiledCloudFormationTemplate = {
|
||||
|
||||
@ -35,7 +35,7 @@ class AwsInfo {
|
||||
* Gather information about the service
|
||||
*/
|
||||
gather() {
|
||||
const stackName = this.provider.getStackName(this.options.stage);
|
||||
const stackName = this.provider.naming.getStackName(this.options.stage);
|
||||
const info = {
|
||||
service: this.serverless.service.service,
|
||||
stage: this.options.stage,
|
||||
@ -54,9 +54,15 @@ class AwsInfo {
|
||||
if (result) {
|
||||
outputs = result.Stacks[0].Outputs;
|
||||
|
||||
const lambdaArnOutputRegex = this.provider.naming
|
||||
.getLambdaOutputLogicalIdRegex();
|
||||
|
||||
const serviceEndpointOutputRegex = this.provider.naming
|
||||
.getServiceEndpointRegex();
|
||||
|
||||
// Functions
|
||||
info.functions = [];
|
||||
outputs.filter(x => x.OutputKey.match(/LambdaFunctionArn$/))
|
||||
outputs.filter(x => x.OutputKey.match(lambdaArnOutputRegex))
|
||||
.forEach(x => {
|
||||
const functionInfo = {};
|
||||
functionInfo.arn = x.OutputValue;
|
||||
@ -65,7 +71,7 @@ class AwsInfo {
|
||||
});
|
||||
|
||||
// Endpoints
|
||||
outputs.filter(x => x.OutputKey.match(/^ServiceEndpoint/))
|
||||
outputs.filter(x => x.OutputKey.match(serviceEndpointOutputRegex))
|
||||
.forEach(x => {
|
||||
info.endpoint = x.OutputValue;
|
||||
});
|
||||
|
||||
@ -170,7 +170,7 @@ describe('AwsInfo', () => {
|
||||
'CloudFormation',
|
||||
'describeStacks',
|
||||
{
|
||||
StackName: awsInfo.provider.getStackName(awsInfo.options.stage),
|
||||
StackName: awsInfo.provider.naming.getStackName(),
|
||||
},
|
||||
awsInfo.options.stage,
|
||||
awsInfo.options.region
|
||||
|
||||
153
lib/plugins/aws/lib/naming.js
Normal file
153
lib/plugins/aws/lib/naming.js
Normal file
@ -0,0 +1,153 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
|
||||
module.exports = {
|
||||
|
||||
// General
|
||||
normalizeName(name) {
|
||||
return `${_.upperFirst(name)}`;
|
||||
},
|
||||
normalizeNameToAlphaNumericOnly(name) {
|
||||
return this.normalizeName(name.replace(/[^0-9A-Za-z]/g, ''));
|
||||
},
|
||||
normalizePathPart(path) {
|
||||
return this.normalizeNameToAlphaNumericOnly(
|
||||
path.replace(/-/g, 'Dash')
|
||||
.replace(/\{(.*)\}/g, '$1Var'));
|
||||
},
|
||||
|
||||
getServiceEndpointRegex() {
|
||||
return /^ServiceEndpoint/;
|
||||
},
|
||||
|
||||
// Stack
|
||||
getStackName() {
|
||||
return `${this.sdk.serverless.service.service}-${this.sdk.getStage()}`;
|
||||
},
|
||||
|
||||
getLogGroupLogicalId(functionName) {
|
||||
return `${this.getNormalizedFunctionName(functionName)}LogGroup`;
|
||||
},
|
||||
|
||||
// Lambda
|
||||
getNormalizedFunctionName(functionName) {
|
||||
return this.normalizeName(functionName
|
||||
.replace(/-/g, 'Dash')
|
||||
.replace(/_/g, 'Underscore'));
|
||||
},
|
||||
extractLambdaNameFromArn(functionArn) {
|
||||
return functionArn.substring(functionArn.lastIndexOf(':') + 1);
|
||||
},
|
||||
extractAuthorizerNameFromArn(functionArn) {
|
||||
const splitArn = functionArn.split(':');
|
||||
// TODO the following two lines assumes default function naming? Is there a better way?
|
||||
// TODO (see ~/lib/classes/Service.js:~155)
|
||||
const splitName = splitArn[splitArn.length - 1].split('-');
|
||||
return splitName[splitName.length - 1];
|
||||
},
|
||||
getLambdaLogicalId(functionName) {
|
||||
return `${this.getNormalizedFunctionName(functionName)}LambdaFunction`;
|
||||
},
|
||||
getLambdaLogicalIdRegex() {
|
||||
return /LambdaFunction$/;
|
||||
},
|
||||
getLambdaOutputLogicalId(functionName) {
|
||||
return `${this.getLambdaLogicalId(functionName)}Arn`;
|
||||
},
|
||||
getLambdaOutputLogicalIdRegex() {
|
||||
return /LambdaFunctionArn$/;
|
||||
},
|
||||
|
||||
// API Gateway
|
||||
generateApiGatewayDeploymentLogicalId() {
|
||||
return `ApiGatewayDeployment${(new Date()).getTime().toString()}`;
|
||||
},
|
||||
getRestApiLogicalId() {
|
||||
return 'ApiGatewayRestApi';
|
||||
},
|
||||
getNormalizedAuthorizerName(functionName) {
|
||||
return this.getNormalizedFunctionName(functionName);
|
||||
},
|
||||
getAuthorizerLogicalId(functionName) {
|
||||
return `${this.getNormalizedAuthorizerName(functionName)}ApiGatewayAuthorizer`;
|
||||
},
|
||||
normalizePath(resourcePath) {
|
||||
return resourcePath.split('/').map(
|
||||
this.normalizePathPart.bind(this)
|
||||
).join('');
|
||||
},
|
||||
getResourceLogicalId(resourcePath) {
|
||||
return `ApiGatewayResource${this.normalizePath(resourcePath)}`;
|
||||
},
|
||||
extractResourceId(resourceLogicalId) {
|
||||
return resourceLogicalId.match(/ApiGatewayResource(.*)/)[1];
|
||||
},
|
||||
normalizeMethodName(methodName) {
|
||||
return this.normalizeName(methodName.toLowerCase());
|
||||
},
|
||||
getMethodLogicalId(resourceId, methodName) {
|
||||
return `ApiGatewayMethod${resourceId}${this.normalizeMethodName(methodName)}`;
|
||||
},
|
||||
getApiKeyLogicalId(apiKeyNumber) {
|
||||
return `ApiGatewayApiKey${apiKeyNumber}`;
|
||||
},
|
||||
getApiKeyLogicalIdRegex() {
|
||||
return /^ApiGatewayApiKey/;
|
||||
},
|
||||
|
||||
// S3
|
||||
getDeploymentBucketLogicalId() {
|
||||
return 'ServerlessDeploymentBucket';
|
||||
},
|
||||
getDeploymentBucketOutputLogicalId() {
|
||||
return 'ServerlessDeploymentBucketName';
|
||||
},
|
||||
normalizeBucketName(bucketName) {
|
||||
return this.normalizeNameToAlphaNumericOnly(bucketName);
|
||||
},
|
||||
getBucketLogicalId(bucketName) {
|
||||
return `S3Bucket${this.normalizeBucketName(bucketName)}`;
|
||||
},
|
||||
|
||||
// SNS
|
||||
normalizeTopicName(topicName) {
|
||||
return this.normalizeNameToAlphaNumericOnly(topicName);
|
||||
},
|
||||
getTopicLogicalId(topicName) {
|
||||
return `SNSTopic${this.normalizeTopicName(topicName)}`;
|
||||
},
|
||||
|
||||
// Schedule
|
||||
getScheduleId(functionName) {
|
||||
return `${functionName}Schedule`;
|
||||
},
|
||||
getScheduleLogicalId(functionName, scheduleIndex) {
|
||||
return `${this.getNormalizedFunctionName(functionName)}EventsRuleSchedule${scheduleIndex}`;
|
||||
},
|
||||
|
||||
// Stream
|
||||
getStreamLogicalId(functionName, streamType, streamName) {
|
||||
return `${
|
||||
this.getNormalizedFunctionName(functionName)
|
||||
}EventSourceMapping${
|
||||
this.normalizeName(streamType)
|
||||
}${this.normalizeNameToAlphaNumericOnly(streamName)}`;
|
||||
},
|
||||
|
||||
// Permissions
|
||||
getLambdaS3PermissionLogicalId(functionName) {
|
||||
return `${this.getNormalizedFunctionName(functionName)}LambdaPermissionS3`;
|
||||
},
|
||||
getLambdaSnsPermissionLogicalId(functionName, topicName) {
|
||||
return `${this.getNormalizedFunctionName(functionName)}LambdaPermission${
|
||||
this.normalizeTopicName(topicName)}`;
|
||||
},
|
||||
getLambdaSchedulePermissionLogicalId(functionName, scheduleIndex) {
|
||||
return `${this.getNormalizedFunctionName(functionName)}LambdaPermissionEventsRuleSchedule${
|
||||
scheduleIndex}`;
|
||||
},
|
||||
getLambdaApiGatewayPermissionLogicalId(functionName) {
|
||||
return `${this.getNormalizedFunctionName(functionName)}LambdaPermissionApiGateway`;
|
||||
},
|
||||
};
|
||||
@ -9,7 +9,7 @@ module.exports = {
|
||||
this.createLater = false;
|
||||
this.serverless.cli.log('Creating Stack...');
|
||||
|
||||
const stackName = `${this.serverless.service.service}-${this.options.stage}`;
|
||||
const stackName = this.provider.naming.getStackName();
|
||||
let stackTags = { STAGE: this.options.stage };
|
||||
const templateUrl = `https://s3.amazonaws.com/${
|
||||
this.bucketName
|
||||
@ -48,7 +48,7 @@ module.exports = {
|
||||
}/compiled-cloudformation-template.json`;
|
||||
|
||||
this.serverless.cli.log('Updating Stack…');
|
||||
const stackName = `${this.serverless.service.service}-${this.options.stage}`;
|
||||
const stackName = this.provider.naming.getStackName();
|
||||
let stackTags = { STAGE: this.options.stage };
|
||||
|
||||
// Merge additional stack tags
|
||||
|
||||
@ -1,9 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
const AWS = require('aws-sdk');
|
||||
const BbPromise = require('bluebird');
|
||||
const HttpsProxyAgent = require('https-proxy-agent');
|
||||
const url = require('url');
|
||||
const AWS = require('aws-sdk');
|
||||
|
||||
const naming = require('../lib/naming.js');
|
||||
|
||||
const constants = {
|
||||
providerName: 'aws',
|
||||
};
|
||||
|
||||
const impl = {
|
||||
/**
|
||||
@ -13,11 +19,11 @@ const impl = {
|
||||
*/
|
||||
addCredentials: (credentials, config) => {
|
||||
if (credentials &&
|
||||
config &&
|
||||
config.accessKeyId &&
|
||||
config.accessKeyId !== 'undefined' &&
|
||||
config.secretAccessKey &&
|
||||
config.secretAccessKey !== 'undefined') {
|
||||
config &&
|
||||
config.accessKeyId &&
|
||||
config.accessKeyId !== 'undefined' &&
|
||||
config.secretAccessKey &&
|
||||
config.secretAccessKey !== 'undefined') {
|
||||
if (config.accessKeyId) {
|
||||
credentials.accessKeyId = config.accessKeyId; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
@ -72,14 +78,18 @@ const impl = {
|
||||
|
||||
class AwsProvider {
|
||||
static getProviderName() {
|
||||
return 'aws';
|
||||
return constants.providerName;
|
||||
}
|
||||
|
||||
constructor(serverless) {
|
||||
constructor(serverless, options) {
|
||||
this.naming = { sdk: this };
|
||||
this.options = options;
|
||||
this.provider = this; // only load plugin in an AWS service context
|
||||
this.serverless = serverless;
|
||||
this.sdk = AWS;
|
||||
this.provider = this; // only load plugin in an AWS service context
|
||||
this.serverless.setProvider(this.constructor.getProviderName(), this);
|
||||
this.serverless.setProvider(constants.providerName, this);
|
||||
|
||||
Object.assign(this.naming, naming);
|
||||
|
||||
// Use HTTPS Proxy (Optional)
|
||||
const proxy = process.env.proxy
|
||||
@ -101,9 +111,9 @@ class AwsProvider {
|
||||
}
|
||||
}
|
||||
|
||||
request(service, method, params, stage, region) {
|
||||
request(service, method, params) {
|
||||
const that = this;
|
||||
const credentials = that.getCredentials(stage, region);
|
||||
const credentials = that.getCredentials();
|
||||
const persistentRequest = (f) => new BbPromise((resolve, reject) => {
|
||||
const doCall = () => {
|
||||
f()
|
||||
@ -124,7 +134,7 @@ class AwsProvider {
|
||||
const awsService = new that.sdk[service](credentials);
|
||||
const req = awsService[method](params);
|
||||
|
||||
// TODO: Add listeners, put Debug statments here…
|
||||
// TODO: Add listeners, put Debug statments here...
|
||||
// req.on('send', function (r) {console.log(r)});
|
||||
|
||||
return new BbPromise((resolve, reject) => {
|
||||
@ -151,14 +161,12 @@ class AwsProvider {
|
||||
/**
|
||||
* Fetch credentials directly or using a profile from serverless yml configuration or from the
|
||||
* well known environment variables
|
||||
* @param stage
|
||||
* @param region
|
||||
* @returns {{region: *}}
|
||||
*/
|
||||
getCredentials(stage, region) {
|
||||
const ret = { region };
|
||||
getCredentials() {
|
||||
const returnValue = { region: this.getRegion() };
|
||||
const credentials = {};
|
||||
const stageUpper = stage ? stage.toUpperCase() : null;
|
||||
const stageUpper = this.getStage() ? this.getStage().toUpperCase() : null;
|
||||
|
||||
// add specified credentials, overriding with more specific declarations
|
||||
impl.addCredentials(credentials, this.serverless.service.provider.credentials); // config creds
|
||||
@ -169,29 +177,46 @@ class AwsProvider {
|
||||
impl.addEnvironmentProfile(credentials, `AWS_${stageUpper}`);
|
||||
|
||||
if (Object.keys(credentials).length) {
|
||||
ret.credentials = credentials;
|
||||
returnValue.credentials = credentials;
|
||||
}
|
||||
return ret;
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
getServerlessDeploymentBucketName(stage, region) {
|
||||
getRegion() {
|
||||
let returnValue = 'us-east-1';
|
||||
if (this.options && this.options.region) {
|
||||
returnValue = this.options.region;
|
||||
} else if (this.serverless.config.region) {
|
||||
returnValue = this.serverless.config.region;
|
||||
} else if (this.serverless.service.provider.region) {
|
||||
returnValue = this.serverless.service.provider.region;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
getServerlessDeploymentBucketName() {
|
||||
if (this.serverless.service.provider.deploymentBucket) {
|
||||
return BbPromise.resolve(this.serverless.service.provider.deploymentBucket);
|
||||
}
|
||||
const stackName = `${this.serverless.service.service}-${stage}`;
|
||||
return this.request('CloudFormation',
|
||||
'describeStackResource',
|
||||
{
|
||||
StackName: stackName,
|
||||
LogicalResourceId: 'ServerlessDeploymentBucket',
|
||||
},
|
||||
stage,
|
||||
region
|
||||
StackName: this.naming.getStackName(),
|
||||
LogicalResourceId: this.naming.getDeploymentBucketLogicalId(),
|
||||
}
|
||||
).then((result) => result.StackResourceDetail.PhysicalResourceId);
|
||||
}
|
||||
|
||||
getStackName(stage) {
|
||||
return `${this.serverless.service.service}-${stage}`;
|
||||
getStage() {
|
||||
let returnValue = 'dev';
|
||||
if (this.options && this.options.stage) {
|
||||
returnValue = this.options.stage;
|
||||
} else if (this.serverless.config.stage) {
|
||||
returnValue = this.serverless.config.stage;
|
||||
} else if (this.serverless.service.provider.stage) {
|
||||
returnValue = this.serverless.service.provider.stage;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,21 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
const sinon = require('sinon');
|
||||
const BbPromise = require('bluebird');
|
||||
const expect = require('chai').expect;
|
||||
const Serverless = require('../../../Serverless');
|
||||
const AwsProvider = require('./awsProvider');
|
||||
const proxyquire = require('proxyquire');
|
||||
const sinon = require('sinon');
|
||||
|
||||
const AwsProvider = require('./awsProvider');
|
||||
const Serverless = require('../../../Serverless');
|
||||
|
||||
describe('AwsProvider', () => {
|
||||
let awsProvider;
|
||||
let serverless;
|
||||
const options = {
|
||||
stage: 'dev',
|
||||
region: 'us-east-1',
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
const options = {
|
||||
stage: 'dev',
|
||||
region: 'us-east-1',
|
||||
};
|
||||
serverless = new Serverless(options);
|
||||
awsProvider = new AwsProvider(serverless, options);
|
||||
awsProvider.serverless.cli = new serverless.classes.CLI();
|
||||
@ -42,7 +43,7 @@ describe('AwsProvider', () => {
|
||||
|
||||
it('should set AWS proxy', () => {
|
||||
process.env.proxy = 'http://a.b.c.d:n';
|
||||
const newAwsProvider = new AwsProvider(serverless);
|
||||
const newAwsProvider = new AwsProvider(serverless, options);
|
||||
|
||||
expect(typeof newAwsProvider.sdk.config.httpOptions.agent).to.not.equal('undefined');
|
||||
|
||||
@ -52,7 +53,7 @@ describe('AwsProvider', () => {
|
||||
|
||||
it('should set AWS timeout', () => {
|
||||
process.env.AWS_CLIENT_TIMEOUT = '120000';
|
||||
const newAwsProvider = new AwsProvider(serverless);
|
||||
const newAwsProvider = new AwsProvider(serverless, options);
|
||||
|
||||
expect(typeof newAwsProvider.sdk.config.httpOptions.timeout).to.not.equal('undefined');
|
||||
|
||||
@ -90,7 +91,7 @@ describe('AwsProvider', () => {
|
||||
},
|
||||
};
|
||||
|
||||
return awsProvider.request('S3', 'putObject', {}, 'dev', 'us-east-1').then(data => {
|
||||
return awsProvider.request('S3', 'putObject', {}).then(data => {
|
||||
expect(data.called).to.equal(true);
|
||||
});
|
||||
});
|
||||
@ -123,12 +124,10 @@ describe('AwsProvider', () => {
|
||||
awsProvider.sdk = {
|
||||
S3: FakeS3,
|
||||
};
|
||||
awsProvider.request('S3', 'error', {}, 'dev', 'us-east-1')
|
||||
awsProvider.request('S3', 'error', {})
|
||||
.then(data => {
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
expect(data).to.exist;
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
expect(first).to.be.false;
|
||||
expect(data).to.exist; // eslint-disable-line no-unused-expressions
|
||||
expect(first).to.be.false; // eslint-disable-line no-unused-expressions
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
@ -155,7 +154,7 @@ describe('AwsProvider', () => {
|
||||
awsProvider.sdk = {
|
||||
S3: FakeS3,
|
||||
};
|
||||
awsProvider.request('S3', 'error', {}, 'dev', 'us-east-1')
|
||||
awsProvider.request('S3', 'error', {})
|
||||
.then(() => done('Should not succeed'))
|
||||
.catch(() => done());
|
||||
});
|
||||
@ -181,7 +180,7 @@ describe('AwsProvider', () => {
|
||||
awsProvider.sdk = {
|
||||
S3: FakeS3,
|
||||
};
|
||||
awsProvider.request('S3', 'error', {}, 'dev', 'us-east-1')
|
||||
awsProvider.request('S3', 'error', {})
|
||||
.then(() => done('Should not succeed'))
|
||||
.catch((err) => {
|
||||
expect(err.message).to.contain('https://git.io/vXsdd');
|
||||
@ -203,14 +202,18 @@ describe('AwsProvider', () => {
|
||||
});
|
||||
|
||||
let newAwsProvider;
|
||||
const newOptions = {
|
||||
stage: 'teststage',
|
||||
region: 'testregion',
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
newAwsProvider = new AwsProviderProxyquired(serverless);
|
||||
newAwsProvider = new AwsProviderProxyquired(serverless, newOptions);
|
||||
});
|
||||
|
||||
it('should set region for credentials', () => {
|
||||
const credentials = newAwsProvider.getCredentials('teststage', 'testregion');
|
||||
expect(credentials.region).to.equal('testregion');
|
||||
const credentials = newAwsProvider.getCredentials();
|
||||
expect(credentials.region).to.equal(newOptions.region);
|
||||
});
|
||||
|
||||
it('should get credentials from provider', () => {
|
||||
@ -221,14 +224,14 @@ describe('AwsProvider', () => {
|
||||
|
||||
it('should not set credentials if empty profile is set', () => {
|
||||
serverless.service.provider.profile = '';
|
||||
const credentials = mockCreds(newAwsProvider.getCredentials('teststage', 'testregion'));
|
||||
expect(credentials).to.eql({ region: 'testregion' });
|
||||
const credentials = mockCreds(newAwsProvider.getCredentials());
|
||||
expect(credentials).to.eql({ region: newOptions.region });
|
||||
});
|
||||
|
||||
it('should not set credentials if credentials is an empty object', () => {
|
||||
serverless.service.provider.credentials = {};
|
||||
const credentials = mockCreds(newAwsProvider.getCredentials('teststage', 'testregion'));
|
||||
expect(credentials).to.eql({ region: 'testregion' });
|
||||
const credentials = mockCreds(newAwsProvider.getCredentials());
|
||||
expect(credentials).to.eql({ region: newOptions.region });
|
||||
});
|
||||
|
||||
it('should not set credentials if credentials has undefined values', () => {
|
||||
@ -237,8 +240,8 @@ describe('AwsProvider', () => {
|
||||
secretAccessKey: undefined,
|
||||
sessionToken: undefined,
|
||||
};
|
||||
const credentials = mockCreds(newAwsProvider.getCredentials('teststage', 'testregion'));
|
||||
expect(credentials).to.eql({ region: 'testregion' });
|
||||
const credentials = mockCreds(newAwsProvider.getCredentials());
|
||||
expect(credentials).to.eql({ region: newOptions.region });
|
||||
});
|
||||
|
||||
it('should not set credentials if credentials has empty string values', () => {
|
||||
@ -247,8 +250,8 @@ describe('AwsProvider', () => {
|
||||
secretAccessKey: '',
|
||||
sessionToken: '',
|
||||
};
|
||||
const credentials = mockCreds(newAwsProvider.getCredentials('teststage', 'testregion'));
|
||||
expect(credentials).to.eql({ region: 'testregion' });
|
||||
const credentials = mockCreds(newAwsProvider.getCredentials());
|
||||
expect(credentials).to.eql({ region: newOptions.region });
|
||||
});
|
||||
|
||||
it('should get credentials from provider declared credentials', () => {
|
||||
@ -265,7 +268,7 @@ describe('AwsProvider', () => {
|
||||
secretAccessKey: 'secretAccessKey',
|
||||
sessionToken: 'sessionToken',
|
||||
};
|
||||
const credentials = newAwsProvider.getCredentials('teststage', 'testregion');
|
||||
const credentials = newAwsProvider.getCredentials();
|
||||
expect(credentials.credentials).to.deep.eql(serverless.service.provider.credentials);
|
||||
|
||||
process.env.AWS_ACCESS_KEY_ID = tmpAccessKeyID;
|
||||
@ -287,7 +290,7 @@ describe('AwsProvider', () => {
|
||||
process.env.AWS_ACCESS_KEY_ID = testVal.accessKeyId;
|
||||
process.env.AWS_SECRET_ACCESS_KEY = testVal.secretAccessKey;
|
||||
process.env.AWS_SESSION_TOKEN = testVal.sessionToken;
|
||||
const credentials = newAwsProvider.getCredentials('teststage', 'testregion');
|
||||
const credentials = newAwsProvider.getCredentials();
|
||||
process.env.AWS_ACCESS_KEY_ID = prevVal.accessKeyId;
|
||||
process.env.AWS_SECRET_ACCESS_KEY = prevVal.secretAccessKey;
|
||||
process.env.AWS_SESSION_TOKEN = prevVal.sessionToken;
|
||||
@ -308,7 +311,7 @@ describe('AwsProvider', () => {
|
||||
process.env.AWS_TESTSTAGE_ACCESS_KEY_ID = testVal.accessKeyId;
|
||||
process.env.AWS_TESTSTAGE_SECRET_ACCESS_KEY = testVal.secretAccessKey;
|
||||
process.env.AWS_TESTSTAGE_SESSION_TOKEN = testVal.sessionToken;
|
||||
const credentials = newAwsProvider.getCredentials('teststage', 'testregion');
|
||||
const credentials = newAwsProvider.getCredentials();
|
||||
process.env.AWS_TESTSTAGE_ACCESS_KEY_ID = prevVal.accessKeyId;
|
||||
process.env.AWS_TESTSTAGE_SECRET_ACCESS_KEY = prevVal.secretAccessKey;
|
||||
process.env.AWS_TESTSTAGE_SESSION_TOKEN = prevVal.sessionToken;
|
||||
@ -317,14 +320,14 @@ describe('AwsProvider', () => {
|
||||
|
||||
it('should not set credentials if profile is not set', () => {
|
||||
serverless.service.provider.profile = undefined;
|
||||
const credentials = mockCreds(newAwsProvider.getCredentials('teststage', 'testregion'));
|
||||
expect(credentials).to.eql({ region: 'testregion' });
|
||||
const credentials = mockCreds(newAwsProvider.getCredentials());
|
||||
expect(credentials).to.eql({ region: newOptions.region });
|
||||
});
|
||||
|
||||
it('should not set credentials if empty profile is set', () => {
|
||||
serverless.service.provider.profile = '';
|
||||
const credentials = mockCreds(newAwsProvider.getCredentials('teststage', 'testregion'));
|
||||
expect(credentials).to.eql({ region: 'testregion' });
|
||||
const credentials = mockCreds(newAwsProvider.getCredentials());
|
||||
expect(credentials).to.eql({ region: newOptions.region });
|
||||
});
|
||||
|
||||
it('should get credentials from provider declared profile', () => {
|
||||
@ -344,19 +347,63 @@ describe('AwsProvider', () => {
|
||||
it('should get credentials from environment declared stage-specific profile', () => {
|
||||
const prevVal = process.env.AWS_TESTSTAGE_PROFILE;
|
||||
process.env.AWS_TESTSTAGE_PROFILE = 'notDefault';
|
||||
const credentials = newAwsProvider.getCredentials('teststage', 'testregion');
|
||||
const credentials = newAwsProvider.getCredentials();
|
||||
process.env.AWS_TESTSTAGE_PROFILE = prevVal;
|
||||
expect(credentials.credentials.profile).to.equal('notDefault');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getServerlessDeploymentBucketName', () => {
|
||||
it('should return the name of the serverless deployment bucket', () => {
|
||||
const options = {
|
||||
stage: 'dev',
|
||||
region: 'us-east-1',
|
||||
};
|
||||
describe('#getRegion()', () => {
|
||||
let newAwsProvider;
|
||||
|
||||
it('should prefer options over config or provider', () => {
|
||||
const newOptions = {
|
||||
region: 'optionsRegion',
|
||||
};
|
||||
const config = {
|
||||
region: 'configRegion',
|
||||
};
|
||||
serverless = new Serverless(config);
|
||||
serverless.service.provider.region = 'providerRegion';
|
||||
newAwsProvider = new AwsProvider(serverless, newOptions);
|
||||
|
||||
expect(newAwsProvider.getRegion()).to.equal(newOptions.region);
|
||||
});
|
||||
|
||||
it('should prefer config over provider in lieu of options', () => {
|
||||
const newOptions = {};
|
||||
const config = {
|
||||
region: 'configRegion',
|
||||
};
|
||||
serverless = new Serverless(config);
|
||||
serverless.service.provider.region = 'providerRegion';
|
||||
newAwsProvider = new AwsProvider(serverless, newOptions);
|
||||
|
||||
expect(newAwsProvider.getRegion()).to.equal(config.region);
|
||||
});
|
||||
|
||||
it('should use provider in lieu of options and config', () => {
|
||||
const newOptions = {};
|
||||
const config = {};
|
||||
serverless = new Serverless(config);
|
||||
serverless.service.provider.region = 'providerRegion';
|
||||
newAwsProvider = new AwsProvider(serverless, newOptions);
|
||||
|
||||
expect(newAwsProvider.getRegion()).to.equal(serverless.service.provider.region);
|
||||
});
|
||||
|
||||
it('should use the default us-east-1 in lieu of options, config, and provider', () => {
|
||||
const newOptions = {};
|
||||
const config = {};
|
||||
serverless = new Serverless(config);
|
||||
newAwsProvider = new AwsProvider(serverless, newOptions);
|
||||
|
||||
expect(newAwsProvider.getRegion()).to.equal('us-east-1');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getServerlessDeploymentBucketName()', () => {
|
||||
it('should return the name of the serverless deployment bucket', () => {
|
||||
const describeStackResourcesStub = sinon
|
||||
.stub(awsProvider, 'request')
|
||||
.returns(BbPromise.resolve({
|
||||
@ -365,7 +412,7 @@ describe('AwsProvider', () => {
|
||||
},
|
||||
}));
|
||||
|
||||
return awsProvider.getServerlessDeploymentBucketName(options.stage, options.region)
|
||||
return awsProvider.getServerlessDeploymentBucketName()
|
||||
.then((bucketName) => {
|
||||
expect(bucketName).to.equal('serverlessDeploymentBucketName');
|
||||
expect(describeStackResourcesStub.calledOnce).to.be.equal(true);
|
||||
@ -373,11 +420,9 @@ describe('AwsProvider', () => {
|
||||
'CloudFormation',
|
||||
'describeStackResource',
|
||||
{
|
||||
StackName: `${awsProvider.serverless.service.service}-${options.stage}`,
|
||||
StackName: awsProvider.naming.getStackName(),
|
||||
LogicalResourceId: 'ServerlessDeploymentBucket',
|
||||
},
|
||||
options.stage,
|
||||
options.region
|
||||
}
|
||||
)).to.be.equal(true);
|
||||
awsProvider.request.restore();
|
||||
});
|
||||
@ -385,10 +430,6 @@ describe('AwsProvider', () => {
|
||||
|
||||
it('should return the name of the custom deployment bucket', () => {
|
||||
awsProvider.serverless.service.provider.deploymentBucket = 'custom-bucket';
|
||||
const options = {
|
||||
stage: 'dev',
|
||||
region: 'us-east-1',
|
||||
};
|
||||
|
||||
const describeStackResourcesStub = sinon
|
||||
.stub(awsProvider, 'request')
|
||||
@ -398,20 +439,59 @@ describe('AwsProvider', () => {
|
||||
},
|
||||
}));
|
||||
|
||||
return awsProvider.getServerlessDeploymentBucketName(options.stage, options.region)
|
||||
return awsProvider.getServerlessDeploymentBucketName()
|
||||
.then((bucketName) => {
|
||||
expect(describeStackResourcesStub.called).to.be.equal(false);
|
||||
expect(bucketName).to.equal('custom-bucket');
|
||||
awsProvider.request.restore();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getStackName', () => {
|
||||
it('should return the stack name', () => {
|
||||
serverless.service.service = 'myservice';
|
||||
describe('#getStage()', () => {
|
||||
it('should prefer options over config or provider', () => {
|
||||
const newOptions = {
|
||||
stage: 'optionsStage',
|
||||
};
|
||||
const config = {
|
||||
stage: 'configStage',
|
||||
};
|
||||
serverless = new Serverless(config);
|
||||
serverless.service.provider.stage = 'providerStage';
|
||||
awsProvider = new AwsProvider(serverless, newOptions);
|
||||
|
||||
expect(awsProvider.getStackName('dev')).to.equal('myservice-dev');
|
||||
expect(awsProvider.getStage()).to.equal(newOptions.stage);
|
||||
});
|
||||
|
||||
it('should prefer config over provider in lieu of options', () => {
|
||||
const newOptions = {};
|
||||
const config = {
|
||||
stage: 'configStage',
|
||||
};
|
||||
serverless = new Serverless(config);
|
||||
serverless.service.provider.stage = 'providerStage';
|
||||
awsProvider = new AwsProvider(serverless, newOptions);
|
||||
|
||||
expect(awsProvider.getStage()).to.equal(config.stage);
|
||||
});
|
||||
|
||||
it('should use provider in lieu of options and config', () => {
|
||||
const newOptions = {};
|
||||
const config = {};
|
||||
serverless = new Serverless(config);
|
||||
serverless.service.provider.stage = 'providerStage';
|
||||
awsProvider = new AwsProvider(serverless, newOptions);
|
||||
|
||||
expect(awsProvider.getStage()).to.equal(serverless.service.provider.stage);
|
||||
});
|
||||
|
||||
it('should use the default dev in lieu of options, config, and provider', () => {
|
||||
const newOptions = {};
|
||||
const config = {};
|
||||
serverless = new Serverless(config);
|
||||
awsProvider = new AwsProvider(serverless, newOptions);
|
||||
|
||||
expect(awsProvider.getStage()).to.equal('dev');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
322
lib/plugins/aws/tests/naming.js
Normal file
322
lib/plugins/aws/tests/naming.js
Normal file
@ -0,0 +1,322 @@
|
||||
'use strict';
|
||||
|
||||
const expect = require('chai').expect;
|
||||
|
||||
const SDK = require('../provider/awsProvider');
|
||||
const Serverless = require('../../../Serverless');
|
||||
|
||||
describe('#naming()', () => {
|
||||
let options;
|
||||
let serverless;
|
||||
let sdk;
|
||||
|
||||
beforeEach(() => {
|
||||
options = {
|
||||
stage: 'dev',
|
||||
region: 'us-east-1',
|
||||
};
|
||||
serverless = new Serverless(options);
|
||||
sdk = new SDK(serverless, options);
|
||||
});
|
||||
|
||||
describe('#normalizeName()', () => {
|
||||
it('should capitalize the first letter', () => {
|
||||
expect(sdk.naming.normalizeName('name')).to.equal('Name');
|
||||
});
|
||||
|
||||
it('should have no effect on caps', () => {
|
||||
expect(sdk.naming.normalizeName('Name')).to.equal('Name');
|
||||
});
|
||||
|
||||
it('should have no effect on the rest of the name', () => {
|
||||
expect(sdk.naming.normalizeName('nAME')).to.equal('NAME');
|
||||
});
|
||||
});
|
||||
describe('#normalizeNameToAlphaNumericOnly()', () => {
|
||||
it('should strip non-alpha-numeric characters', () => {
|
||||
expect(sdk.naming
|
||||
.normalizeNameToAlphaNumericOnly('`!@#$%^&*()-={}|[]\\:";\'<>?,./')).to.equal('');
|
||||
});
|
||||
|
||||
it('should apply normalizeName to the remaining characters', () => {
|
||||
expect(sdk.naming.normalizeNameToAlphaNumericOnly('a-b-c')).to.equal('Abc');
|
||||
});
|
||||
});
|
||||
describe('#normalizeNameToCapitalAlphaNumbericOnly()', () => {
|
||||
it('converts `-` to `Dash`', () => {
|
||||
expect(sdk.naming.normalizePathPart(
|
||||
'a-path'
|
||||
)).to.equal('ADashpath');
|
||||
});
|
||||
|
||||
it('converts variable declarations (`${var}`) to `VariableVar`', () => {
|
||||
expect(sdk.naming.normalizePathPart(
|
||||
'${variable}'
|
||||
)).to.equal('VariableVar');
|
||||
});
|
||||
|
||||
it('converts variable declarations prefixes to `VariableVarPath`', () => {
|
||||
expect(sdk.naming.normalizePathPart(
|
||||
'${variable}Path'
|
||||
)).to.equal('VariableVarPath');
|
||||
});
|
||||
|
||||
it('converts variable declarations suffixes to `PathvariableVar`', () => {
|
||||
expect(sdk.naming.normalizePathPart(
|
||||
'path${variable}'
|
||||
)).to.equal('PathvariableVar');
|
||||
});
|
||||
|
||||
it('converts variable declarations in center to `PathvariableVarDir`', () => {
|
||||
expect(sdk.naming.normalizePathPart(
|
||||
'path${variable}Dir'
|
||||
)).to.equal('PathvariableVarDir');
|
||||
});
|
||||
});
|
||||
describe('#getServiceEndpointRegex()', () => {
|
||||
it('should match the prefix', () => {
|
||||
expect(sdk.naming.getServiceEndpointRegex().test('ServiceEndpoint'))
|
||||
.to.equal(true);
|
||||
});
|
||||
|
||||
it('should not match a name without the prefix', () => {
|
||||
expect(sdk.naming.getServiceEndpointRegex()
|
||||
.test('NotThePrefixServiceEndpoint')).to.equal(false);
|
||||
});
|
||||
|
||||
it('should match a name with the prefix', () => {
|
||||
expect(sdk.naming.getServiceEndpointRegex()
|
||||
.test('ServiceEndpointForAService')).to.equal(true);
|
||||
});
|
||||
});
|
||||
describe('#getStackName()', () => {
|
||||
it('should use the service name and stage from the service and config', () => {
|
||||
serverless.service.service = 'myService';
|
||||
expect(sdk.naming.getStackName()).to.equal(`${serverless.service.service}-${options.stage}`);
|
||||
});
|
||||
});
|
||||
describe('#getNormalizedFunctionName()', () => {
|
||||
it('should normalize the given functionName', () => {
|
||||
expect(sdk.naming.getNormalizedFunctionName('functionName'))
|
||||
.to.equal('FunctionName');
|
||||
});
|
||||
|
||||
it('should normalize the given functionName with an underscore', () => {
|
||||
expect(sdk.naming.getNormalizedFunctionName('hello_world'))
|
||||
.to.equal('HelloUnderscoreworld');
|
||||
});
|
||||
|
||||
it('should normalize the given functionName with a dash', () => {
|
||||
expect(sdk.naming.getNormalizedFunctionName('hello-world'))
|
||||
.to.equal('HelloDashworld');
|
||||
});
|
||||
});
|
||||
describe('#extractAuthorizerNameFromArn()', () => {
|
||||
it('should extract everything after the last colon and dash', () => {
|
||||
const arn = 'arn:aws:lambda:us-east-1:0123456789:my-dev-lambda';
|
||||
expect(sdk.naming.extractAuthorizerNameFromArn(arn)).to.equal('lambda');
|
||||
});
|
||||
});
|
||||
describe('#extractLambdaNameFromArn()', () => {
|
||||
it('should extract everything after the last colon', () => {
|
||||
const arn = 'arn:aws:lambda:us-east-1:0123456789:my-dev-lambda';
|
||||
expect(sdk.naming.extractLambdaNameFromArn(arn)).to.equal('my-dev-lambda');
|
||||
});
|
||||
});
|
||||
describe('#getLambdaLogicalId()', () => {
|
||||
it('should normalize the function name and add the logical suffix', () => {
|
||||
expect(sdk.naming.getLambdaLogicalId('functionName'))
|
||||
.to.equal('FunctionNameLambdaFunction');
|
||||
});
|
||||
});
|
||||
describe('#getLambdaLogicalIdRegex()', () => {
|
||||
it('should match the suffix', () => {
|
||||
expect(sdk.naming.getLambdaLogicalIdRegex()
|
||||
.test('LambdaFunction')).to.equal(true);
|
||||
});
|
||||
|
||||
it('should not match a name without the suffix', () => {
|
||||
expect(sdk.naming.getLambdaLogicalIdRegex()
|
||||
.test('LambdaFunctionNotTheSuffix')).to.equal(false);
|
||||
});
|
||||
|
||||
it('should match a name with the suffix', () => {
|
||||
expect(sdk.naming.getLambdaLogicalIdRegex()
|
||||
.test('AFunctionNameLambdaFunction')).to.equal(true);
|
||||
});
|
||||
});
|
||||
describe('#getLambdaOutputLogicalId()', () => {
|
||||
it('should normalize the function name and add the logical arn suffix', () => {
|
||||
expect(
|
||||
sdk.naming.getLambdaOutputLogicalId('functionName')
|
||||
).to.equal('FunctionNameLambdaFunctionArn');
|
||||
});
|
||||
});
|
||||
describe('#getLambdaOutputLogicalIdRegex()', () => {
|
||||
it('should match the suffix', () => {
|
||||
expect(sdk.naming.getLambdaOutputLogicalIdRegex()
|
||||
.test('aLambdaFunctionArn')).to.equal(true);
|
||||
});
|
||||
|
||||
it('should not match a name without the suffix', () => {
|
||||
expect(sdk.naming.getLambdaOutputLogicalIdRegex()
|
||||
.test('LambdaFunctionArnNotTheSuffix'))
|
||||
.to.equal(false);
|
||||
});
|
||||
|
||||
it('should match a name with the suffix', () => {
|
||||
expect(sdk.naming.getLambdaOutputLogicalIdRegex()
|
||||
.test('AFunctionArnNameLambdaFunctionArn'))
|
||||
.to.equal(true);
|
||||
});
|
||||
});
|
||||
describe('#generateApiGatewayDeploymentLogicalId()', () => {
|
||||
it('should return ApiGatewayDeployment with a date based suffix', () => {
|
||||
expect(sdk.naming.generateApiGatewayDeploymentLogicalId()
|
||||
.match(/ApiGatewayDeployment(.*)/).length)
|
||||
.to.be.greaterThan(1);
|
||||
});
|
||||
});
|
||||
describe('#getRestApiLogicalId()', () => {
|
||||
it('should return ApiGatewayRestApi', () => {
|
||||
expect(sdk.naming.getRestApiLogicalId()).to.equal('ApiGatewayRestApi');
|
||||
});
|
||||
});
|
||||
describe('#getNormalizedAuthorizerName()', () => {
|
||||
it('normalize the authorizer name', () => {
|
||||
expect(sdk.naming.getNormalizedAuthorizerName('authorizerName'))
|
||||
.to.equal('AuthorizerName');
|
||||
});
|
||||
});
|
||||
describe('#getAuthorizerLogicalId()', () => {
|
||||
it('should normalize the authorizer name and add the standard suffix', () => {
|
||||
expect(sdk.naming.getAuthorizerLogicalId('authorizerName'))
|
||||
.to.equal('AuthorizerNameApiGatewayAuthorizer');
|
||||
});
|
||||
});
|
||||
describe('#extractAuthorizerNameFromArn()', () => {
|
||||
it('should extract the authorizer name from an ARN', () => {
|
||||
const arn = 'arn:aws:lambda:us-east-1:0123456789:my-dev-lambda';
|
||||
expect(sdk.naming.extractAuthorizerNameFromArn(arn)).to.equal('lambda');
|
||||
});
|
||||
});
|
||||
describe('#normalizePath()', () => {
|
||||
it('should normalize each part of the resource path and remove non-alpha-numeric characters',
|
||||
() => {
|
||||
expect(sdk.naming.normalizePath(
|
||||
'my/path/to/a-${var}-resource'
|
||||
)).to.equal('MyPathToADashvarVarDashresource');
|
||||
});
|
||||
});
|
||||
describe('#getResourceLogicalId()', () => {
|
||||
it('should normalize the resource and add the standard suffix', () => {
|
||||
expect(sdk.naming.getResourceLogicalId(
|
||||
'my/path/to/a-${var}-resource'
|
||||
)).to.equal('ApiGatewayResourceMyPathToADashvarVarDashresource');
|
||||
});
|
||||
});
|
||||
describe('#extractResourceId()', () => {
|
||||
it('should extract the normalized resource name', () => {
|
||||
expect(sdk.naming.extractResourceId(
|
||||
'ApiGatewayResourceMyPathToADashvarVarDashResource'
|
||||
)).to.equal('MyPathToADashvarVarDashResource');
|
||||
});
|
||||
});
|
||||
describe('#normalizeMethodName()', () => {
|
||||
it('should capitalize the first letter and lowercase any other characters', () => {
|
||||
expect(sdk.naming.normalizeMethodName('gET')).to.equal('Get');
|
||||
});
|
||||
});
|
||||
describe('#getMethodLogicalId()', () => {
|
||||
it('', () => {
|
||||
expect(sdk.naming.getMethodLogicalId(
|
||||
'ResourceId', 'get'
|
||||
)).to.equal('ApiGatewayMethodResourceIdGet');
|
||||
});
|
||||
});
|
||||
describe('#getApiKeyLogicalIdRegex()', () => {
|
||||
it('should match the prefix', () => {
|
||||
expect(sdk.naming.getApiKeyLogicalIdRegex()
|
||||
.test('ApiGatewayApiKey')).to.equal(true);
|
||||
});
|
||||
|
||||
it('should not match a name without the prefix', () => {
|
||||
expect(sdk.naming.getApiKeyLogicalIdRegex()
|
||||
.test('NotThePrefixApiGatewayApiKey')).to.equal(false);
|
||||
});
|
||||
|
||||
it('should match a name with the prefix', () => {
|
||||
expect(sdk.naming.getApiKeyLogicalIdRegex()
|
||||
.test('ApiGatewayApiKeySuffix')).to.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getDeploymentBucketLogicalId()', () => {
|
||||
it('should return "ServerlessDeploymentBucket"', () => {
|
||||
expect(sdk.naming.getDeploymentBucketLogicalId()).to.equal('ServerlessDeploymentBucket');
|
||||
});
|
||||
});
|
||||
describe('#getDeploymentBucketOutputLogicalId()', () => {
|
||||
it('should return "ServerlessDeploymentBucketName"', () => {
|
||||
expect(sdk.naming.getDeploymentBucketOutputLogicalId())
|
||||
.to.equal('ServerlessDeploymentBucketName');
|
||||
});
|
||||
});
|
||||
describe('#normalizeBucketName()', () => {
|
||||
it('should remove all non-alpha-numeric characters and capitalize the first letter', () => {
|
||||
expect(sdk.naming.normalizeBucketName('b!u@c#k$e%t^N&a*m(e')).to.equal('BucketName');
|
||||
});
|
||||
});
|
||||
describe('#getBucketLogicalId()', () => {
|
||||
it('should normalize the bucket name and add the standard prefix', () => {
|
||||
expect(sdk.naming.getBucketLogicalId('b!u@c#k$e%t^N&a*m(e')).to.equal('S3BucketBucketName');
|
||||
});
|
||||
});
|
||||
describe('#normalizeTopicName()', () => {
|
||||
it('should remove all non-alpha-numeric characters and capitalize the first letter', () => {
|
||||
expect(sdk.naming.normalizeTopicName('t!o@p#i$c%N^a&m*e')).to.equal('TopicName');
|
||||
});
|
||||
});
|
||||
describe('#getTopicLogicalId()', () => {
|
||||
it('should remove all non-alpha-numeric characters and capitalize the first letter', () => {
|
||||
expect(sdk.naming.getTopicLogicalId('t!o@p#i$c%N^a&m*e')).to.equal('SNSTopicTopicName');
|
||||
});
|
||||
});
|
||||
describe('#getScheduleId()', () => {
|
||||
it('should add the standard suffix', () => {
|
||||
expect(sdk.naming.getScheduleId('functionName')).to.equal('functionNameSchedule');
|
||||
});
|
||||
});
|
||||
describe('#getScheduleLogicalId()', () => {
|
||||
it('should normalize the function name and add the standard suffix including the index', () => {
|
||||
expect(sdk.naming.getScheduleLogicalId('functionName', 0))
|
||||
.to.equal('FunctionNameEventsRuleSchedule0');
|
||||
});
|
||||
});
|
||||
describe('#getLambdaS3PermissionLogicalId()', () => {
|
||||
it('should normalize the function name and add the standard suffix', () => {
|
||||
expect(sdk.naming.getLambdaS3PermissionLogicalId('functionName'))
|
||||
.to.equal('FunctionNameLambdaPermissionS3');
|
||||
});
|
||||
});
|
||||
describe('#getLambdaSnsPermissionLogicalId()', () => {
|
||||
it('should normalize the function and topic names and add them as prefix and suffix to the ' +
|
||||
'standard permission center', () => {
|
||||
expect(sdk.naming.getLambdaSnsPermissionLogicalId('functionName', 'topicName'))
|
||||
.to.equal('FunctionNameLambdaPermissionTopicName');
|
||||
});
|
||||
});
|
||||
describe('#getLambdaSchedulePermissionLogicalId()', () => {
|
||||
it('should normalize the function name and add the standard suffix including event index',
|
||||
() => {
|
||||
expect(sdk.naming.getLambdaSchedulePermissionLogicalId('functionName', 0))
|
||||
.to.equal('FunctionNameLambdaPermissionEventsRuleSchedule0');
|
||||
});
|
||||
});
|
||||
describe('#getLambdaApiGatewayPermissionLogicalId()', () => {
|
||||
it('should normalize the function name and append the standard suffix', () => {
|
||||
expect(sdk.naming.getLambdaApiGatewayPermissionLogicalId('functionName'))
|
||||
.to.equal('FunctionNameLambdaPermissionApiGateway');
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -25,6 +25,7 @@ require('../lib/plugins/rollback/tests/rollback');
|
||||
// AWS Plugins Tests
|
||||
require('../lib/plugins/aws/provider/awsProvider.test');
|
||||
require('../lib/plugins/aws/tests/validate');
|
||||
require('../lib/plugins/aws/tests/naming');
|
||||
require('../lib/plugins/aws/tests/monitorStack');
|
||||
require('../lib/plugins/aws/tests/setBucketName');
|
||||
require('../lib/plugins/aws/tests/findAndGroupDeployments');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user