aws-sdk 1.2.6 → 1.3.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 (60) hide show
  1. data/lib/aws.rb +2 -0
  2. data/lib/aws/api_config/DynamoDB-2011-12-05.yml +721 -0
  3. data/lib/aws/core.rb +10 -1
  4. data/lib/aws/core/client.rb +17 -12
  5. data/lib/aws/core/configuration.rb +13 -3
  6. data/lib/aws/core/configured_json_client_methods.rb +71 -0
  7. data/lib/aws/core/lazy_error_classes.rb +7 -2
  8. data/lib/aws/core/option_grammar.rb +67 -13
  9. data/lib/aws/core/resource.rb +9 -1
  10. data/lib/aws/core/session_signer.rb +95 -0
  11. data/lib/aws/dynamo_db.rb +169 -0
  12. data/lib/aws/dynamo_db/attribute_collection.rb +460 -0
  13. data/lib/aws/dynamo_db/batch_get.rb +206 -0
  14. data/lib/aws/dynamo_db/client.rb +119 -0
  15. data/lib/aws/dynamo_db/config.rb +20 -0
  16. data/lib/aws/dynamo_db/errors.rb +57 -0
  17. data/lib/aws/dynamo_db/expectations.rb +40 -0
  18. data/lib/aws/dynamo_db/item.rb +130 -0
  19. data/lib/aws/dynamo_db/item_collection.rb +837 -0
  20. data/lib/aws/{record/optimistic_locking.rb → dynamo_db/item_data.rb} +9 -12
  21. data/lib/aws/{record/attributes/boolean.rb → dynamo_db/keys.rb} +15 -23
  22. data/lib/aws/dynamo_db/primary_key_element.rb +47 -0
  23. data/lib/aws/dynamo_db/request.rb +78 -0
  24. data/lib/aws/{record/attributes/float.rb → dynamo_db/resource.rb} +10 -25
  25. data/lib/aws/dynamo_db/table.rb +418 -0
  26. data/lib/aws/dynamo_db/table_collection.rb +165 -0
  27. data/lib/aws/dynamo_db/types.rb +86 -0
  28. data/lib/aws/ec2/resource_tag_collection.rb +3 -1
  29. data/lib/aws/record.rb +36 -8
  30. data/lib/aws/record/abstract_base.rb +642 -0
  31. data/lib/aws/record/attributes.rb +384 -0
  32. data/lib/aws/record/dirty_tracking.rb +0 -1
  33. data/lib/aws/record/errors.rb +0 -8
  34. data/lib/aws/record/hash_model.rb +163 -0
  35. data/lib/aws/record/hash_model/attributes.rb +182 -0
  36. data/lib/aws/record/hash_model/finder_methods.rb +178 -0
  37. data/lib/aws/record/hash_model/scope.rb +108 -0
  38. data/lib/aws/record/model.rb +429 -0
  39. data/lib/aws/record/model/attributes.rb +377 -0
  40. data/lib/aws/record/model/finder_methods.rb +232 -0
  41. data/lib/aws/record/model/scope.rb +213 -0
  42. data/lib/aws/record/scope.rb +43 -169
  43. data/lib/aws/record/validations.rb +11 -11
  44. data/lib/aws/s3/client.rb +9 -6
  45. data/lib/aws/s3/object_collection.rb +1 -1
  46. data/lib/aws/simple_db/expect_condition_option.rb +1 -1
  47. data/lib/aws/simple_db/item_collection.rb +5 -3
  48. data/lib/aws/sts/client.rb +9 -0
  49. metadata +73 -30
  50. data/lib/aws/record/attribute.rb +0 -94
  51. data/lib/aws/record/attribute_macros.rb +0 -312
  52. data/lib/aws/record/attributes/date.rb +0 -89
  53. data/lib/aws/record/attributes/datetime.rb +0 -86
  54. data/lib/aws/record/attributes/integer.rb +0 -68
  55. data/lib/aws/record/attributes/sortable_float.rb +0 -60
  56. data/lib/aws/record/attributes/sortable_integer.rb +0 -95
  57. data/lib/aws/record/attributes/string.rb +0 -69
  58. data/lib/aws/record/base.rb +0 -828
  59. data/lib/aws/record/finder_methods.rb +0 -230
  60. data/lib/aws/record/scopes.rb +0 -55
