aws-sdk 1.0.4 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/lib/aws.rb +10 -9
  2. data/lib/aws/api_config/IAM-2010-07-15.yml +632 -0
  3. data/lib/aws/base_client.rb +1 -1
  4. data/lib/aws/cacheable.rb +34 -46
  5. data/lib/aws/client_logging.rb +19 -14
  6. data/lib/aws/collections.rb +230 -0
  7. data/lib/aws/common.rb +4 -0
  8. data/lib/aws/configuration.rb +7 -0
  9. data/lib/aws/ec2.rb +2 -2
  10. data/lib/aws/ec2/attachment.rb +64 -71
  11. data/lib/aws/ec2/attachment_collection.rb +11 -9
  12. data/lib/aws/ec2/availability_zone.rb +40 -31
  13. data/lib/aws/ec2/availability_zone_collection.rb +2 -3
  14. data/lib/aws/ec2/elastic_ip.rb +25 -22
  15. data/lib/aws/ec2/elastic_ip_collection.rb +5 -2
  16. data/lib/aws/ec2/image.rb +113 -129
  17. data/lib/aws/ec2/image_collection.rb +5 -6
  18. data/lib/aws/ec2/instance.rb +290 -233
  19. data/lib/aws/ec2/instance_collection.rb +72 -67
  20. data/lib/aws/ec2/key_pair.rb +16 -18
  21. data/lib/aws/ec2/region.rb +25 -17
  22. data/lib/aws/ec2/reserved_instances.rb +7 -1
  23. data/lib/aws/ec2/reserved_instances_collection.rb +3 -3
  24. data/lib/aws/ec2/reserved_instances_offering.rb +7 -1
  25. data/lib/aws/ec2/reserved_instances_offering_collection.rb +3 -3
  26. data/lib/aws/ec2/resource.rb +41 -222
  27. data/lib/aws/ec2/security_group.rb +22 -18
  28. data/lib/aws/ec2/security_group_collection.rb +2 -5
  29. data/lib/aws/ec2/snapshot.rb +44 -35
  30. data/lib/aws/ec2/snapshot_collection.rb +43 -1
  31. data/lib/aws/ec2/tag.rb +14 -18
  32. data/lib/aws/ec2/volume.rb +59 -72
  33. data/lib/aws/ec2/volume_collection.rb +16 -12
  34. data/lib/aws/errors.rb +14 -5
  35. data/lib/aws/http/httparty_handler.rb +2 -2
  36. data/lib/aws/iam.rb +306 -0
  37. data/lib/aws/iam/access_key.rb +183 -0
  38. data/lib/aws/iam/access_key_collection.rb +131 -0
  39. data/lib/aws/iam/account_alias_collection.rb +81 -0
  40. data/lib/aws/iam/client.rb +44 -0
  41. data/lib/aws/iam/client/xml.rb +38 -0
  42. data/lib/aws/iam/collection.rb +87 -0
  43. data/lib/aws/iam/errors.rb +29 -0
  44. data/lib/aws/iam/group.rb +117 -0
  45. data/lib/aws/iam/group_collection.rb +135 -0
  46. data/lib/aws/iam/group_policy_collection.rb +49 -0
  47. data/lib/aws/iam/group_user_collection.rb +94 -0
  48. data/lib/aws/iam/login_profile.rb +97 -0
  49. data/lib/aws/iam/mfa_device.rb +52 -0
  50. data/lib/aws/iam/mfa_device_collection.rb +119 -0
  51. data/lib/aws/iam/policy.rb +48 -0
  52. data/lib/aws/iam/policy_collection.rb +191 -0
  53. data/lib/aws/iam/request.rb +27 -0
  54. data/lib/aws/iam/resource.rb +74 -0
  55. data/lib/aws/iam/server_certificate.rb +143 -0
  56. data/lib/aws/iam/server_certificate_collection.rb +174 -0
  57. data/lib/aws/iam/signing_certificate.rb +171 -0
  58. data/lib/aws/iam/signing_certificate_collection.rb +134 -0
  59. data/lib/aws/iam/user.rb +196 -0
  60. data/lib/aws/iam/user_collection.rb +136 -0
  61. data/lib/aws/iam/user_group_collection.rb +101 -0
  62. data/lib/aws/iam/user_policy.rb +90 -0
  63. data/lib/aws/iam/user_policy_collection.rb +48 -0
  64. data/lib/aws/resource.rb +381 -0
  65. data/lib/aws/resource_cache.rb +1 -2
  66. data/lib/aws/response.rb +5 -1
  67. data/lib/aws/response_cache.rb +1 -1
  68. data/lib/aws/s3/client.rb +3 -1
  69. data/lib/aws/s3/presigned_post.rb +1 -1
  70. data/lib/aws/simple_db.rb +1 -1
  71. metadata +113 -50
