greenhat 0.5.1 → 0.6.1

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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/lib/greenhat/archive.rb +2 -0
  3. data/lib/greenhat/cli.rb +12 -2
  4. data/lib/greenhat/entrypoint.rb +36 -33
  5. data/lib/greenhat/logbot.rb +1 -1
  6. data/lib/greenhat/paper/flag_helper.rb +18 -0
  7. data/lib/greenhat/paper/paper_helper.rb +118 -0
  8. data/lib/greenhat/paper.rb +34 -0
  9. data/lib/greenhat/reports/builder.rb +98 -0
  10. data/lib/greenhat/reports/helpers.rb +101 -0
  11. data/lib/greenhat/reports/internal_methods.rb +156 -0
  12. data/lib/greenhat/reports/reports/errors.rb +49 -0
  13. data/lib/greenhat/reports/reports/faststats.rb +42 -0
  14. data/lib/greenhat/reports/reports/full.rb +143 -0
  15. data/lib/greenhat/reports/runner.rb +58 -0
  16. data/lib/greenhat/reports/shared.rb +37 -0
  17. data/lib/greenhat/reports/shell_helper.rb +34 -0
  18. data/lib/greenhat/reports.rb +79 -0
  19. data/lib/greenhat/settings.rb +6 -1
  20. data/lib/greenhat/shell/args.rb +9 -9
  21. data/lib/greenhat/shell/color_string.rb +1 -1
  22. data/lib/greenhat/shell/faststats.rb +24 -5
  23. data/lib/greenhat/shell/field_helper.rb +1 -1
  24. data/lib/greenhat/shell/filter_help.rb +36 -189
  25. data/lib/greenhat/shell/log.rb +18 -14
  26. data/lib/greenhat/shell/markdown.rb +355 -352
  27. data/lib/greenhat/shell/process.rb +11 -5
  28. data/lib/greenhat/shell/query.rb +183 -27
  29. data/lib/greenhat/shell/report.rb +415 -412
  30. data/lib/greenhat/shell/reports.rb +41 -0
  31. data/lib/greenhat/shell/shell_helper.rb +92 -34
  32. data/lib/greenhat/shell.rb +13 -2
  33. data/lib/greenhat/thing/file_types.rb +14 -0
  34. data/lib/greenhat/thing/formatters/clean_raw.rb +1 -1
  35. data/lib/greenhat/thing/formatters/runner_log.rb +70 -0
  36. data/lib/greenhat/thing/formatters/time_json.rb +12 -1
  37. data/lib/greenhat/thing/kind.rb +1 -1
  38. data/lib/greenhat/version.rb +1 -1
  39. data/lib/greenhat.rb +6 -8
  40. metadata +31 -4
  41. data/lib/greenhat/pry_helpers.rb +0 -51
  42. data/lib/greenhat/thing/super_log.rb +0 -1
@@ -0,0 +1,41 @@
1
+ # Reporting
2
+ require 'greenhat/reports/shared' # Methods for Shell and Builder
3
+ require 'greenhat/reports/internal_methods' # Class / Execution Only
4
+ require 'greenhat/reports/runner' # Class execution
5
+ require 'greenhat/reports/builder' # CLI Reports
6
+ require 'greenhat/reports/shell_helper'
7
+
8
+ module GreenHat
9
+ # CLI Helper
10
+ module Shell
11
+ # Logs
12
+ module Reports
13
+ # Easy Show All
14
+ def self.ls(raw = [])
15
+ filter, _flags, _args = Args.parse(raw)
16
+
17
+ list = GreenHat::ShellHelper::Reports.list
18
+ list.select! { |x| x.include? filter.first } unless filter.blank?
19
+
20
+ list.each do |x|
21
+ puts "- #{File.basename(x, '.rb').pastel(:yellow)}"
22
+ end
23
+ end
24
+
25
+ def self.default(raw = [])
26
+ list, flags, args = Args.parse(raw)
27
+
28
+ # Collect Reporst to Run
29
+ run_list = GreenHat::ShellHelper::Reports.list.select do |entry|
30
+ list.include? File.basename(entry, '.rb')
31
+ end
32
+
33
+ run_list.uniq!
34
+
35
+ run_list.each do |file|
36
+ GreenHat::ShellHelper::Reports.run(file: file, args: args, flags: flags)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -48,35 +48,64 @@ module GreenHat
48
48
 
