greenhat 0.1.5 → 0.3.2

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/lib/greenhat/accessors/disk.rb +58 -2
  3. data/lib/greenhat/accessors/gitlab.rb +75 -0
  4. data/lib/greenhat/accessors/memory.rb +10 -10
  5. data/lib/greenhat/accessors/process.rb +10 -1
  6. data/lib/greenhat/cli.rb +148 -63
  7. data/lib/greenhat/color.rb +27 -0
  8. data/lib/greenhat/logbot.rb +9 -9
  9. data/lib/greenhat/settings.rb +51 -3
  10. data/lib/greenhat/shell/args.rb +146 -0
  11. data/lib/greenhat/shell/cat.rb +25 -73
  12. data/lib/greenhat/shell/color_string.rb +43 -0
  13. data/lib/greenhat/shell/disk.rb +30 -42
  14. data/lib/greenhat/shell/faststats.rb +104 -58
  15. data/lib/greenhat/shell/field_helper.rb +75 -0
  16. data/lib/greenhat/shell/filter_help.rb +162 -0
  17. data/lib/greenhat/shell/gitlab.rb +61 -2
  18. data/lib/greenhat/shell/help.rb +98 -15
  19. data/lib/greenhat/shell/list.rb +46 -0
  20. data/lib/greenhat/shell/log.rb +115 -209
  21. data/lib/greenhat/shell/page.rb +39 -0
  22. data/lib/greenhat/shell/process.rb +57 -2
  23. data/lib/greenhat/shell/report.rb +70 -60
  24. data/lib/greenhat/shell/shell_helper.rb +654 -0
  25. data/lib/greenhat/shell.rb +27 -13
  26. data/lib/greenhat/thing/file_types.rb +54 -7
  27. data/lib/greenhat/thing/formatters/json_shellwords.rb +0 -3
  28. data/lib/greenhat/thing/formatters/nginx.rb +44 -0
  29. data/lib/greenhat/thing/formatters/syslog.rb +39 -0
  30. data/lib/greenhat/thing/helpers.rb +4 -4
  31. data/lib/greenhat/thing/kind.rb +9 -2
  32. data/lib/greenhat/thing/spinner.rb +3 -3
  33. data/lib/greenhat/thing.rb +25 -3
  34. data/lib/greenhat/tty/columns.rb +44 -0
  35. data/lib/greenhat/version.rb +1 -1
  36. data/lib/greenhat.rb +16 -14
  37. metadata +42 -17
  38. data/lib/greenhat/shell/helper.rb +0 -541
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.1.5
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Davin Walker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-08 00:00:00.000000000 Z
11
+ date: 2021-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: amazing_print
@@ -53,49 +53,49 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '5.14'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rake
56
+ name: minitest-reporters
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '13.0'
61
+ version: '1.4'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '13.0'
68
+ version: '1.4'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rubocop
70
+ name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '1.12'
75
+ version: '13.0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '1.12'
82
+ version: '13.0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: actionview
84
+ name: rubocop
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '6.1'
90
- type: :runtime
89
+ version: '1.12'
90
+ type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '6.1'
96
+ version: '1.12'
97
97
  - !ruby/object:Gem::Dependency
98
- name: activesupport
98
+ name: actionview
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
@@ -109,19 +109,19 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: '6.1'
111
111
  - !ruby/object:Gem::Dependency
112
- name: colorize
112
+ name: activesupport
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '0.8'
117
+ version: '6.1'
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '0.8'
124
+ version: '6.1'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: did_you_mean
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -360,6 +360,20 @@ dependencies:
360
360
  - - "~>"
361
361
  - !ruby/object:Gem::Version
362
362
  version: '0.12'
363
+ - !ruby/object:Gem::Dependency
364
+ name: tty-which
365
+ requirement: !ruby/object:Gem::Requirement
366
+ requirements:
367
+ - - "~>"
368
+ - !ruby/object:Gem::Version
369
+ version: '0.5'
370
+ type: :runtime
371
+ prerelease: false
372
+ version_requirements: !ruby/object:Gem::Requirement
373
+ requirements:
374
+ - - "~>"
375
+ - !ruby/object:Gem::Version
376
+ version: '0.5'
363
377
  - !ruby/object:Gem::Dependency
