Permalink
Browse files

Merge branch 'develop' into dynamodb-decimal

Conflicts:
	docs/source/dynamodb_tut.rst
  • Loading branch information...
2 parents 7972dda + 9b09f54 commit d6f853afb57d1eaedd4538dd6e16310965e01117 @jamesls committed Jan 8, 2013
Showing with 3,698 additions and 397 deletions.
  1. +18 −0 LICENSE
  2. +15 −15 bin/glacier
  3. +12 −17 boto/auth.py
  4. +9 −3 boto/cloudformation/connection.py
  5. +23 −25 boto/cloudfront/distribution.py
  6. +0 −52 boto/contrib/m2helpers.py
  7. 0 boto/datapipeline/__init__.py
  8. +42 −0 boto/datapipeline/exceptions.py
  9. +546 −0 boto/datapipeline/layer1.py
  10. +1 −1 boto/dynamodb/layer1.py
  11. +34 −13 boto/dynamodb/layer2.py
  12. +38 −0 boto/dynamodb/schema.py
  13. +45 −4 boto/dynamodb/table.py
  14. +20 −2 boto/ec2/__init__.py
  15. +56 −4 boto/ec2/connection.py
  16. +13 −4 boto/ec2/instance.py
  17. +91 −7 boto/ec2/networkinterface.py
  18. +34 −18 boto/ec2/spotinstancerequest.py
  19. +15 −34 boto/exception.py
  20. +21 −6 boto/glacier/job.py
  21. +15 −6 boto/glacier/layer1.py
  22. +30 −0 boto/glacier/utils.py
  23. +5 −3 boto/gs/bucket.py
  24. +2 −2 boto/manage/cmdshell.py
  25. +12 −0 boto/provider.py
  26. +74 −14 boto/route53/connection.py
  27. +14 −1 boto/route53/record.py
  28. +42 −0 boto/route53/status.py
  29. +412 −0 boto/route53/zone.py
  30. +4 −3 boto/s3/bucket.py
  31. +4 −2 boto/s3/connection.py
  32. +16 −9 boto/s3/key.py
  33. +10 −4 boto/s3/multipart.py
  34. +22 −16 boto/sdb/db/test_db.py
  35. +6 −3 boto/sns/connection.py
  36. +6 −0 boto/sqs/queue.py
  37. +5 −5 boto/sts/connection.py
  38. +342 −0 boto/swf/layer2.py
  39. +3 −5 boto/utils.py
  40. +38 −0 boto/vpc/__init__.py
  41. +15 −0 docs/source/boto_config_tut.rst
  42. +77 −4 docs/source/dynamodb_tut.rst
  43. +1 −1 docs/source/elb_tut.rst
  44. +1 −0 docs/source/index.rst
  45. +26 −0 docs/source/ref/datapipeline.rst
  46. +23 −16 docs/source/ref/ec2.rst
  47. +1 −1 requirements.txt
  48. +122 −0 tests/integration/datapipeline/test_layer1.py
  49. +84 −0 tests/integration/dynamodb/test_table.py
  50. +3 −3 tests/integration/ec2/test_cert_verification.py
  51. 0 tests/integration/ec2/vpc/__init__.py
  52. +95 −0 tests/integration/ec2/vpc/test_connection.py
  53. 0 tests/integration/gs/__init__.py
  54. +4 −4 tests/integration/{s3/cb_test_harnass.py → gs/cb_test_harness.py}
  55. +1 −16 tests/integration/{s3/test_gsconnection.py → gs/test_connection.py}
  56. +28 −23 tests/integration/{s3 → gs}/test_resumable_downloads.py
  57. +36 −31 tests/integration/{s3 → gs}/test_resumable_uploads.py
  58. +198 −0 tests/integration/gs/test_versioning.py
  59. +15 −0 tests/integration/gs/util.py
  60. +132 −0 tests/integration/route53/test_zone.py
  61. +119 −0 tests/unit/dynamodb/test_layer2.py
  62. +26 −1 tests/unit/ec2/test_connection.py
  63. +153 −8 tests/unit/ec2/test_instance.py
  64. +140 −0 tests/unit/ec2/test_networkinterface.py
  65. +60 −0 tests/unit/glacier/test_job.py
  66. +22 −2 tests/unit/glacier/test_layer1.py
  67. +49 −9 tests/unit/glacier/test_utils.py
  68. +27 −0 tests/unit/provider/test_provider.py
  69. +6 −0 tests/unit/s3/test_key.py
  70. 0 tests/unit/sns/__init__.py
  71. +99 −0 tests/unit/sns/test_connection.py
  72. +40 −0 tests/unit/sqs/test_queue.py