49
49
  # Check if content needs to paged, or if auto_height is off
50
50
  if Page.skip?(flags, data)
51
- puts data.map { |entry| entry_show(flags, entry) }.compact.join("\n")
51
+ create_ledger(data, flags).each { |entry| puts entry.render }
52
52
  return true
53
53
  end
54
54
 
55
- # Default Pager
55
+ # Create Jobs
56
+ # Generate List of Formatted Output
57
+ ledger = create_ledger(data, flags)
58
+
59
+ # Start Thread
60
+ # TODO: Confirm / Test or Remove
61
+ unless flags.no_paper_thread
62
+ thread = Thread.new do
63
+ pending = ledger.clone
64
+ loop do
65
+ pending = pending.reject(&:done)
66
+ break if pending.empty?
67
+
68
+ pending.first.async
69
+ end
70
+ end
71
+ end
72
+
56
73
  TTY::Pager.page do |pager|
57
- data.each do |entry|
58
- output = "\n#{entry_show(flags, entry)}"
74
+ ledger.each do |paper|
75
+ # New Line is only needed on pager.write
76
+ pager.write "#{paper.render}\n"
77
+ end
78
+ end
59
79
 
60
- # output += "\n" if flags[:table_style] == 'basic'
80
+ # Terminate
81
+ thread.kill unless flags.no_paper_thread
61
82
 
62
- # Breaks any intentional spaces
63
- # next if output.blank?
83
+ # -----------------
84
+ end
64
85
 
65
- pager.write(output) # write line to the pager
66
- end
86
+ # Collect Class Objects for output
87
+ def self.create_ledger(data, flags)
88
+ data.map do |x|
89
+ Paper.new(data: x, flags: flags)
67
90
  end
68
91
  end
69
92
 
93
+ def self.puts(text = '')
94
+ $stdout.puts text
95
+ end
96
+
70
97
  # Entry Shower / Top Level
71
98
  def self.entry_show(flags, entry, key = nil)
72
99
  LogBot.debug('Entry Show', entry.class) if ENV['DEBUG']
73
100
  case entry
74
101
  when Hash then render_table(entry, flags)
75
- when Float, Integer, Array
102
+ when Float, Integer
76
103
  format_table_entry(flags, entry, key)
77
104
  # Ignore Special Formatting for Strings / Usually already formatted
78
105
  when String
79
106
  entry
107
+ when Array
108
+ render_array_table(entry, flags)
80
109
  else
81
110
  LogBot.warn('Shell Show', "Unknown #{entry.class}")
82
111
  nil
@@ -117,6 +146,22 @@ module GreenHat
117
146
  end
118
147
  end
119
148
 
149
+ def self.render_array_table(entry, flags)
150
+ table_style = flags[:table_style]&.to_sym || :unicode
151
+ header, rows = entry
152
+ table = TTY::Table.new(header: header, rows: rows)
153
+
154
+ LogBot.debug('Rendering Entries') if ENV['DEBUG']
155
+ output = table.render(table_style, padding: [0, 1, 0, 1], multiline: true) do |renderer|
156
+ renderer.border.style = :cyan
157
+ end
158
+
159
+ # Line breaks for basic tables
160
+ output += "\n" if flags[:table_style] == 'basic'
161
+
162
+ output
163
+ end
164
+
120
165
  # Print the Table in a Nice way
121
166
  def self.render_table(entry, flags)
122
167
  entry = entry.to_h { |k, v| [k, format_table_entry(flags, v, k)] }
@@ -135,9 +180,6 @@ module GreenHat
135
180
  output += "\n" if flags[:table_style] == 'basic'
136
181
 
137
182
  output
138
-
139
- # LogBot.debug('Finish Render Table') if ENV['DEBUG']
140
- # Fall Back to Amazing Inspect
141
183
  rescue StandardError => e
142
184
  if ENV['DEBUG']
143
185
  LogBot.warn('Table', message: e.message)
@@ -183,28 +225,42 @@ module GreenHat
183
225
 
184
226
  # Total Count Helper
185
227
  def self.total_count(results, flags)
