Repository: ansible/ansible-modules-core

Issue:
NoneType Object Exception in S3 module
##### Issue Type:

Bug Report
##### Ansible Version:

1.8.4 and 

```
ansible 1.9.0 (detached HEAD bce4bb2ce2) last updated 2015/03/18 17:03:10 (GMT -400)
  lib/ansible/modules/core: (detached HEAD 31cc5f543f) last updated 2015/03/16 12:19:43 (GMT -400)
  lib/ansible/modules/extras: (detached HEAD 8baba98ebe) last updated 2015/03/16 12:19:43 (GMT -400)
  v2/ansible/modules/core: (detached HEAD 34784b7a61) last updated 2015/03/16 12:19:43 (GMT -400)
  v2/ansible/modules/extras: (detached HEAD 46e316a20a) last updated 2015/03/16 12:19:44 (GMT -400)
  configured module search path = None
```
##### Environment:

OSX
##### Summary:

Seems that the instantiation of the S3 connection object is faulty.
##### Steps To Reproduce:

Run this playbook (note: also attempted with put with the same outcome):

```

---
- name: Spin up instances for testing
  connection: local
  hosts: localhost
  tasks:
     - name: s3s3
       s3:
        bucket: deleteme
        aws_access_key: '{{ access }}'
        aws_secret_key: '{{ secret }}'
        mode: create
```
##### Expected Results:

The bucket gets created.
##### Actual Results:

```
failed: [localhost] => {"failed": true, "parsed": false}
Traceback (most recent call last):
  File "/Users/jdavila/.ansible/tmp/ansible-tmp-1426712862.59-255191123006590/s3", line 2299, in <module>
    main()
  File "/Users/jdavila/.ansible/tmp/ansible-tmp-1426712862.59-255191123006590/s3", line 452, in main
    bucketrtn = bucket_check(module, s3, bucket)
  File "/Users/jdavila/.ansible/tmp/ansible-tmp-1426712862.59-255191123006590/s3", line 162, in bucket_check
    except s3.provider.storage_response_error, e:
AttributeError: 'NoneType' object has no attribute 'provider'


FATAL: all hosts have already failed -- aborting
```



Discussion:
+1 ... with the PPA repo getting bumped to 1.9.0, this broke all of our provisioning scripts. This was not an issue in 1.8.4 for me.

so the only reason I can fathom for s3 being None at this point is that the connection failed to happen and did not cause an Exception. ... using the object being handled in the exception handler ....gets us here.


Resolving patch:
diff --git a/cloud/amazon/s3.py b/cloud/amazon/s3.py
--- a/cloud/amazon/s3.py
+++ b/cloud/amazon/s3.py
@@ -320,8 +320,8 @@ def main():
 
     # Look at s3_url and tweak connection settings
     # if connecting to Walrus or fakes3
-    if is_fakes3(s3_url):
-        try:
+    try:
+        if is_fakes3(s3_url):
             fakes3 = urlparse.urlparse(s3_url)
             s3 = boto.connect_s3(
                 aws_access_key,
@@ -330,19 +330,22 @@ def main():
                 host=fakes3.hostname,
                 port=fakes3.port,
                 calling_format=OrdinaryCallingFormat())
-        except boto.exception.NoAuthHandlerFound, e:
-            module.fail_json(msg = str(e))
-    elif is_walrus(s3_url):
-        try:
+        elif is_walrus(s3_url):
             walrus = urlparse.urlparse(s3_url).hostname
             s3 = boto.connect_walrus(walrus, aws_access_key, aws_secret_key)
-        except boto.exception.NoAuthHandlerFound, e:
-            module.fail_json(msg = str(e))
-    else:
-        try:
+        else:
             s3 = boto.s3.connect_to_region(location, aws_access_key_id=aws_access_key, aws_secret_access_key=aws_secret_key, is_secure=True, calling_format=OrdinaryCallingFormat())
-        except boto.exception.NoAuthHandlerFound, e:
-            module.fail_json(msg = str(e))
+            # use this as fallback because connect_to_region seems to fail in boto + non 'classic' aws accounts in some cases
+            if s3 is None:
+                s3 = boto.connect_s3(aws_access_key, aws_secret_key)
+
+    except boto.exception.NoAuthHandlerFound, e:
+        module.fail_json(msg='No Authentication Handler found: %s ' % str(e))
+    except Exception, e:
+        module.fail_json(msg='Failed to connect to S3: %s' % str(e))
+
+    if s3 is None: # this should never happen
+        module.fail_json(msg ='Unknown error, failed to create s3 connection, no information from boto.')
 
     # If our mode is a GET operation (download), go through the procedure as appropriate ...
     if mode == 'get':


Test patch: