greenhat 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +64 -0
  3. data/bin/greenhat +12 -0
  4. data/lib/greenhat.rb +80 -0
  5. data/lib/greenhat/accessors/disk.rb +27 -0
  6. data/lib/greenhat/accessors/logs/production.rb +41 -0
  7. data/lib/greenhat/accessors/logs/sidekiq.rb +41 -0
  8. data/lib/greenhat/accessors/memory.rb +46 -0
  9. data/lib/greenhat/accessors/network.rb +8 -0
  10. data/lib/greenhat/accessors/process.rb +8 -0
  11. data/lib/greenhat/archive.rb +108 -0
  12. data/lib/greenhat/cli.rb +448 -0
  13. data/lib/greenhat/host.rb +182 -0
  14. data/lib/greenhat/logbot.rb +86 -0
  15. data/lib/greenhat/pry_helpers.rb +51 -0
  16. data/lib/greenhat/settings.rb +51 -0
  17. data/lib/greenhat/shell.rb +92 -0
  18. data/lib/greenhat/shell/cat.rb +125 -0
  19. data/lib/greenhat/shell/disk.rb +68 -0
  20. data/lib/greenhat/shell/faststats.rb +195 -0
  21. data/lib/greenhat/shell/gitlab.rb +45 -0
  22. data/lib/greenhat/shell/help.rb +15 -0
  23. data/lib/greenhat/shell/helper.rb +514 -0
  24. data/lib/greenhat/shell/log.rb +344 -0
  25. data/lib/greenhat/shell/memory.rb +31 -0
  26. data/lib/greenhat/shell/network.rb +12 -0
  27. data/lib/greenhat/shell/process.rb +12 -0
  28. data/lib/greenhat/shell/report.rb +319 -0
  29. data/lib/greenhat/thing.rb +121 -0
  30. data/lib/greenhat/thing/file_types.rb +705 -0
  31. data/lib/greenhat/thing/formatters/api_json.rb +34 -0
  32. data/lib/greenhat/thing/formatters/bracket_log.rb +44 -0
  33. data/lib/greenhat/thing/formatters/clean_raw.rb +23 -0
  34. data/lib/greenhat/thing/formatters/colon_split_strip.rb +12 -0
  35. data/lib/greenhat/thing/formatters/dotenv.rb +10 -0
  36. data/lib/greenhat/thing/formatters/format.rb +12 -0
  37. data/lib/greenhat/thing/formatters/free_m.rb +29 -0
  38. data/lib/greenhat/thing/formatters/gitlab_ctl_tail.rb +51 -0
  39. data/lib/greenhat/thing/formatters/gitlab_status.rb +26 -0
  40. data/lib/greenhat/thing/formatters/json.rb +63 -0
  41. data/lib/greenhat/thing/formatters/json_shellwords.rb +44 -0
  42. data/lib/greenhat/thing/formatters/multiline_json.rb +10 -0
  43. data/lib/greenhat/thing/formatters/raw.rb +18 -0
  44. data/lib/greenhat/thing/formatters/shellwords.rb +23 -0
  45. data/lib/greenhat/thing/formatters/table.rb +26 -0
  46. data/lib/greenhat/thing/formatters/time_json.rb +21 -0
  47. data/lib/greenhat/thing/formatters/time_shellwords.rb +28 -0
  48. data/lib/greenhat/thing/formatters/time_space.rb +36 -0
  49. data/lib/greenhat/thing/helpers.rb +71 -0
  50. data/lib/greenhat/thing/history.rb +51 -0
  51. data/lib/greenhat/thing/info_format.rb +193 -0
  52. data/lib/greenhat/thing/kind.rb +97 -0
  53. data/lib/greenhat/thing/spinner.rb +52 -0
  54. data/lib/greenhat/thing/super_log.rb +102 -0
  55. data/lib/greenhat/tty/custom_line.rb +29 -0
  56. data/lib/greenhat/tty/line.rb +326 -0
  57. data/lib/greenhat/tty/reader.rb +110 -0
  58. data/lib/greenhat/version.rb +3 -0
  59. data/lib/greenhat/views/css.slim +126 -0
  60. data/lib/greenhat/views/disk_free.slim +18 -0
  61. data/lib/greenhat/views/index.slim +51 -0
  62. data/lib/greenhat/views/info.slim +39 -0
  63. data/lib/greenhat/views/manifest.slim +22 -0
  64. data/lib/greenhat/views/memory.slim +18 -0
  65. data/lib/greenhat/views/netstat.slim +20 -0
  66. data/lib/greenhat/views/process.slim +21 -0
  67. data/lib/greenhat/views/systemctl.slim +40 -0
  68. data/lib/greenhat/views/ulimit.slim +15 -0
  69. data/lib/greenhat/web.rb +46 -0
  70. metadata +476 -0