@@ -20,6 +20,7 @@ require 'aws/core/autoloader'
20
20
  #
21
21
  # The currently supported services are:
22
22
  #
23
+ # * {DynamoDB}
23
24
  # * {EC2}
24
25
  # * {ELB}
25
26
  # * {IAM}
@@ -57,7 +58,7 @@ require 'aws/core/autoloader'
57
58
  module AWS
58
59
 
59
60
  # Current version of the AWS SDK for Ruby
60
- VERSION = "1.2.6"
61
+ VERSION = "1.3.0"
61
62
 
62
63
  register_autoloads(self) do
63
64
  autoload :Errors, 'errors'
@@ -78,6 +79,7 @@ module AWS
78
79
  autoload :Configuration, 'configuration'
79
80
  autoload :ConfiguredClientMethods, 'configured_client_methods'
80
81
  autoload :ConfiguredGrammars, 'configured_grammars'
82
+ autoload :ConfiguredJsonClientMethods, 'configured_json_client_methods'
81
83
  autoload :ConfiguredOptionGrammars, 'configured_option_grammars'
82
84
  autoload :ConfiguredXmlGrammars, 'configured_xml_grammars'
83
85
  autoload :DefaultSigner, 'default_signer'
@@ -96,6 +98,7 @@ module AWS
96
98
  autoload :Response, 'response'
97
99
  autoload :ResponseCache, 'response_cache'
98
100
  autoload :ServiceInterface, 'service_interface'
101
+ autoload :SessionSigner, 'session_signer'
99
102
  autoload :UriEscape, 'uri_escape'
100
103
  autoload :XmlGrammar, 'xml_grammar'
101
104
  end
@@ -153,6 +156,12 @@ module AWS
153
156
  # @param [Hash] options
154
157
  # @option options [String] :access_key_id (nil) AWS access key id
155
158
  # credential.
159
+ # @option options [String] :dynamo_db_endpoint ('dynamodb.amazonaws.com') The
160
+ # service endpoint for Amazon DynamoDB.
161
+ # @option options [String] :dynamo_db_retry_throughput_errors (false) When
162
+ # true, AWS::DynamoDB::Errors::ProvisionedThroughputExceededException
163
+ # errors will be retried. You may need to increase the maximum number
164
+ # of retries if you have a low provisioned throughput.
156
165
  # @option options [String] :ec2_endpoint ('ec2.amazonaws.com') The
157
166
  # service endpoint for Amazon EC2.
158
167
  # @option options [Object] :http_handler (AWS::HTTPartyHandler) The
@@ -181,7 +181,7 @@ module AWS
181
181
  populate_error(response)
182
182
  retry_delays ||= sleep_durations(response)
183
183
  if should_retry?(response) and !retry_delays.empty?
184
- response.rebuild_request
184
+ rebuild_http_request(response)
185
185
  @http_handler.sleep_with_callback(retry_delays.shift) do
186
186
  async_request_with_retries(response, response.http_request, retry_delays)
187
187
  end
@@ -222,15 +222,19 @@ module AWS
222
222
  while should_retry?(response)
223
223
  break if sleeps.empty?
224
224
  Kernel.sleep(sleeps.shift)
225
-
226
225
  # rebuild the request to get a fresh signature
227
- response.rebuild_request
226
+ rebuild_http_request(response)
228
227
  response = yield
229
228
  end
230
229
 
231
230
  response
232
231
 
233
232
  end
233
+
234
+ private
235
+ def rebuild_http_request response
236
+ response.rebuild_request
237
+ end
234
238
 
235
239
  private
236
240
  def sleep_durations response
@@ -266,10 +270,8 @@ module AWS
266
270
  response.error = nil
267
271
  status = response.http_response.status
268
272
  code = nil
269
- code = xml_error_grammar.parse(response.http_response.body).code if
270
- xml_error_response?(response)
271
-
272
-
273
+ code = extract_error_code(response)
274
+
273
275
  case
274
276
  when response.timeout?
275
277
  response.error = Timeout::Error.new
