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
@@ -21,26 +21,29 @@ module AWS
21
21
 
22
22
  # Represents an Amazon Machine Image (AMI).
23
23
  #
24
+ # @attr_reader [String] name The name of the AMI that was provided
25
+ # during image creation.
26
+ #
24
27
  # @attr [String] description A description of the image.
25
28
  #
26
29
  # @attr_reader [String] location The location of the AMI.
27
30
  #
28
31
  # @attr_reader [Symbol] state Current state of the AMI. If the
29
- # state is +:available+, the image is successfully registered
30
- # and available for launching. Valid values:
32
+ # state is +:available+, the image is successfully registered
33
+ # and available for launching. Valid values:
34
+ # * +:available+
35
+ # * +:pending+
36
+ # * +:failed+
31
37
  #
32
- # * +:available+
33
- # * +:pending+
34
- # * +:failed+
38
+ # @attr_reader [String] owner_id The AWS account ID of the image owner.
35
39
  #
36
- # @attr_reader [String] owner_id AWS account ID of the image
37
- # owner.
40
+ # @attr_reader [String] owner_alias The AWS account alias (e.g.,
41
+ # +"amazon"+) or AWS account ID that owns the AMI.
38
42
  #
39
- # @attr_reader [Symbol] architecture The architecture of the
43
+ # @attr_reader [Symbol] architecture The architecture of the
40
44
  # image (e.g. +:i386+).
41
45
  #
42
- # @attr_reader [Symbol] type The type of image. Valid values:
43
- #
46
+ # @attr_reader [Symbol] type The type of image. Valid values are:
44
47
  # * +:machine+
45
48
  # * +:kernel+
46
49
  # * +:ramdisk+
@@ -62,140 +65,152 @@ module AWS
62
65
  #
63
66
  # [message] A textual description of the state change.
64
67
  #
65
- # @attr_reader [String] owner_alias The AWS account alias (e.g.,
66
- # +"amazon"+) or AWS account ID that owns the AMI.
67
- #
68
- # @attr_reader [String] name The name of the AMI that was
69
- # provided during image creation.
70
- #
71
- # @attr [String] description A free-form description of the AMI.
72
- # May contain up to 255 characters.
73
- #
74
68
  # @attr_reader [Symbol] root_device_type The root device type
75
69
  # used by the AMI. Possible values:
76
- #
77
70
  # * +:ebs+
78
71
  # * +:instance_store+
79
72
  #
80
73
  # @attr_reader [String] root_device_name The root device name
81
74
  # (e.g., +"/dev/sda1"+, or +"xvda"+).
82
75
  #
83
- # @attr_reader [Hash] block_device_mappings A hash of block
84
- # device mappings for the image. In each entry, the key is
85
- # the device name (e.g. +"/dev/sda1"+) and the value is an
86
- # object with the following methods that return information
87
- # about the block device:
88
- #
89
- # [snapshot_id] The ID of the snapshot that will be used to
90
- # create this device (may be nil).
91
- #
92
- # [volume_size] The size of the volume, in GiBs.
93
- #
94
- # [delete_on_termination] True if the Amazon EBS volume is
95
- # deleted on instance termination.
96
- #
97
- # @attr_reader [Array<String>] product_codes Returns an array of
98
- # product codes attached to this instance.
99
- #
100
76
  # @attr_reader [Symbol] virtualization_type The type of
101
77
  # virtualization of the AMI. Possible values:
102
- #
103
78
  # * +:paravirtual+
104
79
  # * +:hvm+
105
80
  #
106
- # @attr_reader [Symbol] hypervisor The image's hypervisor type.
107
- # Possible values:
108
- #
81
+ # @attr_reader [Symbol] hypervisor The image's hypervisor type.
82
+ # Possible values are:
109
83
  # * +:ovm+
110
84
  # * +:xen+
85
+ #
86
+ # @attr_reader [Array<String>] product_codes Returns an array of
87
+ # product codes attached to this instance.
88
+ #
111
89
  class Image < Resource
112
90
 
113
91
  include TaggedItem
114
92
  include HasPermissions
115
- alias_method :launch_permissions, :permissions
116
-
117
- # The ID of the AMI.
118
- attr_reader :id
119
93
 
120
94
  # @private
121
- def initialize(id, opts = {})
95
+ def initialize id, options = {}
122
96
  @id = id
