awsutils 1.4.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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