greenhat 0.6.2 → 0.6.3
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 +42 -6
- data/lib/greenhat/accessors/gitlab.rb +1 -1
- data/lib/greenhat/cli.rb +0 -2
- data/lib/greenhat/reports/internal_methods.rb +1 -0
- data/lib/greenhat/reports/reports/full.rb +7 -0
- data/lib/greenhat/reports/reports/full_markdown.rb +140 -0
- data/lib/greenhat/reports/shell_helper.rb +11 -0
- data/lib/greenhat/settings.rb +2 -2
- data/lib/greenhat/shell/gitlab.rb +1 -2
- data/lib/greenhat/shell/query.rb +1 -1
- data/lib/greenhat/shell/reports.rb +14 -0
- data/lib/greenhat/shell/shell_helper.rb +31 -17
- data/lib/greenhat/shell.rb +12 -0
- data/lib/greenhat/thing/file_types.rb +24 -0
- data/lib/greenhat/thing/formatters/gitlab_ctl_tail.rb +1 -1
- data/lib/greenhat/thing/formatters/gitlab_status.rb +1 -1
- data/lib/greenhat/thing/formatters/kube_webservice.rb +1 -1
- data/lib/greenhat/version.rb +1 -1
- metadata +3 -3
- data/lib/greenhat/shell/report.rb +0 -415
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: abf4296d91fa1a63e0858e1a1ee0bc461668a6839d7ffb7ab6fbaeadae035dc1
|
4
|
+
data.tar.gz: c7134e262cabb6c1873dc92e56ca6318cef9c64abb4573646228ee52c36be60e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ea40f3c0fc24c35722631e61ad489bd1b9eabd2d6453669e2b56476a5e1c4c883d181d062794023555598da608a69615d4f10f0bfd0c8a75bccf6e0faed8189
|
7
|
+
data.tar.gz: 9b947cdfc641164da1ed4d76df4e9739a01ad29a8120bc3485a534b7a0274beb3965c07dc275004e0a3320341844a00031b480e984835e91610edf77b70bf3e4
|
@@ -11,7 +11,7 @@ module GreenHat
|
|
11
11
|
x.slice(key)
|
12
12
|
end
|
13
13
|
|
14
|
-
list.map(&:values).flatten.max_by(&:size).size +
|
14
|
+
list.map(&:values).flatten.max_by(&:size).size + 5
|
15
15
|
end
|
16
16
|
|
17
17
|
def self.padding(disks, keys = %i[mounted_on size used avail])
|
@@ -29,6 +29,44 @@ module GreenHat
|
|
29
29
|
things
|
30
30
|
end
|
31
31
|
|
32
|
+
def self.report_output(data, filter = %w[tmpfs loop])
|
33
|
+
output = []
|
34
|
+
|
35
|
+
disks = data.sort_by { |x| x.use.to_i }.reverse
|
36
|
+
disks.reject! { |x| filter.any? { |y| x.filesystem.include? y } }
|
37
|
+
pad_mount, pad_size, pad_used, pad_avail = GreenHat::Disk.padding(disks)
|
38
|
+
|
39
|
+
output << [
|
40
|
+
'Mount'.ljust(pad_mount).pastel(:blue),
|
41
|
+
'Size'.ljust(pad_size).pastel(:magenta),
|
42
|
+
'Used'.ljust(pad_used).pastel(:cyan),
|
43
|
+
'Avail'.ljust(pad_avail).pastel(:white),
|
44
|
+
'% Use'.ljust(pad_avail).pastel(:green)
|
45
|
+
].join
|
46
|
+
|
47
|
+
disks.map do |disk|
|
48
|
+
# Pretty Disk Use
|
49
|
+
use = [
|
50
|
+
disk.use.rjust(5).ljust(5).pastel(:green),
|
51
|
+
' ['.pastel(:blue),
|
52
|
+
('=' * (disk.use.to_i / 2)).pastel(:green),
|
53
|
+
' ' * (50 - (disk.use.to_i / 2)),
|
54
|
+
']'.pastel(:blue)
|
55
|
+
].join
|
56
|
+
|
57
|
+
# Whole Thing
|
58
|
+
output << [
|
59
|
+
disk.mounted_on.ljust(pad_mount).pastel(:blue),
|
60
|
+
disk[:size].to_s.ljust(pad_size).pastel(:magenta),
|
61
|
+
disk.used.to_s.ljust(pad_used).pastel(:cyan),
|
62
|
+
disk.avail.to_s.ljust(pad_avail).pastel(:white),
|
63
|
+
use
|
64
|
+
].join
|
65
|
+
end
|
66
|
+
|
67
|
+
output.join("\n ")
|
68
|
+
end
|
69
|
+
|
32
70
|
# Unified Output Handler
|
33
71
|
def self.format_output(file, name = false, limit = nil, filter = %w[tmpfs loop])
|
34
72
|
output = []
|
@@ -79,13 +117,11 @@ module GreenHat
|
|
79
117
|
end
|
80
118
|
|
81
119
|
# Unified Output Handler
|
82
|
-
def self.markdown_format(
|
120
|
+
def self.markdown_format(data, _name = false, limit = nil, filter = %w[tmpfs loop])
|
83
121
|
output = []
|
84
122
|
|
85
|
-
output << file.friendly_name if name
|
86
|
-
|
87
123
|
# Reject TMPFS
|
88
|
-
disks =
|
124
|
+
disks = data.sort_by { |x| x.use.to_i }.reverse
|
89
125
|
|
90
126
|
# Filter
|
91
127
|
disks.reject! { |x| filter.any? { |y| x.filesystem.include? y } }
|
@@ -115,7 +151,7 @@ module GreenHat
|
|
115
151
|
].join
|
116
152
|
end
|
117
153
|
|
118
|
-
output
|
154
|
+
output.join("\n")
|
119
155
|
end
|
120
156
|
# =
|
121
157
|
end
|
@@ -26,7 +26,7 @@ module GreenHat
|
|
26
26
|
|
27
27
|
def self.identify_node(archive)
|
28
28
|
gitlab_status = archive.things.find { |x| x.name == 'gitlab_status' }&.data&.keys
|
29
|
-
hostname = archive.things.find { |x| x.type == 'hostname' }.data.first
|
29
|
+
hostname = archive.things.find { |x| x.type == 'hostname' }.data.first.chomp
|
30
30
|
|
31
31
|
{
|
32
32
|
host: hostname,
|
data/lib/greenhat/cli.rb
CHANGED
@@ -169,8 +169,6 @@ module GreenHat
|
|
169
169
|
def self.did_you_mean
|
170
170
|
dictionary = current_methods + current_submodules + cmd_list
|
171
171
|
|
172
|
-
# all.select! { |x| x.include? cmd }
|
173
|
-
|
174
172
|
all = DidYouMean::SpellChecker.new(dictionary: dictionary).correct(cmd)
|
175
173
|
|
176
174
|
if all.empty?
|
@@ -0,0 +1,140 @@
|
|
1
|
+
quiet!
|
2
|
+
|
3
|
+
puts '**OS**'
|
4
|
+
br
|
5
|
+
|
6
|
+
puts '```'
|
7
|
+
cat 'hostname' do |data|
|
8
|
+
"Hostname: #{data.join}"
|
9
|
+
end
|
10
|
+
|
11
|
+
info 'etc/os-release' do |data|
|
12
|
+
ident = "[#{data.ID}] "
|
13
|
+
pretty_name = data.PRETTY_NAME
|
14
|
+
" Distro: #{ident} #{pretty_name}"
|
15
|
+
end
|
16
|
+
|
17
|
+
cat 'uname' do |data|
|
18
|
+
value, build = data.first.split[2].split('-')
|
19
|
+
build = "(#{build})"
|
20
|
+
" Kernel: #{value} #{build}"
|
21
|
+
end
|
22
|
+
|
23
|
+
cat 'uptime' do |data|
|
24
|
+
init = data.join.split(', load average').first.strip.split('up ', 2).last
|
25
|
+
" Uptime: #{init}"
|
26
|
+
end
|
27
|
+
|
28
|
+
# Load Average
|
29
|
+
info 'lscpu' do |data|
|
30
|
+
uptime = archive.thing? 'uptime'
|
31
|
+
return unless uptime
|
32
|
+
|
33
|
+
cpu_count = data['CPU(s)'].to_i
|
34
|
+
intervals = uptime.data.first.split('load average: ', 2).last.split(', ').map(&:to_f)
|
35
|
+
|
36
|
+
intervals_text = intervals.map do |interval|
|
37
|
+
value = percent(interval, cpu_count)
|
38
|
+
[
|
39
|
+
interval,
|
40
|
+
' (',
|
41
|
+
"#{value}%",
|
42
|
+
')'
|
43
|
+
].join
|
44
|
+
end
|
45
|
+
|
46
|
+
" LoadAvg: [CPU #{cpu_count}] #{intervals_text.join(', ')}"
|
47
|
+
end
|
48
|
+
puts '```'
|
49
|
+
|
50
|
+
br
|
51
|
+
puts '**Memory**'
|
52
|
+
br
|
53
|
+
|
54
|
+
puts '```'
|
55
|
+
info('free_m', false) do |data|
|
56
|
+
free = data.first
|
57
|
+
|
58
|
+
unless free.total.blank?
|
59
|
+
size = number_to_human_size(free.total.to_i * (1024**2))
|
60
|
+
puts " #{ljust('Total', 12)} #{size}"
|
61
|
+
end
|
62
|
+
|
63
|
+
unless free.used.blank?
|
64
|
+
size = number_to_human_size(free.used.to_i * (1024**2))
|
65
|
+
|
66
|
+
puts " #{ljust('Used', 12)} #{size}"
|
67
|
+
end
|
68
|
+
|
69
|
+
unless free.free.blank?
|
70
|
+
size = number_to_human_size(free.free.to_i * (1024**2))
|
71
|
+
puts " #{ljust('Free', 12)} #{size}"
|
72
|
+
end
|
73
|
+
|
74
|
+
unless free.available.blank?
|
75
|
+
size = number_to_human_size(free.available.to_i * (1024**2))
|
76
|
+
puts " #{ljust('Available', 12)} #{size}"
|
77
|
+
end
|
78
|
+
|
79
|
+
# br
|
80
|
+
# data.map { |x| GreenHat::Memory.memory_row x }.each do |row|
|
81
|
+
# puts row
|
82
|
+
# end
|
83
|
+
end
|
84
|
+
puts '```'
|
85
|
+
|
86
|
+
br
|
87
|
+
puts '**Disks**'
|
88
|
+
br
|
89
|
+
|
90
|
+
puts '```'
|
91
|
+
info 'df_hT' do |data|
|
92
|
+
GreenHat::Disk.markdown_format(data, false, 3)
|
93
|
+
end
|
94
|
+
puts '```'
|
95
|
+
|
96
|
+
br
|
97
|
+
puts '**GitLab**'
|
98
|
+
info 'gitlab/version-manifest.json' do |data|
|
99
|
+
"Version: #{data.build_version}"
|
100
|
+
end
|
101
|
+
|
102
|
+
br
|
103
|
+
|
104
|
+
info 'gitlab_status' do
|
105
|
+
GreenHat::GitLab.services_markdown(archive)
|
106
|
+
end
|
107
|
+
|
108
|
+
br
|
109
|
+
puts '**Errors**'
|
110
|
+
br
|
111
|
+
|
112
|
+
puts '```'
|
113
|
+
query 'gitlab-rails/production_json.log --status=500' do |data|
|
114
|
+
ljust('Production', 14) + data.count.to_s
|
115
|
+
end
|
116
|
+
|
117
|
+
query 'gitlab-rails/application_json.log --message!="Cannot obtain an exclusive lease" --severity=error' do |data|
|
118
|
+
ljust('Application', 14) + data.count.to_s
|
119
|
+
end
|
120
|
+
|
121
|
+
query 'sidekiq/current --severity=error' do |data|
|
122
|
+
ljust('Sidekiq', 14) + data.count.to_s
|
123
|
+
end
|
124
|
+
|
125
|
+
query 'gitlab-rails/api_json.log --status=500' do |data|
|
126
|
+
ljust('API', 14) + data.count.to_s
|
127
|
+
end
|
128
|
+
|
129
|
+
query 'gitaly/current --level=error' do |data|
|
130
|
+
ljust('Gitaly', 14) + data.count.to_s
|
131
|
+
end
|
132
|
+
|
133
|
+
query 'gitlab-workhorse/current --level=error' do |data|
|
134
|
+
ljust('Workhorse', 14) + data.count.to_s
|
135
|
+
end
|
136
|
+
|
137
|
+
query 'gitlab-rails/exceptions_json.log' do |data|
|
138
|
+
ljust('Exceptions', 14) + data.count.to_s
|
139
|
+
end
|
140
|
+
puts '```'
|
@@ -29,6 +29,17 @@ module GreenHat
|
|
29
29
|
path = "#{File.dirname(__FILE__)}/reports"
|
30
30
|
Dir["#{path}/*.rb"] + Dir["#{GreenHat::Settings.reports_dir}/*.rb"]
|
31
31
|
end
|
32
|
+
|
33
|
+
# Collect everything from Built-in and local reports
|
34
|
+
def self.auto_complete_list
|
35
|
+
path = "#{File.dirname(__FILE__)}/reports"
|
36
|
+
list = Dir["#{path}/*.rb"] + Dir["#{GreenHat::Settings.reports_dir}/*.rb"]
|
37
|
+
|
38
|
+
list.map do |entry|
|
39
|
+
File.basename(entry, '.rb')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
# --
|
32
43
|
end
|
33
44
|
end
|
34
45
|
end
|
data/lib/greenhat/settings.rb
CHANGED
@@ -82,8 +82,8 @@ module GreenHat
|
|
82
82
|
# rubocop:enable Style/GuardClause
|
83
83
|
|
84
84
|
def self.start
|
85
|
-
|
86
|
-
|
85
|
+
FileUtils.mkdir_p dir
|
86
|
+
FileUtils.mkdir_p reports_dir
|
87
87
|
|
88
88
|
# Load User Settings
|
89
89
|
settings_load
|
@@ -35,7 +35,7 @@ module GreenHat
|
|
35
35
|
results = Archive.all.map { |x| GitLab.identify_node(x) }
|
36
36
|
|
37
37
|
GitLab.node_types.each do |entry|
|
38
|
-
list = results.select { |x| (x.services & entry.pattern).any? }.map(&:host).join(
|
38
|
+
list = results.select { |x| (x.services & entry.pattern).any? }.map(&:host).join("\n")
|
39
39
|
next if list.blank?
|
40
40
|
|
41
41
|
puts entry.name.pastel(:bright_green)
|
@@ -88,7 +88,6 @@ module GreenHat
|
|
88
88
|
"#{service.status}:",
|
89
89
|
service.name.ljust(pad).pastel(color),
|
90
90
|
"#{service.pid_uptime};".ljust(pad)
|
91
|
-
|
92
91
|
]
|
93
92
|
end
|
94
93
|
|
data/lib/greenhat/shell/query.rb
CHANGED
@@ -215,7 +215,7 @@ module GreenHat
|
|
215
215
|
results = filter_pluck(results, flags[:pluck]) if flags.key?(:pluck)
|
216
216
|
|
217
217
|
# Total Counter
|
218
|
-
|
218
|
+
results = ShellHelper.total_count(results, flags) if flags.key?(:total)
|
219
219
|
|
220
220
|
results
|
221
221
|
end
|
@@ -10,6 +10,20 @@ module GreenHat
|
|
10
10
|
module Shell
|
11
11
|
# Logs
|
12
12
|
module Reports
|
13
|
+
def self.auto_complete(_list, word)
|
14
|
+
matches = GreenHat::ShellHelper::Reports.auto_complete_list.select do |x|
|
15
|
+
x.include? word
|
16
|
+
end
|
17
|
+
|
18
|
+
if matches.count > 1
|
19
|
+
puts "#{'Report Options:'.pastel(:bright_blue)} #{matches.join(' ').pastel(:bright_green)}"
|
20
|
+
|
21
|
+
Cli.common_substr(matches.map(&:to_s))
|
22
|
+
elsif matches.count == 1
|
23
|
+
matches.first
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
13
27
|
# Easy Show All
|
14
28
|
def self.ls(raw = [])
|
15
29
|
filter, _flags, _args = Args.parse(raw)
|
@@ -224,22 +224,6 @@ module GreenHat
|
|
224
224
|
|
225
225
|
# Total Count Helper
|
226
226
|
def self.total_count(results, flags)
|
227
|
-
# Support Combine Helper
|
228
|
-
# TODO I Believe this should be removed now
|
229
|
-
# total_count_hash(results, flags) if results.instance_of? Hash
|
230
|
-
|
231
|
-
total_count_array(results, flags) if results.instance_of? Array
|
232
|
-
end
|
233
|
-
|
234
|
-
# Hash Iteration
|
235
|
-
def self.total_count_hash(results, flags)
|
236
|
-
results.flat_map do |k, values|
|
237
|
-
[k, total_count_array(values, flags)]
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
# List Calculation
|
242
|
-
def self.total_count_array(results, flags)
|
243
227
|
# Option to only return the count
|
244
228
|
return results.count if flags[:total] == 'simple'
|
245
229
|
|
@@ -257,9 +241,39 @@ module GreenHat
|
|
257
241
|
# Hide empty results
|
258
242
|
output.reject! { |_k, v| v.blank? }
|
259
243
|
|
260
|
-
|
244
|
+
[output]
|
261
245
|
end
|
262
246
|
|
247
|
+
# TODO: Clean up -- Verify these aren't needed
|
248
|
+
# Hash Iteration
|
249
|
+
# def self.total_count_hash(results, flags)
|
250
|
+
# results.flat_map do |k, values|
|
251
|
+
# [k, total_count_array(values, flags)]
|
252
|
+
# end
|
253
|
+
# end
|
254
|
+
|
255
|
+
# List Calculation
|
256
|
+
# def self.total_count_array(results, flags)
|
257
|
+
# # Option to only return the count
|
258
|
+
# return results.count if flags[:total] == 'simple'
|
259
|
+
|
260
|
+
# output = {}
|
261
|
+
# output[:total] = results.count
|
262
|
+
# output[:duration] = Query.calculate_duration(results)
|
263
|
+
|
264
|
+
# # Sort / Get first and Last
|
265
|
+
# list = results.select(&:time).map(&:time)
|
266
|
+
# unless list.blank?
|
267
|
+
# output[:start] = list.first
|
268
|
+
# output[:end] = list.last
|
269
|
+
# end
|
270
|
+
|
271
|
+
# # Hide empty results
|
272
|
+
# output.reject! { |_k, v| v.blank? }
|
273
|
+
|
274
|
+
# render_table(output, flags)
|
275
|
+
# end
|
276
|
+
|
263
277
|
# Table Printer Helper
|
264
278
|
def self.fields_print(results)
|
265
279
|
results.each do |k, v|
|
data/lib/greenhat/shell.rb
CHANGED
@@ -89,6 +89,18 @@ module GreenHat
|
|
89
89
|
Shell::Cat.default ['uptime']
|
90
90
|
end
|
91
91
|
|
92
|
+
def self.ip_address
|
93
|
+
Shell::Cat.default ['ip_address']
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.ifconfig
|
97
|
+
Shell::Cat.default ['ifconfig']
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.gitlab_rb
|
101
|
+
Shell::Cat.default ['gitlab/gitlab.rb', '--page']
|
102
|
+
end
|
103
|
+
|
92
104
|
def self.hostname
|
93
105
|
Shell::Cat.default ['hostname']
|
94
106
|
end
|
@@ -18,6 +18,18 @@ module GreenHat
|
|
18
18
|
module FileTypes
|
19
19
|
def types
|
20
20
|
{
|
21
|
+
'ifconfig' => {
|
22
|
+
format: :raw,
|
23
|
+
pattern: [
|
24
|
+
/ifconfig/
|
25
|
+
]
|
26
|
+
},
|
27
|
+
'ip_address' => {
|
28
|
+
format: :raw,
|
29
|
+
pattern: [
|
30
|
+
/ip_address/
|
31
|
+
]
|
32
|
+
},
|
21
33
|
'cpuinfo' => {
|
22
34
|
format: :raw,
|
23
35
|
pattern: [
|
@@ -103,6 +115,12 @@ module GreenHat
|
|
103
115
|
/getenforce/
|
104
116
|
]
|
105
117
|
},
|
118
|
+
'gitlab.rb' => {
|
119
|
+
format: :raw,
|
120
|
+
pattern: [
|
121
|
+
%r{gitlab/gitlab.rb}
|
122
|
+
]
|
123
|
+
},
|
106
124
|
'geo-logcursor/current' => {
|
107
125
|
format: :raw,
|
108
126
|
pattern: [
|
@@ -707,6 +725,12 @@ module GreenHat
|
|
707
725
|
%r{gitlab-rails/gitlab-rails-db-migrate.*}
|
708
726
|
]
|
709
727
|
},
|
728
|
+
'rpm_verify' => {
|
729
|
+
format: :raw,
|
730
|
+
pattern: [
|
731
|
+
/rpm_verify/
|
732
|
+
]
|
733
|
+
},
|
710
734
|
'tainted' => {
|
711
735
|
format: :raw,
|
712
736
|
pattern: [
|
data/lib/greenhat/version.rb
CHANGED
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.6.
|
4
|
+
version: 0.6.3
|
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-
|
11
|
+
date: 2022-07-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: amazing_print
|
@@ -478,6 +478,7 @@ files:
|
|
478
478
|
- lib/greenhat/reports/reports/errors.rb
|
479
479
|
- lib/greenhat/reports/reports/faststats.rb
|
480
480
|
- lib/greenhat/reports/reports/full.rb
|
481
|
+
- lib/greenhat/reports/reports/full_markdown.rb
|
481
482
|
- lib/greenhat/reports/runner.rb
|
482
483
|
- lib/greenhat/reports/shared.rb
|
483
484
|
- lib/greenhat/reports/shell_helper.rb
|
@@ -503,7 +504,6 @@ files:
|
|
503
504
|
- lib/greenhat/shell/platform.rb
|
504
505
|
- lib/greenhat/shell/process.rb
|
505
506
|
- lib/greenhat/shell/query.rb
|
506
|
-
- lib/greenhat/shell/report.rb
|
507
507
|
- lib/greenhat/shell/reports.rb
|
508
508
|
- lib/greenhat/shell/shell_helper.rb
|
509
509
|
- lib/greenhat/thing.rb
|
@@ -1,415 +0,0 @@
|
|
1
|
-
# Deprecated in favor of reports module
|
2
|
-
# TODO: Remove
|
3
|
-
# module GreenHat
|
4
|
-
# # Root Level Shell / Report Helper
|
5
|
-
# module Shell
|
6
|
-
# def self.report(raw)
|
7
|
-
|
8
|
-
# _files, flags, _args = Args.parse(raw)
|
9
|
-
|
10
|
-
# archives = if flags.archive
|
11
|
-
# Archive.all.select do |archive|
|
12
|
-
# flags.archive.any? { |x| archive.name.include? x.to_s }
|
13
|
-
# end
|
14
|
-
# else
|
15
|
-
# Archive.all
|
16
|
-
# end
|
17
|
-
|
18
|
-
# output = archives.map { |x| x.report(flags) }.map(&:show).flatten
|
19
|
-
|
20
|
-
# flags[:page] = true if flags.full && !flags.raw
|
21
|
-
|
22
|
-
# ShellHelper.show(output, flags)
|
23
|
-
# end
|
24
|
-
# end
|
25
|
-
# end
|
26
|
-
|
27
|
-
# module GreenHat
|
28
|
-
# # Report Generator Helper
|
29
|
-
#
|
30
|
-
# class Report
|
31
|
-
# include ActionView::Helpers::NumberHelper
|
32
|
-
|
33
|
-
# attr_accessor :archive, :flags, :host, :os_release, :selinux_status, :cpu, :uname,
|
34
|
-
# :timedatectl, :uptime, :meminfo, :gitlab_manifest, :gitlab_status,
|
35
|
-
# :production_log, :api_log, :sidekiq_log,
|
36
|
-
# :exceptions_log, :gitaly_log, :free_m, :disk_free
|
37
|
-
|
38
|
-
# # Find Needed Files for Report
|
39
|
-
#
|
40
|
-
# def initialize(archive, flags)
|
41
|
-
# self.archive = archive
|
42
|
-
# self.flags = flags
|
43
|
-
# self.host = archive.things.find { |x| x.name == 'hostname' }
|
44
|
-
# self.os_release = archive.things.find { |x| x.name == 'etc/os-release' }
|
45
|
-
# self.selinux_status = archive.things.find { |x| x.name == 'sestatus' }
|
46
|
-
# self.cpu = archive.things.find { |x| x.name == 'lscpu' }
|
47
|
-
# self.uname = archive.things.find { |x| x.name == 'uname' }
|
48
|
-
# self.timedatectl = archive.things.find { |x| x.name == 'timedatectl' }
|
49
|
-
# self.uptime = archive.things.find { |x| x.name == 'uptime' }
|
50
|
-
# self.meminfo = archive.things.find { |x| x.name == 'meminfo' }
|
51
|
-
# self.free_m = archive.things.find { |x| x.name == 'free_m' }
|
52
|
-
# self.gitlab_manifest = archive.things.find { |x| x.name == 'gitlab/version-manifest.json' }
|
53
|
-
# self.gitlab_status = archive.things.find { |x| x.name == 'gitlab_status' }
|
54
|
-
# self.production_log = archive.things.find { |x| x.name == 'gitlab-rails/production_json.log' }
|
55
|
-
# self.api_log = archive.things.find { |x| x.name == 'gitlab-rails/api_json.log' }
|
56
|
-
# self.exceptions_log = archive.things.find { |x| x.name == 'gitlab-rails/exceptions_json.log' }
|
57
|
-
# self.gitaly_log = archive.things.find { |x| x.name == 'gitaly/current' }
|
58
|
-
# self.sidekiq_log = archive.things.find { |x| x.name == 'sidekiq/current' }
|
59
|
-
# self.disk_free = archive.things.find { |x| x.name == 'df_hT' }
|
60
|
-
# end
|
61
|
-
|
62
|
-
# def show
|
63
|
-
# output = [
|
64
|
-
# archive.friendly_name.pastel(:blue)
|
65
|
-
# ]
|
66
|
-
|
67
|
-
# # OS
|
68
|
-
# output << 'OS'.pastel(:bright_yellow)
|
69
|
-
# output << hostname if host
|
70
|
-
# output << distro if os_release
|
71
|
-
# output << selinux if selinux_status
|
72
|
-
# # output << arch if cpu
|
73
|
-
# output << kernel if uname
|
74
|
-
# output << sys_time if timedatectl
|
75
|
-
# output << sys_uptime if uptime
|
76
|
-
# output << load_average if uptime && cpu
|
77
|
-
# output << ''
|
78
|
-
|
79
|
-
# # Memory
|
80
|
-
# if meminfo || free_m
|
81
|
-
# output << 'Memory'.pastel(:bright_yellow)
|
82
|
-
# output << memory_perc if meminfo
|
83
|
-
# output << memory_free if free_m
|
84
|
-
# output << ''
|
85
|
-
# end
|
86
|
-
|
87
|
-
# # Disk
|
88
|
-
# if disk_free
|
89
|
-
# output << disks
|
90
|
-
# output << ''
|
91
|
-
# end
|
92
|
-
|
93
|
-
# # Gitlab
|
94
|
-
# output << 'GitLab'.pastel(:bright_yellow) if gitlab_manifest
|
95
|
-
# output << gitlab_version if gitlab_manifest
|
96
|
-
# output << gitlab_services if gitlab_status
|
97
|
-
# output << title('Errors') if production_log || api_log || sidekiq_log
|
98
|
-
# output << production_errors if production_log
|
99
|
-
# output << application_errors if archive.thing?('gitlab-rails/application_json.log')
|
100
|
-
# output << sidekiq_errors if sidekiq_log
|
101
|
-
# output << api_errors if api_log
|
102
|
-
# output << exception_errors if exceptions_log
|
103
|
-
# output << gitaly_errors if gitaly_log
|
104
|
-
# output << workhorse_errors if archive.thing?('gitlab-workhorse/current')
|
105
|
-
|
106
|
-
# full(output) if flags.full
|
107
|
-
|
108
|
-
# # Final Space / Return
|
109
|
-
# output << ''
|
110
|
-
# output
|
111
|
-
# end
|
112
|
-
# # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
|
113
|
-
|
114
|
-
# def full(output)
|
115
|
-
# output << ''
|
116
|
-
# output << 'FastStats Top'
|
117
|
-
# Shell::Faststats.top(['--raw'], true).each { |x| output << x } # Page Row Helper
|
118
|
-
# output << ''
|
119
|
-
|
120
|
-
# output << 'FastStats Errors'
|
121
|
-
# Shell::Faststats.errors(['--raw'], true).each { |x| output << x } # Page Row Helper
|
122
|
-
# output << ''
|
123
|
-
# end
|
124
|
-
|
125
|
-
# def exception_errors
|
126
|
-
# count = exceptions_log.data.count
|
127
|
-
# color = count.zero? ? :green : :red
|
128
|
-
|
129
|
-
# [
|
130
|
-
# title(' Exception', :bright_red, 18),
|
131
|
-
# count.to_s.pastel(color)
|
132
|
-
# ].join
|
133
|
-
# end
|
134
|
-
|
135
|
-
# def workhorse_errors
|
136
|
-
# results = ShellHelper.filter_internal([
|
137
|
-
# 'gitlab-workhorse/current',
|
138
|
-
# '--level=error',
|
139
|
-
# "--archive=#{archive.name}"
|
140
|
-
# ].join(' '))
|
141
|
-
|
142
|
-
# color = results.count.zero? ? :green : :red
|
143
|
-
|
144
|
-
# [
|
145
|
-
# title(' Workhorse', :bright_red, 18),
|
146
|
-
# results.count.to_s.pastel(color)
|
147
|
-
# ].join
|
148
|
-
# end
|
149
|
-
|
150
|
-
# def gitaly_errors
|
151
|
-
# count = gitaly_log.data.count { |x| x.level == 'error' }
|
152
|
-
# color = count.zero? ? :green : :red
|
153
|
-
|
154
|
-
# [
|
155
|
-
# title(' Gitaly', :bright_red, 18),
|
156
|
-
# count.to_s.pastel(color)
|
157
|
-
# ].join
|
158
|
-
# end
|
159
|
-
|
160
|
-
# def production_errors
|
161
|
-
# count = production_log.data.count { |x| x.status == 500 }
|
162
|
-
# color = count.zero? ? :green : :red
|
163
|
-
|
164
|
-
# [
|
165
|
-
# title(' Production', :bright_red, 18),
|
166
|
-
# count.to_s.pastel(color)
|
167
|
-
# ].join
|
168
|
-
# end
|
169
|
-
|
170
|
-
# def api_errors
|
171
|
-
# count = api_log.data.count { |x| x.status == 500 }
|
172
|
-
# color = count.zero? ? :green : :red
|
173
|
-
|
174
|
-
# [
|
175
|
-
# title(' API', :bright_red, 18),
|
176
|
-
# count.to_s.pastel(color)
|
177
|
-
# ].join
|
178
|
-
# end
|
179
|
-
|
180
|
-
# def application_errors
|
181
|
-
# results = ShellHelper.filter_internal([
|
182
|
-
# 'gitlab-rails/application_json.log',
|
183
|
-
# '--message!="Cannot obtain an exclusive lease"',
|
184
|
-
# '--severity=error',
|
185
|
-
# "--archive=#{archive.name}"
|
186
|
-
# ].join(' '))
|
187
|
-
|
188
|
-
# count = results.count { |x| x&.severity == 'ERROR' }
|
189
|
-
# color = count.zero? ? :green : :red
|
190
|
-
|
191
|
-
# [
|
192
|
-
# title(' Application', :bright_red, 18),
|
193
|
-
# count.to_s.pastel(color)
|
194
|
-
# ].join
|
195
|
-
# end
|
196
|
-
|
197
|
-
# def sidekiq_errors
|
198
|
-
# count = sidekiq_log.data.count { |x| x&.severity == 'ERROR' }
|
199
|
-
# color = count.zero? ? :green : :red
|
200
|
-
|
201
|
-
# [
|
202
|
-
# title(' Sidekiq', :bright_red, 18),
|
203
|
-
# count.to_s.pastel(color)
|
204
|
-
# ].join
|
205
|
-
# end
|
206
|
-
|
207
|
-
# def gitlab_services
|
208
|
-
# [
|
209
|
-
# title('Services'),
|
210
|
-
# "\n ",
|
211
|
-
# GitLab.services(archive, 3)
|
212
|
-
# ].join
|
213
|
-
# rescue StandardError => e
|
214
|
-
# LogBot.fatal('GitLab Services', message: e.message, backtrace: e.backtrace.first)
|
215
|
-
# end
|
216
|
-
|
217
|
-
# def gitlab_version
|
218
|
-
# [
|
219
|
-
# title('Version'),
|
220
|
-
# gitlab_manifest.data.build_version
|
221
|
-
# ].join
|
222
|
-
# end
|
223
|
-
|
224
|
-
# def hostname
|
225
|
-
# [
|
226
|
-
# title('Hostname'),
|
227
|
-
# host.data.first
|
228
|
-
# ].join
|
229
|
-
# end
|
230
|
-
|
231
|
-
# def distro
|
232
|
-
# [
|
233
|
-
# title('Distro'),
|
234
|
-
# "[#{os_release.data.ID}] ".pastel(:bright_black),
|
235
|
-
# os_release.data.PRETTY_NAME
|
236
|
-
# ].join
|
237
|
-
# end
|
238
|
-
|
239
|
-
# def selinux
|
240
|
-
# return nil if selinux_status.data.nil?
|
241
|
-
|
242
|
-
# status = selinux_status.data['SELinux status']
|
243
|
-
# status_color = status == 'enabled' ? :green : :red
|
244
|
-
|
245
|
-
# [
|
246
|
-
# title('SeLinux'),
|
247
|
-
# status.pastel(status_color),
|
248
|
-
# ' (',
|
249
|
-
# selinux_status.data['Current mode'],
|
250
|
-
# ')'
|
251
|
-
# ].join
|
252
|
-
# end
|
253
|
-
|
254
|
-
# def arch
|
255
|
-
# [
|
256
|
-
# title('Arch'),
|
257
|
-
# cpu.data.Architecture
|
258
|
-
# ].join
|
259
|
-
# end
|
260
|
-
|
261
|
-
# def kernel
|
262
|
-
# # TODO: Better way to consistently get uname info?
|
263
|
-
# value, build = uname.data.first.split[2].split('-')
|
264
|
-
# [
|
265
|
-
# title('Kernel'),
|
266
|
-
# value,
|
267
|
-
# " (#{build})".pastel(:bright_black)
|
268
|
-
# ].join
|
269
|
-
# end
|
270
|
-
|
271
|
-
# # Helper for finding if NTP is enabled
|
272
|
-
# def ntp_keys
|
273
|
-
# [
|
274
|
-
# 'Network time on', 'NTP enabled', 'NTP service', 'System clock synchronized'
|
275
|
-
# ]
|
276
|
-
# end
|
277
|
-
|
278
|
-
# def sys_time
|
279
|
-
# # Ignore if Empty
|
280
|
-
# return false if timedatectl.data.nil?
|
281
|
-
|
282
|
-
# ntp_statuses = timedatectl.data.slice(*ntp_keys).values.compact
|
283
|
-
|
284
|
-
# enabled = %w[active yes] & ntp_statuses
|
285
|
-
# ntp_status = ntp_statuses.first
|
286
|
-
# ntp_color = enabled.empty? ? :red : :green
|
287
|
-
|
288
|
-
# # Fall Back
|
289
|
-
# ntp_status ||= 'unknown'
|
290
|
-
|
291
|
-
# [
|
292
|
-
# title('Sys Time'),
|
293
|
-
# timedatectl.data['Local time'],
|
294
|
-
# ' (ntp: '.pastel(:bright_black),
|
295
|
-
# ntp_status.pastel(ntp_color),
|
296
|
-
# ')'.pastel(:bright_black)
|
297
|
-
# ].join
|
298
|
-
# end
|
299
|
-
|
300
|
-
# # Strip/Simplify Uptime
|
301
|
-
# def sys_uptime
|
302
|
-
# init = uptime.data.first.split(', load average').first.strip
|
303
|
-
|
304
|
-
# [
|
305
|
-
# title('Uptime'),
|
306
|
-
# init.split('up ', 2).last
|
307
|
-
# ].join
|
308
|
-
# end
|
309
|
-
|
310
|
-
# def load_average
|
311
|
-
# cpu_count = cpu.data['CPU(s)'].to_i
|
312
|
-
# intervals = uptime.data.first.split('load average: ', 2).last.split(', ').map(&:to_f)
|
313
|
-
|
314
|
-
# # Generate Colorized Text for Output
|
315
|
-
# intervals_text = intervals.map do |interval|
|
316
|
-
# value = percent(interval, cpu_count)
|
317
|
-
# color = value > 100 ? :red : :green
|
318
|
-
# [
|
319
|
-
# interval,
|
320
|
-
# ' (',
|
321
|
-
# "#{value}%".pastel(color),
|
322
|
-
# ')'
|
323
|
-
# ].join
|
324
|
-
# end
|
325
|
-
|
326
|
-
# [
|
327
|
-
# title('LoadAvg'),
|
328
|
-
# "[CPU #{cpu_count}] ".pastel(:bright_white),
|
329
|
-
# intervals_text.join(', ')
|
330
|
-
# ].join
|
331
|
-
# end
|
332
|
-
|
333
|
-
# def memory_perc
|
334
|
-
# total = ShellHelper.human_size_to_number(meminfo.data['MemTotal'])
|
335
|
-
# free = ShellHelper.human_size_to_number(meminfo.data['MemFree'])
|
336
|
-
# used = percent((total - free), total)
|
337
|
-
|
338
|
-
# [
|
339
|
-
# title('Usage'),
|
340
|
-
# ' ['.pastel(:bright_black),
|
341
|
-
# '='.pastel(:green) * (used / 2),
|
342
|
-
# ' ' * (50 - (used / 2)),
|
343
|
-
# ']'.pastel(:bright_black),
|
344
|
-
# " #{100 - percent(free, total)}%".pastel(:green) # Inverse
|
345
|
-
# ].join
|
346
|
-
# end
|
347
|
-
|
348
|
-
# def memory_free
|
349
|
-
# free = free_m.data.find { |x| x.kind == 'Mem' }
|
350
|
-
|
351
|
-
# return unless free
|
352
|
-
|
353
|
-
# formatted_mem = free_m.data.map { |x| GreenHat::Memory.memory_row x }
|
354
|
-
|
355
|
-
# output = []
|
356
|
-
# unless free.total.blank?
|
357
|
-
# output << title('Total', :cyan, 14)
|
358
|
-
# output << number_to_human_size(free.total.to_i * (1024**2))
|
359
|
-
# output << "\n"
|
360
|
-
# end
|
361
|
-
|
362
|
-
# unless free.total.blank?
|
363
|
-
# output << title('Used', :yellow, 14)
|
364
|
-
# output << number_to_human_size(free.used.to_i * (1024**2))
|
365
|
-
# output << "\n"
|
366
|
-
# end
|
367
|
-
|
368
|
-
# unless free.total.blank?
|
369
|
-
# output << title('Free', :blue, 14)
|
370
|
-
# output << number_to_human_size(free.free.to_i * (1024**2))
|
371
|
-
# output << "\n"
|
372
|
-
# end
|
373
|
-
|
374
|
-
# unless free.total.blank?
|
375
|
-
# output << title('Available', :green, 14)
|
376
|
-
# output << number_to_human_size(free.available.to_i * (1024**2))
|
377
|
-
# output << "\n"
|
378
|
-
# end
|
379
|
-
|
380
|
-
# output << "\n"
|
381
|
-
# output << formatted_mem.map { |x| x.prepend ' ' * 2 }.join("\n")
|
382
|
-
|
383
|
-
# output.join
|
384
|
-
# rescue StandardError => e
|
385
|
-
# LogBot.fatal('Memory', message: e.message, backtrace: e.backtrace.first)
|
386
|
-
# end
|
387
|
-
|
388
|
-
# def disks
|
389
|
-
# # GreenHat::Disk.df({archive: []})
|
390
|
-
# file = GreenHat::Disk.df({ archive: [archive.name] })
|
391
|
-
|
392
|
-
# disk_list = GreenHat::Disk.format_output(file.first, false, 3)
|
393
|
-
|
394
|
-
# # Preapre / Indent List
|
395
|
-
# [
|
396
|
-
# 'Disks'.pastel(:bright_yellow) + ' (Top % Usage)'.pastel(:bright_black),
|
397
|
-
# "\n",
|
398
|
-
# disk_list.each { |x| x.prepend(' ' * 4) }.join("\n")
|
399
|
-
# ].join
|
400
|
-
# end
|
401
|
-
|
402
|
-
# # ----------------------------
|
403
|
-
# # Helpers
|
404
|
-
# # ----------------------------
|
405
|
-
# def percent(value, total)
|
406
|
-
# ((value / total.to_f) * 100).round
|
407
|
-
# end
|
408
|
-
|
409
|
-
# # Helper to Make Cyan Titles
|
410
|
-
# def title(name, color = :cyan, ljust = 12)
|
411
|
-
# " #{name}:".ljust(ljust).pastel(color)
|
412
|
-
# end
|
413
|
-
# end
|
414
|
-
# # rubocop:enable Metrics/ClassLength
|
415
|
-
# end
|