123
- super(opts)
97
+ super
98
+ end
99
+
100
+ # @return [String] The ID of the AMI.
101
+ attr_reader :id
102
+
103
+ attribute :name, :static => true
104
+
105
+ mutable_attribute :description
106
+
107
+ attribute :location, :as => :image_location, :static => true
108
+
109
+ attribute :state, :as => :image_state, :to_sym => true
110
+
111
+ attribute :owner_id, :as => :image_owner_id, :static => true
112
+
113
+ attribute :owner_alias, :as => :image_owner_alias, :static => true
114
+
115
+ attribute :architecture, :to_sym => true, :static => true
116
+
117
+ attribute :type, :as => :image_type, :to_sym => true, :static => true
118
+
119
+ attribute :kernel_id, :static => true
120
+
121
+ attribute :ramdisk_id, :static => true
122
+
123
+ attribute :platform, :static => true
124
+
125
+ attribute :state_reason
126
+
127
+ attribute :root_device_type, :to_sym => true, :static => true
128
+
129
+ attribute :root_device_name, :static => true
130
+
131
+ attribute :virtualization_type, :to_sym => true, :static => true
132
+
133
+ attribute :hypervisor, :to_sym => true, :static => true
134
+
135
+ attribute :block_device_mapping
136
+ protected :block_device_mapping
137
+
138
+ attribute :product_codes, :static => true do
139
+ translates_output do |list|
140
+ (list || []).collect{|item| item.product_code }
141
+ end
142
+ end
143
+
144
+ populates_from(:describe_images) do |resp|
145
+ resp.image_index[id]
146
+ end
147
+
148
+ alias_method :launch_permissions, :permissions
149
+
150
+ # @return [Hash] Returns a hash of block
151
+ # device mappings for the image. In each entry, the key is
152
+ # the device name (e.g. +"/dev/sda1"+) and the value is an
153
+ # object with the following methods that return information
154
+ # about the block device:
155
+ #
156
+ # [snapshot_id] The ID of the snapshot that will be used to
157
+ # create this device (may be nil).
158
+ #
159
+ # [volume_size] The size of the volume, in GiBs.
160
+ #
161
+ # [delete_on_termination] True if the Amazon EBS volume is
162
+ # deleted on instance termination.
163
+ def block_device_mappings
164
+ (block_device_mapping || []).inject({}) do |h,mapping|
165
+ h[mapping.device_name] = mapping.ebs
166
+ h
167
+ end
124
168
  end
125
169
 
126
170
  # Deregisters this AMI. Once deregistered, the AMI cannot be
127
171
  # used to launch new instances.
172
+ # @return [nil]
128
173
  def deregister
129
174
  client.deregister_image(:image_id => id)
175
+ nil
130
176
  end
177
+
131
178
  alias_method :delete, :deregister
132
179
 
133
- # Runs a single instance of this image.
134
- #
135
- # @param [Hash] opts Additional options for running the
136
- # instance. See {InstanceCollection#create} for a full list
137
- # of supported options.
180
+ # Runs a single instance of this image.
138
181
  #
139
- # @return [Instance] An object representing the new instance.
140
- def run_instance(opts = {})
141
- InstanceCollection.new(:config => config).
142
- create(opts.merge(:image => self))
182
+ # @param [Hash] options
183
+ # @option (see InstanceCollection#create)
184
+ # @return (see InstanceCollection#create)
185
+ def run_instance options = {}
186
+ instances = InstanceCollection.new(:config => config)
187
+ instances.create(options.merge(:image => self))
143
188
  end
144
189
 
145
190
  # Runs multiple instances of this image.
146
191
  #
147
- # @param count How many instances to request. You can specify
192
+ # @param [Integer] count How many instances to request. You can specify
148
193
  # this either as an integer or as a Range, to indicate the
149
194
  # minimum and maximum number of instances to run. Note that
150
195
  # for a new account you can request at most 20 instances at
151
196
  # a time.
152
- #
153
- # @param [Hash] opts Additional options for running the
154
- # instance. See {InstanceCollection#create} for a full list
155
- # of supported options.
156
- #
157
- # @return [Array] An array containing an {Instance} object for
197
+ # @param [Hash] options
198
+ # @option (see InstanceCollection#create)
199
+ # @return [Array<Instance>] An array containing an {Instance} object for
158
200
  # each instance that was run.
159
- def run_instances(count, opts = {})
160
- InstanceCollection.new(:config => config).
161
- create(opts.merge(:image => self,
162
- :count => count))
201
+ def run_instances count, options = {}
202
+ run_instance(options.merge(:count => count))
163
203
  end
164
204
 
165
- # @return [Boolean] +true+ if the AMI exists (is returned by
166
- # the DescribeImages action).
205
+ # @return [Boolean] Returns +true+ if the AMI exists (is returned by
206
+ # the DescribeImages action).
167
207
  def exists?
168
- resp = client.describe_images(:filters =>
169
- [{ :name => "image-id",
170
- :values => [id] }]) and
171
- !resp.images_set.empty?
208
+ resp = client.describe_images(:filters => [
209
+ { :name => "image-id", :values => [id] }
210
+ ])
211
+ !resp.images_set.empty?
172
212
  end