@@ -46,45 +46,43 @@ module AWS
46
46
  include TaggedCollection
47
47
  include BlockDeviceMappings
48
48
 
49
- ##
50
49
  # Runs one or more EC2 instances.
51
50
  #
52
51
  # @example Running a single instance
53
- # i = ec2.instances.create(:image_id => "ami-8c1fece5")
54
- # sleep 1 while i.status == :pending
52
+ # i = ec2.instances.create(:image_id => "ami-8c1fece5")
53
+ # sleep 1 while i.status == :pending
55
54
  #
56
55
  # @example Running multiple instances with the same parameters
57
- # instances =
58
- # ec2.instances.create(:image_id => "ami-8c1fece5",
59
- # :count => 10)
60
- # sleep 1 while instances.any? { |i| i.status == :pending }
56
+ #
57
+ # instances = ec2.instances.create(
58
+ # :image_id => "ami-8c1fece5",
59
+ # :count => 10)
60
+ #
61
+ # sleep 1 while instances.any? {|i| i.status == :pending }
61
62
  #
62
63
  # @example Specifying block device mappings
63
- # ec2.instances.create(:image_id => "ami-8c1fece5",
64
- # :block_device_mappings => {
65
- # "/dev/sda2" => {
66
- # # 15 GiB
67
- # :volume_size => 15,
68
- # :delete_on_termination => true
69
- # }
70
- # })
71
64
  #
72
- # @return [Instance or Array] If a single instance is being created, this returns
73
- # an instance of {EC2::Instance} to represent the newly
74
- # created instance. Otherwise it returns an array of
75
- # EC2::Instance objects.
65
+ # ec2.instances.create({
66
+ # :image_id => "ami-8c1fece5",
67
+ # :block_device_mappings => {
68
+ # "/dev/sda2" => {
69
+ # :volume_size => 15, # 15 GiB
70
+ # :delete_on_termination => true
71
+ # }
72
+ # }
73
+ # })
76
74
  #
77
- # @param [Hash] opts Options for new instance. +:image_id+ is
75
+ # @param [Hash] options Options for new instance. +:image_id+ is
78
76
  # the only required option.
79
77
  #
80
- # @option opts :count How many instances to request. By
78
+ # @option options :count How many instances to request. By
81
79
  # default one instance is requested. You can specify this
82
80
  # either as an integer or as a Range, to indicate the
83
81
  # minimum and maximum number of instances to run. Note that
84
82
  # for a new account you can request at most 20 instances at
85
83
  # once.
86
84
  #
87
- # @option opts [Hash] :block_device_mappings This must be a
85
+ # @option options [Hash] :block_device_mappings This must be a
88
86
  # hash; the keys are device names to map, and the value for
89
87
  # each entry determines how that device is mapped. Valid
90
88
  # values include:
@@ -110,43 +108,43 @@ module AWS
110
108
  # to delete the volume when the
111
109
  # instance is terminated.
112
110
  #
113
- # @option opts [Boolean] :monitoring Setting this to true
111
+ # @option options [Boolean] :monitoring Setting this to true
114
112
  # enables CloudWatch monitoring on the instances once they
115
113
  # are started.
116
114
  #
117
- # @option opts [String] :availability_zone Specifies the
115
+ # @option options [String] :availability_zone Specifies the
118
116
  # availability zone where the instance should run. Without
119
117
  # this option, EC2 will choose an availability zone for you.
