greenhat 0.3.3 → 0.4.0

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/bin/greenhat +1 -4
  3. data/lib/greenhat/accessors/disk.rb +42 -3
  4. data/lib/greenhat/accessors/gitlab.rb +30 -1
  5. data/lib/greenhat/accessors/memory.rb +1 -1
  6. data/lib/greenhat/archive.rb +19 -8
  7. data/lib/greenhat/cli.rb +24 -126
  8. data/lib/greenhat/entrypoint.rb +170 -0
  9. data/lib/greenhat/host.rb +25 -37
  10. data/lib/greenhat/settings.rb +6 -0
  11. data/lib/greenhat/shell/args.rb +22 -9
  12. data/lib/greenhat/shell/faststats.rb +23 -3
  13. data/lib/greenhat/shell/field_helper.rb +1 -1
  14. data/lib/greenhat/shell/filter_help.rb +232 -9
  15. data/lib/greenhat/shell/log.rb +153 -9
  16. data/lib/greenhat/shell/markdown.rb +352 -0
  17. data/lib/greenhat/shell/old_search_helper.rb +54 -0
  18. data/lib/greenhat/shell/page.rb +1 -1
  19. data/lib/greenhat/shell/pipe.rb +31 -0
  20. data/lib/greenhat/shell/platform.rb +28 -0
  21. data/lib/greenhat/shell/report.rb +106 -25
  22. data/lib/greenhat/shell/shell_helper.rb +115 -106
  23. data/lib/greenhat/shell.rb +10 -3
  24. data/lib/greenhat/thing/file_types.rb +136 -8
  25. data/lib/greenhat/thing/formatters/json.rb +4 -0
  26. data/lib/greenhat/thing/formatters/kube_json.rb +36 -0
  27. data/lib/greenhat/thing/formatters/kube_nginx.rb +48 -0
  28. data/lib/greenhat/thing/formatters/kube_webservice.rb +51 -0
  29. data/lib/greenhat/thing/formatters/nginx.rb +6 -2
  30. data/lib/greenhat/thing/formatters/registry.rb +47 -0
  31. data/lib/greenhat/thing/formatters/time_space.rb +0 -16
  32. data/lib/greenhat/thing/helpers.rb +12 -0
  33. data/lib/greenhat/thing/kind.rb +5 -0
  34. data/lib/greenhat/thing.rb +11 -0
  35. data/lib/greenhat/version.rb +1 -1
  36. data/lib/greenhat/views/api.slim +55 -0
  37. data/lib/greenhat/views/chart.slim +42 -0
  38. data/lib/greenhat/views/chart_template.slim +31 -0
  39. data/lib/greenhat/views/chartkick.js +21 -0
  40. data/lib/greenhat/views/css.slim +47 -0
  41. data/lib/greenhat/views/gitaly.slim +53 -0
  42. data/lib/greenhat/views/headers.slim +16 -0
  43. data/lib/greenhat/views/index-old.slim +51 -0
  44. data/lib/greenhat/views/index.slim +14 -14
  45. data/lib/greenhat/views/info.slim +17 -18
  46. data/lib/greenhat/views/production.slim +55 -0
  47. data/lib/greenhat/views/sidekiq.slim +55 -0
  48. data/lib/greenhat/views/time.slim +63 -0
  49. data/lib/greenhat/views/workhorse.slim +16 -0
  50. data/lib/greenhat/web/api.rb +94 -0
  51. data/lib/greenhat/web/chartkick_shim.rb +14 -0
  52. data/lib/greenhat/web/faststats.rb +44 -0
  53. data/lib/greenhat/web/gitaly.rb +65 -0
  54. data/lib/greenhat/web/helpers.rb +198 -0
  55. data/lib/greenhat/web/production.rb +104 -0
  56. data/lib/greenhat/web/sidekiq.rb +73 -0
  57. data/lib/greenhat/web/stats_helpers.rb +74 -0
  58. data/lib/greenhat/web/time.rb +36 -0
  59. data/lib/greenhat/web/workhorse.rb +43 -0
  60. data/lib/greenhat/web.rb +63 -19
  61. data/lib/greenhat.rb +2 -0
  62. metadata +78 -5
