awsum 0.5 → 0.5.1
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.
- data/Gemfile +1 -1
- data/Gemfile.lock +14 -20
- data/README.rdoc +1 -1
- data/Rakefile +3 -3
- data/functional/ec2/instances_spec.rb +46 -0
- data/functional/spec_helper.rb +71 -0
- data/lib/awsum.rb +2 -2
- data/lib/awsum/ec2.rb +85 -68
- data/lib/awsum/ec2/image.rb +1 -1
- data/lib/awsum/ec2/instance.rb +35 -6
- data/lib/awsum/ec2/parsers/image_parser.rb +3 -5
- data/lib/awsum/ec2/parsers/instance_parser.rb +24 -15
- data/lib/awsum/ec2/parsers/snapshot_parser.rb +3 -3
- data/lib/awsum/ec2/parsers/tag_parser.rb +56 -0
- data/lib/awsum/ec2/parsers/volume_parser.rb +3 -5
- data/lib/awsum/ec2/region.rb +8 -5
- data/lib/awsum/ec2/security_group.rb +12 -16
- data/lib/awsum/ec2/snapshot.rb +9 -0
- data/lib/awsum/ec2/state.rb +22 -0
- data/lib/awsum/ec2/tag.rb +17 -0
- data/lib/awsum/ec2/volume.rb +12 -2
- data/lib/awsum/requestable.rb +53 -3
- data/spec/fixtures/ec2/authorize_group_access.xml +12 -0
- data/spec/fixtures/ec2/create_security_group.xml +3 -3
- data/spec/fixtures/ec2/delete_security_group.xml +3 -3
- data/spec/fixtures/ec2/purchase_reserved_instances_offering2.xml +5 -0
- data/spec/fixtures/ec2/tags.xml +12 -0
- data/spec/lib/awsum/ec2/image_spec.rb +60 -0
- data/spec/lib/awsum/ec2/instance_spec.rb +39 -1
- data/spec/lib/awsum/ec2/parsers/instance_parser_spec.rb +4 -3
- data/spec/lib/awsum/ec2/parsers/tag_parser_spec.rb +29 -0
- data/spec/lib/awsum/ec2/region_spec.rb +31 -2
- data/spec/lib/awsum/ec2/reserved_instance_spec.rb +3 -19
- data/spec/lib/awsum/ec2/security_group_spec.rb +123 -51
- data/spec/lib/awsum/ec2/snapshots_spec.rb +27 -1
- data/spec/lib/awsum/ec2/state_spec.rb +11 -0
- data/spec/lib/awsum/ec2/tag_spec.rb +45 -0
- data/spec/lib/awsum/ec2/volume_spec.rb +47 -0
- data/spec/lib/awsum/requestable_spec.rb +1 -1
- data/tools/dump.rb +55 -0
- metadata +176 -32
- data/.gitignore +0 -5
- data/spec/fixtures/ec2/purchase_reserved_instances_offerings.xml +0 -6
data/lib/awsum/ec2/image.rb
CHANGED
@@ -48,7 +48,7 @@ module Awsum
|
|
48
48
|
# * <tt>:key_name</tt> - The name of the key pair with which to launch instances
|
49
49
|
# * <tt>:security_groups</tt> - The names of security groups to associate launched instances with
|
50
50
|
# * <tt>:user_data</tt> - User data made available to instances (Note: Must be 16K or less, will be base64 encoded by Awsum)
|
51
|
-
# * <tt>:instance_type</tt> - The size of the instances to launch, can be one of [m1.small, m1.large, m1.xlarge, c1.medium, c1.xlarge], default is m1.small
|
51
|
+
# * <tt>:instance_type</tt> - The size of the instances to launch, can be one of [m1.small, m1.large, m1.xlarge, c1.medium, c1.xlarge, m2.xlarge, m2.2xlarge, m2.4xlarge, cc1.4xlarge, cg1.4xlarge, t1.micro], default is m1.small
|
52
52
|
# * <tt>:availability_zone</tt> - The name of the availability zone to launch this instance in
|
53
53
|
# * <tt>:kernel_id</tt> - The ID of the kernel with which to launch instances
|
54
54
|
# * <tt>:ramdisk_id</tt> - The ID of the RAM disk with which to launch instances
|
data/lib/awsum/ec2/instance.rb
CHANGED
@@ -23,6 +23,24 @@ module Awsum
|
|
23
23
|
@launch_index = launch_index
|
24
24
|
end
|
25
25
|
|
26
|
+
def reload
|
27
|
+
replacement_instance = @ec2.instance id
|
28
|
+
#TODO: Make this easier
|
29
|
+
@image_id = replacement_instance.image_id
|
30
|
+
@type = replacement_instance.type
|
31
|
+
@state = replacement_instance.state
|
32
|
+
@dns_name = replacement_instance.dns_name
|
33
|
+
@private_dns_name = replacement_instance.private_dns_name
|
34
|
+
@key_name = replacement_instance.key_name
|
35
|
+
@kernel_id = replacement_instance.kernel_id
|
36
|
+
@launch_time = replacement_instance.launch_time
|
37
|
+
@availability_zone = replacement_instance.availability_zone
|
38
|
+
@product_codes = replacement_instance.product_codes
|
39
|
+
@ramdisk_id = replacement_instance.ramdisk_id
|
40
|
+
@reason = replacement_instance.reason
|
41
|
+
@launch_index = replacement_instance.launch_index
|
42
|
+
end
|
43
|
+
|
26
44
|
# Terminates this instance
|
27
45
|
def terminate
|
28
46
|
@ec2.terminate_instances(id)
|
@@ -36,15 +54,26 @@ module Awsum
|
|
36
54
|
|
37
55
|
# Will create and attach a Volume to this Instance
|
38
56
|
# You must specify a size or a snapshot_id
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
57
|
+
#
|
58
|
+
# ===Options:
|
59
|
+
# :tags => Hash of tags
|
60
|
+
# :device => Will automatically attach the volume to the specified device
|
61
|
+
def create_volume(size_or_snapshot_id, options = {})
|
62
|
+
options = {:device => '/dev/sdh'}.merge(options)
|
63
|
+
if size_or_snapshot_id.is_a?(Numeric)
|
64
|
+
volume = @ec2.create_volume availability_zone, :size => size_or_snapshot_id
|
65
|
+
else
|
66
|
+
volume = @ec2.create_volume availability_zone, :snapshot_id => size_or_snapshot_id
|
67
|
+
end
|
68
|
+
if options[:tags]
|
69
|
+
@ec2.create_tags(volume.id, options[:tags])
|
70
|
+
end
|
44
71
|
while volume.status != 'available'
|
45
72
|
volume.reload
|
46
73
|
end
|
47
|
-
|
74
|
+
if options[:device]
|
75
|
+
attach volume, options[:device]
|
76
|
+
end
|
48
77
|
volume
|
49
78
|
end
|
50
79
|
|
@@ -10,8 +10,8 @@ module Awsum
|
|
10
10
|
|
11
11
|
def tag_start(tag, attributes)
|
12
12
|
case tag
|
13
|
-
when 'imagesSet'
|
14
|
-
@stack <<
|
13
|
+
when 'imagesSet', 'blockDeviceMapping', 'productCodes'
|
14
|
+
@stack << tag
|
15
15
|
when 'item'
|
16
16
|
case @stack[-1]
|
17
17
|
when 'imagesSet'
|
@@ -21,8 +21,6 @@ module Awsum
|
|
21
21
|
@product_codes = []
|
22
22
|
@text = ''
|
23
23
|
end
|
24
|
-
when 'productCodes'
|
25
|
-
@stack << 'productCodes'
|
26
24
|
end
|
27
25
|
end
|
28
26
|
|
@@ -34,7 +32,7 @@ module Awsum
|
|
34
32
|
case tag
|
35
33
|
when 'DescribeImagesResponse', 'requestId'
|
36
34
|
#no-op
|
37
|
-
when 'imagesSet', 'productCodes'
|
35
|
+
when 'imagesSet', 'productCodes', 'blockDeviceMapping'
|
38
36
|
@stack.pop
|
39
37
|
when 'item'
|
40
38
|
case @stack[-1]
|
@@ -12,16 +12,8 @@ module Awsum
|
|
12
12
|
|
13
13
|
def tag_start(tag, attributes)
|
14
14
|
case tag
|
15
|
-
when 'reservationSet'
|
16
|
-
@stack <<
|
17
|
-
when 'instancesSet'
|
18
|
-
@stack << 'instancesSet'
|
19
|
-
when 'productCodes'
|
20
|
-
@stack << 'productCodes'
|
21
|
-
when 'instanceState'
|
22
|
-
@stack << 'instanceState'
|
23
|
-
when 'placement'
|
24
|
-
@stack << 'placement'
|
15
|
+
when 'reservationSet', 'instancesSet', 'productCodes', 'instanceState', 'blockDeviceMapping', 'tagSet', 'placement'
|
16
|
+
@stack << tag
|
25
17
|
when 'item'
|
26
18
|
case @stack[-1]
|
27
19
|
when 'reservationSet'
|
@@ -30,6 +22,10 @@ module Awsum
|
|
30
22
|
@state = {}
|
31
23
|
when 'productCodes'
|
32
24
|
@product_codes = []
|
25
|
+
when 'blockDeviceMapping'
|
26
|
+
@blockDeviceMapping = {}
|
27
|
+
when 'tagSet'
|
28
|
+
@tagSet = {}
|
33
29
|
end
|
34
30
|
end
|
35
31
|
@text = ''
|
@@ -43,7 +39,7 @@ module Awsum
|
|
43
39
|
case tag
|
44
40
|
when 'DescribeInstancesResponse', 'requestId', 'reservationId'
|
45
41
|
#no-op
|
46
|
-
when 'reservationSet', 'instancesSet', 'productCodes', 'instanceState', 'placement'
|
42
|
+
when 'reservationSet', 'instancesSet', 'productCodes', 'instanceState', 'placement', 'blockDeviceMapping', 'tagSet'
|
47
43
|
@stack.pop
|
48
44
|
when 'item'
|
49
45
|
case @stack[-1]
|
@@ -53,7 +49,7 @@ module Awsum
|
|
53
49
|
@current['instanceId'],
|
54
50
|
@current['imageId'],
|
55
51
|
@current['instanceType'],
|
56
|
-
@state,
|
52
|
+
State.new(@state[:code], @state[:name]),
|
57
53
|
@current['dnsName'],
|
58
54
|
@current['privateDnsName'],
|
59
55
|
@current['keyName'],
|
@@ -75,9 +71,22 @@ module Awsum
|
|
75
71
|
when 'name'
|
76
72
|
@state[:name] = @text.strip if @stack[-1] == 'instanceState'
|
77
73
|
else
|
78
|
-
|
79
|
-
|
80
|
-
|
74
|
+
case @stack[-1]
|
75
|
+
when 'blockDeviceMapping'
|
76
|
+
unless @text.nil? || @blockDeviceMapping.nil?
|
77
|
+
text = @text.strip
|
78
|
+
@blockDeviceMapping[tag] = (text == '' ? nil : text)
|
79
|
+
end
|
80
|
+
when 'tagSet'
|
81
|
+
unless @text.nil? || @blockDeviceMapping.nil?
|
82
|
+
text = @text.strip
|
83
|
+
@blockDeviceMapping[tag] = (text == '' ? nil : text)
|
84
|
+
end
|
85
|
+
else
|
86
|
+
unless @text.nil? || @current.nil?
|
87
|
+
text = @text.strip
|
88
|
+
@current[tag] = (text == '' ? nil : text)
|
89
|
+
end
|
81
90
|
end
|
82
91
|
end
|
83
92
|
end
|
@@ -15,8 +15,8 @@ module Awsum
|
|
15
15
|
end
|
16
16
|
|
17
17
|
case tag
|
18
|
-
when 'snapshotSet'
|
19
|
-
@stack <<
|
18
|
+
when 'snapshotSet', 'tagSet'
|
19
|
+
@stack << tag
|
20
20
|
when 'item', 'CreateSnapshotResponse'
|
21
21
|
case @stack[-1]
|
22
22
|
when 'snapshotSet'
|
@@ -34,7 +34,7 @@ module Awsum
|
|
34
34
|
case tag
|
35
35
|
when 'DescribeSnapshotsResponts'
|
36
36
|
#no-op
|
37
|
-
when 'snapshotSet'
|
37
|
+
when 'snapshotSet', 'tagSet'
|
38
38
|
@stack.pop
|
39
39
|
when 'item', 'CreateSnapshotResponse'
|
40
40
|
case @stack[-1]
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Awsum
|
2
|
+
class Ec2
|
3
|
+
class TagParser < Awsum::Parser #:nodoc:
|
4
|
+
def initialize(ec2)
|
5
|
+
@ec2 = ec2
|
6
|
+
@tags = []
|
7
|
+
@text = nil
|
8
|
+
@stack = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def tag_start(tag, attributes)
|
12
|
+
case tag
|
13
|
+
when 'tagSet'
|
14
|
+
@stack << tag
|
15
|
+
when 'item'
|
16
|
+
case @stack[-1]
|
17
|
+
when 'tagSet'
|
18
|
+
@current = {}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
@text = ''
|
22
|
+
end
|
23
|
+
|
24
|
+
def text(text)
|
25
|
+
@text << text unless @text.nil?
|
26
|
+
end
|
27
|
+
|
28
|
+
def tag_end(tag)
|
29
|
+
case tag
|
30
|
+
when 'tagSet'
|
31
|
+
@stack.pop
|
32
|
+
when 'item'
|
33
|
+
case @stack[-1]
|
34
|
+
when 'tagSet'
|
35
|
+
@tags << Tag.new(
|
36
|
+
@ec2,
|
37
|
+
@current['resourceId'],
|
38
|
+
@current['resourceType'],
|
39
|
+
@current['key'],
|
40
|
+
@current['value']
|
41
|
+
)
|
42
|
+
end
|
43
|
+
else
|
44
|
+
unless @text.nil? || @current.nil?
|
45
|
+
text = @text.strip
|
46
|
+
@current[tag] = (text == '' ? nil : text)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def result
|
52
|
+
@tags
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -15,10 +15,8 @@ module Awsum
|
|
15
15
|
end
|
16
16
|
|
17
17
|
case tag
|
18
|
-
when 'volumeSet'
|
19
|
-
@stack <<
|
20
|
-
when 'attachmentSet'
|
21
|
-
@stack << 'attachmentSet'
|
18
|
+
when 'volumeSet', 'attachmentSet', 'tagSet'
|
19
|
+
@stack << tag
|
22
20
|
when 'item', 'CreateVolumeResponse'
|
23
21
|
case @stack[-1]
|
24
22
|
when 'volumeSet'
|
@@ -37,7 +35,7 @@ module Awsum
|
|
37
35
|
case tag
|
38
36
|
when 'DescribeVolumesResponse'
|
39
37
|
#no-op
|
40
|
-
when 'volumeSet', 'attachmentSet'
|
38
|
+
when 'volumeSet', 'attachmentSet', 'tagSet'
|
41
39
|
@stack.pop
|
42
40
|
when 'item', 'CreateVolumeResponse'
|
43
41
|
case @stack[-1]
|
data/lib/awsum/ec2/region.rb
CHANGED
@@ -30,15 +30,18 @@ module Awsum
|
|
30
30
|
# region.availability_zones
|
31
31
|
# end
|
32
32
|
def use(&block)
|
33
|
-
old_host = @ec2.host
|
34
|
-
@ec2.host = end_point
|
35
33
|
if block_given?
|
36
|
-
|
34
|
+
begin
|
35
|
+
old_host = @ec2.host
|
36
|
+
@ec2.host = end_point
|
37
|
+
block.arity < 1 ? instance_eval(&block) : block[self]
|
38
|
+
ensure
|
39
|
+
@ec2.host = old_host
|
40
|
+
end
|
37
41
|
else
|
42
|
+
@ec2.host = end_point
|
38
43
|
self
|
39
44
|
end
|
40
|
-
ensure
|
41
|
-
@ec2.host = old_host
|
42
45
|
end
|
43
46
|
|
44
47
|
private
|
@@ -14,24 +14,20 @@ module Awsum
|
|
14
14
|
@group_permissions = group_permissions
|
15
15
|
end
|
16
16
|
|
17
|
-
# Authorize access
|
18
|
-
|
19
|
-
|
17
|
+
# Authorize access
|
18
|
+
#
|
19
|
+
# ===Options:
|
20
|
+
# See Ec2#authorize_security_group_ingress
|
21
|
+
def authorize(arguments)
|
22
|
+
@ec2.authorize_security_group_ingress(@name, arguments)
|
20
23
|
end
|
21
24
|
|
22
|
-
# Revoke access
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
def authorize_ip(from_port, to_port, protocol = 'tcp', cidr_ip = '0.0.0.0/0')
|
29
|
-
@ec2.authorize_security_group_ingress(@name, :ip_protocol => protocol, :from_port => from_port, :to_port => to_port, :cidr_ip => cidr_ip)
|
30
|
-
end
|
31
|
-
|
32
|
-
# Revoke access from an ip address
|
33
|
-
def revoke_ip(from_port, to_port, protocol = 'tcp', cidr_ip = '0.0.0.0/0')
|
34
|
-
@ec2.revoke_security_group_ingress(@name, :ip_protocol => protocol, :from_port => from_port, :to_port => to_port, :cidr_ip => cidr_ip)
|
25
|
+
# Revoke access
|
26
|
+
#
|
27
|
+
# ===Options:
|
28
|
+
# See Ec2#revoke_security_group_ingress
|
29
|
+
def revoke(arguments)
|
30
|
+
@ec2.revoke_security_group_ingress(@name, arguments)
|
35
31
|
end
|
36
32
|
|
37
33
|
# Delete this SecurityGroup
|
data/lib/awsum/ec2/snapshot.rb
CHANGED
@@ -18,6 +18,15 @@ module Awsum
|
|
18
18
|
def delete
|
19
19
|
@ec2.delete_snapshot id
|
20
20
|
end
|
21
|
+
|
22
|
+
def reload
|
23
|
+
reloaded_snapshot = @ec2.snapshot id
|
24
|
+
|
25
|
+
@volume_id = reloaded_snapshot.volume_id
|
26
|
+
@status = reloaded_snapshot.status
|
27
|
+
@start_time = reloaded_snapshot.start_time
|
28
|
+
@progress = reloaded_snapshot.progress
|
29
|
+
end
|
21
30
|
end
|
22
31
|
end
|
23
32
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Awsum
|
2
|
+
class Ec2
|
3
|
+
class State
|
4
|
+
attr_reader :code, :name
|
5
|
+
|
6
|
+
def initialize(code, name)
|
7
|
+
@code = code.to_i
|
8
|
+
@name = name
|
9
|
+
end
|
10
|
+
|
11
|
+
def ==(other)
|
12
|
+
if other.is_a?(Numeric)
|
13
|
+
@code == other
|
14
|
+
elsif other.is_a?(String)
|
15
|
+
@name == other
|
16
|
+
else
|
17
|
+
@code = other.code && @name == other.name
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'awsum/ec2/parsers/tag_parser'
|
2
|
+
|
3
|
+
module Awsum
|
4
|
+
class Ec2
|
5
|
+
class Tag
|
6
|
+
attr_reader :resource_id, :resource_type, :key, :value
|
7
|
+
|
8
|
+
def initialize(ec2, resource_id, resource_type, key, value) #:nodoc:
|
9
|
+
@ec2 = ec2
|
10
|
+
@resource_id = resource_id
|
11
|
+
@resource_type = resource_type
|
12
|
+
@key = key
|
13
|
+
@value = value
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/awsum/ec2/volume.rb
CHANGED
@@ -50,9 +50,19 @@ module Awsum
|
|
50
50
|
@ec2.delete_volume id
|
51
51
|
end
|
52
52
|
|
53
|
+
# Force delete this volume
|
54
|
+
# will detach it first
|
55
|
+
def delete!
|
56
|
+
detach true
|
57
|
+
while status != 'available'
|
58
|
+
reload
|
59
|
+
end
|
60
|
+
@ec2.delete_volume id
|
61
|
+
end
|
62
|
+
|
53
63
|
# Creates a Snapshot of this Volume
|
54
|
-
def create_snapshot
|
55
|
-
@ec2.create_snapshot id
|
64
|
+
def create_snapshot(options = {})
|
65
|
+
@ec2.create_snapshot id, options
|
56
66
|
end
|
57
67
|
|
58
68
|
# Lists the Snapshot(s) of this Volume
|
data/lib/awsum/requestable.rb
CHANGED
@@ -197,14 +197,64 @@ module Awsum
|
|
197
197
|
|
198
198
|
# Converts an array of paramters into <param_name>.<num> format
|
199
199
|
def array_to_params(arr, param_name)
|
200
|
-
arr = [arr]
|
200
|
+
arr = [arr].flatten
|
201
201
|
params = {}
|
202
|
-
arr.each_with_index do |value,i|
|
203
|
-
|
202
|
+
arr.each_with_index do |value, i|
|
203
|
+
if value.respond_to?(:keys)
|
204
|
+
value.each do |key, val|
|
205
|
+
param_key = "#{param_name}.#{i+1}.#{parameterize(key)}"
|
206
|
+
if val.is_a?(Array) || val.respond_to?(:keys)
|
207
|
+
params.merge! array_to_params(val, param_key)
|
208
|
+
else
|
209
|
+
params[param_key] = val
|
210
|
+
end
|
211
|
+
end
|
212
|
+
else
|
213
|
+
params["#{param_name}.#{i+1}"] = value
|
214
|
+
end
|
204
215
|
end
|
205
216
|
params
|
206
217
|
end
|
207
218
|
|
219
|
+
def parameterize(string)
|
220
|
+
string.to_s.split(/_/).map{ |w| w.downcase.sub(/^(.)/){ $1.upcase } }.join
|
221
|
+
end
|
222
|
+
|
223
|
+
def parse_filters(filters, tags = nil)
|
224
|
+
result = []
|
225
|
+
if filters
|
226
|
+
filters.each do |k,v|
|
227
|
+
values = v.is_a?(Array) ? v : [v]
|
228
|
+
result << {:name => k, :value => values}
|
229
|
+
end
|
230
|
+
end
|
231
|
+
if tags
|
232
|
+
tags.each do |k,v|
|
233
|
+
values = v.is_a?(Array) ? v : [v]
|
234
|
+
result << {:name => "tag:#{k}", :value => values}
|
235
|
+
end
|
236
|
+
end
|
237
|
+
if result.size > 0
|
238
|
+
array_to_params(result, "Filter")
|
239
|
+
else
|
240
|
+
{}
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
def parse_tag_keys(tags)
|
245
|
+
result = []
|
246
|
+
if tags
|
247
|
+
tags.each do |k,v|
|
248
|
+
result << {:key => k, :value => v}
|
249
|
+
end
|
250
|
+
end
|
251
|
+
if result.size > 0
|
252
|
+
array_to_params(result, "Tag")
|
253
|
+
else
|
254
|
+
{}
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
208
258
|
# Sign a string with a digest, wrap in HMAC digest and base64 encode
|
209
259
|
#
|
210
260
|
# ===Returns
|