From 44697b94b4b065c5ecd5c8dc262b2fe598f1e5ba Mon Sep 17 00:00:00 2001 From: Tyler Hogan Date: Wed, 24 Apr 2019 21:41:12 -0700 Subject: [PATCH] Allow Fn::Join in stream event arns --- docs/providers/aws/events/streams.md | 11 ++++ .../package/compile/events/stream/index.js | 8 ++- .../compile/events/stream/index.test.js | 66 +++++++++++++++---- 3 files changed, 70 insertions(+), 15 deletions(-) diff --git a/docs/providers/aws/events/streams.md b/docs/providers/aws/events/streams.md index 530eefb77..d4bee8e4c 100644 --- a/docs/providers/aws/events/streams.md +++ b/docs/providers/aws/events/streams.md @@ -44,6 +44,17 @@ functions: type: kinesis arn: Fn::ImportValue: MyExportedKinesisStreamArnId + - stream + type: kinesis + arn: + Fn::Join: + - ":" + - - arn + - aws + - kinesis + - Ref: AWS::Region + - Ref: AWS::AccountId + - MyOtherKinesisStream ``` ## Setting the BatchSize and StartingPosition diff --git a/lib/plugins/aws/package/compile/events/stream/index.js b/lib/plugins/aws/package/compile/events/stream/index.js index 61820a094..9fe115404 100644 --- a/lib/plugins/aws/package/compile/events/stream/index.js +++ b/lib/plugins/aws/package/compile/events/stream/index.js @@ -70,8 +70,9 @@ class AwsCompileStreamEvents { .Error(errorMessage); } if (Object.keys(event.stream.arn).length !== 1 - || !(_.has(event.stream.arn, 'Fn::ImportValue') - || _.has(event.stream.arn, 'Fn::GetAtt'))) { + || !(_.has(event.stream.arn, 'Fn::ImportValue') + || _.has(event.stream.arn, 'Fn::GetAtt') + || _.has(event.stream.arn, 'Fn::Join'))) { const errorMessage = [ `Bad dynamic ARN property on stream event in function "${functionName}"`, ' If you use a dynamic "arn" (such as with Fn::GetAtt or Fn::ImportValue)', @@ -109,6 +110,9 @@ class AwsCompileStreamEvents { return EventSourceArn['Fn::GetAtt'][0]; } else if (EventSourceArn['Fn::ImportValue']) { return EventSourceArn['Fn::ImportValue']; + } else if (EventSourceArn['Fn::Join']) { + // [0] is the used delimiter, [1] is the array with values + return EventSourceArn['Fn::Join'][1].slice(-1).pop(); } return EventSourceArn.split('/')[1]; }()); diff --git a/lib/plugins/aws/package/compile/events/stream/index.test.js b/lib/plugins/aws/package/compile/events/stream/index.test.js index 1571bab4e..d22c1c206 100644 --- a/lib/plugins/aws/package/compile/events/stream/index.test.js +++ b/lib/plugins/aws/package/compile/events/stream/index.test.js @@ -337,21 +337,21 @@ describe('AwsCompileStreamEvents', () => { .Properties.EventSourceArn ).to.equal( awsCompileStreamEvents.serverless.service.functions.first.events[0] - .stream.arn + .stream.arn ); expect(awsCompileStreamEvents.serverless.service .provider.compiledCloudFormationTemplate.Resources.FirstEventSourceMappingDynamodbFoo .Properties.BatchSize ).to.equal( awsCompileStreamEvents.serverless.service.functions.first.events[0] - .stream.batchSize + .stream.batchSize ); expect(awsCompileStreamEvents.serverless.service .provider.compiledCloudFormationTemplate.Resources.FirstEventSourceMappingDynamodbFoo .Properties.StartingPosition ).to.equal( awsCompileStreamEvents.serverless.service.functions.first.events[0] - .stream.startingPosition + .stream.startingPosition ); expect(awsCompileStreamEvents.serverless.service .provider.compiledCloudFormationTemplate.Resources.FirstEventSourceMappingDynamodbFoo @@ -372,7 +372,7 @@ describe('AwsCompileStreamEvents', () => { .Properties.EventSourceArn ).to.equal( awsCompileStreamEvents.serverless.service.functions.first.events[1] - .stream.arn + .stream.arn ); expect(awsCompileStreamEvents.serverless.service .provider.compiledCloudFormationTemplate.Resources.FirstEventSourceMappingDynamodbBar @@ -401,7 +401,7 @@ describe('AwsCompileStreamEvents', () => { .Properties.EventSourceArn ).to.equal( awsCompileStreamEvents.serverless.service.functions.first.events[2] - .stream + .stream ); expect(awsCompileStreamEvents.serverless.service .provider.compiledCloudFormationTemplate.Resources.FirstEventSourceMappingDynamodbBaz @@ -433,13 +433,30 @@ describe('AwsCompileStreamEvents', () => { type: 'kinesis', }, }, + { + stream: { + arn: { + 'Fn::Join': [ + ':', [ + 'arn', 'aws', 'kinesis', { + Ref: 'AWS::Region', + }, { + Ref: 'AWS::AccountId', + }, + 'MyStream', + ], + ], + }, + type: 'kinesis', + }, + }, ], }, }; awsCompileStreamEvents.compileStreamEvents(); - // dynamodb version + // dynamodb with Fn::GetAtt expect(awsCompileStreamEvents.serverless.service .provider.compiledCloudFormationTemplate.Resources .FirstEventSourceMappingDynamodbSomeDdbTable.Properties.EventSourceArn @@ -468,13 +485,36 @@ describe('AwsCompileStreamEvents', () => { ], } ); - // and now kinesis + + // kinesis with Fn::ImportValue expect(awsCompileStreamEvents.serverless.service .provider.compiledCloudFormationTemplate.Resources .FirstEventSourceMappingKinesisForeignKinesis.Properties.EventSourceArn ).to.deep.equal( { 'Fn::ImportValue': 'ForeignKinesis' } ); + + // kinesis with Fn::Join + expect(awsCompileStreamEvents.serverless.service + .provider.compiledCloudFormationTemplate.Resources + .FirstEventSourceMappingKinesisMyStream.Properties.EventSourceArn + ).to.deep.equal( + { + 'Fn::Join': [ + ':', [ + 'arn', + 'aws', + 'kinesis', + { + Ref: 'AWS::Region', + }, { + Ref: 'AWS::AccountId', + }, + 'MyStream', + ], + ], + } + ); }); it('fails if Fn::GetAtt/dynamic stream ARN is used without a type', () => { @@ -493,7 +533,7 @@ describe('AwsCompileStreamEvents', () => { expect(() => awsCompileStreamEvents.compileStreamEvents()).to.throw(Error); }); - it('fails if keys other than Fn::GetAtt/ImportValue are used for dynamic stream ARN', () => { + it('fails if keys other than Fn::GetAtt/ImportValue/Join are used for dynamic stream ARN', () => { awsCompileStreamEvents.serverless.service.functions = { first: { events: [ @@ -594,21 +634,21 @@ describe('AwsCompileStreamEvents', () => { .Properties.EventSourceArn ).to.equal( awsCompileStreamEvents.serverless.service.functions.first.events[0] - .stream.arn + .stream.arn ); expect(awsCompileStreamEvents.serverless.service .provider.compiledCloudFormationTemplate.Resources.FirstEventSourceMappingKinesisFoo .Properties.BatchSize ).to.equal( awsCompileStreamEvents.serverless.service.functions.first.events[0] - .stream.batchSize + .stream.batchSize ); expect(awsCompileStreamEvents.serverless.service .provider.compiledCloudFormationTemplate.Resources.FirstEventSourceMappingKinesisFoo .Properties.StartingPosition ).to.equal( awsCompileStreamEvents.serverless.service.functions.first.events[0] - .stream.startingPosition + .stream.startingPosition ); expect(awsCompileStreamEvents.serverless.service .provider.compiledCloudFormationTemplate.Resources.FirstEventSourceMappingKinesisFoo @@ -629,7 +669,7 @@ describe('AwsCompileStreamEvents', () => { .Properties.EventSourceArn ).to.equal( awsCompileStreamEvents.serverless.service.functions.first.events[1] - .stream.arn + .stream.arn ); expect(awsCompileStreamEvents.serverless.service .provider.compiledCloudFormationTemplate.Resources.FirstEventSourceMappingKinesisBar @@ -658,7 +698,7 @@ describe('AwsCompileStreamEvents', () => { .Properties.EventSourceArn ).to.equal( awsCompileStreamEvents.serverless.service.functions.first.events[2] - .stream + .stream ); expect(awsCompileStreamEvents.serverless.service .provider.compiledCloudFormationTemplate.Resources.FirstEventSourceMappingKinesisBaz