120
118
  #
121
- # @option opts [String] :image_id ID of the AMI you want to
119
+ # @option options [String] :image_id ID of the AMI you want to
122
120
  # launch.
123
121
  #
124
- # @option opts [String] :key_name The name of the key pair to
122
+ # @option options [String] :key_name The name of the key pair to
125
123
  # use. Note: Launching public images without a key pair ID
126
124
  # will leave them inaccessible.
127
125
  #
128
- # @option opts [Array] :security_groups The names of the
126
+ # @option options [Array] :security_groups The names of the
129
127
  # security groups that will be used to determine network
130
128
  # access rules for the instances. You may pass instances of
131
129
  # {SecurityGroup} as well.
132
130
  #
133
- # @option opts [String] :user_data Arbitrary user data. You
131
+ # @option options [String] :user_data Arbitrary user data. You
134
132
  # do not need to encode this value.
135
133
  #
136
- # @option opts [String] :instance_type The type of instance to
134
+ # @option options [String] :instance_type The type of instance to
137
135
  # launch, for example "m1.small".
138
136
  #
139
- # @option opts [String] :kernel_id The ID of the kernel with
137
+ # @option options [String] :kernel_id The ID of the kernel with
140
138
  # which to launch the instance.
141
139
  #
142
- # @option opts [String] :ramdisk_id The ID of the RAM disk to
140
+ # @option options [String] :ramdisk_id The ID of the RAM disk to
143
141
  # select. Some kernels require additional drivers at
144
142
  # launch. Check the kernel requirements for information on
145
143
  # whether you need to specify a RAM disk. To find kernel
146
144
  # requirements, refer to the Resource Center and search for
147
145
  # the kernel ID.
148
146
  #
149
- # @option opts [Boolean] :disable_api_termination Specifies
147
+ # @option options [Boolean] :disable_api_termination Specifies
150
148
  # whether you can terminate the instance using the EC2
151
149
  # API. A value of true means you can't terminate the
152
150
  # instance using the API (i.e., the instance is "locked"); a
@@ -161,54 +159,61 @@ module AWS
161
159
  # i.api_termination_disabled = false
162
160
  # i.terminate # terminates the instance
163
161
  #
164
- # @option opts [String] :instance_initiated_shutdown_behavior
162
+ # @option options [String] :instance_initiated_shutdown_behavior
165
163
  # Determines whether the instance stops or terminates on
166
164
  # instance-initiated shutdown.
167
- def create(opts = {})
168
- if image = opts.delete(:image)
169
- opts[:image_id] = image.id
165
+ #
166
+ # @return [Instance or Array] If a single instance is being created,
167
+ # this returns an {EC2::Instance} to represent the newly
168
+ # created instance. Otherwise it returns an array of instance
169
+ # objects.
170
+ #
171
+ def create options = {}
172
+
173
+ if image = options.delete(:image)
174
+ options[:image_id] = image.id
170
175
  end
171
176
 
172
- if kernel = opts.delete(:kernel)
173
- opts[:kernel_id] = kernel.id
177
+ if kernel = options.delete(:kernel)
178
+ options[:kernel_id] = kernel.id
174
179
  end
175
180
 
176
- if ramdisk = opts.delete(:ramdisk)
177
- opts[:ramdisk_id] = ramdisk.id
181
+ if ramdisk = options.delete(:ramdisk)
182
+ options[:ramdisk_id] = ramdisk.id
178
183
  end
179
184
 
180
- if key_pair = opts.delete(:key_pair)
181
- opts[:key_name] = key_pair.name
185
+ if key_pair = options.delete(:key_pair)
186
+ options[:key_name] = key_pair.name
182
187
  end
183
188
 
184
- opts = count_opts(opts).merge(opts)
185
- opts.delete(:count)
189
+ options = count_options(options).merge(options)
190
+ options.delete(:count)
186
191
 
187
- opts[:user_data] = Base64.encode64(opts[:user_data]).strip if
188
- opts[:user_data]
192
+ options[:user_data] = Base64.encode64(options[:user_data]).strip if
193
+ options[:user_data]
189
194
 