@@ -0,0 +1,28 @@
1
+ module GreenHat
2
+ # Common Helpers
3
+ module Platform
4
+ def self.platform
5
+ if @platform
6
+ @platform
7
+ else
8
+ require 'tty-platform'
9
+ @platform ||= TTY::Platform.new
10
+
11
+ end
12
+ end
13
+
14
+ def self.open(url = 'http://localhost:4567/chart/time')
15
+ cmd = if platform.linux? || platform.unix?
16
+ 'xdg-open'
17
+ elsif platform.mac?
18
+ 'open'
19
+ end
20
+
21
+ # platform.windows? # => false
22
+ # platform.unix? # => true
23
+ # platform.linux? # => false
24
+ # platform.mac? # => true
25
+ system("#{cmd} '#{url}'")
26
+ end
27
+ end
28
+ end
@@ -12,7 +12,11 @@ module GreenHat
12
12
  Archive.all
13
13
  end
14
14
 
15
- ShellHelper.show(archives.map(&:report).map(&:show).flatten, flags)
15
+ output = archives.map { |x| x.report(flags) }.map(&:show).flatten
16
+
17
+ flags[:page] = true if flags.full && !flags.raw
18
+
19
+ ShellHelper.show(output, flags)
16
20
  end
17
21
  end
18
22
  end
@@ -23,14 +27,16 @@ module GreenHat
23
27
  class Report
24
28
  include ActionView::Helpers::NumberHelper
25
29
 
26
- attr_accessor :archive, :host, :os_release, :selinux_status, :cpu, :uname,
30
+ attr_accessor :archive, :flags, :host, :os_release, :selinux_status, :cpu, :uname,
27
31
  :timedatectl, :uptime, :meminfo, :gitlab_manifest, :gitlab_status,
28
- :production_log, :api_log, :application_log, :sidekiq_log, :free_m, :disk_free
32
+ :production_log, :api_log, :sidekiq_log,
33
+ :exceptions_log, :gitaly_log, :free_m, :disk_free
29
34
 
30
35
  # Find Needed Files for Report
31
36
  # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
32
- def initialize(archive)
37
+ def initialize(archive, flags)
33
38
  self.archive = archive
39
+ self.flags = flags
34
40
  self.host = archive.things.find { |x| x.name == 'hostname' }
35
41
  self.os_release = archive.things.find { |x| x.name == 'etc/os-release' }
36
42
  self.selinux_status = archive.things.find { |x| x.name == 'sestatus' }
@@ -44,7 +50,8 @@ module GreenHat
44
50
  self.gitlab_status = archive.things.find { |x| x.name == 'gitlab_status' }
45
51
  self.production_log = archive.things.find { |x| x.name == 'gitlab-rails/production_json.log' }
46
52
  self.api_log = archive.things.find { |x| x.name == 'gitlab-rails/api_json.log' }
47
- self.application_log = archive.things.find { |x| x.name == 'gitlab-rails/application_json.log' }
53
+ self.exceptions_log = archive.things.find { |x| x.name == 'gitlab-rails/exceptions_json.log' }
54
+ self.gitaly_log = archive.things.find { |x| x.name == 'gitaly/current' }
48
55
  self.sidekiq_log = archive.things.find { |x| x.name == 'sidekiq/current' }
49
56
  self.disk_free = archive.things.find { |x| x.name == 'df_h' }
50
57
  end
@@ -84,11 +91,16 @@ module GreenHat
84
91
  output << 'GitLab'.pastel(:bright_yellow) if gitlab_manifest
85
92
  output << gitlab_version if gitlab_manifest
86
93
  output << gitlab_services if gitlab_status
87
- output << title('Errors') if production_log || api_log || application_log || sidekiq_log
94
+ output << title('Errors') if production_log || api_log || sidekiq_log
88
95
  output << production_errors if production_log
