summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.rst6
-rw-r--r--boto/__init__.py46
-rw-r--r--boto/auth.py4
-rw-r--r--boto/cognito/__init__.py21
-rw-r--r--boto/cognito/identity/__init__.py42
-rw-r--r--boto/cognito/identity/exceptions.py40
-rw-r--r--boto/cognito/identity/layer1.py303
-rw-r--r--boto/cognito/sync/__init__.py41
-rw-r--r--boto/cognito/sync/exceptions.py50
-rw-r--r--boto/cognito/sync/layer1.py307
-rw-r--r--boto/ec2/autoscale/__init__.py5
-rw-r--r--boto/ec2/autoscale/launchconfig.py4
-rw-r--r--boto/ec2/elb/__init__.py4
-rw-r--r--boto/endpoints.json9
-rw-r--r--boto/sts/connection.py2
-rw-r--r--boto/vpc/routetable.py6
-rw-r--r--docs/source/index.rst2
-rw-r--r--docs/source/ref/cognito-identity.rst26
-rw-r--r--docs/source/ref/cognito-sync.rst26
-rw-r--r--docs/source/s3_tut.rst2
-rw-r--r--setup.py3
-rw-r--r--tests/integration/cognito/__init__.py41
-rw-r--r--tests/integration/cognito/identity/__init__.py21
-rw-r--r--tests/integration/cognito/identity/test_cognito_identity.py52
-rw-r--r--tests/integration/cognito/sync/__init__.py21
-rw-r--r--tests/integration/cognito/sync/test_cognito_sync.py46
-rw-r--r--[-rwxr-xr-x]tests/unit/ec2/autoscale/test_group.py10
-rw-r--r--tests/unit/s3/test_connection.py20
-rw-r--r--tests/unit/sts/test_connection.py20
-rw-r--r--tests/unit/vpc/test_routetable.py20
30 files changed, 1165 insertions, 35 deletions
diff --git a/README.rst b/README.rst
index e78a0ad4..c7de6205 100644
--- a/README.rst
+++ b/README.rst
@@ -5,10 +5,10 @@ boto 2.32.1
Released: 04-Aug-2014
-.. image:: https://travis-ci.org/boto/boto.png?branch=develop
+.. image:: https://travis-ci.org/boto/boto.svg?branch=develop
:target: https://travis-ci.org/boto/boto
-.. image:: https://pypip.in/d/boto/badge.png
+.. image:: https://pypip.in/d/boto/badge.svg
:target: https://pypi.python.org/pypi/boto/
************
@@ -67,6 +67,8 @@ At the moment, boto supports:
* Amazon Simple Queue Service (SQS) (Python 3)
* Amazon Simple Notification Server (SNS) (Python 3)
* Amazon Simple Email Service (SES) (Python 3)
+ * Amazon Cognito Identity (Python 3)
+ * Amazon Cognito Sync (Python 3)
* Monitoring
diff --git a/boto/__init__.py b/boto/__init__.py
index d76b67cc..1737f45c 100644
--- a/boto/__init__.py
+++ b/boto/__init__.py
@@ -882,6 +882,52 @@ def connect_route53domains(aws_access_key_id=None,
)
+def connect_cognito_identity(aws_access_key_id=None,
+ aws_secret_access_key=None,
+ **kwargs):
+ """
+ Connect to Amazon Cognito Identity
+
+ :type aws_access_key_id: string
+ :param aws_access_key_id: Your AWS Access Key ID
+
+ :type aws_secret_access_key: string
+ :param aws_secret_access_key: Your AWS Secret Access Key
+
+ rtype: :class:`boto.cognito.identity.layer1.CognitoIdentityConnection`
+ :return: A connection to the Amazon Cognito Identity service
+ """
+ from boto.cognito.identity.layer1 import CognitoIdentityConnection
+ return CognitoIdentityConnection(
+ aws_access_key_id=aws_access_key_id,
+ aws_secret_access_key=aws_secret_access_key,
+ **kwargs
+ )
+
+
+def connect_cognito_sync(aws_access_key_id=None,
+ aws_secret_access_key=None,
+ **kwargs):
+ """
+ Connect to Amazon Cognito Sync
+
+ :type aws_access_key_id: string
+ :param aws_access_key_id: Your AWS Access Key ID
+
+ :type aws_secret_access_key: string
+ :param aws_secret_access_key: Your AWS Secret Access Key
+
+ rtype: :class:`boto.cognito.sync.layer1.CognitoSyncConnection`
+ :return: A connection to the Amazon Cognito Sync service
+ """
+ from boto.cognito.sync.layer1 import CognitoSyncConnection
+ return CognitoSyncConnection(
+ aws_access_key_id=aws_access_key_id,
+ aws_secret_access_key=aws_secret_access_key,
+ **kwargs
+ )
+
+
def storage_uri(uri_str, default_scheme='file', debug=0, validate=True,
bucket_storage_uri_class=BucketStorageUri,
suppress_consec_slashes=True, is_latest=False):
diff --git a/boto/auth.py b/boto/auth.py
index bc8d3b7c..f05bb275 100644
--- a/boto/auth.py
+++ b/boto/auth.py
@@ -703,6 +703,10 @@ class S3HmacAuthV4Handler(HmacAuthV4Handler, AuthHandler):
if self._provider.security_token:
params['X-Amz-Security-Token'] = self._provider.security_token
+ headers_to_sign = self.headers_to_sign(req)
+ l = sorted(['%s' % n.lower().strip() for n in headers_to_sign])
+ params['X-Amz-SignedHeaders'] = ';'.join(l)
+
req.params.update(params)
cr = self.canonical_request(req)
diff --git a/boto/cognito/__init__.py b/boto/cognito/__init__.py
new file mode 100644
index 00000000..70cc23fe
--- /dev/null
+++ b/boto/cognito/__init__.py
@@ -0,0 +1,21 @@
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
diff --git a/boto/cognito/identity/__init__.py b/boto/cognito/identity/__init__.py
new file mode 100644
index 00000000..e58b480b
--- /dev/null
+++ b/boto/cognito/identity/__init__.py
@@ -0,0 +1,42 @@
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates.
+# All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+from boto.regioninfo import RegionInfo, get_regions
+
+
+def regions():
+ """
+ Get all available regions for the Amazon Cognito Identity service.
+
+ :rtype: list
+ :return: A list of :class:`boto.regioninfo.RegionInfo`
+ """
+ from boto.cognito.identity.layer1 import CognitoIdentityConnection
+ return get_regions('cognito-identity',
+ connection_cls=CognitoIdentityConnection)
+
+
+def connect_to_region(region_name, **kw_params):
+ for region in regions():
+ if region.name == region_name:
+ return region.connect(**kw_params)
+ return None
diff --git a/boto/cognito/identity/exceptions.py b/boto/cognito/identity/exceptions.py
new file mode 100644
index 00000000..179089df
--- /dev/null
+++ b/boto/cognito/identity/exceptions.py
@@ -0,0 +1,40 @@
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+from boto.exception import BotoServerError
+
+
+class LimitExceededException(BotoServerError):
+ pass
+
+
+class ResourceConflictException(BotoServerError):
+ pass
+
+
+class TooManyRequestsException(BotoServerError):
+ pass
+
+
+class InvalidParameterException(BotoServerError):
+ pass
+
+
+class ResourceNotFoundException(BotoServerError):
+ pass
+
+
+class InternalErrorException(BotoServerError):
+ pass
+
+
+class NotAuthorizedException(BotoServerError):
+ pass
diff --git a/boto/cognito/identity/layer1.py b/boto/cognito/identity/layer1.py
new file mode 100644
index 00000000..0a9c8e4e
--- /dev/null
+++ b/boto/cognito/identity/layer1.py
@@ -0,0 +1,303 @@
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+
+import boto
+from boto.compat import json
+from boto.connection import AWSQueryConnection
+from boto.regioninfo import RegionInfo
+from boto.exception import JSONResponseError
+from boto.cognito.identity import exceptions
+
+
+class CognitoIdentityConnection(AWSQueryConnection):
+ """
+ Amazon Cognito
+ Amazon Cognito is a web service that facilitates the delivery of
+ scoped, temporary credentials to mobile devices or other untrusted
+ environments. Amazon Cognito uniquely identifies a device or user
+ and supplies the user with a consistent identity throughout the
+ lifetime of an application.
+
+ Amazon Cognito lets users authenticate with third-party identity
+ providers (Facebook, Google, or Login with Amazon). As a
+ developer, you decide which identity providers to trust. You can
+ also choose to support unauthenticated access from your
+ application. Your users are provided with Cognito tokens that
+ uniquely identify their device and any information provided about
+ third-party logins.
+ """
+ APIVersion = "2014-06-30"
+ DefaultRegionName = "us-east-1"
+ DefaultRegionEndpoint = "cognito-identity.us-east-1.amazonaws.com"
+ ServiceName = "CognitoIdentity"
+ TargetPrefix = "AWSCognitoIdentityService"
+ ResponseError = JSONResponseError
+
+ _faults = {
+ "LimitExceededException": exceptions.LimitExceededException,
+ "ResourceConflictException": exceptions.ResourceConflictException,
+ "TooManyRequestsException": exceptions.TooManyRequestsException,
+ "InvalidParameterException": exceptions.InvalidParameterException,
+ "ResourceNotFoundException": exceptions.ResourceNotFoundException,
+ "InternalErrorException": exceptions.InternalErrorException,
+ "NotAuthorizedException": exceptions.NotAuthorizedException,
+ }
+
+
+ def __init__(self, **kwargs):
+ region = kwargs.pop('region', None)
+ if not region:
+ region = RegionInfo(self, self.DefaultRegionName,
+ self.DefaultRegionEndpoint)
+
+ if 'host' not in kwargs or kwargs['host'] is None:
+ kwargs['host'] = region.endpoint
+
+ super(CognitoIdentityConnection, self).__init__(**kwargs)
+ self.region = region
+
+ def _required_auth_capability(self):
+ return ['hmac-v4']
+
+ def create_identity_pool(self, identity_pool_name,
+ allow_unauthenticated_identities,
+ supported_login_providers=None):
+ """
+ Creates a new identity pool. The identity pool is a store of
+ user identity information that is specific to your AWS
+ account.
+
+ :type identity_pool_name: string
+ :param identity_pool_name: A string that you provide.
+
+ :type allow_unauthenticated_identities: boolean
+ :param allow_unauthenticated_identities: TRUE if the identity pool
+ supports unauthenticated logins.
+
+ :type supported_login_providers: map
+ :param supported_login_providers: Optional key:value pairs mapping
+ provider names to provider app IDs.
+
+ """
+ params = {
+ 'IdentityPoolName': identity_pool_name,
+ 'AllowUnauthenticatedIdentities': allow_unauthenticated_identities,
+ }
+ if supported_login_providers is not None:
+ params['SupportedLoginProviders'] = supported_login_providers
+ return self.make_request(action='CreateIdentityPool',
+ body=json.dumps(params))
+
+ def delete_identity_pool(self, identity_pool_id):
+ """
+ Deletes a user pool. Once a pool is deleted, users will not be
+ able to authenticate with the pool.
+
+ :type identity_pool_id: string
+ :param identity_pool_id: An identity pool ID in the format REGION:GUID.
+
+ """
+ params = {'IdentityPoolId': identity_pool_id, }
+ return self.make_request(action='DeleteIdentityPool',
+ body=json.dumps(params))
+
+ def describe_identity_pool(self, identity_pool_id):
+ """
+ Gets details about a particular identity pool, including the
+ pool name, ID description, creation date, and current number
+ of users.
+
+ :type identity_pool_id: string
+ :param identity_pool_id: An identity pool ID in the format REGION:GUID.
+
+ """
+ params = {'IdentityPoolId': identity_pool_id, }
+ return self.make_request(action='DescribeIdentityPool',
+ body=json.dumps(params))
+
+ def get_id(self, account_id, identity_pool_id, logins=None):
+ """
+ Generates (or retrieves) a Cognito ID. Supplying multiple
+ logins will create an implicit linked account.
+
+ :type account_id: string
+ :param account_id: A standard AWS account ID (9+ digits).
+
+ :type identity_pool_id: string
+ :param identity_pool_id: An identity pool ID in the format REGION:GUID.
+
+ :type logins: map
+ :param logins: A set of optional name/value pairs that map provider
+ names to provider tokens.
+
+ """
+ params = {
+ 'AccountId': account_id,
+ 'IdentityPoolId': identity_pool_id,
+ }
+ if logins is not None:
+ params['Logins'] = logins
+ return self.make_request(action='GetId',
+ body=json.dumps(params))
+
+ def get_open_id_token(self, identity_id, logins=None):
+ """
+ Gets an OpenID token, using a known Cognito ID. This known
+ Cognito ID is returned from GetId. You can optionally add
+ additional logins for the identity. Supplying multiple logins
+ creates an implicit link.
+
+ :type identity_id: string
+ :param identity_id: A unique identifier in the format REGION:GUID.
+
+ :type logins: map
+ :param logins: A set of optional name/value pairs that map provider
+ names to provider tokens.
+
+ """
+ params = {'IdentityId': identity_id, }
+ if logins is not None:
+ params['Logins'] = logins
+ return self.make_request(action='GetOpenIdToken',
+ body=json.dumps(params))
+
+ def list_identities(self, identity_pool_id, max_results, next_token=None):
+ """
+ Lists the identities in a pool.
+
+ :type identity_pool_id: string
+ :param identity_pool_id: An identity pool ID in the format REGION:GUID.
+
+ :type max_results: integer
+ :param max_results: The maximum number of identities to return.
+
+ :type next_token: string
+ :param next_token: A pagination token.
+
+ """
+ params = {
+ 'IdentityPoolId': identity_pool_id,
+ 'MaxResults': max_results,
+ }
+ if next_token is not None:
+ params['NextToken'] = next_token
+ return self.make_request(action='ListIdentities',
+ body=json.dumps(params))
+
+ def list_identity_pools(self, max_results, next_token=None):
+ """
+ Lists all of the Cognito identity pools registered for your
+ account.
+
+ :type max_results: integer
+ :param max_results: The maximum number of identities to return.
+
+ :type next_token: string
+ :param next_token: A pagination token.
+
+ """
+ params = {'MaxResults': max_results, }
+ if next_token is not None:
+ params['NextToken'] = next_token
+ return self.make_request(action='ListIdentityPools',
+ body=json.dumps(params))
+
+ def unlink_identity(self, identity_id, logins, logins_to_remove):
+ """
+ Unlinks a federated identity from an existing account.
+ Unlinked logins will be considered new identities next time
+ they are seen. Removing the last linked login will make this
+ identity inaccessible.
+
+ :type identity_id: string
+ :param identity_id: A unique identifier in the format REGION:GUID.
+
+ :type logins: map
+ :param logins: A set of optional name/value pairs that map provider
+ names to provider tokens.
+
+ :type logins_to_remove: list
+ :param logins_to_remove: Provider names to unlink from this identity.
+
+ """
+ params = {
+ 'IdentityId': identity_id,
+ 'Logins': logins,
+ 'LoginsToRemove': logins_to_remove,
+ }
+ return self.make_request(action='UnlinkIdentity',
+ body=json.dumps(params))
+
+ def update_identity_pool(self, identity_pool_id, identity_pool_name,
+ allow_unauthenticated_identities,
+ supported_login_providers=None):
+ """
+ Updates a user pool.
+
+ :type identity_pool_id: string
+ :param identity_pool_id: An identity pool ID in the format REGION:GUID.
+
+ :type identity_pool_name: string
+ :param identity_pool_name: A string that you provide.
+
+ :type allow_unauthenticated_identities: boolean
+ :param allow_unauthenticated_identities: TRUE if the identity pool
+ supports unauthenticated logins.
+
+ :type supported_login_providers: map
+ :param supported_login_providers: Optional key:value pairs mapping
+ provider names to provider app IDs.
+
+ """
+ params = {
+ 'IdentityPoolId': identity_pool_id,
+ 'IdentityPoolName': identity_pool_name,
+ 'AllowUnauthenticatedIdentities': allow_unauthenticated_identities,
+ }
+ if supported_login_providers is not None:
+ params['SupportedLoginProviders'] = supported_login_providers
+ return self.make_request(action='UpdateIdentityPool',
+ body=json.dumps(params))
+
+ def make_request(self, action, body):
+ headers = {
+ 'X-Amz-Target': '%s.%s' % (self.TargetPrefix, action),
+ 'Host': self.region.endpoint,
+ 'Content-Type': 'application/x-amz-json-1.1',
+ 'Content-Length': str(len(body)),
+ }
+ http_request = self.build_base_http_request(
+ method='POST', path='/', auth_path='/', params={},
+ headers=headers, data=body)
+ response = self._mexe(http_request, sender=None,
+ override_num_retries=10)
+ response_body = response.read().decode('utf-8')
+ boto.log.debug(response_body)
+ if response.status == 200:
+ if response_body:
+ return json.loads(response_body)
+ else:
+ json_body = json.loads(response_body)
+ fault_name = json_body.get('__type', None)
+ exception_class = self._faults.get(fault_name, self.ResponseError)
+ raise exception_class(response.status, response.reason,
+ body=json_body)
diff --git a/boto/cognito/sync/__init__.py b/boto/cognito/sync/__init__.py
new file mode 100644
index 00000000..3d48bd18
--- /dev/null
+++ b/boto/cognito/sync/__init__.py
@@ -0,0 +1,41 @@
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates.
+# All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+from boto.regioninfo import RegionInfo, get_regions
+
+
+def regions():
+ """
+ Get all available regions for the Amazon Cognito Sync service.
+
+ :rtype: list
+ :return: A list of :class:`boto.regioninfo.RegionInfo`
+ """
+ from boto.cognito.sync.layer1 import CognitoSyncConnection
+ return get_regions('cognito-sync', connection_cls=CognitoSyncConnection)
+
+
+def connect_to_region(region_name, **kw_params):
+ for region in regions():
+ if region.name == region_name:
+ return region.connect(**kw_params)
+ return None
diff --git a/boto/cognito/sync/exceptions.py b/boto/cognito/sync/exceptions.py
new file mode 100644
index 00000000..d64fb278
--- /dev/null
+++ b/boto/cognito/sync/exceptions.py
@@ -0,0 +1,50 @@
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+from boto.exception import BotoServerError
+
+
+class LimitExceededException(BotoServerError):
+ pass
+
+
+class ResourceConflictException(BotoServerError):
+ pass
+
+
+class TooManyRequestsException(BotoServerError):
+ pass
+
+
+class InvalidParameterException(BotoServerError):
+ pass
+
+
+class ResourceNotFoundException(BotoServerError):
+ pass
+
+
+class InternalErrorException(BotoServerError):
+ pass
+
+
+class NotAuthorizedException(BotoServerError):
+ pass
diff --git a/boto/cognito/sync/layer1.py b/boto/cognito/sync/layer1.py
new file mode 100644
index 00000000..545af5eb
--- /dev/null
+++ b/boto/cognito/sync/layer1.py
@@ -0,0 +1,307 @@
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+from boto.compat import json
+from boto.exception import JSONResponseError
+from boto.connection import AWSAuthConnection
+from boto.regioninfo import RegionInfo
+from boto.cognito.sync import exceptions
+
+
+class CognitoSyncConnection(AWSAuthConnection):
+ """
+ Amazon Cognito Sync
+ Amazon Cognito Sync provides an AWS service and client library
+ that enable cross-device syncing of application-related user data.
+ High-level client libraries are available for both iOS and
+ Android. You can use these libraries to persist data locally so
+ that it's available even if the device is offline. Developer
+ credentials don't need to be stored on the mobile device to access
+ the service. You can use Amazon Cognito to obtain a normalized
+ user ID and credentials. User data is persisted in a dataset that
+ can store up to 1 MB of key-value pairs, and you can have up to 20
+ datasets per user identity.
+ """
+ APIVersion = "2014-06-30"
+ DefaultRegionName = "us-east-1"
+ DefaultRegionEndpoint = "cognito-sync.us-east-1.amazonaws.com"
+ ResponseError = JSONResponseError
+
+ _faults = {
+ "LimitExceededException": exceptions.LimitExceededException,
+ "ResourceConflictException": exceptions.ResourceConflictException,
+ "TooManyRequestsException": exceptions.TooManyRequestsException,
+ "InvalidParameterException": exceptions.InvalidParameterException,
+ "ResourceNotFoundException": exceptions.ResourceNotFoundException,
+ "InternalErrorException": exceptions.InternalErrorException,
+ "NotAuthorizedException": exceptions.NotAuthorizedException,
+ }
+
+
+ def __init__(self, **kwargs):
+ region = kwargs.get('region')
+ if not region:
+ region = RegionInfo(self, self.DefaultRegionName,
+ self.DefaultRegionEndpoint)
+ else:
+ del kwargs['region']
+ kwargs['host'] = region.endpoint
+ super(CognitoSyncConnection, self).__init__(**kwargs)
+ self.region = region
+
+ def _required_auth_capability(self):
+ return ['hmac-v4']
+
+ def delete_dataset(self, identity_pool_id, identity_id, dataset_name):
+ """
+ Deletes the specific dataset. The dataset will be deleted
+ permanently, and the action can't be undone. Datasets that
+ this dataset was merged with will no longer report the merge.
+ Any consequent operation on this dataset will result in a
+ ResourceNotFoundException.
+
+ :type identity_pool_id: string
+ :param identity_pool_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ :type identity_id: string
+ :param identity_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ :type dataset_name: string
+ :param dataset_name: A string of up to 128 characters. Allowed
+ characters are a-z, A-Z, 0-9, '_' (underscore), '-' (dash), and '.'
+ (dot).
+
+ """
+ uri = '/identitypools/{0}/identities/{1}/datasets/{2}'.format(
+ identity_pool_id, identity_id, dataset_name)
+ return self.make_request('DELETE', uri, expected_status=200)
+
+ def describe_dataset(self, identity_pool_id, identity_id, dataset_name):
+ """
+ Gets metadata about a dataset by identity and dataset name.
+
+ :type identity_pool_id: string
+ :param identity_pool_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ :type identity_id: string
+ :param identity_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ :type dataset_name: string
+ :param dataset_name: A string of up to 128 characters. Allowed
+ characters are a-z, A-Z, 0-9, '_' (underscore), '-' (dash), and '.'
+ (dot).
+
+ """
+ uri = '/identitypools/{0}/identities/{1}/datasets/{2}'.format(
+ identity_pool_id, identity_id, dataset_name)
+ return self.make_request('GET', uri, expected_status=200)
+
+ def describe_identity_pool_usage(self, identity_pool_id):
+ """
+ Gets usage details (for example, data storage) about a
+ particular identity pool.
+
+ :type identity_pool_id: string
+ :param identity_pool_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ """
+ uri = '/identitypools/{0}'.format(identity_pool_id)
+ return self.make_request('GET', uri, expected_status=200)
+
+ def describe_identity_usage(self, identity_pool_id, identity_id):
+ """
+ Gets usage information for an identity, including number of
+ datasets and data usage.
+
+ :type identity_pool_id: string
+ :param identity_pool_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ :type identity_id: string
+ :param identity_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ """
+ uri = '/identitypools/{0}/identities/{1}'.format(
+ identity_pool_id, identity_id)
+ return self.make_request('GET', uri, expected_status=200)
+
+ def list_datasets(self, identity_pool_id, identity_id, next_token=None,
+ max_results=None):
+ """
+ Lists datasets for an identity.
+
+ :type identity_pool_id: string
+ :param identity_pool_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ :type identity_id: string
+ :param identity_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ :type next_token: string
+ :param next_token: A pagination token for obtaining the next page of
+ results.
+
+ :type max_results: integer
+ :param max_results: The maximum number of results to be returned.
+
+ """
+ uri = '/identitypools/{0}/identities/{1}/datasets'.format(
+ identity_pool_id, identity_id)
+ params = {}
+ headers = {}
+ return self.make_request('GET', uri, expected_status=200,
+ data=json.dumps(params), headers=headers)
+
+ def list_identity_pool_usage(self, next_token=None, max_results=None):
+ """
+ Gets a list of identity pools registered with Cognito.
+
+ :type next_token: string
+ :param next_token: A pagination token for obtaining the next page of
+ results.
+
+ :type max_results: integer
+ :param max_results: The maximum number of results to be returned.
+
+ """
+ uri = '/identitypools'
+ params = {}
+ headers = {}
+ return self.make_request('GET', uri, expected_status=200,
+ data=json.dumps(params), headers=headers)
+
+ def list_records(self, identity_pool_id, identity_id, dataset_name,
+ last_sync_count=None, next_token=None, max_results=None,
+ sync_session_token=None):
+ """
+ Gets paginated records, optionally changed after a particular
+ sync count for a dataset and identity.
+
+ :type identity_pool_id: string
+ :param identity_pool_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ :type identity_id: string
+ :param identity_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ :type dataset_name: string
+ :param dataset_name: A string of up to 128 characters. Allowed
+ characters are a-z, A-Z, 0-9, '_' (underscore), '-' (dash), and '.'
+ (dot).
+
+ :type last_sync_count: long
+ :param last_sync_count: The last server sync count for this record.
+
+ :type next_token: string
+ :param next_token: A pagination token for obtaining the next page of
+ results.
+
+ :type max_results: integer
+ :param max_results: The maximum number of results to be returned.
+
+ :type sync_session_token: string
+ :param sync_session_token: A token containing a session ID, identity
+ ID, and expiration.
+
+ """
+ uri = '/identitypools/{0}/identities/{1}/datasets/{2}/records'.format(
+ identity_pool_id, identity_id, dataset_name)
+ params = {}
+ headers = {}
+ return self.make_request('GET', uri, expected_status=200,
+ data=json.dumps(params), headers=headers)
+
+ def update_records(self, identity_pool_id, identity_id, dataset_name,
+ sync_session_token, record_patches=None,
+ client_context=None):
+ """
+ Posts updates to records and add and delete records for a
+ dataset and user.
+
+ :type identity_pool_id: string
+ :param identity_pool_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ :type identity_id: string
+ :param identity_id: A name-spaced GUID (for example, us-
+ east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon
+ Cognito. GUID generation is unique within a region.
+
+ :type dataset_name: string
+ :param dataset_name: A string of up to 128 characters. Allowed
+ characters are a-z, A-Z, 0-9, '_' (underscore), '-' (dash), and '.'
+ (dot).
+
+ :type record_patches: list
+ :param record_patches:
+
+ :type sync_session_token: string
+ :param sync_session_token: The SyncSessionToken returned by a previous
+ call to ListRecords for this dataset and identity.
+
+ :type client_context: string
+ :param client_context:
+
+ """
+ uri = '/identitypools/{0}/identities/{1}/datasets/{2}'.format(
+ identity_pool_id, identity_id, dataset_name)
+ params = {'SyncSessionToken': sync_session_token, }
+ headers = {}
+ if record_patches is not None:
+ params['RecordPatches'] = record_patches
+ if client_context is not None:
+ headers['x-amz-Client-Context'] = client_context
+ return self.make_request('POST', uri, expected_status=200,
+ data=json.dumps(params), headers=headers)
+
+ def make_request(self, verb, resource, headers=None, data='',
+ expected_status=None, params=None):
+ if headers is None:
+ headers = {}
+ response = AWSAuthConnection.make_request(
+ self, verb, resource, headers=headers, data=data, params=params)
+ body = json.loads(response.read().decode('utf-8'))
+ if response.status == expected_status:
+ return body
+ else:
+ error_type = response.getheader('x-amzn-ErrorType').split(':')[0]
+ error_class = self._faults.get(error_type, self.ResponseError)
+ raise error_class(response.status, response.reason, body)
diff --git a/boto/ec2/autoscale/__init__.py b/boto/ec2/autoscale/__init__.py
index 96c42848..5a58748d 100644
--- a/boto/ec2/autoscale/__init__.py
+++ b/boto/ec2/autoscale/__init__.py
@@ -222,7 +222,10 @@ class AutoScaleConnection(AWSQueryConnection):
if launch_config.key_name:
params['KeyName'] = launch_config.key_name
if launch_config.user_data:
- params['UserData'] = base64.b64encode(launch_config.user_data).decode('utf-8')
+ user_data = launch_config.user_data
+ if isinstance(user_data, six.text_type):
+ user_data = user_data.encode('utf-8')
+ params['UserData'] = base64.b64encode(user_data).decode('utf-8')
if launch_config.kernel_id:
params['KernelId'] = launch_config.kernel_id
if launch_config.ramdisk_id:
diff --git a/boto/ec2/autoscale/launchconfig.py b/boto/ec2/autoscale/launchconfig.py
index 6d897fd2..889cee21 100644
--- a/boto/ec2/autoscale/launchconfig.py
+++ b/boto/ec2/autoscale/launchconfig.py
@@ -128,8 +128,8 @@ class LaunchConfiguration(object):
:type instance_type: str
:param instance_type: The instance type
- :type kern_id: str
- :param kern_id: Kernel id for instance
+ :type kernel_id: str
+ :param kernel_id: Kernel id for instance
:type ramdisk_id: str
:param ramdisk_id: RAM disk id for instance
diff --git a/boto/ec2/elb/__init__.py b/boto/ec2/elb/__init__.py
index 5ae272f7..f88b4937 100644
--- a/boto/ec2/elb/__init__.py
+++ b/boto/ec2/elb/__init__.py
@@ -400,7 +400,7 @@ class ELBConnection(AWSQueryConnection):
:param attribute: The attribute you wish to change.
* crossZoneLoadBalancing - Boolean (true)
- * connectionSettings - :py:class:`ConnectionSettingAttribute` instance
+ * connectingSettings - :py:class:`ConnectionSettingAttribute` instance
* accessLog - :py:class:`AccessLogAttribute` instance
* connectionDraining - :py:class:`ConnectionDrainingAttribute` instance
@@ -472,7 +472,7 @@ class ELBConnection(AWSQueryConnection):
* accessLog - :py:class:`AccessLogAttribute` instance
* crossZoneLoadBalancing - Boolean
- * connectionSettings - :py:class:`ConnectionSettingAttribute` instance
+ * connectingSettings - :py:class:`ConnectionSettingAttribute` instance
* connectionDraining - :py:class:`ConnectionDrainingAttribute`
instance
diff --git a/boto/endpoints.json b/boto/endpoints.json
index 5c95b5ca..46276438 100644
--- a/boto/endpoints.json
+++ b/boto/endpoints.json
@@ -35,6 +35,9 @@
},
"cloudsearch": {
"ap-southeast-1": "cloudsearch.ap-southeast-1.amazonaws.com",
+ "ap-southeast-2": "cloudsearch.ap-southeast-2.amazonaws.com",
+ "ap-northeast-1": "cloudsearch.ap-northeast-1.amazonaws.com",
+ "sa-east-1": "cloudsearch.sa-east-1.amazonaws.com",
"eu-west-1": "cloudsearch.eu-west-1.amazonaws.com",
"us-east-1": "cloudsearch.us-east-1.amazonaws.com",
"us-west-1": "cloudsearch.us-west-1.amazonaws.com",
@@ -62,6 +65,12 @@
"us-west-1": "monitoring.us-west-1.amazonaws.com",
"us-west-2": "monitoring.us-west-2.amazonaws.com"
},
+ "cognito-identity": {
+ "us-east-1": "cognito-identity.us-east-1.amazonaws.com"
+ },
+ "cognito-sync": {
+ "us-east-1": "cognito-sync.us-east-1.amazonaws.com"
+ },
"datapipeline": {
"us-east-1": "datapipeline.us-east-1.amazonaws.com",
"us-west-2": "datapipeline.us-west-2.amazonaws.com",
diff --git a/boto/sts/connection.py b/boto/sts/connection.py
index 59526222..e02f0f1e 100644
--- a/boto/sts/connection.py
+++ b/boto/sts/connection.py
@@ -92,7 +92,7 @@ class STSConnection(AWSQueryConnection):
if self.anon:
return ['pure-query']
else:
- return ['sign-v2']
+ return ['hmac-v4']
def _check_token_cache(self, token_key, duration=None, window_seconds=60):
token = _session_token_cache.get(token_key, None)
diff --git a/boto/vpc/routetable.py b/boto/vpc/routetable.py
index 7f83717e..21060ee9 100644
--- a/boto/vpc/routetable.py
+++ b/boto/vpc/routetable.py
@@ -67,6 +67,8 @@ class Route(object):
self.destination_cidr_block = None
self.gateway_id = None
self.instance_id = None
+ self.interface_id = None
+ self.vpc_peering_connection_id = None
self.state = None
def __repr__(self):
@@ -82,6 +84,10 @@ class Route(object):
self.gateway_id = value
elif name == 'instanceId':
self.instance_id = value
+ elif name == 'networkInterfaceId':
+ self.interface_id = value
+ elif name == 'vpcPeeringConnectionId':
+ self.vpc_peering_connection_id = value
elif name == 'state':
self.state = value
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 00f26417..914c5328 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -73,6 +73,8 @@ Currently Supported Services
* :doc:`Simple Queue Service (SQS) <sqs_tut>` -- (:doc:`API Reference <ref/sqs>`) (Python 3)
* Simple Notification Service (SNS) -- (:doc:`API Reference <ref/sns>`) (Python 3)
* :doc:`Simple Email Service (SES) <ses_tut>` -- (:doc:`API Reference <ref/ses>`) (Python 3)
+ * Amazon Cognito Identity -- (:doc:`API Reference <ref/cognito-identity`) (Python 3)
+ * Amazon Cognito Sync -- (:doc:`API Reference <ref/cognito-sync`) (Python 3)
* **Monitoring**
diff --git a/docs/source/ref/cognito-identity.rst b/docs/source/ref/cognito-identity.rst
new file mode 100644
index 00000000..65ec98ff
--- /dev/null
+++ b/docs/source/ref/cognito-identity.rst
@@ -0,0 +1,26 @@
+.. ref-cognito-identity
+
+================
+Cognito Identity
+================
+
+boto.cognito.identity
+---------------------
+
+.. automodule:: boto.cognito.identity
+ :members:
+ :undoc-members:
+
+boto.cognito.identity.layer1
+----------------------------
+
+.. automodule:: boto.cognito.identity.layer1
+ :members:
+ :undoc-members:
+
+boto.cognito.identity.exceptions
+--------------------------------
+
+.. automodule:: boto.cognito.identity.exceptions
+ :members:
+ :undoc-members:
diff --git a/docs/source/ref/cognito-sync.rst b/docs/source/ref/cognito-sync.rst
new file mode 100644
index 00000000..a8a6dd40
--- /dev/null
+++ b/docs/source/ref/cognito-sync.rst
@@ -0,0 +1,26 @@
+.. ref-cognito-sync
+
+============
+Cognito Sync
+============
+
+boto.cognito.sync
+-----------------
+
+.. automodule:: boto.cognito.sync
+ :members:
+ :undoc-members:
+
+boto.cognito.sync.layer1
+------------------------
+
+.. automodule:: boto.cognito.sync.layer1
+ :members:
+ :undoc-members:
+
+boto.cognito.sync.exceptions
+----------------------------
+
+.. automodule:: boto.cognito.sync.exceptions
+ :members:
+ :undoc-members:
diff --git a/docs/source/s3_tut.rst b/docs/source/s3_tut.rst
index e5de8af9..98cd235a 100644
--- a/docs/source/s3_tut.rst
+++ b/docs/source/s3_tut.rst
@@ -53,7 +53,7 @@ later, first let's just create a bucket. That can be accomplished like this::
raise S3CreateError(response.status, response.reason)
boto.exception.S3CreateError: S3Error[409]: Conflict
-Whoa. What happended there? Well, the thing you have to know about
+Whoa. What happened there? Well, the thing you have to know about
buckets is that they are kind of like domain names. It's one flat name
space that everyone who uses S3 shares. So, someone has already create
a bucket called "mybucket" in S3 and that means no one else can grab that
diff --git a/setup.py b/setup.py
index af7db329..b46e683e 100644
--- a/setup.py
+++ b/setup.py
@@ -77,7 +77,8 @@ setup(name = "boto",
"boto.dynamodb2", "boto.support", "boto.cloudtrail",
"boto.directconnect", "boto.kinesis", "boto.rds2",
"boto.cloudsearch2", "boto.logs", "boto.vendored",
- "boto.route53.domains"],
+ "boto.route53.domains", "boto.cognito",
+ "boto.cognito.identity", "boto.cognito.sync"],
package_data = {
"boto.cacerts": ["cacerts.txt"],
"boto": ["endpoints.json"],
diff --git a/tests/integration/cognito/__init__.py b/tests/integration/cognito/__init__.py
new file mode 100644
index 00000000..571bc50d
--- /dev/null
+++ b/tests/integration/cognito/__init__.py
@@ -0,0 +1,41 @@
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+
+import boto
+from tests.compat import unittest
+
+
+class CognitoTest(unittest.TestCase):
+ def setUp(self):
+ self.cognito_identity = boto.connect_cognito_identity()
+ self.cognito_sync = boto.connect_cognito_sync()
+ self.identity_pool_name = 'myIdentityPool'
+ response = self.cognito_identity.create_identity_pool(
+ identity_pool_name=self.identity_pool_name,
+ allow_unauthenticated_identities=False
+ )
+ self.identity_pool_id = response['IdentityPoolId']
+
+ def tearDown(self):
+ self.cognito_identity.delete_identity_pool(
+ identity_pool_id=self.identity_pool_id
+ )
diff --git a/tests/integration/cognito/identity/__init__.py b/tests/integration/cognito/identity/__init__.py
new file mode 100644
index 00000000..70cc23fe
--- /dev/null
+++ b/tests/integration/cognito/identity/__init__.py
@@ -0,0 +1,21 @@
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
diff --git a/tests/integration/cognito/identity/test_cognito_identity.py b/tests/integration/cognito/identity/test_cognito_identity.py
new file mode 100644
index 00000000..7d9f6647
--- /dev/null
+++ b/tests/integration/cognito/identity/test_cognito_identity.py
@@ -0,0 +1,52 @@
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+
+from boto.cognito.identity.exceptions import ResourceNotFoundException
+from tests.integration.cognito import CognitoTest
+
+
+class TestCognitoIdentity(CognitoTest):
+ """
+ Test Cognitoy identity pools operations since individual Cognito identities
+ require an AWS account ID.
+ """
+ def test_cognito_identity(self):
+ # Ensure the identity pool is in the list of pools.
+ response = self.cognito_identity.list_identity_pools(max_results=5)
+ expected_identity = {'IdentityPoolId': self.identity_pool_id,
+ 'IdentityPoolName': self.identity_pool_name}
+ self.assertIn(expected_identity, response['IdentityPools'])
+
+ # Ensure the pool's attributes are as expected.
+ response = self.cognito_identity.describe_identity_pool(
+ identity_pool_id=self.identity_pool_id
+ )
+ self.assertEqual(response['IdentityPoolName'], self.identity_pool_name)
+ self.assertEqual(response['IdentityPoolId'], self.identity_pool_id)
+ self.assertFalse(response['AllowUnauthenticatedIdentities'])
+
+ def test_resource_not_found_exception(self):
+ with self.assertRaises(ResourceNotFoundException):
+ # Note the region is us-east-0 which is an invalid region name.
+ self.cognito_identity.describe_identity_pool(
+ identity_pool_id='us-east-0:c09e640-b014-4822-86b9-ec77c40d8d6f'
+ )
diff --git a/tests/integration/cognito/sync/__init__.py b/tests/integration/cognito/sync/__init__.py
new file mode 100644
index 00000000..70cc23fe
--- /dev/null
+++ b/tests/integration/cognito/sync/__init__.py
@@ -0,0 +1,21 @@
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
diff --git a/tests/integration/cognito/sync/test_cognito_sync.py b/tests/integration/cognito/sync/test_cognito_sync.py
new file mode 100644
index 00000000..fdfd40ee
--- /dev/null
+++ b/tests/integration/cognito/sync/test_cognito_sync.py
@@ -0,0 +1,46 @@
+# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+
+from boto.cognito.sync.exceptions import ResourceNotFoundException
+from tests.integration.cognito import CognitoTest
+
+
+class TestCognitoSync(CognitoTest):
+ """
+ Even more so for Cognito Sync, Cognito identites are required. However,
+ AWS account IDs are required to aqcuire a Cognito identity so only
+ Cognito pool identity related operations are tested.
+ """
+ def test_cognito_sync(self):
+ response = self.cognito_sync.describe_identity_pool_usage(
+ identity_pool_id=self.identity_pool_id
+ )
+ identity_pool_usage = response['IdentityPoolUsage']
+ self.assertEqual(identity_pool_usage['SyncSessionsCount'], None)
+ self.assertEqual(identity_pool_usage['DataStorage'], 0)
+
+ def test_resource_not_found_exception(self):
+ with self.assertRaises(ResourceNotFoundException):
+ # Note the region is us-east-0 which is an invalid region name.
+ self.cognito_sync.describe_identity_pool_usage(
+ identity_pool_id='us-east-0:c09e640-b014-4822-86b9-ec77c40d8d6f'
+ )
diff --git a/tests/unit/ec2/autoscale/test_group.py b/tests/unit/ec2/autoscale/test_group.py
index 19e2c7ca..5c5b4dcd 100755..100644
--- a/tests/unit/ec2/autoscale/test_group.py
+++ b/tests/unit/ec2/autoscale/test_group.py
@@ -351,11 +351,9 @@ class TestLaunchConfiguration(AWSMockServiceTestCase):
# This unit test is based on #753 and #1343
self.set_http_response(status_code=200)
dev_sdf = EBSBlockDeviceType(snapshot_id='snap-12345')
- dev_sdg = EBSBlockDeviceType(snapshot_id='snap-12346')
bdm = BlockDeviceMapping()
bdm['/dev/sdf'] = dev_sdf
- bdm['/dev/sdg'] = dev_sdg
lc = launchconfig.LaunchConfiguration(
connection=self.service_connection,
@@ -363,7 +361,7 @@ class TestLaunchConfiguration(AWSMockServiceTestCase):
image_id='123456',
instance_type='m1.large',
user_data='#!/bin/bash',
- security_groups=['group1', 'group2'],
+ security_groups=['group1'],
spot_price='price',
block_device_mappings=[bdm],
associate_public_ip_address=True,
@@ -379,17 +377,13 @@ class TestLaunchConfiguration(AWSMockServiceTestCase):
'BlockDeviceMappings.member.1.DeviceName': '/dev/sdf',
'BlockDeviceMappings.member.1.Ebs.DeleteOnTermination': 'false',
'BlockDeviceMappings.member.1.Ebs.SnapshotId': 'snap-12345',
- 'BlockDeviceMappings.member.2.DeviceName': '/dev/sdg',
- 'BlockDeviceMappings.member.2.Ebs.DeleteOnTermination': 'false',
- 'BlockDeviceMappings.member.2.Ebs.SnapshotId': 'snap-12346',
'EbsOptimized': 'false',
'LaunchConfigurationName': 'launch_config',
'ImageId': '123456',
- 'UserData': base64.b64encode('#!/bin/bash').decode('utf-8'),
+ 'UserData': base64.b64encode(b'#!/bin/bash').decode('utf-8'),
'InstanceMonitoring.Enabled': 'false',
'InstanceType': 'm1.large',
'SecurityGroups.member.1': 'group1',
- 'SecurityGroups.member.2': 'group2',
'SpotPrice': 'price',
'AssociatePublicIpAddress': 'true',
'VolumeType': 'atype',
diff --git a/tests/unit/s3/test_connection.py b/tests/unit/s3/test_connection.py
index 35ebce97..5839a6a2 100644
--- a/tests/unit/s3/test_connection.py
+++ b/tests/unit/s3/test_connection.py
@@ -135,6 +135,26 @@ class TestSigV4Presigned(MockServiceWithConfigTestCase):
self.assertIn('VersionId=2', url)
self.assertIn('X-Amz-Security-Token=token', url)
+ def test_sigv4_presign_headers(self):
+ self.config = {
+ 's3': {
+ 'use-sigv4': True,
+ }
+ }
+
+ conn = self.connection_class(
+ aws_access_key_id='less',
+ aws_secret_access_key='more',
+ host='s3.amazonaws.com'
+ )
+
+ headers = {'x-amz-meta-key': 'val'}
+ url = conn.generate_url_sigv4(86400, 'GET', bucket='examplebucket',
+ key='test.txt', headers=headers)
+
+ self.assertIn('host', url)
+ self.assertIn('x-amz-meta-key', url)
+
class TestUnicodeCallingFormat(AWSMockServiceTestCase):
connection_class = S3Connection
diff --git a/tests/unit/sts/test_connection.py b/tests/unit/sts/test_connection.py
index 9bf70304..dd97c770 100644
--- a/tests/unit/sts/test_connection.py
+++ b/tests/unit/sts/test_connection.py
@@ -72,9 +72,7 @@ class TestSTSConnection(AWSMockServiceTestCase):
{'Action': 'AssumeRole',
'RoleArn': 'arn:role',
'RoleSessionName': 'mysession'},
- ignore_params_values=['Timestamp', 'AWSAccessKeyId',
- 'SignatureMethod', 'SignatureVersion',
- 'Version'])
+ ignore_params_values=['Version'])
self.assertEqual(response.credentials.access_key, 'accesskey')
self.assertEqual(response.credentials.secret_key, 'secretkey')
self.assertEqual(response.credentials.session_token, 'session_token')
@@ -95,9 +93,7 @@ class TestSTSConnection(AWSMockServiceTestCase):
'RoleSessionName': 'mysession',
'SerialNumber': 'GAHT12345678',
'TokenCode': 'abc123'},
- ignore_params_values=['Timestamp', 'AWSAccessKeyId',
- 'SignatureMethod', 'SignatureVersion',
- 'Version'])
+ ignore_params_values=['Version'])
self.assertEqual(response.credentials.access_key, 'accesskey')
self.assertEqual(response.credentials.secret_key, 'secretkey')
self.assertEqual(response.credentials.session_token, 'session_token')
@@ -160,16 +156,12 @@ class TestSTSWebIdentityConnection(AWSMockServiceTestCase):
)
self.assert_request_parameters({
'RoleSessionName': 'guestuser',
- 'AWSAccessKeyId': 'aws_access_key_id',
'RoleArn': arn,
'WebIdentityToken': wit,
'ProviderId': 'www.amazon.com',
'Action': 'AssumeRoleWithWebIdentity'
}, ignore_params_values=[
- 'SignatureMethod',
- 'Timestamp',
- 'SignatureVersion',
- 'Version',
+ 'Version'
])
self.assertEqual(
response.credentials.access_key.strip(),
@@ -239,11 +231,7 @@ class TestSTSSAMLConnection(AWSMockServiceTestCase):
'SAMLAssertion': assertion,
'Action': 'AssumeRoleWithSAML'
}, ignore_params_values=[
- 'AWSAccessKeyId',
- 'SignatureMethod',
- 'Timestamp',
- 'SignatureVersion',
- 'Version',
+ 'Version'
])
self.assertEqual(response.credentials.access_key, 'accesskey')
self.assertEqual(response.credentials.secret_key, 'secretkey')
diff --git a/tests/unit/vpc/test_routetable.py b/tests/unit/vpc/test_routetable.py
index 3518fd74..c90e56c4 100644
--- a/tests/unit/vpc/test_routetable.py
+++ b/tests/unit/vpc/test_routetable.py
@@ -48,6 +48,18 @@ class TestDescribeRouteTables(AWSMockServiceTestCase):
<gatewayId>igw-eaad4883</gatewayId>
<state>active</state>
</item>
+ <item>
+ <destinationCidrBlock>10.0.0.0/21</destinationCidrBlock>
+ <networkInterfaceId>eni-884ec1d1</networkInterfaceId>
+ <state>blackhole</state>
+ <origin>CreateRoute</origin>
+ </item>
+ <item>
+ <destinationCidrBlock>11.0.0.0/22</destinationCidrBlock>
+ <vpcPeeringConnectionId>pcx-efc52b86</vpcPeeringConnectionId>
+ <state>blackhole</state>
+ <origin>CreateRoute</origin>
+ </item>
</routeSet>
<associationSet>
<item>
@@ -88,13 +100,19 @@ class TestDescribeRouteTables(AWSMockServiceTestCase):
self.assertIsNone(api_response[0].associations[0].subnet_id)
self.assertEquals(api_response[0].associations[0].main, True)
self.assertEquals(api_response[1].id, 'rtb-f9ad4890')
- self.assertEquals(len(api_response[1].routes), 2)
+ self.assertEquals(len(api_response[1].routes), 4)
self.assertEquals(api_response[1].routes[0].destination_cidr_block, '10.0.0.0/22')
self.assertEquals(api_response[1].routes[0].gateway_id, 'local')
self.assertEquals(api_response[1].routes[0].state, 'active')
self.assertEquals(api_response[1].routes[1].destination_cidr_block, '0.0.0.0/0')
self.assertEquals(api_response[1].routes[1].gateway_id, 'igw-eaad4883')
self.assertEquals(api_response[1].routes[1].state, 'active')
+ self.assertEquals(api_response[1].routes[2].destination_cidr_block, '10.0.0.0/21')
+ self.assertEquals(api_response[1].routes[2].interface_id, 'eni-884ec1d1')
+ self.assertEquals(api_response[1].routes[2].state, 'blackhole')
+ self.assertEquals(api_response[1].routes[3].destination_cidr_block, '11.0.0.0/22')
+ self.assertEquals(api_response[1].routes[3].vpc_peering_connection_id, 'pcx-efc52b86')
+ self.assertEquals(api_response[1].routes[3].state, 'blackhole')
self.assertEquals(len(api_response[1].associations), 1)
self.assertEquals(api_response[1].associations[0].id, 'rtbassoc-faad4893')
self.assertEquals(api_response[1].associations[0].route_table_id, 'rtb-f9ad4890')