190
- opts[:block_device_mappings] =
191
- translate_block_device_mappings(opts[:block_device_mappings]) if
192
- opts[:block_device_mappings]
195
+ options[:block_device_mappings] =
196
+ translate_block_device_mappings(options[:block_device_mappings]) if
197
+ options[:block_device_mappings]
193
198
 
194
- opts[:monitoring] = { :enabled => true } if
195
- opts[:monitoring_enabled]
196
- opts.delete(:monitoring_enabled)
199
+ options[:monitoring] = { :enabled => true } if
200
+ options[:monitoring_enabled]
201
+ options.delete(:monitoring_enabled)
197
202
 
198
- opts[:placement] = {
199
- :availability_zone => opts[:availability_zone].to_s
200
- } if opts[:availability_zone]
201
- opts.delete(:availability_zone)
203
+ options[:placement] = {
204
+ :availability_zone => options[:availability_zone].to_s
205
+ } if options[:availability_zone]
206
+ options.delete(:availability_zone)
202
207
 
203
- opts[:security_groups] = group_opts(opts[:security_groups]) if
204
- opts[:security_groups]
208
+ options[:security_groups] = group_opts(options[:security_groups]) if
209
+ options[:security_groups]
205
210
 
206
- opts[:client_token] = UUIDTools::UUID.timestamp_create.to_s
211
+ options[:client_token] = UUIDTools::UUID.timestamp_create.to_s
207
212
 
208
- resp = client.run_instances(opts)
213
+ resp = client.run_instances(options)
209
214
 
210
- if opts[:min_count] == opts[:max_count] and
211
- opts[:min_count] == 1
215
+ if options[:min_count] == options[:max_count] and
216
+ options[:min_count] == 1
212
217
  self[resp.instances_set.first.instance_id]
213
218
  else
214
219
  resp.instances_set.map do |i|
@@ -216,6 +221,7 @@ module AWS
216
221
  end
217
222
  end
218
223
  end
224
+
219
225
  alias_method :run, :create
220
226
 
221
227
  # @yield [Instance] Yields each instance in the collection.
@@ -242,18 +248,17 @@ module AWS
242
248
 
243
249
  # @private
244
250
  private
245
- def count_opts(opts)
251
+ def count_options options
246
252
  min = max = 1
247
- count = opts[:count]
253
+ count = options[:count]
248
254
  case count
249
255
  when Range
250
256
  min = count.begin
251
- max = (count.exclude_end? ? count.end-1 : count.end)
257
+ max = (count.exclude_end? ? count.end - 1 : count.end)
252
258
  when Integer
253
259
  min = max = count
254
260
  end
255
- { :min_count => min,
256
- :max_count => max }
261
+ { :min_count => min, :max_count => max }
257
262
  end
258
263
 
259
264
  # @private
@@ -17,11 +17,12 @@ module AWS
17
17
  class EC2
18
18
 
19
19
  # Represents an EC2 key pair.
20
+ # @attr_reader [String] fingerprint A SHA-1 digest of the DER encoded
21
+ # private key
20
22
  class KeyPair < Resource
21
23
 
22
24
  def initialize name, options = {}
23
25
  @name = name.to_s
24
- @fingerprint = options[:fingerprint]
25
26
  @private_key = options[:private_key]
26
27
  super
27
28
  end
@@ -29,19 +30,24 @@ module AWS
29
30
  # @return [String] The name of the key pair.
30
31
  attr_reader :name
31
32
 
33
+ attribute :fingerprint, :as => :key_fingerprint, :static => true
34
+
35
+ populates_from(:create_key_pair, :import_key_pair) do |resp|
36
+ resp if resp.key_name == name
37
+ end
38
+
39
+ populates_from(:describe_key_pairs) do |resp|
40
+ resp.key_set.find{|k| k.key_name == name }
41
+ end
42
+
32
43
  # @return [Boolean] True if the key pair exists.
33
44
  def exists?
34
- !client.describe_key_pairs(:filters => [{ :name => "key-name",
35
- :values => [name] }]).
36
- key_set.empty?
45
+ resp = client.describe_key_pairs(:filters => [
46
+ { :name => "key-name", :values => [name] }
47
+ ])
48
+ !resp.key_set.empty?
37
49
  end