173
213
 
174
- mutable_attribute :description
175
- # use describe_images to get it, so it will work with public images
176
- describe_call_attribute :description
177
-
178
- describe_call_attribute :name, :memoize => true
179
- describe_call_attribute(:image_location,
180
- :getter => :location,
181
- :memoize => true)
182
- describe_call_attribute :image_state, :getter => :state, :to_sym => true
183
- describe_call_attribute(:image_owner_id,
184
- :getter => :owner_id,
185
- :memoize => true)
186
- describe_call_attribute(:image_owner_alias,
187
- :getter => :owner_alias,
188
- :memoize => true)
189
- describe_call_attribute(:architecture,
190
- :to_sym => true,
191
- :memoize => true)
192
- describe_call_attribute(:image_type,
193
- :getter => :type,
194
- :to_sym => true,
195
- :memoize => true)
196
-
197
- describe_call_attribute :kernel_id, :memoize => true
198
-
199
214
  # @return [Image] The kernel associated with the image, if
200
215
  # any. Only applicable for machine images.
201
216
  def kernel
@@ -204,8 +219,6 @@ module AWS
204
219
  end
205
220
  end
206
221
 
207
- describe_call_attribute :ramdisk_id, :memoize => true
208
-
209
222
  # @return [Image] The RAM disk associated with the image, if
210
223
  # any. Only applicable for machine images.
211
224
  def ramdisk
@@ -214,30 +227,6 @@ module AWS
214
227
  end
215
228
  end
216
229
 
217
- describe_call_attribute :platform, :memoize => true
218
- describe_call_attribute :state_reason
219
- describe_call_attribute(:root_device_type,
220
- :to_sym => true,
221
- :memoize => true)
222
- describe_call_attribute :root_device_name
223
- describe_call_attribute :virtualization_type, :to_sym => true
224
- describe_call_attribute :hypervisor, :to_sym => true
225
- describe_call_attribute(:block_device_mapping,
226
- :getter => :block_device_mappings) do
227
- translate_output do |mappings|
228
- (mappings || []).inject({}) do |h, mapping|
229
- h[mapping.device_name] = mapping.ebs
230
- h
231
- end
232
- end
233
- end
234
-
235
- describe_call_attribute :product_codes, :memoize => true do
236
- translate_output do |list|
237
- (list || []).collect{|item| item.product_code }
238
- end
239
- end
240
-
241
230
  # Adds one or more product codes:
242
231
  #
243
232
  # image.add_product_codes 'ABCXYZ', 'MNOPQR'
@@ -261,11 +250,6 @@ module AWS
261
250
  "launchPermission"
262
251
  end
263
252
 
264
- protected
265
- def find_in_response(resp)
266
- resp.image_index[id]
267
- end
268
-
269
253
  end
270
254
 
271
255
  end
@@ -79,15 +79,14 @@ module AWS
79
79
 
80
80
  # @yield [image] Each image in the collection.
81
81
  # @return [nil]
82
- def each(&block)
82
+ def each &block
83
83
  opts = {}
84
- opts[:owners] = @owners.map { |id| id.to_s } unless
85
- @owners.empty?
84
+ opts[:owners] = @owners.map { |id| id.to_s } unless @owners.empty?
86
85
  opts[:executable_users] = @executable_users.map { |id| id.to_s } unless
87
86
  @executable_users.empty?
88
87
  response = filtered_request(:describe_images, opts)
89
88
  response.images_set.each do |i|
90
- image = Image.new(i.image_id, :config => config)
89
+ image = Image.new_from(:describe_images, i, i.image_id, :config => config)
91
90
  yield(image)
92
91
  end
93
92
  nil
@@ -194,7 +193,7 @@ module AWS
194
193
  # to delete the volume when the
195
194
  # instance is terminated.
196
195
  # @return [Image]
197
- def create(options = {})
196
+ def create options = {}
198
197
  resp = case
199
198
  when options[:instance_id]
200
199
  client.create_image(options)
@@ -214,7 +213,7 @@ module AWS
214
213
  "expected instance_id, image_location, " +
215
214
  "or root_device_name")
216
215
  end
217
- self[resp.image_id]
216
+ Image.new(resp.image_id, :config => config)
218
217
  end
219
218
 
220
219
  # @private
@@ -33,11 +33,11 @@ module AWS
33
33
  # The instance must be in a stopped state to change user data;
34
34
  # for example:
35
35
  #
36
- # i.user_data # => "HELLO"
37
- # i.status # => :running
38
- # i.user_data = "GOODBYE" # raises an exception
39
- # i.stop; sleep 1 until i.status == :stopped
40
- # i.user_data = "GOODBYE" # => "GOODBYE"
36
+ # i.user_data # => "HELLO"
37
+ # i.status # => :running
38
+ # i.user_data = "GOODBYE" # raises an exception
39
+ # i.stop; sleep 1 until i.status == :stopped
40
+ # i.user_data = "GOODBYE" # => "GOODBYE"
41
41
  #
