rudy 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES.txt +54 -30
- data/README.rdoc +100 -12
- data/Rakefile +103 -8
- data/Rudyfile +119 -0
- data/bin/ird +175 -0
- data/bin/rudy +259 -156
- data/bin/rudy-ec2 +228 -95
- data/bin/rudy-s3 +76 -0
- data/bin/rudy-sdb +67 -0
- data/lib/annoy.rb +270 -0
- data/lib/console.rb +30 -9
- data/lib/escape.rb +305 -0
- data/lib/rudy.rb +151 -182
- data/lib/rudy/aws.rb +56 -49
- data/lib/rudy/aws/ec2.rb +47 -292
- data/lib/rudy/aws/ec2/address.rb +157 -0
- data/lib/rudy/aws/ec2/group.rb +301 -0
- data/lib/rudy/aws/ec2/image.rb +168 -0
- data/lib/rudy/aws/ec2/instance.rb +434 -0
- data/lib/rudy/aws/ec2/keypair.rb +104 -0
- data/lib/rudy/aws/ec2/snapshot.rb +98 -0
- data/lib/rudy/aws/ec2/volume.rb +230 -0
- data/lib/rudy/aws/ec2/zone.rb +77 -0
- data/lib/rudy/aws/s3.rb +54 -0
- data/lib/rudy/aws/sdb.rb +298 -0
- data/lib/rudy/aws/sdb/error.rb +46 -0
- data/lib/rudy/{metadata/backup.rb → backup.rb} +26 -51
- data/lib/rudy/cli.rb +157 -0
- data/lib/rudy/cli/aws/ec2/addresses.rb +105 -0
- data/lib/rudy/cli/aws/ec2/candy.rb +208 -0
- data/lib/rudy/cli/aws/ec2/groups.rb +121 -0
- data/lib/rudy/cli/aws/ec2/images.rb +196 -0
- data/lib/rudy/cli/aws/ec2/instances.rb +194 -0
- data/lib/rudy/cli/aws/ec2/keypairs.rb +53 -0
- data/lib/rudy/cli/aws/ec2/snapshots.rb +49 -0
- data/lib/rudy/cli/aws/ec2/volumes.rb +104 -0
- data/lib/rudy/cli/aws/ec2/zones.rb +22 -0
- data/lib/rudy/cli/aws/s3/buckets.rb +50 -0
- data/lib/rudy/cli/aws/s3/store.rb +22 -0
- data/lib/rudy/cli/aws/sdb/domains.rb +41 -0
- data/lib/rudy/cli/candy.rb +8 -0
- data/lib/rudy/{command → cli}/config.rb +34 -24
- data/lib/rudy/cli/disks.rb +35 -0
- data/lib/rudy/cli/machines.rb +94 -0
- data/lib/rudy/cli/routines.rb +57 -0
- data/lib/rudy/config.rb +77 -72
- data/lib/rudy/config/objects.rb +29 -0
- data/lib/rudy/disks.rb +248 -0
- data/lib/rudy/global.rb +121 -0
- data/lib/rudy/huxtable.rb +340 -0
- data/lib/rudy/machines.rb +245 -0
- data/lib/rudy/metadata.rb +123 -13
- data/lib/rudy/routines.rb +47 -0
- data/lib/rudy/routines/helpers/diskhelper.rb +101 -0
- data/lib/rudy/routines/helpers/scripthelper.rb +91 -0
- data/lib/rudy/routines/release.rb +34 -0
- data/lib/rudy/routines/shutdown.rb +57 -0
- data/lib/rudy/routines/startup.rb +58 -0
- data/lib/rudy/scm/svn.rb +1 -1
- data/lib/rudy/utils.rb +322 -4
- data/lib/storable.rb +26 -17
- data/lib/sysinfo.rb +274 -0
- data/lib/tryouts.rb +6 -13
- data/rudy.gemspec +128 -42
- data/support/randomize-root-password +45 -0
- data/support/rudy-ec2-startup +9 -9
- data/support/update-ec2-ami-tools +20 -0
- data/test/05_config/00_setup_test.rb +20 -0
- data/test/05_config/30_machines_test.rb +69 -0
- data/test/20_sdb/00_setup_test.rb +16 -0
- data/test/20_sdb/10_domains_test.rb +115 -0
- data/test/25_ec2/00_setup_test.rb +29 -0
- data/test/25_ec2/10_keypairs_test.rb +41 -0
- data/test/25_ec2/20_groups_test.rb +131 -0
- data/test/25_ec2/30_addresses_test.rb +38 -0
- data/test/25_ec2/40_volumes_test.rb +49 -0
- data/test/25_ec2/50_snapshots_test.rb +74 -0
- data/test/26_ec2_instances/00_setup_test.rb +28 -0
- data/test/26_ec2_instances/10_instances_test.rb +83 -0
- data/test/26_ec2_instances/50_images_test.rb +13 -0
- data/test/30_sdb_metadata/00_setup_test.rb +21 -0
- data/test/30_sdb_metadata/10_disks_test.rb +109 -0
- data/test/30_sdb_metadata/20_backups_test.rb +102 -0
- data/test/coverage.txt +51 -0
- data/test/helper.rb +36 -0
- data/vendor/highline-1.5.1/CHANGELOG +222 -0
- data/vendor/highline-1.5.1/INSTALL +35 -0
- data/vendor/highline-1.5.1/LICENSE +7 -0
- data/vendor/highline-1.5.1/README +63 -0
- data/vendor/highline-1.5.1/Rakefile +82 -0
- data/vendor/highline-1.5.1/TODO +6 -0
- data/vendor/highline-1.5.1/examples/ansi_colors.rb +38 -0
- data/vendor/highline-1.5.1/examples/asking_for_arrays.rb +18 -0
- data/vendor/highline-1.5.1/examples/basic_usage.rb +75 -0
- data/vendor/highline-1.5.1/examples/color_scheme.rb +32 -0
- data/vendor/highline-1.5.1/examples/limit.rb +12 -0
- data/vendor/highline-1.5.1/examples/menus.rb +65 -0
- data/vendor/highline-1.5.1/examples/overwrite.rb +19 -0
- data/vendor/highline-1.5.1/examples/page_and_wrap.rb +322 -0
- data/vendor/highline-1.5.1/examples/password.rb +7 -0
- data/vendor/highline-1.5.1/examples/trapping_eof.rb +22 -0
- data/vendor/highline-1.5.1/examples/using_readline.rb +17 -0
- data/vendor/highline-1.5.1/lib/highline.rb +758 -0
- data/vendor/highline-1.5.1/lib/highline/color_scheme.rb +120 -0
- data/vendor/highline-1.5.1/lib/highline/compatibility.rb +17 -0
- data/vendor/highline-1.5.1/lib/highline/import.rb +43 -0
- data/vendor/highline-1.5.1/lib/highline/menu.rb +395 -0
- data/vendor/highline-1.5.1/lib/highline/question.rb +463 -0
- data/vendor/highline-1.5.1/lib/highline/system_extensions.rb +193 -0
- data/vendor/highline-1.5.1/setup.rb +1360 -0
- data/vendor/highline-1.5.1/test/tc_color_scheme.rb +56 -0
- data/vendor/highline-1.5.1/test/tc_highline.rb +823 -0
- data/vendor/highline-1.5.1/test/tc_import.rb +54 -0
- data/vendor/highline-1.5.1/test/tc_menu.rb +429 -0
- data/vendor/highline-1.5.1/test/ts_all.rb +15 -0
- metadata +141 -38
- data/lib/aws_sdb.rb +0 -3
- data/lib/aws_sdb/error.rb +0 -42
- data/lib/aws_sdb/service.rb +0 -215
- data/lib/rudy/aws/simpledb.rb +0 -53
- data/lib/rudy/command/addresses.rb +0 -46
- data/lib/rudy/command/backups.rb +0 -175
- data/lib/rudy/command/base.rb +0 -841
- data/lib/rudy/command/deploy.rb +0 -12
- data/lib/rudy/command/disks.rb +0 -213
- data/lib/rudy/command/environment.rb +0 -73
- data/lib/rudy/command/groups.rb +0 -61
- data/lib/rudy/command/images.rb +0 -91
- data/lib/rudy/command/instances.rb +0 -85
- data/lib/rudy/command/machines.rb +0 -161
- data/lib/rudy/command/metadata.rb +0 -41
- data/lib/rudy/command/release.rb +0 -174
- data/lib/rudy/command/volumes.rb +0 -66
- data/lib/rudy/metadata/disk.rb +0 -138
- data/tryouts/console_tryout.rb +0 -91
@@ -0,0 +1,301 @@
|
|
1
|
+
|
2
|
+
module Rudy::AWS
|
3
|
+
|
4
|
+
class EC2::Group < Storable
|
5
|
+
class Rule < Storable
|
6
|
+
field :ports => Range # Port range
|
7
|
+
field :protocol => String
|
8
|
+
|
9
|
+
def to_s(with_title=false)
|
10
|
+
if self.ports.first == self.ports.last
|
11
|
+
"%s(%s)" % [self.protocol, self.ports.last]
|
12
|
+
else
|
13
|
+
"%s(%s..%s)" % [self.protocol, self.ports.first, self.ports.last]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class EC2::Group < Storable
|
20
|
+
field :name => String
|
21
|
+
field :description => String
|
22
|
+
field :owner_id => String
|
23
|
+
field :addresses => Hash # key: address/mask, value Array of Rule object
|
24
|
+
field :groups => Hash # key: group, value Array of Rule object
|
25
|
+
|
26
|
+
|
27
|
+
def liner_note
|
28
|
+
info = "(authorized accounts: #{@groups.keys.join(', ')})"
|
29
|
+
info = '' if @groups.empty?
|
30
|
+
"%s %s" % [@name.bright, info]
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
# Print info about a security group
|
35
|
+
#
|
36
|
+
# * +group+ is a Rudy::AWS::EC2::Group object
|
37
|
+
def to_s(with_title=false)
|
38
|
+
lines = [liner_note]
|
39
|
+
(self.addresses || {}).each_pair do |address,rules|
|
40
|
+
lines << "%18s -> %s" % [address.to_s, rules.collect { |p| p.to_s}.join(', ')]
|
41
|
+
end
|
42
|
+
lines.join($/)
|
43
|
+
end
|
44
|
+
|
45
|
+
def inspect
|
46
|
+
lines = [@name.bright]
|
47
|
+
field_names.each do |key|
|
48
|
+
next unless self.respond_to?(key)
|
49
|
+
next if [:addresses, :groups].member?(key)
|
50
|
+
val = self.send(key)
|
51
|
+
lines << sprintf(" %12s: %s", key, (val.is_a?(Array) ? val.join(', ') : val))
|
52
|
+
end
|
53
|
+
@addresses.each_pair do |a,r|
|
54
|
+
rules = r.collect { |r| r.to_s }.join(', ') if r
|
55
|
+
lines << sprintf(" %12s: %s (%s)", 'address', a.to_s, rules)
|
56
|
+
end
|
57
|
+
@groups.each_pair do |g,r|
|
58
|
+
rules = r.collect { |r| r.to_s }.join(', ')
|
59
|
+
lines << sprintf(" %12s: %s (%s)", 'group', g.to_s, rules)
|
60
|
+
end
|
61
|
+
lines.join($/)
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
# * +ipaddress+ is a String, ipaddress/mask/protocol
|
66
|
+
# * +rule+ is a Rule object
|
67
|
+
def add_address(ipaddress, rule)
|
68
|
+
return false unless rule.is_a?(Rule)
|
69
|
+
@addresses ||= {}
|
70
|
+
(@addresses[ipaddress] ||= []) << rule
|
71
|
+
rule
|
72
|
+
end
|
73
|
+
|
74
|
+
# * +group+ is a String, accountnum:group
|
75
|
+
# * +rule+ is a Rule object
|
76
|
+
def add_group(group, rule)
|
77
|
+
return false unless rule.is_a?(Rule)
|
78
|
+
@groups ||= {}
|
79
|
+
(@groups[group] ||= []) << rule
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
|
86
|
+
module EC2
|
87
|
+
class Groups
|
88
|
+
include Rudy::AWS::ObjectBase
|
89
|
+
include Rudy::AWS::EC2::Base
|
90
|
+
|
91
|
+
# Create a new EC2 security group
|
92
|
+
# Returns list of created groups
|
93
|
+
def create(name, desc=nil, addresses=[], ports=[], protocols=[], &each_group)
|
94
|
+
desc ||= "Security Group #{name}"
|
95
|
+
ret = @ec2.create_security_group(:group_name => name, :group_description => desc)
|
96
|
+
return false unless (ret && ret['return'] == 'true')
|
97
|
+
authorize(name, addresses, ports, protocols)
|
98
|
+
get(name, &each_group)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Delete an EC2 security group
|
102
|
+
# Returns true/false whether successful
|
103
|
+
def destroy(name, &each_group)
|
104
|
+
list(name, &each_group) if each_group
|
105
|
+
ret = @ec2.delete_security_group(:group_name => name)
|
106
|
+
(ret && ret['return'] == 'true')
|
107
|
+
end
|
108
|
+
|
109
|
+
# Authorize a port/protocol for a specific IP address
|
110
|
+
def authorize(name, addresses=[], ports=[], protocols=[], &each_group)
|
111
|
+
modify_rules(:authorize, name, addresses, ports, protocols, &each_group)
|
112
|
+
end
|
113
|
+
alias :authorise :authorize
|
114
|
+
|
115
|
+
# Revoke a port/protocol for a specific IP address
|
116
|
+
# Takes the same arguments as authorize
|
117
|
+
def revoke(name, addresses=[], ports=[], protocols=[], &each_group)
|
118
|
+
modify_rules(:revoke, name, addresses, ports, protocols, &each_group)
|
119
|
+
end
|
120
|
+
|
121
|
+
def authorize_group(name, gname, owner, &each_group)
|
122
|
+
modify_group_rules(:authorize, name, gname, owner, &each_group)
|
123
|
+
end
|
124
|
+
alias :authorise_group :authorize_group
|
125
|
+
|
126
|
+
def revoke_group(name, gname, owner, &each_group)
|
127
|
+
modify_group_rules(:revoke, name, gname, owner, &each_group)
|
128
|
+
end
|
129
|
+
|
130
|
+
def list(group_names=[], &each_group)
|
131
|
+
group_names ||= []
|
132
|
+
groups = list_as_hash(group_names, &each_group)
|
133
|
+
groups &&= groups.values
|
134
|
+
groups
|
135
|
+
end
|
136
|
+
|
137
|
+
# * +group_names+ is a list of security group names to look for. If it's empty, all groups
|
138
|
+
# associated to the account will be returned.
|
139
|
+
#
|
140
|
+
# Returns an Array of Rudy::AWS::EC2::Group objects
|
141
|
+
def list_as_hash(group_names=[], &each_group)
|
142
|
+
group_names = [group_names].flatten.compact
|
143
|
+
glist = @ec2.describe_security_groups(:group_name => group_names) || {}
|
144
|
+
return unless glist['securityGroupInfo'].is_a?(Hash)
|
145
|
+
groups = {}
|
146
|
+
glist['securityGroupInfo']['item'].each do |oldg|
|
147
|
+
g = Groups.from_hash(oldg)
|
148
|
+
groups[g.name] = g
|
149
|
+
end
|
150
|
+
groups.each_value { |g| each_group.call(g) } if each_group
|
151
|
+
groups
|
152
|
+
end
|
153
|
+
|
154
|
+
def any?
|
155
|
+
groups = list || []
|
156
|
+
!groups.empty?
|
157
|
+
end
|
158
|
+
|
159
|
+
# * +name+ a string
|
160
|
+
def get(name)
|
161
|
+
(list([name]) || []).first
|
162
|
+
end
|
163
|
+
|
164
|
+
# +group+ a Rudy::AWS::EC2::Group object
|
165
|
+
#def save(group)
|
166
|
+
#
|
167
|
+
#end
|
168
|
+
|
169
|
+
# Does the security group +name+ exist?
|
170
|
+
def exists?(name)
|
171
|
+
begin
|
172
|
+
g = list([name.to_s])
|
173
|
+
rescue ::EC2::InvalidGroupNotFound
|
174
|
+
return false
|
175
|
+
end
|
176
|
+
|
177
|
+
!g.empty?
|
178
|
+
end
|
179
|
+
|
180
|
+
|
181
|
+
|
182
|
+
|
183
|
+
# * +ghash+ is an EC2::Base Security Group Hash. This is the format
|
184
|
+
# returned by EC2::Base#describe_security_groups
|
185
|
+
#
|
186
|
+
# groupName: stage-app
|
187
|
+
# groupDescription:
|
188
|
+
# ownerId: "207436219441"
|
189
|
+
# ipPermissions:
|
190
|
+
# item:
|
191
|
+
# - ipRanges:
|
192
|
+
# item:
|
193
|
+
# - cidrIp: 216.19.182.83/32
|
194
|
+
# - cidrIp: 24.5.71.201/32
|
195
|
+
# - cidrIp: 75.157.176.202/32
|
196
|
+
# - cidrIp: 84.28.52.172/32
|
197
|
+
# - cidrIp: 87.212.145.201/32
|
198
|
+
# - cidrIp: 96.49.129.178/32
|
199
|
+
# groups:
|
200
|
+
# item:
|
201
|
+
# - groupName: default
|
202
|
+
# userId: "207436219441"
|
203
|
+
# - groupName: stage-app
|
204
|
+
# userId: "207436219441"
|
205
|
+
# fromPort: "22"
|
206
|
+
# toPort: "22"
|
207
|
+
# ipProtocol: tcp
|
208
|
+
#
|
209
|
+
# Returns a Rudy::AWS::EC2::Group object
|
210
|
+
def self.from_hash(ghash)
|
211
|
+
newg = Rudy::AWS::EC2::Group.new
|
212
|
+
newg.name = ghash['groupName']
|
213
|
+
newg.description = ghash['groupDescription']
|
214
|
+
newg.owner_id = ghash['ownerId']
|
215
|
+
newg.addresses = {}
|
216
|
+
newg.groups = {}
|
217
|
+
|
218
|
+
return newg unless ghash['ipPermissions'].is_a?(Hash)
|
219
|
+
|
220
|
+
ghash['ipPermissions']['item'].each do |oldp|
|
221
|
+
newp = Rudy::AWS::EC2::Group::Rule.new
|
222
|
+
newp.ports = Range.new(oldp['fromPort'], oldp['toPort'])
|
223
|
+
newp.protocol = oldp['ipProtocol']
|
224
|
+
if oldp['groups'].is_a?(Hash)
|
225
|
+
oldp['groups']['item'].each do |oldpg|
|
226
|
+
name = [oldpg['userId'], oldpg['groupName']].join(':') # account_num:name
|
227
|
+
newg.add_group(name, newp)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
if oldp['ipRanges'].is_a?(Hash)
|
231
|
+
oldp['ipRanges']['item'].each do |olda|
|
232
|
+
name = "#{olda['cidrIp']}"
|
233
|
+
newg.add_address(name, newp) # ipaddress/mask/protocol
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
newg
|
238
|
+
end
|
239
|
+
|
240
|
+
|
241
|
+
private
|
242
|
+
|
243
|
+
|
244
|
+
def modify_rules(meth, name, addresses, ports, protocols, &each_group)
|
245
|
+
list(name, &each_group) if each_group
|
246
|
+
|
247
|
+
ports = [[22,22],[80,80],[443,443]] if !ports || ports.empty?
|
248
|
+
protocols = ["tcp"] if !protocols || protocols.empty?
|
249
|
+
addresses = [Rudy::Utils::external_ip_address] if !addresses || addresses.empty?
|
250
|
+
|
251
|
+
# Make sure the IP addresses have ranges
|
252
|
+
addresses.collect! { |ip| (ip.match /\/\d+/) ? ip : "#{ip}/32" }
|
253
|
+
protocols.collect! { |p| p.to_s }
|
254
|
+
ret = false
|
255
|
+
protocols.each do |protocol|
|
256
|
+
addresses.each do |address|
|
257
|
+
ports.each do |port|
|
258
|
+
port_lo, port_hi = port.is_a?(Array) ? [port[0], port[1]] : [port, port]
|
259
|
+
@logger.puts "#{meth} for ports #{port[0]}:#{port[1]} (#{protocol}) for #{addresses.join(', ')}" if @logger
|
260
|
+
ret = modify_rule(meth, name, port[0].to_i, (port[1] || port[0]).to_i, protocol, address)
|
261
|
+
raise "Unknown error during #{meth}" unless ret
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
ret
|
267
|
+
end
|
268
|
+
|
269
|
+
def modify_rule(meth, name, from_port, to_port, protocol, ipa)
|
270
|
+
opts = {
|
271
|
+
:group_name => name,
|
272
|
+
:ip_protocol => protocol,
|
273
|
+
:from_port => from_port,
|
274
|
+
:to_port => to_port,
|
275
|
+
:cidr_ip => ipa
|
276
|
+
}
|
277
|
+
ret = @ec2.send("#{meth}_security_group_ingress", opts)
|
278
|
+
(ret && ret['return'] == 'true')
|
279
|
+
end
|
280
|
+
|
281
|
+
|
282
|
+
def modify_group_rules(meth, name, gname, gowner, &each_group)
|
283
|
+
list(name, &each_group) if each_group
|
284
|
+
# probably works, needs to be tested
|
285
|
+
#gowner &&= gowner.tr!('-', '') # Remove dashes from aws account number
|
286
|
+
|
287
|
+
opts = {
|
288
|
+
:group_name => name,
|
289
|
+
:source_security_group_name => gname,
|
290
|
+
:source_security_group_owner_id => gowner
|
291
|
+
}
|
292
|
+
ret = @ec2.send("#{meth}_security_group_ingress", opts)
|
293
|
+
(ret && ret['return'] == 'true')
|
294
|
+
end
|
295
|
+
|
296
|
+
|
297
|
+
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Rudy::AWS
|
4
|
+
class EC2::Image < Storable
|
5
|
+
@@sformat = " -> %8s; %12s; %12s; %12s; %8s"
|
6
|
+
|
7
|
+
field :awsid
|
8
|
+
field :owner
|
9
|
+
field :aki
|
10
|
+
field :ari
|
11
|
+
field :state
|
12
|
+
field :arch
|
13
|
+
field :visibility
|
14
|
+
field :location
|
15
|
+
field :kind
|
16
|
+
|
17
|
+
def liner_note
|
18
|
+
info = @location
|
19
|
+
# Highlight "debian-5" in /dir/debian-5.manifest.xml
|
20
|
+
#info = info.split(/\//)
|
21
|
+
#info[-1].gsub!(/(.+?)((\.img)?\.manifest\.xml)/) { |m,n| ($1 || "").bright << $2 }
|
22
|
+
#info = info.join('/')
|
23
|
+
"%s %-6s (%s)" % [self.awsid.bright, self.arch, info]
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_s(with_title=false)
|
27
|
+
lines = []
|
28
|
+
lines << liner_note
|
29
|
+
#if self.available?
|
30
|
+
# p = public? ? "public" : "private"
|
31
|
+
# k, r = @aki || 'aki-unknown', @ari || 'ari-unknown'
|
32
|
+
# lines << @@sformat % %w{arch owner aki ari visibility} if with_title
|
33
|
+
# lines << @@sformat % [@arch, @owner, k, r, p]
|
34
|
+
#end
|
35
|
+
lines.join($/)
|
36
|
+
end
|
37
|
+
|
38
|
+
def inspect
|
39
|
+
lines = []
|
40
|
+
lines << liner_note
|
41
|
+
field_names.each do |key|
|
42
|
+
next unless self.respond_to?(key)
|
43
|
+
val = self.send(key)
|
44
|
+
lines << sprintf(" %22s: %s", key, (val.is_a?(Array) ? val.join(', ') : val))
|
45
|
+
end
|
46
|
+
lines.join($/)
|
47
|
+
end
|
48
|
+
|
49
|
+
def available?; @state && @state == "available"; end
|
50
|
+
def public?; @visibility && @visibility == 'public'; end
|
51
|
+
def private?; !public? end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
module EC2
|
56
|
+
|
57
|
+
class Images
|
58
|
+
include Rudy::AWS::ObjectBase
|
59
|
+
include Rudy::AWS::EC2::Base
|
60
|
+
|
61
|
+
def list(owner=[], image_ids=[], executable_by=[], &each_image)
|
62
|
+
images = list_as_hash(owner, image_ids, executable_by)
|
63
|
+
images &&= images.values
|
64
|
+
images
|
65
|
+
end
|
66
|
+
|
67
|
+
def list_as_hash(owner=[], image_ids=[], executable_by=[], &each_image)
|
68
|
+
owner &&= [owner].flatten.compact
|
69
|
+
image_ids &&= [image_ids].flatten.compact
|
70
|
+
executable_by &&= [executable_by].flatten.compact
|
71
|
+
|
72
|
+
# Remove dashes from aws account numbers
|
73
|
+
owner &&= owner.collect { |o| o.tr('-', '') }
|
74
|
+
# If we got Image objects, we want just the IDs.
|
75
|
+
# This method always returns an Array.
|
76
|
+
image_ids = objects_to_image_ids(image_ids)
|
77
|
+
|
78
|
+
opts = {
|
79
|
+
:owner_id => owner || [],
|
80
|
+
:image_id => image_ids || [],
|
81
|
+
:executable_by => executable_by || []
|
82
|
+
}
|
83
|
+
|
84
|
+
response = execute_request({}) { @ec2.describe_images(opts) }
|
85
|
+
|
86
|
+
return nil unless response['imagesSet'].is_a?(Hash) # No instances
|
87
|
+
|
88
|
+
resids = []
|
89
|
+
images = {}
|
90
|
+
response['imagesSet']['item'].each do |res|
|
91
|
+
resids << res['reservationId']
|
92
|
+
img = Images.from_hash(res)
|
93
|
+
images[img.awsid] = img
|
94
|
+
end
|
95
|
+
|
96
|
+
images.each_value { |image| each_image.call(image) } if each_image
|
97
|
+
|
98
|
+
images = nil if images.empty? # Don't return an empty hash
|
99
|
+
images
|
100
|
+
end
|
101
|
+
|
102
|
+
# +id+ AMI ID to deregister (ami-XXXXXXX)
|
103
|
+
# Returns true when successful. Otherwise throws an exception.
|
104
|
+
def deregister(id)
|
105
|
+
opts = {
|
106
|
+
:image_id => id
|
107
|
+
}
|
108
|
+
ret = @ec2.deregister_image(opts)
|
109
|
+
puts ret.to_yaml
|
110
|
+
true
|
111
|
+
end
|
112
|
+
|
113
|
+
# +path+ the S3 path to the manifest (bucket/file.manifest.xml)
|
114
|
+
# Returns the AMI ID when successful, otherwise throws an exception.
|
115
|
+
def register(path)
|
116
|
+
opts = {
|
117
|
+
:image_location => path
|
118
|
+
}
|
119
|
+
ret = @ec2.register_image(opts)
|
120
|
+
puts ret.to_yaml
|
121
|
+
true
|
122
|
+
end
|
123
|
+
|
124
|
+
# imageOwnerId: "203338247012"
|
125
|
+
# kernelId: aki-a71cf9ce
|
126
|
+
# ramdiskId: ari-a51cf9cc
|
127
|
+
# imageState: available
|
128
|
+
# imageId: ami-dd34d3b4
|
129
|
+
# architecture: i386
|
130
|
+
# isPublic: "false"
|
131
|
+
# imageLocation: solutious-rudy-us/debian-squeeze-m1.small-v5.manifest.xml
|
132
|
+
# imageType: machine
|
133
|
+
def Images.from_hash(h)
|
134
|
+
img = Rudy::AWS::EC2::Image.new
|
135
|
+
img.owner = h['imageOwnerId']
|
136
|
+
img.aki = h['kernelId']
|
137
|
+
img.ari = h['ramdiskId']
|
138
|
+
img.state = h['imageState']
|
139
|
+
img.awsid = h['imageId']
|
140
|
+
img.arch = h['architecture']
|
141
|
+
img.visibility = h['isPublic'] == 'true' ? 'public' : 'private'
|
142
|
+
img.location = h['imageLocation']
|
143
|
+
img.kind = h['imageType']
|
144
|
+
img
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
private
|
149
|
+
|
150
|
+
# * +img_ids+ an Array of images IDs (Strings) or Image objects.
|
151
|
+
# Note: This method removes nil values and always returns an Array.
|
152
|
+
# Returns an Array of image IDs.
|
153
|
+
def objects_to_image_ids(img_ids)
|
154
|
+
img_ids = [img_ids].flatten # Make sure it's an Array
|
155
|
+
img_ids = img_ids.collect do |img|
|
156
|
+
next if img.nil? || img.to_s.empty?
|
157
|
+
if !img.is_a?(Rudy::AWS::EC2::Image) && !Rudy::Utils.is_id?(:image, img)
|
158
|
+
raise %Q("#{img}" is not an image ID or object)
|
159
|
+
end
|
160
|
+
img.is_a?(Rudy::AWS::EC2::Image) ? img.awsid : img
|
161
|
+
end
|
162
|
+
img_ids
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
end
|