awsutils 1.4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +58 -0
- data/Rakefile +11 -0
- data/awsutils.gemspec +33 -0
- data/bin/ec2addsg +14 -0
- data/bin/ec2delsg +14 -0
- data/bin/ec2info +13 -0
- data/bin/ec2latestimage +12 -0
- data/bin/ec2listmachines +13 -0
- data/bin/ec2lsgrp +25 -0
- data/bin/elbls +13 -0
- data/bin/r53ls +14 -0
- data/lib/awsutils.rb +1 -0
- data/lib/awsutils/ec2addsg.rb +200 -0
- data/lib/awsutils/ec2delsg.rb +96 -0
- data/lib/awsutils/ec2info.rb +701 -0
- data/lib/awsutils/ec2latestimage.rb +84 -0
- data/lib/awsutils/ec2listmachines.rb +406 -0
- data/lib/awsutils/ec2lsgrp.rb +91 -0
- data/lib/awsutils/ec2sg.rb +77 -0
- data/lib/awsutils/elbls.rb +51 -0
- data/lib/awsutils/r53addrr.rb +28 -0
- data/lib/awsutils/r53ls.rb +92 -0
- data/lib/awsutils/version.rb +3 -0
- data/spec/lib/awsutils/ec2addsg_spec.rb +11 -0
- data/spec/lib/awsutils/ec2lsgrp_spec.rb +178 -0
- data/spec/spec_helper.rb +10 -0
- metadata +238 -0
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'net/http'
|
3
|
+
# require 'aws-sdk' # see the comment on `image_details` below
|
4
|
+
|
5
|
+
module AwsUtils
|
6
|
+
class Ec2LatestImage
|
7
|
+
def releases
|
8
|
+
@releases ||= begin
|
9
|
+
resp = JSON.parse(
|
10
|
+
Net::HTTP.get(
|
11
|
+
URI('http://cloud-images.ubuntu.com/locator/ec2/releasesTable')
|
12
|
+
).sub(/\],\n\]/, "]\n]")
|
13
|
+
)
|
14
|
+
parse_releases_array(resp['aaData']).select do |rel|
|
15
|
+
rel[:region] == 'us-east-1' &&
|
16
|
+
rel[:distro_version] == '14.04 LTS' &&
|
17
|
+
rel[:arch] == 'amd64'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def run
|
23
|
+
print_releases
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def print_releases
|
29
|
+
# Print a header
|
30
|
+
printf("%-13s %-10s %-9s %-20s\n", 'ID', 'Version', 'Release', 'Type')
|
31
|
+
|
32
|
+
puts('-' * 53)
|
33
|
+
|
34
|
+
# Print the releases
|
35
|
+
releases.each do |rel|
|
36
|
+
printf(
|
37
|
+
"%-13s %-10s %-9s %-20s\n",
|
38
|
+
rel[:ami],
|
39
|
+
rel[:distro_version],
|
40
|
+
rel[:release],
|
41
|
+
rel[:type]
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# def image_details
|
47
|
+
# This functionalty allows us to get more image details from the AWS API but
|
48
|
+
# it's not necessary for the library to work and right now we're not using it
|
49
|
+
# because it slows down loading time.
|
50
|
+
#
|
51
|
+
# @our_images ||= begin
|
52
|
+
# our_ami_ids = releases.map { |rel| rel[:ami] }
|
53
|
+
# images_details = connection.describe_images(image_ids: our_ami_ids).images
|
54
|
+
|
55
|
+
# images_details.each_with_object({}) { |ami, m| m[ami.image_id] = ami }
|
56
|
+
# end
|
57
|
+
# end
|
58
|
+
|
59
|
+
# rubocop:disable Metrics/MethodLength
|
60
|
+
def parse_releases_array(releases)
|
61
|
+
releases.map do |rel|
|
62
|
+
{
|
63
|
+
region: rel[0],
|
64
|
+
distro_name: rel[1],
|
65
|
+
distro_version: rel[2],
|
66
|
+
arch: rel[3],
|
67
|
+
type: rel[4],
|
68
|
+
release: rel[5],
|
69
|
+
ami: parse_ami_link(rel[6]),
|
70
|
+
aki: rel[7]
|
71
|
+
}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
# rubocop:enable Metrics/MethodLength
|
75
|
+
|
76
|
+
def parse_ami_link(link)
|
77
|
+
link.match(/launchAmi=(ami-\w{8})/)[1]
|
78
|
+
end
|
79
|
+
|
80
|
+
def connection
|
81
|
+
@connection ||= Aws::EC2::Client.new
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,406 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'trollop'
|
3
|
+
require 'fog'
|
4
|
+
|
5
|
+
gem 'fog', '>= 1.6.0'
|
6
|
+
|
7
|
+
class Array
|
8
|
+
def longest
|
9
|
+
length = 0
|
10
|
+
val = ''
|
11
|
+
each do |a|
|
12
|
+
len_new = a.length
|
13
|
+
if len_new > length
|
14
|
+
length = len_new
|
15
|
+
val = a
|
16
|
+
end
|
17
|
+
end
|
18
|
+
val
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module AwsUtils
|
23
|
+
class Ec2ListMachines
|
24
|
+
def connect
|
25
|
+
@connect = Fog::Compute.new(provider: 'AWS')
|
26
|
+
if $DEBUG
|
27
|
+
puts 'Inspect connection result:'
|
28
|
+
puts connect.inspect
|
29
|
+
end
|
30
|
+
|
31
|
+
@connect
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_servers(opts)
|
35
|
+
static_ips = []
|
36
|
+
connect.addresses.all.each do |eip|
|
37
|
+
static_ips << eip.public_ip
|
38
|
+
end
|
39
|
+
|
40
|
+
group_map = {}
|
41
|
+
connect.security_groups.map { |g| group_map[g.name] = g.group_id }
|
42
|
+
|
43
|
+
if opts[:search]
|
44
|
+
servers = connect.servers.select do |s|
|
45
|
+
s.tags['Name'] =~ /.*#{opts[:search]}.*/
|
46
|
+
end
|
47
|
+
else
|
48
|
+
servers = connect.servers
|
49
|
+
end
|
50
|
+
|
51
|
+
servers_a = []
|
52
|
+
|
53
|
+
servers.each do |s|
|
54
|
+
if (opts[:state].nil? || (s.state == opts[:state])) &&
|
55
|
+
(
|
56
|
+
(opts[:terminated] == true) ||
|
57
|
+
(s.state != 'terminated') ||
|
58
|
+
(opts[:state] == 'terminated')
|
59
|
+
) &&
|
60
|
+
(opts[:flavor].nil? || (s.flavor_id == opts[:flavor])) &&
|
61
|
+
(opts[:role].nil? || (s.tags['Role'] == opts[:role])) &&
|
62
|
+
(opts[:zone].nil? || (s.availability_zone.to_s == opts[:zone]))
|
63
|
+
|
64
|
+
if s.public_ip_address.nil?
|
65
|
+
pub_ip = ''
|
66
|
+
else
|
67
|
+
pub_ip = s.public_ip_address
|
68
|
+
|
69
|
+
static_ip = static_ips.include?(pub_ip) ? '(S)' : '(D)'
|
70
|
+
end
|
71
|
+
|
72
|
+
role = s.tags['Role'] ? '-' : s.tags['Role']
|
73
|
+
|
74
|
+
if s.groups.first =~ /-/
|
75
|
+
group_to_insert = "#{group_map[s.groups.first]}/#{s.groups.first}"
|
76
|
+
else
|
77
|
+
group_to_insert = s.groups.first
|
78
|
+
end
|
79
|
+
|
80
|
+
created = s.tags['created_on'] ||= s.created_at
|
81
|
+
|
82
|
+
servers_a << {
|
83
|
+
name: s.tags['Name'].to_s,
|
84
|
+
date: created.to_s,
|
85
|
+
role: role.to_s,
|
86
|
+
az: s.availability_zone.to_s,
|
87
|
+
id: s.id,
|
88
|
+
group: group_to_insert,
|
89
|
+
pub_ip: pub_ip,
|
90
|
+
static_ip: static_ip,
|
91
|
+
flavor: s.flavor_id,
|
92
|
+
state: s.state
|
93
|
+
}
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
servers_a
|
99
|
+
end
|
100
|
+
|
101
|
+
def sort_servers(servers_a, sort_col)
|
102
|
+
case sort_col
|
103
|
+
when 'role'
|
104
|
+
servers_a.sort_by { |a| a[:role] }
|
105
|
+
when 'az'
|
106
|
+
servers_a.sort_by { |a| a[:az] }
|
107
|
+
when 'name'
|
108
|
+
servers_a.sort_by { |a| a[:name] }
|
109
|
+
when 'id'
|
110
|
+
servers_a.sort_by { |a| a[:id] }
|
111
|
+
when 'group'
|
112
|
+
servers_a.sort_by { |a| a[:group] }
|
113
|
+
when 'flavor'
|
114
|
+
servers_a.sort_by { |a| a[:flavor] }
|
115
|
+
when 'state'
|
116
|
+
servers_a.sort_by { |a| a[:state] }
|
117
|
+
when 'ip'
|
118
|
+
servers_a.sort_by { |a| a[:pub_ip] }
|
119
|
+
when 'static'
|
120
|
+
servers_a.sort_by { |a| a[:static_ip] }
|
121
|
+
when 'date'
|
122
|
+
servers_a.sort_by { |a| a[:date] }
|
123
|
+
else
|
124
|
+
servers_a.sort_by { |a| a[:name] }
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def get_longest_server_name(servers_sorted)
|
129
|
+
server_names = []
|
130
|
+
servers_sorted.each do |server|
|
131
|
+
server_names << server[:name]
|
132
|
+
end
|
133
|
+
|
134
|
+
server_names.longest.length + 1
|
135
|
+
end
|
136
|
+
|
137
|
+
def print_headers(csv_opt, servers_sorted, longest_server_name, show_dates)
|
138
|
+
if csv_opt == true
|
139
|
+
if show_dates
|
140
|
+
printf(
|
141
|
+
"%s,%s,%s,%s,%s,%s,%s,%s,%s\n",
|
142
|
+
'Name',
|
143
|
+
'Created',
|
144
|
+
'Role',
|
145
|
+
'AZ',
|
146
|
+
'ID',
|
147
|
+
'Sec Group',
|
148
|
+
'Public IP,(S/D)',
|
149
|
+
'Flavor',
|
150
|
+
'State'
|
151
|
+
)
|
152
|
+
else
|
153
|
+
printf(
|
154
|
+
"%s,%s,%s,%s,%s,%s,%s,%s\n",
|
155
|
+
'Name',
|
156
|
+
'Role',
|
157
|
+
'AZ',
|
158
|
+
'ID',
|
159
|
+
'Sec Group',
|
160
|
+
'Public IP,(S/D)',
|
161
|
+
'Flavor',
|
162
|
+
'State'
|
163
|
+
)
|
164
|
+
end
|
165
|
+
else
|
166
|
+
if show_dates
|
167
|
+
printf(
|
168
|
+
"\033[0;4m%-#{longest_server_name}s %-30s %-16s %-10s %-10s " \
|
169
|
+
"%-24s %-19s %-10s %-7s\033[0m\n",
|
170
|
+
'Name',
|
171
|
+
'Created',
|
172
|
+
'Role',
|
173
|
+
'AZ',
|
174
|
+
'ID',
|
175
|
+
'Sec Group',
|
176
|
+
'Public IP (S/D)',
|
177
|
+
'Flavor',
|
178
|
+
'State'
|
179
|
+
)
|
180
|
+
else
|
181
|
+
printf(
|
182
|
+
"\033[0;4m%-#{longest_server_name}s %-16s %-10s %-10s %-24s " \
|
183
|
+
"%-19s %-10s %-7s\033[0m\n",
|
184
|
+
'Name',
|
185
|
+
'Role',
|
186
|
+
'AZ',
|
187
|
+
'ID',
|
188
|
+
'Sec Group',
|
189
|
+
'Public IP (S/D)',
|
190
|
+
'Flavor',
|
191
|
+
'State'
|
192
|
+
)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def get_flavor_color(flavor)
|
198
|
+
case flavor
|
199
|
+
when 't1.micro'
|
200
|
+
'1;33'
|
201
|
+
when 'm1.large'
|
202
|
+
'0;33'
|
203
|
+
when 'm1.xlarge'
|
204
|
+
'0;34'
|
205
|
+
when 'm2.2xlarge'
|
206
|
+
'0;35'
|
207
|
+
when 'm2.4xlarge'
|
208
|
+
'0;31'
|
209
|
+
when 'm2.xlarge'
|
210
|
+
'0;36'
|
211
|
+
else
|
212
|
+
'0'
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def get_state_color(state)
|
217
|
+
case state
|
218
|
+
when 'running'
|
219
|
+
'1;32'
|
220
|
+
when 'stopped'
|
221
|
+
'1;31'
|
222
|
+
when 'starting'
|
223
|
+
'5;32'
|
224
|
+
when 'stopping'
|
225
|
+
'5;31'
|
226
|
+
else
|
227
|
+
'0'
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def print_machine_list(servers_sorted, nocolor_opt, csv_opt, longest_server_name, show_dates)
|
232
|
+
servers_sorted.each do |server|
|
233
|
+
name = server[:name]
|
234
|
+
date = server[:date]
|
235
|
+
role = server[:role]
|
236
|
+
az = server[:az]
|
237
|
+
id = server[:id]
|
238
|
+
group = server[:group]
|
239
|
+
ip = server[:pub_ip]
|
240
|
+
static_ip = server[:static_ip]
|
241
|
+
flavor = server[:flavor]
|
242
|
+
state = server[:state]
|
243
|
+
fcolor = get_flavor_color(flavor)
|
244
|
+
scolor = get_state_color(state)
|
245
|
+
|
246
|
+
if (nocolor_opt == false) && (csv_opt == false)
|
247
|
+
if show_dates
|
248
|
+
printf(
|
249
|
+
"\033[1m%-#{longest_server_name}s\033[0m %-30s %-16s %-10s %-10s " \
|
250
|
+
"%-24s %-19s \033[#{fcolor}m%-11s\033[#{scolor}m%-7s\033[0m\n",
|
251
|
+
name,
|
252
|
+
date,
|
253
|
+
role,
|
254
|
+
az,
|
255
|
+
id,
|
256
|
+
group,
|
257
|
+
"#{ip} #{static_ip}",
|
258
|
+
flavor,
|
259
|
+
state
|
260
|
+
)
|
261
|
+
else
|
262
|
+
printf(
|
263
|
+
"\033[1m%-#{longest_server_name}s\033[0m %-16s %-10s %-10s " \
|
264
|
+
"%-24s %-19s \033[#{fcolor}m%-11s\033[#{scolor}m%-7s\033[0m\n",
|
265
|
+
name,
|
266
|
+
role,
|
267
|
+
az,
|
268
|
+
id,
|
269
|
+
group,
|
270
|
+
"#{ip} #{static_ip}",
|
271
|
+
flavor,
|
272
|
+
state
|
273
|
+
)
|
274
|
+
end
|
275
|
+
elsif csv_opt == true
|
276
|
+
if show_dates
|
277
|
+
printf(
|
278
|
+
"%s,%s,%s,%s,%s,%s,%s,%s,%s\n",
|
279
|
+
name,
|
280
|
+
date,
|
281
|
+
role,
|
282
|
+
az,
|
283
|
+
id,
|
284
|
+
group,
|
285
|
+
"#{ip},#{static_ip}",
|
286
|
+
flavor,
|
287
|
+
state
|
288
|
+
)
|
289
|
+
else
|
290
|
+
printf(
|
291
|
+
"%s,%s,%s,%s,%s,%s,%s,%s\n",
|
292
|
+
name,
|
293
|
+
role,
|
294
|
+
az,
|
295
|
+
id,
|
296
|
+
group,
|
297
|
+
"#{ip},#{static_ip}",
|
298
|
+
flavor,
|
299
|
+
state
|
300
|
+
)
|
301
|
+
end
|
302
|
+
else
|
303
|
+
if show_dates
|
304
|
+
printf(
|
305
|
+
"%-#{longest_server_name}s %-20s %-16s %-10s %-10s %-20s %-19s %-11s%-7s\n",
|
306
|
+
name,
|
307
|
+
date,
|
308
|
+
role,
|
309
|
+
az,
|
310
|
+
id,
|
311
|
+
group,
|
312
|
+
"#{ip} #{static_ip}",
|
313
|
+
flavor,
|
314
|
+
state
|
315
|
+
)
|
316
|
+
else
|
317
|
+
printf(
|
318
|
+
"%-#{longest_server_name}s %-16s %-10s %-10s %-20s %-19s %-11s%-7s\n",
|
319
|
+
name,
|
320
|
+
role,
|
321
|
+
az,
|
322
|
+
id,
|
323
|
+
group,
|
324
|
+
"#{ip} #{static_ip}",
|
325
|
+
flavor,
|
326
|
+
state
|
327
|
+
)
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
def print_counts(servers_sorted, opts_csv)
|
334
|
+
flavor_data = {}
|
335
|
+
connect.flavors.each do |f|
|
336
|
+
flavor_data[f.id] = {
|
337
|
+
'cores' => f.cores,
|
338
|
+
'disk' => f.disk,
|
339
|
+
'ram' => f.ram
|
340
|
+
}
|
341
|
+
end
|
342
|
+
total_cores = 0
|
343
|
+
total_disk = 0.0
|
344
|
+
total_ram = 0.0
|
345
|
+
|
346
|
+
servers_sorted.each do |s|
|
347
|
+
total_cores += flavor_data[s[:flavor]]['cores']
|
348
|
+
total_disk += flavor_data[s[:flavor]]['disk'].to_f
|
349
|
+
total_ram += flavor_data[s[:flavor]]['ram'].to_f
|
350
|
+
end
|
351
|
+
|
352
|
+
if opts_csv
|
353
|
+
puts "total_instances,#{servers_sorted.count}"
|
354
|
+
puts "total_cores,#{total_cores}"
|
355
|
+
puts "total_disk,#{total_disk}"
|
356
|
+
puts "total_ram,#{total_ram}"
|
357
|
+
else
|
358
|
+
puts "\nTotals"
|
359
|
+
puts "\tInstances: #{servers_sorted.count}"
|
360
|
+
puts "\tCores: #{total_cores}"
|
361
|
+
printf("\tInstance storage: %.2f TB\n", total_disk / 1024)
|
362
|
+
printf("\tRAM: %.2f GB\n", total_ram / 1024)
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
def list_instances(opts)
|
367
|
+
servers = get_servers(opts)
|
368
|
+
servers_sorted = sort_servers(servers, opts[:sort])
|
369
|
+
longest_server_name = get_longest_server_name(servers_sorted)
|
370
|
+
print_headers(opts[:csv], servers_sorted, longest_server_name, opts[:dates])
|
371
|
+
print_machine_list(
|
372
|
+
servers_sorted,
|
373
|
+
opts[:nocolor],
|
374
|
+
opts[:csv],
|
375
|
+
longest_server_name,
|
376
|
+
opts[:dates]
|
377
|
+
)
|
378
|
+
|
379
|
+
print_counts(servers_sorted, opts[:csv])
|
380
|
+
end
|
381
|
+
|
382
|
+
def parse_opts
|
383
|
+
opts = Trollop.options do
|
384
|
+
opt :sort, 'Sort order', short: 's', type: String
|
385
|
+
opt :state, 'State', short: 'S', type: String
|
386
|
+
opt :flavor, 'Flavor', short: 'F', type: String
|
387
|
+
opt :role, 'Role', short: 'r', type: String
|
388
|
+
opt :zone, 'Availability Zone', short: 'Z', type: String
|
389
|
+
opt :csv, 'Output in CSV Format', short: 'C', default: false
|
390
|
+
opt :dates, 'Show creation timestamp', short: 'd', default: false
|
391
|
+
opt :terminated, 'Show terminated instances', short: 't', default: false
|
392
|
+
opt :nocolor, 'No color', short: 'c'
|
393
|
+
end
|
394
|
+
|
395
|
+
opts[:search] = ARGV[0] unless ARGV[0].empty?
|
396
|
+
|
397
|
+
opts
|
398
|
+
end
|
399
|
+
|
400
|
+
def initialize
|
401
|
+
list_instances(parse_opts)
|
402
|
+
rescue Interrupt
|
403
|
+
puts 'Interrupted by user (SIGINT, Ctrl+C, etc.)'
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|