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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2222386bd03c3421453df6fc47a6d91343a68a4e10f2eb33a5ca3108c9f39147
4
- data.tar.gz: d234523870e13a2bdd163b101a0f82e270205e80929c013adda59d4d9a51b388
3
+ metadata.gz: 89f4f13274b708ecae4ba0db251e0edc4b63e28ca0a5a482512db7cf7c68d6a8
4
+ data.tar.gz: 3a44997b59f6963c3d1509540051704d4ab7efa6f820222c39b35c5982dc7481
5
5
  SHA512:
6
- metadata.gz: 1255ff0bc3a4e7393c82a0a404b17090397fe5956a7e389d0069d66790bfe262418baf197871f667e69e47843d10fc3c1fae0b514d49a7f91547b8688ce074b5
7
- data.tar.gz: b52e63e8fc994b9d5310c12c315830ec58e0bf2537d8fbd0d3f45a2881ce41a35f9284e1e7b46baeb25257cf6fb581c13d59f991ac12c914c88f67cc4193c15e
6
+ metadata.gz: 6b178d04e887558d28024837ab6e613741cea34ac2f8d9df8876db60775c1ecc0fca729e944c1375c6a1884512845868e829396d00b7702a65f81c4bcba9b939
7
+ data.tar.gz: f8976bdd3303b3e1a057cc9ce6c43f86dda8e094294364acf3bdc2fe883bf2b2e952e8d5925dd6b68eee9f313e99eddf82e8a045c2432619ef952275f7641679
data/README.md CHANGED
@@ -1,3 +1,4 @@
1
1
  # Checkson
2
2
  [![pipeline status](https://gitlab.fsrv.xyz/fsrv/checkson/badges/master/pipeline.svg)](https://gitlab.fsrv.xyz/fsrv/checkson/commits/master)
3
+ [![Gem Version](https://badge.fury.io/rb/checkson.svg)](https://badge.fury.io/rb/checkson)
3
4
 
data/bin/checkson CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require_relative '../lib/checkson'
4
+ require 'checkson'
5
5
  Checkson::UI.new
data/lib/checkson.rb CHANGED
@@ -1,6 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'checkson/ui'
4
- require_relative 'checkson/context'
5
- require_relative 'checkson/config'
6
- require_relative 'checkson/check'
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
@@ -1,31 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Base
4
- attr_reader :status
5
-
6
- def initialize(_opts = {})
7
- @status = :ok
8
- end
9
-
10
- def ok?
11
- @status == :ok
12
- end
13
-
14
- def failed?
15
- !ok?
16
- end
17
-
18
- protected
19
-
20
- def log(message)
21
- @messages << message
22
- end
23
-
24
- def ok!
25
- @status = :ok
26
- end
27
-
28
- def failed!
29
- @status = :failed
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
- class Shell < Base
4
- def initialize(opts = {})
5
- @opts = (@opts || {}).merge(opts)
6
- super()
7
- end
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
- def check
10
- raise ArgumentError, 'No code given' unless @opts[:code]
11
+ def check
12
+ raise ArgumentError, 'No code given' unless @opts[:code]
11
13
 
12
- execute(@opts[:code])
13
- failed! unless $?.exitstatus.zero?
14
- end
14
+ execute(@opts[:code])
15
+ failed! unless $?.exitstatus.zero?
16
+ end
15
17
 
16
- protected
18
+ protected
17
19
 
18
- def execute(command)
19
- `sh -c "#{command.gsub(/"/, '\"')}"`
20
+ def execute(command)
21
+ `sh -c "#{command.gsub(/"/, '\"')}"`
22
+ end
23
+ end
20
24
  end
21
25
  end
@@ -5,6 +5,7 @@ require 'ostruct'
5
5
  module Checkson
6
6
  class Config
7
7
  attr_reader :checks, :name
8
+ include Checkson::Check
8
9
 
9
10
  def initialize(file)
10
11
  @checks = []
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
- protected
15
-
16
- def winsize
17
- require 'io/console'
18
- IO.console.winsize
19
- end
16
+ private
20
17
 
21
18
  def start_checks
22
- @config = Checkson::Config.new(@opts[:config])
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
- output c, check
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
- config: '/etc/checkson.rb'
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('-c', '--config FILE', 'Config file to use') do |file|
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[:config] = file
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
- check.help.each do |message|
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.2'
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-03-18 00:00:00.000000000 Z
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/check.rb
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
@@ -1,4 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'checks/base'
4
- require_relative 'checks/shell'