Merge pull request #6445 from zvymazal/fix/cross_account_sns_events

Fix cross-account/cross-regions SNS subscriptions to topics with the same name
This commit is contained in:
Philipp Muens 2019-07-26 13:28:14 +02:00 committed by GitHub
commit a768e2fe52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 84 additions and 3 deletions

View File

@ -80,7 +80,20 @@ functions:
topicName: MyCustomTopic
```
**Note:** If an `arn` string is specified but not a `topicName`, the last substring starting with `:` will be extracted as the `topicName`. If an `arn` object is specified, `topicName` must be specified as a string, used only to name the underlying Cloudformation mapping resources.
**Note:** If an `arn` string is specified but not a `topicName`, the last substring starting with `:` will be extracted as the `topicName`. If an `arn` object is specified, `topicName` must be specified as a string, used only to name the underlying Cloudformation mapping resources. You can take advantage of this behavior when subscribing to multiple topics with the same name in different regions/accounts to avoid collisions between Cloudformation resource names.
```yml
functions:
hello:
handler: handler.run
events:
- sns:
arn: arn:aws:sns:us-east-1:00000000000:topicname
topicName: topicname-account-1-us-east-1
- sns:
arn: arn:aws:sns:us-east-1:11111111111:topicname
topicName: topicname-account-2-us-east-1
```
## Setting a display name

View File

@ -77,7 +77,7 @@ class AwsCompileSNSEvents {
this.invalidPropertyErrorMessage(functionName, 'arn')
);
}
topicName = topicName || event.sns.topicName;
topicName = event.sns.topicName || topicName;
if (!topicName || typeof topicName !== 'string') {
throw new this.serverless.classes.Error(
this.invalidPropertyErrorMessage(functionName, 'topicName')

View File

@ -327,7 +327,7 @@ describe('AwsCompileSNSEvents', () => {
}).to.throw(Error);
});
it('should create SNS topic when arn and topicName are given as object properties', () => {
it('should create SNS topic when both arn and topicName are given as object properties', () => {
awsCompileSNSEvents.serverless.service.functions = {
first: {
events: [
@ -358,6 +358,74 @@ describe('AwsCompileSNSEvents', () => {
).to.equal('AWS::Lambda::Permission');
});
it('should create two SNS topic subsriptions for ARNs with the same topic name in two regions when different topicName parameters are specified', () => {
awsCompileSNSEvents.serverless.service.functions = {
first: {
events: [
{
sns: {
topicName: 'first',
arn: 'arn:aws:sns:region-1:accountid:bar',
},
},
{
sns: {
topicName: 'second',
arn: 'arn:aws:sns:region-2:accountid:bar',
},
},
],
},
};
awsCompileSNSEvents.compileSNSEvents();
expect(
Object.keys(
awsCompileSNSEvents.serverless.service.provider.compiledCloudFormationTemplate.Resources
)
).to.have.length(4);
expect(
awsCompileSNSEvents.serverless.service.provider.compiledCloudFormationTemplate.Resources
.FirstSnsSubscriptionFirst.Type
).to.equal('AWS::SNS::Subscription');
expect(
awsCompileSNSEvents.serverless.service.provider.compiledCloudFormationTemplate.Resources
.FirstSnsSubscriptionSecond.Type
).to.equal('AWS::SNS::Subscription');
});
it('should override SNS topic subsription CF resource name when arn and topicName are given as object properties', () => {
awsCompileSNSEvents.serverless.service.functions = {
first: {
events: [
{
sns: {
topicName: 'foo',
arn: 'arn:aws:sns:region:accountid:bar',
},
},
],
},
};
awsCompileSNSEvents.compileSNSEvents();
expect(
Object.keys(
awsCompileSNSEvents.serverless.service.provider.compiledCloudFormationTemplate.Resources
)
).to.have.length(2);
expect(
awsCompileSNSEvents.serverless.service.provider.compiledCloudFormationTemplate.Resources
.FirstSnsSubscriptionFoo.Type
).to.equal('AWS::SNS::Subscription');
expect(
awsCompileSNSEvents.serverless.service.provider.compiledCloudFormationTemplate.Resources
.FirstLambdaPermissionFooSNS.Type
).to.equal('AWS::Lambda::Permission');
});
// eslint-disable-next-line max-len
it('should create SNS topic when arn object and topicName are given as object properties', () => {
awsCompileSNSEvents.serverless.service.functions = {