42
42
  # @attr [String] instance_type The instance type,
43
43
  # e.g. "m1.small". The instance must be in a stopped state to
@@ -73,7 +73,6 @@ module AWS
73
73
  # @attr_reader [Symbol] root_device_type The root device type
74
74
  # used by the AMI. The AMI can use an Amazon EBS or instance
75
75
  # store root device. Valid values:
76
- #
77
76
  # * +:ebs+
78
77
  # * +:instance_store+
79
78
  #
@@ -96,12 +95,21 @@ module AWS
96
95
  # @attr_reader [String] ip_address The IP address of the
97
96
  # instance.
98
97
  #
98
+ # @attr_reader [Symbol] status The instance status. Valid values are:
99
+ # * +:pending+
100
+ # * +:running+
101
+ # * +:shutting_down+
102
+ # * +:terminated+
103
+ # * +:stopping+
104
+ # * +:stopped+
105
+ #
106
+ # @attr_reader [Integer] status_code The numeric instance status code.
107
+ #
99
108
  # @attr_reader [Symbol] architecture The architecture of the
100
109
  # image.
101
110
  #
102
111
  # @attr_reader [Symbol] virtualization_type The instance's
103
112
  # virtualization type. Valid values:
104
- #
105
113
  # * +:paravirtual+
106
114
  # * +:hvm+
107
115
  #
@@ -117,7 +125,6 @@ module AWS
117
125
  #
118
126
  # @attr_reader [Symbol] monitoring The status of CloudWatch
119
127
  # monitoring for the instance. Valid values:
120
- #
121
128
  # * +:enabled+
122
129
  # * +:disabled+
123
130
  # * +:pending+
@@ -133,12 +140,12 @@ module AWS
133
140
  #
134
141
  # @attr_reader [Symbol] hypervisor The instance's hypervisor
135
142
  # type. Valid values:
136
- #
137
143
  # * +:ovm+
138
144
  # * +:xen+
139
145
  #
140
146
  # @attr_reader [String] client_token Idempotency token you
141
147
  # provided when you launched the instance.
148
+ #
142
149
  class Instance < Resource
143
150
 
144
151
  include TaggedItem
@@ -150,111 +157,251 @@ module AWS
150
157
  def initialize(instance_id, opts = {})
151
158
  super
152
159
  @id = instance_id
153
- @reservation_attributes = {}
154
160
  end
155
161
 
156
162
  # @return [String] Returns the instance id.
157
163
  attr_reader :id
158
164
 
159
- # @return [Boolean] True if the instance exists according to
160
- # EC2.
161
- def exists?
162
- client.describe_instances(:filters =>
163
- [{
164
- :name => "instance-id",
165
- :values => [id]
166
- }]).instance_index.key?(id)
165
+ # @private
166
+ def self.reservation_attributes
167
+ @reservation_attributes ||= {}
167
168
  end
168
169
 
169
170
  # @private
170
- def self.instance_action(name)
171
- define_method(name) do
172
- client.send("#{name}_instances", :instance_ids => [id])
173
- nil
174
- end
171
+ def self.reservation_attribute name, options = {}, &block
172
+ attr = attribute(name, options, &block)
173
+ reservation_attributes[attr.name] = attr
174
+ end
175
+
176
+ # @private
177
+ def self.describe_call_attributes
178
+ @describe_call_attributes ||= {}
175
179
  end
176
180
 
177
- # Terminates the instance.
178
- # @return [nil]
179
- def terminate; end
180
- instance_action :terminate
181
- alias_method :delete, :terminate
181
+ # @private
182
+ def self.mutable_describe_attributes
183
+ @mutable_describe_attributes ||= {}
184
+ end
182
185
 
183
- # Reboots the instance.
184
- # @return [nil]
185
- def reboot; end
186
- instance_action :reboot
186
+ # @private
187
+ def self.describe_call_attribute name, options = {}, &block
188
+ attr = attribute(name, options, &block)
189
+ describe_call_attributes[attr.name] = attr
190
+ end
187
191
 
188
- # Starts the instance, assuming it is in a stopped state.
189
- # @see stop
190
- # @return [nil]
191
- def start; end
192
- instance_action :start
192
+ # @private
193
+ def self.mutable_describe_call_attribute name, options = {}, &block
194
+ attr = mutable_attribute(name, options, &block)
195
+ describe_call_attributes[attr.name] = attr
196
+ end
193
197
 
