panda-motd 0.0.3 → 0.0.4
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.
- 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
|