Repository: serverless/serverless (JavaScript)
Date: 2017-04-23 14:03:08+00:00
Task type: Feature

Issue:
Update SNS event to support arn config parameter
# This is a Feature Proposal

## Description

#3443 recently added the functionality to use intrinsic functions for `arn` definitions. The `sns` event also supports the usage of `arn` like this:

```yml
functions:
  hello:
    handler: handler.hello
    events:
      - sns: arn:aws:sns:us-east-1:XXXX:some-topic
```

However it should also be possible to specify the `arn` like this:

```yml
functions:
  hello:
    handler: handler.hello
    events:
      - sns:
          arn: arn:aws:sns:us-east-1:XXXX:some-topic
```


Issue discussion:
I have been working on this.
Awesome! Thanks @horike37 🥇 

Excited about the PR! 💯 Let us know if you need any help here.

Solution patch:
diff --git a/docs/providers/aws/events/sns.md b/docs/providers/aws/events/sns.md
index 3481150fa95..2dd1b2d091c 100644
--- a/docs/providers/aws/events/sns.md
+++ b/docs/providers/aws/events/sns.md
@@ -50,6 +50,15 @@ functions:
       - sns: arn:xxx
 ```
 
+```yml
+functions:
+  dispatcher:
+    handler: dispatcher.dispatch
+    events:
+      - sns:
+          arn: arn:xxx
+```
+
 Or with intrinsic CloudFormation function like `Fn::Join` or `Fn::GetAtt`.
 
 ```yml
diff --git a/lib/plugins/aws/package/compile/events/sns/index.js b/lib/plugins/aws/package/compile/events/sns/index.js
index 1fcba97d217..69325ec4064 100644
--- a/lib/plugins/aws/package/compile/events/sns/index.js
+++ b/lib/plugins/aws/package/compile/events/sns/index.js
@@ -32,6 +32,10 @@ class AwsCompileSNSEvents {
                   if (event.sns.topicName && typeof event.sns.topicName === 'string') {
                     topicArn = event.sns.arn;
                     topicName = event.sns.topicName;
+                  } else if (event.sns.arn.indexOf('arn:') === 0) {
+                    topicArn = event.sns.arn;
+                    const splitArn = topicArn.split(':');
+                    topicName = splitArn[splitArn.length - 1];
                   } else {
                     const errorMessage = [
                       'Missing or invalid topicName property for sns event',


Test patch:
diff --git a/lib/plugins/aws/package/compile/events/sns/index.test.js b/lib/plugins/aws/package/compile/events/sns/index.test.js
index d59af889eef..edcbe67d0a8 100644
--- a/lib/plugins/aws/package/compile/events/sns/index.test.js
+++ b/lib/plugins/aws/package/compile/events/sns/index.test.js
@@ -134,7 +134,7 @@ describe('AwsCompileSNSEvents', () => {
       ).to.deep.equal({});
     });
 
-    it('should not create SNS topic when arn is given', () => {
+    it('should create SNS topic when arn is given as a string', () => {
       awsCompileSNSEvents.serverless.service.functions = {
         first: {
           events: [
@@ -158,23 +158,33 @@ describe('AwsCompileSNSEvents', () => {
       ).to.equal('AWS::Lambda::Permission');
     });
 
-    it('should raise an error when only arn is present', () => {
+    it('should create SNS topic when only arn is given as an object property', () => {
       awsCompileSNSEvents.serverless.service.functions = {
         first: {
           events: [
             {
               sns: {
-                arn: 'arn:aws:sns:region:accountid:bar',
+                arn: 'arn:aws:sns:region:accountid:foo',
               },
             },
           ],
         },
       };
 
-      expect(() => { awsCompileSNSEvents.compileSNSEvents(); }).to.throw(Error);
+      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');
     });
 
-    it('should not create SNS topic when arn is provided', () => {
+    it('should create SNS topic when arn and topicName are given as object properties', () => {
       awsCompileSNSEvents.serverless.service.functions = {
         first: {
           events: [