@@ -290,12 +292,15 @@ module AWS
290
292
  end
291
293
 
292
294
  protected
293
- def xml_error_response? response
294
- response.http_response.status >= 300 and
295
- response.http_response.body and
296
- xml_error_grammar.parse(response.http_response.body).respond_to?(:code)
295
+ def extract_error_code response
296
+ if response.http_response.status >= 300 and
297
+ body = response.http_response.body and
298
+ parse = xml_error_grammar.parse(body) and
299
+ parse.respond_to?(:code)
300
+ parse.code
301
+ end
297
302
  end
298
-
303
+
299
304
  protected
300
305
  def xml_error_grammar
301
306
  if service_module::const_defined?(:Errors) and
@@ -273,9 +273,19 @@ module AWS
273
273
 
274
274
  accepted_options << name
275
275
 
276
- define_method(name) do
277
- value = supplied.has_key?(name) ? supplied[name] : default_value
276
+ define_method(name) do |&default_override|
277
+
278
+ value =
279
+ if supplied.has_key?(name)
280
+ supplied[name]
281
+ elsif default_override
282
+ default_override.call
283
+ else
284
+ default_value
285
+ end
286
+
278
287
  transform ? transform.call(value) : value
288
+
279
289
  end
280
290
 
281
291
  alias_method("#{name}?", name) if options[:boolean]
@@ -339,7 +349,7 @@ module AWS
339
349
 
340
350
  add_option :access_key_id,
341
351
  ENV['AWS_ACCESS_KEY_ID'] || ENV['AMAZON_ACCESS_KEY_ID']
342
-
352
+
343
353
  add_option :http_handler, Core::Http::NetHttpHandler.new
344
354
 
345
355
  add_option :logger
@@ -0,0 +1,71 @@
1
+ # Copyright 2011-2012 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 'json'
15
+
16
+ module AWS
17
+ module Core
18
+
19
+ # @private
20
+ module ConfiguredJsonClientMethods
21
+
22
+ # @private
23
+ module ClassMethods
24
+
25
+ include ApiConfig
26
+
27
+ def configure_client
28
+
29
+ super
30
+
31
+ unless self::Options.include?(ConfiguredOptionGrammars)
32
+ self::Options.module_eval do
33
+ include(ConfiguredOptionGrammars)
34
+ define_configured_grammars
35
+ end
36
+ end
37
+
38
+ api_config[:operations].each do |name, customizations|
39
+ option_grammar = self::Options.operation_grammar(name)
40
+ target_prefix = self::TARGET_PREFIX
41
+ add_client_request_method(Inflection.ruby_name(name).to_sym) do
42
+ configure_request do |request, options|
43
+ request.headers["x-amz-target"] = target_prefix + name
44
+ request.body = option_grammar.to_json(options)
45
+ end
46
+
47
+ process_response do |response|
48
+ data = JSON.load(response.http_response.body)
49
+ MetaUtils.extend_method(response, :data) { data }
50
+ end
51
+
52
+ simulate_response do |response|
53
+ data = {}
54
+ MetaUtils.extend_method(response, :data) { data }
55
+ end
56
+ end
57
+ end
58
+
59
+ end
60
+
61
+ end
62
+
63
+ def self.included(mod)
64
+ mod.extend(ClassMethods)
65
+ end
66
+
67
+ end
68
+
69
+ end
70
+ end
71
+
@@ -22,14 +22,16 @@ module AWS
22
22
 
23
23
  def const_missing(name)
24
24
  base_error_grammar = self::BASE_ERROR_GRAMMAR
25
+ mod = self::ERROR_MODULE
25
26
  const_missing_mutex.synchronize do
26
27
  return if const_defined?(name)
27
28
  const_set(name,
28
29
  Class.new(self::Base) do
29
- include Errors::ModeledError
30
-
30
+ include mod::ModeledError
31
+
31
32
  # so that MyService::Errors::Foo::Bar will work
32
33
  const_set(:BASE_ERROR_GRAMMAR, base_error_grammar)
34
+ const_set(:ERROR_MODULE, mod)
33
35
  include LazyErrorClasses
34
36
  end)
35
37
  end
