aws-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. data/.yardopts +6 -0
  2. data/LICENSE.txt +171 -0
  3. data/NOTICE.txt +2 -0
  4. data/README.rdoc +189 -0
  5. data/lib/aws-sdk.rb +14 -0
  6. data/lib/aws.rb +63 -0
  7. data/lib/aws/api_config.rb +45 -0
  8. data/lib/aws/api_config/.document +0 -0
  9. data/lib/aws/api_config/EC2-2011-02-28.yml +2314 -0
  10. data/lib/aws/api_config/SNS-2010-03-31.yml +171 -0
  11. data/lib/aws/api_config/SQS-2009-02-01.yml +161 -0
  12. data/lib/aws/api_config/SimpleDB-2009-04-15.yml +278 -0
  13. data/lib/aws/api_config/SimpleEmailService-2010-12-01.yml +147 -0
  14. data/lib/aws/api_config_transform.rb +32 -0
  15. data/lib/aws/async_handle.rb +90 -0
  16. data/lib/aws/authorize_v2.rb +37 -0
  17. data/lib/aws/authorize_v3.rb +37 -0
  18. data/lib/aws/base_client.rb +524 -0
  19. data/lib/aws/cacheable.rb +92 -0
  20. data/lib/aws/common.rb +228 -0
  21. data/lib/aws/configurable.rb +36 -0
  22. data/lib/aws/configuration.rb +272 -0
  23. data/lib/aws/configured_client_methods.rb +81 -0
  24. data/lib/aws/configured_grammars.rb +65 -0
  25. data/lib/aws/configured_option_grammars.rb +46 -0
  26. data/lib/aws/configured_xml_grammars.rb +47 -0
  27. data/lib/aws/default_signer.rb +38 -0
  28. data/lib/aws/ec2.rb +321 -0
  29. data/lib/aws/ec2/attachment.rb +149 -0
  30. data/lib/aws/ec2/attachment_collection.rb +57 -0
  31. data/lib/aws/ec2/availability_zone.rb +80 -0
  32. data/lib/aws/ec2/availability_zone_collection.rb +47 -0
  33. data/lib/aws/ec2/block_device_mappings.rb +53 -0
  34. data/lib/aws/ec2/client.rb +54 -0
  35. data/lib/aws/ec2/client/xml.rb +127 -0
  36. data/lib/aws/ec2/collection.rb +39 -0
  37. data/lib/aws/ec2/config_transform.rb +63 -0
  38. data/lib/aws/ec2/elastic_ip.rb +107 -0
  39. data/lib/aws/ec2/elastic_ip_collection.rb +85 -0
  40. data/lib/aws/ec2/errors.rb +29 -0
  41. data/lib/aws/ec2/filtered_collection.rb +65 -0
  42. data/lib/aws/ec2/has_permissions.rb +46 -0
  43. data/lib/aws/ec2/image.rb +245 -0
  44. data/lib/aws/ec2/image_collection.rb +235 -0
  45. data/lib/aws/ec2/instance.rb +515 -0
  46. data/lib/aws/ec2/instance_collection.rb +276 -0
  47. data/lib/aws/ec2/key_pair.rb +86 -0
  48. data/lib/aws/ec2/key_pair_collection.rb +102 -0
  49. data/lib/aws/ec2/permission_collection.rb +177 -0
  50. data/lib/aws/ec2/region.rb +81 -0
  51. data/lib/aws/ec2/region_collection.rb +55 -0
  52. data/lib/aws/ec2/request.rb +27 -0
  53. data/lib/aws/ec2/reserved_instances.rb +50 -0
  54. data/lib/aws/ec2/reserved_instances_collection.rb +44 -0
  55. data/lib/aws/ec2/reserved_instances_offering.rb +55 -0
  56. data/lib/aws/ec2/reserved_instances_offering_collection.rb +43 -0
  57. data/lib/aws/ec2/resource.rb +340 -0
  58. data/lib/aws/ec2/resource_tag_collection.rb +218 -0
  59. data/lib/aws/ec2/security_group.rb +246 -0
  60. data/lib/aws/ec2/security_group/ip_permission.rb +70 -0
  61. data/lib/aws/ec2/security_group/ip_permission_collection.rb +59 -0
  62. data/lib/aws/ec2/security_group_collection.rb +132 -0
  63. data/lib/aws/ec2/snapshot.rb +138 -0
  64. data/lib/aws/ec2/snapshot_collection.rb +90 -0
  65. data/lib/aws/ec2/tag.rb +88 -0
  66. data/lib/aws/ec2/tag_collection.rb +114 -0
  67. data/lib/aws/ec2/tagged_collection.rb +48 -0
  68. data/lib/aws/ec2/tagged_item.rb +87 -0
  69. data/lib/aws/ec2/volume.rb +190 -0
  70. data/lib/aws/ec2/volume_collection.rb +95 -0
  71. data/lib/aws/errors.rb +129 -0
  72. data/lib/aws/http/builtin_handler.rb +69 -0
  73. data/lib/aws/http/curb_handler.rb +123 -0
  74. data/lib/aws/http/handler.rb +77 -0
  75. data/lib/aws/http/httparty_handler.rb +61 -0
  76. data/lib/aws/http/request.rb +136 -0
  77. data/lib/aws/http/request_param.rb +63 -0
  78. data/lib/aws/http/response.rb +75 -0
  79. data/lib/aws/ignore_result_element.rb +38 -0
  80. data/lib/aws/indifferent_hash.rb +86 -0
  81. data/lib/aws/inflection.rb +46 -0
  82. data/lib/aws/lazy_error_classes.rb +64 -0
  83. data/lib/aws/meta_utils.rb +43 -0
  84. data/lib/aws/model.rb +57 -0
  85. data/lib/aws/naming.rb +32 -0
  86. data/lib/aws/option_grammar.rb +544 -0
  87. data/lib/aws/policy.rb +912 -0
  88. data/lib/aws/rails.rb +209 -0
  89. data/lib/aws/record.rb +79 -0
  90. data/lib/aws/record/attribute.rb +94 -0
  91. data/lib/aws/record/attribute_macros.rb +288 -0
  92. data/lib/aws/record/attributes/boolean.rb +49 -0
  93. data/lib/aws/record/attributes/datetime.rb +86 -0
  94. data/lib/aws/record/attributes/float.rb +48 -0
  95. data/lib/aws/record/attributes/integer.rb +68 -0
  96. data/lib/aws/record/attributes/sortable_float.rb +60 -0
  97. data/lib/aws/record/attributes/sortable_integer.rb +95 -0
  98. data/lib/aws/record/attributes/string.rb +69 -0
  99. data/lib/aws/record/base.rb +728 -0
  100. data/lib/aws/record/conversion.rb +38 -0
  101. data/lib/aws/record/dirty_tracking.rb +286 -0
  102. data/lib/aws/record/errors.rb +153 -0
  103. data/lib/aws/record/exceptions.rb +48 -0
  104. data/lib/aws/record/finder_methods.rb +262 -0
  105. data/lib/aws/record/naming.rb +31 -0
  106. data/lib/aws/record/scope.rb +157 -0
  107. data/lib/aws/record/validations.rb +653 -0
  108. data/lib/aws/record/validator.rb +237 -0
  109. data/lib/aws/record/validators/acceptance.rb +51 -0
  110. data/lib/aws/record/validators/block.rb +38 -0
  111. data/lib/aws/record/validators/confirmation.rb +43 -0
  112. data/lib/aws/record/validators/count.rb +108 -0
  113. data/lib/aws/record/validators/exclusion.rb +43 -0
  114. data/lib/aws/record/validators/format.rb +57 -0
  115. data/lib/aws/record/validators/inclusion.rb +56 -0
  116. data/lib/aws/record/validators/length.rb +107 -0
  117. data/lib/aws/record/validators/numericality.rb +138 -0
  118. data/lib/aws/record/validators/presence.rb +45 -0
  119. data/lib/aws/resource_cache.rb +39 -0
  120. data/lib/aws/response.rb +113 -0
  121. data/lib/aws/response_cache.rb +50 -0
  122. data/lib/aws/s3.rb +109 -0
  123. data/lib/aws/s3/access_control_list.rb +252 -0
  124. data/lib/aws/s3/acl_object.rb +266 -0
  125. data/lib/aws/s3/bucket.rb +320 -0
  126. data/lib/aws/s3/bucket_collection.rb +122 -0
  127. data/lib/aws/s3/bucket_version_collection.rb +85 -0
  128. data/lib/aws/s3/client.rb +999 -0
  129. data/lib/aws/s3/client/xml.rb +190 -0
  130. data/lib/aws/s3/data_options.rb +99 -0
  131. data/lib/aws/s3/errors.rb +43 -0
  132. data/lib/aws/s3/multipart_upload.rb +318 -0
  133. data/lib/aws/s3/multipart_upload_collection.rb +78 -0
  134. data/lib/aws/s3/object_collection.rb +159 -0
  135. data/lib/aws/s3/object_metadata.rb +67 -0
  136. data/lib/aws/s3/object_upload_collection.rb +83 -0
  137. data/lib/aws/s3/object_version.rb +141 -0
  138. data/lib/aws/s3/object_version_collection.rb +78 -0
  139. data/lib/aws/s3/paginated_collection.rb +94 -0
  140. data/lib/aws/s3/policy.rb +76 -0
  141. data/lib/aws/s3/prefix_and_delimiter_collection.rb +56 -0
  142. data/lib/aws/s3/prefixed_collection.rb +84 -0
  143. data/lib/aws/s3/presigned_post.rb +504 -0
  144. data/lib/aws/s3/request.rb +198 -0
  145. data/lib/aws/s3/s3_object.rb +794 -0
  146. data/lib/aws/s3/tree.rb +116 -0
  147. data/lib/aws/s3/tree/branch_node.rb +71 -0
  148. data/lib/aws/s3/tree/child_collection.rb +108 -0
  149. data/lib/aws/s3/tree/leaf_node.rb +99 -0
  150. data/lib/aws/s3/tree/node.rb +22 -0
  151. data/lib/aws/s3/tree/parent.rb +90 -0
  152. data/lib/aws/s3/uploaded_part.rb +82 -0
  153. data/lib/aws/s3/uploaded_part_collection.rb +86 -0
  154. data/lib/aws/service_interface.rb +60 -0
  155. data/lib/aws/simple_db.rb +202 -0
  156. data/lib/aws/simple_db/attribute.rb +159 -0
  157. data/lib/aws/simple_db/attribute_collection.rb +227 -0
  158. data/lib/aws/simple_db/client.rb +52 -0
  159. data/lib/aws/simple_db/client/options.rb +34 -0
  160. data/lib/aws/simple_db/client/xml.rb +68 -0
  161. data/lib/aws/simple_db/consistent_read_option.rb +42 -0
  162. data/lib/aws/simple_db/delete_attributes.rb +64 -0
  163. data/lib/aws/simple_db/domain.rb +118 -0
  164. data/lib/aws/simple_db/domain_collection.rb +116 -0
  165. data/lib/aws/simple_db/domain_metadata.rb +112 -0
  166. data/lib/aws/simple_db/errors.rb +46 -0
  167. data/lib/aws/simple_db/expect_condition_option.rb +45 -0
  168. data/lib/aws/simple_db/item.rb +84 -0
  169. data/lib/aws/simple_db/item_collection.rb +594 -0
  170. data/lib/aws/simple_db/item_data.rb +70 -0
  171. data/lib/aws/simple_db/put_attributes.rb +62 -0
  172. data/lib/aws/simple_db/request.rb +27 -0
  173. data/lib/aws/simple_email_service.rb +373 -0
  174. data/lib/aws/simple_email_service/client.rb +39 -0
  175. data/lib/aws/simple_email_service/client/options.rb +24 -0
  176. data/lib/aws/simple_email_service/client/xml.rb +38 -0
  177. data/lib/aws/simple_email_service/email_address_collection.rb +66 -0
  178. data/lib/aws/simple_email_service/errors.rb +29 -0
  179. data/lib/aws/simple_email_service/quotas.rb +64 -0
  180. data/lib/aws/simple_email_service/request.rb +27 -0
  181. data/lib/aws/sns.rb +69 -0
  182. data/lib/aws/sns/client.rb +37 -0
  183. data/lib/aws/sns/client/options.rb +24 -0
  184. data/lib/aws/sns/client/xml.rb +38 -0
  185. data/lib/aws/sns/errors.rb +29 -0
  186. data/lib/aws/sns/policy.rb +49 -0
  187. data/lib/aws/sns/request.rb +27 -0
  188. data/lib/aws/sns/subscription.rb +100 -0
  189. data/lib/aws/sns/subscription_collection.rb +84 -0
  190. data/lib/aws/sns/topic.rb +384 -0
  191. data/lib/aws/sns/topic_collection.rb +70 -0
  192. data/lib/aws/sns/topic_subscription_collection.rb +58 -0
  193. data/lib/aws/sqs.rb +70 -0
  194. data/lib/aws/sqs/client.rb +38 -0
  195. data/lib/aws/sqs/client/xml.rb +36 -0
  196. data/lib/aws/sqs/errors.rb +33 -0
  197. data/lib/aws/sqs/policy.rb +50 -0
  198. data/lib/aws/sqs/queue.rb +507 -0
  199. data/lib/aws/sqs/queue_collection.rb +105 -0
  200. data/lib/aws/sqs/received_message.rb +184 -0
  201. data/lib/aws/sqs/received_sns_message.rb +112 -0
  202. data/lib/aws/sqs/request.rb +44 -0
  203. data/lib/aws/xml_grammar.rb +923 -0
  204. data/rails/init.rb +15 -0
  205. metadata +298 -0
