Permalink
Browse files

Merge branch 'release-2.14.0'

  • Loading branch information...
danielgtaylor committed Oct 9, 2013
2 parents 3c56d13 + a008516 commit 5005178d88ef8e4bbe8c30949ffab46e46a716b0
Showing with 12,671 additions and 2,460 deletions.
  1. +2 −0 .gitignore
  2. +7 −10 README.rst
  3. +1 −1 bin/dynamodb_load
  4. +2 −3 bin/elbadmin
  5. +1 −1 bin/instance_events
  6. +1 −1 bin/list_instances
  7. +75 −23 bin/s3put
  8. +7 −2 boto/__init__.py
  9. +52 −6 boto/auth.py
  10. +2,814 −563 boto/cacerts/cacerts.txt
  11. +8 −5 boto/cloudformation/stack.py
  12. +14 −12 boto/cloudfront/distribution.py
  13. +1 −1 boto/cloudsearch/__init__.py
  14. +17 −9 boto/cloudsearch/layer1.py
  15. +12 −4 boto/cloudsearch/layer2.py
  16. +13 −2 boto/cloudsearch/search.py
  17. +91 −31 boto/connection.py
  18. +3 −0 boto/dynamodb/__init__.py
  19. +6 −0 boto/dynamodb2/__init__.py
  20. +138 −64 boto/dynamodb2/items.py
  21. +13 −4 boto/dynamodb2/layer1.py
  22. +13 −9 boto/dynamodb2/results.py
  23. +52 −14 boto/dynamodb2/table.py
  24. +6 −0 boto/ec2/__init__.py
  25. +25 −8 boto/ec2/address.py
  26. +40 −8 boto/ec2/autoscale/__init__.py
  27. +6 −0 boto/ec2/autoscale/group.py
  28. +7 −0 boto/ec2/autoscale/policy.py
  29. +3 −3 boto/ec2/autoscale/tag.py
  30. +10 −2 boto/ec2/blockdevicemapping.py
  31. +1 −0 boto/ec2/cloudwatch/__init__.py
  32. +2 −2 boto/ec2/cloudwatch/alarm.py
  33. +899 −127 boto/ec2/connection.py
  34. +14 −6 boto/ec2/ec2object.py
  35. +33 −2 boto/ec2/elb/__init__.py
  36. +39 −2 boto/ec2/elb/loadbalancer.py
  37. +21 −1 boto/ec2/elb/policies.py
  38. +58 −24 boto/ec2/image.py
  39. +60 −44 boto/ec2/instance.py
  40. +9 −9 boto/ec2/keypair.py
  41. +46 −6 boto/ec2/networkinterface.py
  42. +7 −4 boto/ec2/placementgroup.py
  43. +124 −2 boto/ec2/reservedinstance.py
  44. +64 −29 boto/ec2/securitygroup.py
  45. +39 −22 boto/ec2/snapshot.py
  46. +6 −4 boto/ec2/spotdatafeedsubscription.py
  47. +5 −2 boto/ec2/spotinstancerequest.py
  48. +36 −16 boto/ec2/volume.py
  49. +3 −0 boto/elasticache/__init__.py
  50. +777 −368 boto/elasticache/layer1.py
  51. +7 −7 boto/emr/__init__.py
  52. +1 −1 boto/emr/connection.py
  53. +2 −2 boto/emr/instance_group.py
  54. +12 −6 boto/exception.py
  55. +10 −2 boto/glacier/layer2.py
  56. +21 −3 boto/gs/bucket.py
  57. +11 −2 boto/gs/key.py
  58. +3 −0 boto/iam/__init__.py
  59. +4 −1 boto/iam/connection.py
  60. +3 −3 boto/manage/server.py
  61. +1 −1 boto/mashups/server.py
  62. +4 −0 boto/mws/response.py
  63. +818 −200 boto/opsworks/layer1.py
  64. +4 −0 boto/provider.py
  65. +1 −1 boto/pyami/installers/ubuntu/ebs.py
  66. +157 −21 boto/rds/__init__.py
  67. +16 −1 boto/rds/dbinstance.py
  68. +69 −0 boto/rds/dbsubnetgroup.py
  69. +85 −0 boto/rds/vpcsecuritygroupmembership.py
  70. +8 −0 boto/redshift/exceptions.py
  71. +154 −41 boto/redshift/layer1.py
  72. +3 −0 boto/route53/record.py
  73. +3 −0 boto/s3/__init__.py
  74. +35 −19 boto/s3/key.py
  75. +1 −1 boto/s3/keyfile.py
  76. +4 −0 boto/s3/multipart.py
  77. +2 −2 boto/sdb/db/manager/__init__.py
  78. +11 −7 boto/sdb/db/manager/sdbmanager.py
  79. +14 −11 boto/sdb/db/model.py
  80. +2 −1 boto/ses/connection.py
  81. +3 −0 boto/sns/__init__.py
  82. +416 −128 boto/sns/connection.py
  83. +2 −0 boto/sqs/__init__.py
  84. +3 −0 boto/sqs/message.py
  85. +4 −0 boto/sts/__init__.py
  86. +6 −2 boto/sts/connection.py
  87. +3 −0 boto/sts/credentials.py
  88. +1 −0 boto/swf/__init__.py
  89. +22 −22 boto/swf/layer1.py
  90. +20 −20 boto/swf/layer2.py
  91. +282 −47 boto/vpc/__init__.py
  92. +5 −2 boto/vpc/vpc.py
  93. +5 −2 boto/vpc/vpnconnection.py
  94. +10 −6 boto/vpc/vpngateway.py
  95. +7 −1 docs/Makefile
  96. +44 −0 docs/source/apps_built_on_boto.rst
  97. +1 −2 docs/source/autoscale_tut.rst
  98. +85 −0 docs/source/commandline.rst
  99. +23 −0 docs/source/contributing.rst
  100. +2 −6 docs/source/dynamodb2_tut.rst
  101. +1 −1 docs/source/ec2_tut.rst
  102. +18 −32 docs/source/index.rst
  103. +7 −0 docs/source/ref/cloudwatch.rst
  104. +2 −15 docs/source/ref/contrib.rst
  105. +20 −6 docs/source/ref/elb.rst
  106. +28 −0 docs/source/ref/opsworks.rst
  107. +0 −7 docs/source/ref/s3.rst
  108. +9 −22 docs/source/ref/sdb_db.rst
  109. +4 −1 docs/source/ref/swf.rst
  110. +21 −0 docs/source/releasenotes/dev.rst
  111. +21 −0 docs/source/releasenotes/releasenotes_template.rst
  112. +1 −1 docs/source/releasenotes/v2.0.0.rst
  113. +54 −0 docs/source/releasenotes/v2.10.0.rst
  114. +62 −0 docs/source/releasenotes/v2.11.0.rst
  115. +32 −0 docs/source/releasenotes/v2.12.0.rst
  116. +40 −0 docs/source/releasenotes/v2.13.0.rst
  117. +39 −0 docs/source/releasenotes/v2.13.2.rst
  118. +11 −0 docs/source/releasenotes/v2.13.3.rst
  119. +63 −0 docs/source/releasenotes/v2.14.0.rst
  120. +1 −1 docs/source/releasenotes/v2.9.8.rst
  121. +50 −0 docs/source/releasenotes/v2.9.9.rst
  122. +1 −1 docs/source/s3_tut.rst
  123. +1 −1 docs/source/sqs_tut.rst
  124. +67 −0 tests/integration/__init__.py
  125. +7 −8 tests/integration/cloudformation/test_cert_verification.py
  126. +8 −9 tests/integration/cloudsearch/test_cert_verification.py
  127. +75 −0 tests/integration/cloudsearch/test_layers.py
  128. +7 −8 tests/integration/dynamodb/test_cert_verification.py
  129. +7 −8 tests/integration/dynamodb2/test_cert_verification.py
  130. +73 −4 tests/integration/dynamodb2/test_highlevel.py
  131. +7 −8 tests/integration/ec2/autoscale/test_cert_verification.py
  132. +7 −8 tests/integration/ec2/cloudwatch/test_cert_verification.py
  133. +7 −8 tests/integration/ec2/elb/test_cert_verification.py
  134. +22 −0 tests/integration/ec2/elb/test_connection.py
  135. +7 −8 tests/integration/ec2/test_cert_verification.py
  136. +50 −1 tests/integration/ec2/test_connection.py
  137. +47 −2 tests/integration/ec2/vpc/test_connection.py
  138. +7 −8 tests/integration/elastictranscoder/test_cert_verification.py
  139. +7 −8 tests/integration/emr/test_cert_verification.py
  140. +7 −8 tests/integration/glacier/test_cert_verification.py
  141. +7 −2 tests/integration/gs/cb_test_harness.py
  142. +62 −33 tests/integration/gs/test_resumable_uploads.py
  143. +2 −2 tests/integration/gs/testcase.py
  144. +2 −1 tests/integration/gs/util.py
  145. +7 −8 tests/integration/iam/test_cert_verification.py
  146. +10 −0 tests/integration/mws/test.py
  147. +7 −8 tests/integration/rds/test_cert_verification.py
  148. +92 −0 tests/integration/rds/test_db_subnet_group.py
  149. +7 −8 tests/integration/redshift/test_cert_verification.py
  150. +7 −8 tests/integration/route53/test_cert_verification.py
  151. +47 −1 tests/integration/route53/test_resourcerecordsets.py
  152. +7 −8 tests/integration/s3/test_cert_verification.py
  153. +11 −0 tests/integration/s3/test_key.py
  154. +20 −0 tests/integration/s3/test_multipart.py
  155. +7 −8 tests/integration/sdb/test_cert_verification.py
  156. +7 −8 tests/integration/ses/test_cert_verification.py
  157. +2 −0 tests/integration/ses/test_connection.py
  158. +7 −8 tests/integration/sns/test_cert_verification.py
  159. +68 −0 tests/integration/sns/test_connection.py
  160. +3 −3 tests/integration/sns/test_sns_sqs_subscription.py
  161. +7 −8 tests/integration/sqs/test_cert_verification.py
  162. +42 −0 tests/integration/sqs/test_connection.py
  163. +7 −8 tests/integration/sts/test_cert_verification.py
  164. +6 −4 tests/integration/sts/test_session_token.py
  165. +7 −8 tests/integration/support/test_cert_verification.py
  166. +7 −8 tests/integration/swf/test_cert_verification.py
  167. +76 −0 tests/unit/auth/test_query.py
  168. +81 −0 tests/unit/auth/test_sigv4.py
  169. +5 −5 tests/unit/cloudformation/test_connection.py
  170. +38 −4 tests/unit/cloudformation/test_stack.py
  171. +21 −0 tests/unit/cloudfront/test_distribution.py
  172. +17 −0 tests/unit/cloudfront/test_signed_urls.py
  173. +3 −12 tests/unit/cloudsearch/test_connection.py
  174. +37 −0 tests/unit/cloudsearch/test_exceptions.py
  175. +35 −3 tests/unit/cloudsearch/test_search.py
  176. +8 −0 tests/unit/dynamodb2/test_layer1.py
  177. +207 −2 tests/unit/dynamodb2/test_table.py
  178. +256 −0 tests/unit/ec2/autoscale/test_group.py
  179. +97 −0 tests/unit/ec2/elb/test_loadbalancer.py
  180. +13 −3 tests/unit/ec2/test_address.py
  181. +54 −0 tests/unit/ec2/test_blockdevicemapping.py
  182. +657 −0 tests/unit/ec2/test_connection.py
  183. +1 −1 tests/unit/ec2/test_instance.py
  184. +104 −44 tests/unit/ec2/test_networkinterface.py
  185. +212 −0 tests/unit/ec2/test_securitygroup.py
  186. +28 −9 tests/unit/ec2/test_volume.py
  187. +57 −0 tests/unit/emr/test_instance_group_args.py
  188. +49 −3 tests/unit/glacier/test_layer2.py
  189. +328 −0 tests/unit/rds/test_connection.py
  190. +7 −14 tests/unit/s3/test_key.py
  191. 0 tests/unit/ses/__init__.py
  192. +82 −0 tests/unit/ses/test_identity.py
  193. +135 −0 tests/unit/sns/test_connection.py
  194. +35 −0 tests/unit/sqs/test_message.py
  195. 0 tests/unit/sts/__init__.py
  196. +88 −0 tests/unit/sts/test_connection.py
  197. +38 −0 tests/unit/sts/test_credentials.py
  198. 0 tests/unit/swf/__init__.py
  199. +87 −0 tests/unit/swf/test_layer2_actors.py
  200. +112 −0 tests/unit/swf/test_layer2_domain.py
  201. +46 −0 tests/unit/swf/test_layer2_types.py
  202. +100 −1 tests/unit/test_connection.py
  203. +45 −3 tests/unit/test_exception.py
  204. +3 −0 tests/unit/vpc/__init__.py
  205. +60 −3 tests/unit/vpc/test_vpc.py
