Repository: serverless/serverless (JavaScript) — Feature

Issue:
DX: Improve the error message when deploymentBucket returns statuscode 403
<!--
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 (Feature Proposal)

## Description
the following error message is showed when the deploymentBucket I specified in serverless.yml  returns statuscode 403(S3 api returns this).
First, when I faced this error, I thought there was the cause related to rights on my localmachine.
Therefore it took a time to resolve it.

I'd like to improve this error message like this: `Access Denied for deploymentBucket you specify in serverless.yml`

```
$sls deploy -v --profile dev
 
  Serverless Error ---------------------------------------
 
     Access Denied
 
  Stack Trace --------------------------------------------
 
ServerlessError: Access Denied
    at Response.req.send (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/lib/plugins/aws/provider/awsProvider.js:163:20)
    at Request.<anonymous> (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/node_modules/aws-sdk/lib/request.js:360:18)
    at Request.callListeners (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/node_modules/aws-sdk/lib/sequential_executor.js:105:20)
    at Request.emit (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/node_modules/aws-sdk/lib/sequential_executor.js:77:10)
    at Request.emit (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/node_modules/aws-sdk/lib/request.js:678:14)
    at Request.transition (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at /Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/node_modules/aws-sdk/lib/request.js:680:12)
    at Request.callListeners (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/node_modules/aws-sdk/lib/sequential_executor.js:115:18)
    at Request.emit (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/node_modules/aws-sdk/lib/sequential_executor.js:77:10)
    at Request.emit (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/node_modules/aws-sdk/lib/request.js:678:14)
    at Request.transition (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at /Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/node_modules/aws-sdk/lib/request.js:680:12)
    at Request.callListeners (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/node_modules/aws-sdk/lib/sequential_executor.js:115:18)
    at callNextListener (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/node_modules/aws-sdk/lib/sequential_executor.js:95:12)
    at Request.RESET_RETRY_STATE (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/node_modules/aws-sdk/lib/event_listeners.js:426:9)
    at Request.callListeners (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/node_modules/aws-sdk/lib/sequential_executor.js:101:18)
From previous event:
    at persistentRequest (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/lib/plugins/aws/provider/awsProvider.js:151:14)
    at doCall (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/lib/plugins/aws/provider/awsProvider.js:130:9)
    at BbPromise (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/lib/plugins/aws/provider/awsProvider.js:141:14)
From previous event:
    at persistentRequest (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/lib/plugins/aws/provider/awsProvider.js:128:38)
    at AwsProvider.request (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/lib/plugins/aws/provider/awsProvider.js:144:12)
    at AwsPackage.BbPromise.bind.then.then (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/lib/plugins/aws/package/lib/generateCoreTemplate.js:31:35)
From previous event:
    at AwsPackage.generateCoreTemplate (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/lib/plugins/aws/package/lib/generateCoreTemplate.js:31:10)
From previous event:
    at Object.package:initialize [as hook] (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/lib/plugins/aws/package/index.js:60:10)
    at BbPromise.reduce (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/lib/classes/PluginManager.js:234:55)
From previous event:
    at PluginManager.invoke (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/lib/classes/PluginManager.js:234:22)
    at PluginManager.spawn (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/lib/classes/PluginManager.js:246:17)
    at Deploy.BbPromise.bind.then (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/lib/plugins/deploy/deploy.js:79:48)
From previous event:
    at Object.before:deploy:deploy [as hook] (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/lib/plugins/deploy/deploy.js:77:8)
    at BbPromise.reduce (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/lib/classes/PluginManager.js:234:55)
    at runCallback (timers.js:637:20)
    at tryOnImmediate (timers.js:610:5)
    at processImmediate [as _immediateCallback] (timers.js:582:5)
From previous event:
    at PluginManager.invoke (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/lib/classes/PluginManager.js:234:22)
    at PluginManager.run (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/lib/classes/PluginManager.js:253:17)
    at variables.populateService.then (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/lib/Serverless.js:96:33)
From previous event:
    at Serverless.run (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/lib/Serverless.js:87:74)
    at serverless.init.then (/Users/horike/.nodebrew/node/v6.9.2/lib/node_modules/serverless/bin/serverless:23:50)
 
  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
     Forums:        forum.serverless.com
     Chat:          gitter.im/serverless/serverless
 
  Your Environment Information -----------------------------
     OS:                 darwin
     Node Version:       6.9.2
     Serverless Version: 1.13.2

```



Discussion:

Resolving patch:
diff --git a/lib/plugins/aws/package/lib/generateCoreTemplate.js b/lib/plugins/aws/package/lib/generateCoreTemplate.js
index 7d61fa7f824..ef15492bef8 100644
--- a/lib/plugins/aws/package/lib/generateCoreTemplate.js
+++ b/lib/plugins/aws/package/lib/generateCoreTemplate.js
@@ -36,6 +36,11 @@ module.exports = {
           this.options.stage,
           this.options.region
         ))
+        .catch(err => {
+          throw new this.serverless.classes.Error(
+            `Could not locate deployment bucket. Error: ${err.message}`
+          );
+        })
         .then(resultParam => {
           const result = resultParam;
           if (result.LocationConstraint === '') result.LocationConstraint = 'us-east-1';


Test patch:
diff --git a/lib/plugins/aws/package/lib/generateCoreTemplate.test.js b/lib/plugins/aws/package/lib/generateCoreTemplate.test.js
index 51732129d7e..b8a0e4264c8 100644
--- a/lib/plugins/aws/package/lib/generateCoreTemplate.test.js
+++ b/lib/plugins/aws/package/lib/generateCoreTemplate.test.js
@@ -40,6 +40,25 @@ describe('#generateCoreTemplate()', () => {
     };
   });
 
+  it('should reject an S3 bucket that does not exist', () => {
+    const bucketName = 'com.serverless.deploys';
+    const errorObj = { message: 'Access Denied' };
+
+    const createStackStub = sinon
+      .stub(awsPlugin.provider, 'request').throws(errorObj);
+
+    awsPlugin.serverless.service.provider.deploymentBucket = bucketName;
+    return awsPlugin.generateCoreTemplate()
+      .catch((err) => {
+        expect(createStackStub.args[0][0]).to.equal('S3');
+        expect(createStackStub.args[0][1]).to.equal('getBucketLocation');
+        expect(createStackStub.args[0][2].Bucket).to.equal(bucketName);
+        expect(err.message).to.contain(errorObj.message);
+        expect(err.message).to.contain('Could not locate deployment bucket');
+      })
+      .then(() => {});
+  });
+
   it('should validate the region for the given S3 bucket', () => {
     const bucketName = 'com.serverless.deploys';