89
- output << api_errors if api_log
90
- output << application_errors if application_log
96
+ output << application_errors if archive.thing?('gitlab-rails/application_json.log')
91
97
  output << sidekiq_errors if sidekiq_log
98
+ output << api_errors if api_log
99
+ output << exception_errors if exceptions_log
100
+ output << gitaly_errors if gitaly_log
101
+ output << workhorse_errors if archive.thing?('gitlab-workhorse/current')
102
+
103
+ full(output) if flags.full
92
104
 
93
105
  # Final Space / Return
94
106
  output << ''
@@ -96,6 +108,52 @@ module GreenHat
96
108
  end
97
109
  # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
98
110
 
111
+ def full(output)
112
+ output << ''
113
+ output << 'FastStats Top'
114
+ Shell::Faststats.top(['--raw'], true).each { |x| output << x } # Page Row Helper
115
+ output << ''
116
+
117
+ output << 'FastStats Errors'
118
+ Shell::Faststats.errors(['--raw'], true).each { |x| output << x } # Page Row Helper
119
+ output << ''
120
+ end
121
+
122
+ def exception_errors
123
+ count = exceptions_log.data.count
124
+ color = count.zero? ? :green : :red
125
+
126
+ [
127
+ title(' Exception', :bright_red, 18),
128
+ count.to_s.pastel(color)
129
+ ].join
130
+ end
131
+
132
+ def workhorse_errors
133
+ results = ShellHelper.filter_internal([
134
+ 'gitlab-workhorse/current',
135
+ '--level=error',
136
+ "--archive=#{archive.name}"
137
+ ].join(' '))
138
+
139
+ color = results.count.zero? ? :green : :red
140
+
141
+ [
142
+ title(' Workhorse', :bright_red, 18),
143
+ results.count.to_s.pastel(color)
144
+ ].join
145
+ end
146
+
147
+ def gitaly_errors
148
+ count = gitaly_log.data.count { |x| x.level == 'error' }
149
+ color = count.zero? ? :green : :red
150
+
151
+ [
152
+ title(' Gitaly', :bright_red, 18),
153
+ count.to_s.pastel(color)
154
+ ].join
155
+ end
156
+
99
157
  def production_errors
100
158
  count = production_log.data.count { |x| x.status == 500 }
101
159
  color = count.zero? ? :green : :red
@@ -117,7 +175,14 @@ module GreenHat
117
175
  end
118
176
 
119
177
  def application_errors
120
- count = application_log.data.count { |x| x&.severity == 'ERROR' }
178
+ results = ShellHelper.filter_internal([
179
+ 'gitlab-rails/application_json.log',
180
+ '--message!="Cannot obtain an exclusive lease"',
181
+ '--severity=error',
182
+ "--archive=#{archive.name}"
183
+ ].join(' '))
184
+
185
+ count = results.count { |x| x&.severity == 'ERROR' }
121
186
  color = count.zero? ? :green : :red
122
187
 
123
188
  [
@@ -269,7 +334,7 @@ module GreenHat
269
334
  title('Usage'),
270
335
  ' ['.pastel(:bright_black),
271
336
  '='.pastel(:green) * (used / 2),
272
- ' ' * (50 - used / 2),
337
+ ' ' * (50 - (used / 2)),
273
338
  ']'.pastel(:bright_black),
274
339
  " #{100 - percent(free, total)}%".pastel(:green) # Inverse
275
340
  ].join
@@ -282,21 +347,37 @@ module GreenHat
282
347
 
283
348
  formatted_mem = free_m.data.map { |x| GreenHat::Memory.memory_row x }
284
349
 
