gcloud 0.0.4 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (768) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +4 -0
  3. data/Makefile +4 -0
  4. data/Manifest +760 -1
  5. data/bin/gcloud +7 -0
  6. data/bin/{gcutil → gcutil.symlink} +0 -0
  7. data/bin/gsutil-symlink +377 -0
  8. data/gcloud.gemspec +5 -5
  9. data/packages/gsutil/CHECKSUM +1 -0
  10. data/packages/gsutil/COPYING +202 -0
  11. data/packages/gsutil/LICENSE.third_party +295 -0
  12. data/packages/gsutil/MANIFEST.in +5 -0
  13. data/packages/gsutil/README +38 -0
  14. data/packages/gsutil/README.pkg +49 -0
  15. data/packages/gsutil/ReleaseNotes.txt +780 -0
  16. data/packages/gsutil/VERSION +1 -0
  17. data/packages/gsutil/boto/Changelog.rst +35 -0
  18. data/packages/gsutil/boto/LICENSE +18 -0
  19. data/packages/gsutil/boto/MANIFEST.in +12 -0
  20. data/packages/gsutil/boto/README.rst +163 -0
  21. data/packages/gsutil/boto/bin/asadmin +290 -0
  22. data/packages/gsutil/boto/bin/bundle_image +27 -0
  23. data/packages/gsutil/boto/bin/cfadmin +108 -0
  24. data/packages/gsutil/boto/bin/cq +89 -0
  25. data/packages/gsutil/boto/bin/cwutil +140 -0
  26. data/packages/gsutil/boto/bin/elbadmin +284 -0
  27. data/packages/gsutil/boto/bin/fetch_file +43 -0
  28. data/packages/gsutil/boto/bin/glacier +154 -0
  29. data/packages/gsutil/boto/bin/instance_events +145 -0
  30. data/packages/gsutil/boto/bin/kill_instance +35 -0
  31. data/packages/gsutil/boto/bin/launch_instance +252 -0
  32. data/packages/gsutil/boto/bin/list_instances +90 -0
  33. data/packages/gsutil/boto/bin/lss3 +77 -0
  34. data/packages/gsutil/boto/bin/mturk +465 -0
  35. data/packages/gsutil/boto/bin/pyami_sendmail +52 -0
  36. data/packages/gsutil/boto/bin/route53 +205 -0
  37. data/packages/gsutil/boto/bin/s3put +374 -0
  38. data/packages/gsutil/boto/bin/sdbadmin +194 -0
  39. data/packages/gsutil/boto/bin/taskadmin +116 -0
  40. data/packages/gsutil/boto/boto/__init__.py +793 -0
  41. data/packages/gsutil/boto/boto/__init__.pyc +0 -0
  42. data/packages/gsutil/boto/boto/auth.py +682 -0
  43. data/packages/gsutil/boto/boto/auth.pyc +0 -0
  44. data/packages/gsutil/boto/boto/auth_handler.py +58 -0
  45. data/packages/gsutil/boto/boto/auth_handler.pyc +0 -0
  46. data/packages/gsutil/boto/boto/beanstalk/__init__.py +65 -0
  47. data/packages/gsutil/boto/boto/beanstalk/exception.py +64 -0
  48. data/packages/gsutil/boto/boto/beanstalk/layer1.py +1153 -0
  49. data/packages/gsutil/boto/boto/beanstalk/response.py +703 -0
  50. data/packages/gsutil/boto/boto/beanstalk/wrapper.py +29 -0
  51. data/packages/gsutil/boto/boto/cacerts/__init__.py +22 -0
  52. data/packages/gsutil/boto/boto/cacerts/__init__.pyc +0 -0
  53. data/packages/gsutil/boto/boto/cacerts/cacerts.txt +633 -0
  54. data/packages/gsutil/boto/boto/cloudformation/__init__.py +68 -0
  55. data/packages/gsutil/boto/boto/cloudformation/connection.py +364 -0
  56. data/packages/gsutil/boto/boto/cloudformation/stack.py +360 -0
  57. data/packages/gsutil/boto/boto/cloudformation/template.py +43 -0
  58. data/packages/gsutil/boto/boto/cloudfront/__init__.py +324 -0
  59. data/packages/gsutil/boto/boto/cloudfront/distribution.py +745 -0
  60. data/packages/gsutil/boto/boto/cloudfront/exception.py +26 -0
  61. data/packages/gsutil/boto/boto/cloudfront/identity.py +122 -0
  62. data/packages/gsutil/boto/boto/cloudfront/invalidation.py +216 -0
  63. data/packages/gsutil/boto/boto/cloudfront/logging.py +38 -0
  64. data/packages/gsutil/boto/boto/cloudfront/object.py +48 -0
  65. data/packages/gsutil/boto/boto/cloudfront/origin.py +150 -0
  66. data/packages/gsutil/boto/boto/cloudfront/signers.py +60 -0
  67. data/packages/gsutil/boto/boto/cloudsearch/__init__.py +45 -0
  68. data/packages/gsutil/boto/boto/cloudsearch/document.py +265 -0
  69. data/packages/gsutil/boto/boto/cloudsearch/domain.py +394 -0
  70. data/packages/gsutil/boto/boto/cloudsearch/layer1.py +738 -0
  71. data/packages/gsutil/boto/boto/cloudsearch/layer2.py +67 -0
  72. data/packages/gsutil/boto/boto/cloudsearch/optionstatus.py +248 -0
  73. data/packages/gsutil/boto/boto/cloudsearch/search.py +365 -0
  74. data/packages/gsutil/boto/boto/cloudsearch/sourceattribute.py +75 -0
  75. data/packages/gsutil/boto/boto/compat.py +28 -0
  76. data/packages/gsutil/boto/boto/compat.pyc +0 -0
  77. data/packages/gsutil/boto/boto/connection.py +1081 -0
  78. data/packages/gsutil/boto/boto/connection.pyc +0 -0
  79. data/packages/gsutil/boto/boto/contrib/__init__.py +22 -0
  80. data/packages/gsutil/boto/boto/contrib/ymlmessage.py +52 -0
  81. data/packages/gsutil/boto/boto/core/README +58 -0
  82. data/packages/gsutil/boto/boto/core/__init__.py +23 -0
  83. data/packages/gsutil/boto/boto/core/auth.py +78 -0
  84. data/packages/gsutil/boto/boto/core/credentials.py +154 -0
  85. data/packages/gsutil/boto/boto/core/dictresponse.py +178 -0
  86. data/packages/gsutil/boto/boto/core/service.py +67 -0
  87. data/packages/gsutil/boto/boto/datapipeline/__init__.py +0 -0
  88. data/packages/gsutil/boto/boto/datapipeline/exceptions.py +42 -0
  89. data/packages/gsutil/boto/boto/datapipeline/layer1.py +546 -0
  90. data/packages/gsutil/boto/boto/dynamodb/__init__.py +66 -0
  91. data/packages/gsutil/boto/boto/dynamodb/batch.py +262 -0
  92. data/packages/gsutil/boto/boto/dynamodb/condition.py +170 -0
  93. data/packages/gsutil/boto/boto/dynamodb/exceptions.py +64 -0
  94. data/packages/gsutil/boto/boto/dynamodb/item.py +196 -0
  95. data/packages/gsutil/boto/boto/dynamodb/layer1.py +575 -0
  96. data/packages/gsutil/boto/boto/dynamodb/layer2.py +798 -0
  97. data/packages/gsutil/boto/boto/dynamodb/schema.py +112 -0
  98. data/packages/gsutil/boto/boto/dynamodb/table.py +540 -0
  99. data/packages/gsutil/boto/boto/dynamodb/types.py +326 -0
  100. data/packages/gsutil/boto/boto/ec2/__init__.py +96 -0
  101. data/packages/gsutil/boto/boto/ec2/address.py +103 -0
  102. data/packages/gsutil/boto/boto/ec2/autoscale/__init__.py +781 -0
  103. data/packages/gsutil/boto/boto/ec2/autoscale/activity.py +74 -0
  104. data/packages/gsutil/boto/boto/ec2/autoscale/group.py +337 -0
  105. data/packages/gsutil/boto/boto/ec2/autoscale/instance.py +60 -0
  106. data/packages/gsutil/boto/boto/ec2/autoscale/launchconfig.py +209 -0
  107. data/packages/gsutil/boto/boto/ec2/autoscale/policy.py +166 -0
  108. data/packages/gsutil/boto/boto/ec2/autoscale/request.py +38 -0
  109. data/packages/gsutil/boto/boto/ec2/autoscale/scheduled.py +60 -0
  110. data/packages/gsutil/boto/boto/ec2/autoscale/tag.py +84 -0
  111. data/packages/gsutil/boto/boto/ec2/blockdevicemapping.py +141 -0
  112. data/packages/gsutil/boto/boto/ec2/bundleinstance.py +78 -0
  113. data/packages/gsutil/boto/boto/ec2/buyreservation.py +84 -0
  114. data/packages/gsutil/boto/boto/ec2/cloudwatch/__init__.py +603 -0
  115. data/packages/gsutil/boto/boto/ec2/cloudwatch/alarm.py +316 -0
  116. data/packages/gsutil/boto/boto/ec2/cloudwatch/datapoint.py +40 -0
  117. data/packages/gsutil/boto/boto/ec2/cloudwatch/dimension.py +38 -0
  118. data/packages/gsutil/boto/boto/ec2/cloudwatch/listelement.py +31 -0
  119. data/packages/gsutil/boto/boto/ec2/cloudwatch/metric.py +175 -0
  120. data/packages/gsutil/boto/boto/ec2/connection.py +3409 -0
  121. data/packages/gsutil/boto/boto/ec2/ec2object.py +107 -0
  122. data/packages/gsutil/boto/boto/ec2/elb/__init__.py +553 -0
  123. data/packages/gsutil/boto/boto/ec2/elb/healthcheck.py +89 -0
  124. data/packages/gsutil/boto/boto/ec2/elb/instancestate.py +62 -0
  125. data/packages/gsutil/boto/boto/ec2/elb/listelement.py +36 -0
  126. data/packages/gsutil/boto/boto/ec2/elb/listener.py +75 -0
  127. data/packages/gsutil/boto/boto/ec2/elb/loadbalancer.py +324 -0
  128. data/packages/gsutil/boto/boto/ec2/elb/policies.py +89 -0
  129. data/packages/gsutil/boto/boto/ec2/elb/securitygroup.py +38 -0
  130. data/packages/gsutil/boto/boto/ec2/group.py +39 -0
  131. data/packages/gsutil/boto/boto/ec2/image.py +350 -0
  132. data/packages/gsutil/boto/boto/ec2/instance.py +661 -0
  133. data/packages/gsutil/boto/boto/ec2/instanceinfo.py +51 -0
  134. data/packages/gsutil/boto/boto/ec2/instancestatus.py +207 -0
  135. data/packages/gsutil/boto/boto/ec2/keypair.py +113 -0
  136. data/packages/gsutil/boto/boto/ec2/launchspecification.py +105 -0
  137. data/packages/gsutil/boto/boto/ec2/networkinterface.py +247 -0
  138. data/packages/gsutil/boto/boto/ec2/placementgroup.py +51 -0
  139. data/packages/gsutil/boto/boto/ec2/regioninfo.py +34 -0
  140. data/packages/gsutil/boto/boto/ec2/reservedinstance.py +227 -0
  141. data/packages/gsutil/boto/boto/ec2/securitygroup.py +357 -0
  142. data/packages/gsutil/boto/boto/ec2/snapshot.py +170 -0
  143. data/packages/gsutil/boto/boto/ec2/spotdatafeedsubscription.py +63 -0
  144. data/packages/gsutil/boto/boto/ec2/spotinstancerequest.py +188 -0
  145. data/packages/gsutil/boto/boto/ec2/spotpricehistory.py +55 -0
  146. data/packages/gsutil/boto/boto/ec2/tag.py +87 -0
  147. data/packages/gsutil/boto/boto/ec2/vmtype.py +58 -0
  148. data/packages/gsutil/boto/boto/ec2/volume.py +293 -0
  149. data/packages/gsutil/boto/boto/ec2/volumestatus.py +200 -0
  150. data/packages/gsutil/boto/boto/ec2/zone.py +80 -0
  151. data/packages/gsutil/boto/boto/ecs/__init__.py +90 -0
  152. data/packages/gsutil/boto/boto/ecs/item.py +153 -0
  153. data/packages/gsutil/boto/boto/elasticache/__init__.py +62 -0
  154. data/packages/gsutil/boto/boto/elasticache/layer1.py +1252 -0
  155. data/packages/gsutil/boto/boto/elastictranscoder/__init__.py +62 -0
  156. data/packages/gsutil/boto/boto/elastictranscoder/exceptions.py +46 -0
  157. data/packages/gsutil/boto/boto/elastictranscoder/layer1.py +509 -0
  158. data/packages/gsutil/boto/boto/emr/__init__.py +73 -0
  159. data/packages/gsutil/boto/boto/emr/bootstrap_action.py +44 -0
  160. data/packages/gsutil/boto/boto/emr/connection.py +531 -0
  161. data/packages/gsutil/boto/boto/emr/emrobject.py +176 -0
  162. data/packages/gsutil/boto/boto/emr/instance_group.py +43 -0
  163. data/packages/gsutil/boto/boto/emr/step.py +281 -0
  164. data/packages/gsutil/boto/boto/exception.py +476 -0
  165. data/packages/gsutil/boto/boto/exception.pyc +0 -0
  166. data/packages/gsutil/boto/boto/file/README +49 -0
  167. data/packages/gsutil/boto/boto/file/__init__.py +28 -0
  168. data/packages/gsutil/boto/boto/file/bucket.py +112 -0
  169. data/packages/gsutil/boto/boto/file/connection.py +33 -0
  170. data/packages/gsutil/boto/boto/file/key.py +199 -0
  171. data/packages/gsutil/boto/boto/file/simpleresultset.py +30 -0
  172. data/packages/gsutil/boto/boto/fps/__init__.py +21 -0
  173. data/packages/gsutil/boto/boto/fps/connection.py +369 -0
  174. data/packages/gsutil/boto/boto/fps/exception.py +344 -0
  175. data/packages/gsutil/boto/boto/fps/response.py +175 -0
  176. data/packages/gsutil/boto/boto/glacier/__init__.py +57 -0
  177. data/packages/gsutil/boto/boto/glacier/concurrent.py +409 -0
  178. data/packages/gsutil/boto/boto/glacier/exceptions.py +58 -0
  179. data/packages/gsutil/boto/boto/glacier/job.py +152 -0
  180. data/packages/gsutil/boto/boto/glacier/layer1.py +637 -0
  181. data/packages/gsutil/boto/boto/glacier/layer2.py +93 -0
  182. data/packages/gsutil/boto/boto/glacier/response.py +48 -0
  183. data/packages/gsutil/boto/boto/glacier/utils.py +163 -0
  184. data/packages/gsutil/boto/boto/glacier/vault.py +387 -0
  185. data/packages/gsutil/boto/boto/glacier/writer.py +242 -0
  186. data/packages/gsutil/boto/boto/gs/__init__.py +22 -0
  187. data/packages/gsutil/boto/boto/gs/__init__.pyc +0 -0
  188. data/packages/gsutil/boto/boto/gs/acl.py +304 -0
  189. data/packages/gsutil/boto/boto/gs/acl.pyc +0 -0
  190. data/packages/gsutil/boto/boto/gs/bucket.py +870 -0
  191. data/packages/gsutil/boto/boto/gs/bucket.pyc +0 -0
  192. data/packages/gsutil/boto/boto/gs/bucketlistresultset.py +64 -0
  193. data/packages/gsutil/boto/boto/gs/bucketlistresultset.pyc +0 -0
  194. data/packages/gsutil/boto/boto/gs/connection.py +103 -0
  195. data/packages/gsutil/boto/boto/gs/connection.pyc +0 -0
  196. data/packages/gsutil/boto/boto/gs/cors.py +169 -0
  197. data/packages/gsutil/boto/boto/gs/cors.pyc +0 -0
  198. data/packages/gsutil/boto/boto/gs/key.py +704 -0
  199. data/packages/gsutil/boto/boto/gs/key.pyc +0 -0
  200. data/packages/gsutil/boto/boto/gs/resumable_upload_handler.py +659 -0
  201. data/packages/gsutil/boto/boto/gs/resumable_upload_handler.pyc +0 -0
  202. data/packages/gsutil/boto/boto/gs/user.py +54 -0
  203. data/packages/gsutil/boto/boto/gs/user.pyc +0 -0
  204. data/packages/gsutil/boto/boto/handler.py +44 -0
  205. data/packages/gsutil/boto/boto/handler.pyc +0 -0
  206. data/packages/gsutil/boto/boto/https_connection.py +124 -0
  207. data/packages/gsutil/boto/boto/https_connection.pyc +0 -0
  208. data/packages/gsutil/boto/boto/iam/__init__.py +74 -0
  209. data/packages/gsutil/boto/boto/iam/connection.py +1317 -0
  210. data/packages/gsutil/boto/boto/iam/summarymap.py +42 -0
  211. data/packages/gsutil/boto/boto/jsonresponse.py +163 -0
  212. data/packages/gsutil/boto/boto/jsonresponse.pyc +0 -0
  213. data/packages/gsutil/boto/boto/manage/__init__.py +23 -0
  214. data/packages/gsutil/boto/boto/manage/cmdshell.py +241 -0
  215. data/packages/gsutil/boto/boto/manage/propget.py +64 -0
  216. data/packages/gsutil/boto/boto/manage/server.py +556 -0
  217. data/packages/gsutil/boto/boto/manage/task.py +175 -0
  218. data/packages/gsutil/boto/boto/manage/test_manage.py +34 -0
  219. data/packages/gsutil/boto/boto/manage/volume.py +420 -0
  220. data/packages/gsutil/boto/boto/mashups/__init__.py +23 -0
  221. data/packages/gsutil/boto/boto/mashups/interactive.py +97 -0
  222. data/packages/gsutil/boto/boto/mashups/iobject.py +115 -0
  223. data/packages/gsutil/boto/boto/mashups/order.py +211 -0
  224. data/packages/gsutil/boto/boto/mashups/server.py +395 -0
  225. data/packages/gsutil/boto/boto/mturk/__init__.py +23 -0
  226. data/packages/gsutil/boto/boto/mturk/connection.py +1027 -0
  227. data/packages/gsutil/boto/boto/mturk/layoutparam.py +55 -0
  228. data/packages/gsutil/boto/boto/mturk/notification.py +103 -0
  229. data/packages/gsutil/boto/boto/mturk/price.py +48 -0
  230. data/packages/gsutil/boto/boto/mturk/qualification.py +137 -0
  231. data/packages/gsutil/boto/boto/mturk/question.py +455 -0
  232. data/packages/gsutil/boto/boto/mws/__init__.py +21 -0
  233. data/packages/gsutil/boto/boto/mws/connection.py +813 -0
  234. data/packages/gsutil/boto/boto/mws/exception.py +75 -0
  235. data/packages/gsutil/boto/boto/mws/response.py +655 -0
  236. data/packages/gsutil/boto/boto/plugin.py +90 -0
  237. data/packages/gsutil/boto/boto/plugin.pyc +0 -0
  238. data/packages/gsutil/boto/boto/provider.py +337 -0
  239. data/packages/gsutil/boto/boto/provider.pyc +0 -0
  240. data/packages/gsutil/boto/boto/pyami/__init__.py +22 -0
  241. data/packages/gsutil/boto/boto/pyami/__init__.pyc +0 -0
  242. data/packages/gsutil/boto/boto/pyami/bootstrap.py +134 -0
  243. data/packages/gsutil/boto/boto/pyami/config.py +229 -0
  244. data/packages/gsutil/boto/boto/pyami/config.pyc +0 -0
  245. data/packages/gsutil/boto/boto/pyami/copybot.cfg +60 -0
  246. data/packages/gsutil/boto/boto/pyami/copybot.py +97 -0
  247. data/packages/gsutil/boto/boto/pyami/helloworld.py +28 -0
  248. data/packages/gsutil/boto/boto/pyami/installers/__init__.py +64 -0
  249. data/packages/gsutil/boto/boto/pyami/installers/ubuntu/__init__.py +22 -0
  250. data/packages/gsutil/boto/boto/pyami/installers/ubuntu/apache.py +43 -0
  251. data/packages/gsutil/boto/boto/pyami/installers/ubuntu/ebs.py +238 -0
  252. data/packages/gsutil/boto/boto/pyami/installers/ubuntu/installer.py +96 -0
  253. data/packages/gsutil/boto/boto/pyami/installers/ubuntu/mysql.py +109 -0
  254. data/packages/gsutil/boto/boto/pyami/installers/ubuntu/trac.py +139 -0
  255. data/packages/gsutil/boto/boto/pyami/launch_ami.py +178 -0
  256. data/packages/gsutil/boto/boto/pyami/scriptbase.py +44 -0
  257. data/packages/gsutil/boto/boto/pyami/startup.py +60 -0
  258. data/packages/gsutil/boto/boto/rds/__init__.py +1194 -0
  259. data/packages/gsutil/boto/boto/rds/dbinstance.py +357 -0
  260. data/packages/gsutil/boto/boto/rds/dbsecuritygroup.py +177 -0
  261. data/packages/gsutil/boto/boto/rds/dbsnapshot.py +108 -0
  262. data/packages/gsutil/boto/boto/rds/event.py +49 -0
  263. data/packages/gsutil/boto/boto/rds/parametergroup.py +201 -0
  264. data/packages/gsutil/boto/boto/rds/regioninfo.py +32 -0
  265. data/packages/gsutil/boto/boto/regioninfo.py +63 -0
  266. data/packages/gsutil/boto/boto/regioninfo.pyc +0 -0
  267. data/packages/gsutil/boto/boto/resultset.py +169 -0
  268. data/packages/gsutil/boto/boto/resultset.pyc +0 -0
  269. data/packages/gsutil/boto/boto/roboto/__init__.py +1 -0
  270. data/packages/gsutil/boto/boto/roboto/awsqueryrequest.py +504 -0
  271. data/packages/gsutil/boto/boto/roboto/awsqueryservice.py +121 -0
  272. data/packages/gsutil/boto/boto/roboto/param.py +147 -0
  273. data/packages/gsutil/boto/boto/route53/__init__.py +75 -0
  274. data/packages/gsutil/boto/boto/route53/connection.py +403 -0
  275. data/packages/gsutil/boto/boto/route53/exception.py +27 -0
  276. data/packages/gsutil/boto/boto/route53/hostedzone.py +56 -0
  277. data/packages/gsutil/boto/boto/route53/record.py +306 -0
  278. data/packages/gsutil/boto/boto/route53/status.py +42 -0
  279. data/packages/gsutil/boto/boto/route53/zone.py +412 -0
  280. data/packages/gsutil/boto/boto/s3/__init__.py +84 -0
  281. data/packages/gsutil/boto/boto/s3/__init__.pyc +0 -0
  282. data/packages/gsutil/boto/boto/s3/acl.py +164 -0
  283. data/packages/gsutil/boto/boto/s3/acl.pyc +0 -0
  284. data/packages/gsutil/boto/boto/s3/bucket.py +1634 -0
  285. data/packages/gsutil/boto/boto/s3/bucket.pyc +0 -0
  286. data/packages/gsutil/boto/boto/s3/bucketlistresultset.py +139 -0
  287. data/packages/gsutil/boto/boto/s3/bucketlistresultset.pyc +0 -0
  288. data/packages/gsutil/boto/boto/s3/bucketlogging.py +83 -0
  289. data/packages/gsutil/boto/boto/s3/bucketlogging.pyc +0 -0
  290. data/packages/gsutil/boto/boto/s3/connection.py +540 -0
  291. data/packages/gsutil/boto/boto/s3/connection.pyc +0 -0
  292. data/packages/gsutil/boto/boto/s3/cors.py +210 -0
  293. data/packages/gsutil/boto/boto/s3/cors.pyc +0 -0
  294. data/packages/gsutil/boto/boto/s3/deletemarker.py +55 -0
  295. data/packages/gsutil/boto/boto/s3/deletemarker.pyc +0 -0
  296. data/packages/gsutil/boto/boto/s3/key.py +1712 -0
  297. data/packages/gsutil/boto/boto/s3/key.pyc +0 -0
  298. data/packages/gsutil/boto/boto/s3/keyfile.py +134 -0
  299. data/packages/gsutil/boto/boto/s3/keyfile.pyc +0 -0
  300. data/packages/gsutil/boto/boto/s3/lifecycle.py +231 -0
  301. data/packages/gsutil/boto/boto/s3/lifecycle.pyc +0 -0
  302. data/packages/gsutil/boto/boto/s3/multidelete.py +138 -0
  303. data/packages/gsutil/boto/boto/s3/multidelete.pyc +0 -0
  304. data/packages/gsutil/boto/boto/s3/multipart.py +315 -0
  305. data/packages/gsutil/boto/boto/s3/multipart.pyc +0 -0
  306. data/packages/gsutil/boto/boto/s3/prefix.py +42 -0
  307. data/packages/gsutil/boto/boto/s3/prefix.pyc +0 -0
  308. data/packages/gsutil/boto/boto/s3/resumable_download_handler.py +339 -0
  309. data/packages/gsutil/boto/boto/s3/resumable_download_handler.pyc +0 -0
  310. data/packages/gsutil/boto/boto/s3/tagging.py +71 -0
  311. data/packages/gsutil/boto/boto/s3/tagging.pyc +0 -0
  312. data/packages/gsutil/boto/boto/s3/user.py +49 -0
  313. data/packages/gsutil/boto/boto/s3/user.pyc +0 -0
  314. data/packages/gsutil/boto/boto/s3/website.py +237 -0
  315. data/packages/gsutil/boto/boto/s3/website.pyc +0 -0
  316. data/packages/gsutil/boto/boto/sdb/__init__.py +67 -0
  317. data/packages/gsutil/boto/boto/sdb/connection.py +617 -0
  318. data/packages/gsutil/boto/boto/sdb/db/__init__.py +20 -0
  319. data/packages/gsutil/boto/boto/sdb/db/blob.py +75 -0
  320. data/packages/gsutil/boto/boto/sdb/db/key.py +59 -0
  321. data/packages/gsutil/boto/boto/sdb/db/manager/__init__.py +85 -0
  322. data/packages/gsutil/boto/boto/sdb/db/manager/sdbmanager.py +732 -0
  323. data/packages/gsutil/boto/boto/sdb/db/manager/xmlmanager.py +517 -0
  324. data/packages/gsutil/boto/boto/sdb/db/model.py +294 -0
  325. data/packages/gsutil/boto/boto/sdb/db/property.py +703 -0
  326. data/packages/gsutil/boto/boto/sdb/db/query.py +85 -0
  327. data/packages/gsutil/boto/boto/sdb/db/sequence.py +226 -0
  328. data/packages/gsutil/boto/boto/sdb/db/test_db.py +231 -0
  329. data/packages/gsutil/boto/boto/sdb/domain.py +377 -0
  330. data/packages/gsutil/boto/boto/sdb/item.py +181 -0
  331. data/packages/gsutil/boto/boto/sdb/queryresultset.py +92 -0
  332. data/packages/gsutil/boto/boto/sdb/regioninfo.py +32 -0
  333. data/packages/gsutil/boto/boto/services/__init__.py +23 -0
  334. data/packages/gsutil/boto/boto/services/bs.py +179 -0
  335. data/packages/gsutil/boto/boto/services/message.py +58 -0
  336. data/packages/gsutil/boto/boto/services/result.py +136 -0
  337. data/packages/gsutil/boto/boto/services/service.py +161 -0
  338. data/packages/gsutil/boto/boto/services/servicedef.py +91 -0
  339. data/packages/gsutil/boto/boto/services/sonofmmm.cfg +43 -0
  340. data/packages/gsutil/boto/boto/services/sonofmmm.py +81 -0
  341. data/packages/gsutil/boto/boto/services/submit.py +88 -0
  342. data/packages/gsutil/boto/boto/ses/__init__.py +54 -0
  343. data/packages/gsutil/boto/boto/ses/connection.py +521 -0
  344. data/packages/gsutil/boto/boto/ses/exceptions.py +77 -0
  345. data/packages/gsutil/boto/boto/sns/__init__.py +78 -0
  346. data/packages/gsutil/boto/boto/sns/connection.py +431 -0
  347. data/packages/gsutil/boto/boto/sqs/__init__.py +56 -0
  348. data/packages/gsutil/boto/boto/sqs/attributes.py +46 -0
  349. data/packages/gsutil/boto/boto/sqs/batchresults.py +95 -0
  350. data/packages/gsutil/boto/boto/sqs/connection.py +417 -0
  351. data/packages/gsutil/boto/boto/sqs/jsonmessage.py +43 -0
  352. data/packages/gsutil/boto/boto/sqs/message.py +253 -0
  353. data/packages/gsutil/boto/boto/sqs/queue.py +478 -0
  354. data/packages/gsutil/boto/boto/sqs/regioninfo.py +32 -0
  355. data/packages/gsutil/boto/boto/storage_uri.py +835 -0
  356. data/packages/gsutil/boto/boto/storage_uri.pyc +0 -0
  357. data/packages/gsutil/boto/boto/sts/__init__.py +55 -0
  358. data/packages/gsutil/boto/boto/sts/connection.py +207 -0
  359. data/packages/gsutil/boto/boto/sts/credentials.py +215 -0
  360. data/packages/gsutil/boto/boto/swf/__init__.py +60 -0
  361. data/packages/gsutil/boto/boto/swf/exceptions.py +44 -0
  362. data/packages/gsutil/boto/boto/swf/layer1.py +1512 -0
  363. data/packages/gsutil/boto/boto/swf/layer1_decisions.py +287 -0
  364. data/packages/gsutil/boto/boto/swf/layer2.py +342 -0
  365. data/packages/gsutil/boto/boto/utils.py +927 -0
  366. data/packages/gsutil/boto/boto/utils.pyc +0 -0
  367. data/packages/gsutil/boto/boto/vpc/__init__.py +910 -0
  368. data/packages/gsutil/boto/boto/vpc/customergateway.py +54 -0
  369. data/packages/gsutil/boto/boto/vpc/dhcpoptions.py +72 -0
  370. data/packages/gsutil/boto/boto/vpc/internetgateway.py +72 -0
  371. data/packages/gsutil/boto/boto/vpc/routetable.py +109 -0
  372. data/packages/gsutil/boto/boto/vpc/subnet.py +57 -0
  373. data/packages/gsutil/boto/boto/vpc/vpc.py +54 -0
  374. data/packages/gsutil/boto/boto/vpc/vpnconnection.py +60 -0
  375. data/packages/gsutil/boto/boto/vpc/vpngateway.py +83 -0
  376. data/packages/gsutil/boto/docs/BotoCheatSheet.pdf +0 -0
  377. data/packages/gsutil/boto/docs/Makefile +89 -0
  378. data/packages/gsutil/boto/docs/make.bat +113 -0
  379. data/packages/gsutil/boto/docs/source/_templates/layout.html +3 -0
  380. data/packages/gsutil/boto/docs/source/autoscale_tut.rst +220 -0
  381. data/packages/gsutil/boto/docs/source/boto_config_tut.rst +125 -0
  382. data/packages/gsutil/boto/docs/source/boto_theme/static/boto.css_t +239 -0
  383. data/packages/gsutil/boto/docs/source/boto_theme/static/pygments.css +61 -0
  384. data/packages/gsutil/boto/docs/source/boto_theme/theme.conf +3 -0
  385. data/packages/gsutil/boto/docs/source/cloudfront_tut.rst +196 -0
  386. data/packages/gsutil/boto/docs/source/cloudsearch_tut.rst +411 -0
  387. data/packages/gsutil/boto/docs/source/cloudwatch_tut.rst +116 -0
  388. data/packages/gsutil/boto/docs/source/conf.py +32 -0
  389. data/packages/gsutil/boto/docs/source/contributing.rst +204 -0
  390. data/packages/gsutil/boto/docs/source/documentation.rst +59 -0
  391. data/packages/gsutil/boto/docs/source/dynamodb_tut.rst +339 -0
  392. data/packages/gsutil/boto/docs/source/ec2_tut.rst +86 -0
  393. data/packages/gsutil/boto/docs/source/elb_tut.rst +257 -0
  394. data/packages/gsutil/boto/docs/source/emr_tut.rst +108 -0
  395. data/packages/gsutil/boto/docs/source/index.rst +146 -0
  396. data/packages/gsutil/boto/docs/source/rds_tut.rst +108 -0
  397. data/packages/gsutil/boto/docs/source/ref/autoscale.rst +62 -0
  398. data/packages/gsutil/boto/docs/source/ref/beanstalk.rst +26 -0
  399. data/packages/gsutil/boto/docs/source/ref/boto.rst +47 -0
  400. data/packages/gsutil/boto/docs/source/ref/cloudformation.rst +34 -0
  401. data/packages/gsutil/boto/docs/source/ref/cloudfront.rst +68 -0
  402. data/packages/gsutil/boto/docs/source/ref/cloudsearch.rst +59 -0
  403. data/packages/gsutil/boto/docs/source/ref/cloudwatch.rst +27 -0
  404. data/packages/gsutil/boto/docs/source/ref/contrib.rst +32 -0
  405. data/packages/gsutil/boto/docs/source/ref/datapipeline.rst +26 -0
  406. data/packages/gsutil/boto/docs/source/ref/dynamodb.rst +61 -0
  407. data/packages/gsutil/boto/docs/source/ref/ec2.rst +140 -0
  408. data/packages/gsutil/boto/docs/source/ref/ecs.rst +19 -0
  409. data/packages/gsutil/boto/docs/source/ref/elasticache.rst +19 -0
  410. data/packages/gsutil/boto/docs/source/ref/elastictranscoder.rst +26 -0
  411. data/packages/gsutil/boto/docs/source/ref/elb.rst +47 -0
  412. data/packages/gsutil/boto/docs/source/ref/emr.rst +34 -0
  413. data/packages/gsutil/boto/docs/source/ref/file.rst +34 -0
  414. data/packages/gsutil/boto/docs/source/ref/fps.rst +19 -0
  415. data/packages/gsutil/boto/docs/source/ref/glacier.rst +63 -0
  416. data/packages/gsutil/boto/docs/source/ref/gs.rst +72 -0
  417. data/packages/gsutil/boto/docs/source/ref/iam.rst +27 -0
  418. data/packages/gsutil/boto/docs/source/ref/index.rst +40 -0
  419. data/packages/gsutil/boto/docs/source/ref/manage.rst +47 -0
  420. data/packages/gsutil/boto/docs/source/ref/mturk.rst +54 -0
  421. data/packages/gsutil/boto/docs/source/ref/mws.rst +33 -0
  422. data/packages/gsutil/boto/docs/source/ref/pyami.rst +103 -0
  423. data/packages/gsutil/boto/docs/source/ref/rds.rst +47 -0
  424. data/packages/gsutil/boto/docs/source/ref/route53.rst +34 -0
  425. data/packages/gsutil/boto/docs/source/ref/s3.rst +111 -0
  426. data/packages/gsutil/boto/docs/source/ref/sdb.rst +45 -0
  427. data/packages/gsutil/boto/docs/source/ref/sdb_db.rst +83 -0
  428. data/packages/gsutil/boto/docs/source/ref/services.rst +61 -0
  429. data/packages/gsutil/boto/docs/source/ref/ses.rst +21 -0
  430. data/packages/gsutil/boto/docs/source/ref/sns.rst +17 -0
  431. data/packages/gsutil/boto/docs/source/ref/sqs.rst +61 -0
  432. data/packages/gsutil/boto/docs/source/ref/sts.rst +25 -0
  433. data/packages/gsutil/boto/docs/source/ref/swf.rst +22 -0
  434. data/packages/gsutil/boto/docs/source/ref/vpc.rst +54 -0
  435. data/packages/gsutil/boto/docs/source/s3_tut.rst +450 -0
  436. data/packages/gsutil/boto/docs/source/security_groups.rst +82 -0
  437. data/packages/gsutil/boto/docs/source/ses_tut.rst +171 -0
  438. data/packages/gsutil/boto/docs/source/simpledb_tut.rst +188 -0
  439. data/packages/gsutil/boto/docs/source/sqs_tut.rst +246 -0
  440. data/packages/gsutil/boto/docs/source/vpc_tut.rst +100 -0
  441. data/packages/gsutil/boto/pylintrc +305 -0
  442. data/packages/gsutil/boto/requirements.txt +10 -0
  443. data/packages/gsutil/boto/setup.py +89 -0
  444. data/packages/gsutil/boto/tests/__init__.py +20 -0
  445. data/packages/gsutil/boto/tests/db/test_lists.py +96 -0
  446. data/packages/gsutil/boto/tests/db/test_password.py +128 -0
  447. data/packages/gsutil/boto/tests/db/test_query.py +152 -0
  448. data/packages/gsutil/boto/tests/db/test_sequence.py +109 -0
  449. data/packages/gsutil/boto/tests/devpay/__init__.py +0 -0
  450. data/packages/gsutil/boto/tests/devpay/test_s3.py +181 -0
  451. data/packages/gsutil/boto/tests/fps/__init__.py +0 -0
  452. data/packages/gsutil/boto/tests/fps/test.py +100 -0
  453. data/packages/gsutil/boto/tests/fps/test_verify_signature.py +12 -0
  454. data/packages/gsutil/boto/tests/integration/__init__.py +0 -0
  455. data/packages/gsutil/boto/tests/integration/beanstalk/test_wrapper.py +209 -0
  456. data/packages/gsutil/boto/tests/integration/cloudformation/__init__.py +21 -0
  457. data/packages/gsutil/boto/tests/integration/cloudformation/test_cert_verification.py +40 -0
  458. data/packages/gsutil/boto/tests/integration/cloudformation/test_connection.py +110 -0
  459. data/packages/gsutil/boto/tests/integration/cloudsearch/__init__.py +21 -0
  460. data/packages/gsutil/boto/tests/integration/cloudsearch/test_cert_verification.py +40 -0
  461. data/packages/gsutil/boto/tests/integration/datapipeline/test_layer1.py +122 -0
  462. data/packages/gsutil/boto/tests/integration/dynamodb/__init__.py +20 -0
  463. data/packages/gsutil/boto/tests/integration/dynamodb/test_cert_verification.py +40 -0
  464. data/packages/gsutil/boto/tests/integration/dynamodb/test_layer1.py +266 -0
  465. data/packages/gsutil/boto/tests/integration/dynamodb/test_layer2.py +484 -0
  466. data/packages/gsutil/boto/tests/integration/dynamodb/test_table.py +84 -0
  467. data/packages/gsutil/boto/tests/integration/ec2/__init__.py +20 -0
  468. data/packages/gsutil/boto/tests/integration/ec2/autoscale/__init__.py +21 -0
  469. data/packages/gsutil/boto/tests/integration/ec2/autoscale/test_cert_verification.py +40 -0
  470. data/packages/gsutil/boto/tests/integration/ec2/autoscale/test_connection.py +167 -0
  471. data/packages/gsutil/boto/tests/integration/ec2/cloudwatch/__init__.py +20 -0
  472. data/packages/gsutil/boto/tests/integration/ec2/cloudwatch/test_cert_verification.py +40 -0
  473. data/packages/gsutil/boto/tests/integration/ec2/cloudwatch/test_connection.py +277 -0
  474. data/packages/gsutil/boto/tests/integration/ec2/elb/__init__.py +20 -0
  475. data/packages/gsutil/boto/tests/integration/ec2/elb/test_cert_verification.py +40 -0
  476. data/packages/gsutil/boto/tests/integration/ec2/elb/test_connection.py +130 -0
  477. data/packages/gsutil/boto/tests/integration/ec2/test_cert_verification.py +40 -0
  478. data/packages/gsutil/boto/tests/integration/ec2/test_connection.py +192 -0
  479. data/packages/gsutil/boto/tests/integration/ec2/vpc/__init__.py +0 -0
  480. data/packages/gsutil/boto/tests/integration/ec2/vpc/test_connection.py +95 -0
  481. data/packages/gsutil/boto/tests/integration/elasticache/__init__.py +0 -0
  482. data/packages/gsutil/boto/tests/integration/elasticache/test_layer1.py +67 -0
  483. data/packages/gsutil/boto/tests/integration/elastictranscoder/__init__.py +0 -0
  484. data/packages/gsutil/boto/tests/integration/elastictranscoder/test_cert_verification.py +35 -0
  485. data/packages/gsutil/boto/tests/integration/elastictranscoder/test_layer1.py +115 -0
  486. data/packages/gsutil/boto/tests/integration/emr/__init__.py +20 -0
  487. data/packages/gsutil/boto/tests/integration/emr/test_cert_verification.py +40 -0
  488. data/packages/gsutil/boto/tests/integration/glacier/__init__.py +22 -0
  489. data/packages/gsutil/boto/tests/integration/glacier/test_cert_verification.py +40 -0
  490. data/packages/gsutil/boto/tests/integration/glacier/test_layer1.py +44 -0
  491. data/packages/gsutil/boto/tests/integration/glacier/test_layer2.py +45 -0
  492. data/packages/gsutil/boto/tests/integration/gs/__init__.py +0 -0
  493. data/packages/gsutil/boto/tests/integration/gs/cb_test_harness.py +71 -0
  494. data/packages/gsutil/boto/tests/integration/gs/test_basic.py +379 -0
  495. data/packages/gsutil/boto/tests/integration/gs/test_generation_conditionals.py +399 -0
  496. data/packages/gsutil/boto/tests/integration/gs/test_resumable_downloads.py +358 -0
  497. data/packages/gsutil/boto/tests/integration/gs/test_resumable_uploads.py +525 -0
  498. data/packages/gsutil/boto/tests/integration/gs/test_storage_uri.py +125 -0
  499. data/packages/gsutil/boto/tests/integration/gs/test_versioning.py +268 -0
  500. data/packages/gsutil/boto/tests/integration/gs/testcase.py +116 -0
  501. data/packages/gsutil/boto/tests/integration/gs/util.py +63 -0
  502. data/packages/gsutil/boto/tests/integration/iam/__init__.py +20 -0
  503. data/packages/gsutil/boto/tests/integration/iam/test_cert_verification.py +40 -0
  504. data/packages/gsutil/boto/tests/integration/mws/__init__.py +0 -0
  505. data/packages/gsutil/boto/tests/integration/mws/test.py +100 -0
  506. data/packages/gsutil/boto/tests/integration/rds/__init__.py +21 -0
  507. data/packages/gsutil/boto/tests/integration/rds/test_cert_verification.py +40 -0
  508. data/packages/gsutil/boto/tests/integration/route53/__init__.py +20 -0
  509. data/packages/gsutil/boto/tests/integration/route53/test_cert_verification.py +40 -0
  510. data/packages/gsutil/boto/tests/integration/route53/test_zone.py +132 -0
  511. data/packages/gsutil/boto/tests/integration/s3/__init__.py +20 -0
  512. data/packages/gsutil/boto/tests/integration/s3/mock_storage_service.py +589 -0
  513. data/packages/gsutil/boto/tests/integration/s3/other_cacerts.txt +70 -0
  514. data/packages/gsutil/boto/tests/integration/s3/test_bucket.py +263 -0
  515. data/packages/gsutil/boto/tests/integration/s3/test_cert_verification.py +40 -0
  516. data/packages/gsutil/boto/tests/integration/s3/test_connection.py +245 -0
  517. data/packages/gsutil/boto/tests/integration/s3/test_cors.py +78 -0
  518. data/packages/gsutil/boto/tests/integration/s3/test_encryption.py +115 -0
  519. data/packages/gsutil/boto/tests/integration/s3/test_https_cert_validation.py +141 -0
  520. data/packages/gsutil/boto/tests/integration/s3/test_key.py +375 -0
  521. data/packages/gsutil/boto/tests/integration/s3/test_mfa.py +95 -0
  522. data/packages/gsutil/boto/tests/integration/s3/test_multidelete.py +181 -0
  523. data/packages/gsutil/boto/tests/integration/s3/test_multipart.py +139 -0
  524. data/packages/gsutil/boto/tests/integration/s3/test_pool.py +246 -0
  525. data/packages/gsutil/boto/tests/integration/s3/test_versioning.py +158 -0
  526. data/packages/gsutil/boto/tests/integration/sdb/__init__.py +20 -0
  527. data/packages/gsutil/boto/tests/integration/sdb/test_cert_verification.py +40 -0
  528. data/packages/gsutil/boto/tests/integration/sdb/test_connection.py +119 -0
  529. data/packages/gsutil/boto/tests/integration/ses/__init__.py +0 -0
  530. data/packages/gsutil/boto/tests/integration/ses/test_cert_verification.py +40 -0
  531. data/packages/gsutil/boto/tests/integration/ses/test_connection.py +38 -0
  532. data/packages/gsutil/boto/tests/integration/sns/__init__.py +20 -0
  533. data/packages/gsutil/boto/tests/integration/sns/test_cert_verification.py +40 -0
  534. data/packages/gsutil/boto/tests/integration/sqs/__init__.py +20 -0
  535. data/packages/gsutil/boto/tests/integration/sqs/test_cert_verification.py +40 -0
  536. data/packages/gsutil/boto/tests/integration/sqs/test_connection.py +217 -0
  537. data/packages/gsutil/boto/tests/integration/sts/__init__.py +20 -0
  538. data/packages/gsutil/boto/tests/integration/sts/test_cert_verification.py +40 -0
  539. data/packages/gsutil/boto/tests/integration/sts/test_session_token.py +65 -0
  540. data/packages/gsutil/boto/tests/integration/swf/__init__.py +0 -0
  541. data/packages/gsutil/boto/tests/integration/swf/test_cert_verification.py +40 -0
  542. data/packages/gsutil/boto/tests/integration/swf/test_layer1.py +246 -0
  543. data/packages/gsutil/boto/tests/integration/swf/test_layer1_workflow_execution.py +173 -0
  544. data/packages/gsutil/boto/tests/mturk/__init__.py +0 -0
  545. data/packages/gsutil/boto/tests/mturk/_init_environment.py +28 -0
  546. data/packages/gsutil/boto/tests/mturk/all_tests.py +24 -0
  547. data/packages/gsutil/boto/tests/mturk/cleanup_tests.py +47 -0
  548. data/packages/gsutil/boto/tests/mturk/common.py +45 -0
  549. data/packages/gsutil/boto/tests/mturk/create_free_text_question_regex.doctest +100 -0
  550. data/packages/gsutil/boto/tests/mturk/create_hit.doctest +92 -0
  551. data/packages/gsutil/boto/tests/mturk/create_hit_binary.doctest +94 -0
  552. data/packages/gsutil/boto/tests/mturk/create_hit_external.py +21 -0
  553. data/packages/gsutil/boto/tests/mturk/create_hit_from_hit_type.doctest +103 -0
  554. data/packages/gsutil/boto/tests/mturk/create_hit_test.py +21 -0
  555. data/packages/gsutil/boto/tests/mturk/create_hit_with_qualifications.py +16 -0
  556. data/packages/gsutil/boto/tests/mturk/hit_persistence.py +27 -0
  557. data/packages/gsutil/boto/tests/mturk/mocks.py +11 -0
  558. data/packages/gsutil/boto/tests/mturk/reviewable_hits.doctest +129 -0
  559. data/packages/gsutil/boto/tests/mturk/run-doctest.py +13 -0
  560. data/packages/gsutil/boto/tests/mturk/search_hits.doctest +16 -0
  561. data/packages/gsutil/boto/tests/mturk/selenium_support.py +61 -0
  562. data/packages/gsutil/boto/tests/mturk/support.py +7 -0
  563. data/packages/gsutil/boto/tests/mturk/test_disable_hit.py +11 -0
  564. data/packages/gsutil/boto/tests/test.py +59 -0
  565. data/packages/gsutil/boto/tests/unit/__init__.py +79 -0
  566. data/packages/gsutil/boto/tests/unit/auth/__init__.py +0 -0
  567. data/packages/gsutil/boto/tests/unit/auth/test_sigv4.py +73 -0
  568. data/packages/gsutil/boto/tests/unit/beanstalk/__init__.py +0 -0
  569. data/packages/gsutil/boto/tests/unit/beanstalk/test_layer1.py +128 -0
  570. data/packages/gsutil/boto/tests/unit/cloudformation/__init__.py +0 -0
  571. data/packages/gsutil/boto/tests/unit/cloudformation/test_connection.py +605 -0
  572. data/packages/gsutil/boto/tests/unit/cloudformation/test_stack.py +63 -0
  573. data/packages/gsutil/boto/tests/unit/cloudfront/__init__.py +0 -0
  574. data/packages/gsutil/boto/tests/unit/cloudfront/test_invalidation_list.py +113 -0
  575. data/packages/gsutil/boto/tests/unit/cloudfront/test_signed_urls.py +354 -0
  576. data/packages/gsutil/boto/tests/unit/cloudsearch/__init__.py +1 -0
  577. data/packages/gsutil/boto/tests/unit/cloudsearch/test_connection.py +241 -0
  578. data/packages/gsutil/boto/tests/unit/cloudsearch/test_document.py +324 -0
  579. data/packages/gsutil/boto/tests/unit/cloudsearch/test_search.py +325 -0
  580. data/packages/gsutil/boto/tests/unit/dynamodb/__init__.py +0 -0
  581. data/packages/gsutil/boto/tests/unit/dynamodb/test_batch.py +103 -0
  582. data/packages/gsutil/boto/tests/unit/dynamodb/test_layer2.py +119 -0
  583. data/packages/gsutil/boto/tests/unit/dynamodb/test_types.py +82 -0
  584. data/packages/gsutil/boto/tests/unit/ec2/__init__.py +0 -0
  585. data/packages/gsutil/boto/tests/unit/ec2/autoscale/__init__.py +0 -0
  586. data/packages/gsutil/boto/tests/unit/ec2/autoscale/test_group.py +162 -0
  587. data/packages/gsutil/boto/tests/unit/ec2/test_address.py +39 -0
  588. data/packages/gsutil/boto/tests/unit/ec2/test_blockdevicemapping.py +79 -0
  589. data/packages/gsutil/boto/tests/unit/ec2/test_connection.py +480 -0
  590. data/packages/gsutil/boto/tests/unit/ec2/test_instance.py +243 -0
  591. data/packages/gsutil/boto/tests/unit/ec2/test_networkinterface.py +140 -0
  592. data/packages/gsutil/boto/tests/unit/ec2/test_volume.py +248 -0
  593. data/packages/gsutil/boto/tests/unit/emr/test_emr_responses.py +373 -0
  594. data/packages/gsutil/boto/tests/unit/glacier/__init__.py +0 -0
  595. data/packages/gsutil/boto/tests/unit/glacier/test_concurrent.py +120 -0
  596. data/packages/gsutil/boto/tests/unit/glacier/test_job.py +60 -0
  597. data/packages/gsutil/boto/tests/unit/glacier/test_layer1.py +98 -0
  598. data/packages/gsutil/boto/tests/unit/glacier/test_layer2.py +266 -0
  599. data/packages/gsutil/boto/tests/unit/glacier/test_utils.py +116 -0
  600. data/packages/gsutil/boto/tests/unit/glacier/test_vault.py +100 -0
  601. data/packages/gsutil/boto/tests/unit/glacier/test_writer.py +185 -0
  602. data/packages/gsutil/boto/tests/unit/provider/__init__.py +0 -0
  603. data/packages/gsutil/boto/tests/unit/provider/test_provider.py +176 -0
  604. data/packages/gsutil/boto/tests/unit/rds/__init__.py +0 -0
  605. data/packages/gsutil/boto/tests/unit/rds/test_connection.py +131 -0
  606. data/packages/gsutil/boto/tests/unit/s3/__init__.py +0 -0
  607. data/packages/gsutil/boto/tests/unit/s3/test_cors_configuration.py +77 -0
  608. data/packages/gsutil/boto/tests/unit/s3/test_key.py +75 -0
  609. data/packages/gsutil/boto/tests/unit/s3/test_keyfile.py +101 -0
  610. data/packages/gsutil/boto/tests/unit/s3/test_lifecycle.py +97 -0
  611. data/packages/gsutil/boto/tests/unit/s3/test_tagging.py +47 -0
  612. data/packages/gsutil/boto/tests/unit/s3/test_uri.py +257 -0
  613. data/packages/gsutil/boto/tests/unit/s3/test_website.py +188 -0
  614. data/packages/gsutil/boto/tests/unit/sns/__init__.py +0 -0
  615. data/packages/gsutil/boto/tests/unit/sns/test_connection.py +99 -0
  616. data/packages/gsutil/boto/tests/unit/sqs/__init__.py +0 -0
  617. data/packages/gsutil/boto/tests/unit/sqs/test_connection.py +98 -0
  618. data/packages/gsutil/boto/tests/unit/sqs/test_queue.py +40 -0
  619. data/packages/gsutil/boto/tests/unit/sts/test_connection.py +74 -0
  620. data/packages/gsutil/boto/tests/unit/test_connection.py +60 -0
  621. data/packages/gsutil/boto/tests/unit/utils/test_utils.py +109 -0
  622. data/packages/gsutil/boto/tox.ini +8 -0
  623. data/packages/gsutil/gslib/README +5 -0
  624. data/packages/gsutil/gslib/__init__.py +22 -0
  625. data/packages/gsutil/gslib/__init__.pyc +0 -0
  626. data/packages/gsutil/gslib/addlhelp/__init__.py +15 -0
  627. data/packages/gsutil/gslib/addlhelp/acls.py +234 -0
  628. data/packages/gsutil/gslib/addlhelp/anon.py +57 -0
  629. data/packages/gsutil/gslib/addlhelp/command_opts.py +116 -0
  630. data/packages/gsutil/gslib/addlhelp/dev.py +139 -0
  631. data/packages/gsutil/gslib/addlhelp/metadata.py +186 -0
  632. data/packages/gsutil/gslib/addlhelp/naming.py +173 -0
  633. data/packages/gsutil/gslib/addlhelp/prod.py +160 -0
  634. data/packages/gsutil/gslib/addlhelp/projects.py +130 -0
  635. data/packages/gsutil/gslib/addlhelp/subdirs.py +110 -0
  636. data/packages/gsutil/gslib/addlhelp/support.py +86 -0
  637. data/packages/gsutil/gslib/addlhelp/versioning.py +242 -0
  638. data/packages/gsutil/gslib/addlhelp/wildcards.py +170 -0
  639. data/packages/gsutil/gslib/bucket_listing_ref.py +175 -0
  640. data/packages/gsutil/gslib/bucket_listing_ref.pyc +0 -0
  641. data/packages/gsutil/gslib/command.py +722 -0
  642. data/packages/gsutil/gslib/command.pyc +0 -0
  643. data/packages/gsutil/gslib/command_runner.py +101 -0
  644. data/packages/gsutil/gslib/command_runner.pyc +0 -0
  645. data/packages/gsutil/gslib/commands/__init__.py +15 -0
  646. data/packages/gsutil/gslib/commands/__init__.pyc +0 -0
  647. data/packages/gsutil/gslib/commands/cat.py +131 -0
  648. data/packages/gsutil/gslib/commands/cat.pyc +0 -0
  649. data/packages/gsutil/gslib/commands/chacl.py +532 -0
  650. data/packages/gsutil/gslib/commands/chacl.pyc +0 -0
  651. data/packages/gsutil/gslib/commands/config.py +694 -0
  652. data/packages/gsutil/gslib/commands/config.pyc +0 -0
  653. data/packages/gsutil/gslib/commands/cp.py +1818 -0
  654. data/packages/gsutil/gslib/commands/cp.pyc +0 -0
  655. data/packages/gsutil/gslib/commands/disablelogging.py +101 -0
  656. data/packages/gsutil/gslib/commands/disablelogging.pyc +0 -0
  657. data/packages/gsutil/gslib/commands/enablelogging.py +149 -0
  658. data/packages/gsutil/gslib/commands/enablelogging.pyc +0 -0
  659. data/packages/gsutil/gslib/commands/getacl.py +82 -0
  660. data/packages/gsutil/gslib/commands/getacl.pyc +0 -0
  661. data/packages/gsutil/gslib/commands/getcors.py +121 -0
  662. data/packages/gsutil/gslib/commands/getcors.pyc +0 -0
  663. data/packages/gsutil/gslib/commands/getdefacl.py +86 -0
  664. data/packages/gsutil/gslib/commands/getdefacl.pyc +0 -0
  665. data/packages/gsutil/gslib/commands/getlogging.py +137 -0
  666. data/packages/gsutil/gslib/commands/getlogging.pyc +0 -0
  667. data/packages/gsutil/gslib/commands/getversioning.py +116 -0
  668. data/packages/gsutil/gslib/commands/getversioning.pyc +0 -0
  669. data/packages/gsutil/gslib/commands/getwebcfg.py +122 -0
  670. data/packages/gsutil/gslib/commands/getwebcfg.pyc +0 -0
  671. data/packages/gsutil/gslib/commands/help.py +218 -0
  672. data/packages/gsutil/gslib/commands/help.pyc +0 -0
  673. data/packages/gsutil/gslib/commands/ls.py +578 -0
  674. data/packages/gsutil/gslib/commands/ls.pyc +0 -0
  675. data/packages/gsutil/gslib/commands/mb.py +172 -0
  676. data/packages/gsutil/gslib/commands/mb.pyc +0 -0
  677. data/packages/gsutil/gslib/commands/mv.py +159 -0
  678. data/packages/gsutil/gslib/commands/mv.pyc +0 -0
  679. data/packages/gsutil/gslib/commands/perfdiag.py +903 -0
  680. data/packages/gsutil/gslib/commands/perfdiag.pyc +0 -0
  681. data/packages/gsutil/gslib/commands/rb.py +113 -0
  682. data/packages/gsutil/gslib/commands/rb.pyc +0 -0
  683. data/packages/gsutil/gslib/commands/rm.py +239 -0
  684. data/packages/gsutil/gslib/commands/rm.pyc +0 -0
  685. data/packages/gsutil/gslib/commands/setacl.py +138 -0
  686. data/packages/gsutil/gslib/commands/setacl.pyc +0 -0
  687. data/packages/gsutil/gslib/commands/setcors.py +145 -0
  688. data/packages/gsutil/gslib/commands/setcors.pyc +0 -0
  689. data/packages/gsutil/gslib/commands/setdefacl.py +105 -0
  690. data/packages/gsutil/gslib/commands/setdefacl.pyc +0 -0
  691. data/packages/gsutil/gslib/commands/setmeta.py +428 -0
  692. data/packages/gsutil/gslib/commands/setmeta.pyc +0 -0
  693. data/packages/gsutil/gslib/commands/setversioning.py +114 -0
  694. data/packages/gsutil/gslib/commands/setversioning.pyc +0 -0
  695. data/packages/gsutil/gslib/commands/setwebcfg.py +190 -0
  696. data/packages/gsutil/gslib/commands/setwebcfg.pyc +0 -0
  697. data/packages/gsutil/gslib/commands/test.py +228 -0
  698. data/packages/gsutil/gslib/commands/test.pyc +0 -0
  699. data/packages/gsutil/gslib/commands/update.py +305 -0
  700. data/packages/gsutil/gslib/commands/update.pyc +0 -0
  701. data/packages/gsutil/gslib/commands/version.py +150 -0
  702. data/packages/gsutil/gslib/commands/version.pyc +0 -0
  703. data/packages/gsutil/gslib/exception.py +76 -0
  704. data/packages/gsutil/gslib/exception.pyc +0 -0
  705. data/packages/gsutil/gslib/help_provider.py +81 -0
  706. data/packages/gsutil/gslib/help_provider.pyc +0 -0
  707. data/packages/gsutil/gslib/name_expansion.py +550 -0
  708. data/packages/gsutil/gslib/name_expansion.pyc +0 -0
  709. data/packages/gsutil/gslib/no_op_auth_plugin.py +30 -0
  710. data/packages/gsutil/gslib/plurality_checkable_iterator.py +56 -0
  711. data/packages/gsutil/gslib/plurality_checkable_iterator.pyc +0 -0
  712. data/packages/gsutil/gslib/project_id.py +67 -0
  713. data/packages/gsutil/gslib/project_id.pyc +0 -0
  714. data/packages/gsutil/gslib/storage_uri_builder.py +56 -0
  715. data/packages/gsutil/gslib/storage_uri_builder.pyc +0 -0
  716. data/packages/gsutil/gslib/tests/__init__.py +15 -0
  717. data/packages/gsutil/gslib/tests/__init__.pyc +0 -0
  718. data/packages/gsutil/gslib/tests/test_chacl.py +236 -0
  719. data/packages/gsutil/gslib/tests/test_cp.py +267 -0
  720. data/packages/gsutil/gslib/tests/test_data/test.gif +0 -0
  721. data/packages/gsutil/gslib/tests/test_data/test.mp3 +0 -0
  722. data/packages/gsutil/gslib/tests/test_ls.py +66 -0
  723. data/packages/gsutil/gslib/tests/test_mv.py +69 -0
  724. data/packages/gsutil/gslib/tests/test_naming.py +989 -0
  725. data/packages/gsutil/gslib/tests/test_perfdiag.py +41 -0
  726. data/packages/gsutil/gslib/tests/test_plurality_checkable_iterator.py +67 -0
  727. data/packages/gsutil/gslib/tests/test_rm.py +143 -0
  728. data/packages/gsutil/gslib/tests/test_setacl.py +152 -0
  729. data/packages/gsutil/gslib/tests/test_setcors.py +168 -0
  730. data/packages/gsutil/gslib/tests/test_setmeta.py +91 -0
  731. data/packages/gsutil/gslib/tests/test_setversioning.py +44 -0
  732. data/packages/gsutil/gslib/tests/test_setwebcfg.py +63 -0
  733. data/packages/gsutil/gslib/tests/test_thread_pool.py +92 -0
  734. data/packages/gsutil/gslib/tests/test_wildcard_iterator.py +364 -0
  735. data/packages/gsutil/gslib/tests/testcase/__init__.py +18 -0
  736. data/packages/gsutil/gslib/tests/testcase/base.py +89 -0
  737. data/packages/gsutil/gslib/tests/testcase/integration_testcase.py +197 -0
  738. data/packages/gsutil/gslib/tests/testcase/unit_testcase.py +230 -0
  739. data/packages/gsutil/gslib/tests/util.py +125 -0
  740. data/packages/gsutil/gslib/tests/util.pyc +0 -0
  741. data/packages/gsutil/gslib/thread_pool.py +79 -0
  742. data/packages/gsutil/gslib/thread_pool.pyc +0 -0
  743. data/packages/gsutil/gslib/util.py +151 -0
  744. data/packages/gsutil/gslib/util.pyc +0 -0
  745. data/packages/gsutil/gslib/wildcard_iterator.py +492 -0
  746. data/packages/gsutil/gslib/wildcard_iterator.pyc +0 -0
  747. data/packages/gsutil/gsutil +377 -0
  748. data/packages/gsutil/gsutil.spec.in +75 -0
  749. data/packages/gsutil/oauth2_plugin/__init__.py +22 -0
  750. data/packages/gsutil/oauth2_plugin/__init__.pyc +0 -0
  751. data/packages/gsutil/oauth2_plugin/oauth2_client.py +642 -0
  752. data/packages/gsutil/oauth2_plugin/oauth2_client.pyc +0 -0
  753. data/packages/gsutil/oauth2_plugin/oauth2_client_test.py +374 -0
  754. data/packages/gsutil/oauth2_plugin/oauth2_helper.py +110 -0
  755. data/packages/gsutil/oauth2_plugin/oauth2_helper.pyc +0 -0
  756. data/packages/gsutil/oauth2_plugin/oauth2_plugin.py +24 -0
  757. data/packages/gsutil/oauth2_plugin/oauth2_plugin.pyc +0 -0
  758. data/packages/gsutil/pkg_gen.sh +54 -0
  759. data/packages/gsutil/pkg_util.py +60 -0
  760. data/packages/gsutil/setup.py +141 -0
  761. data/packages/gsutil/third_party/__init__.py +0 -0
  762. data/packages/gsutil/third_party/__init__.pyc +0 -0
  763. data/packages/gsutil/third_party/fancy_urllib/README +21 -0
  764. data/packages/gsutil/third_party/fancy_urllib/__init__.py +398 -0
  765. data/packages/gsutil/third_party/fancy_urllib/__init__.pyc +0 -0
  766. data/tasks/rubygem.rake +3 -1
  767. metadata +770 -7
  768. metadata.gz.sig +0 -0