194
- # Stops the instance, eventually putting it into a stopped state.
195
- # @return [nil]
196
- def stop; end
197
- instance_action :stop
198
+ # @private
199
+ def self.mutable_describe_attribute name, options = {}, &block
200
+ attr = mutable_attribute(name, options, &block)
201
+ mutable_describe_attributes[attr.name] = attr
202
+ end
203
+
204
+ reservation_attribute :reservation_id, :static => true
205
+
206
+ reservation_attribute :owner_id, :static => true
207
+
208
+ reservation_attribute :requester_id, :static => true
198
209
 
199
210
  describe_call_attribute :private_dns_name
211
+
200
212
  describe_call_attribute :dns_name
213
+
201
214
  alias_method :public_dns_name, :dns_name
202
- describe_call_attribute :ami_launch_index
203
215
 
204
- describe_call_attribute :monitoring do
205
- translate_output { |v| v.state.to_sym if v }
216
+ describe_call_attribute :product_codes, :static => true
217
+
218
+ describe_call_attribute :ami_launch_index, :static => true
219
+
220
+ describe_call_attribute :monitoring do
221
+ translates_output {|v| v.state.to_sym }
206
222
  end
207
223
 
208
- # @return true if CloudWatch monitoring is enabled for this
209
- # instance.
210
- def monitoring_enabled?
211
- monitoring == :enabled
224
+ describe_call_attribute :private_ip_address
225
+
226
+ describe_call_attribute :ip_address
227
+
228
+ alias_method :public_ip_address, :ip_address
229
+
230
+ describe_call_attribute :architecture, :to_sym => true, :static => true
231
+
232
+ describe_call_attribute :root_device_type, :to_sym => true, :static => true
233
+
234
+ describe_call_attribute :root_device_name, :static => true
235
+
236
+ describe_call_attribute :block_device_mapping
237
+ protected :block_device_mapping
238
+
239
+ describe_call_attribute :instance_lifecycle, :to_sym => true
240
+
241
+ describe_call_attribute :virtualization_type, :to_sym => true, :static => true
242
+
243
+ describe_call_attribute :hypervisor, :to_sym => true, :static => true
244
+
245
+ describe_call_attribute :placement, :static => true
246
+
247
+ describe_call_attribute :state_transition_reason, :get_as => :reason
248
+
249
+ describe_call_attribute :launch_time, :static => true
250
+
251
+ describe_call_attribute :platform, :static => true
252
+
253
+ describe_call_attribute :client_token
254
+
255
+ describe_call_attribute :image_id
256
+
257
+ describe_call_attribute :key_name, :static => true
258
+
259
+ attribute :status do
260
+ translates_output{|state| state.name.tr("-","_").to_sym }
212
261
  end
213
262
 
214
- # Enables or disables monitoring for this instance.
215
- def monitoring_enabled=(value)
216
- if value
217
- client.monitor_instances(:instance_ids => [id])
218
- true
219
- else
220
- client.unmonitor_instances(:instance_ids => [id])
221
- false
263
+ attribute :status_code do
264
+ translates_output{|state| state.code }
265
+ end
266
+
267
+ mutable_describe_call_attribute :instance_type
268
+
269
+ mutable_describe_call_attribute :kernel_id, :set_as => :kernel
270
+
271
+ mutable_describe_call_attribute :ramdisk_id, :set_as => :ramdisk
272
+
273
+ mutable_describe_call_attribute :source_dest_check?,
274
+ :as => :source_dest_check
275
+
276
+ mutable_describe_call_attribute :group_set
277
+
278
+ mutable_describe_attribute(:user_data) do
279
+ translates_output {|v| Base64.decode64(v) if v }
280
+ translates_input {|v| Base64.encode64(v).strip }
281
+ end
282
+
283
+ mutable_describe_attribute :api_termination_disabled?,
284
+ :as => :disable_api_termination
285
+
286
+ mutable_describe_attribute :instance_initiated_shutdown_behavior
287
+
288
+ provider(:describe_instances) do |provider|
289
+ provider.find {|resp| resp.reservation_index[id] }
290
+ provider.provides *reservation_attributes.keys
291
+ end
292
+
293
+ provider(:describe_instances) do |provider|
294
+ provider.find {|resp| resp.instance_index[id] }
295
+ provider.provides *describe_call_attributes.keys
296
+ provider.provides :status, :get_as => :instance_state
297
+ provider.provides :status_code, :get_as => :instance_state
298
+ end
299
+
300
+ provider(:run_instances) do |provider|
301
+ provider.find {|resp| resp.instances_set.find{|i| i.instance_id == id } }
302
+ provider.provides *describe_call_attributes.keys
303
+ provider.provides :status, :get_as => :instance_state
304
+ provider.provides :status_code, :get_as => :instance_state
305
+ end
306
+
307
+ provider(:run_instances) do |provider|
308
+ provider.find {|resp| resp if resp.instances_set.find{|i| i.instance_id == id } }
309
+ provider.provides *reservation_attributes.keys
310
+ end
311
+
312
+ # These are the few attributes that are only returned by
313
+ # :desribe_instance_attribute and are *NOT* returned by
314
+ # :describe_instances. To make matters worse, only one of
315
+ # them is returned per :describe_instance_attribute call.
316
+ mutable_describe_attributes.values.each do |attr|
317
+
318
+ attr_opt_name = Inflection.class_name(attr.get_as.to_s)
319
+ attr_opt_name = attr_opt_name[0,1].downcase + attr_opt_name[1..-1]
320
+
321
+ provider(:describe_instance_attribute) do |provider|
322
+ provider.find do |resp|
323
+ if
324
+ resp.request_options[:instance_id] == id and
325
+ resp.request_options[:attribute] == attr_opt_name
326
+ then
327
+ return resp
328
+ end
329
+ end
330
+ provider.provides(attr.name, :value_wrapped => true)
222
331
  end