285
- [
286
- title('Total', :cyan, 14),
287
- number_to_human_size(free.total.to_i * 1024**2),
288
- "\n",
289
- title('Used', :yellow, 14),
290
- number_to_human_size(free.used.to_i * 1024**2),
291
- "\n",
292
- title('Free', :blue, 14),
293
- number_to_human_size(free.free.to_i * 1024**2),
294
- "\n",
295
- title('Available', :green, 14),
296
- number_to_human_size(free.available.to_i * 1024**2),
297
- "\n\n",
298
- formatted_mem.map { |x| x.prepend ' ' * 2 }.join("\n")
299
- ].join
350
+ output = []
351
+ unless free.total.blank?
352
+ output << title('Total', :cyan, 14)
353
+ output << number_to_human_size(free.total.to_i * (1024**2))
354
+ output << "\n"
355
+ end
356
+
357
+ unless free.total.blank?
358
+ output << title('Used', :yellow, 14)
359
+ output << number_to_human_size(free.used.to_i * (1024**2))
360
+ output << "\n"
361
+ end
362
+
363
+ unless free.total.blank?
364
+ output << title('Free', :blue, 14)
365
+ output << number_to_human_size(free.free.to_i * (1024**2))
366
+ output << "\n"
367
+ end
368
+
369
+ unless free.total.blank?
370
+ output << title('Available', :green, 14)
371
+ output << number_to_human_size(free.available.to_i * (1024**2))
372
+ output << "\n"
373
+ end
374
+
375
+ output << "\n"
376
+ output << formatted_mem.map { |x| x.prepend ' ' * 2 }.join("\n")
377
+
378
+ output.join
379
+ rescue StandardError => e
380
+ LogBot.fatal('Memory', message: e.message, backtrace: e.backtrace.first)
300
381
  end
301
382
 
302
383
  def disks
@@ -55,12 +55,14 @@ module GreenHat
55
55
  # Default Pager
56
56
  TTY::Pager.page do |pager|
57
57
  data.each do |entry|
58
- output = entry_show(flags, entry)
58
+ output = "\n#{entry_show(flags, entry)}"
59
+
60
+ # output += "\n" if flags[:table_style] == 'basic'
59
61
 
60
62
  # Breaks any intentional spaces
61
63
  # next if output.blank?
62
64
 
63
- pager.write("\n#{output}") # write line to the pager
65
+ pager.write(output) # write line to the pager
64
66
  end
65
67
  end
66
68
  end
@@ -103,7 +105,8 @@ module GreenHat
103
105
  StringColor.do(key, entry)
104
106
  end
105
107
 
106
- if flags[:truncate]
108
+ # Stats truncation handled separately
109
+ if flags[:truncate] && !flags[:stats]
107
110
  entry_truncate(formatted_entry, flags[:truncate])
108
111
  else
109
112
  formatted_entry
@@ -125,10 +128,15 @@ module GreenHat
125
128
  table = TTY::Table.new(header: entry.keys, rows: [entry], orientation: :vertical)
126
129
 
127
130
  LogBot.debug('Rendering Entries') if ENV['DEBUG']
128
- table.render(table_style, padding: [0, 1, 0, 1], multiline: true) do |renderer|
131
+ output = table.render(table_style, padding: [0, 1, 0, 1], multiline: true) do |renderer|
129
132
  renderer.border.style = :cyan
130
133
  end
131
134
 
135
+ # Line breaks for basic tables
136
+ output += "\n" if flags[:table_style] == 'basic'
137
+
138
+ output
139
+
132
140
  # LogBot.debug('Finish Render Table') if ENV['DEBUG']
133
141
  # Fall Back to Amazing Inspect
134
142
  rescue StandardError => e
@@ -150,8 +158,21 @@ module GreenHat
150
158
  format_table_entry(flags, val)
151
159
  end
152
160
 
161
+ # Internal Query Helper
162
+ # query = 'gitlab-rails/application_json.log --message!="Cannot obtain an exclusive lease" --severity=error'
163
+ # ShellHelper.filter_internal(query)
164
+ def self.filter_internal(search = '')
165
+ files, flags, args = Args.parse(Shellwords.split(search))
166
+ flags[:combine] = true
167
+
168
+ # Default to everything
169
+ files = Thing.all.map(&:name) if files.empty?
170
+
171
+ ShellHelper.filter_start(files, flags, args)
172
+ end
173
+
153
174
  # Main Entry Point for Filtering
