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
@@ -0,0 +1,86 @@
|
|
1
|
+
# Log Helper
|
2
|
+
module LogBot
|
3
|
+
# For Amazing Print
|
4
|
+
def self.settings
|
5
|
+
{ ruby19_syntax: true, multiline: false }
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.output(name, message, level, duration = nil)
|
9
|
+
time = Time.now.to_s.colorize(:light_black)
|
10
|
+
output = time
|
11
|
+
output += " #{color_level(level)}"
|
12
|
+
output += " - #{name.to_s.colorize(:light_blue)} "
|
13
|
+
output += "(#{duration.round(2)}) ".colorize(:magenta) if duration
|
14
|
+
|
15
|
+
output += ' '
|
16
|
+
if message
|
17
|
+
output += case message
|
18
|
+
when String then message
|
19
|
+
else
|
20
|
+
message.ai(settings)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
puts output unless ENV['TESTING']
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.color_level(level)
|
28
|
+
case level
|
29
|
+
when :debug
|
30
|
+
level.to_s.upcase.colorize(:light_cyan)
|
31
|
+
when :info
|
32
|
+
level.to_s.upcase.colorize(:cyan)
|
33
|
+
when :warn
|
34
|
+
level.to_s.upcase.colorize(:yellow)
|
35
|
+
when :error
|
36
|
+
level.to_s.upcase.colorize(:light_red)
|
37
|
+
when :fatal
|
38
|
+
level.to_s.upcase.colorize(:red)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.info(name, message = nil, level = :info)
|
43
|
+
output(name, message, level)
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.debug(name, message = nil, level = :debug)
|
47
|
+
output(name, message, level)
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.warn(name, message = nil, level = :warn)
|
51
|
+
output(name, message, level)
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.error(name, message = nil, level = :error)
|
55
|
+
output(name, message, level)
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.fatal(name, message = nil, level = :fatal)
|
59
|
+
output(name, message, level)
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.do(name, message = nil, level = nil)
|
63
|
+
began_at = clock_time
|
64
|
+
|
65
|
+
level ||= :info
|
66
|
+
result = yield
|
67
|
+
|
68
|
+
duration = (clock_time - began_at).round(3)
|
69
|
+
|
70
|
+
output(name, message, level, duration)
|
71
|
+
|
72
|
+
result
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.measure
|
76
|
+
began_at = clock_time
|
77
|
+
result = yield
|
78
|
+
duration = (clock_time - began_at).round(3)
|
79
|
+
[result, duration]
|
80
|
+
end
|
81
|
+
|
82
|
+
# From Rack Time
|
83
|
+
def self.clock_time
|
84
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
def show(data)
|
2
|
+
pastel = Pastel.new
|
3
|
+
TTY::Pager.page do |pager|
|
4
|
+
data.each do |e|
|
5
|
+
table = TTY::Table.new(header: e.keys, rows: [e], orientation: :vertical)
|
6
|
+
# do some work with the line
|
7
|
+
|
8
|
+
output = table.render(:unicode, multiline: false) do |renderer|
|
9
|
+
renderer.border.style = :cyan
|
10
|
+
# renderer.filter = ->(val, row_index, col_index) do
|
11
|
+
# val.ai
|
12
|
+
# end
|
13
|
+
|
14
|
+
renderer.filter = lambda { |val, _row_index, col_index|
|
15
|
+
puts val.class unless val.instance_of? String
|
16
|
+
if col_index == 1
|
17
|
+
if val.numeric?
|
18
|
+
pastel.red.blue(val)
|
19
|
+
else
|
20
|
+
val
|
21
|
+
end
|
22
|
+
else
|
23
|
+
val
|
24
|
+
end
|
25
|
+
# .ai(raw: true).gsub('"','')
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
pager.write("\n#{output}") # write line to the pager
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def filter(data, params = {})
|
35
|
+
result = data.clone
|
36
|
+
params.each do |k, v|
|
37
|
+
result.select! do |row|
|
38
|
+
if row.key? k.to_sym
|
39
|
+
row[k.to_sym].include? v
|
40
|
+
else
|
41
|
+
false
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
result
|
47
|
+
end
|
48
|
+
|
49
|
+
def version
|
50
|
+
Thing.find_by(name: 'gitlab_version_manifest_json').data.build_version
|
51
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Top level namespace
|
2
|
+
module GreenHat
|
3
|
+
# Helper for all things user environment / settings / history
|
4
|
+
module Settings
|
5
|
+
def self.settings
|
6
|
+
@settings ||= {
|
7
|
+
history: []
|
8
|
+
}
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.start
|
12
|
+
Dir.mkdir dir unless Dir.exist? dir
|
13
|
+
|
14
|
+
# CMD History Loading / Tracking
|
15
|
+
File.write(cmd_file, "\n") unless File.exist? cmd_file
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.dir
|
19
|
+
"#{ENV['HOME']}/.greenhat"
|
20
|
+
end
|
21
|
+
|
22
|
+
# ----------------------------------
|
23
|
+
# Command History
|
24
|
+
def self.cmd_history
|
25
|
+
"#{dir}/cmd_history"
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.cmd_file
|
29
|
+
"#{dir}/cmd_history"
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.cmd_history_clean
|
33
|
+
File.read(cmd_file).split("\n")
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.cmd_write
|
37
|
+
File.write(cmd_file, cmd_history_clean.join("\n"))
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.cmd_add(line)
|
41
|
+
File.write(cmd_file, line, File.size(cmd_file), mode: 'a')
|
42
|
+
end
|
43
|
+
|
44
|
+
# ----------------------------------
|
45
|
+
|
46
|
+
# File Load History
|
47
|
+
def self.history_file
|
48
|
+
"#{dir}/file_history"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module GreenHat
|
2
|
+
# Root Level Shell
|
3
|
+
module Shell
|
4
|
+
def self.pry
|
5
|
+
binding.pry
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.df
|
9
|
+
Disk.df
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.ps
|
13
|
+
Process.ps
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.netstat
|
17
|
+
Network.netstat
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.free
|
21
|
+
Memory.free
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.load_local
|
25
|
+
return false unless TTY::Prompt.new.yes?('Load local Omnibus GitLab Instance files?')
|
26
|
+
|
27
|
+
archive_path = "#{$TMP}/#{Time.now.to_i}_local"
|
28
|
+
Dir.mkdir(archive_path)
|
29
|
+
# archive = Archive.new(name: 'local')
|
30
|
+
archive = Archive.new(name: archive_path, path: archive_path)
|
31
|
+
|
32
|
+
file_list = Dir['/var/log/gitlab/*/current'] + Dir['/var/log/gitlab/*/*.log']
|
33
|
+
|
34
|
+
file_list.each do |file|
|
35
|
+
next if File.size(file).zero?
|
36
|
+
|
37
|
+
puts "- Loading #{file.colorize(:green)}"
|
38
|
+
|
39
|
+
archive.things_create(file: file).setup
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.debug
|
44
|
+
ENV['DEBUG'] = if ENV['DEBUG']
|
45
|
+
puts "Debug #{'Off'.colorize(:red)}"
|
46
|
+
nil
|
47
|
+
else
|
48
|
+
puts "Debug #{'On'.colorize(:green)}"
|
49
|
+
'true'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.uptime
|
54
|
+
Shell::Cat.default ['uptime']
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.hostname
|
58
|
+
Shell::Cat.default ['hostname']
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.uname
|
62
|
+
Shell::Cat.default ['uname']
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.history_clear
|
66
|
+
File.write(GreenHat::Cli.history_file, "\n")
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.history
|
70
|
+
File.read(GreenHat::Cli.history_file).split("\n").each_with_index do |line, i|
|
71
|
+
puts "#{i.to_s.ljust(3).colorize(:magenta)} #{line}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.ls
|
76
|
+
GreenHat::Cli.help
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.ll
|
80
|
+
GreenHat::Cli.help
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.about
|
84
|
+
puts "#{'GreenHat'.colorize(:green)}: #{GreenHat::VERSION.colorize(:blue)}"
|
85
|
+
puts ' - https://gitlab.com/gitlab-com/support/toolbox/greenhat'.colorize(:cyan)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Load All Sub Files
|
91
|
+
require_all "#{File.dirname(__FILE__)}/accessors"
|
92
|
+
require_all "#{File.dirname(__FILE__)}/shell"
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module GreenHat
|
2
|
+
# CLI Helper
|
3
|
+
module Shell
|
4
|
+
# Common File Reader File
|
5
|
+
module Cat
|
6
|
+
# rubocop:disable Metrics/MethodLength
|
7
|
+
def self.help
|
8
|
+
puts "\u2500".colorize(:cyan) * 20
|
9
|
+
puts "#{'Cat'.colorize(:yellow)} All the files"
|
10
|
+
puts "\u2500".colorize(:cyan) * 20
|
11
|
+
puts 'Print raw file by just entering the file name'
|
12
|
+
puts
|
13
|
+
|
14
|
+
puts 'Common Options'.colorize(:blue)
|
15
|
+
puts ' --raw'.colorize(:green)
|
16
|
+
puts ' Do not use less/paging'
|
17
|
+
puts
|
18
|
+
puts ' --archive'.colorize(:green)
|
19
|
+
puts ' Limit to specific archvie name (inclusive). Matching SOS tar.gz name'
|
20
|
+
puts ' Ex: --archive=dev-gitlab_20210622154626, --archive=202106,202107'
|
21
|
+
puts ' cat mount --archive=dev-gitlab_202106221546'
|
22
|
+
puts
|
23
|
+
|
24
|
+
puts 'Commands'.colorize(:blue)
|
25
|
+
puts 'ls'.colorize(:green)
|
26
|
+
puts ' List available files'
|
27
|
+
puts ' Options'
|
28
|
+
puts ' -a, --all, show all files including source'
|
29
|
+
puts
|
30
|
+
|
31
|
+
puts '<file names+>'.colorize(:green)
|
32
|
+
puts ' Print any file names'
|
33
|
+
puts ' Ex: `free_m`'
|
34
|
+
puts ' Ex: `ps mount --raw`'
|
35
|
+
puts
|
36
|
+
|
37
|
+
puts "#{'show'.colorize(:green)} <file names>"
|
38
|
+
puts ' Attempt to print formatted output'
|
39
|
+
puts ' Ex: show `free_m`'
|
40
|
+
|
41
|
+
puts '--archive'.colorize(:green)
|
42
|
+
puts ' Limit to specific archvie name (inclusive). Matching SOS tar.gz name'
|
43
|
+
puts ' Ex: --archive=dev-gitlab_20210622154626, --archive=202106,202107'
|
44
|
+
puts
|
45
|
+
end
|
46
|
+
# rubocop:enable Metrics/MethodLength
|
47
|
+
|
48
|
+
# ========================================================================
|
49
|
+
# Default
|
50
|
+
# ========================================================================
|
51
|
+
def self.default(file_list)
|
52
|
+
# Extract Args
|
53
|
+
file_list, _opts, args = ShellHelper.param_parse(file_list)
|
54
|
+
|
55
|
+
# Prepare Log List
|
56
|
+
file_list = ShellHelper.prepare_list(file_list, Thing.all)
|
57
|
+
|
58
|
+
# Convert to Things
|
59
|
+
files = ShellHelper.find_things(file_list, args)
|
60
|
+
|
61
|
+
results = ShellHelper.file_process(files) do |file|
|
62
|
+
[
|
63
|
+
file.friendly_name,
|
64
|
+
file.output(false),
|
65
|
+
"\n"
|
66
|
+
]
|
67
|
+
end
|
68
|
+
|
69
|
+
ShellHelper.show(results.flatten, args)
|
70
|
+
end
|
71
|
+
|
72
|
+
# ========================================================================
|
73
|
+
# Show Attempted Formatting
|
74
|
+
# ========================================================================
|
75
|
+
def self.show(file_list)
|
76
|
+
# Extract Args
|
77
|
+
file_list, _opts, args = ShellHelper.param_parse(file_list)
|
78
|
+
|
79
|
+
# Prepare Log List
|
80
|
+
file_list = ShellHelper.prepare_list(file_list, Thing.all)
|
81
|
+
|
82
|
+
# Convert to Things
|
83
|
+
files = ShellHelper.find_things(file_list, args)
|
84
|
+
|
85
|
+
results = ShellHelper.file_process(files) do |file|
|
86
|
+
[
|
87
|
+
file.friendly_name,
|
88
|
+
file.output(false),
|
89
|
+
"\n"
|
90
|
+
]
|
91
|
+
end
|
92
|
+
|
93
|
+
ShellHelper.show(results.flatten, args)
|
94
|
+
end
|
95
|
+
|
96
|
+
# List Files Helpers
|
97
|
+
def self.list(args = [])
|
98
|
+
all = false
|
99
|
+
all = true if args.include?('-a') || args.include?('--all')
|
100
|
+
|
101
|
+
files = Thing.all
|
102
|
+
|
103
|
+
# Sort
|
104
|
+
files.sort_by!(&:name)
|
105
|
+
|
106
|
+
# Short & Uniq
|
107
|
+
files.uniq!(&:name) unless all
|
108
|
+
|
109
|
+
# Print
|
110
|
+
files.each do |log|
|
111
|
+
if all
|
112
|
+
puts "- #{log.friendly_name}"
|
113
|
+
else
|
114
|
+
puts "- #{log.name.colorize(:yellow)}"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def self.ls(args = [])
|
120
|
+
list(args)
|
121
|
+
end
|
122
|
+
# ------------------------------------------------------------------------
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module GreenHat
|
2
|
+
# CLI Helper
|
3
|
+
module Shell
|
4
|
+
# Logs
|
5
|
+
module Disk
|
6
|
+
# Alias
|
7
|
+
def self.ls
|
8
|
+
Cli.help
|
9
|
+
end
|
10
|
+
|
11
|
+
# Easy Show All
|
12
|
+
def self.df
|
13
|
+
ShellHelper.file_output GreenHat::Disk.df
|
14
|
+
end
|
15
|
+
|
16
|
+
# rubocop:disable Metrics/MethodLength,Metrics/BlockLength
|
17
|
+
def self.free
|
18
|
+
GreenHat::Disk.df.each do |file|
|
19
|
+
# Reject TMPFS
|
20
|
+
puts file.friendly_name
|
21
|
+
disks = file.data.sort_by { |x| x.use.to_i }.reverse.reject { |x| x.filesystem.include? 'tmpfs' }
|
22
|
+
|
23
|
+
# pad_mount = GreenHat::Disk.max_padding(disks, :mounted_on)
|
24
|
+
# pad_size = GreenHat::Disk.max_padding(disks, :size)
|
25
|
+
# pad_used = GreenHat::Disk.max_padding(disks, :used)
|
26
|
+
# pad_avail = GreenHat::Disk.max_padding(disks, :avail)
|
27
|
+
|
28
|
+
pad_mount, pad_size, pad_used, pad_avail = GreenHat::Disk.padding(disks)
|
29
|
+
|
30
|
+
# Headers
|
31
|
+
puts [
|
32
|
+
'Mount'.ljust(pad_mount).colorize(:blue),
|
33
|
+
'Size'.ljust(pad_size).colorize(:magenta),
|
34
|
+
'Used'.ljust(pad_used).colorize(:cyan),
|
35
|
+
'Avail'.ljust(pad_avail).colorize(:white),
|
36
|
+
'% Use'.ljust(pad_avail).colorize(:green)
|
37
|
+
].join
|
38
|
+
|
39
|
+
# Table Summary
|
40
|
+
disks.map do |disk|
|
41
|
+
# Pretty Disk Use
|
42
|
+
use = [
|
43
|
+
disk.use.rjust(5).ljust(5).colorize(:green),
|
44
|
+
' ['.colorize(:blue),
|
45
|
+
('=' * (disk.use.to_i / 2)).colorize(:green),
|
46
|
+
' ' * (50 - disk.use.to_i / 2),
|
47
|
+
']'.colorize(:blue)
|
48
|
+
].join
|
49
|
+
|
50
|
+
# Whole Thing
|
51
|
+
puts [
|
52
|
+
disk.mounted_on.ljust(pad_mount).colorize(:blue),
|
53
|
+
disk[:size].to_s.ljust(pad_size).colorize(:magenta),
|
54
|
+
disk.used.to_s.ljust(pad_used).colorize(:cyan),
|
55
|
+
disk.avail.to_s.ljust(pad_avail).colorize(:white),
|
56
|
+
use
|
57
|
+
].join
|
58
|
+
end
|
59
|
+
|
60
|
+
# File End Loop / Break
|
61
|
+
puts
|
62
|
+
end
|
63
|
+
end
|
64
|
+
# rubocop:enable Metrics/MethodLength,Metrics/BlockLength
|
65
|
+
# ------------------------------------------------------------------------
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|