Repository: minio/minio-py
Pull request #858 (2020-02-28 21:46:10)

Fixes not subscriptable objects
Fixes issue #857 

As the issue explains, IamEc2MetaData attempts to access http response data and status using subscripts like the example shown below:

```
if res['status'] != 200:
                return []
```

This throws an exception because the `'HTTPResponse' object is not subscriptable`.


febg: @harshavardhana waiting on your review.

Patch:
diff --git a/examples/aws_credentials.py b/examples/aws_credentials.py
index de255f1..e7a9a81 100644
--- a/examples/aws_credentials.py
+++ b/examples/aws_credentials.py
@@ -21,13 +21,17 @@
 # If you wish to retrieve credentials from a different place you can provide
 # the 'endpoint' paramater to the IamEc2MetaData credentials object
 
-from minio.credentials import IamEc2MetaData
+from minio import Minio
+from minio.credentials import IamEc2MetaData, Credentials
 
 # Initialize Minio with IamEc2MetaData default credentials object
 client = Minio('s3.amazonaws.com',
-               credentials=IamEc2MetaData())
+               credentials=Credentials(
+                   provider=IamEc2MetaData()
+               ))
 
 # Initialize Minio with IamEc2MetaData custom
-
 client = Minio('s3.amazonaws.com',
-               credentials=IamEc2MetaData(endpoint='custom.endpoint'))
+               credentials=Credentials(
+                    provider=IamEc2MetaData(endpoint='custom.endpoint')
+               ))
diff --git a/examples/chain_credentials.py b/examples/chain_credentials.py
index 5272497..d4dd786 100644
--- a/examples/chain_credentials.py
+++ b/examples/chain_credentials.py
@@ -19,10 +19,12 @@
 from minio.credentials import Chain, EnvAWS, EnvMinio, IamEc2MetaData
 
 client = Minio('s3.amazonaws.com',
-               credentials=Chain(
-                   providers=[
-                       IamEc2MetaData(),
-                       EnvAWS(),
-                       EnvMinio()
-                   ]
+               credentials=Credentials(
+                   provider=Chain(
+                        providers=[
+                            IamEc2MetaData(),
+                            EnvAWS(),
+                            EnvMinio()
+                        ]
+                   )
                ))
diff --git a/minio/credentials/aws_iam.py b/minio/credentials/aws_iam.py
index 4988281..1d26c84 100644
--- a/minio/credentials/aws_iam.py
+++ b/minio/credentials/aws_iam.py
@@ -42,31 +42,31 @@ class IamEc2MetaData(Provider):
         url = self._endpoint + self.iam_security_creds_path
         try:
             res = self._http_client.urlopen('GET', url)
-            if res['status'] != 200:
-                return []
+            if res.status != 200:
+                return None
         except:
-            return []
-        creds = res['data'].split('\n')
-        return creds
+            return None
+        creds = res.data
+        return creds.decode("utf-8").split('\n')
 
     def request_cred(self, creds_name):
         url = self._endpoint + self.iam_security_creds_path + "/" + creds_name
         res = self._http_client.urlopen('GET', url)
-        if res['status'] != 200:
+        if res.status != 200:
             raise ResponseError(res, 'GET')
 
-        data = json.loads(res['data'])
+        data = json.loads(res.data)
         if data['Code'] != 'Success':
             raise ResponseError(res)
 
         return data
 
     def retrieve(self):
-        creds_list = self.request_cred_list()
-        if len(creds_list) == 0:
+        role_names = self.request_cred_list()
+        if not role_names:
             return Value()
 
-        creds_name = creds_list[0]
+        creds_name = role_names[0]
         role_creds = self.request_cred(creds_name)
         expiration = datetime.datetime.strptime(role_creds['Expiration'], '%Y-%m-%dT%H:%M:%SZ')
         self._expiry.set_expiration(expiration, self.default_expiry_window)


Test patch:
diff --git a/tests/unit/iam_aws_test.py b/tests/unit/iam_aws_test.py
index 093766f..49e46f4 100644
--- a/tests/unit/iam_aws_test.py
+++ b/tests/unit/iam_aws_test.py
@@ -20,15 +20,13 @@ from unittest import TestCase
 from minio.credentials.aws_iam import IamEc2MetaData
 from nose.tools import eq_
 
-class TestIamEc2MetaData(TestCase):
-    @mock.patch('urllib3.PoolManager.urlopen')
-    def test_iam(self, mock_connection):
-        # get provider
-        mock_cred_list = {
-            "status" : 200,
-            "data" : "test-s3-full-access-for-minio-ec2"
-        }
-        request_cred_data = json.dumps({
+class CredListResponse(object):
+    status = 200
+    data = b'test-s3-full-access-for-minio-ec2'
+
+class CredsResponse(object):
+    status = 200
+    data = json.dumps({
             "Code" : 'Success',
             "Type" : 'AWS-HMAC',
             "AccessKeyId" : 'accessKey',
@@ -37,11 +35,12 @@ class TestIamEc2MetaData(TestCase):
             "Expiration" : '2014-12-16T01:51:37Z',
             "LastUpdated" : '2009-11-23T0:00:00Z'
         })
-        mock_request_cred = {
-            "status" : 200,
-            "data": request_cred_data
-        }
-        mock_connection.side_effect = [mock_cred_list, mock_request_cred]
+
+class TestIamEc2MetaData(TestCase):
+    @mock.patch('urllib3.PoolManager.urlopen')
+    def test_iam(self, mock_connection):
+        # get provider
+        mock_connection.side_effect = [CredListResponse(), CredsResponse()]
         provider = IamEc2MetaData()
         # retrieve credentials
         creds = provider.retrieve()