@@ -51,6 +53,9 @@ module AWS
51
53
  unless mod.const_defined?(:BASE_ERROR_GRAMMAR)
52
54
  mod.const_set(:BASE_ERROR_GRAMMAR, XmlGrammar)
53
55
  end
56
+ unless mod.const_defined?(:ERROR_MODULE)
57
+ mod.const_set(:ERROR_MODULE, mod)
58
+ end
54
59
  mutex = Mutex.new
55
60
  MetaUtils.extend_method(mod, :const_missing_mutex) { mutex }
56
61
  mod.send(:include, Errors)
@@ -12,6 +12,7 @@
12
12
  # language governing permissions and limitations under the License.
13
13
 
14
14
  require 'base64'
15
+ require 'bigdecimal'
15
16
 
16
17
  module AWS
17
18
  module Core
@@ -219,7 +220,13 @@ module AWS
219
220
  return [Http::Request::Param.new(prefixed_name(prefix), "")] if params.empty?
220
221
  params
221
222
  end
222
-
223
+
224
+ def hash_format(value)
225
+ value.map do |v|
226
+ member_option.hash_format(v)
227
+ end
228
+ end
229
+
223
230
  def join
224
231
  '.'
225
232
  end
@@ -284,6 +291,7 @@ module AWS
284
291
  MetaUtils.extend_method(option, :member_options) { options.values }
285
292
  by_ruby_name = options.values.inject({}) do |memo, member_option|
286
293
  memo[member_option.ruby_name] = member_option
294
+ memo[member_option.name] = member_option
287
295
  memo
288
296
  end
289
297
  MetaUtils.extend_method(option, :member_option) { |n| by_ruby_name[n] }
@@ -306,7 +314,8 @@ module AWS
306
314
  raise ArgumentError.new("missing required key #{option.ruby_name} for #{context}") if
307
315
  option.required? and
308
316
  !value.has_key?(option.ruby_name) and
309
- !value.has_key?(option.ruby_name.to_sym)
317
+ !value.has_key?(option.ruby_name.to_sym) and
318
+ !value.has_key?(option.name)
310
319
  end
311
320
  end
312
321
 
@@ -316,7 +325,15 @@ module AWS
316
325
  member_option(name).request_params(value, prefixed_name(prefix))
317
326
  end.flatten
318
327
  end
319
-
328
+
329
+ def hash_format(hash)
330
+ hash.inject({}) do |hash, (name, value)|
331
+ option = member_option(name.to_s)
332
+ hash[option.name] = option.hash_format(value)
333
+ hash
334
+ end
335
+ end
336
+
320
337
  end
321
338
 
322
339
  module Map
@@ -388,13 +405,20 @@ module AWS
388
405
  @_value_option ||= MapOption.new("value")
389
406
  end
390
407
 
391
- class MapOption < DefaultOption
392
- def param_name
393
- @param_name || name
394
- end
395
- def param_name= name
396
- @param_name = name
397
- end
408
+ end
409
+
410
+ module Bigdecimal
411
+
412
+ extend NoArgs
413
+
414
+ def validate(value, context = nil)
415
+ raise format_error("decimal value", context) unless
416
+ value.kind_of?(Numeric) or
417
+ value.respond_to?(:to_int)
418
+ end
419
+
420
+ def hash_format(value)
421
+ BigDecimal(value.to_s)
398
422
  end
399
423
 
400
424
  end
@@ -421,7 +445,11 @@ module AWS
421
445
  def request_params(value, prefix = nil)
422
446
  [Http::Request::Param.new(prefixed_name(prefix), encode_value(value))]
423
447
  end
424
-
448
+
449
+ def hash_format(value)
450
+ value
451
+ end
452
+
425
453
  def prefixed_name(prefix)
426
454
  return "#{prefix}.#{name}" if prefix
427
455
  name
@@ -527,7 +555,8 @@ module AWS
527
555
  options.has_key?(option.ruby_name) || options.has_key?(option.ruby_name.to_sym)
528
556
  end
529
557
  end
530
-
558
+
559
+ # Returns the options in AWS/Query format
531
560
  def request_params(options)
532
561
  validate(options)
533
562
  options.map do |(name, value)|