View
@@ -12,3 +12,5 @@ MANIFEST
.coverage
*flymake.py
venv
+venv-2.5
+env-2.5
View
@@ -1,13 +1,13 @@
####
boto
####
-boto 2.9.8
+boto 2.13.3
-Released: 18-July-2013
+Released: 16-September-2013
.. image:: https://travis-ci.org/boto/boto.png?branch=develop
:target: https://travis-ci.org/boto/boto
-
+
.. image:: https://pypip.in/d/boto/badge.png
:target: https://crate.io/packages/boto/
@@ -41,6 +41,7 @@ At the moment, boto supports:
* AWS Elastic Beanstalk
* AWS CloudFormation
* AWS Data Pipeline
+ * AWS Opsworks
* Identity & Access
@@ -49,6 +50,7 @@ At the moment, boto supports:
* Application Services
* Amazon CloudSearch
+ * Amazon Elastic Transcoder
* Amazon Simple Workflow Service (SWF)
* Amazon Simple Queue Service (SQS)
* Amazon Simple Notification Server (SNS)
@@ -89,9 +91,9 @@ Web Services. In addition, boto provides support for other public
services such as Google Storage in addition to private cloud systems
like Eucalyptus, OpenStack and Open Nebula.
-Boto is developed mainly using Python 2.6.6 and Python 2.7.1 on Mac OSX
+Boto is developed mainly using Python 2.6.6 and Python 2.7.3 on Mac OSX
and Ubuntu Maverick. It is known to work on other Linux distributions
-and on Windows. Boto requires no additional libraries or packages
+and on Windows. Most of Boto requires no additional libraries or packages
other than those that are distributed with Python. Efforts are made
to keep boto compatible with Python 2.5.x but no guarantees are made.
@@ -153,11 +155,6 @@ following environment variables to ascertain your credentials:
Credentials and other boto-related settings can also be stored in a
boto config file. See `this`_ for details.
-Copyright (c) 2006-2012 Mitch Garnaat <mitch@garnaat.com>
-Copyright (c) 2010-2011, Eucalyptus Systems, Inc.
-Copyright (c) 2012 Amazon.com, Inc. or its affiliates.
-All rights reserved.
-
.. _pip: http://www.pip-installer.org/
.. _release notes: https://github.com/boto/boto/wiki
.. _github.com: http://github.com/boto/boto
View
@@ -66,7 +66,7 @@ def load_table(table, in_fd):
data[k] = set(v)
else:
data[k] = v
- table.new_item(attrs=i).put()
+ table.new_item(attrs=data).put()
def dynamodb_load(tables, in_dir, create_tables):
View
@@ -118,9 +118,8 @@ def get(elb, name):
instances = [state.instance_id for state in instance_health]
names = {}
- for r in ec2.get_all_instances(instances):
- for i in r.instances:
- names[i.id] = i.tags.get('Name', '')
+ for i in ec2.get_only_instances(instances):
+ names[i.id] = i.tags.get('Name', '')
name_column_width = max([4] + [len(v) for k,v in names.iteritems()]) + 2
View
@@ -51,7 +51,7 @@ def list(region, headers, order, completed):
ec2 = boto.connect_ec2(region=region)
- reservations = ec2.get_all_instances()
+ reservations = ec2.get_all_reservations()
instanceinfo = {}
events = {}
View
@@ -76,7 +76,7 @@ def main():
print format_string % headers
print "-" * len(format_string % headers)
- for r in ec2.get_all_instances(filters=filters):
+ for r in ec2.get_all_reservations(filters=filters):
groups = [g.name for g in r.groups]
for i in r.instances:
i.groups = ','.join(groups)
View
@@ -37,7 +37,9 @@ try:
multipart_capable = True
usage_flag_multipart_capable = """ [--multipart]"""
usage_string_multipart_capable = """
- multipart - Upload files as multiple parts. This needs filechunkio."""
+ multipart - Upload files as multiple parts. This needs filechunkio.
+ Requires ListBucket, ListMultipartUploadParts,
+ ListBucketMultipartUploads and PutObject permissions."""
except ImportError as err:
multipart_capable = False
usage_flag_multipart_capable = ""
@@ -46,14 +48,17 @@ except ImportError as err:
'" is missing for multipart support '
+DEFAULT_REGION = 'us-east-1'
+
usage_string = """
SYNOPSIS
s3put [-a/--access_key <access_key>] [-s/--secret_key <secret_key>]
-b/--bucket <bucket_name> [-c/--callback <num_cb>]
[-d/--debug <debug_level>] [-i/--ignore <ignore_dirs>]
[-n/--no_op] [-p/--prefix <prefix>] [-k/--key_prefix <key_prefix>]
[-q/--quiet] [-g/--grant grant] [-w/--no_overwrite] [-r/--reduced]
- [--header] [--host <s3_host>]""" + usage_flag_multipart_capable + """ path [path...]
+ [--header] [--region <name>] [--host <s3_host>]""" + \
+ usage_flag_multipart_capable + """ path [path...]
Where
access_key - Your AWS Access Key ID. If not supplied, boto will
@@ -103,6 +108,9 @@ SYNOPSIS
updated.
header - key=value pairs of extra header(s) to pass along in the
request
+ region - Manually set a region for buckets that are not in the US
+ classic region. Normally the region is autodetected, but
+ setting this yourself is more efficient.
host - Hostname override, for using an endpoint other then AWS S3
""" + usage_string_multipart_capable + """
@@ -112,9 +120,9 @@ SYNOPSIS
"""
-def usage():
+def usage(status=1):
print usage_string
- sys.exit()
+ sys.exit(status)
def submit_cb(bytes_so_far, total_bytes):
@@ -168,11 +176,13 @@ def _upload_part(bucketname, aws_key, aws_secret, multipart_id, part_num,
def multipart_upload(bucketname, aws_key, aws_secret, source_path, keyname,
reduced, debug, cb, num_cb, acl='private', headers={},
- guess_mimetype=True, parallel_processes=4):
+ guess_mimetype=True, parallel_processes=4,
+ region=DEFAULT_REGION):
"""
Parallel multipart upload.
"""
- conn = S3Connection(aws_key, aws_secret)
+ conn = boto.s3.connect_to_region(region, aws_access_key_id=aws_key,
+ aws_secret_access_key=aws_secret)
conn.debug = debug
bucket = conn.get_bucket(bucketname)
@@ -242,21 +252,22 @@ def main():
headers = {}
host = None
multipart_requested = False
+ region = None
try:
opts, args = getopt.getopt(
sys.argv[1:], 'a:b:c::d:g:hi:k:np:qs:wr',
['access_key=', 'bucket=', 'callback=', 'debug=', 'help', 'grant=',
'ignore=', 'key_prefix=', 'no_op', 'prefix=', 'quiet',
'secret_key=', 'no_overwrite', 'reduced', 'header=', 'multipart',
- 'host='])
+ 'host=', 'region='])
except:
- usage()
+ usage(1)
# parse opts
for o, a in opts:
if o in ('-h', '--help'):
- usage()
+ usage(0)
if o in ('-a', '--access_key'):
aws_access_key_id = a
if o in ('-b', '--bucket'):
@@ -288,7 +299,7 @@ def main():
if o in ('-r', '--reduced'):
reduced = True
if o in ('--header'):
- (k, v) = a.split("=")
+ (k, v) = a.split("=", 1)
headers[k] = v
if o in ('--host'):
host = a
@@ -297,23 +308,62 @@ def main():
multipart_requested = True
else:
print "multipart upload requested but not capable"
- sys.exit()
+ sys.exit(4)
+ if o in ('--region'):
+ regions = boto.s3.regions()
+ for region_info in regions:
+ if region_info.name == a:
+ region = a
+ break
+ else:
+ raise ValueError('Invalid region %s specified' % a)
if len(args) < 1:
- usage()
+ usage(2)
if not bucket_name:
print "bucket name is required!"
- usage()
+ usage(3)
+
+ connect_args = {
+ 'aws_access_key_id': aws_access_key_id,
+ 'aws_secret_access_key': aws_secret_access_key
+ }
if host:
- c = boto.connect_s3(host=host, aws_access_key_id=aws_access_key_id,
- aws_secret_access_key=aws_secret_access_key)
- else:
- c = boto.connect_s3(aws_access_key_id=aws_access_key_id,
- aws_secret_access_key=aws_secret_access_key)
+ connect_args['host'] = host
+
+ c = boto.s3.connect_to_region(region or DEFAULT_REGION, **connect_args)
c.debug = debug
- b = c.get_bucket(bucket_name)
+ b = c.get_bucket(bucket_name, validate=False)
+
+ # Attempt to determine location and warn if no --host or --region
+ # arguments were passed. Then try to automagically figure out
+ # what should have been passed and fix it.
+ if host is None and region is None:
+ try:
+ location = b.get_location()
+
+ # Classic region will be '', any other will have a name
+ if location:
+ print 'Bucket exists in %s but no host or region given!' % location
+
+ # Override for EU, which is really Ireland according to the docs
+ if location == 'EU':
+ location = 'eu-west-1'
+
+ print 'Automatically setting region to %s' % location
+
+ # Here we create a new connection, and then take the existing
+ # bucket and set it to use the new connection
+ c = boto.s3.connect_to_region(location, **connect_args)
+ c.debug = debug
+ b.connection = c
+ except Exception, e:
+ if debug > 0:
+ print e
+ print 'Could not get bucket region info, skipping...'
+
existing_keys_to_check_against = []
files_to_check_for_upload = []
@@ -350,9 +400,10 @@ def main():
key_name = get_key_name(fullpath, prefix, key_prefix)
if no_overwrite and key_name in existing_keys_to_check_against:
- if not quiet:
- print 'Skipping %s as it exists in s3' % fullpath
- continue
+ if b.get_key(key_name):
+ if not quiet:
+ print 'Skipping %s as it exists in s3' % fullpath
+ continue
if not quiet:
print 'Copying %s to %s/%s' % (fullpath, bucket_name, key_name)
@@ -364,7 +415,8 @@ def main():
multipart_upload(bucket_name, aws_access_key_id,
aws_secret_access_key, fullpath, key_name,
reduced, debug, cb, num_cb,
- grant or 'private', headers)
+ grant or 'private', headers,
+ region=region or DEFAULT_REGION)
else:
singlepart_upload(b, key_name, fullpath, cb=cb, num_cb=num_cb,
policy=grant, reduced_redundancy=reduced,
View
@@ -36,10 +36,15 @@
import urlparse
from boto.exception import InvalidUriError
-__version__ = '2.9.8'
+__version__ = '2.14.0'
Version = __version__ # for backware compatibility
-UserAgent = 'Boto/%s (%s)' % (__version__, sys.platform)
+UserAgent = 'Boto/%s Python/%s %s/%s' % (
+ __version__,
+ platform.python_version(),
+ platform.system(),
+ platform.release()
+)
config = Config()
# Regex to disallow buckets violating charset or not [3..255] chars total.
View
@@ -385,8 +385,9 @@ def signed_headers(self, headers_to_sign):
def canonical_uri(self, http_request):
path = http_request.auth_path
- # Normalize the path.
- normalized = posixpath.normpath(path)
+ # Normalize the path
+ # in windows normpath('/') will be '\\' so we chane it back to '/'
+ normalized = posixpath.normpath(path).replace('\\','/')
# Then urlencode whatever's left.
encoded = urllib.quote(normalized)
if len(path) > 1 and path.endswith('/'):
@@ -430,11 +431,17 @@ def credential_scope(self, http_request):
parts = http_request.host.split('.')
if self.region_name is not None:
region_name = self.region_name
- else:
- if len(parts) == 3:
- region_name = 'us-east-1'
+ elif len(parts) > 1:
+ if parts[1] == 'us-gov':
+ region_name = 'us-gov-west-1'
else:
- region_name = parts[1]
+ if len(parts) == 3:
+ region_name = 'us-east-1'
+ else:
+ region_name = parts[1]
+ else:
+ region_name = parts[0]
+
if self.service_name is not None:
service_name = self.service_name
else:
@@ -509,6 +516,45 @@ def add_auth(self, req, **kwargs):
req.headers['Authorization'] = ','.join(l)
+class QueryAuthHandler(AuthHandler):
+ """
+ Provides pure query construction (no actual signing).
+
+ Mostly useful for STS' ``assume_role_with_web_identity``.
+
+ Does **NOT** escape query string values!
+ """
+
+ capability = ['pure-query']
+
+ def _escape_value(self, value):
+ # Would normally be ``return urllib.quote(value)``.
+ return value
+
+ def _build_query_string(self, params):
+ keys = params.keys()
+ keys.sort(cmp=lambda x, y: cmp(x.lower(), y.lower()))
+ pairs = []
+ for key in keys:
+ val = boto.utils.get_utf8_value(params[key])
+ pairs.append(key + '=' + self._escape_value(val))
+ return '&'.join(pairs)
+
+ def add_auth(self, http_request, **kwargs):
+ headers = http_request.headers
+ params = http_request.params
+ qs = self._build_query_string(
+ http_request.params
+ )
+ boto.log.debug('query_string: %s' % qs)
+ headers['Content-Type'] = 'application/json; charset=UTF-8'
+ http_request.body = ''
+ # if this is a retried request, the qs from the previous try will
+ # already be there, we need to get rid of that and rebuild it
+ http_request.path = http_request.path.split('?')[0]
+ http_request.path = http_request.path + '?' + qs
+
+
class QuerySignatureHelper(HmacKeys):
"""
Helper for Query signature based Auth handler.
Oops, something went wrong.

0 comments on commit 5005178

Please sign in to comment.