@@ -0,0 +1,84 @@
1
+ # Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/
2
+ # Copyright (c) 2010, Eucalyptus Systems, Inc.
3
+ # All rights reserved.
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a
6
+ # copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish, dis-
9
+ # tribute, sublicense, and/or sell copies of the Software, and to permit
10
+ # persons to whom the Software is furnished to do so, subject to the fol-
11
+ # lowing conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included
14
+ # in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17
+ # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
18
+ # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
19
+ # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22
+ # IN THE SOFTWARE.
23
+ #
24
+
25
+ from boto.regioninfo import RegionInfo
26
+
27
+
28
+ class S3RegionInfo(RegionInfo):
29
+
30
+ def connect(self, **kw_params):
31
+ """
32
+ Connect to this Region's endpoint. Returns an connection
33
+ object pointing to the endpoint associated with this region.
34
+ You may pass any of the arguments accepted by the connection
35
+ class's constructor as keyword arguments and they will be
36
+ passed along to the connection object.
37
+
38
+ :rtype: Connection object
39
+ :return: The connection to this regions endpoint
40
+ """
41
+ if self.connection_cls:
42
+ return self.connection_cls(host=self.endpoint, **kw_params)
43
+
44
+
45
+ def regions():
46
+ """
47
+ Get all available regions for the Amazon S3 service.
48
+
49
+ :rtype: list
50
+ :return: A list of :class:`boto.regioninfo.RegionInfo`
51
+ """
52
+ from .connection import S3Connection
53
+ return [S3RegionInfo(name='us-east-1',
54
+ endpoint='s3.amazonaws.com',
55
+ connection_cls=S3Connection),
56
+ S3RegionInfo(name='us-west-1',
57
+ endpoint='s3-us-west-1.amazonaws.com',
58
+ connection_cls=S3Connection),
59
+ S3RegionInfo(name='us-west-2',
60
+ endpoint='s3-us-west-2.amazonaws.com',
61
+ connection_cls=S3Connection),
62
+ S3RegionInfo(name='ap-northeast-1',
63
+ endpoint='s3-ap-northeast-1.amazonaws.com',
64
+ connection_cls=S3Connection),
65
+ S3RegionInfo(name='ap-southeast-1',
66
+ endpoint='s3-ap-southeast-1.amazonaws.com',
67
+ connection_cls=S3Connection),
68
+ S3RegionInfo(name='ap-southeast-2',
69
+ endpoint='s3-ap-southeast-2.amazonaws.com',
70
+ connection_cls=S3Connection),
71
+ S3RegionInfo(name='eu-west-1',
72
+ endpoint='s3-eu-west-1.amazonaws.com',
73
+ connection_cls=S3Connection),
74
+ S3RegionInfo(name='sa-east-1',
75
+ endpoint='s3-sa-east-1.amazonaws.com',
76
+ connection_cls=S3Connection),
77
+ ]
78
+
79
+
80
+ def connect_to_region(region_name, **kw_params):
81
+ for region in regions():
82
+ if region.name == region_name:
83
+ return region.connect(**kw_params)
84
+ return None
@@ -0,0 +1,164 @@
1
+ # Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a
4
+ # copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish, dis-
7
+ # tribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the fol-
9
+ # lowing conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included
12
+ # in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
+ # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
16
+ # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17
+ # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20
+ # IN THE SOFTWARE.
21
+
22
+ from boto.s3.user import User
23
+
24
+
25
+ CannedACLStrings = ['private', 'public-read',
26
+ 'public-read-write', 'authenticated-read',
27
+ 'bucket-owner-read', 'bucket-owner-full-control',
28
+ 'log-delivery-write']
29
+
30
+
31
+ class Policy:
32
+
33
+ def __init__(self, parent=None):
34
+ self.parent = parent
35
+ self.acl = None
36
+
37
+ def __repr__(self):
38
+ grants = []
39
+ for g in self.acl.grants:
40
+ if g.id == self.owner.id:
41
+ grants.append("%s (owner) = %s" % (g.display_name, g.permission))
42
+ else:
43
+ if g.type == 'CanonicalUser':
44
+ u = g.display_name
45
+ elif g.type == 'Group':
46
+ u = g.uri
47
+ else:
48
+ u = g.email_address
49
+ grants.append("%s = %s" % (u, g.permission))
50
+ return "<Policy: %s>" % ", ".join(grants)
51
+
52
+ def startElement(self, name, attrs, connection):
53
+ if name == 'Owner':
54
+ self.owner = User(self)
55
+ return self.owner
56
+ elif name == 'AccessControlList':
57
+ self.acl = ACL(self)
58
+ return self.acl
59
+ else:
60
+ return None
61
+
62
+ def endElement(self, name, value, connection):
63
+ if name == 'Owner':
64
+ pass
65
+ elif name == 'AccessControlList':
66
+ pass
67
+ else:
68
+ setattr(self, name, value)
69
+
70
+ def to_xml(self):
71
+ s = '<AccessControlPolicy>'
72
+ s += self.owner.to_xml()
73
+ s += self.acl.to_xml()
74
+ s += '</AccessControlPolicy>'
75
+ return s
76
+
77
+ class ACL:
78
+
79
+ def __init__(self, policy=None):
80
+ self.policy = policy
81
+ self.grants = []
82
+
83
+ def add_grant(self, grant):
84
+ self.grants.append(grant)
85
+
86
+ def add_email_grant(self, permission, email_address):
87
+ grant = Grant(permission=permission, type='AmazonCustomerByEmail',
88
+ email_address=email_address)
89
+ self.grants.append(grant)
90
+
91
+ def add_user_grant(self, permission, user_id, display_name=None):
92
+ grant = Grant(permission=permission, type='CanonicalUser', id=user_id, display_name=display_name)
93
+ self.grants.append(grant)
94
+
95
+ def startElement(self, name, attrs, connection):
96
+ if name == 'Grant':
97
+ self.grants.append(Grant(self))
98
+ return self.grants[-1]
99
+ else:
100
+ return None
101
+
102
+ def endElement(self, name, value, connection):
103
+ if name == 'Grant':
104
+ pass
105
+ else:
106
+ setattr(self, name, value)
107
+
108
+ def to_xml(self):
109
+ s = '<AccessControlList>'
110
+ for grant in self.grants:
111
+ s += grant.to_xml()
112
+ s += '</AccessControlList>'
113
+ return s
114
+
115
+ class Grant:
116
+
117
+ NameSpace = 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
118
+
119
+ def __init__(self, permission=None, type=None, id=None,
120
+ display_name=None, uri=None, email_address=None):
121
+ self.permission = permission
122
+ self.id = id
123
+ self.display_name = display_name
124
+ self.uri = uri
125
+ self.email_address = email_address
126
+ self.type = type
127
+
128
+ def startElement(self, name, attrs, connection):
129
+ if name == 'Grantee':
130
+ self.type = attrs['xsi:type']
131
+ return None
132
+
133
+ def endElement(self, name, value, connection):
134
+ if name == 'ID':
135
+ self.id = value
136
+ elif name == 'DisplayName':
137
+ self.display_name = value
138
+ elif name == 'URI':
139
+ self.uri = value
140
+ elif name == 'EmailAddress':
141
+ self.email_address = value
142
+ elif name == 'Grantee':
143
+ pass
144
+ elif name == 'Permission':
145
+ self.permission = value
146
+ else:
147
+ setattr(self, name, value)
148
+
149
+ def to_xml(self):
150
+ s = '<Grant>'
151
+ s += '<Grantee %s xsi:type="%s">' % (self.NameSpace, self.type)
152
+ if self.type == 'CanonicalUser':
153
+ s += '<ID>%s</ID>' % self.id
154
+ s += '<DisplayName>%s</DisplayName>' % self.display_name
155
+ elif self.type == 'Group':
156
+ s += '<URI>%s</URI>' % self.uri
157
+ else:
158
+ s += '<EmailAddress>%s</EmailAddress>' % self.email_address
159
+ s += '</Grantee>'
160
+ s += '<Permission>%s</Permission>' % self.permission
161
+ s += '</Grant>'
162
+ return s
163
+
164
+
@@ -0,0 +1,1634 @@
1
+ # Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/
2
+ # Copyright (c) 2010, Eucalyptus Systems, Inc.
3
+ # All rights reserved.
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a
6
+ # copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish, dis-
9
+ # tribute, sublicense, and/or sell copies of the Software, and to permit
10
+ # persons to whom the Software is furnished to do so, subject to the fol-
11
+ # lowing conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included
14
+ # in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17
+ # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
18
+ # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
19
+ # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22
+ # IN THE SOFTWARE.
23
+
24
+ import boto
25
+ from boto import handler
26
+ from boto.resultset import ResultSet
27
+ from boto.exception import BotoClientError
28
+ from boto.s3.acl import Policy, CannedACLStrings, Grant
29
+ from boto.s3.key import Key
30
+ from boto.s3.prefix import Prefix
31
+ from boto.s3.deletemarker import DeleteMarker
32
+ from boto.s3.multipart import MultiPartUpload
33
+ from boto.s3.multipart import CompleteMultiPartUpload
34
+ from boto.s3.multidelete import MultiDeleteResult
35
+ from boto.s3.multidelete import Error
36
+ from boto.s3.bucketlistresultset import BucketListResultSet
37
+ from boto.s3.bucketlistresultset import VersionedBucketListResultSet
38
+ from boto.s3.bucketlistresultset import MultiPartUploadListResultSet
39
+ from boto.s3.lifecycle import Lifecycle
40
+ from boto.s3.tagging import Tags
41
+ from boto.s3.cors import CORSConfiguration
42
+ from boto.s3.bucketlogging import BucketLogging
43
+ from boto.s3 import website
44
+ import boto.jsonresponse
45
+ import boto.utils
46
+ import xml.sax
47
+ import xml.sax.saxutils
48
+ import StringIO
49
+ import urllib
50
+ import re
51
+ import base64
52
+ from collections import defaultdict
53
+
54
+ # as per http://goo.gl/BDuud (02/19/2011)
55
+
56
+
57
+ class S3WebsiteEndpointTranslate:
58
+
59
+ trans_region = defaultdict(lambda: 's3-website-us-east-1')
60
+ trans_region['eu-west-1'] = 's3-website-eu-west-1'
61
+ trans_region['us-west-1'] = 's3-website-us-west-1'
62
+ trans_region['us-west-2'] = 's3-website-us-west-2'
63
+ trans_region['sa-east-1'] = 's3-website-sa-east-1'
64
+ trans_region['ap-northeast-1'] = 's3-website-ap-northeast-1'
65
+ trans_region['ap-southeast-1'] = 's3-website-ap-southeast-1'
66
+
67
+ @classmethod
68
+ def translate_region(self, reg):
69
+ return self.trans_region[reg]
70
+
71
+ S3Permissions = ['READ', 'WRITE', 'READ_ACP', 'WRITE_ACP', 'FULL_CONTROL']
72
+
73
+
74
+ class Bucket(object):
75
+
76
+ LoggingGroup = 'http://acs.amazonaws.com/groups/s3/LogDelivery'
77
+
78
+ BucketPaymentBody = """<?xml version="1.0" encoding="UTF-8"?>
79
+ <RequestPaymentConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
80
+ <Payer>%s</Payer>
81
+ </RequestPaymentConfiguration>"""
82
+
83
+ VersioningBody = """<?xml version="1.0" encoding="UTF-8"?>
84
+ <VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
85
+ <Status>%s</Status>
86
+ <MfaDelete>%s</MfaDelete>
87
+ </VersioningConfiguration>"""
88
+
89
+ WebsiteBody = """<?xml version="1.0" encoding="UTF-8"?>
90
+ <WebsiteConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
91
+ <IndexDocument><Suffix>%s</Suffix></IndexDocument>
92
+ %s
93
+ </WebsiteConfiguration>"""
94
+
95
+ WebsiteErrorFragment = """<ErrorDocument><Key>%s</Key></ErrorDocument>"""
96
+
97
+ VersionRE = '<Status>([A-Za-z]+)</Status>'
98
+ MFADeleteRE = '<MfaDelete>([A-Za-z]+)</MfaDelete>'
99
+
100
+ def __init__(self, connection=None, name=None, key_class=Key):
101
+ self.name = name
102
+ self.connection = connection
103
+ self.key_class = key_class
104
+
105
+ def __repr__(self):
106
+ return '<Bucket: %s>' % self.name
107
+
108
+ def __iter__(self):
109
+ return iter(BucketListResultSet(self))
110
+
111
+ def __contains__(self, key_name):
112
+ return not (self.get_key(key_name) is None)
113
+
114
+ def startElement(self, name, attrs, connection):
115
+ return None
116
+
117
+ def endElement(self, name, value, connection):
118
+ if name == 'Name':
119
+ self.name = value
120
+ elif name == 'CreationDate':
121
+ self.creation_date = value
122
+ else:
123
+ setattr(self, name, value)
124
+
125
+ def set_key_class(self, key_class):
126
+ """
127
+ Set the Key class associated with this bucket. By default, this
128
+ would be the boto.s3.key.Key class but if you want to subclass that
129
+ for some reason this allows you to associate your new class with a
130
+ bucket so that when you call bucket.new_key() or when you get a listing
131
+ of keys in the bucket you will get an instances of your key class
132
+ rather than the default.
133
+
134
+ :type key_class: class
135
+ :param key_class: A subclass of Key that can be more specific
136
+ """
137
+ self.key_class = key_class
138
+
139
+ def lookup(self, key_name, headers=None):
140
+ """
141
+ Deprecated: Please use get_key method.
142
+
143
+ :type key_name: string
144
+ :param key_name: The name of the key to retrieve
145
+
146
+ :rtype: :class:`boto.s3.key.Key`
147
+ :returns: A Key object from this bucket.
148
+ """
149
+ return self.get_key(key_name, headers=headers)
150
+
151
+ def get_key(self, key_name, headers=None, version_id=None,
152
+ response_headers=None):
153
+ """
154
+ Check to see if a particular key exists within the bucket. This
155
+ method uses a HEAD request to check for the existance of the key.
156
+ Returns: An instance of a Key object or None
157
+
158
+ :type key_name: string
159
+ :param key_name: The name of the key to retrieve
160
+
161
+ :type response_headers: dict
162
+ :param response_headers: A dictionary containing HTTP
163
+ headers/values that will override any headers associated
164
+ with the stored object in the response. See
165
+ http://goo.gl/EWOPb for details.
166
+
167
+ :rtype: :class:`boto.s3.key.Key`
168
+ :returns: A Key object from this bucket.
169
+ """
170
+ query_args_l = []
171
+ if version_id:
172
+ query_args_l.append('versionId=%s' % version_id)
173
+ if response_headers:
174
+ for rk, rv in response_headers.iteritems():
175
+ query_args_l.append('%s=%s' % (rk, urllib.quote(rv)))
176
+
177
+ key, resp = self._get_key_internal(key_name, headers, query_args_l)
178
+ return key
179
+
180
+ def _get_key_internal(self, key_name, headers, query_args_l):
181
+ query_args = '&'.join(query_args_l) or None
182
+ response = self.connection.make_request('HEAD', self.name, key_name,
183
+ headers=headers,
184
+ query_args=query_args)
185
+ response.read()
186
+ # Allow any success status (2xx) - for example this lets us
187
+ # support Range gets, which return status 206:
188
+ if response.status / 100 == 2:
189
+ k = self.key_class(self)
190
+ provider = self.connection.provider
191
+ k.metadata = boto.utils.get_aws_metadata(response.msg, provider)
192
+ k.etag = response.getheader('etag')
193
+ k.content_type = response.getheader('content-type')
194
+ k.content_encoding = response.getheader('content-encoding')
195
+ k.content_disposition = response.getheader('content-disposition')
196
+ k.content_language = response.getheader('content-language')
197
+ k.last_modified = response.getheader('last-modified')
198
+ # the following machinations are a workaround to the fact that
199
+ # apache/fastcgi omits the content-length header on HEAD
200
+ # requests when the content-length is zero.
201
+ # See http://goo.gl/0Tdax for more details.
202
+ clen = response.getheader('content-length')
203
+ if clen:
204
+ k.size = int(response.getheader('content-length'))
205
+ else:
206
+ k.size = 0
207
+ k.cache_control = response.getheader('cache-control')
208
+ k.name = key_name
209
+ k.handle_version_headers(response)
210
+ k.handle_encryption_headers(response)
211
+ k.handle_restore_headers(response)
212
+ return k, response
213
+ else:
214
+ if response.status == 404:
215
+ return None, response
216
+ else:
217
+ raise self.connection.provider.storage_response_error(
218
+ response.status, response.reason, '')
219
+
220
+ def list(self, prefix='', delimiter='', marker='', headers=None):
221
+ """
222
+ List key objects within a bucket. This returns an instance of an
223
+ BucketListResultSet that automatically handles all of the result
224
+ paging, etc. from S3. You just need to keep iterating until
225
+ there are no more results.
226
+
227
+ Called with no arguments, this will return an iterator object across
228
+ all keys within the bucket.
229
+
230
+ The Key objects returned by the iterator are obtained by parsing
231
+ the results of a GET on the bucket, also known as the List Objects
232
+ request. The XML returned by this request contains only a subset
233
+ of the information about each key. Certain metadata fields such
234
+ as Content-Type and user metadata are not available in the XML.
235
+ Therefore, if you want these additional metadata fields you will
236
+ have to do a HEAD request on the Key in the bucket.
237
+
238
+ :type prefix: string
239
+ :param prefix: allows you to limit the listing to a particular
240
+ prefix. For example, if you call the method with
241
+ prefix='/foo/' then the iterator will only cycle through
242
+ the keys that begin with the string '/foo/'.
243
+
244
+ :type delimiter: string
245
+ :param delimiter: can be used in conjunction with the prefix
246
+ to allow you to organize and browse your keys
247
+ hierarchically. See http://goo.gl/Xx63h for more details.
248
+
249
+ :type marker: string
250
+ :param marker: The "marker" of where you are in the result set
251
+
252
+ :rtype: :class:`boto.s3.bucketlistresultset.BucketListResultSet`
253
+ :return: an instance of a BucketListResultSet that handles paging, etc
254
+ """
255
+ return BucketListResultSet(self, prefix, delimiter, marker, headers)
256
+
257
+ def list_versions(self, prefix='', delimiter='', key_marker='',
258
+ version_id_marker='', headers=None):
259
+ """
260
+ List version objects within a bucket. This returns an
261
+ instance of an VersionedBucketListResultSet that automatically
262
+ handles all of the result paging, etc. from S3. You just need
263
+ to keep iterating until there are no more results. Called
264
+ with no arguments, this will return an iterator object across
265
+ all keys within the bucket.
266
+
267
+ :type prefix: string
268
+ :param prefix: allows you to limit the listing to a particular
269
+ prefix. For example, if you call the method with
270
+ prefix='/foo/' then the iterator will only cycle through
271
+ the keys that begin with the string '/foo/'.
272
+
273
+ :type delimiter: string
274
+ :param delimiter: can be used in conjunction with the prefix
275
+ to allow you to organize and browse your keys
276
+ hierarchically. See:
277
+
278
+ http://aws.amazon.com/releasenotes/Amazon-S3/213
279
+
280
+ for more details.
281
+
282
+ :type marker: string
283
+ :param marker: The "marker" of where you are in the result set
284
+
285
+ :rtype: :class:`boto.s3.bucketlistresultset.BucketListResultSet`
286
+ :return: an instance of a BucketListResultSet that handles paging, etc
287
+ """
288
+ return VersionedBucketListResultSet(self, prefix, delimiter,
289
+ key_marker, version_id_marker,
290
+ headers)
291
+
292
+ def list_multipart_uploads(self, key_marker='',
293
+ upload_id_marker='',
294
+ headers=None):
295
+ """
296
+ List multipart upload objects within a bucket. This returns an
297
+ instance of an MultiPartUploadListResultSet that automatically
298
+ handles all of the result paging, etc. from S3. You just need
299
+ to keep iterating until there are no more results.
300
+
301
+ :type marker: string
302
+ :param marker: The "marker" of where you are in the result set
303
+
304
+ :rtype: :class:`boto.s3.bucketlistresultset.BucketListResultSet`
305
+ :return: an instance of a BucketListResultSet that handles paging, etc
306
+ """
307
+ return MultiPartUploadListResultSet(self, key_marker,
308
+ upload_id_marker,
309
+ headers)
310
+
311
+ def _get_all(self, element_map, initial_query_string='',
312
+ headers=None, **params):
313
+ l = []
314
+ for k, v in params.items():
315
+ k = k.replace('_', '-')
316
+ if k == 'maxkeys':
317
+ k = 'max-keys'
318
+ if isinstance(v, unicode):
319
+ v = v.encode('utf-8')
320
+ if v is not None and v != '':
321
+ l.append('%s=%s' % (urllib.quote(k), urllib.quote(str(v))))
322
+ if len(l):
323
+ s = initial_query_string + '&' + '&'.join(l)
324
+ else:
325
+ s = initial_query_string
326
+ response = self.connection.make_request('GET', self.name,
327
+ headers=headers,
328
+ query_args=s)
329
+ body = response.read()
330
+ boto.log.debug(body)
331
+ if response.status == 200:
332
+ rs = ResultSet(element_map)
333
+ h = handler.XmlHandler(rs, self)
334
+ xml.sax.parseString(body, h)
335
+ return rs
336
+ else:
337
+ raise self.connection.provider.storage_response_error(
338
+ response.status, response.reason, body)
339
+
340
+ def get_all_keys(self, headers=None, **params):
341
+ """
342
+ A lower-level method for listing contents of a bucket. This
343
+ closely models the actual S3 API and requires you to manually
344
+ handle the paging of results. For a higher-level method that
345
+ handles the details of paging for you, you can use the list
346
+ method.
347
+
348
+ :type max_keys: int
349
+ :param max_keys: The maximum number of keys to retrieve
350
+
351
+ :type prefix: string
352
+ :param prefix: The prefix of the keys you want to retrieve
353
+
354
+ :type marker: string
355
+ :param marker: The "marker" of where you are in the result set
356
+
357
+ :type delimiter: string
358
+ :param delimiter: If this optional, Unicode string parameter
359
+ is included with your request, then keys that contain the
360
+ same string between the prefix and the first occurrence of
361
+ the delimiter will be rolled up into a single result
362
+ element in the CommonPrefixes collection. These rolled-up
363
+ keys are not returned elsewhere in the response.
364
+
365
+ :rtype: ResultSet
366
+ :return: The result from S3 listing the keys requested
367
+
368
+ """
369
+ return self._get_all([('Contents', self.key_class),
370
+ ('CommonPrefixes', Prefix)],
371
+ '', headers, **params)
372
+
373
+ def get_all_versions(self, headers=None, **params):
374
+ """
375
+ A lower-level, version-aware method for listing contents of a
376
+ bucket. This closely models the actual S3 API and requires
377
+ you to manually handle the paging of results. For a
378
+ higher-level method that handles the details of paging for
379
+ you, you can use the list method.
380
+
381
+ :type max_keys: int
382
+ :param max_keys: The maximum number of keys to retrieve
383
+
384
+ :type prefix: string
385
+ :param prefix: The prefix of the keys you want to retrieve
386
+
387
+ :type key_marker: string
388
+ :param key_marker: The "marker" of where you are in the result set
389
+ with respect to keys.
390
+
391
+ :type version_id_marker: string
392
+ :param version_id_marker: The "marker" of where you are in the result
393
+ set with respect to version-id's.
394
+
395
+ :type delimiter: string
396
+ :param delimiter: If this optional, Unicode string parameter
397
+ is included with your request, then keys that contain the
398
+ same string between the prefix and the first occurrence of
399
+ the delimiter will be rolled up into a single result
400
+ element in the CommonPrefixes collection. These rolled-up
401
+ keys are not returned elsewhere in the response.
402
+
403
+ :rtype: ResultSet
404
+ :return: The result from S3 listing the keys requested
405
+ """
406
+ return self._get_all([('Version', self.key_class),
407
+ ('CommonPrefixes', Prefix),
408
+ ('DeleteMarker', DeleteMarker)],
409
+ 'versions', headers, **params)
410
+
411
+ def get_all_multipart_uploads(self, headers=None, **params):
412
+ """
413
+ A lower-level, version-aware method for listing active
414
+ MultiPart uploads for a bucket. This closely models the
415
+ actual S3 API and requires you to manually handle the paging
416
+ of results. For a higher-level method that handles the
417
+ details of paging for you, you can use the list method.
418
+
419
+ :type max_uploads: int
420
+ :param max_uploads: The maximum number of uploads to retrieve.
421
+ Default value is 1000.
422
+
423
+ :type key_marker: string
424
+ :param key_marker: Together with upload_id_marker, this
425
+ parameter specifies the multipart upload after which
426
+ listing should begin. If upload_id_marker is not
427
+ specified, only the keys lexicographically greater than
428
+ the specified key_marker will be included in the list.
429
+
430
+ If upload_id_marker is specified, any multipart uploads
431
+ for a key equal to the key_marker might also be included,
432
+ provided those multipart uploads have upload IDs
433
+ lexicographically greater than the specified
434
+ upload_id_marker.
435
+
436
+ :type upload_id_marker: string
437
+ :param upload_id_marker: Together with key-marker, specifies
438
+ the multipart upload after which listing should begin. If
439
+ key_marker is not specified, the upload_id_marker
440
+ parameter is ignored. Otherwise, any multipart uploads
441
+ for a key equal to the key_marker might be included in the
442
+ list only if they have an upload ID lexicographically
443
+ greater than the specified upload_id_marker.
444
+
445
+ :rtype: ResultSet
446
+ :return: The result from S3 listing the uploads requested
447
+
448
+ """
449
+ return self._get_all([('Upload', MultiPartUpload),
450
+ ('CommonPrefixes', Prefix)],
451
+ 'uploads', headers, **params)
452
+
453
+ def new_key(self, key_name=None):
454
+ """
455
+ Creates a new key
456
+
457
+ :type key_name: string
458
+ :param key_name: The name of the key to create
459
+
460
+ :rtype: :class:`boto.s3.key.Key` or subclass
461
+ :returns: An instance of the newly created key object
462
+ """
463
+ if not key_name:
464
+ raise ValueError('Empty key names are not allowed')
465
+ return self.key_class(self, key_name)
466
+
467
+ def generate_url(self, expires_in, method='GET', headers=None,
468
+ force_http=False, response_headers=None,
469
+ expires_in_absolute=False):
470
+ return self.connection.generate_url(expires_in, method, self.name,
471
+ headers=headers,
472
+ force_http=force_http,
473
+ response_headers=response_headers,
474
+ expires_in_absolute=expires_in_absolute)
475
+
476
+ def delete_keys(self, keys, quiet=False, mfa_token=None, headers=None):
477
+ """
478
+ Deletes a set of keys using S3's Multi-object delete API. If a
479
+ VersionID is specified for that key then that version is removed.
480
+ Returns a MultiDeleteResult Object, which contains Deleted
481
+ and Error elements for each key you ask to delete.
482
+
483
+ :type keys: list
484
+ :param keys: A list of either key_names or (key_name, versionid) pairs
485
+ or a list of Key instances.
486
+
487
+ :type quiet: boolean
488
+ :param quiet: In quiet mode the response includes only keys
489
+ where the delete operation encountered an error. For a
490
+ successful deletion, the operation does not return any
491
+ information about the delete in the response body.
492
+
493
+ :type mfa_token: tuple or list of strings
494
+ :param mfa_token: A tuple or list consisting of the serial
495
+ number from the MFA device and the current value of the
496
+ six-digit token associated with the device. This value is
497
+ required anytime you are deleting versioned objects from a
498
+ bucket that has the MFADelete option on the bucket.
499
+
500
+ :returns: An instance of MultiDeleteResult
501
+ """
502
+ ikeys = iter(keys)
503
+ result = MultiDeleteResult(self)
504
+ provider = self.connection.provider
505
+ query_args = 'delete'
506
+
507
+ def delete_keys2(hdrs):
508
+ hdrs = hdrs or {}
509
+ data = u"""<?xml version="1.0" encoding="UTF-8"?>"""
510
+ data += u"<Delete>"
511
+ if quiet:
512
+ data += u"<Quiet>true</Quiet>"
513
+ count = 0
514
+ while count < 1000:
515
+ try:
516
+ key = ikeys.next()
517
+ except StopIteration:
518
+ break
519
+ if isinstance(key, basestring):
520
+ key_name = key
521
+ version_id = None
522
+ elif isinstance(key, tuple) and len(key) == 2:
523
+ key_name, version_id = key
524
+ elif (isinstance(key, Key) or isinstance(key, DeleteMarker)) and key.name:
525
+ key_name = key.name
526
+ version_id = key.version_id
527
+ else:
528
+ if isinstance(key, Prefix):
529
+ key_name = key.name
530
+ code = 'PrefixSkipped' # Don't delete Prefix
531
+ else:
532
+ key_name = repr(key) # try get a string
533
+ code = 'InvalidArgument' # other unknown type
534
+ message = 'Invalid. No delete action taken for this object.'
535
+ error = Error(key_name, code=code, message=message)
536
+ result.errors.append(error)
537
+ continue
538
+ count += 1
539
+ data += u"<Object><Key>%s</Key>" % xml.sax.saxutils.escape(key_name)
540
+ if version_id:
541
+ data += u"<VersionId>%s</VersionId>" % version_id
542
+ data += u"</Object>"
543
+ data += u"</Delete>"
544
+ if count <= 0:
545
+ return False # no more
546
+ data = data.encode('utf-8')
547
+ fp = StringIO.StringIO(data)
548
+ md5 = boto.utils.compute_md5(fp)
549
+ hdrs['Content-MD5'] = md5[1]
550
+ hdrs['Content-Type'] = 'text/xml'
551
+ if mfa_token:
552
+ hdrs[provider.mfa_header] = ' '.join(mfa_token)
553
+ response = self.connection.make_request('POST', self.name,
554
+ headers=hdrs,
555
+ query_args=query_args,
556
+ data=data)
557
+ body = response.read()
558
+ if response.status == 200:
559
+ h = handler.XmlHandler(result, self)
560
+ xml.sax.parseString(body, h)
561
+ return count >= 1000 # more?
562
+ else:
563
+ raise provider.storage_response_error(response.status,
564
+ response.reason,
565
+ body)
566
+ while delete_keys2(headers):
567
+ pass
568
+ return result
569
+
570
+ def delete_key(self, key_name, headers=None, version_id=None,
571
+ mfa_token=None):
572
+ """
573
+ Deletes a key from the bucket. If a version_id is provided,
574
+ only that version of the key will be deleted.
575
+
576
+ :type key_name: string
577
+ :param key_name: The key name to delete
578
+
579
+ :type version_id: string
580
+ :param version_id: The version ID (optional)
581
+
582
+ :type mfa_token: tuple or list of strings
583
+ :param mfa_token: A tuple or list consisting of the serial
584
+ number from the MFA device and the current value of the
585
+ six-digit token associated with the device. This value is
586
+ required anytime you are deleting versioned objects from a
587
+ bucket that has the MFADelete option on the bucket.
588
+
589
+ :rtype: :class:`boto.s3.key.Key` or subclass
590
+ :returns: A key object holding information on what was
591
+ deleted. The Caller can see if a delete_marker was
592
+ created or removed and what version_id the delete created
593
+ or removed.
594
+ """
595
+ return self._delete_key_internal(key_name, headers=headers,
596
+ version_id=version_id,
597
+ mfa_token=mfa_token,
598
+ query_args_l=None)
599
+
600
+ def _delete_key_internal(self, key_name, headers=None, version_id=None,
601
+ mfa_token=None, query_args_l=None):
602
+ query_args_l = query_args_l or []
603
+ provider = self.connection.provider
604
+ if version_id:
605
+ query_args_l.append('versionId=%s' % version_id)
606
+ query_args = '&'.join(query_args_l) or None
607
+ if mfa_token:
608
+ if not headers:
609
+ headers = {}
610
+ headers[provider.mfa_header] = ' '.join(mfa_token)
611
+ response = self.connection.make_request('DELETE', self.name, key_name,
612
+ headers=headers,
613
+ query_args=query_args)
614
+ body = response.read()
615
+ if response.status != 204:
616
+ raise provider.storage_response_error(response.status,
617
+ response.reason, body)
618
+ else:
619
+ # return a key object with information on what was deleted.
620
+ k = self.key_class(self)
621
+ k.name = key_name
622
+ k.handle_version_headers(response)
623
+ return k
624
+
625
+ def copy_key(self, new_key_name, src_bucket_name,
626
+ src_key_name, metadata=None, src_version_id=None,
627
+ storage_class='STANDARD', preserve_acl=False,
628
+ encrypt_key=False, headers=None, query_args=None):
629
+ """
630
+ Create a new key in the bucket by copying another existing key.
631
+
632
+ :type new_key_name: string
633
+ :param new_key_name: The name of the new key
634
+
635
+ :type src_bucket_name: string
636
+ :param src_bucket_name: The name of the source bucket
637
+
638
+ :type src_key_name: string
639
+ :param src_key_name: The name of the source key
640
+
641
+ :type src_version_id: string
642
+ :param src_version_id: The version id for the key. This param
643
+ is optional. If not specified, the newest version of the
644
+ key will be copied.
645
+
646
+ :type metadata: dict
647
+ :param metadata: Metadata to be associated with new key. If
648
+ metadata is supplied, it will replace the metadata of the
649
+ source key being copied. If no metadata is supplied, the
650
+ source key's metadata will be copied to the new key.
651
+
652
+ :type storage_class: string
653
+ :param storage_class: The storage class of the new key. By
654
+ default, the new key will use the standard storage class.
655
+ Possible values are: STANDARD | REDUCED_REDUNDANCY
656
+
657
+ :type preserve_acl: bool
658
+ :param preserve_acl: If True, the ACL from the source key will
659
+ be copied to the destination key. If False, the
660
+ destination key will have the default ACL. Note that
661
+ preserving the ACL in the new key object will require two
662
+ additional API calls to S3, one to retrieve the current
663
+ ACL and one to set that ACL on the new object. If you
664
+ don't care about the ACL, a value of False will be
665
+ significantly more efficient.
666
+
667
+ :type encrypt_key: bool
668
+ :param encrypt_key: If True, the new copy of the object will
669
+ be encrypted on the server-side by S3 and will be stored
670
+ in an encrypted form while at rest in S3.
671
+
672
+ :type headers: dict
673
+ :param headers: A dictionary of header name/value pairs.
674
+
675
+ :type query_args: string
676
+ :param query_args: A string of additional querystring arguments
677
+ to append to the request
678
+
679
+ :rtype: :class:`boto.s3.key.Key` or subclass
680
+ :returns: An instance of the newly created key object
681
+ """
682
+ headers = headers or {}
683
+ provider = self.connection.provider
684
+ src_key_name = boto.utils.get_utf8_value(src_key_name)
685
+ if preserve_acl:
686
+ if self.name == src_bucket_name:
687
+ src_bucket = self
688
+ else:
689
+ src_bucket = self.connection.get_bucket(src_bucket_name)
690
+ acl = src_bucket.get_xml_acl(src_key_name)
691
+ if encrypt_key:
692
+ headers[provider.server_side_encryption_header] = 'AES256'
693
+ src = '%s/%s' % (src_bucket_name, urllib.quote(src_key_name))
694
+ if src_version_id:
695
+ src += '?versionId=%s' % src_version_id
696
+ headers[provider.copy_source_header] = str(src)
697
+ # make sure storage_class_header key exists before accessing it
698
+ if provider.storage_class_header and storage_class:
699
+ headers[provider.storage_class_header] = storage_class
700
+ if metadata is not None:
701
+ headers[provider.metadata_directive_header] = 'REPLACE'
702
+ headers = boto.utils.merge_meta(headers, metadata, provider)
703
+ elif not query_args: # Can't use this header with multi-part copy.
704
+ headers[provider.metadata_directive_header] = 'COPY'
705
+ response = self.connection.make_request('PUT', self.name, new_key_name,
706
+ headers=headers,
707
+ query_args=query_args)
708
+ body = response.read()
709
+ if response.status == 200:
710
+ key = self.new_key(new_key_name)
711
+ h = handler.XmlHandler(key, self)
712
+ xml.sax.parseString(body, h)
713
+ if hasattr(key, 'Error'):
714
+ raise provider.storage_copy_error(key.Code, key.Message, body)
715
+ key.handle_version_headers(response)
716
+ if preserve_acl:
717
+ self.set_xml_acl(acl, new_key_name)
718
+ return key
719
+ else:
720
+ raise provider.storage_response_error(response.status,
721
+ response.reason, body)
722
+
723
+ def set_canned_acl(self, acl_str, key_name='', headers=None,
724
+ version_id=None):
725
+ assert acl_str in CannedACLStrings
726
+
727
+ if headers:
728
+ headers[self.connection.provider.acl_header] = acl_str
729
+ else:
730
+ headers = {self.connection.provider.acl_header: acl_str}
731
+
732
+ query_args = 'acl'
733
+ if version_id:
734
+ query_args += '&versionId=%s' % version_id
735
+ response = self.connection.make_request('PUT', self.name, key_name,
736
+ headers=headers, query_args=query_args)
737
+ body = response.read()
738
+ if response.status != 200:
739
+ raise self.connection.provider.storage_response_error(
740
+ response.status, response.reason, body)
741
+
742
+ def get_xml_acl(self, key_name='', headers=None, version_id=None):
743
+ query_args = 'acl'
744
+ if version_id:
745
+ query_args += '&versionId=%s' % version_id
746
+ response = self.connection.make_request('GET', self.name, key_name,
747
+ query_args=query_args,
748
+ headers=headers)
749
+ body = response.read()
750
+ if response.status != 200:
751
+ raise self.connection.provider.storage_response_error(
752
+ response.status, response.reason, body)
753
+ return body
754
+
755
+ def set_xml_acl(self, acl_str, key_name='', headers=None, version_id=None,
756
+ query_args='acl'):
757
+ if version_id:
758
+ query_args += '&versionId=%s' % version_id
759
+ response = self.connection.make_request('PUT', self.name, key_name,
760
+ data=acl_str.encode('UTF-8'),
761
+ query_args=query_args,
762
+ headers=headers)
763
+ body = response.read()
764
+ if response.status != 200:
765
+ raise self.connection.provider.storage_response_error(
766
+ response.status, response.reason, body)
767
+
768
+ def set_acl(self, acl_or_str, key_name='', headers=None, version_id=None):
769
+ if isinstance(acl_or_str, Policy):
770
+ self.set_xml_acl(acl_or_str.to_xml(), key_name,
771
+ headers, version_id)
772
+ else:
773
+ self.set_canned_acl(acl_or_str, key_name,
774
+ headers, version_id)
775
+
776
+ def get_acl(self, key_name='', headers=None, version_id=None):
777
+ query_args = 'acl'
778
+ if version_id:
779
+ query_args += '&versionId=%s' % version_id
780
+ response = self.connection.make_request('GET', self.name, key_name,
781
+ query_args=query_args,
782
+ headers=headers)
783
+ body = response.read()
784
+ if response.status == 200:
785
+ policy = Policy(self)
786
+ h = handler.XmlHandler(policy, self)
787
+ xml.sax.parseString(body, h)
788
+ return policy
789
+ else:
790
+ raise self.connection.provider.storage_response_error(
791
+ response.status, response.reason, body)
792
+
793
+ def set_subresource(self, subresource, value, key_name='', headers=None,
794
+ version_id=None):
795
+ """
796
+ Set a subresource for a bucket or key.
797
+
798
+ :type subresource: string
799
+ :param subresource: The subresource to set.
800
+
801
+ :type value: string
802
+ :param value: The value of the subresource.
803
+
804
+ :type key_name: string
805
+ :param key_name: The key to operate on, or None to operate on the
806
+ bucket.
807
+
808
+ :type headers: dict
809
+ :param headers: Additional HTTP headers to include in the request.
810
+
811
+ :type src_version_id: string
812
+ :param src_version_id: Optional. The version id of the key to
813
+ operate on. If not specified, operate on the newest
814
+ version.
815
+ """
816
+ if not subresource:
817
+ raise TypeError('set_subresource called with subresource=None')
818
+ query_args = subresource
819
+ if version_id:
820
+ query_args += '&versionId=%s' % version_id
821
+ response = self.connection.make_request('PUT', self.name, key_name,
822
+ data=value.encode('UTF-8'),
823
+ query_args=query_args,
824
+ headers=headers)
825
+ body = response.read()
826
+ if response.status != 200:
827
+ raise self.connection.provider.storage_response_error(
828
+ response.status, response.reason, body)
829
+
830
+ def get_subresource(self, subresource, key_name='', headers=None,
831
+ version_id=None):
832
+ """
833
+ Get a subresource for a bucket or key.
834
+
835
+ :type subresource: string
836
+ :param subresource: The subresource to get.
837
+
838
+ :type key_name: string
839
+ :param key_name: The key to operate on, or None to operate on the
840
+ bucket.
841
+
842
+ :type headers: dict
843
+ :param headers: Additional HTTP headers to include in the request.
844
+
845
+ :type src_version_id: string
846
+ :param src_version_id: Optional. The version id of the key to
847
+ operate on. If not specified, operate on the newest
848
+ version.
849
+
850
+ :rtype: string
851
+ :returns: The value of the subresource.
852
+ """
853
+ if not subresource:
854
+ raise TypeError('get_subresource called with subresource=None')
855
+ query_args = subresource
856
+ if version_id:
857
+ query_args += '&versionId=%s' % version_id
858
+ response = self.connection.make_request('GET', self.name, key_name,
859
+ query_args=query_args,
860
+ headers=headers)
861
+ body = response.read()
862
+ if response.status != 200:
863
+ raise self.connection.provider.storage_response_error(
864
+ response.status, response.reason, body)
865
+ return body
866
+
867
+ def make_public(self, recursive=False, headers=None):
868
+ self.set_canned_acl('public-read', headers=headers)
869
+ if recursive:
870
+ for key in self:
871
+ self.set_canned_acl('public-read', key.name, headers=headers)
872
+
873
+ def add_email_grant(self, permission, email_address,
874
+ recursive=False, headers=None):
875
+ """
876
+ Convenience method that provides a quick way to add an email grant
877
+ to a bucket. This method retrieves the current ACL, creates a new
878
+ grant based on the parameters passed in, adds that grant to the ACL
879
+ and then PUT's the new ACL back to S3.
880
+
881
+ :type permission: string
882
+ :param permission: The permission being granted. Should be one of:
883
+ (READ, WRITE, READ_ACP, WRITE_ACP, FULL_CONTROL).
884
+
885
+ :type email_address: string
886
+ :param email_address: The email address associated with the AWS
887
+ account your are granting the permission to.
888
+
889
+ :type recursive: boolean
890
+ :param recursive: A boolean value to controls whether the
891
+ command will apply the grant to all keys within the bucket
892
+ or not. The default value is False. By passing a True
893
+ value, the call will iterate through all keys in the
894
+ bucket and apply the same grant to each key. CAUTION: If
895
+ you have a lot of keys, this could take a long time!
896
+ """
897
+ if permission not in S3Permissions:
898
+ raise self.connection.provider.storage_permissions_error(
899
+ 'Unknown Permission: %s' % permission)
900
+ policy = self.get_acl(headers=headers)
901
+ policy.acl.add_email_grant(permission, email_address)
902
+ self.set_acl(policy, headers=headers)
903
+ if recursive:
904
+ for key in self:
905
+ key.add_email_grant(permission, email_address, headers=headers)
906
+
907
+ def add_user_grant(self, permission, user_id, recursive=False,
908
+ headers=None, display_name=None):
909
+ """
910
+ Convenience method that provides a quick way to add a canonical
911
+ user grant to a bucket. This method retrieves the current ACL,
912
+ creates a new grant based on the parameters passed in, adds that
913
+ grant to the ACL and then PUT's the new ACL back to S3.
914
+
915
+ :type permission: string
916
+ :param permission: The permission being granted. Should be one of:
917
+ (READ, WRITE, READ_ACP, WRITE_ACP, FULL_CONTROL).
918
+
919
+ :type user_id: string
920
+ :param user_id: The canonical user id associated with the AWS
921
+ account your are granting the permission to.
922
+
923
+ :type recursive: boolean
924
+ :param recursive: A boolean value to controls whether the
925
+ command will apply the grant to all keys within the bucket
926
+ or not. The default value is False. By passing a True
927
+ value, the call will iterate through all keys in the
928
+ bucket and apply the same grant to each key. CAUTION: If
929
+ you have a lot of keys, this could take a long time!
930
+
931
+ :type display_name: string
932
+ :param display_name: An option string containing the user's
933
+ Display Name. Only required on Walrus.
934
+ """
935
+ if permission not in S3Permissions:
936
+ raise self.connection.provider.storage_permissions_error(
937
+ 'Unknown Permission: %s' % permission)
938
+ policy = self.get_acl(headers=headers)
939
+ policy.acl.add_user_grant(permission, user_id,
940
+ display_name=display_name)
941
+ self.set_acl(policy, headers=headers)
942
+ if recursive:
943
+ for key in self:
944
+ key.add_user_grant(permission, user_id, headers=headers,
945
+ display_name=display_name)
946
+
947
+ def list_grants(self, headers=None):
948
+ policy = self.get_acl(headers=headers)
949
+ return policy.acl.grants
950
+
951
+ def get_location(self):
952
+ """
953
+ Returns the LocationConstraint for the bucket.
954
+
955
+ :rtype: str
956
+ :return: The LocationConstraint for the bucket or the empty
957
+ string if no constraint was specified when bucket was created.
958
+ """
959
+ response = self.connection.make_request('GET', self.name,
960
+ query_args='location')
961
+ body = response.read()
962
+ if response.status == 200:
963
+ rs = ResultSet(self)
964
+ h = handler.XmlHandler(rs, self)
965
+ xml.sax.parseString(body, h)
966
+ return rs.LocationConstraint
967
+ else:
968
+ raise self.connection.provider.storage_response_error(
969
+ response.status, response.reason, body)
970
+
971
+ def set_xml_logging(self, logging_str, headers=None):
972
+ """
973
+ Set logging on a bucket directly to the given xml string.
974
+
975
+ :type logging_str: unicode string
976
+ :param logging_str: The XML for the bucketloggingstatus which
977
+ will be set. The string will be converted to utf-8 before
978
+ it is sent. Usually, you will obtain this XML from the
979
+ BucketLogging object.
980
+
981
+ :rtype: bool
982
+ :return: True if ok or raises an exception.
983
+ """
984
+ body = logging_str.encode('utf-8')
985
+ response = self.connection.make_request('PUT', self.name, data=body,
986
+ query_args='logging', headers=headers)
987
+ body = response.read()
988
+ if response.status == 200:
989
+ return True
990
+ else:
991
+ raise self.connection.provider.storage_response_error(
992
+ response.status, response.reason, body)
993
+
994
+ def enable_logging(self, target_bucket, target_prefix='',
995
+ grants=None, headers=None):
996
+ """
997
+ Enable logging on a bucket.
998
+
999
+ :type target_bucket: bucket or string
1000
+ :param target_bucket: The bucket to log to.
1001
+
1002
+ :type target_prefix: string
1003
+ :param target_prefix: The prefix which should be prepended to the
1004
+ generated log files written to the target_bucket.
1005
+
1006
+ :type grants: list of Grant objects
1007
+ :param grants: A list of extra permissions which will be granted on
1008
+ the log files which are created.
1009
+
1010
+ :rtype: bool
1011
+ :return: True if ok or raises an exception.
1012
+ """
1013
+ if isinstance(target_bucket, Bucket):
1014
+ target_bucket = target_bucket.name
1015
+ blogging = BucketLogging(target=target_bucket, prefix=target_prefix,
1016
+ grants=grants)
1017
+ return self.set_xml_logging(blogging.to_xml(), headers=headers)
1018
+
1019
+ def disable_logging(self, headers=None):
1020
+ """
1021
+ Disable logging on a bucket.
1022
+
1023
+ :rtype: bool
1024
+ :return: True if ok or raises an exception.
1025
+ """
1026
+ blogging = BucketLogging()
1027
+ return self.set_xml_logging(blogging.to_xml(), headers=headers)
1028
+
1029
+ def get_logging_status(self, headers=None):
1030
+ """
1031
+ Get the logging status for this bucket.
1032
+
1033
+ :rtype: :class:`boto.s3.bucketlogging.BucketLogging`
1034
+ :return: A BucketLogging object for this bucket.
1035
+ """
1036
+ response = self.connection.make_request('GET', self.name,
1037
+ query_args='logging', headers=headers)
1038
+ body = response.read()
1039
+ if response.status == 200:
1040
+ blogging = BucketLogging()
1041
+ h = handler.XmlHandler(blogging, self)
1042
+ xml.sax.parseString(body, h)
1043
+ return blogging
1044
+ else:
1045
+ raise self.connection.provider.storage_response_error(
1046
+ response.status, response.reason, body)
1047
+
1048
+ def set_as_logging_target(self, headers=None):
1049
+ """
1050
+ Setup the current bucket as a logging target by granting the necessary
1051
+ permissions to the LogDelivery group to write log files to this bucket.
1052
+ """
1053
+ policy = self.get_acl(headers=headers)
1054
+ g1 = Grant(permission='WRITE', type='Group', uri=self.LoggingGroup)
1055
+ g2 = Grant(permission='READ_ACP', type='Group', uri=self.LoggingGroup)
1056
+ policy.acl.add_grant(g1)
1057
+ policy.acl.add_grant(g2)
1058
+ self.set_acl(policy, headers=headers)
1059
+
1060
+ def get_request_payment(self, headers=None):
1061
+ response = self.connection.make_request('GET', self.name,
1062
+ query_args='requestPayment', headers=headers)
1063
+ body = response.read()
1064
+ if response.status == 200:
1065
+ return body
1066
+ else:
1067
+ raise self.connection.provider.storage_response_error(
1068
+ response.status, response.reason, body)
1069
+
1070
+ def set_request_payment(self, payer='BucketOwner', headers=None):
1071
+ body = self.BucketPaymentBody % payer
1072
+ response = self.connection.make_request('PUT', self.name, data=body,
1073
+ query_args='requestPayment', headers=headers)
1074
+ body = response.read()
1075
+ if response.status == 200:
1076
+ return True
1077
+ else:
1078
+ raise self.connection.provider.storage_response_error(
1079
+ response.status, response.reason, body)
1080
+
1081
+ def configure_versioning(self, versioning, mfa_delete=False,
1082
+ mfa_token=None, headers=None):
1083
+ """
1084
+ Configure versioning for this bucket.
1085
+
1086
+ ..note:: This feature is currently in beta.
1087
+
1088
+ :type versioning: bool
1089
+ :param versioning: A boolean indicating whether version is
1090
+ enabled (True) or disabled (False).
1091
+
1092
+ :type mfa_delete: bool
1093
+ :param mfa_delete: A boolean indicating whether the
1094
+ Multi-Factor Authentication Delete feature is enabled
1095
+ (True) or disabled (False). If mfa_delete is enabled then
1096
+ all Delete operations will require the token from your MFA
1097
+ device to be passed in the request.
1098
+
1099
+ :type mfa_token: tuple or list of strings
1100
+ :param mfa_token: A tuple or list consisting of the serial
1101
+ number from the MFA device and the current value of the
1102
+ six-digit token associated with the device. This value is
1103
+ required when you are changing the status of the MfaDelete
1104
+ property of the bucket.
1105
+ """
1106
+ if versioning:
1107
+ ver = 'Enabled'
1108
+ else:
1109
+ ver = 'Suspended'
1110
+ if mfa_delete:
1111
+ mfa = 'Enabled'
1112
+ else:
1113
+ mfa = 'Disabled'
1114
+ body = self.VersioningBody % (ver, mfa)
1115
+ if mfa_token:
1116
+ if not headers:
1117
+ headers = {}
1118
+ provider = self.connection.provider
1119
+ headers[provider.mfa_header] = ' '.join(mfa_token)
1120
+ response = self.connection.make_request('PUT', self.name, data=body,
1121
+ query_args='versioning', headers=headers)
1122
+ body = response.read()
1123
+ if response.status == 200:
1124
+ return True
1125
+ else:
1126
+ raise self.connection.provider.storage_response_error(
1127
+ response.status, response.reason, body)
1128
+
1129
+ def get_versioning_status(self, headers=None):
1130
+ """
1131
+ Returns the current status of versioning on the bucket.
1132
+
1133
+ :rtype: dict
1134
+ :returns: A dictionary containing a key named 'Versioning'
1135
+ that can have a value of either Enabled, Disabled, or
1136
+ Suspended. Also, if MFADelete has ever been enabled on the
1137
+ bucket, the dictionary will contain a key named
1138
+ 'MFADelete' which will have a value of either Enabled or
1139
+ Suspended.
1140
+ """
1141
+ response = self.connection.make_request('GET', self.name,
1142
+ query_args='versioning', headers=headers)
1143
+ body = response.read()
1144
+ boto.log.debug(body)
1145
+ if response.status == 200:
1146
+ d = {}
1147
+ ver = re.search(self.VersionRE, body)
1148
+ if ver:
1149
+ d['Versioning'] = ver.group(1)
1150
+ mfa = re.search(self.MFADeleteRE, body)
1151
+ if mfa:
1152
+ d['MfaDelete'] = mfa.group(1)
1153
+ return d
1154
+ else:
1155
+ raise self.connection.provider.storage_response_error(
1156
+ response.status, response.reason, body)
1157
+
1158
+ def configure_lifecycle(self, lifecycle_config, headers=None):
1159
+ """
1160
+ Configure lifecycle for this bucket.
1161
+
1162
+ :type lifecycle_config: :class:`boto.s3.lifecycle.Lifecycle`
1163
+ :param lifecycle_config: The lifecycle configuration you want
1164
+ to configure for this bucket.
1165
+ """
1166
+ xml = lifecycle_config.to_xml()
1167
+ xml = xml.encode('utf-8')
1168
+ fp = StringIO.StringIO(xml)
1169
+ md5 = boto.utils.compute_md5(fp)
1170
+ if headers is None:
1171
+ headers = {}
1172
+ headers['Content-MD5'] = md5[1]
1173
+ headers['Content-Type'] = 'text/xml'
1174
+ response = self.connection.make_request('PUT', self.name,
1175
+ data=fp.getvalue(),
1176
+ query_args='lifecycle',
1177
+ headers=headers)
1178
+ body = response.read()
1179
+ if response.status == 200:
1180
+ return True
1181
+ else:
1182
+ raise self.connection.provider.storage_response_error(
1183
+ response.status, response.reason, body)
1184
+
1185
+ def get_lifecycle_config(self, headers=None):
1186
+ """
1187
+ Returns the current lifecycle configuration on the bucket.
1188
+
1189
+ :rtype: :class:`boto.s3.lifecycle.Lifecycle`
1190
+ :returns: A LifecycleConfig object that describes all current
1191
+ lifecycle rules in effect for the bucket.
1192
+ """
1193
+ response = self.connection.make_request('GET', self.name,
1194
+ query_args='lifecycle', headers=headers)
1195
+ body = response.read()
1196
+ boto.log.debug(body)
1197
+ if response.status == 200:
1198
+ lifecycle = Lifecycle()
1199
+ h = handler.XmlHandler(lifecycle, self)
1200
+ xml.sax.parseString(body, h)
1201
+ return lifecycle
1202
+ else:
1203
+ raise self.connection.provider.storage_response_error(
1204
+ response.status, response.reason, body)
1205
+
1206
+ def delete_lifecycle_configuration(self, headers=None):
1207
+ """
1208
+ Removes all lifecycle configuration from the bucket.
1209
+ """
1210
+ response = self.connection.make_request('DELETE', self.name,
1211
+ query_args='lifecycle',
1212
+ headers=headers)
1213
+ body = response.read()
1214
+ boto.log.debug(body)
1215
+ if response.status == 204:
1216
+ return True
1217
+ else:
1218
+ raise self.connection.provider.storage_response_error(
1219
+ response.status, response.reason, body)
1220
+
1221
+ def configure_website(self, suffix=None, error_key=None,
1222
+ redirect_all_requests_to=None,
1223
+ routing_rules=None,
1224
+ headers=None):
1225
+ """
1226
+ Configure this bucket to act as a website
1227
+
1228
+ :type suffix: str
1229
+ :param suffix: Suffix that is appended to a request that is for a
1230
+ "directory" on the website endpoint (e.g. if the suffix is
1231
+ index.html and you make a request to samplebucket/images/
1232
+ the data that is returned will be for the object with the
1233
+ key name images/index.html). The suffix must not be empty
1234
+ and must not include a slash character.
1235
+
1236
+ :type error_key: str
1237
+ :param error_key: The object key name to use when a 4XX class
1238
+ error occurs. This is optional.
1239
+
1240
+ :type redirect_all_requests_to: :class:`boto.s3.website.RedirectLocation`
1241
+ :param redirect_all_requests_to: Describes the redirect behavior for
1242
+ every request to this bucket's website endpoint. If this value is
1243
+ non None, no other values are considered when configuring the
1244
+ website configuration for the bucket. This is an instance of
1245
+ ``RedirectLocation``.
1246
+
1247
+ :type routing_rules: :class:`boto.s3.website.RoutingRules`
1248
+ :param routing_rules: Object which specifies conditions
1249
+ and redirects that apply when the conditions are met.
1250
+
1251
+ """
1252
+ config = website.WebsiteConfiguration(
1253
+ suffix, error_key, redirect_all_requests_to,
1254
+ routing_rules)
1255
+ body = config.to_xml()
1256
+ response = self.connection.make_request('PUT', self.name, data=body,
1257
+ query_args='website',
1258
+ headers=headers)
1259
+ body = response.read()
1260
+ if response.status == 200:
1261
+ return True
1262
+ else:
1263
+ raise self.connection.provider.storage_response_error(
1264
+ response.status, response.reason, body)
1265
+
1266
+ def get_website_configuration(self, headers=None):
1267
+ """
1268
+ Returns the current status of website configuration on the bucket.
1269
+
1270
+ :rtype: dict
1271
+ :returns: A dictionary containing a Python representation
1272
+ of the XML response from S3. The overall structure is:
1273
+
1274
+ * WebsiteConfiguration
1275
+
1276
+ * IndexDocument
1277
+
1278
+ * Suffix : suffix that is appended to request that
1279
+ is for a "directory" on the website endpoint
1280
+ * ErrorDocument
1281
+
1282
+ * Key : name of object to serve when an error occurs
1283
+ """
1284
+ return self.get_website_configuration_with_xml(headers)[0]
1285
+
1286
+ def get_website_configuration_with_xml(self, headers=None):
1287
+ """
1288
+ Returns the current status of website configuration on the bucket as
1289
+ unparsed XML.
1290
+
1291
+ :rtype: 2-Tuple
1292
+ :returns: 2-tuple containing:
1293
+ 1) A dictionary containing a Python representation
1294
+ of the XML response. The overall structure is:
1295
+ * WebsiteConfiguration
1296
+ * IndexDocument
1297
+ * Suffix : suffix that is appended to request that
1298
+ is for a "directory" on the website endpoint
1299
+ * ErrorDocument
1300
+ * Key : name of object to serve when an error occurs
1301
+ 2) unparsed XML describing the bucket's website configuration.
1302
+ """
1303
+ response = self.connection.make_request('GET', self.name,
1304
+ query_args='website', headers=headers)
1305
+ body = response.read()
1306
+ boto.log.debug(body)
1307
+
1308
+ if response.status != 200:
1309
+ raise self.connection.provider.storage_response_error(
1310
+ response.status, response.reason, body)
1311
+
1312
+ e = boto.jsonresponse.Element()
1313
+ h = boto.jsonresponse.XmlHandler(e, None)
1314
+ h.parse(body)
1315
+ return e, body
1316
+
1317
+ def delete_website_configuration(self, headers=None):
1318
+ """
1319
+ Removes all website configuration from the bucket.
1320
+ """
1321
+ response = self.connection.make_request('DELETE', self.name,
1322
+ query_args='website', headers=headers)
1323
+ body = response.read()
1324
+ boto.log.debug(body)
1325
+ if response.status == 204:
1326
+ return True
1327
+ else:
1328
+ raise self.connection.provider.storage_response_error(
1329
+ response.status, response.reason, body)
1330
+
1331
+ def get_website_endpoint(self):
1332
+ """
1333
+ Returns the fully qualified hostname to use is you want to access this
1334
+ bucket as a website. This doesn't validate whether the bucket has
1335
+ been correctly configured as a website or not.
1336
+ """
1337
+ l = [self.name]
1338
+ l.append(S3WebsiteEndpointTranslate.translate_region(self.get_location()))
1339
+ l.append('.'.join(self.connection.host.split('.')[-2:]))
1340
+ return '.'.join(l)
1341
+
1342
+ def get_policy(self, headers=None):
1343
+ """
1344
+ Returns the JSON policy associated with the bucket. The policy
1345
+ is returned as an uninterpreted JSON string.
1346
+ """
1347
+ response = self.connection.make_request('GET', self.name,
1348
+ query_args='policy', headers=headers)
1349
+ body = response.read()
1350
+ if response.status == 200:
1351
+ return body
1352
+ else:
1353
+ raise self.connection.provider.storage_response_error(
1354
+ response.status, response.reason, body)
1355
+
1356
+ def set_policy(self, policy, headers=None):
1357
+ """
1358
+ Add or replace the JSON policy associated with the bucket.
1359
+
1360
+ :type policy: str
1361
+ :param policy: The JSON policy as a string.
1362
+ """
1363
+ response = self.connection.make_request('PUT', self.name,
1364
+ data=policy,
1365
+ query_args='policy',
1366
+ headers=headers)
1367
+ body = response.read()
1368
+ if response.status >= 200 and response.status <= 204:
1369
+ return True
1370
+ else:
1371
+ raise self.connection.provider.storage_response_error(
1372
+ response.status, response.reason, body)
1373
+
1374
+ def delete_policy(self, headers=None):
1375
+ response = self.connection.make_request('DELETE', self.name,
1376
+ data='/?policy',
1377
+ query_args='policy',
1378
+ headers=headers)
1379
+ body = response.read()
1380
+ if response.status >= 200 and response.status <= 204:
1381
+ return True
1382
+ else:
1383
+ raise self.connection.provider.storage_response_error(
1384
+ response.status, response.reason, body)
1385
+
1386
+ def set_cors_xml(self, cors_xml, headers=None):
1387
+ """
1388
+ Set the CORS (Cross-Origin Resource Sharing) for a bucket.
1389
+
1390
+ :type cors_xml: str
1391
+ :param cors_xml: The XML document describing your desired
1392
+ CORS configuration. See the S3 documentation for details
1393
+ of the exact syntax required.
1394
+ """
1395
+ fp = StringIO.StringIO(cors_xml)
1396
+ md5 = boto.utils.compute_md5(fp)
1397
+ if headers is None:
1398
+ headers = {}
1399
+ headers['Content-MD5'] = md5[1]
1400
+ headers['Content-Type'] = 'text/xml'
1401
+ response = self.connection.make_request('PUT', self.name,
1402
+ data=fp.getvalue(),
1403
+ query_args='cors',
1404
+ headers=headers)
1405
+ body = response.read()
1406
+ if response.status == 200:
1407
+ return True
1408
+ else:
1409
+ raise self.connection.provider.storage_response_error(
1410
+ response.status, response.reason, body)
1411
+
1412
+ def set_cors(self, cors_config, headers=None):
1413
+ """
1414
+ Set the CORS for this bucket given a boto CORSConfiguration
1415
+ object.
1416
+
1417
+ :type cors_config: :class:`boto.s3.cors.CORSConfiguration`
1418
+ :param cors_config: The CORS configuration you want
1419
+ to configure for this bucket.
1420
+ """
1421
+ return self.set_cors_xml(cors_config.to_xml())
1422
+
1423
+ def get_cors_xml(self, headers=None):
1424
+ """
1425
+ Returns the current CORS configuration on the bucket as an
1426
+ XML document.
1427
+ """
1428
+ response = self.connection.make_request('GET', self.name,
1429
+ query_args='cors', headers=headers)
1430
+ body = response.read()
1431
+ boto.log.debug(body)
1432
+ if response.status == 200:
1433
+ return body
1434
+ else:
1435
+ raise self.connection.provider.storage_response_error(
1436
+ response.status, response.reason, body)
1437
+
1438
+ def get_cors(self, headers=None):
1439
+ """
1440
+ Returns the current CORS configuration on the bucket.
1441
+
1442
+ :rtype: :class:`boto.s3.cors.CORSConfiguration`
1443
+ :returns: A CORSConfiguration object that describes all current
1444
+ CORS rules in effect for the bucket.
1445
+ """
1446
+ body = self.get_cors_xml(headers)
1447
+ cors = CORSConfiguration()
1448
+ h = handler.XmlHandler(cors, self)
1449
+ xml.sax.parseString(body, h)
1450
+ return cors
1451
+
1452
+ def delete_cors(self, headers=None):
1453
+ """
1454
+ Removes all CORS configuration from the bucket.
1455
+ """
1456
+ response = self.connection.make_request('DELETE', self.name,
1457
+ query_args='cors',
1458
+ headers=headers)
1459
+ body = response.read()
1460
+ boto.log.debug(body)
1461
+ if response.status == 204:
1462
+ return True
1463
+ else:
1464
+ raise self.connection.provider.storage_response_error(
1465
+ response.status, response.reason, body)
1466
+
1467
+ def initiate_multipart_upload(self, key_name, headers=None,
1468
+ reduced_redundancy=False,
1469
+ metadata=None, encrypt_key=False,
1470
+ policy=None):
1471
+ """
1472
+ Start a multipart upload operation.
1473
+
1474
+ :type key_name: string
1475
+ :param key_name: The name of the key that will ultimately
1476
+ result from this multipart upload operation. This will be
1477
+ exactly as the key appears in the bucket after the upload
1478
+ process has been completed.
1479
+
1480
+ :type headers: dict
1481
+ :param headers: Additional HTTP headers to send and store with the
1482
+ resulting key in S3.
1483
+
1484
+ :type reduced_redundancy: boolean
1485
+ :param reduced_redundancy: In multipart uploads, the storage
1486
+ class is specified when initiating the upload, not when
1487
+ uploading individual parts. So if you want the resulting
1488
+ key to use the reduced redundancy storage class set this
1489
+ flag when you initiate the upload.
1490
+
1491
+ :type metadata: dict
1492
+ :param metadata: Any metadata that you would like to set on the key
1493
+ that results from the multipart upload.
1494
+
1495
+ :type encrypt_key: bool
1496
+ :param encrypt_key: If True, the new copy of the object will
1497
+ be encrypted on the server-side by S3 and will be stored
1498
+ in an encrypted form while at rest in S3.
1499
+
1500
+ :type policy: :class:`boto.s3.acl.CannedACLStrings`
1501
+ :param policy: A canned ACL policy that will be applied to the
1502
+ new key (once completed) in S3.
1503
+ """
1504
+ query_args = 'uploads'
1505
+ provider = self.connection.provider
1506
+ headers = headers or {}
1507
+ if policy:
1508
+ headers[provider.acl_header] = policy
1509
+ if reduced_redundancy:
1510
+ storage_class_header = provider.storage_class_header
1511
+ if storage_class_header:
1512
+ headers[storage_class_header] = 'REDUCED_REDUNDANCY'
1513
+ # TODO: what if the provider doesn't support reduced redundancy?
1514
+ # (see boto.s3.key.Key.set_contents_from_file)
1515
+ if encrypt_key:
1516
+ headers[provider.server_side_encryption_header] = 'AES256'
1517
+ if metadata is None:
1518
+ metadata = {}
1519
+
1520
+ headers = boto.utils.merge_meta(headers, metadata,
1521
+ self.connection.provider)
1522
+ response = self.connection.make_request('POST', self.name, key_name,
1523
+ query_args=query_args,
1524
+ headers=headers)
1525
+ body = response.read()
1526
+ boto.log.debug(body)
1527
+ if response.status == 200:
1528
+ resp = MultiPartUpload(self)
1529
+ h = handler.XmlHandler(resp, self)
1530
+ xml.sax.parseString(body, h)
1531
+ return resp
1532
+ else:
1533
+ raise self.connection.provider.storage_response_error(
1534
+ response.status, response.reason, body)
1535
+
1536
+ def complete_multipart_upload(self, key_name, upload_id,
1537
+ xml_body, headers=None):
1538
+ """
1539
+ Complete a multipart upload operation.
1540
+ """
1541
+ query_args = 'uploadId=%s' % upload_id
1542
+ if headers is None:
1543
+ headers = {}
1544
+ headers['Content-Type'] = 'text/xml'
1545
+ response = self.connection.make_request('POST', self.name, key_name,
1546
+ query_args=query_args,
1547
+ headers=headers, data=xml_body)
1548
+ contains_error = False
1549
+ body = response.read()
1550
+ # Some errors will be reported in the body of the response
1551
+ # even though the HTTP response code is 200. This check
1552
+ # does a quick and dirty peek in the body for an error element.
1553
+ if body.find('<Error>') > 0:
1554
+ contains_error = True
1555
+ boto.log.debug(body)
1556
+ if response.status == 200 and not contains_error:
1557
+ resp = CompleteMultiPartUpload(self)
1558
+ h = handler.XmlHandler(resp, self)
1559
+ xml.sax.parseString(body, h)
1560
+ # Use a dummy key to parse various response headers
1561
+ # for versioning, encryption info and then explicitly
1562
+ # set the completed MPU object values from key.
1563
+ k = self.key_class(self)
1564
+ k.handle_version_headers(response)
1565
+ k.handle_encryption_headers(response)
1566
+ resp.version_id = k.version_id
1567
+ resp.encrypted = k.encrypted
1568
+ return resp
1569
+ else:
1570
+ raise self.connection.provider.storage_response_error(
1571
+ response.status, response.reason, body)
1572
+
1573
+ def cancel_multipart_upload(self, key_name, upload_id, headers=None):
1574
+ query_args = 'uploadId=%s' % upload_id
1575
+ response = self.connection.make_request('DELETE', self.name, key_name,
1576
+ query_args=query_args,
1577
+ headers=headers)
1578
+ body = response.read()
1579
+ boto.log.debug(body)
1580
+ if response.status != 204:
1581
+ raise self.connection.provider.storage_response_error(
1582
+ response.status, response.reason, body)
1583
+
1584
+ def delete(self, headers=None):
1585
+ return self.connection.delete_bucket(self.name, headers=headers)
1586
+
1587
+ def get_tags(self):
1588
+ response = self.get_xml_tags()
1589
+ tags = Tags()
1590
+ h = handler.XmlHandler(tags, self)
1591
+ xml.sax.parseString(response, h)
1592
+ return tags
1593
+
1594
+ def get_xml_tags(self):
1595
+ response = self.connection.make_request('GET', self.name,
1596
+ query_args='tagging',
1597
+ headers=None)
1598
+ body = response.read()
1599
+ if response.status == 200:
1600
+ return body
1601
+ else:
1602
+ raise self.connection.provider.storage_response_error(
1603
+ response.status, response.reason, body)
1604
+
1605
+ def set_xml_tags(self, tag_str, headers=None, query_args='tagging'):
1606
+ if headers is None:
1607
+ headers = {}
1608
+ md5 = boto.utils.compute_md5(StringIO.StringIO(tag_str))
1609
+ headers['Content-MD5'] = md5[1]
1610
+ headers['Content-Type'] = 'text/xml'
1611
+ response = self.connection.make_request('PUT', self.name,
1612
+ data=tag_str.encode('utf-8'),
1613
+ query_args=query_args,
1614
+ headers=headers)
1615
+ body = response.read()
1616
+ if response.status != 204:
1617
+ raise self.connection.provider.storage_response_error(
1618
+ response.status, response.reason, body)
1619
+ return True
1620
+
1621
+ def set_tags(self, tags, headers=None):
1622
+ return self.set_xml_tags(tags.to_xml(), headers=headers)
1623
+
1624
+ def delete_tags(self, headers=None):
1625
+ response = self.connection.make_request('DELETE', self.name,
1626
+ query_args='tagging',
1627
+ headers=headers)
1628
+ body = response.read()
1629
+ boto.log.debug(body)
1630
+ if response.status == 204:
1631
+ return True
1632
+ else:
1633
+ raise self.connection.provider.storage_response_error(
1634
+ response.status, response.reason, body)