Repository: boto/botocore
Pull request #858 (2016-03-30 19:46:01)

Handle case when s3 config key is not a dict
This fixes a regression for the error case when a user
has an invalid CLI config file.  Examples include:

```
[default]
s3 = foo

[profile foo]
s3 =
signature_version = s3v4
```

Previously, we would check that the 's3' key was a dict type
before trying to access values.  This puts back the old
behavior.

Long term, we're going to need something that properly validates
the config keys and gives good error messages for these conditions.

Without this change you'd get this:

```
Traceback (most recent call last):
  File "aws-cli/awscli/clidriver.py", line 186, in main
    return command_table[parsed_args.command](remaining, parsed_args)
  File "aws-cli/awscli/clidriver.py", line 379, in __call__
    return command_table[parsed_args.operation](remaining, parsed_globals)
  File "aws-cli/awscli/clidriver.py", line 548, in __call__
    call_parameters, parsed_globals)
  File "aws-cli/awscli/clidriver.py", line 665, in invoke
    verify=parsed_globals.verify_ssl)
  File "botocore/botocore/session.py", line 814, in create_client
    client_config=config, api_version=api_version)
  File "botocore/botocore/client.py", line 62, in create_client
    verify, credentials, scoped_config, client_config)
  File "botocore/botocore/client.py", line 182, in _get_client_args
    new_config = Config(**config_kwargs)
  File "botocore/botocore/config.py", line 95, in __init__
    self._validate_s3_configuration(self.s3)
  File "botocore/botocore/config.py", line 132, in _validate_s3_configuration
    addressing_style = s3.get('addressing_style')
AttributeError: 'str' object has no attribute 'get'
```

cc @kyleknap @JordonPhillips 


Patch:
diff --git a/botocore/client.py b/botocore/client.py
index 6c366bac6..f558ec740 100644
--- a/botocore/client.py
+++ b/botocore/client.py
@@ -113,6 +113,14 @@ class ClientCreator(object):
         # Check the scoped config first
         if scoped_config is not None:
             s3_configuration = scoped_config.get('s3')
+            # Until we have proper validation of the config file (including
+            # nested types), we have to account for the fact that the s3
+            # key could be parsed as a string, e.g 's3 = foo'.
+            # In the case we'll ignore the key for now.
+            if not isinstance(s3_configuration, dict):
+                logger.debug("The s3 config key is not a dictionary type, "
+                             "ignoring its value of: %s", s3_configuration)
+                s3_configuration = None
 
         # Next specfic client config values takes precedence over
         # specific values in the scoped config.


Test patch:
diff --git a/tests/unit/test_client.py b/tests/unit/test_client.py
index 08007bee9..b002918b1 100644
--- a/tests/unit/test_client.py
+++ b/tests/unit/test_client.py
@@ -1085,6 +1085,14 @@ class TestAutoGeneratedClient(unittest.TestCase):
         self.assertEqual(
             my_client.meta.config.s3['addressing_style'], 'auto')
 
+    def test_client_s3_addressing_style_with_bad_value(self):
+        creator = self.create_client_creator()
+        client = creator.create_client(
+            'myservice', 'us-west-2',
+            scoped_config={'s3': ''},
+        )
+        self.assertIsNone(client.meta.config.s3)
+
     def test_client_s3_addressing_style_with_scoped_config(self):
         creator = self.create_client_creator()
         client = creator.create_client(