332
+
223
333
  end
224
334
 
225
- # @return [Array] A list of security groups
226
- # the instance is in. Each member is an instance of
227
- # {SecurityGroup}.
335
+ provider(:terminate_instances, :start_instances, :stop_instances) do |provider|
336
+ provider.find do |resp|
337
+ resp.instances_set.find { |i| i.instance_id == id }
338
+ end
339
+ provider.provides :status, :get_as => :current_state
340
+ provider.provides :status_code, :get_as => :current_state
341
+ end
342
+
343
+ provider(:monitor_instances, :unmonitor_instances) do |provider|
344
+ provider.find do |resp|
345
+ resp.instances_set.find { |i| i.instance_id == id }
346
+ end
347
+ provider.provides :monitoring
348
+ end
349
+
350
+ # @return [Array<SecurityGroup>] Returns a list of security
351
+ # groups the instance belongs to.
228
352
  def security_groups
229
- group_set
230
- end
231
- describe_call_attribute :group_set do
232
- translate_output do |groups|
233
- (groups || []).map do |g|
234
- SecurityGroup.new(g.group_id,
235
- :name => g.group_name,
236
- :config => config)
237
- end
353
+ (group_set || []).collect do |g|
354
+ SecurityGroup.new(g.group_id, :name => g.group_name, :config => config)
238
355
  end
239
356
  end
357
+
240
358
  alias_method :groups, :security_groups
241
359
 
242
- describe_call_attribute :private_ip_address
243
- describe_call_attribute :ip_address
244
- alias_method :public_ip_address, :ip_address
245
- describe_call_attribute :architecture, :to_sym => true
246
- describe_call_attribute :root_device_type, :to_sym => true
247
- describe_call_attribute :instance_lifecycle, :to_sym => true
360
+ # @return [Hash<String,Attachment>] Returns a hash of device mappings.
361
+ # The keys are device name strings (e.g. '/dev/sda') and the values
362
+ # are {Attachment} objects.
363
+ def block_device_mappings
364
+ (block_device_mapping || []).inject({}) do |m, mapping|
365
+ device = mapping.device_name
366
+ volume = Volume.new(mapping.ebs.volume_id, :config => config)
367
+ attachment = Attachment.new(volume, self, device, :config => config)
368
+ m[device] = attachment
369
+ m
370
+ end
371
+ end
372
+
373
+ # Enables monitoring for this instance.
374
+ # @return [nil]
375
+ def enable_monitoring
376
+ client.monitor_instances(:instance_ids => [id])
377
+ nil
378
+ end
379
+
380
+ # Disables monitoring for this instance.
381
+ # @return [nil]
382
+ def disable_monitoring
383
+ client.unmonitor_instances(:instance_ids => [id])
384
+ nil
385
+ end
386
+
387
+ # Enables or disables monitoring for this instance.
388
+ # @param [Boolean] state A true or false value. Enables monintoring
389
+ # for a true value, disables it for a false value.
390
+ def monitoring_enabled= value
391
+ value ? enable_monitoring : disable_monitoring
392
+ end
393
+
394
+ # @return [Booelan] Returns +true+ if CloudWatch monitoring is
395
+ # enabled for this instance.
396
+ def monitoring_enabled?
397
+ monitoring == :enabled
398
+ end
248
399
 
249
400
  # @return [Boolean] true if the instance is a Spot instance.
250
401
  def spot_instance?
251
402
  instance_lifecycle == :spot
252
403
  end
253
404
 
254
- describe_call_attribute :virtualization_type, :to_sym => true
255
- describe_call_attribute :hypervisor, :to_sym => true
256
- describe_call_attribute :placement
257
-
258
405
  # @return [String] The availability zone where the instance is
259
406
  # running.
260
407
  def availability_zone
