Repository: serverless/serverless (JavaScript)
Date: 2017-09-21 05:25:46+00:00
Task type: Feature

Issue:
Add Amazon S3 Transfer Acceleration support
# This is a Feature Proposal

## Description

The framework could optionally enable S3 Transfer Acceleration and use the s3-accelerate endpoint to upload heavy deployment packages.

* **Use case**: heavy deployment packages or "remote" regions

## Additional Data

Feature announcement/description [here](https://aws.amazon.com/blogs/aws/aws-storage-update-amazon-s3-transfer-acceleration-larger-snowballs-in-more-regions/).

I have tested the transfer speed with the AWS CLI, uploading a 43MB file to us-west-2 from western Europe.

### Without transfer acceleration
```bash
$time aws s3 cp ./my-big-file.zip s3://my-bucket/my-big-file.zip
real	0m33.990s
user	0m2.044s
sys	0m0.608s
(peak: 1.7 MiB/s)
```

### With transfer acceleration
```bash
$time aws s3 cp ./my-big-file.zip s3://my-bucket/my-big-file.zip --endpoint-url http://s3-accelerate.amazonaws.com
real	0m6.867s
user	0m1.303s
sys	0m0.346s
(peak: 10.5 MiB/s)
```

## What's needed?

We'd need to enable transfer acceleration (no CloudFormation support yet).
This is how you do it with the CLI:

```bash
aws s3api put-bucket-accelerate-configuration --bucket bucketname --accelerate-configuration Status=Enabled
```

And then simply append the `--endpoint` option when uploading.

Eventually, it could be a simple plugin, but it sounds simple and useful enough to be an option in the core.


Issue discussion:
P.s. You can also run a multi-region test, wherever you are in the world :)

http://s3-accelerate-speedtest.s3-accelerate.amazonaws.com/en/accelerate-speed-comparsion.html

(I got a +9000% improvement for the Sydney region!)
Great proposal! I agree.
If it is possible, it would be better to use a deploymentbucket with Transfer Acceleration mode by default.
@horike37 not sure if by default is the best for everybody because of additional data transfer costs (around $0.04/GB), but I would personally agree :)