154
- def self.filter_start(files, flags, args)
175
+ def self.filter_start(files, flags = {}, args = {})
155
176
  # Convert to Things
156
177
  logs = ShellHelper.find_things(files, flags).select(&:processed?)
157
178
 
@@ -167,11 +188,17 @@ module GreenHat
167
188
 
168
189
  # Include Total Count in Name
169
190
  results = ShellHelper.filter(log.data, flags, args)
191
+ duration = calculate_duration(results)
192
+
170
193
  title = [
171
194
  log.friendly_name,
172
195
  " #{results.count}".pastel(:bright_black)
196
+
173
197
  ]
174
198
 
199
+ # Append Duration
200
+ title.push(" #{duration.pastel(:cyan, :dim)}") unless duration.blank?
201
+
175
202
  # Save unless empty
176
203
  obj[title.join] = results unless results.count.zero?
177
204
 
@@ -180,6 +207,32 @@ module GreenHat
180
207
  end
181
208
  end
182
209
 
210
+ def self.calculate_duration(results)
211
+ # Skip for Pluck
212
+ only_with_time = results.select { |x| x.instance_of?(Hash) && x.key?(:time) }
213
+
214
+ # If slice is used ignore
215
+ return nil if only_with_time.empty?
216
+
217
+ sorted = only_with_time.map(&:time).sort
218
+ humanize_time(sorted.first, sorted.last)
219
+ end
220
+
221
+ # Replace TimeDifference with https://stackoverflow.com/a/4136485/1678507
222
+ def self.humanize_time(time_start, time_end, increments = 2)
223
+ miliseconds = (time_end - time_start) * 1000
224
+
225
+ list = [[1000, :ms], [60, :s], [60, :m], [24, :h]].map do |count, name|
226
+ next unless miliseconds.positive?
227
+
228
+ miliseconds, n = miliseconds.divmod(count)
229
+
230
+ "#{n.to_i}#{name}" unless n.to_i.zero?
231
+ end
232
+
233
+ list.compact.reverse[0..increments - 1].join(' ')
234
+ end
235
+
183
236
  # Filter Logic
184
237
  # TODO: Simplify
185
238
  # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
@@ -189,7 +242,7 @@ module GreenHat
189
242
  # Experimenting with deep clone
190
243
  results = Marshal.load(Marshal.dump(data))
191
244
  results.select! do |row|
192
- args.send(flags.logic) do |arg|
245
+ args.send(flags.logic || :all?) do |arg|
193
246
  filter_row_key(row, arg, flags)
194
247
  end
195
248
  end
@@ -255,7 +308,6 @@ module GreenHat
255
308
  end
256
309
 
257
310
  # Filter Start and End Times
258
- # rubocop:disable Metrics/MethodLength
259
311
  # TODO: This is a bit icky, simplify/dry
260
312
  def self.filter_time(results, flags)
261
313
  if flags.key?(:start)
@@ -292,7 +344,6 @@ module GreenHat
292
344
 
293
345
  results
294
346
  end
295
- # rubocop:enable Metrics/MethodLength
296
347
 
297
348
  def self.filter_except(results, except)
298
349
  # Avoid Empty Results
@@ -370,6 +421,9 @@ module GreenHat
370
421
  stats.map do |field|
371
422
  occurrences = filter_count_occurrences(results, field, flags)
372
423
 
424
+ # Use Truncate For Long Keys
425
+ occurrences.transform_keys! { |key| key.to_s[0..flags[:truncate]] } if flags[:truncate]
426
+
373
427
  # Total Occurences
374
428
  total = occurrences.values.sum
375
429
 
@@ -387,13 +441,6 @@ module GreenHat
387
441
  # Append Header / Total with field name
388
442
  output.unshift([field.to_s.pastel(:bright_black), total])
389
443
 
390
- # Use Truncate For Long Keys
391
- if flags[:truncate]
392
- output.map! do |key, value|
393
- [key.to_s[0..flags[:truncate]], value]
394
- end
395
- end
396
-
397
444
  # Format