38
50
 
39
- # @return [String] A SHA-1 digest of the DER encoded private key
40
- def fingerprint; end
41
- describe_call_attribute(:key_fingerprint,
42
- :getter => :fingerprint,
43
- :memoize => true)
44
-
45
51
  # Returns the private key. Raises an exception if called
46
52
  # against an existing key. You can only get the private key
47
53
  # at the time of creation.
@@ -63,14 +69,6 @@ module AWS
63
69
  true
64
70
  end
65
71
 
66
- [:create_key_pair,
67
- :import_key_pair].each do |op|
68
- populate_from op do |resp|
69
- attributes_from_response_object(resp) if
70
- resp.key_name == name
71
- end
72
- end
73
-
74
72
  protected
75
73
  def response_id_method
76
74
  :key_name
@@ -29,19 +29,25 @@ module AWS
29
29
  # h[region.name] = region.instances.map(&:id)
30
30
  # h
31
31
  # end
32
+ #
33
+ # @attr_reader [String] endpoint The endpoint to use for this region
34
+ # (e.g. "ec2.eu-west-1.amazonaws.com").
35
+ #
32
36
  class Region < Resource
33
37
 
34
- # The name of the region (e.g. "us-east-1")
35
- attr_reader :name
36
-
37
38
  def initialize(name, options = {})
38
39
  @name = name
39
40
  super(options)
40
41
  end
41
42
 
42
- # @return [String] The endpoint to use for this region.
43
- def endpoint; end
44
- describe_call_attribute :region_endpoint, :getter => :endpoint, :memoize => true
43
+ # @return [String] The name of the region (e.g. "us-east-1").
44
+ attr_reader :name
45
+
46
+ attribute :endpoint, :as => :region_endpoint, :static => true
47
+
48
+ populates_from(:describe_regions) do |resp|
49
+ resp.region_info.find{|r| r.region_name == name }
50
+ end
45
51
 
46
52
  # @return [Boolean] True if the region is available for this
47
53
  # account.
@@ -51,17 +57,19 @@ module AWS
51
57
  region_info.empty?
52
58
  end
53
59
 
54
- PROXIED_METHODS = [:instances,
55
- :security_groups,
56
- :key_pairs,
57
- :elastic_ips,
58
- :tags,
59
- :availability_zones,
60
- :images,
61
- :volumes,
62
- :snapshots,
63
- :reserved_instances,
64
- :reserved_instances_offerings]
60
+ PROXIED_METHODS = [
61
+ :instances,
62
+ :security_groups,
63
+ :key_pairs,
64
+ :elastic_ips,
65
+ :tags,
66
+ :availability_zones,
67
+ :images,
68
+ :volumes,
69
+ :snapshots,
70
+ :reserved_instances,
71
+ :reserved_instances_offerings
72
+ ]
65
73
 
66
74
  PROXIED_METHODS.each do |method|
67
75
  define_method(method) do
@@ -42,7 +42,13 @@ module AWS
42
42
  attr_reader :id
43
43
 
44
44
  ATTRIBUTES.each do |attr_name|
45
- describe_call_attribute attr_name, :memoize => true
45
+ attribute(attr_name, :static => true)
46
+ end
47
+
48
+ populates_from(:describe_reserved_instances) do |resp|
49
+ resp.reserved_instances_set.find do |r|
50
+ r.reserved_instances_id == id
51
+ end
46
52
  end
47
53
 
48
54
  end
@@ -30,9 +30,9 @@ module AWS
30
30
  response = filtered_request(:describe_reserved_instances)
31
31
  response.reserved_instances_set.each do |item|
32
32
 
33
- reserved_instance = ReservedInstances.new(
34
- item.reserved_instances_id,
35
- :config => config)
33
+ reserved_instance = ReservedInstances.new_from(
34
+ :describe_reserved_instances, item,
35
+ item.reserved_instances_id, :config => config)
36
36
 
37
37
  yield(reserved_instance)
38
38
 