364
378
  name: warning
365
379
  requirement: !ruby/object:Gem::Requirement
@@ -386,6 +400,7 @@ files:
386
400
  - bin/greenhat
387
401
  - lib/greenhat.rb
388
402
  - lib/greenhat/accessors/disk.rb
403
+ - lib/greenhat/accessors/gitlab.rb
389
404
  - lib/greenhat/accessors/logs/production.rb
390
405
  - lib/greenhat/accessors/logs/sidekiq.rb
391
406
  - lib/greenhat/accessors/memory.rb
@@ -393,22 +408,29 @@ files:
393
408
  - lib/greenhat/accessors/process.rb
394
409
  - lib/greenhat/archive.rb
395
410
  - lib/greenhat/cli.rb
411
+ - lib/greenhat/color.rb
396
412
  - lib/greenhat/host.rb
397
413
  - lib/greenhat/logbot.rb
398
414
  - lib/greenhat/pry_helpers.rb
399
415
  - lib/greenhat/settings.rb
400
416
  - lib/greenhat/shell.rb
417
+ - lib/greenhat/shell/args.rb
401
418
  - lib/greenhat/shell/cat.rb
419
+ - lib/greenhat/shell/color_string.rb
402
420
  - lib/greenhat/shell/disk.rb
403
421
  - lib/greenhat/shell/faststats.rb
422
+ - lib/greenhat/shell/field_helper.rb
423
+ - lib/greenhat/shell/filter_help.rb
404
424
  - lib/greenhat/shell/gitlab.rb
405
425
  - lib/greenhat/shell/help.rb
406
- - lib/greenhat/shell/helper.rb
426
+ - lib/greenhat/shell/list.rb
407
427
  - lib/greenhat/shell/log.rb
408
428
  - lib/greenhat/shell/memory.rb
409
429
  - lib/greenhat/shell/network.rb
430
+ - lib/greenhat/shell/page.rb
410
431
  - lib/greenhat/shell/process.rb
411
432
  - lib/greenhat/shell/report.rb
433
+ - lib/greenhat/shell/shell_helper.rb
412
434
  - lib/greenhat/thing.rb
413
435
  - lib/greenhat/thing/file_types.rb
414
436
  - lib/greenhat/thing/formatters/api_json.rb
@@ -423,8 +445,10 @@ files:
423
445
  - lib/greenhat/thing/formatters/json.rb
424
446
  - lib/greenhat/thing/formatters/json_shellwords.rb
425
447
  - lib/greenhat/thing/formatters/multiline_json.rb
448
+ - lib/greenhat/thing/formatters/nginx.rb
426
449
  - lib/greenhat/thing/formatters/raw.rb
427
450
  - lib/greenhat/thing/formatters/shellwords.rb
451
+ - lib/greenhat/thing/formatters/syslog.rb
428
452
  - lib/greenhat/thing/formatters/table.rb
429
453
  - lib/greenhat/thing/formatters/time_json.rb
430
454
  - lib/greenhat/thing/formatters/time_shellwords.rb
@@ -435,6 +459,7 @@ files:
435
459
  - lib/greenhat/thing/kind.rb
436
460
  - lib/greenhat/thing/spinner.rb
437
461
  - lib/greenhat/thing/super_log.rb
462
+ - lib/greenhat/tty/columns.rb
438
463
  - lib/greenhat/tty/custom_line.rb
439
464
  - lib/greenhat/tty/line.rb
440
465
  - lib/greenhat/tty/reader.rb
