greenhat 0.1.4
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.
- checksums.yaml +7 -0
- data/README.md +64 -0
- data/bin/greenhat +12 -0
- data/lib/greenhat.rb +80 -0
- data/lib/greenhat/accessors/disk.rb +27 -0
- data/lib/greenhat/accessors/logs/production.rb +41 -0
- data/lib/greenhat/accessors/logs/sidekiq.rb +41 -0
- data/lib/greenhat/accessors/memory.rb +46 -0
- data/lib/greenhat/accessors/network.rb +8 -0
- data/lib/greenhat/accessors/process.rb +8 -0
- data/lib/greenhat/archive.rb +108 -0
- data/lib/greenhat/cli.rb +448 -0
- data/lib/greenhat/host.rb +182 -0
- data/lib/greenhat/logbot.rb +86 -0
- data/lib/greenhat/pry_helpers.rb +51 -0
- data/lib/greenhat/settings.rb +51 -0
- data/lib/greenhat/shell.rb +92 -0
- data/lib/greenhat/shell/cat.rb +125 -0
- data/lib/greenhat/shell/disk.rb +68 -0
- data/lib/greenhat/shell/faststats.rb +195 -0
- data/lib/greenhat/shell/gitlab.rb +45 -0
- data/lib/greenhat/shell/help.rb +15 -0
- data/lib/greenhat/shell/helper.rb +514 -0
- data/lib/greenhat/shell/log.rb +344 -0
- data/lib/greenhat/shell/memory.rb +31 -0
- data/lib/greenhat/shell/network.rb +12 -0
- data/lib/greenhat/shell/process.rb +12 -0
- data/lib/greenhat/shell/report.rb +319 -0
- data/lib/greenhat/thing.rb +121 -0
- data/lib/greenhat/thing/file_types.rb +705 -0
- data/lib/greenhat/thing/formatters/api_json.rb +34 -0
- data/lib/greenhat/thing/formatters/bracket_log.rb +44 -0
- data/lib/greenhat/thing/formatters/clean_raw.rb +23 -0
- data/lib/greenhat/thing/formatters/colon_split_strip.rb +12 -0
- data/lib/greenhat/thing/formatters/dotenv.rb +10 -0
- data/lib/greenhat/thing/formatters/format.rb +12 -0
- data/lib/greenhat/thing/formatters/free_m.rb +29 -0
- data/lib/greenhat/thing/formatters/gitlab_ctl_tail.rb +51 -0
- data/lib/greenhat/thing/formatters/gitlab_status.rb +26 -0
- data/lib/greenhat/thing/formatters/json.rb +63 -0
- data/lib/greenhat/thing/formatters/json_shellwords.rb +44 -0
- data/lib/greenhat/thing/formatters/multiline_json.rb +10 -0
- data/lib/greenhat/thing/formatters/raw.rb +18 -0
- data/lib/greenhat/thing/formatters/shellwords.rb +23 -0
- data/lib/greenhat/thing/formatters/table.rb +26 -0
- data/lib/greenhat/thing/formatters/time_json.rb +21 -0
- data/lib/greenhat/thing/formatters/time_shellwords.rb +28 -0
- data/lib/greenhat/thing/formatters/time_space.rb +36 -0
- data/lib/greenhat/thing/helpers.rb +71 -0
- data/lib/greenhat/thing/history.rb +51 -0
- data/lib/greenhat/thing/info_format.rb +193 -0
- data/lib/greenhat/thing/kind.rb +97 -0
- data/lib/greenhat/thing/spinner.rb +52 -0
- data/lib/greenhat/thing/super_log.rb +102 -0
- data/lib/greenhat/tty/custom_line.rb +29 -0
- data/lib/greenhat/tty/line.rb +326 -0
- data/lib/greenhat/tty/reader.rb +110 -0
- data/lib/greenhat/version.rb +3 -0
- data/lib/greenhat/views/css.slim +126 -0
- data/lib/greenhat/views/disk_free.slim +18 -0
- data/lib/greenhat/views/index.slim +51 -0
- data/lib/greenhat/views/info.slim +39 -0
- data/lib/greenhat/views/manifest.slim +22 -0
- data/lib/greenhat/views/memory.slim +18 -0
- data/lib/greenhat/views/netstat.slim +20 -0
- data/lib/greenhat/views/process.slim +21 -0
- data/lib/greenhat/views/systemctl.slim +40 -0
- data/lib/greenhat/views/ulimit.slim +15 -0
- data/lib/greenhat/web.rb +46 -0
- metadata +476 -0
data/lib/greenhat/cli.rb
ADDED
@@ -0,0 +1,448 @@
|
|
1
|
+
# Top level namespace
|
2
|
+
module GreenHat
|
3
|
+
# CLI Methods
|
4
|
+
# rubocop:disable Metrics/ModuleLength
|
5
|
+
module Cli
|
6
|
+
def self.cursor
|
7
|
+
@cursor = TTY::Cursor
|
8
|
+
end
|
9
|
+
|
10
|
+
# Input Loop Listener
|
11
|
+
def self.reader
|
12
|
+
@reader ||= reader_setup
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.files
|
16
|
+
@files ||= Thing.all.map(&:name).uniq
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.reader_setup
|
20
|
+
reader = TTY::Reader.new(history_duplicates: false, interrupt: -> { back })
|
21
|
+
|
22
|
+
Settings.cmd_history_clean.each do |line|
|
23
|
+
reader.add_to_history(line)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Blank?
|
27
|
+
reader.add_to_history ''
|
28
|
+
|
29
|
+
# Remove Line
|
30
|
+
reader.on(:keyctrl_u) do |_event|
|
31
|
+
reader.line.remove reader.line.text.size
|
32
|
+
end
|
33
|
+
|
34
|
+
# Navigate Word Left
|
35
|
+
reader.on(:keyctrl_left) { reader.line.move_word_left }
|
36
|
+
|
37
|
+
# Navigate Word Right
|
38
|
+
reader.on(:keyctrl_right) { reader.line.move_word_right }
|
39
|
+
|
40
|
+
# Navigate Beginning
|
41
|
+
reader.on(:keyctrl_a) { reader.line.move_to_start }
|
42
|
+
|
43
|
+
# Navigate End
|
44
|
+
reader.on(:keyctrl_e) { reader.line.move_to_end }
|
45
|
+
|
46
|
+
reader.on(:keyback_tab) { back }
|
47
|
+
|
48
|
+
reader.on(:keytab) do
|
49
|
+
process
|
50
|
+
auto
|
51
|
+
end
|
52
|
+
|
53
|
+
reader.instance_variable_get(:@history)
|
54
|
+
|
55
|
+
# DEBUG PRY
|
56
|
+
reader.on(:keyctrl_p) do |event|
|
57
|
+
binding.pry
|
58
|
+
end
|
59
|
+
reader
|
60
|
+
end
|
61
|
+
|
62
|
+
# =========================================================
|
63
|
+
# Auto Complete
|
64
|
+
# =========================================================
|
65
|
+
def self.auto
|
66
|
+
word = reader.line.word
|
67
|
+
|
68
|
+
if word.blank?
|
69
|
+
help
|
70
|
+
else
|
71
|
+
auto_match(current_methods + current_submodules + cmd_list, word)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.auto_match(matches, word)
|
76
|
+
matches.select! { |x| x[/^#{Regexp.escape(word)}/] }
|
77
|
+
|
78
|
+
if submodule?
|
79
|
+
submodule!
|
80
|
+
reader.breaker = true
|
81
|
+
# Only one Match!
|
82
|
+
elsif matches.count == 1
|
83
|
+
auto_update(matches.first, word)
|
84
|
+
|
85
|
+
# Print List of Options
|
86
|
+
elsif matches.count > 1
|
87
|
+
puts matches.join("\t").colorize(:light_green)
|
88
|
+
|
89
|
+
# No other Matches
|
90
|
+
else
|
91
|
+
file_matches = files.select { |x| x[/^#{Regexp.escape(word)}/] }
|
92
|
+
auto_files(file_matches, word) unless file_matches.empty?
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Auto Complete File Names
|
98
|
+
def self.auto_files(matches, word)
|
99
|
+
if matches.count == 1
|
100
|
+
auto_update(matches.first, word)
|
101
|
+
|
102
|
+
# Print List of Options
|
103
|
+
elsif matches.count > 1
|
104
|
+
auto_update(common_substr(matches), word)
|
105
|
+
puts matches.join("\t").colorize(:light_green)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Handle Updates to Reader
|
110
|
+
def self.auto_update(match, word)
|
111
|
+
add = match.split(word, 2).last
|
112
|
+
reader.line.insert add unless add.nil?
|
113
|
+
end
|
114
|
+
|
115
|
+
# Complete as much as possible comparison
|
116
|
+
# https://stackoverflow.com/a/2158481/1678507
|
117
|
+
def self.common_substr(strings)
|
118
|
+
shortest = strings.min_by(&:length)
|
119
|
+
maxlen = shortest.length
|
120
|
+
maxlen.downto(0) do |len|
|
121
|
+
0.upto(maxlen - len) do |start|
|
122
|
+
substr = shortest[start, len]
|
123
|
+
return substr if strings.all? { |str| str.include? substr }
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
# =========================================================
|
128
|
+
|
129
|
+
def self.did_you_mean
|
130
|
+
dictionary = current_methods + current_submodules + cmd_list
|
131
|
+
|
132
|
+
# all.select! { |x| x.include? cmd }
|
133
|
+
|
134
|
+
all = DidYouMean::SpellChecker.new(dictionary: dictionary).correct(cmd)
|
135
|
+
|
136
|
+
if all.empty?
|
137
|
+
puts [
|
138
|
+
'Command not found '.colorize(:red),
|
139
|
+
cmd.colorize(:light_yellow),
|
140
|
+
' ('.colorize(:light_black),
|
141
|
+
'help'.colorize(:blue),
|
142
|
+
' to show available commands'.colorize(:light_black),
|
143
|
+
')'.colorize(:light_black)
|
144
|
+
].join
|
145
|
+
else
|
146
|
+
puts "#{'Did you mean?'.colorize(:cyan)} #{all.join("\t").colorize(:green)}"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# Auto/Run Process - Populate and parse: @list
|
151
|
+
def self.process
|
152
|
+
line = reader.line
|
153
|
+
@list = Shellwords.split line.text
|
154
|
+
rescue StandardError => e
|
155
|
+
puts "#{'Invalid Command'.colorize(:red)}: #{e.message.colorize(:green)}"
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.available(list)
|
159
|
+
list.map(&:to_s).map(&:downcase)
|
160
|
+
end
|
161
|
+
|
162
|
+
# Reader helper
|
163
|
+
def self.cmd
|
164
|
+
@list.first
|
165
|
+
end
|
166
|
+
|
167
|
+
def self.run?
|
168
|
+
current_methods.include? cmd
|
169
|
+
end
|
170
|
+
|
171
|
+
# Special Command Overrides
|
172
|
+
def self.cmd_list
|
173
|
+
['help', '~', '..', 'back', 'clear']
|
174
|
+
end
|
175
|
+
|
176
|
+
def self.cmd?
|
177
|
+
cmd_list.any? cmd
|
178
|
+
end
|
179
|
+
|
180
|
+
def self.submodule?
|
181
|
+
current_submodules.include? @list.first
|
182
|
+
end
|
183
|
+
|
184
|
+
def self.cmd_run
|
185
|
+
case cmd
|
186
|
+
when 'help' then help
|
187
|
+
when '~' then home
|
188
|
+
when '..', 'back' then back
|
189
|
+
when 'clear' then clear_screen
|
190
|
+
end
|
191
|
+
|
192
|
+
@list.shift
|
193
|
+
end
|
194
|
+
|
195
|
+
# Final Command Execution
|
196
|
+
def self.run!
|
197
|
+
# Shift to prevent duplicate Runs / Arity for identifying if Method has params
|
198
|
+
if current_location.method(@list.first).arity.zero?
|
199
|
+
current_location.send(@list.shift.clone)
|
200
|
+
else
|
201
|
+
current_location.send(@list.shift.clone, @list.clone)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def self.run
|
206
|
+
return true if @list.blank?
|
207
|
+
|
208
|
+
if cmd?
|
209
|
+
cmd_run
|
210
|
+
elsif run?
|
211
|
+
run!
|
212
|
+
|
213
|
+
return true # End Early
|
214
|
+
|
215
|
+
elsif current_submodule?
|
216
|
+
@list.shift
|
217
|
+
elsif submodule?
|
218
|
+
submodule!
|
219
|
+
# Prepend Default if exists
|
220
|
+
elsif default?
|
221
|
+
@list.unshift 'default'
|
222
|
+
else
|
223
|
+
did_you_mean
|
224
|
+
@list.shift
|
225
|
+
end
|
226
|
+
|
227
|
+
run # Loop Back
|
228
|
+
rescue StandardError => e
|
229
|
+
LogBot.fatal('CLI Run', e.message)
|
230
|
+
puts e.backtrace[0..4].join("\n").colorize(:red)
|
231
|
+
end
|
232
|
+
|
233
|
+
# Check for `default` method and files
|
234
|
+
def self.default?
|
235
|
+
files.include?(cmd) && current_methods.include?('default')
|
236
|
+
end
|
237
|
+
|
238
|
+
# General Helper
|
239
|
+
def self.help
|
240
|
+
if current_location.methods(false).count.zero?
|
241
|
+
puts 'No Commands'.colorize(:red)
|
242
|
+
else
|
243
|
+
puts 'Commands: '
|
244
|
+
current_location.methods(false).map(&:to_s).sort.each do |item|
|
245
|
+
next if %w[default help].any? { |x| x == item }
|
246
|
+
|
247
|
+
puts "=> #{item.to_s.colorize(:blue)}"
|
248
|
+
end
|
249
|
+
|
250
|
+
current_location.send(:help) if current_methods.include? 'help'
|
251
|
+
end
|
252
|
+
|
253
|
+
puts ''
|
254
|
+
|
255
|
+
if current_location.constants.count.zero?
|
256
|
+
puts 'No Submodules'.colorize(:red)
|
257
|
+
else
|
258
|
+
puts 'Submodules'
|
259
|
+
current_location.constants.each do |item|
|
260
|
+
puts "-> #{item.to_s.demodulize.downcase.colorize(:yellow)}"
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
def self.location
|
266
|
+
@location ||= [Shell]
|
267
|
+
end
|
268
|
+
|
269
|
+
# Replace Location
|
270
|
+
def self.move(spot)
|
271
|
+
@location = [spot]
|
272
|
+
end
|
273
|
+
|
274
|
+
# Append to Location
|
275
|
+
def self.submodule!
|
276
|
+
spot = @list.shift
|
277
|
+
reader.line.replace @list.join(' ')
|
278
|
+
@location << current_location.const_get(spot.capitalize.to_sym)
|
279
|
+
end
|
280
|
+
|
281
|
+
def self.home
|
282
|
+
move Shell
|
283
|
+
end
|
284
|
+
|
285
|
+
def self.back
|
286
|
+
move location[-2] if location.count > 1
|
287
|
+
end
|
288
|
+
|
289
|
+
# Reader to Get Last Location's Available Methods / Keep Helper Methods
|
290
|
+
def self.current_methods
|
291
|
+
current_location.methods(false).map(&:to_s)
|
292
|
+
# .reject { |x| x.include? '_help' }
|
293
|
+
end
|
294
|
+
|
295
|
+
def self.current_submodules
|
296
|
+
current_location.constants.map(&:to_s).map(&:downcase)
|
297
|
+
end
|
298
|
+
|
299
|
+
# Full Commands at the Submodule `disk summary` from `disk`
|
300
|
+
def self.current_submodule?
|
301
|
+
current_location.to_s.demodulize.downcase == @list.first
|
302
|
+
end
|
303
|
+
|
304
|
+
def self.current_location
|
305
|
+
location.last
|
306
|
+
end
|
307
|
+
|
308
|
+
def self.location_reader
|
309
|
+
location.map(&:to_s).map(&:downcase).map(&:demodulize).join('/').gsub('shell', '~').colorize(:blue)
|
310
|
+
end
|
311
|
+
|
312
|
+
def self.readline_notch
|
313
|
+
"#{'greenhat'.colorize(:light_black)} #{location_reader} » "
|
314
|
+
end
|
315
|
+
|
316
|
+
def self.clear_screen
|
317
|
+
print cursor.clear_screen + cursor.move_to(0, 0)
|
318
|
+
end
|
319
|
+
|
320
|
+
def self.quiet
|
321
|
+
@quiet
|
322
|
+
end
|
323
|
+
|
324
|
+
# Process any Args
|
325
|
+
# --report
|
326
|
+
# --quiet
|
327
|
+
# --load -- Auto Load Things
|
328
|
+
# TODO: Add Help (--help)
|
329
|
+
def self.startup_args(files)
|
330
|
+
@report = true if files.any? { |x| ['--report', '-r'].include? x }
|
331
|
+
@quiet = true if files.any? { |x| ['--quiet', '-q'].include? x }
|
332
|
+
@load = true if files.any? { |x| ['--load', '-l'].include? x }
|
333
|
+
|
334
|
+
binding.pry if files.include? '--help'
|
335
|
+
|
336
|
+
files.reject! { |x| startup_arg_list.include? x }
|
337
|
+
end
|
338
|
+
|
339
|
+
def self.startup_arg_list
|
340
|
+
['--load', '--l', '--quiet', '-q', '--report', '-r']
|
341
|
+
end
|
342
|
+
|
343
|
+
# rubocop:disable Metrics/MethodLength
|
344
|
+
def self.start(files)
|
345
|
+
# If no arguments Supplied Print and quit - rather than nasty exception
|
346
|
+
# TODO: Add Usage
|
347
|
+
|
348
|
+
Settings.start
|
349
|
+
|
350
|
+
startup_args files
|
351
|
+
clear_screen
|
352
|
+
|
353
|
+
if files.empty? || files.count { |x| File.exist? x }.zero?
|
354
|
+
puts "No arguments or files don't exist".colorize(:red)
|
355
|
+
puts 'Usage: greenhat <sos-archive.tgz> <sos-archive2.tgz>'
|
356
|
+
Shell.about
|
357
|
+
end
|
358
|
+
|
359
|
+
load_files files
|
360
|
+
|
361
|
+
# Handle Args
|
362
|
+
if @report
|
363
|
+
# Don't Use Pagination
|
364
|
+
GreenHat::Shell.report(['--raw'])
|
365
|
+
return true
|
366
|
+
end
|
367
|
+
|
368
|
+
Thing.all.each(&:process) if @load
|
369
|
+
|
370
|
+
value ||= '' # Empty Start
|
371
|
+
|
372
|
+
loop do
|
373
|
+
line = reader.read_line(readline_notch, value: value)
|
374
|
+
value = '' # Remove Afterwards
|
375
|
+
|
376
|
+
if reader.breaker
|
377
|
+
value = line
|
378
|
+
puts ''
|
379
|
+
next
|
380
|
+
end
|
381
|
+
|
382
|
+
if line =~ /^exit/i
|
383
|
+
Settings.cmd_write
|
384
|
+
|
385
|
+
break
|
386
|
+
end
|
387
|
+
|
388
|
+
Settings.cmd_add(line) unless line.blank?
|
389
|
+
|
390
|
+
process
|
391
|
+
run
|
392
|
+
end
|
393
|
+
end
|
394
|
+
# rubocop:enable Metrics/MethodLength
|
395
|
+
|
396
|
+
def self.load_files(files)
|
397
|
+
# TODO: Web Helpers?
|
398
|
+
# suppress_output { GreenHat::Web.start }
|
399
|
+
|
400
|
+
# Don't double up on archives / Only Existing files
|
401
|
+
puts 'Loading Archives'.colorize(:blue)
|
402
|
+
files.uniq.each do |file|
|
403
|
+
next unless File.exist?(file)
|
404
|
+
|
405
|
+
puts "- #{file}".colorize(:magenta)
|
406
|
+
ArchiveLoader.load file
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
def self.suppress_output
|
411
|
+
original_stderr = $stderr.clone
|
412
|
+
original_stdout = $stdout.clone
|
413
|
+
$stderr.reopen(File.new('/dev/null', 'w'))
|
414
|
+
$stdout.reopen(File.new('/dev/null', 'w'))
|
415
|
+
yield
|
416
|
+
ensure
|
417
|
+
$stdout.reopen(original_stdout)
|
418
|
+
$stderr.reopen(original_stderr)
|
419
|
+
end
|
420
|
+
|
421
|
+
def self.template
|
422
|
+
"#{__dir__}/views/index.slim"
|
423
|
+
end
|
424
|
+
|
425
|
+
def self.output
|
426
|
+
'greenhat.html'
|
427
|
+
end
|
428
|
+
|
429
|
+
def self.prompt
|
430
|
+
TTY::Prompt.new(active_color: :cyan)
|
431
|
+
end
|
432
|
+
|
433
|
+
# TODO
|
434
|
+
def self.menu
|
435
|
+
prompt.select('Wat do?') do |menu|
|
436
|
+
menu.choice name: 'exit'
|
437
|
+
menu.choice name: 'Export Kibana Dashboard', value: 'export'
|
438
|
+
menu.choice name: 'console (pry)', value: 'console'
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
442
|
+
def self.bad_file(archive)
|
443
|
+
puts color("Cannot find archive: #{archive}", :red)
|
444
|
+
exit 1
|
445
|
+
end
|
446
|
+
end
|
447
|
+
# rubocop:enable Metrics/ModuleLength
|
448
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
# Individual Host Helper
|
2
|
+
class Host < Teron
|
3
|
+
include ActionView::Helpers::DateHelper
|
4
|
+
include ActionView::Helpers::NumberHelper
|
5
|
+
|
6
|
+
field :name
|
7
|
+
|
8
|
+
belongs_to :archive
|
9
|
+
|
10
|
+
# def load(file)
|
11
|
+
# @file = file
|
12
|
+
# self.files = Archive.load(file)
|
13
|
+
# save!
|
14
|
+
# end
|
15
|
+
|
16
|
+
def archive_name
|
17
|
+
File.basename archive
|
18
|
+
end
|
19
|
+
|
20
|
+
def find_file(file_name)
|
21
|
+
files.find { |x| x.name == file_name }
|
22
|
+
end
|
23
|
+
|
24
|
+
def icon
|
25
|
+
release_file = find_file files.map(&:name).grep(/_release/).first
|
26
|
+
|
27
|
+
release = release_file.raw.join
|
28
|
+
|
29
|
+
if release.include? 'ubuntu'
|
30
|
+
'fa-ubuntu'
|
31
|
+
elsif release.include? 'suse'
|
32
|
+
'fa-suse'
|
33
|
+
elsif release.include? 'redhat'
|
34
|
+
'fa-redhat'
|
35
|
+
elsif release.include? 'centos'
|
36
|
+
'fa-centos'
|
37
|
+
else
|
38
|
+
'fa-linux'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# ----------------------------
|
43
|
+
# Helpers
|
44
|
+
# ----------------------------
|
45
|
+
def percent(value, total)
|
46
|
+
(value.to_i / total.to_f).round(2) * 100
|
47
|
+
end
|
48
|
+
|
49
|
+
def systemctl_color(entry)
|
50
|
+
case entry.status
|
51
|
+
when 'enabled' then :green
|
52
|
+
when 'static' then :orange
|
53
|
+
when 'disabled' then :red
|
54
|
+
else
|
55
|
+
:grey
|
56
|
+
end
|
57
|
+
end
|
58
|
+
# ---------------------------
|
59
|
+
|
60
|
+
def manifest
|
61
|
+
file = find_file 'gitlab_version_manifest_json'
|
62
|
+
return nil unless file
|
63
|
+
|
64
|
+
Oj.load file.raw.join
|
65
|
+
end
|
66
|
+
|
67
|
+
def uptime
|
68
|
+
file = find_file 'uptime'
|
69
|
+
return nil unless file
|
70
|
+
|
71
|
+
file.raw
|
72
|
+
end
|
73
|
+
|
74
|
+
def uname
|
75
|
+
file = find_file 'uname'
|
76
|
+
return nil unless file
|
77
|
+
|
78
|
+
file.raw.join
|
79
|
+
end
|
80
|
+
|
81
|
+
def cpuinfo
|
82
|
+
file = find_file 'cpuinfo'
|
83
|
+
return nil unless file
|
84
|
+
|
85
|
+
file.raw.join("\n").split("\n\n").map do |cpu|
|
86
|
+
all = cpu.split("\n").map do |row|
|
87
|
+
row.delete("\t").split(': ')
|
88
|
+
end
|
89
|
+
{ details: all[1..], order: all[0].last }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def cpu_speed
|
94
|
+
file = find_file 'lscpu'
|
95
|
+
return nil unless file
|
96
|
+
|
97
|
+
details = file.raw.find { |x| x.include? 'MHz' }
|
98
|
+
details.reverse.split(' ', 2).map(&:reverse).reverse
|
99
|
+
end
|
100
|
+
|
101
|
+
def total_memory
|
102
|
+
file = find_file 'free_m'
|
103
|
+
return nil unless file
|
104
|
+
|
105
|
+
value = file.raw.dig(1, 1).to_i
|
106
|
+
number_to_human_size(value * 1024 * 1024)
|
107
|
+
end
|
108
|
+
|
109
|
+
def free_m
|
110
|
+
file = find_file 'free_m'
|
111
|
+
return nil unless file
|
112
|
+
|
113
|
+
file.raw
|
114
|
+
end
|
115
|
+
|
116
|
+
def df_h
|
117
|
+
file = find_file 'df_h'
|
118
|
+
return nil unless file
|
119
|
+
|
120
|
+
file.raw
|
121
|
+
end
|
122
|
+
|
123
|
+
def netstat
|
124
|
+
file = find_file 'netstat'
|
125
|
+
return nil unless file
|
126
|
+
|
127
|
+
file.raw
|
128
|
+
end
|
129
|
+
|
130
|
+
def ulimit
|
131
|
+
file = find_file 'ulimit'
|
132
|
+
return nil unless file
|
133
|
+
|
134
|
+
results = file.raw.map do |entry|
|
135
|
+
{
|
136
|
+
value: entry.split[-1],
|
137
|
+
details: entry.split(' ').first
|
138
|
+
}
|
139
|
+
end
|
140
|
+
|
141
|
+
results.sort_by { |x| x[:details].downcase }
|
142
|
+
end
|
143
|
+
|
144
|
+
def processes
|
145
|
+
file = find_file 'ps'
|
146
|
+
return nil unless file
|
147
|
+
|
148
|
+
headers = file.raw.first.split(' ', 11)
|
149
|
+
list = file.raw[1..].each.map do |row|
|
150
|
+
row.split(' ', 11).each_with_index.each_with_object({}) do |(v, i), obj|
|
151
|
+
obj[headers[i]] = v
|
152
|
+
end
|
153
|
+
end
|
154
|
+
{ headers: headers, list: list }
|
155
|
+
end
|
156
|
+
|
157
|
+
def systemctl_unit_files
|
158
|
+
file = find_file 'systemctl_unit_files'
|
159
|
+
return nil unless file
|
160
|
+
|
161
|
+
all = file.raw[1..-2].map do |x|
|
162
|
+
unit, status = x.split
|
163
|
+
{ unit: unit, status: status }
|
164
|
+
end
|
165
|
+
|
166
|
+
all.reject! { |x| x[:unit].nil? }
|
167
|
+
all.sort_by(&:unit)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# # Slim Wrapper
|
172
|
+
# class List
|
173
|
+
# attr_accessor :hosts
|
174
|
+
|
175
|
+
# def initialize
|
176
|
+
# self.hosts = []
|
177
|
+
# end
|
178
|
+
|
179
|
+
# def slim(file, host = nil)
|
180
|
+
# Slim::Template.new("#{__dir__}/views/#{file}.slim").render(host)
|
181
|
+
# end
|
182
|
+
# end
|