398
445
  output.to_h
399
446
  end
@@ -433,48 +480,83 @@ module GreenHat
433
480
  end
434
481
 
435
482
  # Break out filter row logic into separate method
436
-
437
483
  def self.filter_row_key(row, arg, flags)
438
484
  # Ignore Other Logic if Field isn't even included / Full Text Searching
439
485
  return false unless row.key?(arg[:field]) || arg[:field] == :text
440
486
 
441
487
  # Sensitivity Check / Check for Match / Full Text Searching
442
- included = if arg[:field] == :text
443
- filter_row_entry(row.to_s, arg, flags)
444
- else
445
- filter_row_entry(row[arg.field].to_s, arg, flags)
446
- end
488
+ search_data = arg[:field] == :text ? row : row[arg.field]
489
+ match = filter_row_entry(search_data.to_s, arg, flags)
447
490
 
448
491
  # Pivot of off include vs exclude
449
492
  if arg.bang
450
- !included
493
+ !match
451
494
  else
452
- included
495
+ match
453
496
  end
454
497
  end
455
498
 
456
499
  # Field Partial / Case / Exact search
457
500
  def self.filter_row_entry(entry, arg, flags)
458
501
  # Exact Matching / Unless doing full text search
459
- return entry.to_s == arg.value.to_s if flags.key?(:exact) && arg.field != :text
502
+ return entry == arg.value.to_s if flags.key?(:exact) && arg.field != :text
460
503
 
461
- if flags.key?(:case)
462
- entry.include? arg.value.to_s
463
- else
464
- entry.downcase.include? arg.value.to_s.downcase
504
+ # Cast to String/Integer Helper
505
+ entry, value = filter_entry_cast(entry, arg, flags)
506
+
507
+ entry.send(arg.logic, value)
508
+ end
509
+
510
+ # Handle casting to strings or integers
511
+ def self.filter_entry_cast(entry, arg, flags)
512
+ # Cast to String
513
+ value = arg.value.to_s
514
+
515
+ case arg.logic
516
+ when :include?
517
+
518
+ # Exact Case argument
519
+ unless flags.key?(:case)
520
+ entry.downcase!
521
+ value.downcase!
522
+ end
523
+ when :>=, :<=
524
+ entry = entry.to_i if entry.numeric?
525
+ value = value.to_i if value&.numeric?
465
526
  end
527
+
528
+ [entry, value]
529
+ end
530
+
531
+ def self.filter_entry_logic(entry, arg)
532
+ entry.send(arg.logic, arg.value)
466
533
  end
467
534
 
468
535
  # Total Count Helper
469
- def self.total_count(results)
470
- results.each do |k, v|
536
+ def self.total_count(results, flags)
537
+ results.map do |k, v|
471
538
  puts k
472
- puts "Total: #{v.count.to_s.pastel(:blue)}"
539
+ # puts "Total: #{v.count.to_s.pastel(:blue)}"
540
+ # puts "Time Covered: #{calculate_duration(v).pastel(:cyan)}"
541
+
542
+ output = {}
543
+ output[:total] = v.count
544
+ output[:duration] = calculate_duration(v)
545
+
546
+ # Sort / Get first and Last
547
+ list = v.select(&:time).map(&:time)
548
+ unless list.blank?
549
+ output[:start] = list.first
550
+ output[:end] = list.last
551
+ end
552
+
553
+ puts render_table(output, flags)
554
+
473
555
  puts
474
556
  end
475
557
  end
476
558
 
477
- # Total Count Helper
559
+ # Table Printer Helper
478
560
  def self.fields_print(results)
479
561
  results.each do |k, v|
480
562
  puts k
@@ -538,7 +620,7 @@ module GreenHat
538
620
  return file if file.instance_of?(Thing)
539
621
 
540
622
  if flags.fuzzy_file_match
541
- Thing.all.select { |x| x.name.include? file }
623
+ Thing.all.select { |x| x.name.include?(file) || x.type.include?(file) }
542
624
  else