@@ -1,541 +0,0 @@
1
- module GreenHat
2
- # Common Helpers
3
- # rubocop:disable Metrics/ModuleLength
4
- module ShellHelper
5
- # Generic Parameter Parsing
6
- def self.param_parse(params)
7
- # Turn Params into Hash
8
- opts = params.flat_map { |param| param_opt_scan(param) }
9
-
10
- # Collect and Remove Args
11
- args = params.each_with_object({}) { |param, obj| param_arg_scan(param, obj) }
12
-
13
- # Move Special Arguments
14
- opts.reject! do |opt|
15
- if param_special_opts.include? opt.field
16
- args[opt.field] = opt.value.split(',').map(&:to_sym)
17
- true
18
- end
19
- end
20
-
21
- # Remove Opts and Args
22
- params.reject! do |param|
23
- opt_field_remove?(opts, param) || arg_field_remove?(args, param)
24
- end
25
-
26
- [params, opts, args]
27
- end
28
-
29
- def self.opt_field_remove?(opts, param)
30
- opts.any? do |opt|
31
- param.include? "--#{opt.field}#{opt.bang ? '!' : nil}=#{opt.value}"
32
- end
33
- end
34
-
35
- def self.arg_field_remove?(args, param)
36
- args.keys.any? { |field| param.include? "--#{field}" }
37
- end
38
-
39
- # Def Param Scan (Split -- values into keys)
40
- def self.param_opt_scan(param)
41
- param.scan(/--([^=]+)=(.*)/).map do |field, value|
42
- bang = false
43
- if field.include? '!'
44
- field.delete!('!')
45
- bang = true
46
- end
47
-
48
- { field: field.to_sym, value: value, bang: bang }
49
- end
50
- end
51
-
52
- # Params that should be set as Args
53
- # Comma Delimited
54
- # --slice=thing,thing2
55
- # --except=time,params
56
- # --round=2
57
-
58
- def self.param_special_opts
59
- %i[
60
- slice except stats uniq pluck round archive start end sort limit
61
- ]
62
- end
63
-
64
- # Parameter Extraction
65
- # Special Opts: --slice, --except
66
- def self.param_arg_scan(param, obj)
67
- # TODO: Why is capture group doing two arrays
68
- param.scan(/--([^=]+)$/).flatten.each do |field|
69
- obj[field.to_sym] = param_arg_defaults(field.to_sym)
70
- end
71
-
72
- obj
73
- end
74
-
75
- # Arg Defaults
76
- def self.param_arg_defaults(field)
77
- case field
78
- when :round then 2
79
- when :limit then [TTY::Screen.height / 2]
80
- when *param_special_opts then []
81
- else
82
- true
83
- end
84
- end
85
-
86
- # Use File Process for Output
87
- def self.file_output(files)
88
- results = file_process(files) do |file|
89
- [
90
- file.friendly_name,
91
- file.output(false),
92
- "\n"
93
- ]
94
- end
95
-
96
- ShellHelper.show(results.flatten)
97
- end
98
-
99
- def self.file_process(files, &block)
100
- files.map do |file|
101
- next if file.output(false).empty?
102
-
103
- block.call(file)
104
- end.flatten
105
- end
106
-
107
- # Pagination Helper
108
- def self.page(data)
109
- TTY::Pager.page do |pager|
110
- data.flatten.each do |output|
111
- pager.write("\n#{output}") # write line to the pager
112
- end
113
- end
114
- end
115
-
116
- # Show Data / Auto Paginate Helper
117
- def self.show(data, args = {})
118
- # If Block of String
119
- if data.instance_of?(String)
120
- TTY::Pager.page data
121
- return true
122
- end
123
-
124
- # If raw just print out
125
- if args.raw
126
- puts data.join("\n")
127
- return true
128
- end
129
-
130
- # Check if content needs to paged, or if auto_height is off
131
- if !args.page && count_rows(data)
132
- puts data.map { |x| entry_show(x, args) }.compact.join("\n")
133
- return true
134
- end
135
-
136
- # Default Pager
137
- TTY::Pager.page do |pager|
138
- data.each do |entry|
139
- output = entry_show(entry, args)
140
-
141
- next if output.blank?
142
-
143
- pager.write("\n#{output}") # write line to the pager
144
- end
145
- end
146
- end
147
-
148
- # Array/Hash and String pagination check. Don't unncessarily loop through everything
149
- def self.count_rows(data)
150
- height = TTY::Screen.height
151
- size = 0
152
-
153
- data.each do |entry|
154
- size += case entry
155
- when Hash then entry.keys.count
156
- when Array then entry.count
157
- else
158
- 1
159
- end
160
-
161
- break if size > height
162
- end
163
-
164
- height > size
165
- end
166
-
167
- # Entry Shower
168
- def self.entry_show(entry, args)
169
- case entry
170
- when Hash then render_table(entry, args)
171
- when String, Float, Integer then entry
172
- when Array
173
- entry.map { |x| x.ai(multiline: false) }.join("\n")
174
- else
175
- LogBot.warn('Shell Show', "Unknown #{entry.class}")
176
- nil
177
- end
178
- end
179
-
180
- # Print the Table in a Nice way
181
- def self.render_table(entry, args)
182
- table = TTY::Table.new(header: entry.keys, rows: [entry], orientation: :vertical)
183
-
184
- table.render(:unicode, padding: [0, 1, 0, 1]) do |renderer|
185
- renderer.border.style = :cyan
186
-
187
- renderer.filter = lambda do |val, _row_index, col_index|
188
- if col_index == 1
189
- if val.numeric?
190
- # TODO: Better Casting?
191
- val = val.to_f.round(args.round.first.to_s.to_i) if args.round
192
- val.to_s.colorize(:blue)
193
- else
194
- val.to_s
195
- end
196
- else
197
- val.to_s
198
- end
199
- end
200
- end
201
-
202
- # Fall Back to Amazing Inspect
203
- rescue StandardError => e
204
- LogBot.warn('Table', message: e.message, backtrace: e.backtrace.first) if ENV['DEBUG']
205
-
206
- [
207
- entry.ai,
208
- ('_' * (TTY::Screen.width / 3)).colorize(:cyan),
209
- "\n"
210
- ].join("\n")
211
- end
212
-
213
- # Main Entry Point for Filtering
214
- def self.filter_start(log_list, filter_type, args, opts)
215
- # Convert to Things
216
- logs = ShellHelper.find_things(log_list, args).select(&:processed?)
217
-
218
- # Ignore Archive/Host Dividers
219
- if args[:combine]
220
- results = logs.reject(&:blank?).map(&:data).flatten.compact
221
- ShellHelper.filter(results, filter_type, args, opts)
222
- else
223
- # Iterate and Preserve Archive/Host Index
224
- logs.each_with_object({}) do |log, obj|
225
- # Ignore Empty Results / No Thing
226
- next if log&.blank?
227
-
228
- obj[log.friendly_name] = ShellHelper.filter(log.data, filter_type, args, opts)
229
-
230
- obj
231
- end
232
- end
233
- end
234
-
235
- # Filter Logic
236
- # TODO: Simplify
237
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
238
- def self.filter(data, type = :all?, args = {}, opts = {})
239
- results = data.clone.flatten.compact
240
- results.select! do |row|
241
- opts.send(type) do |opt|
242
- filter_row_key(row, opt)
243
- end
244
- end
245
-
246
- # Time Filtering
247
- results = filter_time(results, args) if args[:start] || args[:end]
248
-
249
- # Strip Results if Slice is defined
250
- results = filter_slice(results, args[:slice]) if args[:slice]
251
-
252
- # Strip Results if Except is defined
253
- results = filter_except(results, args[:except]) if args[:except]
254
-
255
- # Remove Blank from either slice or except
256
- results.reject!(&:empty?)
257
-
258
- # Sort
259
- results.sort_by! { |x| x.slice(*args[:sort]).values } if args[:sort]
260
-
261
- # JSON Formatting
262
- results = results.map { |x| Oj.dump(x) } if args[:json]
263
-
264
- # Show Unique Only
265
- results = filter_uniq(results, args[:uniq]) if args.key?(:uniq)
266
-
267
- # Reverse
268
- results.reverse! if args[:reverse]
269
-
270
- # Count occurrences / Skip Results
271
- return filter_stats(results, args[:stats]) if args[:stats]
272
-
273
- # Pluck
274
- results = filter_pluck(results, args[:pluck]) if args.key?(:pluck)
275
-
276
- # Limit
277
- if args[:limit]
278
- results[0..args[:limit].map(&:to_s).join.to_i]
279
- else
280
- results
281
- end
282
- end
283
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
284
-
285
- # Filter Start and End Times
286
- # rubocop:disable Metrics/MethodLength
287
- # TODO: This is a bit icky, simplify/dry
288
- def self.filter_time(results, args)
289
- if args.start
290
- begin
291
- time_start = Time.parse(args.start.first.to_s)
292
-
293
- results.select! do |x|
294
- if x.time
295
- time_start < x.time
296
- else
297
- true
298
- end
299
- end
300
- rescue StandardError
301
- puts 'Unable to Process Start Time Filter'.colorize(:red)
302
- end
303
- end
304
-
305
- if args.end
306
- begin
307
- time_start = Time.parse(args.end.first.to_s)
308
-
309
- results.select! do |x|
310
- if x.time
311
- time_start > x.time
312
- else
313
- true
314
- end
315
- end
316
- rescue StandardError
317
- puts 'Unable to Process End Time Filter'.colorize(:red)
318
- end
319
- end
320
-
321
- results
322
- end
323
- # rubocop:enable Metrics/MethodLength
324
-
325
- def self.filter_except(results, except)
326
- # Avoid Empty Results
327
- if slice.empty?
328
- filter_empty_arg('slice')
329
- return results
330
- end
331
-
332
- results.map { |row| row.except(*except) }
333
- end
334
-
335
- def self.filter_slice(results, slice)
336
- # Avoid Empty Results
337
- if slice.empty?
338
- filter_empty_arg('slice')
339
- return results
340
- end
341
-
342
- results.map { |row| row.slice(*slice) }
343
- end
344
-
345
- def self.filter_pluck(results, pluck)
346
- # Avoid Empty Results
347
- if pluck.empty?
348
- filter_empty_arg('pluck')
349
- return results
350
- end
351
-
352
- results.map { |x| x.slice(*pluck).values }.flatten
353
- end
354
-
355
- def self.filter_uniq(results, unique)
356
- # Avoid Empty Results
357
- if unique.empty?
358
- filter_empty_arg('uniq')
359
- return results
360
- end
361
-
362
- unique.map do |field|
363
- results.uniq { |x| x[field] }
364
- end.flatten
365
- end
366
-
367
- def self.filter_stats(results, stats)
368
- # Avoid Empty Results
369
- if stats.empty?
370
- filter_empty_arg('stats')
371
- return results
372
- end
373
-
374
- stats.map do |stat|
375
- occurrences = filter_count_occurrences(results, stat)
376
- occurrences.sort_by(&:last).to_h
377
- end
378
- end
379
-
380
- # Helper to Count occurrences
381
- def self.filter_count_occurrences(results, stat)
382
- results.each_with_object(Hash.new(0)) do |entry, counts|
383
- next unless entry.key? stat
384
-
385
- counts[entry[stat]] += 1
386
-
387
- counts
388
- end
389
- end
390
-
391
- def self.filter_empty_arg(arg)
392
- puts [
393
- 'Ignoring'.colorize(:light_yellow),
394
- "--#{arg}".colorize(:cyan),
395
- 'it requires an argument'.colorize(:red)
396
- ].join(' ')
397
- end
398
-
399
- # Break out filter row logic into separate method
400
- def self.filter_row_key(row, param)
401
- # Ignore Other Logic if Field isn't even included
402
- return false unless row.key? param.field
403
-
404
- # Not Included Param
405
- included = row[param.field].to_s.include? param.value.to_s
406
-
407
- if param.bang
408
- !included
409
- else
410
- included
411
- end
412
- end
413
-
414
- # Total Count Helper
415
- def self.total_count(results)
416
- results.each do |k, v|
417
- puts k
418
- puts "Total: #{v.count.to_s.colorize(:blue)}"
419
- puts
420
- end
421
- end
422
-
423
- # Total Log List Manipulator
424
- def self.prepare_list(log_list, base_list = nil)
425
- base_list ||= GreenHat::ShellHelper::Log.list
426
-
427
- # Assume all
428
- log_list.push '*' if log_list.empty?
429
-
430
- # Map for All
431
- log_list = base_list.map(&:name) if log_list == ['*']
432
-
433
- log_list
434
- end
435
-
436
- # Shortcut find things
437
- def self.find_things(log_list, args = {})
438
- things = log_list.uniq.flat_map do |log|
439
- Thing.where name: log
440
- end
441
-
442
- # Host / Archive
443
- things.select! { |x| x.archive? args.archive } if args.archive
444
-
445
- things
446
- end
447
-
448
- # Main Entry Point for Searching
449
- def self.search_start(log_list, filter_type, args, opts)
450
- # Convert to Things
451
- logs = ShellHelper.find_things(log_list, args)
452
-
453
- logs.each_with_object({}) do |log, obj|
454
- # Ignore Empty Results / No Thing
455
- next if log&.data.blank?
456
-
457
- obj[log.friendly_name] = ShellHelper.search(log.data, filter_type, args, opts)
458
-
459
- obj
460
- end
461
- end
462
-
463
- # Generic Search Helper / String/Regex
464
- def self.search(data, type = :all?, args = {}, opts = {})
465
- results = data.clone.flatten.compact
466
-
467
- results.select! do |row|
468
- opts.send(type) do |opt|
469
- search_row(row, opt)
470
- end
471
- end
472
-
473
- # Strip Results if Slice is defined
474
- results.map! { |row| row.slice(*args[:slice]) } if args[:slice]
475
-
476
- # Strip Results if Except is defined
477
- results.map! { |row| row.except(*args[:except]) } if args[:except]
478
-
479
- # Remove Blank from either slice or except
480
- results.reject!(&:empty?)
481
-
482
- results
483
- end
484
-
485
- # Break out filter row logic into separate method
486
- def self.search_row(row, param)
487
- # Not Included Param
488
- included = row.to_s.include? param.value
489
-
490
- if param.bang
491
- !included
492
- else
493
- included
494
- end
495
- end
496
-
497
- # Color Reader Helper
498
- def self.pastel
499
- @pastel ||= Pastel.new
500
- end
501
-
502
- # Number Helper
503
- # https://gitlab.com/zedtux/human_size_to_number/-/blob/master/lib/human_size_to_number/helper.rb
504
- def self.human_size_to_number(string)
505
- size, unit = string.scan(/(\d*\.?\d+)\s?(Bytes?|KB|MB|GB|TB)/i).first
506
- number = size.to_f
507
-
508
- number = case unit.downcase
509
- when 'byte', 'bytes'
510
- number
511
- when 'kb'
512
- number * 1024
513
- when 'mb'
514
- number * 1024 * 1024
515
- when 'gb'
516
- number * 1024 * 1024 * 1024
517
- when 'tb'
518
- number * 1024 * 1024 * 1024 * 1024
519
- end
520
- number.round
521
- end
522
-
523
- # TODO: Needed?
524
- def self.filter_and(data, params = {})
525
- result = data.clone.flatten.compact
526
- params.each do |k, v|
527
- result.select! do |row|
528
- if row.key? k.to_sym
529
- row[k.to_sym].include? v
530
- else
531
- false
532
- end
533
- end
534
- next
535
- end
536
-
537
- result
538
- end
539
- end
540
- # rubocop:enable Metrics/ModuleLength
541
- end