checkson 0.3 → 0.8

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: 0d96211a8a64dbfbc3d84af7825432105a02c024fe2309b6dc09993ad6d402df
4
- data.tar.gz: e133df83fcdfdb21c3f2c48ac941edbf17e21d3ddd3a9b6415f25df979fd0d87
3
+ metadata.gz: e687727e776e3750c0e7f1a9c8df3b889af66c6f36fcc416a2136d412e3de4b4
4
+ data.tar.gz: df086a10ff20f5ed195ee5723f4801583ccf7f77eece76dc8580ff35aaadb58c
5
5
  SHA512:
6
- metadata.gz: 9df0c30156b15cbb707d7ef889f731b835058a7d5516907d2c164c452cd34d79ce95417c931431d8f2365133fe30e280ef4be9851c7cd99ab8036359673b5229
7
- data.tar.gz: e59a8be148940843a85c7d21f572a6796231bfd5df8b653d57c886a91d36337984f8bf6a27fe7b0877f22566673549811072199b0436f183abba22425a427bab
6
+ metadata.gz: ae576c7cf8532badde63953fce6f8d09cd0b74340efe12267513a76a8dc9b3d086be47467749f3caca70df5beb320ccbbc40e9ce147b81287e2de14d0ca628e4
7
+ data.tar.gz: c3c7fb75ffbdc836c8e6b92232a886b4cac45e15f649719cb8c76b5ee6a26b33e22663ddb64590396a8a4721572e70880a1c0f40ca1ed55b4fbcd7acd520f5b0
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,32 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Base
4
- attr_reader :status, :messages
5
-
6
- def initialize(_opts = {})
7
- @messages = []
8
- @status = :ok
9
- end
10
-
11
- def ok?
12
- @status == :ok
13
- end
14
-
15
- def failed?
16
- !ok?
17
- end
18
-
19
- protected
20
-
21
- def log(message)
22
- @messages << message
23
- end
24
-
25
- def ok!
26
- @status = :ok
27
- end
28
-
29
- def failed!
30
- @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
31
35
  end
32
36
  end
@@ -1,25 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class DNS < Base
4
- def initialize(opts = {})
5
- @opts = { domain: 'heise.de',
6
- timeout: 1,
7
- host: 'localhost' }.merge(opts)
8
- super()
9
- end
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
10
12
 
11
- def check
12
- require 'resolv'
13
- resolver = Resolv::DNS.new(nameserver: [@opts[:host]])
14
- resolver.timeouts = @opts[:timeout]
15
- begin
16
- resolver.getaddress(@opts[:domain])
17
- rescue Resolv::ResolvTimeout
18
- failed!
19
- log("Resolving #{@opts[:domain]} timed out")
20
- rescue Resolv::ResolvError
21
- failed!
22
- log("Could not resolve #{@opts[:domain]}")
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
23
27
  end
24
28
  end
25
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 auxwww')
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,15 +13,15 @@ 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])
23
25
 
24
26
  @num_checks = @config.checks.length
25
27
  @num_ok = 0
@@ -27,29 +29,47 @@ module Checkson
27
29
  c = check.klass.new(check.params)
28
30
  c.check
29
31
  @num_ok += 1 if c.status.eql? :ok
30
- output c, check
32
+ output c, check if @opts[:verbose]
31
33
  end
32
34
  @num_failed = (@num_checks - @num_ok)
33
- puts "\n#{@num_checks} checks performed: #{@num_ok} ok, #{@num_failed} failed"
35
+ puts "-> #{@num_checks} checks performed: #{@num_ok} ok, #{@num_failed} failed"
34
36
  end
35
37
 
36
38
  def set_default_options
37
39
  @opts = {
38
- config: '/etc/checkson.rb'
40
+ datasource: :file,
41
+ verbose: false,
42
+ config_file: '/etc/checkson.rb',
43
+ endpoint: 'https://checkson.fsrv.services:8080'
39
44
  }
40
45
  end
41
46
 
42
47
  def parse_options
43
48
  OptionParser.new do |opts|
44
49
  opts.banner = 'Usage: checkson [options]'
45
- 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|
46
57
  if File.exist?(file)
47
- @opts[:config] = file
58
+ @opts[:config_file] = file
48
59
  else
49
60
  die("Config file #{file} does not exist")
50
61
  end
51
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
52
70
  end.parse!
71
+ logger = Logger.new(STDOUT)
72
+ logger.info "Using datasource `#{@opts[:datasource]}`"
53
73
  end
54
74
 
55
75
  def output(sym, check)
@@ -65,6 +85,11 @@ module Checkson
65
85
  end
66
86
  end
67
87
 
88
+ def winsize
89
+ require 'io/console'
90
+ IO.console.winsize
91
+ end
92
+
68
93
  def die(msg)
69
94
  warn(msg)
70
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.3'
4
+ version: '0.8'
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-28 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,9 +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
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
26
29
  - lib/checkson/checks/shell.rb
27
30
  - lib/checkson/config.rb
28
31
  - lib/checkson/context.rb
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'checks/base'
4
- require_relative 'checks/shell'
5
- require_relative 'checks/dns'