@@ -0,0 +1,52 @@
1
+ module GreenHat
2
+ # Info Formatter
3
+ module Spinner
4
+ def spin_start(title)
5
+ # Ignore when Quiet is Set
6
+ return true if Cli.quiet
7
+
8
+ @spin_time = Time.now
9
+ @spinner = TTY::Spinner.new(
10
+ "#{time.colorize(:light_black)} - [:spinner] :title", hide_cursor: true, success_mark: '✔'.colorize(:green)
11
+ )
12
+ @spinner.update(title: title)
13
+
14
+ # Don't Auto spin when debug output is happening
15
+ @spinner.auto_spin unless ENV['DEBUG']
16
+ end
17
+
18
+ def spin_done
19
+ # Ignore when Quiet is Set
20
+ return true if Cli.quiet
21
+
22
+ title = @spinner.tokens[:title]
23
+ spin_end = humanize(@spin_time)
24
+
25
+ title_update = if spin_end.blank?
26
+ title
27
+ else
28
+ "#{title} (#{spin_end.colorize(:blue)})"
29
+ end
30
+
31
+ @spinner.update(title: title_update)
32
+ @spinner.success
33
+ end
34
+
35
+ def time
36
+ Time.now.strftime('%I:%M:%S').colorize(:light_black)
37
+ end
38
+
39
+ # Replace TimeDifference with https://stackoverflow.com/a/4136485/1678507
40
+ def humanize(time)
41
+ miliseconds = (Time.now - time) * 1000
42
+
43
+ [[1000, :ms], [60, :s], [60, :m], [24, :h]].map do |count, name|
44
+ next unless miliseconds.positive?
45
+
46
+ miliseconds, n = miliseconds.divmod(count)
47
+
48
+ "#{n.to_i}#{name}" unless n.to_i.zero?
49
+ end.compact.reverse.join(' ')
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,102 @@
1
+ # TODO: Deprecate, was used specifically for Elk
2
+ # rubocop:disable /AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity, Metrics/
3
+ module GreenHat
4
+ # Log Identifier
5
+ module SuperLog
6
+ def self.log?(kind)
7
+ [
8
+ 'gitaly/current',
9
+ 'gitaly/gitaly_ruby_json.log',
10
+ 'gitlab-rails/api_json.log',
11
+ 'gitlab-rails/application_json.log',
12
+ 'gitlab-rails/audit_json.log',
13
+ 'gitlab-rails/graphql_json.log',
14
+ 'gitlab-rails/integrations_json.log',
15
+ 'gitlab-rails/production_json.log',
16
+ 'gitlab-rails/sidekiq_client.log',
17
+ 'gitlab-shell/gitlab-shell.log',
18
+ 'gitlab-workhorse/current',
19
+ 'puma/puma_stdout.log',
20
+ 'sidekiq/current',
21
+ 'gitlab-rails/importer.log',
22
+ 'gitlabsos.log',
23
+ 'nginx/gitlab_access.log',
24
+ 'patroni/current'
25
+ ].any? { |x| x.include? kind.to_s }
26
+
27
+ true
28
+ end
29
+
30
+ # ==========================================================================
31
+ # File Pattern Matching
32
+ # ==========================================================================
33
+ def self.api_json_format?(path)
34
+ ['rails_api_json_log'].any? { |x| path.include? x }
35
+ end
36
+
37
+ def self.unicorn_stderr_format?(path)
38
+ %w[
39
+ unicorn_stderr
40
+ ].any? { |x| path.include? x }
41
+ end
42
+
43
+ def self.reconfigure_format?(path)
44
+ %w[
45
+ reconfigure
46
+ ].any? { |x| path.include? x }
47
+ end
48
+
49
+ def self.shellwords?(path)
50
+ %w[
51
+ gitlab_pages_current
52
+ alertmanager_current
53
+ registry_current
54
+ prometheus_current
55
+
56
+ ].any? { |x| path.include? x }
57
+ end
58
+
59
+ def self.time_space?(path)
60
+ %w[
61
+ postgresql_current
62
+ redis_current
63
+ unicorn_current
64
+ gitlab_monitor_current
65
+ sidekiq_exporter_log
66
+ ].any? { |x| path.include? x }
67
+ end
68
+
69
+ def self.json_format?(path)
70
+ %w[
71
+ production_json_log
72
+ gitaly_current
73
+ geo_log
74
+ sidekiq_current
75
+ sidekiq_log
76
+ gitlab_shell_gitlab_shell_log
77
+ gitlab_rails_audit_json_log
78
+ gitlab_rails_application_json_log
79
+ ].any? { |x| path.include? x }
80
+ end
81
+
82
+ def self.dmesg_format?(path)
83
+ %w[
84
+ dmesg
85
+ ].any? { |x| path.include? x }
86
+ end
87
+ # ==========================================================================
88
+
89
+ # Identify Formatter
90
+ def self.type?(path)
91
+ return :api_json_format if api_json_format?(path)
92
+ return :unicorn_stderr_format if unicorn_stderr_format?(path)
93
+ return :reconfigure_format if reconfigure_format?(path)
94
+ return :shellwords if shellwords?(path)
95
+ return :time_space if time_space?(path)
96
+ return :json_format if json_format?(path)
97
+ return :dmesg_format if dmesg_format?(path)
98
+
99
+ nil
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,29 @@
1
+ module TTY
2
+ class Reader
3
+ # Shim Helper
4
+ class Line
5
+ def move_word_left
6
+ loop do
7
+ # Don't go past beginning
8
+ break if @cursor.zero?
9
+
10
+ left 1
11
+
12
+ break if self[@cursor].blank?
13
+ end
14
+ end
15
+
16
+ def move_word_right
17
+ loop do
18
+ right 1
19
+ break if self[@cursor].blank?
20
+ end
21
+ end
22
+
23
+ # No Tabs
24
+ def insert(chars)
25
+ self[@cursor] = chars unless ["\t", "\e[Z"].include?(chars)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,326 @@
1
+ # https://github.com/piotrmurach/tty-reader/commit/cc38eadf888ac179a77d72c21ebda987cfea3aca
2
+
3
+ # Disabling Since this is a Shim
4
+ # rubocop:disable all
5
+
6
+
7
+ module TTY
8
+ class Reader
9
+ class Line
10
+ # ANSI_MATCHER = /(\[)?\033(\[)?[;?\d]*[\dA-Za-z](\])?/
11
+
12
+ # The word break characters list used by shell
13
+ DEFAULT_WORD_BREAK_CHARACTERS = " \t\n\"\\'`@$><=|&{("
14
+
15
+ # Strip ANSI characters from the text
16
+ #
17
+ # @param [String] text
18
+ #
19
+ # @return [String]
20
+ #
21
+ # @api public
22
+ def self.sanitize(text)
23
+ text.dup.gsub(ANSI_MATCHER, '')
24
+ end
25
+
26
+ # The editable text
27
+ # @api public
28
+ attr_accessor :text
29
+
30
+ # The current cursor position witin the text
31
+ # @api public
32
+ attr_reader :cursor
33
+
34
+ # The line mode
35
+ # @api public
36
+ attr_reader :mode
37
+
38
+ # The prompt displayed before input
39
+ # @api public
40
+ attr_reader :prompt
41
+
42
+ # The word separator pattern for splitting the text
43
+ #
44
+ # @return [Regexp]
45
+ #
46
+ # @api public
47
+ attr_reader :separator
48
+
49
+ # Create a Line instance
50
+ #
51
+ # @api private
52
+ def initialize(text = '', prompt: '', separator: nil)
53
+ @text = text.dup
54
+ @prompt = prompt.dup
55
+ break_chars = DEFAULT_WORD_BREAK_CHARACTERS.chars
56
+ @separator = separator || Regexp.union(break_chars)
57
+ @cursor = [0, @text.length].max
58
+ @mode = :edit
59
+
60
+ yield self if block_given?
61
+ end
62
+
63
+ # Check if line is in edit mode
64
+ #
65
+ # @return [Boolean]
66
+ #
67
+ # @public
68
+ def editing?
69
+ @mode == :edit
70
+ end
71
+
72
+ # Enable edit mode
73
+ #
74
+ # @return [Boolean]
75
+ #
76
+ # @public
77
+ def edit_mode
78
+ @mode = :edit
79
+ end
80
+
81
+ # Check if line is in replace mode
82
+ #
83
+ # @return [Boolean]
84
+ #
85
+ # @public
86
+ def replacing?
87
+ @mode == :replace
88
+ end
89
+
90
+ # Enable replace mode
91
+ #
92
+ # @return [Boolean]
93
+ #
94
+ # @public
95
+ def replace_mode
96
+ @mode = :replace
97
+ end
98
+
99
+ # Check if cursor reached beginning of the line
100
+ #
101
+ # @return [Boolean]
102
+ #
103
+ # @api public
104
+ def start?
105
+ @cursor.zero?
106
+ end
107
+
108
+ # Check if cursor reached end of the line
109
+ #
110
+ # @return [Boolean]
111
+ #
112
+ # @api public
113
+ def end?
114
+ @cursor == @text.length
115
+ end
116
+
117
+ # Move line position to the left by n chars
118
+ #
119
+ # @api public
120
+ def left(n = 1)
121
+ @cursor = [0, @cursor - n].max
122
+ end
123
+
124
+ # Move line position to the right by n chars
125
+ #
126
+ # @api public
127
+ def right(n = 1)
128
+ @cursor = [@text.length, @cursor + n].min
129
+ end
130
+
131
+ # Move cursor to beginning position
132
+ #
133
+ # @api public
134
+ def move_to_start
135
+ @cursor = 0
136
+ end
137
+
138
+ # Move cursor to end position
139
+ #
140
+ # @api public
141
+ def move_to_end
142
+ @cursor = @text.length # put cursor outside of text
143
+ end
144
+
145
+ # Insert characters inside a line. When the lines exceeds
146
+ # maximum length, an extra space is added to accomodate index.
147
+ #
148
+ # @param [Integer] i
149
+ # the index to insert at
150
+ #
151
+ # @param [String] chars
152
+ # the characters to insert
153
+ #
154
+ # @example
155
+ # text = "aaa"
156
+ # line[5]= "b"
157
+ # => "aaa b"
158
+ #
159
+ # @api public
160
+ def []=(i, chars)
161
+ edit_mode
162
+
163
+ if i.is_a?(Range)
164
+ @text[i] = chars
165
+ @cursor += chars.length
166
+ return
167
+ end
168
+
169
+ if i <= 0
170
+ before_text = ''
171
+ after_text = @text.dup
172
+ elsif i > @text.length - 1 # insert outside of line input
173
+ before_text = @text.dup
174
+ after_text = "\s" * (i - @text.length)
175
+ @cursor += after_text.length
176
+ else
177
+ before_text = @text[0..i - 1].dup
178
+ after_text = @text[i..-1].dup
179
+ end
180
+
181
+ @text = if i > @text.length - 1
182
+ before_text + after_text + chars
183
+ else
184
+ before_text + chars + after_text
185
+ end
186
+
187
+ @cursor = i + chars.length
188
+ end
189
+
190
+ # Read character
191
+ #
192
+ # @api public
193
+ def [](i)
194
+ @text[i]
195
+ end
196
+
197
+ # Find a word under the cursor based on the word separator
198
+ #
199
+ # @param [Boolean] before
200
+ # whether to start searching before or after a break character
201
+ #
202
+ # @return [String]
203
+ #
204
+ # @api public
205
+ def word(before: true)
206
+ @text[range(before: before)]
207
+ end
208
+
209
+ # Find a range of characters under the cursor based on the word separator
210
+ #
211
+ # @param [Integer] from
212
+ # the start index
213
+ #
214
+ # @param [Symbol] before
215
+ # whether to start search before or after break character
216
+ #
217
+ # @return [Range]
218
+ #
219
+ # @api public
220
+ def range(from: @cursor, before: true)
221
+ # move back or forward by one character when at a word boundary
222
+ if word_boundary?
223
+ from = before ? from - 1 : from + 1
224
+ end
225
+
226
+ # find start position
227
+ start_pos = @text.rindex(separator, from) || 0
228
+ start_pos += 1 unless start_pos.zero?
229
+
230
+ # find end position
231
+ end_pos = @text.index(separator, start_pos) || text_size
232
+ end_pos -= 1 unless @text.empty?
233
+
234
+ start_pos..end_pos
235
+ end
236
+
237
+ # Check if cursor is at a word boundary
238
+ #
239
+ # @return [Boolean]
240
+ #
241
+ # @api private
242
+ def word_boundary?
243
+ @text[@cursor] =~ separator
244
+ end
245
+
246
+ # Replace current line with new text
247
+ #
248
+ # @param [String] text
249
+ #
250
+ # @api public
251
+ def replace(text)
252
+ @text = text
253
+ @cursor = @text.length # put cursor outside of text
254
+ replace_mode
255
+ end
256
+
257
+ # Insert char(s) at cursor position
258
+ #
259
+ # @api public
260
+ def insert(chars)
261
+ self[@cursor] = chars
262
+ end
263
+
264
+ # Add char and move cursor
265
+ #
266
+ # @api public
267
+ def <<(char)
268
+ @text << char
269
+ @cursor += 1
270
+ end
271
+
272
+ # Remove char from the line at current position
273
+ #
274
+ # @api public
275
+ def delete(n = 1)
276
+ @text.slice!(@cursor, n)
277
+ end
278
+
279
+ # Remove char from the line in front of the cursor
280
+ #
281
+ # @param [Integer] n
282
+ # the number of chars to remove
283
+ #
284
+ # @api public
285
+ def remove(n = 1)
286
+ left(n)
287
+ @text.slice!(@cursor, n)
288
+ end
289
+
290
+ # Full line with prompt as string
291
+ #
292
+ # @api public
293
+ def to_s
294
+ "#{@prompt}#{@text}"
295
+ end
296
+ alias inspect to_s
297
+
298
+ # Prompt size
299
+ #
300
+ # @api public
301
+ def prompt_size
302
+ p = self.class.sanitize(@prompt).split(/\r?\n/)
303
+ # return the length of each line + screen width for every line past the first
304
+ # which accounts for multi-line prompts
305
+ p.join.length + ((p.length - 1) * TTY::Screen.width)
306
+ end
307
+
308
+ # Text size
309
+ #
310
+ # @api public
311
+ def text_size
312
+ self.class.sanitize(@text).size
313
+ end
314
+
315
+ # Full line size with prompt
316
+ #
317
+ # @api public
318
+ def size
319
+ prompt_size + text_size
320
+ end
321
+ alias length size
322
+ end
323
+ end
324
+ end
325
+
326
+ # rubocop:enable all