greenhat 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/greenhat/accessors/disk.rb +13 -13
- data/lib/greenhat/accessors/gitlab.rb +75 -0
- data/lib/greenhat/accessors/memory.rb +10 -10
- data/lib/greenhat/accessors/process.rb +4 -0
- data/lib/greenhat/cli.rb +127 -52
- data/lib/greenhat/color.rb +27 -0
- data/lib/greenhat/logbot.rb +9 -9
- data/lib/greenhat/settings.rb +27 -7
- data/lib/greenhat/shell/args.rb +146 -0
- data/lib/greenhat/shell/cat.rb +25 -73
- data/lib/greenhat/shell/color_string.rb +8 -8
- data/lib/greenhat/shell/disk.rb +31 -4
- data/lib/greenhat/shell/faststats.rb +79 -59
- data/lib/greenhat/shell/{filter.rb → filter_help.rb} +48 -33
- data/lib/greenhat/shell/gitlab.rb +61 -2
- data/lib/greenhat/shell/help.rb +96 -15
- data/lib/greenhat/shell/list.rb +46 -0
- data/lib/greenhat/shell/log.rb +77 -104
- data/lib/greenhat/shell/page.rb +11 -5
- data/lib/greenhat/shell/process.rb +29 -17
- data/lib/greenhat/shell/report.rb +27 -43
- data/lib/greenhat/shell/{helper.rb → shell_helper.rb} +204 -187
- data/lib/greenhat/shell.rb +23 -9
- data/lib/greenhat/thing/file_types.rb +20 -1
- data/lib/greenhat/thing/formatters/json_shellwords.rb +0 -3
- data/lib/greenhat/thing/helpers.rb +4 -4
- data/lib/greenhat/thing/kind.rb +9 -2
- data/lib/greenhat/thing/spinner.rb +3 -3
- data/lib/greenhat/thing.rb +3 -3
- data/lib/greenhat/tty/columns.rb +4 -0
- data/lib/greenhat/version.rb +1 -1
- data/lib/greenhat.rb +14 -14
- metadata +22 -18
@@ -0,0 +1,27 @@
|
|
1
|
+
# Top level namespace
|
2
|
+
module GreenHat
|
3
|
+
# Replace Colorize with Pastel Monkey Patch String Shim
|
4
|
+
# https://github.com/piotrmurach/pastel#features
|
5
|
+
|
6
|
+
# Looping in GreenHat to allow disabling of Color
|
7
|
+
module Color
|
8
|
+
def self.pastel
|
9
|
+
@pastel ||= Pastel.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.decorate(args)
|
13
|
+
Settings.color? ? pastel.decorate(*args) : args.first
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Monkey Patch
|
19
|
+
class String
|
20
|
+
def pastel(*args)
|
21
|
+
GreenHat::Color.decorate(args.unshift(self))
|
22
|
+
end
|
23
|
+
|
24
|
+
def unpastel
|
25
|
+
GreenHat::Color.pastel.strip self
|
26
|
+
end
|
27
|
+
end
|
data/lib/greenhat/logbot.rb
CHANGED
@@ -6,11 +6,11 @@ module LogBot
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def self.output(name, message, level, duration = nil)
|
9
|
-
time = Time.now.to_s.
|
9
|
+
time = Time.now.to_s.pastel(:bright_black)
|
10
10
|
output = time
|
11
11
|
output += " #{color_level(level)}"
|
12
|
-
output += " - #{name.to_s.
|
13
|
-
output += "(#{duration.round(2)}) ".
|
12
|
+
output += " - #{name.to_s.pastel(:bright_blue)} "
|
13
|
+
output += "(#{duration.round(2)}) ".pastel(:magenta) if duration
|
14
14
|
|
15
15
|
output += ' '
|
16
16
|
if message
|
@@ -21,21 +21,21 @@ module LogBot
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
puts output unless ENV['TESTING']
|
24
|
+
puts output unless ENV['TESTING'] || GreenHat::Cli.quiet
|
25
25
|
end
|
26
26
|
|
27
27
|
def self.color_level(level)
|
28
28
|
case level
|
29
29
|
when :debug
|
30
|
-
level.to_s.upcase.
|
30
|
+
level.to_s.upcase.pastel(:bright_cyan)
|
31
31
|
when :info
|
32
|
-
level.to_s.upcase.
|
32
|
+
level.to_s.upcase.pastel(:cyan)
|
33
33
|
when :warn
|
34
|
-
level.to_s.upcase.
|
34
|
+
level.to_s.upcase.pastel(:yellow)
|
35
35
|
when :error
|
36
|
-
level.to_s.upcase.
|
36
|
+
level.to_s.upcase.pastel(:bright_red)
|
37
37
|
when :fatal
|
38
|
-
level.to_s.upcase.
|
38
|
+
level.to_s.upcase.pastel(:red)
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
data/lib/greenhat/settings.rb
CHANGED
@@ -5,14 +5,25 @@ module GreenHat
|
|
5
5
|
def self.settings
|
6
6
|
@settings ||= {
|
7
7
|
history: [],
|
8
|
+
assume_json: true,
|
9
|
+
fuzzy_file_match: true,
|
8
10
|
|
9
11
|
# round: [2],
|
10
12
|
# page: [:true] Automatic,
|
11
|
-
truncate:
|
12
|
-
|
13
|
+
truncate: TTY::Screen.width * 4,
|
14
|
+
color: true
|
13
15
|
}
|
14
16
|
end
|
15
17
|
|
18
|
+
def self.assume_json?
|
19
|
+
settings.assume_json
|
20
|
+
end
|
21
|
+
|
22
|
+
# Allow for future disabling of color output
|
23
|
+
def self.color?
|
24
|
+
settings.color
|
25
|
+
end
|
26
|
+
|
16
27
|
# Load User Settings and drop them into settings
|
17
28
|
def self.settings_load
|
18
29
|
return true unless File.exist?(settings_file)
|
@@ -26,12 +37,21 @@ module GreenHat
|
|
26
37
|
"#{dir}/settings.json"
|
27
38
|
end
|
28
39
|
|
29
|
-
# Set any Log Arguments that weren't set otherwise
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
40
|
+
# Set any Log Arguments that weren't set otherwise | Conditional assign applied on bool
|
41
|
+
# rubocop:disable Style/GuardClause
|
42
|
+
def self.default_log_flags(flags, skip_flags)
|
43
|
+
flags[:round] = settings.round if !(skip_flags.include?(:round) || flags.key?(:round)) && settings.round
|
44
|
+
|
45
|
+
flags[:page] = settings.page if !(skip_flags.include?(:page) || flags.key?(:page)) && settings.page
|
46
|
+
|
47
|
+
flags[:truncate] = settings.truncate unless skip_flags.include?(:truncate) || flags.key?(:truncate)
|
48
|
+
|
49
|
+
# Fuzzy File Match
|
50
|
+
unless skip_flags.include?(:fuzzy_file_match) || flags.key?(:fuzzy_file_match)
|
51
|
+
flags[:fuzzy_file_match] = settings.fuzzy_file_match
|
52
|
+
end
|
34
53
|
end
|
54
|
+
# rubocop:enable Style/GuardClause
|
35
55
|
|
36
56
|
def self.start
|
37
57
|
Dir.mkdir dir unless Dir.exist? dir
|
@@ -0,0 +1,146 @@
|
|
1
|
+
module GreenHat
|
2
|
+
# Module for Argument Parsing
|
3
|
+
# Possible Args
|
4
|
+
# --value=thing
|
5
|
+
# --value / Default => --value=thing
|
6
|
+
# --flag
|
7
|
+
# --slice=value,value2
|
8
|
+
# files
|
9
|
+
|
10
|
+
# Variable Breakdown
|
11
|
+
# Args:Array supplied or default values for entry looping action
|
12
|
+
# Flags:Hash Key/Value filter Actionables
|
13
|
+
# Files:Array/String are any non start `-` dash entries
|
14
|
+
module Args
|
15
|
+
def self.parse(raw, skip_flags = [])
|
16
|
+
# Don't affect original object / Better deep clone?
|
17
|
+
cmd = raw.clone
|
18
|
+
# cmd = Marshal.load(Marshal.dump(raw))
|
19
|
+
|
20
|
+
# Extract Files
|
21
|
+
files = cmd.grep_v(/^-+([^=]+)/)
|
22
|
+
|
23
|
+
# Collect and Naturalize Arguments
|
24
|
+
args = cmd.flat_map { |arg| arg_scan(arg) }
|
25
|
+
|
26
|
+
# Collect all Flags to Hash
|
27
|
+
flags = cmd.flat_map { |flag| flag_scan(flag) }.to_h
|
28
|
+
|
29
|
+
# Move Flags to Args
|
30
|
+
arg_to_flag(flags, args)
|
31
|
+
|
32
|
+
# Logic
|
33
|
+
# And / Or
|
34
|
+
flag_defaults(flags, skip_flags)
|
35
|
+
|
36
|
+
[files, flags, args]
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.flag_defaults(flags, skip_flags)
|
40
|
+
# Update other user defaults
|
41
|
+
Settings.default_log_flags(flags, skip_flags)
|
42
|
+
|
43
|
+
# FastStats / Don't set default flags
|
44
|
+
return if skip_flags.include? :logic
|
45
|
+
|
46
|
+
# Default Logic
|
47
|
+
if flags.key?(:or)
|
48
|
+
flags.logic = :any?
|
49
|
+
flags.delete(:or)
|
50
|
+
else
|
51
|
+
flags.logic = :all?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Move Valued Flags to arguments (--truncate=5)
|
56
|
+
def self.arg_to_flag(flags, args)
|
57
|
+
args.reject! do |arg|
|
58
|
+
# Entries specifically to move to Args
|
59
|
+
if arg_to_flag_list.include?(arg.field)
|
60
|
+
flags[arg.field] = arg.value
|
61
|
+
|
62
|
+
true
|
63
|
+
# Ignore Good Entries
|
64
|
+
else
|
65
|
+
false
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Flags Anything that isn't sent as a key/filter
|
71
|
+
def self.arg_to_flag_list
|
72
|
+
%i[
|
73
|
+
archive end except exists json limit pluck reverse round slice sort start stats
|
74
|
+
truncate uniq page
|
75
|
+
]
|
76
|
+
end
|
77
|
+
|
78
|
+
# Arg Scan (Split -- values into keys)
|
79
|
+
def self.arg_scan(arg)
|
80
|
+
arg.scan(/^-+([^=]+)=(.*)/).map do |field, value|
|
81
|
+
bang = false
|
82
|
+
if field.include? '!'
|
83
|
+
field.delete!('!')
|
84
|
+
bang = true
|
85
|
+
end
|
86
|
+
|
87
|
+
# Symbolize
|
88
|
+
field = field.to_sym
|
89
|
+
|
90
|
+
{
|
91
|
+
field: field,
|
92
|
+
value: arg_normalize(field, value),
|
93
|
+
bang: bang
|
94
|
+
}
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Collect All Flags
|
99
|
+
def self.flag_scan(arg)
|
100
|
+
arg.scan(/^-+([^=]+)$/).map do |field, _val|
|
101
|
+
# Symbolize
|
102
|
+
field = field.to_sym
|
103
|
+
|
104
|
+
[field, flag_arg_defaults(field)]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Naturlalize Values, Manipluate Special Values
|
109
|
+
def self.arg_normalize(field, value)
|
110
|
+
# Special Comma Params With Symbol
|
111
|
+
return value.split(',').map(&:to_sym) if arg_special_split.include?(field)
|
112
|
+
|
113
|
+
# Integer Arguments
|
114
|
+
return value.to_i if value.numeric?
|
115
|
+
|
116
|
+
# Other Field Manipulation
|
117
|
+
case field
|
118
|
+
when :page then value == 'true'
|
119
|
+
else
|
120
|
+
|
121
|
+
# Default Original
|
122
|
+
value
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# Arguments that Accept multiple options / Comma Delimted
|
127
|
+
def self.arg_special_split
|
128
|
+
%i[
|
129
|
+
slice except uniq pluck sort archive stats exists
|
130
|
+
]
|
131
|
+
end
|
132
|
+
|
133
|
+
# Arg Defaults
|
134
|
+
def self.flag_arg_defaults(field)
|
135
|
+
case field
|
136
|
+
when :round then 2
|
137
|
+
when :limit then (TTY::Screen.height / 3) - 3
|
138
|
+
when :truncate then TTY::Screen.width * 4
|
139
|
+
# when :page, :case, :exact then :true # Override Specials
|
140
|
+
when *arg_special_split then []
|
141
|
+
else
|
142
|
+
true
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
data/lib/greenhat/shell/cat.rb
CHANGED
@@ -3,60 +3,38 @@ module GreenHat
|
|
3
3
|
module Shell
|
4
4
|
# Common File Reader File
|
5
5
|
module Cat
|
6
|
-
# rubocop:disable Metrics/MethodLength
|
7
6
|
def self.help
|
8
|
-
puts "\u2500".
|
9
|
-
puts "#{'Cat'.
|
10
|
-
puts "\u2500".
|
7
|
+
puts "\u2500".pastel(:cyan) * 20
|
8
|
+
puts "#{'Cat'.pastel(:yellow)} All the files"
|
9
|
+
puts "\u2500".pastel(:cyan) * 20
|
11
10
|
puts 'Print raw file by just entering the file name'
|
12
11
|
puts
|
13
12
|
|
14
|
-
|
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
|
13
|
+
ShellHelper.common_opts
|
23
14
|
|
24
|
-
puts 'Commands'.
|
25
|
-
puts
|
26
|
-
puts ' List available files'
|
27
|
-
puts ' Options'
|
28
|
-
puts ' -a, --all, show all files including source'
|
29
|
-
puts
|
15
|
+
puts 'Commands'.pastel(:blue)
|
16
|
+
puts ShellHelper::List.help
|
30
17
|
|
31
|
-
puts '<file names+>'.
|
32
|
-
puts '
|
33
|
-
puts '
|
34
|
-
puts '
|
18
|
+
puts ' <file names+>'.pastel(:green)
|
19
|
+
puts ' Print any file names'
|
20
|
+
puts ' Ex: `free_m`'
|
21
|
+
puts ' Ex: `ps mount --raw`'
|
35
22
|
puts
|
36
23
|
|
37
|
-
puts "#{'show'.
|
38
|
-
puts '
|
39
|
-
puts '
|
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
|
24
|
+
puts " #{'show'.pastel(:green)} <file names>"
|
25
|
+
puts ' Attempt to print formatted output'
|
26
|
+
puts ' Ex: show `free_m`'
|
45
27
|
end
|
46
|
-
# rubocop:enable Metrics/MethodLength
|
47
28
|
|
48
29
|
# ========================================================================
|
49
30
|
# Default
|
50
31
|
# ========================================================================
|
51
|
-
def self.default(
|
32
|
+
def self.default(raw)
|
52
33
|
# Extract Args
|
53
|
-
|
54
|
-
|
55
|
-
# Prepare Log List
|
56
|
-
file_list = ShellHelper.prepare_list(file_list, Thing.all)
|
34
|
+
files_list, flags, _args = Args.parse(raw)
|
57
35
|
|
58
|
-
#
|
59
|
-
files = ShellHelper.
|
36
|
+
# Collect Files
|
37
|
+
files = ShellHelper.files(files_list, Thing.all, flags)
|
60
38
|
|
61
39
|
results = ShellHelper.file_process(files) do |file|
|
62
40
|
[
|
@@ -66,58 +44,32 @@ module GreenHat
|
|
66
44
|
]
|
67
45
|
end
|
68
46
|
|
69
|
-
ShellHelper.show(results.flatten,
|
47
|
+
ShellHelper.show(results.flatten, flags)
|
70
48
|
end
|
71
49
|
|
72
50
|
# ========================================================================
|
73
51
|
# Show Attempted Formatting
|
74
52
|
# ========================================================================
|
75
|
-
def self.show(
|
53
|
+
def self.show(raw)
|
76
54
|
# Extract Args
|
77
|
-
|
55
|
+
files_list, flags, _args = Args.parse(raw)
|
78
56
|
|
79
|
-
#
|
80
|
-
|
81
|
-
|
82
|
-
# Convert to Things
|
83
|
-
files = ShellHelper.find_things(file_list, args)
|
57
|
+
# Collect Files
|
58
|
+
files = ShellHelper.files(files_list, Thing.all, flags)
|
84
59
|
|
85
60
|
results = ShellHelper.file_process(files) do |file|
|
86
61
|
[
|
87
62
|
file.friendly_name,
|
88
|
-
file.
|
63
|
+
file.data,
|
89
64
|
"\n"
|
90
65
|
]
|
91
66
|
end
|
92
67
|
|
93
|
-
ShellHelper.show(results.flatten,
|
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
|
68
|
+
ShellHelper.show(results.flatten, flags)
|
117
69
|
end
|
118
70
|
|
119
71
|
def self.ls(args = [])
|
120
|
-
list(args)
|
72
|
+
ShellHelper::List.list(args, Thing.all)
|
121
73
|
end
|
122
74
|
# ------------------------------------------------------------------------
|
123
75
|
end
|
@@ -6,20 +6,20 @@ module GreenHat
|
|
6
6
|
LogBot.debug('Unknown Format', entry.class) if ENV['DEBUG'] && !entry.instance_of?(String)
|
7
7
|
|
8
8
|
# Other Helpful colorizers
|
9
|
-
if
|
10
|
-
|
9
|
+
if pastel?(key)
|
10
|
+
pastel(key, entry)
|
11
11
|
else
|
12
12
|
entry.to_s
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
16
|
# Add Color?
|
17
|
-
def self.
|
17
|
+
def self.pastel?(key)
|
18
18
|
[:severity].any? key
|
19
19
|
end
|
20
20
|
|
21
21
|
# General Key/Value Coloring
|
22
|
-
def self.
|
22
|
+
def self.pastel(key, value)
|
23
23
|
case key
|
24
24
|
when :severity then severity(value)
|
25
25
|
else
|
@@ -30,10 +30,10 @@ module GreenHat
|
|
30
30
|
|
31
31
|
def self.severity(value)
|
32
32
|
case value.to_s.downcase.to_sym
|
33
|
-
when :debug then value.
|
34
|
-
when :info then value.
|
35
|
-
when :warn then value.
|
36
|
-
when :fatal, :error then value.
|
33
|
+
when :debug then value.pastel(:blue)
|
34
|
+
when :info then value.pastel(:cyan)
|
35
|
+
when :warn then value.pastel(:yellow)
|
36
|
+
when :fatal, :error then value.pastel(:bright_red)
|
37
37
|
else
|
38
38
|
value.to_s
|
39
39
|
end
|