diff --git a/lib/plugins/aws/provider/awsProvider.js b/lib/plugins/aws/provider/awsProvider.js index 4456cc305..fc20ae9c6 100644 --- a/lib/plugins/aws/provider/awsProvider.js +++ b/lib/plugins/aws/provider/awsProvider.js @@ -19,7 +19,8 @@ const constants = { providerName: 'aws', }; -const validStageNamePattern = /^[a-zA-Z0-9]+$/; +const validCloudFrontStageNamePattern = /^[a-zA-Z0-9-]+$/; +const validAPIGatewayStageNamePattern = /^[a-zA-Z0-9_]+$/; PromiseQueue.configure(BbPromise.Promise); @@ -203,14 +204,24 @@ class AwsProvider { } const stage = this.getStage(); - if (!validStageNamePattern.test(stage)) { + if (!validCloudFrontStageNamePattern.test(stage)) { throw new Error([ `Invalid stage name ${stage}: `, - 'it should contains only [a-zA-Z0-9] for AWS provider ', - 'since API Gateway stage name cannot contain hyphens ', - 'and CloudFront stack name cannot contain underscores.', + 'it should contains only [a-zA-Z0-9] and hyphens for AWS provider.', ].join('')); } + + this.serverless.service.getAllFunctions().forEach(funcName => { + _.forEach(this.serverless.service.getAllEventsInFunction(funcName), event => { + if (_.has(event, 'http') && !validAPIGatewayStageNamePattern.test(stage)) { + throw new Error([ + `Invalid stage name ${stage}: `, + 'it should contains only [a-zA-Z0-9] for AWS provider if http event are present ', + 'since API Gateway stage name cannot contains hyphens.', + ].join('')); + } + }); + }); } /** diff --git a/lib/plugins/aws/provider/awsProvider.test.js b/lib/plugins/aws/provider/awsProvider.test.js index 50eed5237..d6a38f85a 100644 --- a/lib/plugins/aws/provider/awsProvider.test.js +++ b/lib/plugins/aws/provider/awsProvider.test.js @@ -91,7 +91,7 @@ describe('AwsProvider', () => { }); describe('validation on construction', () => { - it('should not throw if stage name contains only alphanumeric', () => { + it('should not throw an error if stage name contains only alphanumeric', () => { const config = { stage: 'configStage', }; @@ -99,14 +99,6 @@ describe('AwsProvider', () => { expect(() => new AwsProvider(serverless, config)).to.not.throw(Error); }); - it('should throw an error if stage name contains hyphen', () => { - const config = { - stage: 'config-stage', - }; - serverless = new Serverless(config); - expect(() => new AwsProvider(serverless, config)).to.throw(Error); - }); - it('should throw an error if stage name contains underscore', () => { const config = { stage: 'config_stage', @@ -123,6 +115,44 @@ describe('AwsProvider', () => { serverless = new Serverless(config); expect(() => new AwsProvider(serverless, config)).to.throw(Error); }); + + it('should not throw an error if stage contains hyphen but http events are absent', () => { + const config = { + stage: 'config-stage', + }; + serverless = new Serverless(config); + expect(() => new AwsProvider(serverless, config)).to.not.throw(Error); + }); + + it('should throw an error if stage contains hyphen and http events are present', () => { + const config = { + stage: 'config-stage', + }; + serverless = new Serverless(config); + + const serverlessYml = { + service: 'new-service', + provider: { + name: 'aws', + stage: 'config-stage', + }, + functions: { + first: { + events: [ + { + http: { + path: 'foo', + method: 'GET', + }, + }, + ], + }, + }, + }; + serverless.service = new serverless.classes.Service(serverless, serverlessYml); + + expect(() => new AwsProvider(serverless, config)).to.throw(Error); + }); }); describe('certificate authority - environment variable', () => {