amazon-ec2 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,47 @@
1
+ # Amazon Web Services EC2 Query API Ruby Library
2
+ # This library has been packaged as a Ruby Gem
3
+ # by Glenn Rempe ( glenn @nospam@ elasticworkbench.com ).
4
+ #
5
+ # Source code and gem hosted on RubyForge
6
+ # under the Ruby License as of 12/14/2006:
7
+ # http://amazon-ec2.rubyforge.org
8
+
9
+ module EC2
10
+
11
+ class AWSAuthConnection
12
+
13
+ # The ModifyImageAttribute operation modifies an attribute of an AMI.
14
+ #
15
+ # Currently the only attribute supported is launchPermission. By
16
+ # modifying this attribute it is possible to make an AMI public or
17
+ # to grant specific users launch permissions for the AMI. To make the
18
+ # AMI public add the group=all attribute item. To grant launch permissions
19
+ # for a specific user add a userId=<userid> attribute item.
20
+ def modify_image_attribute(imageId, attribute, operationType, attributeValueHash)
21
+ params = {
22
+ "ImageId" => imageId,
23
+ "Attribute" => attribute,
24
+ "OperationType" => operationType
25
+ }
26
+ if attribute == "launchPermission"
27
+ params.merge!(pathlist("UserGroup", attributeValueHash[:userGroups])) if attributeValueHash.has_key? :userGroups
28
+ params.merge!(pathlist("UserId", attributeValueHash[:userIds])) if attributeValueHash.has_key? :userIds
29
+ end
30
+ ModifyImageAttributeResponse.new(make_request("ModifyImageAttribute", params))
31
+ end
32
+
33
+ # The DescribeImageAttribute operation returns information about an attribute of an AMI.
34
+ def describe_image_attribute(imageId, attribute)
35
+ params = { "ImageId" => imageId, "Attribute" => attribute }
36
+ DescribeImageAttributeResponse.new(make_request("DescribeImageAttribute", params))
37
+ end
38
+
39
+ # The ResetImageAttribute operation resets an attribute of an AMI to its default value.
40
+ def reset_image_attribute(imageId, attribute)
41
+ params = { "ImageId" => imageId, "Attribute" => attribute }
42
+ ResetImageAttributeResponse.new(make_request("ResetImageAttribute", params))
43
+ end
44
+
45
+ end
46
+
47
+ end
data/lib/EC2/images.rb ADDED
@@ -0,0 +1,87 @@
1
+ # Amazon Web Services EC2 Query API Ruby Library
2
+ # This library has been packaged as a Ruby Gem
3
+ # by Glenn Rempe ( glenn @nospam@ elasticworkbench.com ).
4
+ #
5
+ # Source code and gem hosted on RubyForge
6
+ # under the Ruby License as of 12/14/2006:
7
+ # http://amazon-ec2.rubyforge.org
8
+
9
+ module EC2
10
+
11
+ class AWSAuthConnection
12
+
13
+ # The RegisterImage operation registers an AMI with Amazon EC2.
14
+ # Images must be registered before they can be launched. Each
15
+ # AMI is associated with an unique ID which is provided by the
16
+ # EC2 service via the Registerimage operation. As part of the
17
+ # registration process, Amazon EC2 will retrieve the specified
18
+ # image manifest from Amazon S3 and verify that the image is
19
+ # owned by the user requesting image registration. The image
20
+ # manifest is retrieved once and stored within the Amazon EC2
21
+ # network. Any modifications to an image in Amazon S3 invalidate
22
+ # this registration. If you do have to make changes and upload
23
+ # a new image deregister the previous image and register the new image.
24
+ def register_image(imageLocation)
25
+ params = { "ImageLocation" => imageLocation }
26
+ RegisterImageResponse.new(make_request("RegisterImage", params))
27
+ end
28
+
29
+ # The DescribeImages operation returns information about AMIs available
30
+ # for use by the user. This includes both public AMIs (those available
31
+ # for any user to launch) and private AMIs (those owned by the user
32
+ # making the request and those owned by other users that the user
33
+ # making the request has explicit launch permissions for).
34
+ #
35
+ # The list of AMIs returned can be modified via optional lists of AMI IDs,
36
+ # owners or users with launch permissions. If all three optional lists
37
+ # are empty all AMIs the user has launch permissions for are returned.
38
+ # Launch permissions fall into three categories:
39
+ #
40
+ # Launch Permission Description
41
+ # * public The all group has launch permissions for the AMI. All users have
42
+ # launch permissions for these AMIs.
43
+ # * explicit The owner of the AMIs has granted a specific user launch permissions for the AMI.
44
+ # * implicit A user has implicit launch permissions for all AMIs he or she owns.
45
+ #
46
+ # If one or more of the lists are specified the result set is the intersection
47
+ # of AMIs matching the criteria of the individual lists.
48
+ #
49
+ # Providing the list of AMI IDs requests information for those AMIs only.
50
+ # If no AMI IDs are provided, information of all relevant AMIs will be
51
+ # returned. If an AMI is specified that does not exist a fault is returned.
52
+ # If an AMI is specified that exists but the user making the request does
53
+ # not have launch permissions for, then that AMI will not be included in
54
+ # the returned results.
55
+ #
56
+ # Providing the list of owners requests information for AMIs owned
57
+ # by the specified owners only. Only AMIs the user has launch permissions
58
+ # for are returned. The items of the list may be account ids for AMIs
59
+ # owned by users with those account ids, amazon for AMIs owned by Amazon
60
+ # or self for AMIs owned by the user making the request.
61
+ #
62
+ # The executable list may be provided to request information for AMIs
63
+ # that only the specified users have launch permissions for. The items of
64
+ # the list may be account ids for AMIs owned by the user making the request
65
+ # that the users with the specified account ids have explicit launch permissions
66
+ # for, self for AMIs the user making the request has explicit launch permissions
67
+ # for or all for public AMIs.
68
+ #
69
+ # Deregistered images will be included in the returned results for an
70
+ # unspecified interval subsequent to deregistration.
71
+ def describe_images(imageIds=[], owners=[], executableBy=[])
72
+ params = pathlist("ImageId", imageIds)
73
+ params.merge!(pathlist("Owner", owners))
74
+ params.merge!(pathlist("ExecutableBy", executableBy))
75
+ DescribeImagesResponse.new(make_request("DescribeImages", params))
76
+ end
77
+
78
+ # The DeregisterImage operation deregisters an AMI. Once deregistered,
79
+ # instances of the AMI may no longer be launched.
80
+ def deregister_image(imageId)
81
+ params = { "ImageId" => imageId }
82
+ DeregisterImageResponse.new(make_request("DeregisterImage", params))
83
+ end
84
+
85
+ end
86
+
87
+ end
@@ -0,0 +1,95 @@
1
+ # Amazon Web Services EC2 Query API Ruby Library
2
+ # This library has been packaged as a Ruby Gem
3
+ # by Glenn Rempe ( glenn @nospam@ elasticworkbench.com ).
4
+ #
5
+ # Source code and gem hosted on RubyForge
6
+ # under the Ruby License as of 12/14/2006:
7
+ # http://amazon-ec2.rubyforge.org
8
+
9
+ module EC2
10
+
11
+ class AWSAuthConnection
12
+
13
+ # The RunInstances operation launches a specified number of instances.
14
+ #
15
+ # Note:
16
+ # The Query version of RunInstances only allows instances of a
17
+ # single AMI to be launched in one call. This is different
18
+ # from the SOAP API call of the same name but similar to the
19
+ # ec2-run-instances command line tool.
20
+ #
21
+ # A call to RunInstances is guaranteed to start no fewer than the
22
+ # requested minimum. If there is insufficient capacity available
23
+ # then no instances will be started. Amazon EC2 will make a best
24
+ # effort attempt to satisfy the requested maximum values.
25
+ #
26
+ # Every instance is launched in a security group. This may be
27
+ # specified as part of the launch request. If a security group is
28
+ # not indicated then instances are started in a the default security group.
29
+ #
30
+ # An optional keypair ID may be provided for each image in the launch
31
+ # request. All instances that are created from images for which this
32
+ # is provided will have access to the associated public key at boot
33
+ # time (detailed below). This key may be used to provide secure access
34
+ # to an instance of an image on a per-instance basis. Amazon EC2 public
35
+ # images make use of this functionality to provide secure passwordless
36
+ # access to instances (and launching those images without a keypair ID
37
+ # will leave them inaccessible).
38
+ #
39
+ # The public key material is made available to the instance at boot
40
+ # time by placing it in a file named openssh_id.pub on a logical
41
+ # device that is exposed to the instance as /dev/sda2 (the ephemeral store).
42
+ # The format of this file is suitable for use as an entry within
43
+ # ~/.ssh/authorized_keys (the OpenSSH format). This can be done at boot
44
+ # time (as part of rclocal, for example) allowing for secure
45
+ # password-less access. As the need arises, other formats will
46
+ # also be considered.
47
+ def run_instances(imageId, kwargs={})
48
+ in_params = { :minCount=>1, :maxCount=>1, :keyname=>nil, :groupIds=>[], :userData=>nil, :base64Encoded=>false }
49
+ in_params.merge!(kwargs)
50
+ userData = Base64.encode64(userData) if userData and not base64Encoded
51
+
52
+ params = {
53
+ "ImageId" => imageId,
54
+ "MinCount" => in_params[:minCount].to_s,
55
+ "MaxCount" => in_params[:maxCount].to_s,
56
+ }.merge(pathlist("SecurityGroup", in_params[:groupIds]))
57
+
58
+ params["KeyName"] = in_params[:keyname] unless in_params[:keyname].nil?
59
+
60
+ RunInstancesResponse.new(make_request("RunInstances", params))
61
+ end
62
+
63
+ # The DescribeInstances operation returns information about instances owned
64
+ # by the user making the request.
65
+ #
66
+ # An optional list of instance IDs may be provided to request information
67
+ # for those instances only. If no instance IDs are provided, information of
68
+ # all relevant instances information will be returned. If an instance is
69
+ # specified that does not exist a fault is returned. If an instance is specified
70
+ # that exists but is not owned by the user making the request, then that
71
+ # instance will not be included in the returned results.
72
+ #
73
+ # Recently terminated instances will be included in the returned results
74
+ # for a small interval subsequent to their termination. This interval
75
+ # is typically of the order of one hour.
76
+ def describe_instances(instanceIds=[])
77
+ params = pathlist("InstanceId", instanceIds)
78
+ DescribeInstancesResponse.new(make_request("DescribeInstances", params))
79
+ end
80
+
81
+ # The TerminateInstances operation shuts down one or more instances.
82
+ # This operation is idempotent and terminating an instance that is
83
+ # in the process of shutting down (or already terminated) will succeed.
84
+ #
85
+ # Terminated instances remain visible for a short period of time
86
+ # (approximately one hour) after termination, after which their
87
+ # instance ID is invalidated.
88
+ def terminate_instances(instanceIds)
89
+ params = pathlist("InstanceId", instanceIds)
90
+ TerminateInstancesResponse.new(make_request("TerminateInstances", params))
91
+ end
92
+
93
+ end
94
+
95
+ end
@@ -0,0 +1,38 @@
1
+ # Amazon Web Services EC2 Query API Ruby Library
2
+ # This library has been packaged as a Ruby Gem
3
+ # by Glenn Rempe ( glenn @nospam@ elasticworkbench.com ).
4
+ #
5
+ # Source code and gem hosted on RubyForge
6
+ # under the Ruby License as of 12/14/2006:
7
+ # http://amazon-ec2.rubyforge.org
8
+
9
+ module EC2
10
+
11
+ class AWSAuthConnection
12
+
13
+ # The CreateKeyPair operation creates a new 2048 bit RSA keypair
14
+ # and returns a unique ID that can be used to reference this
15
+ # keypair when launching new instances.
16
+ def create_keypair(keyName)
17
+ params = { "KeyName" => keyName }
18
+ CreateKeyPairResponse.new(make_request("CreateKeyPair", params))
19
+ end
20
+
21
+ # The DescribeKeyPairs operation returns information about keypairs
22
+ # available for use by the user making the request. Selected keypairs
23
+ # may be specified or the list may be left empty if information for
24
+ # all registered keypairs is required.
25
+ def describe_keypairs(keyNames=[])
26
+ params = pathlist("KeyName", keyNames)
27
+ DescribeKeyPairsResponse.new(make_request("DescribeKeyPairs", params))
28
+ end
29
+
30
+ # The DeleteKeyPair operation deletes a keypair.
31
+ def delete_keypair(keyName)
32
+ params = { "KeyName" => keyName }
33
+ DeleteKeyPairResponse.new(make_request("DeleteKeyPair", params))
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,340 @@
1
+ # Amazon Web Services EC2 Query API Ruby Library
2
+ # This library has been packaged as a Ruby Gem
3
+ # by Glenn Rempe ( glenn @nospam@ elasticworkbench.com ).
4
+ #
5
+ # Source code and gem hosted on RubyForge
6
+ # under the Ruby License as of 12/14/2006:
7
+ # http://amazon-ec2.rubyforge.org
8
+
9
+ module EC2
10
+
11
+ class Response
12
+ attr_reader :http_response
13
+ attr_reader :http_xml
14
+ attr_reader :structure
15
+
16
+ ERROR_XPATH = "Response/Errors/Error"
17
+
18
+ def initialize(http_response)
19
+ @http_response = http_response
20
+ @http_xml = http_response.body
21
+ @is_error = false
22
+ if http_response.is_a? Net::HTTPSuccess
23
+ @structure = parse
24
+ else
25
+ @is_error = true
26
+ @structure = parse_error
27
+ end
28
+ end
29
+
30
+ def is_error?
31
+ @is_error
32
+ end
33
+
34
+ def parse_error
35
+ doc = Document.new(@http_xml)
36
+ element = XPath.first(doc, ERROR_XPATH)
37
+
38
+ errorCode = XPath.first(element, "Code").text
39
+ errorMessage = XPath.first(element, "Message").text
40
+
41
+ [["#{errorCode}: #{errorMessage}"]]
42
+ end
43
+
44
+ def parse
45
+ # Placeholder -- this method should be overridden in child classes.
46
+ nil
47
+ end
48
+
49
+ def to_s
50
+ @structure.collect do |line|
51
+ line.join("\t")
52
+ end.join("\n")
53
+ end
54
+
55
+ end
56
+
57
+
58
+ class DescribeImagesResponse < Response
59
+ ELEMENT_XPATH = "DescribeImagesResponse/imagesSet/item"
60
+ def parse
61
+ doc = Document.new(@http_xml)
62
+ lines = []
63
+
64
+ doc.elements.each(ELEMENT_XPATH) do |element|
65
+ imageId = XPath.first(element, "imageId").text
66
+ imageLocation = XPath.first(element, "imageLocation").text
67
+ imageOwnerId = XPath.first(element, "imageOwnerId").text
68
+ imageState = XPath.first(element, "imageState").text
69
+ isPublic = XPath.first(element, "isPublic").text
70
+ lines << ["IMAGE", imageId, imageLocation, imageOwnerId, imageState, isPublic]
71
+ end
72
+ lines
73
+ end
74
+ end
75
+
76
+
77
+ class RegisterImageResponse < Response
78
+ ELEMENT_XPATH = "RegisterImageResponse/imageId"
79
+ def parse
80
+ doc = Document.new(@http_xml)
81
+ lines = [["IMAGE", XPath.first(doc, ELEMENT_XPATH).text]]
82
+ end
83
+ end
84
+
85
+
86
+ class DeregisterImageResponse < Response
87
+ def parse
88
+ # If we don't get an error, the deregistration succeeded.
89
+ [["Image deregistered."]]
90
+ end
91
+ end
92
+
93
+
94
+ class CreateKeyPairResponse < Response
95
+ ELEMENT_XPATH = "CreateKeyPairResponse"
96
+ def parse
97
+ doc = Document.new(@http_xml)
98
+ element = XPath.first(doc, ELEMENT_XPATH)
99
+
100
+ keyName = XPath.first(element, "keyName").text
101
+ keyFingerprint = XPath.first(element, "keyFingerprint").text
102
+ keyMaterial = XPath.first(element, "keyMaterial").text
103
+
104
+ line = [["KEYPAIR", keyName, keyFingerprint], [keyMaterial]]
105
+ end
106
+ end
107
+
108
+
109
+ class DescribeKeyPairsResponse < Response
110
+ ELEMENT_XPATH = "DescribeKeyPairsResponse/keySet/item"
111
+ def parse
112
+ doc = Document.new(@http_xml)
113
+ lines = []
114
+
115
+ doc.elements.each(ELEMENT_XPATH) do |element|
116
+ keyName = XPath.first(element, "keyName").text
117
+ keyFingerprint = XPath.first(element, "keyFingerprint").text
118
+ lines << ["KEYPAIR", keyName, keyFingerprint]
119
+ end
120
+ lines
121
+ end
122
+ end
123
+
124
+
125
+ class DeleteKeyPairResponse < Response
126
+ def parse
127
+ # If we don't get an error, the deletion succeeded.
128
+ [["Keypair deleted."]]
129
+ end
130
+ end
131
+
132
+
133
+ class RunInstancesResponse < Response
134
+ ELEMENT_XPATH = "RunInstancesResponse"
135
+ def parse
136
+ doc = Document.new(@http_xml)
137
+ lines = []
138
+
139
+ rootelement = XPath.first(doc, ELEMENT_XPATH)
140
+
141
+ reservationId = XPath.first(rootelement, "reservationId").text
142
+ ownerId = XPath.first(rootelement, "ownerId").text
143
+ groups = nil
144
+ rootelement.elements.each("groupSet/item/groupId") do |element|
145
+ if not groups
146
+ groups = element.text
147
+ else
148
+ groups += "," + element.text
149
+ end
150
+ end
151
+ lines << ["RESERVATION", reservationId, ownerId, groups]
152
+
153
+ # rootelement = XPath.first(doc, ELEMENT_XPATH)
154
+ rootelement.elements.each("instancesSet/item") do |element|
155
+ instanceId = XPath.first(element, "instanceId").text
156
+ imageId = XPath.first(element, "imageId").text
157
+ instanceState = XPath.first(element, "instanceState/name").text
158
+ # Only for debug mode, which we don't support yet:
159
+ instanceStateCode = XPath.first(element, "instanceState/code").text
160
+ dnsName = XPath.first(element, "dnsName").text
161
+ # We don't return this, but still:
162
+ reason = XPath.first(element, "reason").text
163
+ lines << ["INSTANCE", instanceId, imageId, dnsName, instanceState]
164
+ end
165
+ lines
166
+ end
167
+ end
168
+
169
+
170
+ class DescribeInstancesResponse < Response
171
+ ELEMENT_XPATH = "DescribeInstancesResponse/reservationSet/item"
172
+ def parse
173
+ doc = Document.new(@http_xml)
174
+ lines = []
175
+
176
+ doc.elements.each(ELEMENT_XPATH) do |rootelement|
177
+ reservationId = XPath.first(rootelement, "reservationId").text
178
+ ownerId = XPath.first(rootelement, "ownerId").text
179
+ groups = nil
180
+ rootelement.elements.each("groupSet/item/groupId") do |element|
181
+ if not groups
182
+ groups = element.text
183
+ else
184
+ groups += "," + element.text
185
+ end
186
+ end
187
+ lines << ["RESERVATION", reservationId, ownerId, groups]
188
+
189
+ rootelement.elements.each("instancesSet/item") do |element|
190
+ instanceId = XPath.first(element, "instanceId").text
191
+ imageId = XPath.first(element, "imageId").text
192
+ instanceState = XPath.first(element, "instanceState/name").text
193
+ # Only for debug mode, which we don't support yet:
194
+ instanceStateCode = XPath.first(element, "instanceState/code").text
195
+ dnsName = XPath.first(element, "dnsName").text
196
+ # We don't return this, but still:
197
+ reason = XPath.first(element, "reason").text
198
+ lines << ["INSTANCE", instanceId, imageId, dnsName, instanceState]
199
+ end
200
+ end
201
+ lines
202
+ end
203
+ end
204
+
205
+
206
+ class TerminateInstancesResponse < Response
207
+ ELEMENT_XPATH = "TerminateInstancesResponse/instancesSet/item"
208
+ def parse
209
+ doc = Document.new(@http_xml)
210
+ lines = []
211
+
212
+ doc.elements.each(ELEMENT_XPATH) do |element|
213
+ instanceId = XPath.first(element, "instanceId").text
214
+ shutdownState = XPath.first(element, "shutdownState/name").text
215
+ # Only for debug mode, which we don't support yet:
216
+ shutdownStateCode = XPath.first(element, "shutdownState/code").text
217
+ previousState = XPath.first(element, "previousState/name").text
218
+ # Only for debug mode, which we don't support yet:
219
+ previousStateCode = XPath.first(element, "previousState/code").text
220
+ lines << ["INSTANCE", instanceId, previousState, shutdownState]
221
+ end
222
+ lines
223
+ end
224
+ end
225
+
226
+
227
+ class CreateSecurityGroupResponse < Response
228
+ def parse
229
+ # If we don't get an error, the creation succeeded.
230
+ [["Security Group created."]]
231
+ end
232
+ end
233
+
234
+
235
+ class DescribeSecurityGroupsResponse < Response
236
+ ELEMENT_XPATH = "DescribeSecurityGroupsResponse/securityGroupInfo/item"
237
+ def parse
238
+ doc = Document.new(@http_xml)
239
+ lines = []
240
+
241
+ doc.elements.each(ELEMENT_XPATH) do |rootelement|
242
+ groupName = XPath.first(rootelement, "groupName").text
243
+ ownerId = XPath.first(rootelement, "ownerId").text
244
+ groupDescription = XPath.first(rootelement, "groupDescription").text
245
+ lines << ["GROUP", ownerId, groupName, groupDescription]
246
+ rootelement.elements.each("ipPermissions/item") do |element|
247
+ ipProtocol = XPath.first(element, "ipProtocol").text
248
+ fromPort = XPath.first(element, "fromPort").text
249
+ toPort = XPath.first(element, "toPort").text
250
+ permArr = [
251
+ "PERMISSION",
252
+ ownerId,
253
+ groupName,
254
+ "ALLOWS",
255
+ ipProtocol,
256
+ fromPort,
257
+ toPort,
258
+ "FROM"
259
+ ]
260
+ element.elements.each("groups/item") do |subelement|
261
+ userId = XPath.first(subelement, "userId").text
262
+ targetGroupName = XPath.first(subelement, "groupName").text
263
+ lines << permArr + ["USER", userId, "GRPNAME", targetGroupName]
264
+ end
265
+ element.elements.each("ipRanges/item") do |subelement|
266
+ cidrIp = XPath.first(subelement, "cidrIp").text
267
+ lines << permArr + ["CIDR", cidrIp]
268
+ end
269
+ end
270
+ end
271
+ lines
272
+ end
273
+ end
274
+
275
+
276
+ class DeleteSecurityGroupResponse < Response
277
+ def parse
278
+ # If we don't get an error, the deletion succeeded.
279
+ [["Security Group deleted."]]
280
+ end
281
+ end
282
+
283
+
284
+ class AuthorizeSecurityGroupIngressResponse < Response
285
+ def parse
286
+ # If we don't get an error, the authorization succeeded.
287
+ [["Ingress authorized."]]
288
+ end
289
+ end
290
+
291
+
292
+ class RevokeSecurityGroupIngressResponse < Response
293
+ def parse
294
+ # If we don't get an error, the revocation succeeded.
295
+ [["Ingress revoked."]]
296
+ end
297
+ end
298
+
299
+
300
+ class ModifyImageAttributeResponse < Response
301
+ def parse
302
+ # If we don't get an error, modification succeeded.
303
+ [["Image attribute modified."]]
304
+ end
305
+ end
306
+
307
+
308
+ class ResetImageAttributeResponse < Response
309
+ def parse
310
+ # If we don't get an error, reset succeeded.
311
+ [["Image attribute reset."]]
312
+ end
313
+ end
314
+
315
+
316
+ class DescribeImageAttributeResponse < Response
317
+ ELEMENT_XPATH = "DescribeImageAttributeResponse"
318
+ def parse
319
+ doc = Document.new(@http_xml)
320
+ lines = []
321
+
322
+ rootelement = XPath.first(doc, ELEMENT_XPATH)
323
+ imageId = XPath.first(rootelement, "imageId").text
324
+
325
+ # Handle launchPermission attributes:
326
+ rootelement.elements.each("launchPermission/item/*") do |element|
327
+ lines << [
328
+ "launchPermission",
329
+ imageId,
330
+ element.name,
331
+ element.text
332
+ ]
333
+ end
334
+ lines
335
+ end
336
+ end
337
+
338
+ # end EC2 Module
339
+ end
340
+