This is also interesting (taken from the [pricing page](https://aws.amazon.com/s3/pricing/)):

> Each time you use Transfer Acceleration to upload an object, we will check whether Transfer Acceleration is likely to be faster than a regular Amazon S3 transfer. If we determine that Transfer Acceleration is not likely to be faster than a regular Amazon S3 transfer of the same object to the same destination AWS region, we will not charge for that use of Transfer Acceleration for that transfer, and may bypass the Transfer Acceleration system for that upload.
@alexcasalboni @horike37 If we'd enable the setting by default, there should be a config option (globally?) to turn it of for a whole system.

Example: We build and deploy our projects with CI/CD and it does not really matter if the deployment takes 5 seconds or 30 seconds, but what does matter is, if we generate costs for an "improvement" that we do not need. The size of all project deployments resulting from the CI/CD approach, is quite big, so there will be noticable costs (I'm ignoring the statement of AWS quoted below, because that's not reliable and who knows if it is disabled or not).

So there should be a way to disable the behavior on the server (maybe through an environment variable). Having a switch in the project config is for such a behavior imo not the right place.
I agree with that proposal once we're fighting a bit with large packages in our project.

@HyperBrain What about It be disable by default and provide an inline option to use.
@wenderjean A command line option instead of an environment variable would also be ok, as it can be even set for specific builds. But how would it be named best? `--use-s3-accel` or `--use-fast-s3`? I have no idea of something well-sounding 😄 .
What about `--use-s3-acceleration`? it would be a too long word a little bit, but we have the CLI Autocomplete functionality.
I feel this is understandable and well-sounding 😄
```bash
--s3-accel
--s3-accelerate
```
I think the first one (yours) is a good choice.
Nice discussion 👍

Given the fact that this may increase costs I'd propose to make this opt-in. I'd vote for `--aws-s3-accel` or `--aws-s3-accelerate`.

**Aside:** We just need to prefix this with AWS since this is a provider-dependent CLI option.
+1 for making it opt-in

It's a great feature if your deployment packages are above 10MB or 20MB, or if you really must use remote regions (which you can often workaround during prototyping), or for live demos with terrible WiFi (true story!).

I might have time to work on a PR sometime around late next week, if nobody else wants to jump in earlier :)

Solution patch:
diff --git a/docs/providers/aws/cli-reference/deploy.md b/docs/providers/aws/cli-reference/deploy.md
index a7ad350e0f9..66204c690a9 100644
--- a/docs/providers/aws/cli-reference/deploy.md
+++ b/docs/providers/aws/cli-reference/deploy.md
@@ -25,6 +25,7 @@ serverless deploy
 - `--verbose` or `-v` Shows all stack events during deployment, and display any Stack Output.
 - `--function` or `-f` Invoke `deploy function` (see above). Convenience shortcut - cannot be used with `--package`.
 - `--conceal` Hides secrets from the output (e.g. API Gateway key values).
+- `--aws-s3-accelerate` Enables S3 Transfer Acceleration making uploading artifacts much faster. You can read more about it [here](http://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html). **Note: When using Transfer Acceleration, additional data transfer charges may apply**
 
 ## Artifacts
 
diff --git a/docs/providers/aws/guide/deploying.md b/docs/providers/aws/guide/deploying.md
index c40022fd569..fa05211eb00 100644
--- a/docs/providers/aws/guide/deploying.md
+++ b/docs/providers/aws/guide/deploying.md
@@ -68,6 +68,8 @@ The Serverless Framework translates all syntax in `serverless.yml` to a single A
 * You can specify your own S3 bucket which should be used to store all the deployment artifacts.
   The `deploymentBucket` config which is nested under `provider` lets you e.g. set the `name` or the `serverSideEncryption` method for this bucket
 
+* You can make uploading to S3 faster by adding `--aws-s3-accelerate`
+
 Check out the [deploy command docs](../cli-reference/deploy.md) for all details and options.
 
 ## Deploy Function
diff --git a/lib/plugins/aws/deploy/lib/createStack.js b/lib/plugins/aws/deploy/lib/createStack.js
index fc3bcf4c285..61f44e00bcb 100644
--- a/lib/plugins/aws/deploy/lib/createStack.js
+++ b/lib/plugins/aws/deploy/lib/createStack.js
@@ -56,11 +56,21 @@ module.exports = {
 
     return BbPromise.bind(this)
       .then(() => this.provider.request('CloudFormation',
-          'describeStackResources',
+          'describeStacks',
           { StackName: stackName },
           this.options.stage,
           this.options.region)
-          .then(() => BbPromise.resolve('alreadyCreated')))
+          .then((data) => {
+            if (this.provider.isS3TransferAccelerationEnabled()) {
+              const isAlreadyAccelerated = !!_.find(data.Stacks[0].Outputs,
+                { OutputKey: 'ServerlessDeploymentBucketAccelerated' });
+              if (!isAlreadyAccelerated) {
+                this.serverless.cli.log('Not using S3 Transfer Acceleration (1st deploy)');
+                this.provider.disableTransferAccelerationForCurrentDeploy();
+              }
+            }
+            BbPromise.resolve('alreadyCreated');
+          }))
       .catch((e) => {
         if (e.message.indexOf('does not exist') > -1) {
           if (this.serverless.service.provider.deploymentBucket) {
diff --git a/lib/plugins/aws/package/lib/generateCoreTemplate.js b/lib/plugins/aws/package/lib/generateCoreTemplate.js
index ef15492bef8..648edd97de4 100644
--- a/lib/plugins/aws/package/lib/generateCoreTemplate.js
+++ b/lib/plugins/aws/package/lib/generateCoreTemplate.js
@@ -24,6 +24,7 @@ module.exports = {
     );
 
     const bucketName = this.serverless.service.provider.deploymentBucket;
+    const isS3TransferAccelerationEnabled = this.provider.isS3TransferAccelerationEnabled();
 
     if (bucketName) {
       return BbPromise.bind(this)
@@ -50,6 +51,11 @@ module.exports = {
               'Deployment bucket is not in the same region as the lambda function'
             );
           }
+          if (isS3TransferAccelerationEnabled) {
+            const warningMessage =
+              'Warning: S3 Transfer Acceleration will not be enabled on deploymentBucket.';
+            this.serverless.cli.log(warningMessage);
+          }
           this.bucketName = bucketName;
           this.serverless.service.package.deploymentBucket = bucketName;
           this.serverless.service.provider.compiledCloudFormationTemplate
@@ -64,6 +70,19 @@ module.exports = {
       return BbPromise.resolve();
     }
 
+    this.serverless.service.provider.compiledCloudFormationTemplate
+      .Resources.ServerlessDeploymentBucket.Properties = {
+        AccelerateConfiguration: {
+          AccelerationStatus:
+            isS3TransferAccelerationEnabled ? 'Enabled' : 'Suspended',
+        },
+      };
+
+    if (isS3TransferAccelerationEnabled) {
+      this.serverless.service.provider.compiledCloudFormationTemplate
+      .Outputs.ServerlessDeploymentBucketAccelerated = { Value: true };
+    }
+
     const coreTemplateFileName = this.provider.naming.getCoreTemplateFileName();
 
     const coreTemplateFilePath = path.join(this.serverless.config.servicePath,
diff --git a/lib/plugins/aws/provider/awsProvider.js b/lib/plugins/aws/provider/awsProvider.js
index a9958f2bdbf..0d4fd604abf 100644
--- a/lib/plugins/aws/provider/awsProvider.js
+++ b/lib/plugins/aws/provider/awsProvider.js
@@ -164,6 +164,11 @@ class AwsProvider {
       return doCall();
     });
 
+    // Support S3 Transfer Acceleration
+    if (this.canUseS3TransferAcceleration(service, method)) {
+      this.enableS3TransferAcceleration(credentials);
+    }
+
     return persistentRequest(() => {
       const awsService = new that.sdk[service](credentials);
       const req = awsService[method](params);
@@ -226,6 +231,28 @@ class AwsProvider {
     return result;
   }
 
+  canUseS3TransferAcceleration(service, method) {
+    // TODO enable more S3 APIs?
+    return service === 'S3'
+        && ['upload', 'putObject'].indexOf(method) !== -1
+        && this.isS3TransferAccelerationEnabled();
+  }
+
+  isS3TransferAccelerationEnabled() {
+    return !!this.options['aws-s3-accelerate'];
+  }
+
+  disableTransferAccelerationForCurrentDeploy() {
+    delete this.options['aws-s3-accelerate'];
+  }
+
+  enableS3TransferAcceleration(credentials) {
+    this.serverless.cli.log('Using S3 Transfer Acceleration Endpoint...');
+    credentials.useAccelerateEndpoint = true;  // eslint-disable-line no-param-reassign
+    credentials.signatureVersion = 'v2';  // eslint-disable-line no-param-reassign
+    // see https://github.com/aws/aws-sdk-js/issues/281
+  }
+
   getRegion() {
     const defaultRegion = 'us-east-1';
 
diff --git a/lib/plugins/deploy/deploy.js b/lib/plugins/deploy/deploy.js
index 7be8078edf9..9191d742096 100644
--- a/lib/plugins/deploy/deploy.js
+++ b/lib/plugins/deploy/deploy.js
@@ -54,6 +54,9 @@ class Deploy {
             usage: 'Function name. Deploys a single function (see \'deploy function\')',
             shortcut: 'f',
           },
+          'aws-s3-accelerate': {
+            usage: 'Enables S3 Transfer Acceleration making uploading artifacts much faster.',
+          },
         },
         commands: {
           function: {


Test patch:
diff --git a/lib/plugins/aws/deploy/lib/createStack.test.js b/lib/plugins/aws/deploy/lib/createStack.test.js
index 235726b5ea4..a75e8e8f6e2 100644
--- a/lib/plugins/aws/deploy/lib/createStack.test.js
+++ b/lib/plugins/aws/deploy/lib/createStack.test.js
@@ -28,7 +28,7 @@ describe('createStack', () => {
   beforeEach(() => {
     sandbox = sinon.sandbox.create();
     const serverless = new Serverless();
-    serverless.setProvider('aws', new AwsProvider(serverless));
+    serverless.setProvider('aws', new AwsProvider(serverless, {}));
     serverless.utils.writeFileSync(serverlessYmlPath, serverlessYml);
     serverless.config.servicePath = tmpDirPath;
     const options = {
@@ -128,5 +128,26 @@ describe('createStack', () => {
         expect(createStub.calledOnce).to.be.equal(true);
       });
     });
+
+    it('should disable S3 Transfer Acceleration if missing Output', () => {
+      const disableTransferAccelerationStub = sandbox
+        .stub(awsDeploy.provider,
+          'disableTransferAccelerationForCurrentDeploy').resolves();
+
+      const describeStacksOutput = {
+        Stacks: [
+          {
+            Outputs: [],
+          },
+        ],
+      };
+      sandbox.stub(awsDeploy.provider, 'request').resolves(describeStacksOutput);
+
+      awsDeploy.provider.options['aws-s3-accelerate'] = true;
+
+      return awsDeploy.createStack().then(() => {
+        expect(disableTransferAccelerationStub.called).to.be.equal(true);
+      });
+    });
   });
 });
diff --git a/lib/plugins/aws/deploy/lib/uploadArtifacts.test.js b/lib/plugins/aws/deploy/lib/uploadArtifacts.test.js
index 7af45d186ae..8bd9fefe3b2 100644
--- a/lib/plugins/aws/deploy/lib/uploadArtifacts.test.js
+++ b/lib/plugins/aws/deploy/lib/uploadArtifacts.test.js
@@ -19,7 +19,7 @@ describe('uploadArtifacts', () => {
   beforeEach(() => {
     serverless = new Serverless();
     serverless.config.servicePath = 'foo';
-    serverless.setProvider('aws', new AwsProvider(serverless));
+    serverless.setProvider('aws', new AwsProvider(serverless, {}));
     const options = {
       stage: 'dev',
       region: 'us-east-1',
@@ -60,6 +60,7 @@ describe('uploadArtifacts', () => {
       return awsDeploy.uploadArtifacts().then(() => {
         expect(uploadCloudFormationFileStub.calledOnce)
           .to.be.equal(true);
+
         expect(uploadFunctionsStub.calledAfter(uploadCloudFormationFileStub)).to.be.equal(true);
 
         awsDeploy.uploadCloudFormationFile.restore();
diff --git a/lib/plugins/aws/package/lib/generateCoreTemplate.test.js b/lib/plugins/aws/package/lib/generateCoreTemplate.test.js
index b8a0e4264c8..f028c6a5484 100644
--- a/lib/plugins/aws/package/lib/generateCoreTemplate.test.js
+++ b/lib/plugins/aws/package/lib/generateCoreTemplate.test.js
@@ -16,7 +16,7 @@ describe('#generateCoreTemplate()', () => {
   beforeEach(() => {
     serverless = new Serverless();
     awsPlugin.serverless = serverless;
-    awsPlugin.provider = new AwsProvider(serverless);
+    awsPlugin.provider = new AwsProvider(serverless, {});
     awsPlugin.options = {
       stage: 'dev',
       region: 'us-east-1',
@@ -152,4 +152,30 @@ describe('#generateCoreTemplate()', () => {
         });
     });
   });
+
+  it('should add a deployment bucket to the CF template, if not provided', () => {
+    sinon.stub(awsPlugin.provider, 'request').resolves();
+    sinon.stub(serverless.utils, 'writeFileSync').resolves();
+    serverless.config.servicePath = './';
+
+    return awsPlugin.generateCoreTemplate()
+      .then(() => {
+        const template = serverless.service.provider.coreCloudFormationTemplate;
+        expect(template).to.not.equal(null);
+      });
+  });
+
+  it('should add a custom output if S3 Transfer Acceleration is enabled', () => {
+    sinon.stub(awsPlugin.provider, 'request').resolves();
+    sinon.stub(serverless.utils, 'writeFileSync').resolves();
+    serverless.config.servicePath = './';
+    awsPlugin.provider.options['aws-s3-accelerate'] = true;
+
+    return awsPlugin.generateCoreTemplate()
+      .then(() => {
+        const template = serverless.service.provider.coreCloudFormationTemplate;
+        expect(template.Outputs.ServerlessDeploymentBucketAccelerated).to.not.equal(null);
+        expect(template.Outputs.ServerlessDeploymentBucketAccelerated.Value).to.equal(true);
+      });
+  });
 });
diff --git a/lib/plugins/aws/provider/awsProvider.test.js b/lib/plugins/aws/provider/awsProvider.test.js
index 8e8389f5a17..8ee355259b9 100644
--- a/lib/plugins/aws/provider/awsProvider.test.js
+++ b/lib/plugins/aws/provider/awsProvider.test.js
@@ -243,6 +243,43 @@ describe('AwsProvider', () => {
         })
         .catch(done);
     });
+
+    it('should enable S3 acceleration if CLI option is provided', () => {
+      // mocking S3 for testing
+      class FakeS3 {
+        constructor(credentials) {
+          this.credentials = credentials;
+        }
+
+        putObject() {
+          return {
+            send: (cb) => cb(null, { called: true }),
+          };
+        }
+      }
+      awsProvider.sdk = {
+        S3: FakeS3,
+      };
+      awsProvider.serverless.service.environment = {
+        vars: {},
+        stages: {
+          dev: {
+            vars: {
+              profile: 'default',
+            },
+            regions: {},
+          },
+        },
+      };
+
+      const enableS3TransferAccelerationStub = sinon
+        .stub(awsProvider, 'enableS3TransferAcceleration').resolves();
+
+      awsProvider.options['aws-s3-accelerate'] = true;
+      return awsProvider.request('S3', 'putObject', {}).then(() => {
+        expect(enableS3TransferAccelerationStub.calledOnce).to.equal(true);
+      });
+    });
   });
 
   describe('#getCredentials()', () => {
@@ -572,74 +609,136 @@ describe('AwsProvider', () => {
           awsProvider.request.restore();
         });
     });
+  });
 
-    describe('#getStage()', () => {
-      it('should prefer options over config or provider', () => {
-        const newOptions = {
-          stage: 'optionsStage',
-        };
-        const config = {
-          stage: 'configStage',
-        };
-        serverless = new Serverless(config);
-        serverless.service.provider.stage = 'providerStage';
-        awsProvider = new AwsProvider(serverless, newOptions);
+  describe('#getStage()', () => {
+    it('should prefer options over config or provider', () => {
+      const newOptions = {
+        stage: 'optionsStage',
+      };
+      const config = {
+        stage: 'configStage',
+      };
+      serverless = new Serverless(config);
+      serverless.service.provider.stage = 'providerStage';
+      awsProvider = new AwsProvider(serverless, newOptions);
 
-        expect(awsProvider.getStage()).to.equal(newOptions.stage);
-      });
+      expect(awsProvider.getStage()).to.equal(newOptions.stage);
+    });
 
-      it('should prefer config over provider in lieu of options', () => {
-        const newOptions = {};
-        const config = {
-          stage: 'configStage',
-        };
-        serverless = new Serverless(config);
-        serverless.service.provider.stage = 'providerStage';
-        awsProvider = new AwsProvider(serverless, newOptions);
+    it('should prefer config over provider in lieu of options', () => {
+      const newOptions = {};
+      const config = {
+        stage: 'configStage',
+      };
+      serverless = new Serverless(config);
+      serverless.service.provider.stage = 'providerStage';
+      awsProvider = new AwsProvider(serverless, newOptions);
 
-        expect(awsProvider.getStage()).to.equal(config.stage);
-      });
+      expect(awsProvider.getStage()).to.equal(config.stage);
+    });
 
-      it('should use provider in lieu of options and config', () => {
-        const newOptions = {};
-        const config = {};
-        serverless = new Serverless(config);
-        serverless.service.provider.stage = 'providerStage';
-        awsProvider = new AwsProvider(serverless, newOptions);
+    it('should use provider in lieu of options and config', () => {
+      const newOptions = {};
+      const config = {};
+      serverless = new Serverless(config);
+      serverless.service.provider.stage = 'providerStage';
+      awsProvider = new AwsProvider(serverless, newOptions);
 
-        expect(awsProvider.getStage()).to.equal(serverless.service.provider.stage);
-      });
+      expect(awsProvider.getStage()).to.equal(serverless.service.provider.stage);
+    });
 
-      it('should use the default dev in lieu of options, config, and provider', () => {
-        const newOptions = {};
-        const config = {};
-        serverless = new Serverless(config);
-        awsProvider = new AwsProvider(serverless, newOptions);
+    it('should use the default dev in lieu of options, config, and provider', () => {
+      const newOptions = {};
+      const config = {};
+      serverless = new Serverless(config);
+      awsProvider = new AwsProvider(serverless, newOptions);
 
-        expect(awsProvider.getStage()).to.equal('dev');
-      });
+      expect(awsProvider.getStage()).to.equal('dev');
     });
+  });
 
-    describe('#getAccountId()', () => {
-      it('should return the AWS account id', () => {
-        const accountId = '12345678';
-
-        const stsGetCallerIdentityStub = sinon
-          .stub(awsProvider, 'request')
-          .resolves({
-            ResponseMetadata: { RequestId: '12345678-1234-1234-1234-123456789012' },
-            UserId: 'ABCDEFGHIJKLMNOPQRSTU:VWXYZ',
-            Account: accountId,
-            Arn: 'arn:aws:sts::123456789012:assumed-role/ROLE-NAME/VWXYZ',
-          });
-
-        return awsProvider.getAccountId()
-          .then((result) => {
-            expect(stsGetCallerIdentityStub.calledOnce).to.equal(true);
-            expect(result).to.equal(accountId);
-            awsProvider.request.restore();
-          });
-      });
+  describe('#getAccountId()', () => {
+    it('should return the AWS account id', () => {
+      const accountId = '12345678';
+
+      const stsGetCallerIdentityStub = sinon
+        .stub(awsProvider, 'request')
+        .resolves({
+          ResponseMetadata: { RequestId: '12345678-1234-1234-1234-123456789012' },
+          UserId: 'ABCDEFGHIJKLMNOPQRSTU:VWXYZ',
+          Account: accountId,
+          Arn: 'arn:aws:sts::123456789012:assumed-role/ROLE-NAME/VWXYZ',
+        });
+
+      return awsProvider.getAccountId()
+        .then((result) => {
+          expect(stsGetCallerIdentityStub.calledOnce).to.equal(true);
+          expect(result).to.equal(accountId);
+          awsProvider.request.restore();
+        });
+    });
+  });
+
+  describe('#isS3TransferAccelerationEnabled()', () => {
+    it('should return false by default', () => {
+      awsProvider.options['aws-s3-accelerate'] = undefined;
+      return expect(awsProvider.isS3TransferAccelerationEnabled())
+        .to.equal(false);
+    });
+    it('should return true when CLI option is provided', () => {
+      awsProvider.options['aws-s3-accelerate'] = true;
+      return expect(awsProvider.isS3TransferAccelerationEnabled())
+        .to.equal(true);
+    });
+  });
+
+  describe('#canUseS3TransferAcceleration()', () => {
+    it('should return false by default with any input', () => {
+      awsProvider.options['aws-s3-accelerate'] = undefined;
+      return expect(awsProvider.canUseS3TransferAcceleration('lambda', 'updateFunctionCode'))
+        .to.equal(false);
+    });
+    it('should return false by default with S3.upload too', () => {
+      awsProvider.options['aws-s3-accelerate'] = undefined;
+      return expect(awsProvider.canUseS3TransferAcceleration('S3', 'upload'))
+        .to.equal(false);
+    });
+    it('should return false by default with S3.putObject too', () => {
+      awsProvider.options['aws-s3-accelerate'] = undefined;
+      return expect(awsProvider.canUseS3TransferAcceleration('S3', 'putObject'))
+        .to.equal(false);
+    });
+    it('should return false when CLI option is provided but not an S3 upload', () => {
+      awsProvider.options['aws-s3-accelerate'] = true;
+      return expect(awsProvider.canUseS3TransferAcceleration('lambda', 'updateFunctionCode'))
+        .to.equal(false);
+    });
+    it('should return true when CLI option is provided for S3.upload', () => {
+      awsProvider.options['aws-s3-accelerate'] = true;
+      return expect(awsProvider.canUseS3TransferAcceleration('S3', 'upload'))
+        .to.equal(true);
+    });
+    it('should return true when CLI option is provided for S3.putObject', () => {
+      awsProvider.options['aws-s3-accelerate'] = true;
+      return expect(awsProvider.canUseS3TransferAcceleration('S3', 'putObject'))
+        .to.equal(true);
+    });
+  });
+
+  describe('#enableS3TransferAcceleration()', () => {
+    it('should update the given credentials object to enable S3 acceleration', () => {
+      const credentials = {};
+      awsProvider.enableS3TransferAcceleration(credentials);
+      return expect(credentials.useAccelerateEndpoint).to.equal(true);
+    });
+  });
+
+  describe('#disableTransferAccelerationForCurrentDeploy()', () => {
+    it('should remove the corresponding option for the current deploy', () => {
+      awsProvider.options['aws-s3-accelerate'] = true;
+      awsProvider.disableTransferAccelerationForCurrentDeploy();
+      return expect(awsProvider.options['aws-s3-accelerate']).to.be.undefined;
     });
   });
 });