@@ -40,7 +40,13 @@ module AWS
40
40
  attr_reader :id
41
41
 
42
42
  ATTRIBUTES.each do |attr_name|
43
- describe_call_attribute attr_name, :memoize => true
43
+ attribute(attr_name, :static => true)
44
+ end
45
+
46
+ populates_from(:describe_reserved_instances_offerings) do |resp|
47
+ resp.reserved_instances_offerings_set.find do |r|
48
+ r.reserved_instances_offering_id == id
49
+ end
44
50
  end
45
51
 
46
52
  def purchase options = {}
@@ -29,9 +29,9 @@ module AWS
29
29
  response = filtered_request(:describe_reserved_instances_offerings)
30
30
  response.reserved_instances_offerings_set.each do |item|
31
31
 
32
- reserved_instance_offering = ReservedInstancesOffering.new(
33
- item.reserved_instances_offering_id,
34
- :config => config)
32
+ reserved_instance_offering = ReservedInstancesOffering.new_from(
33
+ :describe_reserved_instances_offerings, item,
34
+ item.reserved_instances_offering_id, :config => config)
35
35
 
36
36
  yield(reserved_instance_offering)
37
37
 
@@ -11,64 +11,25 @@
11
11
  # ANY KIND, either express or implied. See the License for the specific
12
12
  # language governing permissions and limitations under the License.
13
13
 
14
- require 'aws/model'
15
- require 'aws/cacheable'
14
+ require 'aws/resource'
16
15
 
17
16
  module AWS
18
17
  class EC2
19
18
 
20
19
  # @private
21
- class Resource
20
+ class Resource < AWS::Resource
22
21
 
23
- include Model
24
- include Cacheable
25
-
26
- def initialize(*args)
27
- super
28
- @memoized_attributes = {}
29
- if options = args.last and options.kind_of?(Hash)
30
- self.class.memoized_attributes.each do |att|
31
- @memoized_attributes[att] = options[att] if options.key?(att)
32
- end
33
- end
34
- end
35
-
36
- def inspect
37
- "<#{self.class}:#{__resource_id__}>"
38
- end
39
-
40
- def local_cache_key
41
- "#{self.class}:#{__resource_id__}"
42
- end
43
-
44
- def attributes_from_response(response)
45
- if atts = super
46
- self.class.memoized_attributes.each do |att|
47
- @memoized_attributes[att] = atts[att]
48
- end
49
- atts
50
- end
51
- end
52
-
53
- def ==(other)
54
- other.kind_of?(self.class) and
55
- __resource_id__ == other.__resource_id__
22
+ # @private
23
+ protected
24
+ def resource_identifiers
25
+ [[resource_id_method, send(resource_id_method)]]
56
26
  end
57
27
 
58
- alias_method :eql?, :==
59
-
60
28
  protected
61
29
  def __resource_id__
62
30
  send(resource_id_method)
63
31
  end
64
32
 
65
- protected
66
- def find_in_response(resp)
67
- resp.send(plural_name + "_set").find do |obj|
68
- obj.send(response_id_method) == __resource_id__
69
- end
70
- end
71
-
72
33
  protected
73
34
  def response_id_method
74
35
  # e.g. instance_id
@@ -93,74 +54,54 @@ module AWS
93
54
  end
94
55
 
95
56
  protected
96
- def describe_call
97
- name = self.class.describe_call_name
98
- if client.respond_to?(name)
99
- client.send(name, Hash[[[(response_id_method.to_s + "s").to_sym,
100
- [__resource_id__]]]])
101
- else
102
- raise NotImplementedError
103
- end
104
- end
105
-
106
- protected
107
- def describe_attribute_call(attribute_name)
108
- name = describe_attribute_call_name
109
- client.send(name, Hash[[[response_id_method.to_sym,
110
- __resource_id__],
111
- [:attribute, attribute_name]]])
57
+ def get_resource attribute
58
+ describe_call
112
59
  end
113
60
 
114
61
  protected