543
625
  Thing.where name: file
544
626
  end
@@ -550,62 +632,6 @@ module GreenHat
550
632
  things
551
633
  end
552
634
 
553
- # Main Entry Point for Searching
554
- # def self.search_start(log_list, filter_type, args, opts)
555
- def self.search_start(files, flags, args)
556
- # Convert to Things
557
- logs = ShellHelper.find_things(files, flags)
558
-
559
- logs.each_with_object({}) do |log, obj|
560
- # Ignore Empty Results / No Thing
561
- next if log&.data.blank?
562
-
563
- obj[log.friendly_name] = ShellHelper.search(log.data, flags, args)
564
-
565
- obj
566
- end
567
- end
568
-
569
- # Generic Search Helper / String/Regex
570
- def self.search(data, flags = {}, args = {})
571
- results = data.clone.flatten.compact
572
- results.select! do |row|
573
- args.send(flags.logic) do |arg|
574
- search_row(row, arg, flags)
575
- end
576
- end
577
-
578
- # Strip Results if Slice is defined
579
- results.map! { |row| row.slice(*flags[:slice]) } if flags[:slice]
580
-
581
- # Strip Results if Except is defined
582
- results.map! { |row| row.except(*flags[:except]) } if flags[:except]
583
-
584
- # Remove Blank from either slice or except
585
- results.reject!(&:empty?)
586
-
587
- results
588
- end
589
-
590
- # Break out filter row logic into separate method
591
- def self.search_row(row, arg, flags)
592
- # Sensitivity Check / Check for Match
593
- included = filter_row_entry(row.to_s, arg, flags)
594
-
595
- # Pivot of off include vs exclude
596
- if arg.bang
597
- !included
598
- else
599
- included
600
- end
601
- end
602
-
603
- # TODO: Remove?
604
- # Color Reader Helper
605
- # def self.pastel
606
- # @pastel ||= Pastel.new
607
- # end
608
-
609
635
  # Number Helper
610
636
  # https://gitlab.com/zedtux/human_size_to_number/-/blob/master/lib/human_size_to_number/helper.rb
611
637
  def self.human_size_to_number(string)
@@ -627,23 +653,6 @@ module GreenHat
627
653
  number.round
628
654
  end
629
655
 
630
- # TODO: Needed?
631
- def self.filter_and(data, params = {})
632
- result = data.clone.flatten.compact
633
- params.each do |k, v|
634
- result.select! do |row|
635
- if row.key? k.to_sym
636
- row[k.to_sym].include? v
637
- else
638
- false
639
- end
640
- end
641
- next
642
- end
643
-
644
- result
645
- end
646
-
647
656
  # General Helper for `show`
648
657
  def self.common_opts
649
658
  puts 'Common Options'.pastel(:blue)
@@ -7,6 +7,13 @@ module GreenHat
7
7
  # rubocop:enable Lint/Debugger
8
8
  end
9
9
 
10
+ def self.web
11
+ # Load Required Files
12
+ require 'greenhat/web'
13
+
14
+ GreenHat::Web.toggle
15
+ end
16
+
10
17
  def self.df
11
18
  Disk.df
12
19
  end
@@ -23,12 +30,12 @@ module GreenHat
23
30
  Memory.free
24
31
  end
25
32
 
26
- def self.load_local
27
- return false unless TTY::Prompt.new.yes?('Load local Omnibus GitLab Instance files?')
33
+ def self.load_local(prompt = true)
34
+ return false if prompt && !TTY::Prompt.new.yes?('Load local Omnibus GitLab Instance files?')
28
35
 
29
36
  archive_path = "#{$TMP}/#{Time.now.to_i}_local"
30
37
  Dir.mkdir(archive_path)
31
- # archive = Archive.new(name: 'local')
38
+
32
39
  archive = Archive.new(name: archive_path, path: archive_path)
33
40
 
34
41
  file_list = Dir['/var/log/gitlab/*/current'] + Dir['/var/log/gitlab/*/*.log']