@@ -0,0 +1,147 @@
1
+ # Copyright 2011 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ # http://aws.amazon.com/apache2.0/
8
+ #
9
+ # or in the "license" file accompanying this file. This file is
10
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
+ # ANY KIND, either express or implied. See the License for the specific
12
+ # language governing permissions and limitations under the License.
13
+
14
+ ---
15
+ :operations:
16
+ SendEmail:
17
+ :input:
18
+ Source:
19
+ - :string
20
+ - :required
21
+ Destination:
22
+ - :structure:
23
+ ToAddresses:
24
+ - :list:
25
+ - :string
26
+ CcAddresses:
27
+ - :list:
28
+ - :string
29
+ BccAddresses:
30
+ - :list:
31
+ - :string
32
+ - :required
33
+ Message:
34
+ - :structure:
35
+ Subject:
36
+ - :structure:
37
+ Data:
38
+ - :string
39
+ - :required
40
+ Charset:
41
+ - :string
42
+ - :required
43
+ Body:
44
+ - :structure:
45
+ Text:
46
+ - :structure:
47
+ Data:
48
+ - :string
49
+ - :required
50
+ Charset:
51
+ - :string
52
+ Html:
53
+ - :structure:
54
+ Data:
55
+ - :string
56
+ - :required
57
+ Charset:
58
+ - :string
59
+ - :required
60
+ - :required
61
+ ReplyToAddresses:
62
+ - :list:
63
+ - :string
64
+ ReturnPath:
65
+ - :string
66
+ :output: []
67
+
68
+ SendRawEmail:
69
+ :input:
70
+ Source:
71
+ - :string
72
+ Destinations:
73
+ - :list:
74
+ - :string
75
+ RawMessage:
76
+ - :structure:
77
+ Data:
78
+ - :blob
79
+ - :required
80
+ - :required
81
+ :output: []
82
+
83
+ GetSendStatistics:
84
+ :input: {}
85
+
86
+ :output:
87
+ - SendDataPoints:
88
+ - :list: member
89
+ - member:
90
+ - Timestamp:
91
+ - :timestamp
92
+ - DeliveryAttempts:
93
+ - :long
94
+ - Bounces:
95
+ - :long
96
+ - Complaints:
97
+ - :long
98
+ - Rejects:
99
+ - :long
100
+ GetSendQuota:
101
+ :input: {}
102
+
103
+ :output:
104
+ - Max24HourSend:
105
+ - :float
106
+ - MaxSendRate:
107
+ - :float
108
+ - SentLast24Hours:
109
+ - :float
110
+ VerifyEmailAddress:
111
+ :input:
112
+ EmailAddress:
113
+ - :string
114
+ - :required
115
+ :output: []
116
+
117
+ ListVerifiedEmailAddresses:
118
+ :input: {}
119
+
120
+ :output:
121
+ - VerifiedEmailAddresses:
122
+ - :list: member
123
+ DeleteVerifiedEmailAddress:
124
+ :input:
125
+ EmailAddress:
126
+ - :string
127
+ - :required
128
+ :output: []
129
+
130
+ :client_errors:
131
+ MessageRejected: []
132
+
133
+ MalformedQueryString: []
134
+
135
+ InvalidParameterCombination: []
136
+
137
+ InvalidParameterValue: []
138
+
139
+ InvalidQueryParameter: []
140
+
141
+ MissingAction: []
142
+
143
+ MissingParameter: []
144
+
145
+ RequestExpired: []
146
+
147
+ :server_errors: {}
@@ -0,0 +1,32 @@
1
+ # Copyright 2011 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ # http://aws.amazon.com/apache2.0/
8
+ #
9
+ # or in the "license" file accompanying this file. This file is
10
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
+ # ANY KIND, either express or implied. See the License for the specific
12
+ # language governing permissions and limitations under the License.
13
+
14
+ module AWS
15
+
16
+ # @private
17
+ class ApiConfigTransform
18
+
19
+ def self.rename_input_list_to_membered_list api_config
20
+ api_config[:operations].each_pair do |name,customizations|
21
+
22
+ input = api_config[:operations][name][:input]
23
+ fixed_input = input.to_yaml.gsub(/:list:/, ':membered_list:')
24
+
25
+ api_config[:operations][name][:input] = YAML.load(fixed_input)
26
+
27
+ end
28
+ api_config
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,90 @@
1
+ # Copyright 2011 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ # http://aws.amazon.com/apache2.0/
8
+ #
9
+ # or in the "license" file accompanying this file. This file is
10
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
+ # ANY KIND, either express or implied. See the License for the specific
12
+ # language governing permissions and limitations under the License.
13
+
14
+ module AWS
15
+
16
+ # Mixin that provides a generic callback facility for asynchronous
17
+ # tasks that can either succeed or fail.
18
+ # @private
19
+ module AsyncHandle
20
+
21
+ # Called to signal success and fire off the success and complete callbacks.
22
+ def signal_success
23
+ __send_signal(:success)
24
+ end
25
+
26
+ # Called to signal failure and fire off the failure and complete callbacks.
27
+ def signal_failure
28
+ __send_signal(:failure)
29
+ end
30
+
31
+ # Registers a callback to be called on successful completion of
32
+ # the task.
33
+ #
34
+ # handle.on_success { puts "It worked!" }
35
+ #
36
+ # If this is called when the task has already completed
37
+ # successfully, it will call the callback immediately.
38
+ def on_success(&blk)
39
+ if @_async_status == :success
40
+ blk.call
41
+ else
42
+ (@_async_callbacks ||= []) << { :success => blk }
43
+ end
44
+ end
45
+
46
+ # Registers a callback to be called when the task fails.
47
+ #
48
+ # handle.on_failure { puts "It didn't work!" }
49
+ #
50
+ # If this is called when the task has already failed, it will
51
+ # call the callback immediately.
52
+ def on_failure(&blk)
53
+ if @_async_status == :failure
54
+ blk.call
55
+ else
56
+ (@_async_callbacks ||= []) << { :failure => blk }
57
+ end
58
+ end
59
+
60
+ # Registers a callback to be called when the task is complete,
61
+ # regardless of its status. Yields the status to the block.
62
+ #
63
+ # handle.on_complete do |status|
64
+ # puts "It #{status == :success ? 'did' : 'did not'} work!"
65
+ # end
66
+ #
67
+ # If this is called when the task has already completed, it will
68
+ # call the callback immediately.
69
+ def on_complete(&blk)
70
+ if !@_async_status.nil?
71
+ blk.call(@_async_status)
72
+ else
73
+ (@_async_callbacks ||= []) << {
74
+ :failure => lambda { blk.call(:failure) },
75
+ :success => lambda { blk.call(:success) }
76
+ }
77
+ end
78
+ end
79
+
80
+ private
81
+ def __send_signal(kind)
82
+ @_async_status = kind
83
+ @_async_callbacks.map do |cb|
84
+ cb[kind]
85
+ end.compact.each { |blk| blk.call } if @_async_callbacks
86
+ end
87
+
88
+ end
89
+
90
+ end
@@ -0,0 +1,37 @@
1
+ # Copyright 2011 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ # http://aws.amazon.com/apache2.0/
8
+ #
9
+ # or in the "license" file accompanying this file. This file is
10
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
+ # ANY KIND, either express or implied. See the License for the specific
12
+ # language governing permissions and limitations under the License.
13
+
14
+ module AWS
15
+
16
+ # Mixed into clients that use v2 authorization.
17
+ # @private
18
+ module AuthorizeV2
19
+
20
+ def string_to_sign
21
+ parts = [http_method,
22
+ host,
23
+ path,
24
+ params.sort.collect { |p| p.encoded }.join('&')]
25
+ parts.join("\n")
26
+ end
27
+
28
+ def add_authorization! signer
29
+ self.access_key_id = signer.access_key_id
30
+ add_param('AWSAccessKeyId', access_key_id)
31
+ add_param('SignatureVersion', '2')
32
+ add_param('SignatureMethod', 'HmacSHA256')
33
+ add_param('Signature', signer.sign(string_to_sign))
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,37 @@
1
+ # Copyright 2011 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ # http://aws.amazon.com/apache2.0/
8
+ #
9
+ # or in the "license" file accompanying this file. This file is
10
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
+ # ANY KIND, either express or implied. See the License for the specific
12
+ # language governing permissions and limitations under the License.
13
+
14
+ require 'base64'
15
+ require 'time'
16
+
17
+ module AWS
18
+
19
+ # Mixed into clients that use v3 authorization.
20
+ # @private
21
+ module AuthorizeV3
22
+
23
+ def string_to_sign
24
+ headers['date'] ||= Time.now.rfc822
25
+ end
26
+
27
+ def add_authorization! signer
28
+ self.access_key_id = signer.access_key_id
29
+ parts = []
30
+ parts << "AWS3-HTTPS AWSAccessKeyId=#{access_key_id}"
31
+ parts << "Algorithm=HmacSHA256"
32
+ parts << "Signature=#{signer.sign(string_to_sign)}"
33
+ headers['x-amzn-authorization'] = parts.join(',')
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,524 @@
1
+ # Copyright 2011 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ # http://aws.amazon.com/apache2.0/
8
+ #
9
+ # or in the "license" file accompanying this file. This file is
10
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
+ # ANY KIND, either express or implied. See the License for the specific
12
+ # language governing permissions and limitations under the License.
13
+
14
+ require 'aws/errors'
15
+ require 'aws/inflection'
16
+ require 'aws/naming'
17
+ require 'aws/response'
18
+ require 'aws/async_handle'
19
+ require 'aws/configurable'
20
+ require 'aws/http/handler'
21
+ require 'aws/http/request'
22
+ require 'aws/http/response'
23
+ require 'aws/xml_grammar'
24
+ require 'aws/option_grammar'
25
+ require 'benchmark'
26
+ require 'set'
27
+
28
+ module AWS
29
+
30
+ # Base class for all of the Amazon AWS service clients.
31
+ # @private
32
+ class BaseClient
33
+
34
+ include Configurable
35
+
36
+ extend Naming
37
+
38
+ CACHEABLE_REQUESTS = Set.new
39
+
40
+ # Creates a new low-level client.
41
+ #
42
+ # == Required Options
43
+ #
44
+ # To create a client you must provide access to AWS credentials.
45
+ # There are two options:
46
+ #
47
+ # * +:signer+ -- An object that responds to +access_key_id+
48
+ # (to return the AWS Access Key ID) and to
49
+ # <code>sign(string_to_sign)</code> (to return a signature
50
+ # for a given string). An example implementation is
51
+ # AWS::DefaultSigner. This option is useful if you want to
52
+ # more tightly control access to your secret access key (for
53
+ # example by moving the signature computation into a
54
+ # different process).
55
+ #
56
+ # * +:access_key_id+ and +:secret_access_key+ -- You can use
57
+ # these options to provide the AWS Access Key ID and AWS
58
+ # Secret Access Key directly to the client.
59
+ #
60
+ # == Optional
61
+ #
62
+ # * +:http_handler+ -- Any object that implements a
63
+ # <code>handle(request, response)</code> method; an example
64
+ # is BuiltinHttpHandler. This method is used to perform the
65
+ # HTTP requests that this client constructs.
66
+ #
67
+ def initialize options = {}
68
+
69
+ if options[:endpoint]
70
+ options[:"#{self.class.service_ruby_name}_endpoint"] =
71
+ options.delete(:endpoint)
72
+ end
73
+
74
+ @config = options[:config]
75
+ @config ||= AWS.config
76
+ @config = @config.with(options)
77
+ @signer = @config.signer
78
+ @http_handler = @config.http_handler
79
+ @stubs = {}
80
+
81
+ end
82
+
83
+ # @return [Configuration] This clients configuration.
84
+ attr_reader :config
85
+
86
+ # @return [DefaultSigner,Object] Returns the signer for this client.
87
+ # This is normally a DefaultSigner, but it can be configured to
88
+ # an other object.
89
+ attr_reader :signer
90
+
91
+ # @return [String] the configured endpoint for this client.
92
+ def endpoint
93
+ config.send(:"#{self.class.service_ruby_name}_endpoint")
94
+ end
95
+
96
+ # Returns a copy of the client with a different HTTP handler.
97
+ # You can pass an object like BuiltinHttpHandler or you can
98
+ # use a block; for example:
99
+ #
100
+ # s3_with_logging = s3.with_http_handler do |request, response|
101
+ # $stderr.puts request.inspect
102
+ # super
103
+ # end
104
+ #
105
+ # The block executes in the context of an HttpHandler
106
+ # instance, and +super+ delegates to the HTTP handler used by
107
+ # this client. This provides an easy way to spy on requests
108
+ # and responses. See HttpHandler, HttpRequest, and
109
+ # HttpResponse for more details on how to implement a fully
110
+ # functional HTTP handler using a different HTTP library than
111
+ # the one that ships with Ruby.
112
+ # @param handler (nil) A new http handler. Leave blank and pass a
113
+ # block to wrap the current handler with the block.
114
+ # @return [BaseClient] Returns a new instance of the client class with
115
+ # the modified or wrapped http handler.
116
+ def with_http_handler(handler = nil, &blk)
117
+ handler ||= Http::Handler.new(@http_handler, &blk)
118
+ with_options(:http_handler => handler)
119
+ end
120
+
121
+ # @param [Hash] options
122
+ # @see AWS.config detailed list of accepted options.
123
+ def with_options options
124
+ with_config(config.with(options))
125
+ end
126
+
127
+ # @param [Configuration] The configuration object to use.
128
+ # @return [BaseClient] Returns a new client object with the given
129
+ # configuration.
130
+ def with_config config
131
+ self.class.new(:config => config)
132
+ end
133
+
134
+ # The stub returned is memoized.
135
+ # @see new_stub_for
136
+ # @private
137
+ def stub_for method_name
138
+ @stubs[method_name] ||= new_stub_for(method_name)
139
+ end
140
+
141
+ # Primarily used for testing, this method returns an empty psuedo
142
+ # service response without making a request. Its used primarily for
143
+ # testing the ligher level service interfaces.
144
+ # @private
145
+ def new_stub_for method_name
146
+ response = Response.new(Http::Request.new, Http::Response.new)
147
+ response.request_type = method_name
148
+ response.request_options = {}
149
+ send("simulate_#{method_name}_response", response)
150
+ response.signal_success
151
+ response
152
+ end
153
+
154
+ protected
155
+ def new_request
156
+ req = self.class::REQUEST_CLASS.new
157
+ req.http_method = 'POST'
158
+ req.headers['Content-Type'] = 'application/x-www-form-urlencoded'
159
+ req.add_param 'Timestamp', Time.now.utc.strftime('%Y-%m-%dT%TZ')
160
+ req.add_param 'Version', self.class::API_VERSION
161
+ req
162
+ end
163
+
164
+ protected
165
+ def new_response(*args)
166
+ Response.new(*args)
167
+ end
168
+
169
+ private
170
+ def log severity, message
171
+ config.logger.send(severity, message + "\n") if config.logger
172
+ end
173
+
174
+ private
175
+ def log_client_request method_name, options, &block
176
+
177
+ response = nil
178
+ time = Benchmark.measure do
179
+ response = yield
180
+ end
181
+
182
+ if options[:async]
183
+ response.on_success { log_client_request_on_success(method_name,
184
+ options,
185
+ response,
186
+ time) }
187
+ else
188
+ log_client_request_on_success(method_name,
189
+ options,
190
+ response,
191
+ time)
192
+ end
193
+
194
+ response
195
+
196
+ end
197
+
198
+ private
199
+ def log_client_request_on_success(method_name, options, response, time)
200
+ status = response.http_response.status
201
+ service = self.class.service_name
202
+
203
+ pattern = "[AWS %s %s %.06f] %s %s"
204
+ parts = [service, status, time.real, method_name, options.inspect]
205
+ severity = :info
206
+
207
+ if response.error
208
+ pattern += " %s: %s"
209
+ parts << response.error.class
210
+ parts << response.error.message
211
+ severity = :error
212
+ end
213
+
214
+ if response.cached
215
+ pattern << " [CACHED]"
216
+ end
217
+
218
+ log(severity, pattern % parts)
219
+ end
220
+
221
+ private
222
+ def make_async_request response
223
+
224
+ pauses = async_request_with_retries(response,
225
+ response.http_request)
226
+
227
+ response
228
+
229
+ end
230
+
231
+ private
232
+ def async_request_with_retries response, http_request, retry_delays = nil
233
+
234
+ response.http_response = AWS::Http::Response.new
235
+
236
+ handle = Object.new
237
+ handle.extend AsyncHandle
238
+ handle.on_complete do |status|
239
+ case status
240
+ when :failure
241
+ response.error = StandardError.new("failed to contact the service")
242
+ response.signal_failure
243
+ when :success
244
+ populate_error(response)
245
+ retry_delays ||= sleep_durations(response)
246
+ if should_retry?(response) and !retry_delays.empty?
247
+ @http_handler.sleep_with_callback(retry_delays.shift) do
248
+ async_request_with_retries(response, http_request, retry_delays)
249
+ end
250
+ else
251
+ response.error ?
252
+ response.signal_failure :
253
+ response.signal_success
254
+ end
255
+ end
256
+ end
257
+
258
+ @http_handler.handle_async(http_request, response.http_response, handle)
259
+
260
+ end
261
+
262
+ private
263
+ def make_sync_request response
264
+ retry_server_errors do
265
+
266
+ response.http_response = http_response =
267
+ AWS::Http::Response.new
268
+
269
+ @http_handler.handle(response.http_request, http_response)
270
+
271
+ populate_error(response)
272
+ response.signal_success unless response.error
273
+ response
274
+
275
+ end
276
+ end
277
+
278
+ private
279
+ def retry_server_errors &block
280
+
281
+ response = yield
282
+
283
+ sleeps = sleep_durations(response)
284
+ while should_retry?(response)
285
+ break if sleeps.empty?
286
+ Kernel.sleep(sleeps.shift)
287
+ response = yield
288
+ end
289
+
290
+ response
291
+
292
+ end
293
+
294
+ private
295
+ def sleep_durations response
296
+ factor = scaling_factor(response)
297
+ Array.new(config.max_retries) {|n| (2 ** n) * factor }
298
+ end
299
+
300
+ private
301
+ def scaling_factor response
302
+ response.throttled? ? (0.5 + Kernel.rand * 0.1) : 0.3
303
+ end
304
+
305
+ private
306
+ def should_retry? response
307
+ response.timeout? or
308
+ response.throttled? or
309
+ response.error.kind_of?(Errors::ServerError)
310
+ end
311
+
312
+ private
313
+ def return_or_raise options, &block
314
+ response = yield
315
+ unless options[:async]
316
+ raise response.error if response.error
317
+ end
318
+ response
319
+ end
320
+
321
+ protected
322
+ def populate_error response
323
+
324
+ # clear out a previous error
325
+ response.error = nil
326
+ status = response.http_response.status
327
+ code = nil
328
+ code = xml_error_grammar.parse(response.http_response.body).code if
329
+ xml_error_response?(response)
330
+
331
+ case
332
+ when response.timeout?
333
+ response.error = Timeout::Error.new
334
+
335
+ when code
336
+ response.error =
337
+ service_module::Errors.error_class(code).new(response.http_request,
338
+ response.http_response)
339
+ when status >= 500
340
+ response.error =
341
+ Errors::ServerError.new(response.http_request, response.http_response)
342
+
343
+ when status >= 300
344
+ response.error =
345
+ Errors::ClientError.new(response.http_request, response.http_response)
346
+ end
347
+
348
+ end
349
+
350
+ protected
351
+ def xml_error_response? response
352
+ response.http_response.status >= 300 and
353
+ xml_error_grammar.parse(response.http_response.body).respond_to?(:code)
354
+
355
+ end
356
+
357
+ protected
358
+ def xml_error_grammar
359
+ if service_module::const_defined?(:Errors) and
360
+ service_module::Errors::const_defined?(:BASE_ERROR_GRAMMAR)
361
+ service_module::Errors::BASE_ERROR_GRAMMAR
362
+ else
363
+ XmlGrammar
364
+ end
365
+ end
366
+
367
+ protected
368
+ def service_module
369
+ AWS.const_get(self.class.to_s[/(\w+)::Client/, 1])
370
+ end
371
+
372
+ private
373
+ def client_request name, options, &block
374
+ return_or_raise(options) do
375
+ log_client_request(name, options) do
376
+
377
+ # we dont want to pass the async option to the configure block
378
+ opts = options.dup
379
+ opts.delete(:async)
380
+
381
+ # configure the http request
382
+ http_request = new_request
383
+ http_request.host = endpoint
384
+ http_request.use_ssl = config.use_ssl?
385
+ send("configure_#{name}_request", http_request, opts, &block)
386
+ http_request.headers["user-agent"] = user_agent_string
387
+ http_request.add_authorization!(signer)
388
+
389
+ if config.stub_requests?
390
+
391
+ response = stub_for(name)
392
+ response.http_request = http_request
393
+ response.request_options = options
394
+ response
395
+
396
+ else
397
+
398
+ response = new_response(http_request)
399
+ response.request_type = name
400
+ response.request_options = options
401
+
402
+ if self.class::CACHEABLE_REQUESTS.
403
+ include?(name) and
404
+ cache = AWS.response_cache and
405
+ cached_response = cache.cached(response)
406
+ cached_response.cached = true
407
+ cached_response
408
+ else
409
+ # process the http request
410
+ options[:async] ?
411
+ make_async_request(response) :
412
+ make_sync_request(response)
413
+
414
+ # process the http response
415
+ response.on_success do
416
+ send("process_#{name}_response", response)
417
+ if cache = AWS.response_cache
418
+ cache.add(response)
419
+ end
420
+ end
421
+
422
+ response
423
+
424
+ end
425
+
426
+ end
427
+
428
+ end
429
+ end
430
+ end
431
+
432
+ private
433
+ def user_agent_string
434
+ engine = (RUBY_ENGINE rescue nil or "ruby")
435
+ user_agent = "%s aws-sdk-ruby/1.0 %s/%s %s" %
436
+ [config.user_agent_prefix, engine, RUBY_VERSION, RUBY_PLATFORM]
437
+ user_agent.strip!
438
+ if AWS.memoizing?
439
+ user_agent << " memoizing"
440
+ end
441
+ user_agent
442
+ end
443
+
444
+ private
445
+ def self.add_client_request_method method_name, options = {}, &block
446
+
447
+ method = ClientRequestMethodBuilder.new(self, method_name, &block)
448
+
449
+ if xml_grammar = options[:xml_grammar]
450
+
451
+ method.process_response do |resp|
452
+ xml_grammar.parse(resp.http_response.body, :context => resp)
453
+ super(resp)
454
+ end
455
+
456
+ method.simulate_response do |resp|
457
+ xml_grammar.simulate(resp)
458
+ super(resp)
459
+ end
460
+
461
+ end
462
+
463
+ module_eval <<-END
464
+ def #{method_name}(*args, &block)
465
+ options = args.first ? args.first : {}
466
+ client_request(#{method_name.inspect}, options, &block)
467
+ end
468
+ END
469
+
470
+ end
471
+
472
+ # defined using MetaUtils so it can be extended by
473
+ # modules such as ConfiguredClientMethods
474
+ MetaUtils.extend_method(self, :configure_client) do
475
+
476
+ module_eval('module Options; end')
477
+ module_eval('module XML; end')
478
+
479
+ make_configurable :"#{service_ruby_name}_client",
480
+ :needs => [:signer, :http_handler]
481
+
482
+ end
483
+
484
+ # @private
485
+ class ClientRequestMethodBuilder
486
+
487
+ def initialize client_class, method_name, &block
488
+ @client_class = client_class
489
+ @method_name = method_name
490
+ configure_request {|request, options|}
491
+ process_response {|response|}
492
+ simulate_response {|response|}
493
+ instance_eval(&block)
494
+ end
495
+
496
+ def configure_request options = {}, &block
497
+ name = "configure_#{@method_name}_request"
498
+ MetaUtils.class_extend_method(@client_class, name, &block)
499
+
500
+ if block.arity == 3
501
+ m = Module.new
502
+ m.module_eval(<<-END)
503
+ def #{name}(req, options, &block)
504
+ super(req, options, block)
505
+ end
506
+ END
507
+ @client_class.send(:include, m)
508
+ end
509
+ end
510
+
511
+ def process_response &block
512
+ name = "process_#{@method_name}_response"
513
+ MetaUtils.class_extend_method(@client_class, name, &block)
514
+ end
515
+
516
+ def simulate_response &block
517
+ name = "simulate_#{@method_name}_response"
518
+ MetaUtils.class_extend_method(@client_class, name, &block)
519
+ end
520
+
521
+ end
522
+
523
+ end
524
+ end