115
- def get_mutable_attribute(name)
116
- att_name = Inflection.class_name(name.to_s)
117
- att_name = att_name[0,1].downcase + att_name[1..-1]
118
- method_name = "describe_#{inflected_name}_attribute"
119
- resp = client.send(method_name,
120
- Hash[[[:"#{inflected_name}_id", __resource_id__],
121
- [:attribute, att_name]]])
122
- if att = resp.send(name) and
123
- att.respond_to?(:value)
124
- att.value
62
+ def retrieve_attribute attribute_or_attribute_name, &block
63
+ if attribute_or_attribute_name.is_a?(Symbol)
64
+ attribute = self.class.attributes[attribute_or_attribute_name]
125
65
  else
126
- nil
66
+ attribute = attribute_or_attribute_name
127
67
  end
68
+ super(attribute, &block)
128
69
  end
129
70
 
130
71
  protected
131
- def set_mutable_attribute(name, input_value)
132
- value = send("translate_input_for_#{name}", input_value) if
133
- respond_to?("translate_input_for_#{name}")
134
- opts = {}
135
- opts[name] = { :value => value }
136
- opts["#{inflected_name}_id".to_sym] = __resource_id__
137
- method_name = "modify_#{inflected_name}_attribute"
138
- resp = client.send(method_name, opts)
139
- input_value
72
+ def describe_call
73
+ options = { :"#{response_id_method}s" => [__resource_id__] }
74
+ client.send(describe_call_name, options)
140
75
  end
141
76
 
142
77
  protected
143
- def attributes_from_response_object(obj)
144
- atts = {}
145
- self.class.describe_call_attributes.each do |att, response_att|
146
- raw_value = (obj.send(response_att) if obj.respond_to?(response_att))
147
- translated = send("translate_describe_output_for_#{response_att}", raw_value)
148
- atts[att] = translated
149
- end
150
- atts
78
+ def describe_attribute_call(attribute)
79
+ name = describe_attribute_call_name
80
+
81
+ attr_opt_name = Inflection.class_name(attribute.get_as.to_s)
82
+ attr_opt_name = attr_opt_name[0,1].downcase + attr_opt_name[1..-1]
83
+
84
+ client.send(name, Hash[[[response_id_method.to_sym,
85
+ __resource_id__],
86
+ [:attribute, attr_opt_name]]])
151
87
  end
152
88
 
153
89
  protected
154
- def attributes_from_describe_attribute_response(resp)
155
- requested_att = resp.request_options[:attribute]
156
- return nil unless
157
- resp.request_options[response_id_method.to_sym] == __resource_id__
90
+ def update_resource attribute, value
91
+ options = {}
92
+ options[attribute.set_as] = { :value => value }
93
+ options[:"#{inflected_name}_id"] = __resource_id__
94
+ method_name = "modify_#{inflected_name}_attribute"
95
+ client.send(method_name, options)
96
+ end
158
97
 
159
- response_att = Inflection.ruby_name(requested_att)
160
- if getter = self.class.mutable_attributes[response_att.to_sym]
161
- raw_value = resp.send(response_att)
162
- translated = send("translate_describe_attribute_output_for_#{response_att}", raw_value)
163
- Hash[[[getter, translated]]]
98
+ # required for tagged item, which most ec2 resources are
99
+ protected
100
+ def find_in_response response
101
+ self.class.attribute_providers.each do |provider|
102
+ if provider.request_types.include?(response.request_type)
103
+ return send(provider.finder_method, response)
104
+ end
164
105
  end
165
106
  end
166
107
 
@@ -168,7 +109,7 @@ module AWS
168
109
 
169
110
  protected
170
111
  def describe_call_name
171
- name = "describe_#{plural_name}"
112
+ :"describe_#{plural_name}"
172
113
  end
173
114
 
174
115
  protected
@@ -202,134 +143,12 @@ module AWS
202
143
  extend InflectionMethods
203
144
  include InflectionMethods
204
145
 