@@ -263,20 +410,11 @@ module AWS
263
410
  end
264
411
  end
265
412
 
266
- describe_call_attribute :reason, :getter => :state_transition_reason
267
-
268
- describe_call_attribute :launch_time
269
- describe_call_attribute :platform
270
- describe_call_attribute :client_token
271
- describe_call_attribute :image_id
272
-
273
413
  # @return [Image] The AMI used to launch the instance.
274
414
  def image
275
415
  Image.new(image_id, :config => config)
276
416
  end
277
417
 
278
- describe_call_attribute :key_name
279
-
280
418
  # @return [KeyPair] The key pair with which this instance was
281
419
  # associated at launch.
282
420
  def key_pair
@@ -306,110 +444,9 @@ module AWS
306
444
  # be guaranteed.
307
445
  #
308
446
  # @return [Image] The newly created image.
309
- def create_image(name, options = {})
310
- ImageCollection.new(:config => config).
311
- create(options.merge(:instance_id => id,
312
- :name => name))
313
- end
314
-
315
- # @private
316
- def self.reservation_attribute(name)
317
- define_method(name) do
318
- @reservation_attributes[name] ||= retrieve_attribute(name) do
319
- client.describe_instances(:instance_ids => [id])
320
- end
321
- end
322
- MetaUtils.class_extend_method(self, :attributes_from_reservation) do |r, i|
323
- if atts = super(r, i)
324
- atts[name] = (r.send(name) if r.respond_to?(name))
325
- atts
326
- end
327
- end
328
- end
329
-
330
- MetaUtils.class_extend_method(self, :attributes_from_reservation) do |r, i|
331
- attributes_from_response_object(i) if i
332
- end
333
-
334
- reservation_attribute :reservation_id
335
- reservation_attribute :owner_id
336
- reservation_attribute :requester_id
337
-
338
- mutable_attribute :user_data do
339
- # mutable_attribute unwraps the ".value" unless you translate
340
- # the output yourself
341
- translate_output { |v| Base64.decode64(v.value) if v }
342
- translate_input { |v| Base64.encode64(v).strip }
343
- end
344
-
345
- describe_call_attribute :instance_type
346
- mutable_attribute :instance_type
347
-
348
- mutable_attribute :source_dest_check, :getter => :source_dest_check?
349
- mutable_attribute(:disable_api_termination,
350
- :getter => :api_termination_disabled?,
351
- :setter => :api_termination_disabled=)
352
- mutable_attribute :instance_initiated_shutdown_behavior
353
- describe_call_attribute :kernel_id
354
- mutable_attribute :kernel, :getter => :kernel_id, :setter => :kernel_id=
355
-
356
- ##
357
- # Resets the kernel to its default value.
358
- def reset_kernel_id
359
- client.reset_instance_attribute(:instance_id => id,
360
- :attribute => "kernel").return
361
- end
362
-
363
- describe_call_attribute :ramdisk_id
364
- mutable_attribute :ramdisk, :getter => :ramdisk_id, :setter => :ramdisk_id=
365
-
366
- ##
367
- # Resets the RAM disk to its default value.
368
- def reset_ramdisk_id
369
- client.reset_instance_attribute(:instance_id => id,
370
- :attribute => "ramdisk").return
371
- end
372
-
373
- describe_call_attribute :root_device_name
374
- mutable_attribute :root_device_name, :setter => false
375
-
376
- # @return [Hash] A hash in which each key is the name of a
377
- # device that is mapped to an EBS volume. The value of each
378
- # entry is an object describing the volume, including the
379
- # following fields:
380
- #
381
- # [status] The status of the attachment (e.g. "attached").
382
- #
383
- # [volume_id] The ID of the EBS volume.
384
- #
385
- # [attach_time] The time at which the volume was attached.
386
- #
387
- # [delete_on_termination?] True if the volume will be
388
- # automatically deleted when the
389
- # instance terminates.
390
- def block_device_mappings; end
391
-
392
- describe_call_attribute(:block_device_mapping,
393
- :getter => :block_device_mappings) do
394
- translate_output { |v| translate_block_device_mappings(v) }
395
- end
396
- mutable_attribute(:block_device_mapping,
397
- :setter => false,
398
- :getter => :block_device_mappings) do
399
- translate_output { |v| translate_block_device_mappings(v) }
400
- end
401
-
402
- # @return [Symbol] The status of the instance. Valid values:
403
- # * +:pending+
404
- # * +:running+
405
- # * +:shutting_down+
406
- # * +:terminated+
407
- # * +:stopping+
408
- # * +:stopped+
409
- def status
410
- retrieve_attribute(:status) do
411
- client.describe_instances(:instance_ids => [id])
412
- end
447
+ def create_image name, options = {}
448
+ images = ImageCollection.new(:config => config)
449
+ images.create(options.merge(:instance_id => id, :name => name))
413
450
  end
