Repository: serverless/serverless (JavaScript)
Date: 2018-04-20 11:16:58+00:00
Task type: Bug Fix

Issue:
Shared API functionality has been broken on top of master
<!--
1. If you have a question and not a bug/feature request please ask it at http://forum.serverless.com
2. Please check if an issue already exists so there are no duplicates
3. Check out and follow our Guidelines: https://github.com/serverless/serverless/blob/master/CONTRIBUTING.md
4. Fill out the whole template so we have a good overview on the issue
5. Do not remove any section of the template. If something is not applicable leave it empty but leave it in the Issue
6. Please follow the template, otherwise we'll have to ask you to update it
-->

# This is a (Bug Report)

## Description
It seems that Shared API functionality has been broken on top of master with following error when sls deploy. maybe any one of PRs have introduced this after releasing v1.26.1

```
$sls deploy
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip file to S3 (409 B)...
Serverless: Validating template...
 
  Error --------------------------------------------------
 
  The CloudFormation template is invalid: Template error: every Fn::Join object requires two parameters, (1) a string delimiter and (2) a list of strings to be joined or a function that returns a list of strings (such as Fn::GetAZs) to be joined.
 
     For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.
 
  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
     Issues:        forum.serverless.com
 
  Your Environment Information -----------------------------
     OS:                     darwin
     Node Version:           8.8.1
     Serverless Version:     1.26.0
```
Here is serverless.yml
```yml
service: shared-service

provider:
  name: aws
  runtime: nodejs6.10
  apiGateway:
    restApiId: [ID]
    restApiRootResourceId: [ID2]

functions:
  hello:
    handler: handler.hello
    events:
      - http:
          path: /hello
          method: get
```


## Additional Data

* ***Serverless Framework Version you're using***: top of master
* ***Operating System***: darwin
* ***Stack Trace***: above
* ***Provider Error messages***: above



Issue discussion:

Solution patch:
diff --git a/lib/plugins/aws/package/compile/events/apiGateway/lib/permissions.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/permissions.js
index cbb137d1ff7..61641b53505 100644
--- a/lib/plugins/aws/package/compile/events/apiGateway/lib/permissions.js
+++ b/lib/plugins/aws/package/compile/events/apiGateway/lib/permissions.js
@@ -30,7 +30,7 @@ module.exports = {
                   ':',
                   { Ref: 'AWS::AccountId' },
                   ':',
-                  { Ref: this.provider.naming.getRestApiLogicalId() },
+                  this.provider.getApiGatewayRestApiId(),
                   '/*/*',
                 ],
               ],
diff --git a/lib/plugins/aws/package/compile/events/apiGateway/lib/usagePlan.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/usagePlan.js
index e5cfe02cdf2..4206370ddcf 100644
--- a/lib/plugins/aws/package/compile/events/apiGateway/lib/usagePlan.js
+++ b/lib/plugins/aws/package/compile/events/apiGateway/lib/usagePlan.js
@@ -14,9 +14,7 @@ module.exports = {
           Properties: {
             ApiStages: [
               {
-                ApiId: {
-                  Ref: this.provider.naming.getRestApiLogicalId(),
-                },
+                ApiId: this.provider.getApiGatewayRestApiId(),
                 Stage: this.provider.getStage(),
               },
             ],


Test patch:
diff --git a/lib/plugins/aws/package/compile/events/apiGateway/lib/permissions.test.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/permissions.test.js
index cc89148cf2a..a0ff32a6749 100644
--- a/lib/plugins/aws/package/compile/events/apiGateway/lib/permissions.test.js
+++ b/lib/plugins/aws/package/compile/events/apiGateway/lib/permissions.test.js
@@ -70,6 +70,61 @@ describe('#awsCompilePermissions()', () => {
     });
   });
 
+  it('should create limited permission resource scope to REST API with restApiId provided', () => {
+    awsCompileApigEvents.serverless.service.provider.apiGateway = {
+      restApiId: 'xxxxx',
+    };
+    awsCompileApigEvents.validated.events = [
+      {
+        functionName: 'First',
+        http: {
+          path: 'foo/bar',
+          method: 'post',
+        },
+      },
+    ];
+    awsCompileApigEvents.apiGatewayRestApiLogicalId = 'ApiGatewayRestApi';
+    awsCompileApigEvents.permissionMapping = [
+      {
+        lambdaLogicalId: 'FirstLambdaFunction',
+        resourceName: 'FooBar',
+        event: {
+          http: {
+            path: 'foo/bar',
+            method: 'post',
+          },
+          functionName: 'First',
+        },
+      },
+    ];
+
+    return awsCompileApigEvents.compilePermissions().then(() => {
+      expect(awsCompileApigEvents.serverless.service.provider.compiledCloudFormationTemplate
+        .Resources.FirstLambdaPermissionApiGateway
+        .Properties.FunctionName['Fn::GetAtt'][0]).to.equal('FirstLambdaFunction');
+
+      const deepObj = {
+        'Fn::Join': ['',
+          [
+            'arn:',
+            { Ref: 'AWS::Partition' },
+            ':execute-api:',
+            { Ref: 'AWS::Region' },
+            ':',
+            { Ref: 'AWS::AccountId' },
+            ':',
+            'xxxxx',
+            '/*/*',
+          ],
+        ],
+      };
+
+      expect(awsCompileApigEvents.serverless.service.provider.compiledCloudFormationTemplate
+        .Resources.FirstLambdaPermissionApiGateway
+        .Properties.SourceArn).to.deep.equal(deepObj);
+    });
+  });
+
   it('should create permission resources for authorizers', () => {
     awsCompileApigEvents.validated.events = [
       {
diff --git a/lib/plugins/aws/package/compile/events/apiGateway/lib/usagePlan.test.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/usagePlan.test.js
index d43e8fe4746..168d83f5424 100644
--- a/lib/plugins/aws/package/compile/events/apiGateway/lib/usagePlan.test.js
+++ b/lib/plugins/aws/package/compile/events/apiGateway/lib/usagePlan.test.js
@@ -151,4 +151,20 @@ describe('#compileUsagePlan()', () => {
       ).to.equal('first-service-dev');
     });
   });
+
+  it('should compile custom usage plan resource with restApiId provided', () => {
+    serverless.service.provider.apiKeys = ['1234567890'];
+    awsCompileApigEvents.serverless.service.provider.apiGateway = {
+      restApiId: 'xxxxx',
+    };
+
+    return awsCompileApigEvents.compileUsagePlan().then(() => {
+      expect(
+        awsCompileApigEvents.serverless.service.provider.compiledCloudFormationTemplate
+          .Resources[
+          awsCompileApigEvents.provider.naming.getUsagePlanLogicalId()
+          ].Properties.ApiStages[0].ApiId
+      ).to.equal('xxxxx');
+    });
+  });
 });