panda-motd 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/panda_motd/component_error.rb +14 -0
- data/lib/panda_motd/components/ascii_text_art.rb +15 -4
- data/lib/panda_motd/components/filesystems.rb +120 -0
- data/lib/panda_motd/components/service_status.rb +17 -50
- data/lib/panda_motd/components/ssl_certificates.rb +85 -0
- data/lib/panda_motd/components/uptime.rb +5 -2
- data/lib/panda_motd/config.rb +13 -3
- data/lib/panda_motd/default_config.yaml +87 -21
- data/lib/panda_motd/motd.rb +10 -9
- data/lib/panda_motd/version.rb +1 -1
- metadata +19 -3
- data/lib/panda_motd/component.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 324ec514bbb141949c82866eed44d830d6f0f768824f42cda912f872f205bdc8
|
4
|
+
data.tar.gz: 867433a26a6277120037b51c7f16b0eb6cb32edac085f1f245048c7097148829
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bec0220f18e5b3c5c2f32958ba93cd463efe92ce87dee363b9dd5ee2aec2ab7579b3ce1cc6794dae483f82b8b8ba38d15d974ef77a8bb91b2524fd5ff12a4180
|
7
|
+
data.tar.gz: 71e8cba32a1936bdf7304c296364ef2dc2aeb9cce2f4a9fb747db3bd97bee4f4ae8c5c4130ca0c6abc9a719f78ad01f98215b4ede31b72d48736e7c871a36fc2
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'colorize'
|
2
|
+
|
3
|
+
class ComponentError
|
4
|
+
attr_reader :component, :message
|
5
|
+
|
6
|
+
def initialize(component, message)
|
7
|
+
@component = component
|
8
|
+
@message = message
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
return "#{@component.name} error: ".red + @message.to_s
|
13
|
+
end
|
14
|
+
end
|
@@ -1,18 +1,29 @@
|
|
1
1
|
require 'artii'
|
2
2
|
require 'colorize'
|
3
3
|
|
4
|
-
class
|
4
|
+
class ASCIITextArt
|
5
|
+
attr_reader :name, :errors, :results
|
6
|
+
|
5
7
|
def initialize(motd)
|
8
|
+
@name = 'ascii_text_art'
|
6
9
|
@motd = motd
|
7
|
-
@config = motd.config.component_config(
|
10
|
+
@config = motd.config.component_config(@name)
|
11
|
+
@errors = []
|
8
12
|
end
|
9
13
|
|
10
14
|
def process
|
11
15
|
@text = `hostname`
|
12
|
-
|
16
|
+
|
17
|
+
begin
|
18
|
+
@art = Artii::Base.new font: @config['font']
|
19
|
+
@results = @art.asciify(@text)
|
20
|
+
@results = @results.send(@config['color'].to_sym) if @config['color']
|
21
|
+
rescue Errno::EISDIR # Artii doesn't handle invalid font names very well
|
22
|
+
@errors << ComponentError.new(self, 'Invalid font name')
|
23
|
+
end
|
13
24
|
end
|
14
25
|
|
15
26
|
def to_s
|
16
|
-
return @
|
27
|
+
return @results
|
17
28
|
end
|
18
29
|
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'ruby-units'
|
2
|
+
require 'colorize'
|
3
|
+
|
4
|
+
class Filesystems
|
5
|
+
attr_reader :name, :errors
|
6
|
+
attr_reader :results
|
7
|
+
|
8
|
+
def initialize(motd)
|
9
|
+
@name = 'filesystems'
|
10
|
+
@motd = motd
|
11
|
+
@config = motd.config.component_config(@name)
|
12
|
+
@errors = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def process
|
16
|
+
@results = parse_filesystem_usage(@config['filesystems'])
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
name_col_size = @results.select { |r| r.is_a? Hash }.map { |r| r[:pretty_name].length }.max
|
21
|
+
name_col_size = 0 if name_col_size.nil?
|
22
|
+
|
23
|
+
name_col_size_with_padding = (name_col_size + 6) > 13 ? (name_col_size + 6) : 13
|
24
|
+
|
25
|
+
result = 'Filesystems'.ljust(name_col_size_with_padding, ' ')
|
26
|
+
result += "Size Used Free Use%\n"
|
27
|
+
|
28
|
+
@results.each do |filesystem|
|
29
|
+
# handle filesystem not found
|
30
|
+
if filesystem.is_a? String
|
31
|
+
result += " #{filesystem}\n"
|
32
|
+
next
|
33
|
+
end
|
34
|
+
|
35
|
+
result += " #{filesystem[:pretty_name]}".ljust(name_col_size_with_padding, ' ')
|
36
|
+
|
37
|
+
[:size, :used, :avail].each do |metric|
|
38
|
+
units = if filesystem[metric] > 10**12
|
39
|
+
'terabytes'
|
40
|
+
elsif filesystem[metric] > 10**9
|
41
|
+
'gigabytes'
|
42
|
+
elsif filesystem[metric] > 10**6
|
43
|
+
'megabytes'
|
44
|
+
elsif filesystem[metric] > 10**3
|
45
|
+
'kilobytes'
|
46
|
+
else
|
47
|
+
'bytes'
|
48
|
+
end
|
49
|
+
|
50
|
+
value = Unit.new("#{filesystem[metric]} bytes").convert_to(units)
|
51
|
+
|
52
|
+
# we have 4 characters of space to include the number, a potential decimal point, and
|
53
|
+
# the unit character at the end. if the whole number component is 3+ digits long then
|
54
|
+
# we omit the decimal point and just display the whole number component. if the whole
|
55
|
+
# number component is 2 digits long, we can't afford to use a decimal point, so we still
|
56
|
+
# only display the whole number component. if the whole number component is 1 digit long,
|
57
|
+
# we use the single whole number component digit, a decimal point, a single fractional
|
58
|
+
# digit, and the unit character.
|
59
|
+
whole_number_length = value.scalar.floor.to_s.length
|
60
|
+
round_amount = whole_number_length > 1 ? 0 : 1
|
61
|
+
formatted_value = value.scalar.round(round_amount).to_s + units[0].upcase
|
62
|
+
result += formatted_value.rjust(4, ' ') + ' '
|
63
|
+
end
|
64
|
+
|
65
|
+
percentage_used = ((filesystem[:used].to_f / filesystem[:size].to_f) * 100).round
|
66
|
+
result += (percentage_used.to_s.rjust(3, ' ') + '%').send(percentage_color(percentage_used))
|
67
|
+
|
68
|
+
result += "\n"
|
69
|
+
|
70
|
+
total_ticks = name_col_size_with_padding + 18
|
71
|
+
used_ticks = (total_ticks * (percentage_used.to_f / 100)).round
|
72
|
+
|
73
|
+
result += " [#{('=' * used_ticks).send(percentage_color(percentage_used))}#{('=' * (total_ticks - used_ticks)).light_black}]\n"
|
74
|
+
end
|
75
|
+
|
76
|
+
return result
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def percentage_color(percentage)
|
82
|
+
return :green if (0..75).cover? percentage
|
83
|
+
return :yellow if (75..95).cover? percentage
|
84
|
+
return :red if (95..100).cover? percentage
|
85
|
+
return :white
|
86
|
+
end
|
87
|
+
|
88
|
+
def find_header_id_by_text(header_array, text)
|
89
|
+
return header_array.each_index.select { |i| header_array[i].downcase.include? text }.first
|
90
|
+
end
|
91
|
+
|
92
|
+
def parse_filesystem_usage(filesystems)
|
93
|
+
command_result = `BLOCKSIZE=1024 df`.split("\n")
|
94
|
+
header = command_result[0].split
|
95
|
+
entries = command_result[1..command_result.count]
|
96
|
+
|
97
|
+
name_index = find_header_id_by_text(header, 'filesystem')
|
98
|
+
size_index = find_header_id_by_text(header, 'blocks')
|
99
|
+
used_index = find_header_id_by_text(header, 'used')
|
100
|
+
avail_index = find_header_id_by_text(header, 'avail')
|
101
|
+
|
102
|
+
results = filesystems.map do |filesystem, name|
|
103
|
+
matching_entry = entries.find { |e| e.split[name_index] == filesystem }
|
104
|
+
|
105
|
+
if matching_entry
|
106
|
+
{
|
107
|
+
pretty_name: name,
|
108
|
+
filesystem_name: matching_entry.split[name_index],
|
109
|
+
size: matching_entry.split[size_index].to_i * 1024,
|
110
|
+
used: matching_entry.split[used_index].to_i * 1024,
|
111
|
+
avail: matching_entry.split[avail_index].to_i * 1024
|
112
|
+
}
|
113
|
+
else
|
114
|
+
"#{filesystem} was not found"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
return results
|
119
|
+
end
|
120
|
+
end
|
@@ -1,31 +1,30 @@
|
|
1
1
|
require 'colorize'
|
2
2
|
|
3
3
|
class ServiceStatus
|
4
|
+
attr_reader :name, :errors
|
4
5
|
attr_reader :results
|
5
6
|
|
6
7
|
def initialize(motd)
|
8
|
+
@name = 'service_status'
|
7
9
|
@motd = motd
|
8
|
-
@config = motd.config.component_config(
|
10
|
+
@config = motd.config.component_config(@name)
|
11
|
+
@errors = []
|
9
12
|
end
|
10
13
|
|
11
14
|
def process
|
12
15
|
@services = @config['services']
|
13
|
-
@results =
|
14
|
-
|
15
|
-
parse_services
|
16
|
+
@results = parse_services(@services)
|
16
17
|
end
|
17
18
|
|
18
19
|
def to_s
|
19
20
|
if @results.any?
|
20
21
|
result = "Services:\n"
|
21
22
|
longest_name_size = @results.keys.map { |k| k.to_s.length }.max + 1 # add 1 for the ':' at the end
|
22
|
-
@results.
|
23
|
-
name_part =
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
28
|
-
result += " #{name_part} #{status}\n"
|
23
|
+
@results.each_with_index do |(name, status), i|
|
24
|
+
name_part = (name.to_s + ':').ljust(longest_name_size, ' ')
|
25
|
+
status_part = status.to_s.send(service_colors[status])
|
26
|
+
result += " #{name_part} #{status_part}"
|
27
|
+
result += "\n" unless i == @results.count - 1 # don't print newline for last entry
|
29
28
|
end
|
30
29
|
|
31
30
|
return result
|
@@ -36,62 +35,30 @@ class ServiceStatus
|
|
36
35
|
|
37
36
|
private
|
38
37
|
|
39
|
-
def parse_services
|
40
|
-
case Gem::Platform.local.os
|
41
|
-
when 'darwin'
|
42
|
-
@results = parse_services_macos(@services)
|
43
|
-
when 'linux'
|
44
|
-
@results = parse_services_linux(@services)
|
45
|
-
end
|
46
|
-
|
47
|
-
return self
|
48
|
-
end
|
49
|
-
|
50
|
-
def parse_services_macos(services)
|
38
|
+
def parse_services(services)
|
51
39
|
results = {}
|
52
40
|
|
53
|
-
|
54
|
-
`brew services list`.split("\n").each do |line|
|
55
|
-
parsed_name = line.split[0]
|
56
|
-
parsed_status = line.split[1]
|
41
|
+
cmd_result = `systemctl | grep '\.service'`
|
57
42
|
|
58
|
-
|
59
|
-
|
60
|
-
if matching_service
|
61
|
-
results[parsed_name.to_sym] = parsed_status.send(macos_service_colors[parsed_status.to_sym])
|
62
|
-
end
|
43
|
+
if cmd_result.empty?
|
44
|
+
@errors << ComponentError.new(self, 'Unable to parse systemctl output')
|
63
45
|
end
|
64
46
|
|
65
|
-
|
66
|
-
end
|
67
|
-
|
68
|
-
def parse_services_linux(services)
|
69
|
-
results = {}
|
70
|
-
|
71
|
-
`systemctl | grep '\.service'`.split("\n").each do |line|
|
47
|
+
cmd_result.split("\n").each do |line|
|
72
48
|
parsed_name = line.split[0].gsub('.service', '')
|
73
49
|
parsed_status = line.split[3]
|
74
50
|
|
75
51
|
matching_service = services.find { |service, _name| service == parsed_name }
|
76
52
|
|
77
53
|
if matching_service
|
78
|
-
results[parsed_name.to_sym] = parsed_status.
|
54
|
+
results[parsed_name.to_sym] = parsed_status.to_sym
|
79
55
|
end
|
80
56
|
end
|
81
57
|
|
82
58
|
return results
|
83
59
|
end
|
84
60
|
|
85
|
-
def
|
86
|
-
return {
|
87
|
-
started: :green,
|
88
|
-
stopped: :white,
|
89
|
-
error: :red,
|
90
|
-
unknown: :yellow
|
91
|
-
}
|
92
|
-
end
|
93
|
-
|
94
|
-
def linux_service_colors
|
61
|
+
def service_colors
|
95
62
|
return {
|
96
63
|
running: :green,
|
97
64
|
exited: :white,
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
class SSLCertificates
|
4
|
+
attr_reader :name, :errors, :results
|
5
|
+
|
6
|
+
def initialize(motd)
|
7
|
+
@name = 'ssl_certificates'
|
8
|
+
@motd = motd
|
9
|
+
@config = motd.config.component_config(@name)
|
10
|
+
@errors = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def process
|
14
|
+
@certs = @config['certs']
|
15
|
+
@results = cert_dates(@certs)
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
result = "SSL Certificates:\n"
|
20
|
+
longest_name_size = @results.map { |r| r[0].length }.max
|
21
|
+
|
22
|
+
@results.each_with_index do |cert, i|
|
23
|
+
if cert.is_a? String # print the not found message
|
24
|
+
result += " #{cert}"
|
25
|
+
else
|
26
|
+
name_portion = " #{cert[0]}".ljust(longest_name_size + 6, ' ')
|
27
|
+
|
28
|
+
status = cert_status(cert[1])
|
29
|
+
|
30
|
+
date_portion = "#{cert_status_strings[status]} ".send(cert_status_colors[status]) + cert[1].strftime('%e %b %Y %H:%M:%S%p').to_s
|
31
|
+
result += name_portion + date_portion
|
32
|
+
end
|
33
|
+
|
34
|
+
result += "\n" unless i == @results.count - 1 # don't print newline for last entry
|
35
|
+
end
|
36
|
+
|
37
|
+
return result
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def cert_dates(certs)
|
43
|
+
return certs.map do |name, path|
|
44
|
+
if File.exist?(path)
|
45
|
+
cmd_result = `openssl x509 -in #{path} -dates`
|
46
|
+
parsed = cmd_result.match(/notAfter=([\w\s:]+)\n/)
|
47
|
+
if parsed.nil?
|
48
|
+
@errors << ComponentError.new(self, 'Unable to find certificate expiration date')
|
49
|
+
else
|
50
|
+
begin
|
51
|
+
expiry_date = DateTime.parse(parsed[1])
|
52
|
+
[name, expiry_date]
|
53
|
+
rescue ArgumentError
|
54
|
+
@errors << ComponentError.new(self, 'Found expiration date, but unable to parse as date')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
else
|
58
|
+
"Certificate #{name} not found at path: #{path}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def cert_status(expiry_date)
|
64
|
+
status = :valid
|
65
|
+
status = :expiring if (DateTime.now...DateTime.now + 30).cover? expiry_date # ... range excludes end
|
66
|
+
status = :expired if DateTime.now >= expiry_date
|
67
|
+
return status
|
68
|
+
end
|
69
|
+
|
70
|
+
def cert_status_colors
|
71
|
+
return {
|
72
|
+
valid: :green,
|
73
|
+
expiring: :yellow,
|
74
|
+
expired: :red
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
def cert_status_strings
|
79
|
+
return {
|
80
|
+
valid: 'valid until',
|
81
|
+
expiring: 'expiring at',
|
82
|
+
expired: 'expired at'
|
83
|
+
}
|
84
|
+
end
|
85
|
+
end
|
@@ -1,11 +1,14 @@
|
|
1
1
|
require 'sysinfo'
|
2
2
|
|
3
3
|
class Uptime
|
4
|
+
attr_reader :name, :errors
|
4
5
|
attr_reader :days, :hours, :minutes
|
5
6
|
|
6
7
|
def initialize(motd)
|
8
|
+
@name = 'uptime'
|
7
9
|
@motd = motd
|
8
|
-
@config = motd.config.component_config(
|
10
|
+
@config = motd.config.component_config(@name)
|
11
|
+
@errors = []
|
9
12
|
end
|
10
13
|
|
11
14
|
def process
|
@@ -22,6 +25,6 @@ class Uptime
|
|
22
25
|
result += "#{@days} day#{'s' if @days != 1}, " unless @days.zero?
|
23
26
|
result += "#{@hours} hour#{'s' if @hours != 1}, " unless @hours.zero? && @days.zero?
|
24
27
|
result += "#{@minutes} minute#{'s' if @minutes != 1}"
|
25
|
-
return "
|
28
|
+
return "#{@config['prefix'] || 'up'} #{result}"
|
26
29
|
end
|
27
30
|
end
|
data/lib/panda_motd/config.rb
CHANGED
@@ -3,7 +3,7 @@ require 'fileutils'
|
|
3
3
|
|
4
4
|
class Config
|
5
5
|
def initialize(file_path = nil)
|
6
|
-
@file_path = File.join(Dir.home, '.config', 'panda-motd.yaml')
|
6
|
+
@file_path = file_path.nil? ? File.join(Dir.home, '.config', 'panda-motd.yaml') : file_path
|
7
7
|
create_config(@file_path) unless File.exist?(@file_path)
|
8
8
|
load_config(@file_path)
|
9
9
|
end
|
@@ -11,8 +11,8 @@ class Config
|
|
11
11
|
def components_enabled
|
12
12
|
# first iterate through the config hash and grab all names of enabled components
|
13
13
|
enabled_list = @config['components'].map { |component, setting| component if setting['enabled'] }.compact
|
14
|
-
#
|
15
|
-
return enabled_list.map { |e|
|
14
|
+
# get the class constant
|
15
|
+
return enabled_list.map { |e| component_classes[e.to_sym] }
|
16
16
|
end
|
17
17
|
|
18
18
|
def component_config(component_name)
|
@@ -21,6 +21,16 @@ class Config
|
|
21
21
|
|
22
22
|
private
|
23
23
|
|
24
|
+
def component_classes
|
25
|
+
return {
|
26
|
+
ascii_text_art: ASCIITextArt,
|
27
|
+
service_status: ServiceStatus,
|
28
|
+
uptime: Uptime,
|
29
|
+
ssl_certificates: SSLCertificates,
|
30
|
+
filesystems: Filesystems
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
24
34
|
def create_config(file_path)
|
25
35
|
default_config_path = File.join(File.dirname(__dir__), 'panda_motd', 'default_config.yaml')
|
26
36
|
FileUtils.cp(default_config_path, file_path)
|
@@ -1,23 +1,89 @@
|
|
1
|
+
# The components section contains an ordered list of components you wish to
|
2
|
+
# print in the MOTD. They will be printed in the order they are defined in
|
3
|
+
# this file. Duplicate components will override previous definitions. Every
|
4
|
+
# component has an "enabled" setting which will turn the component on or off.
|
5
|
+
|
1
6
|
components:
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
#
|
7
|
+
#####
|
8
|
+
# ASCII Text Art
|
9
|
+
# Generates ASCII pictures of strings.
|
10
|
+
#
|
11
|
+
# Settings
|
12
|
+
# font: The figlet font to render the text with. All supported fonts
|
13
|
+
# can be found at http://www.figlet.org/fontdb.cgi
|
14
|
+
# color: The color of the resulting text art. Supports the standard base-8
|
15
|
+
# colors: black, red, green, yellow, blue, magenta, cyan, and white. You
|
16
|
+
# can also use 'default' for your default terminal color. Additionally,
|
17
|
+
# you can prefix any of the base colors with 'light_' to get the lighter
|
18
|
+
# version.
|
19
|
+
#####
|
20
|
+
|
21
|
+
# ascii_text_art:
|
22
|
+
# enabled: true
|
23
|
+
# font: slant
|
24
|
+
# color: red
|
25
|
+
|
26
|
+
#####
|
27
|
+
# Service Status
|
28
|
+
# Displays the current state of services running on the system. Currently
|
29
|
+
# only supports systemd.
|
30
|
+
#
|
31
|
+
# Settings
|
32
|
+
# services: Pairs following the format "service_name: Pretty Name". The
|
33
|
+
# service_name is the name of the systemd service to look for, NOT
|
34
|
+
# including the '.service' suffix. The pretty name is the name that is
|
35
|
+
# used in the MOTD to represent that service.
|
36
|
+
#####
|
37
|
+
|
38
|
+
# service_status:
|
39
|
+
# enabled: true
|
40
|
+
# services:
|
41
|
+
# chunkwm: chunkwm
|
42
|
+
# skhd: skhd
|
43
|
+
# elasticsearch@5.6: elasticsearch
|
44
|
+
# mysql: MySQL
|
45
|
+
|
46
|
+
#####
|
47
|
+
# Uptime
|
48
|
+
# Displays the current uptime of the machine.
|
49
|
+
#
|
50
|
+
# Settings
|
51
|
+
# prefix: The text to prepend to the uptime string.
|
52
|
+
#####
|
53
|
+
|
54
|
+
# uptime:
|
55
|
+
# enabled: true
|
56
|
+
# prefix: up
|
57
|
+
|
58
|
+
#####
|
59
|
+
# SSL Certificates
|
60
|
+
# Displays the validity and expiration dates of SSL certificates.
|
61
|
+
#
|
62
|
+
# Settings
|
63
|
+
# certs: Pairs following the format "PrettyName: absolute_cert_file_path".
|
64
|
+
# The absolute_cert_file_path is the absolute file path of the SSL
|
65
|
+
# certificate. The pretty name is the name that is used in the MOTD to
|
66
|
+
# represent that certificate, typically a domain name.
|
67
|
+
#####
|
68
|
+
|
69
|
+
# ssl_certificates:
|
70
|
+
# enabled: true
|
71
|
+
# certs:
|
72
|
+
# taylorjthurlow.com: /etc/letsencrypt/live/taylorjthurlow.com/cert.pem
|
73
|
+
|
74
|
+
#####
|
75
|
+
# Filesystems
|
76
|
+
# Displays filesystem usage information.
|
77
|
+
#
|
78
|
+
# Settings
|
79
|
+
# filesystems: Pairs following the format "filesystem_name: Pretty Name".
|
80
|
+
# The filesystem_name is the name of the filesystem listed when using the
|
81
|
+
# `df` command line tool. The pretty name is the name that is used in the
|
82
|
+
# MOTD to represent that filesystem.
|
83
|
+
#####
|
84
|
+
|
85
|
+
# filesystems:
|
19
86
|
# enabled: true
|
20
|
-
#
|
21
|
-
# /dev/
|
22
|
-
# /dev/
|
23
|
-
# /dev/disk2s2: Games
|
87
|
+
# filesystems:
|
88
|
+
# /dev/sda1: Ubuntu
|
89
|
+
# /dev/sdc1: Data
|
data/lib/panda_motd/motd.rb
CHANGED
@@ -3,18 +3,19 @@ require 'sysinfo'
|
|
3
3
|
class MOTD
|
4
4
|
attr_reader :config, :components
|
5
5
|
|
6
|
-
def initialize
|
7
|
-
@config = Config.new
|
8
|
-
|
9
|
-
@components = []
|
10
|
-
@config.components_enabled.each do |component_class|
|
11
|
-
@components << component_class.new(self)
|
12
|
-
end
|
13
|
-
|
6
|
+
def initialize(config_path = nil)
|
7
|
+
@config = config_path ? Config.new(config_path) : Config.new
|
8
|
+
@components = @config.components_enabled.map { |ce| ce.new(self) }
|
14
9
|
@components.each(&:process)
|
15
10
|
end
|
16
11
|
|
17
12
|
def to_s
|
18
|
-
return @components.map
|
13
|
+
return @components.map do |c|
|
14
|
+
if c.errors.any?
|
15
|
+
c.errors.map(&:to_s).join("\n")
|
16
|
+
else
|
17
|
+
c.to_s
|
18
|
+
end
|
19
|
+
end.join("\n\n")
|
19
20
|
end
|
20
21
|
end
|
data/lib/panda_motd/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: panda-motd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Taylor Thurlow
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-05-
|
11
|
+
date: 2018-05-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: artii
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '2.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: ruby-units
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.3'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.3'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: sysinfo
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -173,9 +187,11 @@ extra_rdoc_files: []
|
|
173
187
|
files:
|
174
188
|
- bin/panda-motd
|
175
189
|
- lib/panda_motd.rb
|
176
|
-
- lib/panda_motd/
|
190
|
+
- lib/panda_motd/component_error.rb
|
177
191
|
- lib/panda_motd/components/ascii_text_art.rb
|
192
|
+
- lib/panda_motd/components/filesystems.rb
|
178
193
|
- lib/panda_motd/components/service_status.rb
|
194
|
+
- lib/panda_motd/components/ssl_certificates.rb
|
179
195
|
- lib/panda_motd/components/uptime.rb
|
180
196
|
- lib/panda_motd/config.rb
|
181
197
|
- lib/panda_motd/default_config.yaml
|
data/lib/panda_motd/component.rb
DELETED
File without changes
|