205
- # @private
206
- class AttributeBuilder
207
-
208
- include InflectionMethods
209
-
210
- def initialize(klass, name, type)
211
- @klass = klass
212
- @name = name
213
- @type = type
214
- translate_input { |v| v }
215
- translate_output { |v| v }
216
- end
217
-
218
- def translate_input(&blk)
219
- @klass.send(:define_method, "translate_input_for_#{@name}", &blk)
220
- end
221
-
222
- def translate_output(&blk)
223
- @klass.send(:define_method, output_translator(@name, @type), &blk)
224
- end
225
-
226
- def self.eval(klass, name, type, opts = {}, &blk)
227
- i = new(klass, name, type)
228
- i.instance_eval do
229
- translate_output { |v| v.tr("-","_").to_sym if v } if opts[:to_sym]
230
- translate_output { |v| v.value if v } if opts[:value_wrapper]
231
- instance_eval(&blk) if blk
232
- end
233
- end
234
- end
235
-
236
- class NotFound < StandardError; end
237
-
238
146
  class << self
239
147
 
240
- def memoized_attributes; []; end
241
-
242
148
  # @private
243
149
  protected
244
150
  def describe_call_attribute(name, opts = {}, &blk)
245
- getter_name = opts[:getter] || name
246
-
247
- # define the accessor
248
- define_describe_call_getter(getter_name, opts) do |*args|
249
- begin
250
- retrieve_attribute(getter_name) { describe_call }
251
- rescue Cacheable::NoData => e
252
- name = Inflection.ruby_name(self.class.name).tr("_", " ")
253
- raise NotFound, "unable to find the #{name}"
254
- end
255
- end
256
-
257
- # ensure we are populating from the describe call
258
- populate_from describe_call_name do |resp|
259
- if obj = find_in_response(resp)
260
- attributes_from_response_object(obj)
261
- end
262
- end
263
-
264
- # add it to the list of attributes to populate from the response object
265
- add_to_attribute_map(:describe_call_attributes, getter_name, name)
266
-
267
- if opts[:memoize]
268
- all_memoized = memoized_attributes
269
- all_memoized << getter_name
270
- MetaUtils.extend_method(self, :memoized_attributes) { all_memoized }
271
- end
272
-
273
- # evaluate translators
274
- AttributeBuilder.eval(self, name, :describe, opts, &blk)
275
- end
276
-
277
- protected
278
- def add_to_attribute_map(map_name, key, value)
279
- all_attributes = {}
280
- all_attributes = send(map_name) if respond_to?(map_name)
281
- all_attributes[key] = value
282
- MetaUtils.extend_method(self, map_name) do
283
- all_attributes
284
- end
285
- end
286
-
287
- protected
288
- def define_describe_call_getter(getter_name, opts, &block)
289
- if opts[:memoize]
290
- original_block = block
291
- block = lambda do
292
- if @memoized_attributes.has_key?(getter_name)
293
- @memoized_attributes[getter_name]
294
- else
295
- instance_eval(&original_block)
296
- end
297
- end
298
- end
299
- define_method(getter_name, &block)
300
- end
301
-
302
- # @private
303
- def mutable_attribute(name, opts = {}, &blk)
304
- getter = opts[:getter] || name
305
- setter = opts[:setter] || "#{name}="
306
-
307
- # e.g. "instanceType" or "blockDeviceMapping"
308
- # as passed to the :attribute option of the service call
309
- request_name = Inflection.class_name(name.to_s)
310
- request_name = request_name[0,1].downcase + request_name[1..-1]
311
-
312
- # define getter
313
- define_method(getter) do
314
- retrieve_attribute(getter) { describe_attribute_call(request_name) }
315
- end
316
-
317
- # define setter
318
- define_method(setter) do |input_value|
319
- set_mutable_attribute(name, input_value)
320
- end unless opts[:setter] == false
321
-
322
- # make sure we will populate from this type of response
323
- populate_from describe_attribute_call_name do |resp|
324
- attributes_from_describe_attribute_response(resp)
325
- end
326
-
327
- # describe how to populate this attribute
328
- add_to_attribute_map(:mutable_attributes, name, getter)
329
-
330
- # evaluate translations, etc.
331
- AttributeBuilder.eval(self, name, :describe_attribute,
332
- { :value_wrapper => true }.merge(opts), &blk)
151
+ attribute(name, opts, &blk)
333
152
  end
334
153
 
335
154
  end