checkson 0.2 → 0.7
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/README.md +1 -0
- data/bin/checkson +1 -1
- data/lib/checkson.rb +13 -4
- data/lib/checkson/apiclient.rb +80 -0
- data/lib/checkson/checks/base.rb +32 -27
- data/lib/checkson/checks/dns.rb +29 -0
- data/lib/checkson/checks/packagemanagers/abstractpkgmgr.rb +23 -0
- data/lib/checkson/checks/packages.rb +25 -0
- data/lib/checkson/checks/process.rb +47 -0
- data/lib/checkson/checks/shell.rb +17 -13
- data/lib/checkson/config.rb +1 -0
- data/lib/checkson/ui.rb +44 -16
- metadata +7 -3
- data/lib/checkson/check.rb +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 89f4f13274b708ecae4ba0db251e0edc4b63e28ca0a5a482512db7cf7c68d6a8
|
4
|
+
data.tar.gz: 3a44997b59f6963c3d1509540051704d4ab7efa6f820222c39b35c5982dc7481
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b178d04e887558d28024837ab6e613741cea34ac2f8d9df8876db60775c1ecc0fca729e944c1375c6a1884512845868e829396d00b7702a65f81c4bcba9b939
|
7
|
+
data.tar.gz: f8976bdd3303b3e1a057cc9ce6c43f86dda8e094294364acf3bdc2fe883bf2b2e952e8d5925dd6b68eee9f313e99eddf82e8a045c2432619ef952275f7641679
|
data/README.md
CHANGED
data/bin/checkson
CHANGED
data/lib/checkson.rb
CHANGED
@@ -1,6 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
module Checkson
|
4
|
+
autoload :Config, 'checkson/config'
|
5
|
+
autoload :Context, 'checkson/context'
|
6
|
+
autoload :APIClient, 'checkson/apiclient'
|
7
|
+
autoload :UI, 'checkson/ui'
|
8
|
+
|
9
|
+
module Check
|
10
|
+
autoload :Base, 'checkson/checks/base'
|
11
|
+
autoload :DNS, 'checkson/checks/dns'
|
12
|
+
autoload :Shell, 'checkson/checks/shell'
|
13
|
+
autoload :Process, 'checkson/checks/process'
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'json'
|
5
|
+
require 'uri'
|
6
|
+
require 'erb'
|
7
|
+
require 'socket'
|
8
|
+
require 'digest'
|
9
|
+
require 'logger'
|
10
|
+
|
11
|
+
module Checkson
|
12
|
+
class APIClient
|
13
|
+
attr_reader :apiaddr
|
14
|
+
attr_reader :outfile
|
15
|
+
def initialize(apiaddr, outfile)
|
16
|
+
@apiaddr = apiaddr
|
17
|
+
@outfile = outfile
|
18
|
+
end
|
19
|
+
|
20
|
+
def getchecks
|
21
|
+
template = <<-TEMPLATE
|
22
|
+
<%@checks.each do |check| %>
|
23
|
+
check '<%=check["description"]%>' do
|
24
|
+
using <%=check["check"]%>
|
25
|
+
<%check["sets"].each do |key,value| %>
|
26
|
+
set :<%=key%>, "<%=value%>"
|
27
|
+
<%end%>
|
28
|
+
<%unless check["helps"].eql?(nil)%>
|
29
|
+
<%check["helps"].each do |help| %>
|
30
|
+
help '<%= help %>'
|
31
|
+
<%end%>
|
32
|
+
<%end%>
|
33
|
+
end
|
34
|
+
<% end %>
|
35
|
+
TEMPLATE
|
36
|
+
querydata = get
|
37
|
+
@checks = querydata['checks'] if querydata['status'].eql? 'ok'
|
38
|
+
begin
|
39
|
+
remove_empty_lines(ERB.new(template).result(binding))
|
40
|
+
rescue StandardError
|
41
|
+
die querydata['error']
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def writechecks
|
46
|
+
File.open(@outfile, 'w') do |f|
|
47
|
+
f.write(getchecks)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def remove_empty_lines(string)
|
54
|
+
regex = /^[\s]*$\n/
|
55
|
+
string.gsub(regex, '')
|
56
|
+
end
|
57
|
+
|
58
|
+
def get
|
59
|
+
token = ENV['CHECKSON_API_KEY']
|
60
|
+
token ||= 'empty'
|
61
|
+
hostname = Socket.gethostname
|
62
|
+
query("#{keyhash(token)}/get/#{hostname}")
|
63
|
+
end
|
64
|
+
|
65
|
+
def query(command)
|
66
|
+
@ep = "#{@apiaddr}/api/v1"
|
67
|
+
route = "#{@ep}/#{command}"
|
68
|
+
JSON.parse(Net::HTTP.get(URI.parse(route)))
|
69
|
+
end
|
70
|
+
|
71
|
+
def keyhash(token)
|
72
|
+
Digest::SHA512.hexdigest(token)
|
73
|
+
end
|
74
|
+
|
75
|
+
def die(msg)
|
76
|
+
warn(msg)
|
77
|
+
exit 1
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/checkson/checks/base.rb
CHANGED
@@ -1,31 +1,36 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
3
|
+
module Checkson
|
4
|
+
module Check
|
5
|
+
class Base
|
6
|
+
attr_reader :status, :messages
|
7
|
+
|
8
|
+
def initialize(_opts = {})
|
9
|
+
@messages = []
|
10
|
+
@status = :ok
|
11
|
+
end
|
12
|
+
|
13
|
+
def ok?
|
14
|
+
@status == :ok
|
15
|
+
end
|
16
|
+
|
17
|
+
def failed?
|
18
|
+
!ok?
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def log(message)
|
24
|
+
@messages << message
|
25
|
+
end
|
26
|
+
|
27
|
+
def ok!
|
28
|
+
@status = :ok
|
29
|
+
end
|
30
|
+
|
31
|
+
def failed!
|
32
|
+
@status = :failed
|
33
|
+
end
|
34
|
+
end
|
30
35
|
end
|
31
36
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Checkson
|
4
|
+
module Check
|
5
|
+
class DNS < Checkson::Check::Base
|
6
|
+
def initialize(opts = {})
|
7
|
+
@opts = { domain: 'heise.de',
|
8
|
+
timeout: 1,
|
9
|
+
host: 'localhost' }.merge(opts)
|
10
|
+
super()
|
11
|
+
end
|
12
|
+
|
13
|
+
def check
|
14
|
+
require 'resolv'
|
15
|
+
resolver = Resolv::DNS.new(nameserver: [@opts[:host]])
|
16
|
+
resolver.timeouts = @opts[:timeout]
|
17
|
+
begin
|
18
|
+
resolver.getaddress(@opts[:domain])
|
19
|
+
rescue Resolv::ResolvTimeout
|
20
|
+
failed!
|
21
|
+
log("Resolving #{@opts[:domain]} timed out")
|
22
|
+
rescue Resolv::ResolvError
|
23
|
+
failed!
|
24
|
+
log("Could not resolve #{@opts[:domain]}")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Checkson
|
4
|
+
module Check
|
5
|
+
module Pkganager
|
6
|
+
class AbstractPkgmanager
|
7
|
+
def self.descendants
|
8
|
+
ObjectSpace.each_object(Class).select { |klass| klass < self }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Pkgmanager < AbstractPkgmanager
|
13
|
+
def self.adapters
|
14
|
+
AbstractPkgmanager.descendants - [self]
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.adapter
|
18
|
+
@adapter ||= adapters.find { |adapter| adapter.supports_os? Facter['osfamily'].value.downcase }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Checkson
|
4
|
+
module Check
|
5
|
+
class Shell < Checkson::Check::Base
|
6
|
+
def initialize(opts = {})
|
7
|
+
@opts = (@opts || {}).merge(opts)
|
8
|
+
super()
|
9
|
+
end
|
10
|
+
|
11
|
+
def check
|
12
|
+
raise ArgumentError, 'No code given' unless @opts[:code]
|
13
|
+
|
14
|
+
execute(@opts[:code])
|
15
|
+
failed! unless $?.exitstatus.zero?
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
def execute(command)
|
21
|
+
`sh -c "#{command.gsub(/"/, '\"')}"`
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ipaddr'
|
4
|
+
|
5
|
+
module Checkson
|
6
|
+
module Check
|
7
|
+
class Process < Checkson::Check::Shell
|
8
|
+
def initialize(opts = {})
|
9
|
+
@opts = opts
|
10
|
+
raise ArgumentError, 'Neither pidfile nor process name given' unless @opts[:pidfile] || @opts[:name]
|
11
|
+
|
12
|
+
super()
|
13
|
+
end
|
14
|
+
|
15
|
+
def check
|
16
|
+
@opts[:pidfile] ? check_pidfile : check_name
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def check_pidfile
|
22
|
+
pid = File.read(@opts[:pidfile]).strip
|
23
|
+
execute("kill -0 #{pid} 2>&1")
|
24
|
+
|
25
|
+
unless $?.exitstatus.zero?
|
26
|
+
failed!
|
27
|
+
log("Process ID #{pid} is not running")
|
28
|
+
end
|
29
|
+
rescue Errno::ENOENT
|
30
|
+
failed!
|
31
|
+
log("Cannot open pidfile: #{@opts[:pidfile]}")
|
32
|
+
end
|
33
|
+
|
34
|
+
def check_name
|
35
|
+
ps = execute('ps aux')
|
36
|
+
|
37
|
+
if @opts[:name].is_a?(Regexp) && ps !~ (@opts[:name])
|
38
|
+
failed!
|
39
|
+
log("No process found matching regular expression `#{@opts[:name].source}`")
|
40
|
+
elsif !ps.include?(@opts[:name])
|
41
|
+
failed!
|
42
|
+
log("No process found matching name `#{@opts[:name]}`")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -1,21 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
module Checkson
|
4
|
+
module Check
|
5
|
+
class Shell < Checkson::Check::Base
|
6
|
+
def initialize(opts = {})
|
7
|
+
@opts = (@opts || {}).merge(opts)
|
8
|
+
super()
|
9
|
+
end
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
+
def check
|
12
|
+
raise ArgumentError, 'No code given' unless @opts[:code]
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
|
14
|
+
execute(@opts[:code])
|
15
|
+
failed! unless $?.exitstatus.zero?
|
16
|
+
end
|
15
17
|
|
16
|
-
|
18
|
+
protected
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
+
def execute(command)
|
21
|
+
`sh -c "#{command.gsub(/"/, '\"')}"`
|
22
|
+
end
|
23
|
+
end
|
20
24
|
end
|
21
25
|
end
|
data/lib/checkson/config.rb
CHANGED
data/lib/checkson/ui.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'optparse'
|
4
|
+
require 'logger'
|
5
|
+
require 'uri'
|
4
6
|
|
5
7
|
module Checkson
|
6
8
|
# Simple user interface for checkson
|
@@ -11,39 +13,63 @@ module Checkson
|
|
11
13
|
start_checks
|
12
14
|
end
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
def winsize
|
17
|
-
require 'io/console'
|
18
|
-
IO.console.winsize
|
19
|
-
end
|
16
|
+
private
|
20
17
|
|
21
18
|
def start_checks
|
22
|
-
|
19
|
+
if @opts[:datasource].eql? :api
|
20
|
+
client = Checkson::APIClient.new(@opts[:endpoint], '/tmp/checkson.rb')
|
21
|
+
client.writechecks
|
22
|
+
@opts[:config_file] = client.outfile
|
23
|
+
end
|
24
|
+
@config = Checkson::Config.new(@opts[:config_file])
|
25
|
+
|
26
|
+
@num_checks = @config.checks.length
|
27
|
+
@num_ok = 0
|
23
28
|
@config.checks.each do |check|
|
24
29
|
c = check.klass.new(check.params)
|
25
30
|
c.check
|
26
|
-
|
31
|
+
@num_ok += 1 if c.status.eql? :ok
|
32
|
+
output c, check if @opts[:verbose]
|
27
33
|
end
|
34
|
+
@num_failed = (@num_checks - @num_ok)
|
35
|
+
puts "-> #{@num_checks} checks performed: #{@num_ok} ok, #{@num_failed} failed"
|
28
36
|
end
|
29
37
|
|
30
38
|
def set_default_options
|
31
39
|
@opts = {
|
32
|
-
|
40
|
+
datasource: :file,
|
41
|
+
verbose: false,
|
42
|
+
config_file: '/etc/checkson.rb',
|
43
|
+
endpoint: 'https://checkson.fsrv.services:8080'
|
33
44
|
}
|
34
45
|
end
|
35
46
|
|
36
47
|
def parse_options
|
37
48
|
OptionParser.new do |opts|
|
38
49
|
opts.banner = 'Usage: checkson [options]'
|
39
|
-
opts.on('-
|
50
|
+
opts.on('-v', '--[no-]verbose', 'Run verbosely') do |v|
|
51
|
+
@opts[:verbose] = v
|
52
|
+
end
|
53
|
+
opts.on('-d', '--datasource [TYPE]', %i[file api], 'Set datasource type', '(file, api)') do |d|
|
54
|
+
@opts[:datasource] = d
|
55
|
+
end
|
56
|
+
opts.on('-f', '--file [FILE]', 'Config file to use') do |file|
|
40
57
|
if File.exist?(file)
|
41
|
-
@opts[:
|
58
|
+
@opts[:config_file] = file
|
42
59
|
else
|
43
60
|
die("Config file #{file} does not exist")
|
44
61
|
end
|
45
62
|
end
|
63
|
+
opts.on('-e', '--endpoint [ADDR]', 'Config api to use') do |ep|
|
64
|
+
if ep =~ URI::DEFAULT_PARSER.make_regexp
|
65
|
+
@opts[:endpoint] = ep
|
66
|
+
else
|
67
|
+
die('URL of endpoint not valid')
|
68
|
+
end
|
69
|
+
end
|
46
70
|
end.parse!
|
71
|
+
logger = Logger.new(STDOUT)
|
72
|
+
logger.info "Using datasource `#{@opts[:datasource]}`"
|
47
73
|
end
|
48
74
|
|
49
75
|
def output(sym, check)
|
@@ -54,14 +80,16 @@ module Checkson
|
|
54
80
|
puts "\033[#{status_column}G\033[1;32mOK\033[0m"
|
55
81
|
when :failed
|
56
82
|
puts "\033[#{status_column}G\033[1;31mFAILED\033[0m"
|
57
|
-
unless check.help.empty?
|
58
|
-
|
59
|
-
puts "--> #{message}"
|
60
|
-
end
|
61
|
-
end
|
83
|
+
check.help.each { |message| puts "--> #{message}" } unless check.help.empty?
|
84
|
+
sym.messages.each { |message| puts " * #{message}" }
|
62
85
|
end
|
63
86
|
end
|
64
87
|
|
88
|
+
def winsize
|
89
|
+
require 'io/console'
|
90
|
+
IO.console.winsize
|
91
|
+
end
|
92
|
+
|
65
93
|
def die(msg)
|
66
94
|
warn(msg)
|
67
95
|
exit 1
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: checkson
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.7'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Florian Bauer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-04-14 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A simple framework for checking node facts
|
14
14
|
email: florian@fsrv.xyz
|
@@ -20,8 +20,12 @@ files:
|
|
20
20
|
- README.md
|
21
21
|
- bin/checkson
|
22
22
|
- lib/checkson.rb
|
23
|
-
- lib/checkson/
|
23
|
+
- lib/checkson/apiclient.rb
|
24
24
|
- lib/checkson/checks/base.rb
|
25
|
+
- lib/checkson/checks/dns.rb
|
26
|
+
- lib/checkson/checks/packagemanagers/abstractpkgmgr.rb
|
27
|
+
- lib/checkson/checks/packages.rb
|
28
|
+
- lib/checkson/checks/process.rb
|
25
29
|
- lib/checkson/checks/shell.rb
|
26
30
|
- lib/checkson/config.rb
|
27
31
|
- lib/checkson/context.rb
|
data/lib/checkson/check.rb
DELETED