186
- results.map do |k, v|
187
- puts k
188
- # puts "Total: #{v.count.to_s.pastel(:blue)}"
189
- # puts "Time Covered: #{calculate_duration(v).pastel(:cyan)}"
190
-
191
- output = {}
192
- output[:total] = v.count
193
- output[:duration] = Query.calculate_duration(v)
194
-
195
- # Sort / Get first and Last
196
- list = v.select(&:time).map(&:time)
197
- unless list.blank?
198
- output[:start] = list.first
199
- output[:end] = list.last
200
- end
228
+ # Support Combine Helper
229
+ # TODO I Believe this should be removed now
230
+ # total_count_hash(results, flags) if results.instance_of? Hash
201
231
 
202
- puts render_table(output, flags)
232
+ total_count_array(results, flags) if results.instance_of? Array
233
+ end
203
234
 
204
- puts
235
+ # Hash Iteration
236
+ def self.total_count_hash(results, flags)
237
+ results.flat_map do |k, values|
238
+ [k, total_count_array(values, flags)]
205
239
  end
206
240
  end
207
241
 
242
+ # List Calculation
243
+ def self.total_count_array(results, flags)
244
+ # Option to only return the count
245
+ return results.count if flags[:total] == 'simple'
246
+
247
+ output = {}
248
+ output[:total] = results.count
249
+ output[:duration] = Query.calculate_duration(results)
250
+
251
+ # Sort / Get first and Last
252
+ list = results.select(&:time).map(&:time)
253
+ unless list.blank?
254
+ output[:start] = list.first
255
+ output[:end] = list.last
256
+ end
257
+
258
+ # Hide empty results
259
+ output.reject! { |_k, v| v.blank? }
260
+
261
+ render_table(output, flags)
262
+ end
263
+
208
264
  # Table Printer Helper
209
265
  def self.fields_print(results)
210
266
  results.each do |k, v|
@@ -239,7 +295,7 @@ module GreenHat
239
295
  file_list = prepare_list(file_list, base_list)
240
296
 
241
297
  # Convert to Things
242
- find_things(file_list, flags)
298
+ find_things(file_list, flags, base_list)
243
299
  end
244
300
 
245
301
  # Total Log List Manipulator
@@ -263,13 +319,15 @@ module GreenHat
263
319
  end
264
320
 
265
321
  # Shortcut find things
266
- def self.find_things(files, flags = {})
267
- things = files.uniq.flat_map do |file|
322
+ def self.find_things(file_list, flags = {}, base_list = nil)
323
+ base_list ||= Thing.all
324
+
325
+ things = file_list.uniq.flat_map do |file|
268
326
  # If Thing, Return Thing
269
327
  return file if file.instance_of?(Thing)
270
328
 
271
329
  if flags.fuzzy_file_match
272
- Thing.list.select { |x| x.name.include?(file) || x.type.include?(file) }
330
+ base_list.select { |x| x.name.include?(file) || x.type.include?(file) }
273
331
  else
274
332
  Thing.where name: file
275
333
  end
@@ -18,6 +18,12 @@ module GreenHat
18
18
  GreenHat::Web.toggle
19
19
  end
20
20
 
21
+ # Append Log Location so follow up commands are executed there
22
+ def self.default(raw_list = [])
23
+ Cli.move_shell Shell::Log
24
+ Log.default(raw_list)
25
+ end
26
+
21
27
  def self.df
22
28
  Disk.df
23
29
  end
@@ -101,8 +107,13 @@ module GreenHat
101
107
  end
102
108
  end
103
109
 
104
- def self.ls
105
- GreenHat::Cli.help(false)
110
+ def self.ls(raw = [])
111
+ if raw.empty?
112
+ GreenHat::Cli.help(false)
113
+ else
114
+ Cli.move_shell Shell::Log
115
+ Log.ls(raw)
116
+ end
106
117
  end
107
118
 
108
119
  def self.ll
@@ -65,6 +65,13 @@ module GreenHat
65
65
  %r{log/syslog}
66
66
  ]
67
67
  },
68
+ 'gitlab-runner.log' => {
69
+ format: :runner_log,
70
+ log: true,
71
+ pattern: [
72
+ /gitlab-runner.log/
73
+ ]
74
+ },
68
75
  'etc/fstab' => {
69
76
  format: :clean_raw,
70
77
  pattern: [
@@ -124,6 +131,13 @@ module GreenHat
124
131
  %r{consul/current}
125
132
  ]
126
133
  },