@@ -535,7 +564,23 @@ module AWS
535
564
  option(name).request_params(value)
536
565
  end.flatten
537
566
  end
538
-
567
+
568
+ # Returns the options as a hash (which is used to generate JSON
569
+ # in to_json).
570
+ def to_h(options)
571
+ validate(options)
572
+ options.inject({}) do |hash, (name, value)|
573
+ option = self.option(name.to_s)
574
+ hash[option.name] = option.hash_format(value)
575
+ hash
576
+ end
577
+ end
578
+
579
+ # Returns the options in JSON format
580
+ def to_json(options)
581
+ to_h(options).to_json
582
+ end
583
+
539
584
  def included(m)
540
585
  m.extend(self::ModuleMethods)
541
586
  end
@@ -636,6 +681,15 @@ module AWS
636
681
  end
637
682
 
638
683
  end
684
+
685
+ class MapOption < DefaultOption
686
+ def param_name
687
+ @param_name || name
688
+ end
689
+ def param_name= name
690
+ @param_name = name
691
+ end
692
+ end
639
693
 
640
694
  extend ModuleMethods
641
695
 
@@ -300,6 +300,7 @@ module AWS
300
300
 
301
301
  case
302
302
  when @options[:to_sym] then value.tr('-','_').downcase.to_sym
303
+ when @options[:timestamp] then Time.at(value.to_i)
303
304
  when @output_translator then @output_translator.call(value)
304
305
  else value
305
306
  end
@@ -364,7 +365,14 @@ module AWS
364
365
  attr = @klass.attributes[attr_name]
365
366
  method = options[:get_as] || attr.get_as
366
367
 
367
- v = resp_obj.respond_to?(method) ? resp_obj.send(method) : nil
368
+ v = case
369
+ when resp_obj.respond_to?(method)
370
+ resp_obj.send(method)
371
+ when resp_obj.respond_to?(:key?) && resp_obj.key?(method)
372
+ resp_obj[method]
373
+ else
374
+ nil
375
+ end
368
376
  v = v.value if v and options[:value_wrapped]
369
377
  v = attr.translate_output_value(v)
370
378
 
@@ -0,0 +1,95 @@
1
+ # Copyright 2011-2012 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/sts'
15
+ require 'thread'
16
+
17
+ module AWS
18
+ module Core
19
+
20
+ # @private
21
+ class SessionSigner
22
+
23
+ @create_mutex = Mutex.new
24
+
25
+ def self.for config
26
+ @create_mutex.synchronize do
27
+ @session_signers ||= {}
28
+ @session_signers[config.signer.access_key_id] ||= self.new(config)
29
+ end
30
+ end
31
+
32
+ def initialize config
33
+ @config = config
34
+ @session_mutex = Mutex.new
35
+ end
36
+
37
+ def sign *args
38
+ short_term_signer.sign(*args)
39
+ end
40
+
41
+ def access_key_id
42
+ session.credentials[:access_key_id]
43
+ end
44
+
45
+ def secret_access_key
46
+ session.credentials[:secret_access_key]
47
+ end
48
+
49
+ def session_token
50
+ session.credentials[:session_token]
51
+ end
52
+
53
+ def refresh_session
54
+ sts = AWS::STS.new(:config => @config, :use_ssl => true)
55
+ @session_mutex.synchronize do
56
+ @session = sts.new_session
57
+ end
58
+ end
59
+
60
+ protected
61
+ def get_session
62
+ local_session = nil
63
+ @session_mutex.synchronize do
64
+ local_session = @session
65
+ end
66
+ local_session
67
+ end
68
+
69
+ protected
70
+ def session
71
+
72
+ session = get_session
73
+
74
+ if session.nil?
75
+ refresh_session
76
+ session = get_session
77
+ end
78
+
79
+ if session.expires_at < (Time.now + 15 * 60)
80
+ refresh_session
81
+ session = get_session
82
+ end
83
+
84
+ session
85
+
86
+ end
87
+
88
+ protected
89
+ def short_term_signer
90
+ DefaultSigner.new(access_key_id, secret_access_key, session_token)
91
+ end
92
+
93
+ end
94
+ end
95
+ end