Repository: serverless/serverless (JavaScript)
Date: 2019-07-25 11:15:17+00:00
Task type: Bug Fix

Issue:
Cloudwatch log group subscriptions are removed on subsequent deploys in gov-cloud
<!--
1. If you have a question and not a bug report please ask first at http://forum.serverless.com
2. Please check if an issue already exists. This bug may have already been documented
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

- What went wrong?
  - Log group subscription event is deleted on subsequent deploys in gov-cloud
- What did you expect should have happened?
  - That the lambda event source remains
- What was the config you used?
```
service: my-service

provider:
  name: aws
  runtime: python3.6
  region: us-gov-west-1

functions:
  hello:
    handler: handler.hello
    events:
      - cloudwatchLog:
          logGroup: '/var/log/cloud-init-output.log'
          filter: 'some filter'
```
- What stacktrace or error message from your provider did you see?
None

The issue can be found in this line [here](https://github.com/serverless/serverless/blob/master/lib/plugins/aws/deploy/lib/checkForChanges.js#L220) where the partition is hard coded to `aws`.

Gov-cloud uses the [partition](https://docs.aws.amazon.com/govcloud-us/latest/UserGuide/using-govcloud-arns.html) `aws-us-gov`, so in this situation `oldDestinationArn` will _never_ equal `newDestinationArn `, therefore deleting the subscription filter.

This doesn't happen on an initial deploy, but only subsequent deploys in [`checkForChanges`](https://github.com/serverless/serverless/blob/master/lib/plugins/aws/deploy/lib/checkForChanges.js)

**I have a PR ready** for this (tested and working), so happy to send.

Similar or dependent issues:

- #5700

## Additional Data

- **_Serverless Framework Version you're using_**: 1.48.3
- **_Operating System_**: MacOs 10.14.5
- **_Stack Trace_**: None
- **_Provider Error messages_**: None



Issue discussion:
Looks like this would also apply to [China](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#genref-arns) regions

Solution patch:
diff --git a/lib/plugins/aws/deploy/lib/checkForChanges.js b/lib/plugins/aws/deploy/lib/checkForChanges.js
index 1ef50534453..570503e381b 100644
--- a/lib/plugins/aws/deploy/lib/checkForChanges.js
+++ b/lib/plugins/aws/deploy/lib/checkForChanges.js
@@ -151,7 +151,7 @@ module.exports = {
     const region = this.provider.getRegion();
     const cloudWatchLogsSdk = new this.provider.sdk.CloudWatchLogs({ region });
 
-    return this.provider.getAccountId().then(accountId =>
+    return this.provider.getAccountInfo().then(account =>
       Promise.all(
         this.serverless.service.getAllFunctions().map(functionName => {
           const functionObj = this.serverless.service.getFunction(functionName);
@@ -177,6 +177,9 @@ module.exports = {
               logGroupName = event.cloudwatchLog.replace(/\r?\n/g, '');
             }
 
+            const accountId = account.accountId;
+            const partition = account.partition;
+
             /*
               return a new promise that will check the resource limit exceeded and will fix it if
               the option is enabled
@@ -187,6 +190,7 @@ module.exports = {
               logGroupName,
               functionObj,
               region,
+              partition,
             });
           });
 
@@ -202,6 +206,7 @@ module.exports = {
     const logGroupName = params.logGroupName;
     const functionObj = params.functionObj;
     const region = params.region;
+    const partition = params.partition;
 
     return (
       cloudWatchLogsSdk
@@ -217,7 +222,7 @@ module.exports = {
 
           const oldDestinationArn = subscriptionFilter.destinationArn;
           const filterName = subscriptionFilter.filterName;
-          const newDestinationArn = `arn:aws:lambda:${region}:${accountId}:function:${functionObj.name}`;
+          const newDestinationArn = `arn:${partition}:lambda:${region}:${accountId}:function:${functionObj.name}`;
 
           // everything is fine, just return
           if (oldDestinationArn === newDestinationArn) {


Test patch:
diff --git a/lib/plugins/aws/deploy/lib/checkForChanges.test.js b/lib/plugins/aws/deploy/lib/checkForChanges.test.js
index 313c4c92479..cf4519d56b4 100644
--- a/lib/plugins/aws/deploy/lib/checkForChanges.test.js
+++ b/lib/plugins/aws/deploy/lib/checkForChanges.test.js
@@ -514,7 +514,12 @@ describe('checkForChanges', () => {
 
       provider.sdk.CloudWatchLogs = CloudWatchLogsStub;
 
-      sandbox.stub(provider, 'getAccountId').returns(BbPromise.resolve(accountId));
+      sandbox.stub(provider, 'getAccountInfo').returns(
+        BbPromise.resolve({
+          accountId,
+          partition: 'aws',
+        })
+      );
 
       sandbox.stub(awsDeploy.serverless.service, 'getServiceName').returns(serviceName);
 
@@ -658,6 +663,37 @@ describe('checkForChanges', () => {
           .then(() => expect(deleteSubscriptionFilterStub).to.not.have.been.called);
       });
 
+      it('should not call delete when ARN is the same accounting for non-standard partitions', () => {
+        provider.getAccountInfo.restore();
+        sandbox.stub(provider, 'getAccountInfo').returns(
+          BbPromise.resolve({
+            accountId,
+            partition: 'aws-us-gov',
+          })
+        );
+        awsDeploy.serverless.service.functions = {
+          first: {
+            name: 'my-test-function',
+            events: [{ cloudwatchLog: '/aws/lambda/hello1' }],
+          },
+        };
+
+        awsDeploy.serverless.service.setFunctionNames();
+
+        describeSubscriptionFiltersResponse = {
+          subscriptionFilters: [
+            {
+              destinationArn: `arn:aws-us-gov:lambda:${region}:${accountId}:function:my-test-function`,
+              filterName: 'dummy-filter',
+            },
+          ],
+        };
+
+        return awsDeploy
+          .checkForChanges()
+          .then(() => expect(deleteSubscriptionFilterStub).to.not.have.been.called);
+      });
+
       it('should call delete if there is a subFilter but the ARNs are not the same with custom function name', () => {
         awsDeploy.serverless.service.functions = {
           first: {