134
+ 'gitlab-kas/current' => {
135
+ format: :time_space,
136
+ log: true,
137
+ pattern: [
138
+ %r{gitlab-kas/current}
139
+ ]
140
+ },
127
141
  'sentinel/current' => {
128
142
  format: :time_space,
129
143
  log: true,
@@ -4,7 +4,7 @@ module GreenHat
4
4
  module Formatters
5
5
  # Remove Comments / Empty Lines
6
6
  def format_clean_raw
7
- staging = raw.clone
7
+ staging = raw_full.clone
8
8
 
9
9
  # Empty
10
10
  staging.reject!(&:empty?)
@@ -0,0 +1,70 @@
1
+ # Top
2
+ module GreenHat
3
+ # Log
4
+ module Formatters
5
+ # Attempt to make runner logs easier to parse
6
+ def format_runner_log
7
+ self.result = raw.map do |row|
8
+ next if row.empty? || row == "\n"
9
+ next if row.include? '-- Logs begin at' # Skip Header
10
+
11
+ process_runner_log_row(row)
12
+ end
13
+
14
+ result.compact!
15
+ end
16
+
17
+ # Split / Parse Time
18
+ # TODO: Better sys log parsing? Cannot find ready-made regex/ruby parser
19
+ def process_runner_log_row(row)
20
+ month, day, time, device, service, message = row.split(' ', 6)
21
+ service&.gsub!(':', '')
22
+ pid = service&.match(/\[(.*?)\]/)&.captures&.first
23
+
24
+ entry = {
25
+ time: format_time_parse("#{month} #{day} #{time}"),
26
+ device: device,
27
+ service: service,
28
+ message: message,
29
+ pid: pid,
30
+ row: row # Insert full row for different timestamp formats
31
+ }
32
+
33
+ # Remove Empty Keys
34
+ entry.compact!
35
+
36
+ # Shellwords split - Skip Blank
37
+ process_runner_row_message(message, entry) unless message.blank?
38
+
39
+ entry
40
+
41
+ # Return everything incase of error
42
+ rescue StandardError => e
43
+ LogBot.warn('Runner Log Parse', e.message)
44
+ {
45
+ message: row
46
+ }
47
+ end
48
+
49
+ def process_runner_row_message(message, entry)
50
+ # Insert Keywords / Format Time if Possible
51
+ Shellwords.split(message).select { |x| x.include? '=' }.each do |x|
52
+ key, value = x.split('=', 2)
53
+
54
+ # Don't overwrite stuff
55
+ case key
56
+ when 'time'
57
+ entry["#{key}-msg".to_sym] = format_time_parse value
58
+ when 'message', :message
59
+ entry["#{key}-msg".to_sym] = value
60
+ else
61
+ entry[key.to_sym] = value
62
+ end
63
+ end
64
+ rescue StandardError
65
+ # LogBot.debug('Runner Log Parse', e.message)
66
+ nil
67
+ end
68
+ # --
69
+ end
70
+ end
@@ -10,10 +10,21 @@ module GreenHat
10
10
  self.result = raw.map do |row|
11
11
  time, msg = row.split(' ', 2)
12
12
 
13
- result = Oj.load msg
13
+ # Be mo fault tolerant
14
+ result = begin
15
+ Oj.load msg
16
+ rescue StandardError
17
+ { msg: msg }
18
+ end
19
+
14
20
  result.time = time
15
21
 
16
22
  result
23
+ rescue StandardError => e
24
+ # TODO: Background Logger?
25
+ e.message
26
+ LogBot.warn('Time JSON Parse', e.message)
27
+ next
17
28
  end
18
29
  end
19
30
  # ==========================================================================
@@ -84,7 +84,7 @@ module GreenHat
84
84
  option = prompt.select('Wat is this?', prompt_list.keys.sort_by(&:length), filter: true)
85
85
 
86
86
  # Store for later
87
- ThingHistory.add(name, option)
87
+ ThingHistory.add(name.to_sym, option)
88
88
 
89
89
  self.type = option
90
90
  end
@@ -1,3 +1,3 @@
1
1
  module GreenHat
2
- VERSION = '0.5.1'.freeze
2
+ VERSION = '0.6.1'.freeze
3
3
  end
data/lib/greenhat.rb CHANGED
@@ -24,6 +24,7 @@ require 'tty-table'
24
24
  require 'tty-which'
25
25
  require 'warning'
26
26
  require 'ruby_native_statistics'
27
+ require 'gitlab_chronic_duration'
27
28
 
28
29
  # Custom Gem
29
30
  require 'teron'
@@ -54,8 +55,12 @@ require 'greenhat/logbot'
54
55
  require 'greenhat/settings'
55
56
  require 'greenhat/color'
56
57
 
58
+ # Printer Helpers
59
+ require 'greenhat/paper/paper_helper'
60
+ require 'greenhat/paper/flag_helper'
61
+ require 'greenhat/paper'
62
+
57
63
  # Formatters - Loads Required Files Automatically
58
- require 'greenhat/thing/super_log'
59
64
  require 'greenhat/thing/file_types'
60
65
  require 'greenhat/thing/kind'
61
66
  require 'greenhat/thing/history'
@@ -68,14 +73,7 @@ require 'greenhat/thing'
68
73
  # Shell - Loads Required Files Automatically
69
74
  require 'greenhat/shell'
70
75
 
71
- # TODO: Confirm
72
- # require 'greenhat/host'
73
- # require 'greenhat/web'
74
-
75
- require 'greenhat/pry_helpers'
76
-
77
76
  ## TTY Shims
78
-
79
77
  require 'greenhat/tty/line'
80
78
  require 'greenhat/tty/reader'
81
79
  require 'greenhat/tty/custom_line'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: greenhat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Davin Walker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-17 00:00:00.000000000 Z
11
+ date: 2022-06-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: amazing_print
@@ -164,6 +164,20 @@ dependencies:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
166
  version: '2.7'
167
+ - !ruby/object:Gem::Dependency
168
+ name: gitlab_chronic_duration
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: 0.10.6
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: 0.10.6
167
181
  - !ruby/object:Gem::Dependency
168
182
  name: hash_dot
169
183
  requirement: !ruby/object:Gem::Requirement
@@ -454,7 +468,19 @@ files:
454
468
  - lib/greenhat/entrypoint.rb
455
469
  - lib/greenhat/host.rb
456
470
  - lib/greenhat/logbot.rb
457
- - lib/greenhat/pry_helpers.rb
471
+ - lib/greenhat/paper.rb
472
+ - lib/greenhat/paper/flag_helper.rb
473
+ - lib/greenhat/paper/paper_helper.rb
474
+ - lib/greenhat/reports.rb
475
+ - lib/greenhat/reports/builder.rb
476
+ - lib/greenhat/reports/helpers.rb
477
+ - lib/greenhat/reports/internal_methods.rb
478
+ - lib/greenhat/reports/reports/errors.rb
479
+ - lib/greenhat/reports/reports/faststats.rb
480
+ - lib/greenhat/reports/reports/full.rb
481
+ - lib/greenhat/reports/runner.rb
482
+ - lib/greenhat/reports/shared.rb
483
+ - lib/greenhat/reports/shell_helper.rb
458
484
  - lib/greenhat/settings.rb
459
485
  - lib/greenhat/shell.rb
460
486
  - lib/greenhat/shell/args.rb
@@ -478,6 +504,7 @@ files:
478
504
  - lib/greenhat/shell/process.rb
479
505
  - lib/greenhat/shell/query.rb
480
506
  - lib/greenhat/shell/report.rb
507
+ - lib/greenhat/shell/reports.rb
481
508
  - lib/greenhat/shell/shell_helper.rb
482
509
  - lib/greenhat/thing.rb
483
510
  - lib/greenhat/thing/file_types.rb
@@ -499,6 +526,7 @@ files:
499
526
  - lib/greenhat/thing/formatters/nginx.rb
500
527
  - lib/greenhat/thing/formatters/raw.rb
501
528
  - lib/greenhat/thing/formatters/registry.rb
529
+ - lib/greenhat/thing/formatters/runner_log.rb
502
530
  - lib/greenhat/thing/formatters/shellwords.rb
503
531
  - lib/greenhat/thing/formatters/syslog.rb
504
532
  - lib/greenhat/thing/formatters/table.rb
@@ -510,7 +538,6 @@ files:
510
538
  - lib/greenhat/thing/info_format.rb
511
539
  - lib/greenhat/thing/kind.rb
512
540
  - lib/greenhat/thing/spinner.rb
513
- - lib/greenhat/thing/super_log.rb
514
541
  - lib/greenhat/tty/columns.rb
515
542
  - lib/greenhat/tty/custom_line.rb
516
543
  - lib/greenhat/tty/line.rb
@@ -1,51 +0,0 @@
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
@@ -1 +0,0 @@
1
-