414
451
 
415
452
  # Associates the elastic IP address with this instance.
@@ -421,7 +458,8 @@ module AWS
421
458
  def associate_elastic_ip elastic_ip
422
459
  client.associate_address(
423
460
  :public_ip => elastic_ip.to_s,
424
- :instance_id => self.id)
461
+ :instance_id => self.id
462
+ )
425
463
  nil
426
464
  end
427
465
 
@@ -438,66 +476,85 @@ module AWS
438
476
  end
439
477
  end
440
478
 
479
+ # @return [ElasticIp,nil] Returns an elastic IP address if one
480
+ # is associated with this instance, nil otherwise.
481
+ def elastic_ip
482
+ ips = ElasticIpCollection.new(:config => config)
483
+ ips.filter('instance-id', id).first
484
+ end
485
+
441
486
  # @return [Boolean] Returns true if an elastic IP address is
442
487
  # associated with this instance, false otherwise.
443
488
  def has_elastic_ip?
444
489
  !elastic_ip.nil?
445
490
  end
446
491
 
447
- # @return [ElasticIp,nil] Returns an elastic IP address if one
448
- # is associated with this instance, nil otherwise.
449
- def elastic_ip
450
- ElasticIpCollection.new(:config => config).
451
- filter('instance-id', id).first
492
+ # @return [Boolean] Returns true if the instance exists according to
493
+ # EC2.
494
+ def exists?
495
+ client.describe_instances(:filters => [
496
+ { :name => "instance-id", :values => [id] }
497
+ ]).instance_index.key?(id)
452
498
  end
453
499
 
454
- protected
455
- def find_in_response(resp)
456
- resp.instance_index[id]
500
+ # Resets the kernel to its default value.
501
+ def reset_kernel_id
502
+ client.reset_instance_attribute(
503
+ :instance_id => id, :attribute => "kernel").return
457
504
  end
458
505
 
459
- populate_from :describe_instances do |resp|
460
- if r = resp.reservation_index[id]
461
- attributes_from_reservation(r, resp.instance_index[id])
462
- end
506
+ # Resets the RAM disk to its default value.
507
+ def reset_ramdisk_id
508
+ client.reset_instance_attribute(
509
+ :instance_id => id, :attribute => "ramdisk").return
463
510
  end
464
511
 
465
- populate_from :run_instances do |resp|
466
- attributes_from_reservation(resp,
467
- resp.instances_set.
468
- find { |i| i.instance_id == id })
512
+ # Terminates the instance.
513
+ # @return [nil]
514
+ def terminate
515
+ instance_action :terminate
469
516
  end
517
+ alias_method :delete, :terminate
470
518
 
471
- [:terminate_instances,
472
- :start_instances,
473
- :stop_instances].each do |op|
474
- populate_from op do |resp|
475
- if i = resp.instances_set.find { |i| i.instance_id == id }
476
- { :status => i.current_state.name.tr("-","_").to_sym }
477
- end
478
- end
519
+ # Reboots the instance.
520
+ # @return [nil]
521
+ def reboot
522
+ instance_action :reboot
479
523
  end
480
524
 
481
- [:monitor_instances,
482
- :unmonitor_instances].each do |op|
483
- populate_from op do |resp|
484
- if i = resp.instances_set.find { |i| i.instance_id == id }
485
- { :monitoring =>
486
- attributes_from_response_object(i)[:monitoring] }
487
- end
488
- end
525
+ # Starts the instance, assuming it is in a stopped state.
526
+ # @see stop
527
+ # @return [nil]
528
+ def start
529
+ instance_action :start
530
+ end
531
+
532
+ # Stops the instance, eventually putting it into a stopped state.
533
+ # @return [nil]
534
+ def stop
535
+ instance_action :stop
489
536
  end
490
537
 
538
+ # @private
491
539
  protected
492
- def translate_block_device_mappings(mappings)
493
- mappings.inject({}) do |m, mapping|
494
- m[mapping.device_name] =
495
- Attachment.new(Volume.new(mapping.ebs.volume_id, :config => config),
496
- self,
497
- mapping.device_name,
498
- :config => config)
499
- m
500
- end if mappings
540
+ def find_in_response resp
541
+ resp.instance_index[id]
542
+ end
543
+
544
+ # @private
545
+ protected
546
+ def instance_action name
547
+ client.send("#{name}_instances", :instance_ids => [id])
548
+ nil
549
+ end
550
+
551
+ protected
552
+ def get_resource attribute
553
+ if self.class.mutable_describe_attributes.include?(attribute.name)
554
+ describe_attribute_call(attribute)
555
+ else
556
+ describe_call
557
+ end
501
558
  end
502
559
 
503
560
  protected