View
18 LICENSE
@@ -0,0 +1,18 @@
+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.
View
@@ -51,15 +51,15 @@ glacier <command> [args]
created
Common args:
- access_key - Your AWS Access Key ID. If not supplied, boto will
- use the value of the environment variable
- AWS_ACCESS_KEY_ID
- secret_key - Your AWS Secret Access Key. If not supplied, boto
- will use the value of the environment variable
- AWS_SECRET_ACCESS_KEY
- region - AWS region to use. Possible vaules: us-east-1, us-west-1,
- us-west-2, ap-northeast-1, eu-west-1.
- Default: us-east-1
+ --access_key - Your AWS Access Key ID. If not supplied, boto will
+ use the value of the environment variable
+ AWS_ACCESS_KEY_ID
+ --secret_key - Your AWS Secret Access Key. If not supplied, boto
+ will use the value of the environment variable
+ AWS_SECRET_ACCESS_KEY
+ --region - AWS region to use. Possible values: us-east-1, us-west-1,
+ us-west-2, ap-northeast-1, eu-west-1.
+ Default: us-east-1
Vaults operations:
@@ -91,18 +91,18 @@ def connect(region, debug_level=0, access_key=None, secret_key=None):
def list_vaults(region, access_key=None, secret_key=None):
- layer2 = connect(region, access_key, secret_key)
+ layer2 = connect(region, access_key = access_key, secret_key = secret_key)
for vault in layer2.list_vaults():
print vault.arn
def list_jobs(vault_name, region, access_key=None, secret_key=None):
- layer2 = connect(region, access_key, secret_key)
+ layer2 = connect(region, access_key = access_key, secret_key = secret_key)
print layer2.layer1.list_jobs(vault_name)
def upload_files(vault_name, filenames, region, access_key=None, secret_key=None):
- layer2 = connect(region, access_key, secret_key)
+ layer2 = connect(region, access_key = access_key, secret_key = secret_key)
layer2.create_vault(vault_name)
glacier_vault = layer2.get_vault(vault_name)
for filename in filenames:
@@ -131,11 +131,11 @@ def main():
access_key = secret_key = None
region = 'us-east-1'
for option, value in opts:
- if option in ('a', '--access_key'):
+ if option in ('-a', '--access_key'):
access_key = value
- elif option in ('s', '--secret_key'):
+ elif option in ('-s', '--secret_key'):
secret_key = value
- elif option in ('r', '--region'):
+ elif option in ('-r', '--region'):
region = value
# handle each command
if command == 'vaults':
View
@@ -647,8 +647,7 @@ def get_auth_handler(host, config, provider, requested_capability=None):
An implementation of AuthHandler.
Raises:
- boto.exception.NoAuthHandlerFound:
- boto.exception.TooManyAuthHandlerReadyToAuthenticate:
+ boto.exception.NoAuthHandlerFound
"""
ready_handlers = []
auth_handlers = boto.plugin.get_plugin(AuthHandler, requested_capability)
@@ -667,18 +666,14 @@ def get_auth_handler(host, config, provider, requested_capability=None):
' %s '
'Check your credentials' % (len(names), str(names)))
- if len(ready_handlers) > 1:
- # NOTE: Even though it would be nice to accept more than one handler
- # by using one of the many ready handlers, we are never sure that each
- # of them are referring to the same storage account. Since we cannot
- # easily guarantee that, it is always safe to fail, rather than operate
- # on the wrong account.
- names = [handler.__class__.__name__ for handler in ready_handlers]
- raise boto.exception.TooManyAuthHandlerReadyToAuthenticate(
- '%d AuthHandlers %s ready to authenticate for requested_capability '
- '%s, only 1 expected. This happens if you import multiple '
- 'pluging.Plugin implementations that declare support for the '
- 'requested_capability.' % (len(names), str(names),
- requested_capability))
-
- return ready_handlers[0]
+ # We select the last ready auth handler that was loaded, to allow users to
+ # customize how auth works in environments where there are shared boto
+ # config files (e.g., /etc/boto.cfg and ~/.boto): The more general,
+ # system-wide shared configs should be loaded first, and the user's
+ # customizations loaded last. That way, for example, the system-wide
+ # config might include a plugin_directory that includes a service account
+ # auth plugin shared by all users of a Google Compute Engine instance
+ # (allowing sharing of non-user data between various services), and the
+ # user could override this with a .boto config that includes user-specific
+ # credentials (for access to user data).
+ return ready_handlers[-1]
@@ -38,9 +38,15 @@ class CloudFormationConnection(AWSQueryConnection):
DefaultRegionEndpoint = boto.config.get('Boto', 'cfn_region_endpoint',
'cloudformation.us-east-1.amazonaws.com')
- valid_states = ("CREATE_IN_PROGRESS", "CREATE_FAILED", "CREATE_COMPLETE",
- "ROLLBACK_IN_PROGRESS", "ROLLBACK_FAILED", "ROLLBACK_COMPLETE",
- "DELETE_IN_PROGRESS", "DELETE_FAILED", "DELETE_COMPLETE")
+ valid_states = (
+ 'CREATE_IN_PROGRESS', 'CREATE_FAILED', 'CREATE_COMPLETE',
+ 'ROLLBACK_IN_PROGRESS', 'ROLLBACK_FAILED', 'ROLLBACK_COMPLETE',
+ 'DELETE_IN_PROGRESS', 'DELETE_FAILED', 'DELETE_COMPLETE',
+ 'UPDATE_IN_PROGRESS', 'UPDATE_COMPLETE_CLEANUP_IN_PROGRESS',
+ 'UPDATE_COMPLETE', 'UPDATE_ROLLBACK_IN_PROGRESS',
+ 'UPDATE_ROLLBACK_FAILED',
+ 'UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS',
+ 'UPDATE_ROLLBACK_COMPLETE')
def __init__(self, aws_access_key_id=None, aws_secret_access_key=None,
is_secure=True, port=None, proxy=None, proxy_port=None,
@@ -49,23 +49,23 @@ def __init__(self, connection=None, origin=None, enabled=False,
:param enabled: Whether the distribution is enabled to accept
end user requests for content.
:type enabled: bool
-
+
:param caller_reference: A unique number that ensures the
request can't be replayed. If no
caller_reference is provided, boto
will generate a type 4 UUID for use
as the caller reference.
:type enabled: str
-
+
:param cnames: A CNAME alias you want to associate with this
distribution. You can have up to 10 CNAME aliases
per distribution.
:type enabled: array of str
-
+
:param comment: Any comments you want to include about the
distribution.
:type comment: str
-
+
:param trusted_signers: Specifies any AWS accounts you want to
permit to create signed URLs for private
content. If you want the distribution to
@@ -74,7 +74,7 @@ def __init__(self, connection=None, origin=None, enabled=False,
distribution to use basic URLs, leave
this None.
:type trusted_signers: :class`boto.cloudfront.signers.TrustedSigners`
-
+
:param default_root_object: Designates a default root object.
Only include a DefaultRootObject value
if you are going to assign a default
@@ -86,7 +86,7 @@ def __init__(self, connection=None, origin=None, enabled=False,
this should contain a LoggingInfo object; otherwise
it should contain None.
:type logging: :class`boto.cloudfront.logging.LoggingInfo`
-
+
"""
self.connection = connection
self.origin = origin
@@ -278,7 +278,7 @@ class StreamingDistributionSummary(DistributionSummary):
def get_distribution(self):
return self.connection.get_streaming_distribution_info(self.id)
-
+
class Distribution:
def __init__(self, connection=None, config=None, domain_name='',
@@ -400,11 +400,11 @@ def _get_bucket(self):
return self._bucket
else:
raise NotImplementedError('Unable to get_objects on CustomOrigin')
-
+
def get_objects(self):
"""
Return a list of all content objects in this distribution.
-
+
:rtype: list of :class:`boto.cloudfront.object.Object`
:return: The content objects
"""
@@ -640,32 +640,30 @@ def _custom_policy(resource, expires=None, valid_after=None, ip_address=None):
@staticmethod
def _sign_string(message, private_key_file=None, private_key_string=None):
"""
- Signs a string for use with Amazon CloudFront. Requires the M2Crypto
- library be installed.
+ Signs a string for use with Amazon CloudFront.
+ Requires the rsa library be installed.
"""
try:
- from M2Crypto import EVP
+ import rsa
except ImportError:
- raise NotImplementedError("Boto depends on the python M2Crypto "
+ raise NotImplementedError("Boto depends on the python rsa "
"library to generate signed URLs for "
"CloudFront")
# Make sure only one of private_key_file and private_key_string is set
if private_key_file and private_key_string:
raise ValueError("Only specify the private_key_file or the private_key_string not both")
if not private_key_file and not private_key_string:
raise ValueError("You must specify one of private_key_file or private_key_string")
- # if private_key_file is a file object read the key string from there
+ # If private_key_file is a file, read its contents. Otherwise, open it and then read it
if isinstance(private_key_file, file):
private_key_string = private_key_file.read()
- # Now load key and calculate signature
- if private_key_string:
- key = EVP.load_key_string(private_key_string)
- else:
- key = EVP.load_key(private_key_file)
- key.reset_context(md='sha1')
- key.sign_init()
- key.sign_update(str(message))
- signature = key.sign_final()
+ elif private_key_file:
+ with open(private_key_file, 'r') as file_handle:
+ private_key_string = file_handle.read()
+
+ # Sign it!
+ private_key = rsa.PrivateKey.load_pkcs1(private_key_string)
+ signature = rsa.sign(str(message), private_key, 'SHA-1')
return signature
@staticmethod
@@ -743,5 +741,5 @@ def update(self, enabled=None, cnames=None, comment=None):
def delete(self):
self.connection.delete_streaming_distribution(self.id, self.etag)
-
-
+
+
View
@@ -1,52 +0,0 @@
-# Copyright (c) 2006,2007 Jon Colverson
-#
-# 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.
-
-"""
-This module was contributed by Jon Colverson. It provides a couple of helper
-functions that allow you to use M2Crypto's implementation of HTTPSConnection
-rather than the default version in httplib.py. The main benefit is that
-M2Crypto's version verifies the certificate of the server.
-
-To use this feature, do something like this:
-
-from boto.ec2.connection import EC2Connection
-
-ec2 = EC2Connection(ACCESS_KEY_ID, SECRET_ACCESS_KEY,
- https_connection_factory=https_connection_factory(cafile=CA_FILE))
-
-See http://code.google.com/p/boto/issues/detail?id=57 for more details.
-"""
-from M2Crypto import SSL
-from M2Crypto.httpslib import HTTPSConnection
-
-def secure_context(cafile=None, capath=None):
- ctx = SSL.Context()
- ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, depth=9)
- if ctx.load_verify_locations(cafile=cafile, capath=capath) != 1:
- raise Exception("Couldn't load certificates")
- return ctx
-
-def https_connection_factory(cafile=None, capath=None):
- def factory(*args, **kwargs):
- return HTTPSConnection(
- ssl_context=secure_context(cafile=cafile, capath=capath),
- *args, **kwargs)
- return (factory, (SSL.SSLError,))
No changes.
@@ -0,0 +1,42 @@
+# Copyright (c) 2012 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 JSONResponseError
+
+
+class PipelineDeletedException(JSONResponseError):
+ pass
+
+
+class InvalidRequestException(JSONResponseError):
+ pass
+
+
+class TaskNotFoundException(JSONResponseError):
+ pass
+
+
+class PipelineNotFoundException(JSONResponseError):
+ pass
+
+
+class InternalServiceError(JSONResponseError):
+ pass
Oops, something went wrong.

0 comments on commit d6f853a

Please sign in to comment.