prometheus-splash 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1e6fae61b205672ab555b7cd28f0c0bfc0c48bacbaa81f9696a7ce16ef9eaa2e
4
- data.tar.gz: e9167d60ea4537298014c7af7ee5214ff124d66b1b880925b18069e3a2e5db88
3
+ metadata.gz: 4f2d1cf627c0fd2371da011a6a97a24e82498b9a28b3d4d0485e185841bf7438
4
+ data.tar.gz: e0982026ea749cad8366f420e88cd376bcc8bd0a45e0ec292cc1b9a8237764c2
5
5
  SHA512:
6
- metadata.gz: 5b7e241e27d99e1ca480d387a1c87a86583113d2393756200dc1b167b069b7c24253c911a6dfd05c352f821c3d5e4c691a74a2ace2611f6adf08c545d76019aa
7
- data.tar.gz: 6c5c3579c210e000bdac1f9220b0b89d5bb6e0f1997ea48061d7fe8734546689f18b22fa5d083c4a3fb36e6333b7cdf05637f3dd4c4b5d62ed0988050d758b26
6
+ metadata.gz: b43dcf0493e86ac31da666c4a68c8f2f22f804231f1fd6c0bcc98e3235605e80a4c8e8def976a7c4bf1c54110bdbfe0e67d64040c9d857d23dc16a324cdd1826
7
+ data.tar.gz: 18b7dea993feea9e1a276bf02b5542d98a772754eb68b113bde17ba5f69ec9c346eaa56520d8b960aa658ba1cc4b53a17dd5f7e4af256f8d07b404131573acd4
data/Rakefile CHANGED
@@ -27,6 +27,7 @@ CLOBBER.include('*.tmp', 'build/*','#*#')
27
27
  content = File::readlines(File.join(File.dirname(__FILE__), 'prometheus-splash.gemspec')).join
28
28
  spec = eval(content)
29
29
 
30
+
30
31
  RSpec::Core::RakeTask.new('spec')
31
32
 
32
33
  YARD::Rake::YardocTask.new do |t|
data/bin/splash CHANGED
@@ -5,6 +5,8 @@ begin
5
5
  require 'prometheus/client'
6
6
  require 'prometheus/client/push'
7
7
  require 'thor'
8
+ require 'rufus-scheduler'
9
+
8
10
  rescue Gem::GemNotFoundException
9
11
  $stderr.puts "Loadind error, it's like you try to run Splash, with a lake of dependencies."
10
12
  $stderr.puts "If you run on RVM, please run with rvmsudo and not with sudo."
@@ -17,9 +19,11 @@ require 'splash/constants'
17
19
  require 'splash/helpers'
18
20
  require 'splash/config'
19
21
  require 'splash/templates'
22
+ require 'splash/backends'
20
23
 
21
24
  require 'splash/commands'
22
25
  require 'splash/logs'
26
+ require 'splash/orchestrator'
23
27
  require 'splash/controller'
24
28
 
25
29
  #inhibit warning : due to prometheus-client call to URI.encode warning
@@ -32,20 +36,23 @@ module CLISplash
32
36
 
33
37
  class Commands < Thor
34
38
  include Splash::Config
39
+ include Splash::Backends
35
40
 
36
- desc "wrap NAME", "wrapping for command or ack result"
41
+ desc "run NAME", "run for command/sequence or ack result"
37
42
  long_desc <<-LONGDESC
38
- wrapping for command or ack result
43
+ Running command or sequence or ack result
39
44
  with --no-trace prevent storing execution trace in TRACE_PATH (see config file)
40
45
  with --ack, notify errorcode=0 to Prometheus PushGateway
46
+ with --no-notify, bypass Prometheus notification
41
47
  LONGDESC
42
48
  option :trace, :type => :boolean, :default => true
43
49
  option :ack, :type => :boolean, negate: false
50
+ option :notify, :type => :boolean, :default => true
44
51
  def wrap(name)
45
52
  if is_root? then
46
53
  command = Splash::CommandWrapper::new(name)
47
54
  command.ack if options[:ack]
48
- command.call_and_notify trace: options[:trace]
55
+ command.call_and_notify trace: options[:trace], notify: options[:notify]
49
56
  else
50
57
  $stderr.puts "Command wrapping need to be run as root"
51
58
  exit 60
@@ -53,6 +60,31 @@ module CLISplash
53
60
  end
54
61
 
55
62
 
63
+
64
+ desc "treeview", "Show commands sequence tree"
65
+ def treeview(command, depht = 0)
66
+ puts "Command : #{command.to_s}" if depht == 0
67
+ cmd = get_config.commands[command.to_sym]
68
+ if cmd[:on_failure] then
69
+ print " " * depht + " "
70
+ puts "* on failure => #{cmd[:on_failure]}"
71
+ treeview(cmd[:on_failure], depht+2)
72
+ end
73
+ if cmd[:on_success] then
74
+ print " " * depht + " "
75
+ puts "* on success => #{cmd[:on_success]}"
76
+ treeview(cmd[:on_success],depht+2)
77
+ end
78
+ end
79
+
80
+
81
+
82
+
83
+
84
+
85
+
86
+
87
+
56
88
  desc "list", "Show configured commands"
57
89
  long_desc <<-LONGDESC
58
90
  Show configured commands
@@ -63,11 +95,13 @@ module CLISplash
63
95
  puts "Splash configured commands :"
64
96
  list = get_config.commands
65
97
  puts 'No configured commands found' if list.keys.empty?
66
- listc.keys.each do |command|
98
+ list.keys.each do |command|
67
99
  puts " * #{command.to_s}"
68
100
  if options[:detail] then
69
101
  puts " - command line : '#{list[command][:command]}'"
70
102
  puts " - command description : '#{list[command][:desc]}'"
103
+ puts " - command failure callback : '#{list[command.to_sym][:on_failure]}'" if list[command.to_sym][:on_failure]
104
+ puts " - command success callback : '#{list[command.to_sym][:on_success]}'" if list[command.to_sym][:on_success]
71
105
  end
72
106
  end
73
107
  end
@@ -80,6 +114,8 @@ module CLISplash
80
114
  puts "Splash command : #{command}"
81
115
  puts " - command line : '#{list[command.to_sym][:command]}'"
82
116
  puts " - command description : '#{list[command.to_sym][:desc]}'"
117
+ puts " - command failure callback : '#{list[command.to_sym][:on_failure]}'" if list[command.to_sym][:on_failure]
118
+ puts " - command success callback : '#{list[command.to_sym][:on_success]}'" if list[command.to_sym][:on_success]
83
119
  else
84
120
  $stderr.puts "Command not configured"
85
121
  exit 50
@@ -92,9 +128,10 @@ module CLISplash
92
128
  list = get_config.commands
93
129
  if list.keys.include? command.to_sym then
94
130
  print "Splash command #{command} previous execution report:\n\n"
95
- filename = "#{get_config[:trace_path]}/#{command}_trace.last"
96
- if File::exist? filename then
97
- system("cat #{filename}")
131
+ backend = get_backend :execution_trace
132
+ key = "#{command}_trace.last"
133
+ if backend.exist? key: key then
134
+ print backend.get key: key
98
135
  else
99
136
  puts "Command not already runned."
100
137
  end
@@ -163,12 +200,25 @@ module CLISplash
163
200
 
164
201
 
165
202
  class Logs < Thor
203
+ include Splash::Config
166
204
 
167
205
  desc "analyse", "analyze logs in config"
168
206
  def analyse
169
- result = Splash::LogScanner::new
170
- result.analyse
171
- p result.output
207
+ results = Splash::LogScanner::new
208
+ results.analyse
209
+ puts "SPlash Configured logs status :"
210
+ full_status = true
211
+ results.output.each do |result|
212
+ status = (result[:status] == :clean)? "OK": "KO"
213
+ puts " * Log : #{result[:log]} : [#{status}]"
214
+ puts " - Detected pattern : #{result[:pattern]}"
215
+ puts " - detailled Status : #{result[:status].to_s}"
216
+ puts " count = #{result[:count]}" if result[:status] == :matched
217
+ puts " nb lines = #{result[:lines]}" if result[:status] != :missing
218
+ full_status = false unless result[:status] == :clean
219
+ end
220
+ display_status = (full_status)? "OK": "KO"
221
+ puts "Global Status : [#{display_status}]"
172
222
  end
173
223
 
174
224
  desc "monitor", "monitor logs in config"
@@ -178,6 +228,36 @@ module CLISplash
178
228
  result.notify
179
229
  end
180
230
 
231
+ desc "show LOG", "show configured log monitoring for LOG"
232
+ def show(log)
233
+ log_record_set = get_config.logs.select{|item| item[:log] == log }
234
+ unless log_record_set.empty? then
235
+ record = log_record_set.first
236
+ puts "Splash log monitor : #{record[:log]}"
237
+ puts " -> pattern : /#{record[:pattern]}/"
238
+ else
239
+ $stderr.puts "log not configured"
240
+ exit 50
241
+ end
242
+ end
243
+
244
+ desc "list", "Show configured logs monitoring"
245
+ long_desc <<-LONGDESC
246
+ Show configured logs monitoring
247
+ with --detail, show logs monitor details
248
+ LONGDESC
249
+ option :detail, :type => :boolean
250
+ def list
251
+ puts "Splash configured log monitoring :"
252
+ log_record_set = get_config.logs
253
+ puts 'No configured commands found' if log_record_set.empty?
254
+ log_record_set.each do |record|
255
+ puts " * log monitor : #{record[:log]}"
256
+ if options[:detail] then
257
+ puts " -> pattern : /#{record[:pattern]}/"
258
+ end
259
+ end
260
+ end
181
261
 
182
262
  end
183
263
  end
@@ -1,4 +1,7 @@
1
+ # Splash Configuration
1
2
  :splash:
3
+
4
+ ### Main Configuration
2
5
  :templates:
3
6
  :execution:
4
7
  :path: /etc/splash_execution_report.tpl
@@ -10,31 +13,86 @@
10
13
  - :stderr
11
14
  - :desc
12
15
  - :status
13
- :logs:
14
- - :log: /tmp/test
15
- :pattern: ERROR
16
- - :log: /var/log/message
17
- :pattern: error
16
+ - :exec_time
17
+ :backends:
18
+ :list:
19
+ - :file
20
+ - :redis
21
+ :stores:
22
+ :execution_trace:
23
+ :type: :file
24
+ :path: /tmp/splash
25
+ # :execution_trace:
26
+ # :type: :redis
27
+ # :host: localhost
28
+ # :port: 6379
29
+ # #:auth: "mykey"
30
+ # :base: 1
31
+ :transports:
32
+ :active: :rabbitmq
33
+ :rabbitmq:
34
+ :url: amqp://127.0.0.1
35
+ :daemon:
36
+ :logmon_scheduling:
37
+ :every: 20s
38
+ :process_name: "Splash : daemon."
39
+ :paths:
40
+ :pid_path: /tmp
41
+ :trace_path: /tmp/splash
42
+ :files:
43
+ :stdout_trace: stdout.txt
44
+ :stderr_trace: stderr.txt
45
+ :pid_file: splash.pid
18
46
  :prometheus:
19
47
  :pushgateway:
20
48
  :host: "localhost"
21
49
  :port: 9091
50
+
51
+
52
+ ### configuration of commands and scheduling
22
53
  :commands:
54
+ :id_root:
55
+ :desc: run id command on root
56
+ :command: id root
57
+ :true_test:
58
+ :desc: "test command returning true : 0"
59
+ :command: "true"
60
+ :schedule:
61
+ :every: "1h"
62
+ :on_failure: :ls_slash_tmp
63
+ :on_success: :pwd
23
64
  :false_test:
24
- :desc: "test command"
65
+ :desc: "test command returning false > 0"
25
66
  :command: "false"
67
+ :schedule:
68
+ :every: "1h"
69
+ :on_failure: :ls_slash_tmp
70
+ :on_success: :pwd
26
71
  :ls_slash_tmp:
27
72
  :desc: list file in /tmp
28
73
  :command: ls -al /tmp
29
74
  :user: daemon
30
- :daemon:
31
- :user: daemon
32
- :group: daemon
33
- :process_name: "Splash : Prometheus logs monitoring."
34
- :paths:
35
- :pid_path: /tmp
36
- :trace_path: /tmp/splash
37
- :files:
38
- :stdout_trace: stdout.txt
39
- :stderr_trace: stderr.txt
40
- :pid_file: splash.pid
75
+ :on_success: :echo1
76
+ :pwd:
77
+ :desc: run pwd
78
+ :command: pwd
79
+ :on_success: :echo1
80
+ :on_failure: :echo2
81
+ :echo1:
82
+ :desc: echo 'foo'
83
+ :command: echo foo
84
+ :on_failure: :echo3
85
+ :echo2:
86
+ :desc: echo 'bar'
87
+ :command: echo bar
88
+ :echo3:
89
+ :desc: echo 'been'
90
+ :command: echo been
91
+
92
+
93
+ ### configuration of monitored logs
94
+ :logs:
95
+ - :log: /tmp/test
96
+ :pattern: ERROR
97
+ - :log: /var/log/message
98
+ :pattern: error
@@ -0,0 +1,12 @@
1
+ Dir[File.dirname(__FILE__) + '/backends/*.rb'].each {|file| require file }
2
+
3
+ module Splash
4
+ module Backends
5
+ include Splash::Config
6
+ def get_backend(store)
7
+ aclass = "Splash::Backends::#{get_config[:backends][:stores][store][:type].to_s.capitalize}"
8
+ return Kernel.const_get(aclass)::new(store)
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,35 @@
1
+ module Splash
2
+ module Backends
3
+ class File
4
+ include Splash::Config
5
+ def initialize(store)
6
+ @config = get_config[:backends][:stores][store]
7
+ @path = @config[:path]
8
+ end
9
+
10
+ def list(pattern='*')
11
+ return Dir.glob(pattern)
12
+ end
13
+
14
+ def get(options)
15
+ return ::File.readlines("#{@path}/#{options[:key]}").join
16
+ end
17
+
18
+ def put(options)
19
+ ::File.open("#{@path}/#{options[:key]}", 'w') { |file|
20
+ file.write options[:value]
21
+ }
22
+ end
23
+
24
+ def del(options)
25
+ ::File.unlink("#{@path}/#{options[:key]}") if File.exist?("#{@path}/#{options[:key]}")
26
+ end
27
+
28
+ def exist?(options)
29
+ return ::File.exist?("#{@path}/#{options[:key]}")
30
+ end
31
+
32
+ end
33
+ end
34
+
35
+ end
@@ -0,0 +1,42 @@
1
+ require "redis"
2
+
3
+ module Splash
4
+ module Backends
5
+ class Redis
6
+ include Splash::Config
7
+ def initialize(store)
8
+ @config = get_config[:backends][:stores][store]
9
+ @store = ::Redis.new :host => @config[:host], :port => @config[:port], :db => @config[:base].to_i
10
+ @redis_cli_cmd = `which redis-cli`
11
+ @store.auth(@config[:auth]) if @config[:auth]
12
+ end
13
+
14
+ def list(pattern='*')
15
+ return @store.keys pattern
16
+ end
17
+
18
+ def get(options)
19
+ return @store.get(options[:key])
20
+ end
21
+
22
+ def put(options)
23
+ @store.set options[:key], options[:value]
24
+ end
25
+
26
+ def del(options)
27
+ @store.del options[:key]
28
+ end
29
+
30
+ def flush
31
+ `#{@redis_cli_cmd} -n 3 flushdb`
32
+ # @@store.flushdb
33
+ end
34
+
35
+ def exist?(options)
36
+ return ( not @store.get(options[:key]).nil?)
37
+ end
38
+
39
+ end
40
+ end
41
+
42
+ end
@@ -1,12 +1,13 @@
1
1
  require 'open3'
2
2
  require 'date'
3
-
3
+ require 'socket'
4
4
 
5
5
  module Splash
6
6
  class CommandWrapper
7
7
  include Splash::Templates
8
8
  include Splash::Config
9
9
  include Splash::Helpers
10
+ include Splash::Backends
10
11
 
11
12
  def initialize(name)
12
13
  @config = get_config
@@ -15,6 +16,12 @@ module Splash
15
16
  $stderr.puts "Splash : command #{@name} is not defined in configuration"
16
17
  exit 40
17
18
  end
19
+ @registry = Prometheus::Client.registry
20
+ @url = "http://#{@config.prometheus_pushgateway_host}:#{@config.prometheus_pushgateway_port}"
21
+ @metric_exitcode = Prometheus::Client::Gauge.new(:errorcode, docstring: 'SPLASH metric batch errorcode')
22
+ @metric_time = Prometheus::Client::Gauge.new(:exectime, docstring: 'SPLASH metric batch execution time')
23
+ @registry.register(@metric_exitcode)
24
+ @registry.register(@metric_time)
18
25
  end
19
26
 
20
27
  def ack
@@ -23,39 +30,42 @@ module Splash
23
30
  exit 0
24
31
  end
25
32
 
26
- def notify(value)
33
+ def notify(value,time)
27
34
  unless verify_service host: @config.prometheus_pushgateway_host ,port: @config.prometheus_pushgateway_port then
28
35
  $stderr.puts "Prometheus PushGateway Service IS NOT running"
29
36
  $stderr.puts "Exit without notification."
30
37
  exit 30
31
38
  end
32
- registry = Prometheus::Client.registry
33
- url = "http://#{@config.prometheus_pushgateway_host}:#{@config.prometheus_pushgateway_port}"
34
- metric = Prometheus::Client::Gauge.new(:errorcode, docstring: 'SPLASH metric batch errorcode')
35
- registry.register(metric)
36
- metric.set(value)
37
- Prometheus::Client::Push.new(@name, nil, url).add(registry)
38
- puts "Prometheus Gateway notified."
39
+ @metric_exitcode.set(value)
40
+ @metric_time.set(time)
41
+ hostname = Socket.gethostname
42
+ Prometheus::Client::Push.new(@name, hostname, @url).add(@registry)
43
+ puts " * Prometheus Gateway notified."
39
44
  end
40
45
 
41
46
 
42
47
  def call_and_notify(options)
43
48
  puts "Executing command : '#{@name}' "
49
+ start = Time.now
44
50
  unless options[:trace] then
45
- puts "Traceless execution"
51
+ puts " * Traceless execution"
46
52
  if @config.commands[@name.to_sym][:user] then
53
+ puts " * Execute with user : #{@config.commands[@name.to_sym][:user]}."
47
54
  system("sudo -u #{@config.commands[@name.to_sym][:user]} #{@config.commands[@name.to_sym][:command]} > /dev/null 2>&1")
48
55
  else
49
56
  system("#{@config.commands[@name.to_sym][:command]} > /dev/null 2>&1")
50
57
  end
58
+ time = Time.now - start
51
59
  exit_code = $?.exitstatus
52
60
  else
53
- puts "Tracefull execution"
61
+ puts " * Tracefull execution"
54
62
  if @config.commands[@name.to_sym][:user] then
63
+ puts " * Execute with user : #{@config.commands[@name.to_sym][:user]}."
55
64
  stdout, stderr, status = Open3.capture3("sudo -u #{@config.commands[@name.to_sym][:user]} #{@config.commands[@name.to_sym][:command]}")
56
65
  else
57
66
  stdout, stderr, status = Open3.capture3(@config.commands[@name.to_sym][:command])
58
67
  end
68
+ time = Time.now - start
59
69
  tp = Template::new(
60
70
  list_token: @config.execution_template_tokens,
61
71
  template_file: @config.execution_template_path)
@@ -67,12 +77,43 @@ module Splash
67
77
  tp.status = status.to_s
68
78
  tp.stdout = stdout
69
79
  tp.stderr = stderr
70
- filename = "#{@config[:trace_path]}/#{@name}_trace.last"
71
- File.open(filename, 'w') { |file| file.write(tp.output) }
80
+ tp.exec_time = time.to_s
81
+ backend = get_backend :execution_trace
82
+ key = "#{@name}_trace.last"
83
+ backend.put key: key, value: tp.output
72
84
  exit_code = status.exitstatus
85
+
73
86
  end
74
87
 
75
- notify(exit_code)
88
+ puts " => exitcode #{exit_code}"
89
+ if options[:notify] then
90
+ notify(exit_code,time.to_i)
91
+ else
92
+ puts " * Without Prometheus notification"
93
+ end
94
+ on_failure = (@config.commands[@name.to_sym][:on_failure])? @config.commands[@name.to_sym][:on_failure] : false
95
+ on_success = (@config.commands[@name.to_sym][:on_success])? @config.commands[@name.to_sym][:on_success] : false
96
+
97
+ if on_failure and exit_code > 0 then
98
+ puts " * On failure callback : #{on_failure}"
99
+ if @config.commands.keys.include? on_failure then
100
+ @name = on_failure.to_s
101
+ call_and_notify options
102
+ else
103
+ $stderr.puts "on_failure call error : configuration mistake : #{on_failure} command inexistant."
104
+ end
105
+ end
106
+ if on_success and exit_code == 0 then
107
+ puts " * On success callback : #{on_success}"
108
+ if @config.commands.keys.include? on_success then
109
+ @name = on_success.to_s
110
+ call_and_notify options
111
+ else
112
+ $stderr.puts "on_success call error : configuration mistake : #{on_success} command inexistant."
113
+ end
114
+ end
115
+
116
+
76
117
  exit exit_code
77
118
  end
78
119
  end
@@ -1,12 +1,14 @@
1
+ require 'etc'
1
2
  module Splash
2
3
  module Config
3
4
  include Splash::Helpers
4
5
  include Splash::Constants
5
6
 
6
7
 
7
-
8
+ # Class to manage configuration in Splash from Splash::Constants override by Yaml CONFIG
8
9
  class Configuration < Hash
9
10
  include Splash::Constants
11
+
10
12
  def initialize(config_file=CONFIG_FILE)
11
13
  config_from_file = readconf config_file
12
14
  self[:version] = VERSION
@@ -15,24 +17,57 @@ module Splash
15
17
  self[:prometheus_pushgateway_host] = (config_from_file[:prometheus][:pushgateway][:host])? config_from_file[:prometheus][:pushgateway][:host] : PROMETHEUS_PUSHGATEWAY_HOST
16
18
  self[:prometheus_pushgateway_port] = (config_from_file[:prometheus][:pushgateway][:port])? config_from_file[:prometheus][:pushgateway][:port] : PROMETHEUS_PUSHGATEWAY_PORT
17
19
  self[:daemon_process_name] = (config_from_file[:daemon][:process_name])? config_from_file[:daemon][:process_name] : DAEMON_PROCESS_NAME
18
- self[:daemon_user] = (config_from_file[:daemon][:user])? config_from_file[:daemon][:user] : DAEMON_USER
19
- self[:execution_template_tokens] = (config_from_file[:templates][:execution][:tokens])? config_from_file[:templates][:execution][:tokens] : TOKENS_LIST
20
+ self[:daemon_logmon_scheduling] = (config_from_file[:daemon][:logmon_scheduling])? config_from_file[:daemon][:logmon_scheduling] : DAEMON_LOGMON_SCHEDULING
21
+ self[:execution_template_tokens] = (config_from_file[:templates][:execution][:tokens])? config_from_file[:templates][:execution][:tokens] : EXECUTION_TEMPLATE_TOKENS_LIST
20
22
  self[:execution_template_path] = (config_from_file[:templates][:execution][:path])? config_from_file[:templates][:execution][:path] : EXECUTION_TEMPLATE
21
- self[:daemon_group] = (config_from_file[:daemon][:group])? config_from_file[:daemon][:group] : DAEMON_GROUP
22
- self[:pid_path] = (config_from_file[:daemon][:paths][:pid_path])? config_from_file[:daemon][:paths][:pid_path] : PID_PATH
23
+ self[:pid_path] = (config_from_file[:daemon][:paths][:pid_path])? config_from_file[:daemon][:paths][:pid_path] : DAEMON_PID_PATH
23
24
  self[:trace_path] = (config_from_file[:daemon][:paths][:trace_path])? config_from_file[:daemon][:paths][:trace_path] : TRACE_PATH
24
- self[:pid_file] = (config_from_file[:daemon][:files][:pid_file])? config_from_file[:daemon][:files][:pid_file] : PID_FILE
25
- self[:stdout_trace] = (config_from_file[:daemon][:files][:stdout_trace])? config_from_file[:daemon][:files][:stdout_trace] : STDOUT_TRACE
26
- self[:stderr_trace] = (config_from_file[:daemon][:files][:stderr_trace])? config_from_file[:daemon][:files][:stderr_trace] : STDERR_TRACE
25
+ self[:pid_file] = (config_from_file[:daemon][:files][:pid_file])? config_from_file[:daemon][:files][:pid_file] : DAEMON_PID_FILE
26
+ self[:stdout_trace] = (config_from_file[:daemon][:files][:stdout_trace])? config_from_file[:daemon][:files][:stdout_trace] : DAEMON_STDOUT_TRACE
27
+ self[:stderr_trace] = (config_from_file[:daemon][:files][:stderr_trace])? config_from_file[:daemon][:files][:stderr_trace] : DAEMON_STDERR_TRACE
28
+
29
+ self[:transports] = {} ; self[:transports].merge! TRANSPORTS_STRUCT ; self[:transports].merge! config_from_file[:transports] if config_from_file[:transports]
30
+ self[:backends] = {} ; self[:backends].merge! BACKENDS_STRUCT ; self[:backends].merge! config_from_file[:backends] if config_from_file[:backends]
31
+
27
32
  self[:logs] = (config_from_file[:logs])? config_from_file[:logs] : {}
28
33
  self[:commands] = (config_from_file[:commands])? config_from_file[:commands] : {}
29
34
 
30
35
  end
31
36
 
37
+ # @!group accessors on configurations Items
38
+
39
+ def Configuration.user_root
40
+ return Etc.getpwuid(0).name
41
+ end
42
+
43
+ def Configuration.group_root
44
+ return Etc.getgrgid(0).name
45
+ end
46
+
47
+ def user_root
48
+ return Configuration.user_root
49
+ end
50
+
51
+ def group_root
52
+ return Configuration.group_root
53
+ end
54
+
55
+
56
+ def backends
57
+ return self[:backends]
58
+ end
59
+
60
+ def transports
61
+ return self[:transport]
62
+ end
63
+
64
+ def daemon_logmon_scheduling
65
+ return self[:daemon_logmon_scheduling]
66
+ end
67
+
32
68
  def execution_template_path
33
69
  return self[:execution_template_path]
34
70
  end
35
-
36
71
  def execution_template_tokens
37
72
  return self[:execution_template_tokens]
38
73
  end
@@ -67,14 +102,6 @@ module Splash
67
102
  return self[:prometheus_pushgateway_port]
68
103
  end
69
104
 
70
- def daemon_user
71
- return self[:daemon_user]
72
- end
73
-
74
- def daemon_group
75
- return self[:daemon_group]
76
- end
77
-
78
105
  def full_pid_path
79
106
  return "#{self[:pid_path]}/#{self[:pid_file]}"
80
107
  end
@@ -87,6 +114,8 @@ module Splash
87
114
  return "#{self[:trace_path]}/#{self[:stderr_trace]}"
88
115
  end
89
116
 
117
+ # @!endgroup
118
+
90
119
  private
91
120
  def readconf(file = CONFIG_FILE)
92
121
  return YAML.load_file(file)[:splash]
@@ -95,18 +124,21 @@ module Splash
95
124
 
96
125
  end
97
126
 
98
-
127
+ # factory of Configuration Class instance
128
+ # @param [String] config_file the path of the YAML Config file
129
+ # @return [SPlash::Config::Configuration]
99
130
  def get_config(config_file=CONFIG_FILE)
100
131
  return Configuration::new config_file
101
132
  end
102
133
 
103
-
134
+ # Setup action method for installing Splash
135
+ # @return [Integer] an errorcode value
104
136
  def setupsplash
105
137
  conf_in_path = search_file_in_gem "prometheus-splash", "config/splash.yml"
106
138
  full_res = 0
107
139
  puts "Splash -> setup : "
108
140
  print "* Installing Configuration file : #{CONFIG_FILE} : "
109
- if install_file source: conf_in_path, target: CONFIG_FILE, mode: "644", owner: "root", group: "wheel" then
141
+ if install_file source: conf_in_path, target: CONFIG_FILE, mode: "644", owner: Configuration.user_root, group: Configuration.group_root then
110
142
  puts "[OK]"
111
143
  else
112
144
  full_res =+ 1
@@ -115,7 +147,7 @@ module Splash
115
147
  config = get_config
116
148
  report_in_path = search_file_in_gem "prometheus-splash", "templates/report.txt"
117
149
  print "* Installing template file : #{config.execution_template_path} : "
118
- if install_file source: report_in_path, target: config.execution_template_path, mode: "644", owner: "root", group: "wheel" then
150
+ if install_file source: report_in_path, target: config.execution_template_path, mode: "644", owner: config.user_root, group: config.group_root then
119
151
  puts "[OK]"
120
152
  else
121
153
  full_res =+ 1
@@ -123,7 +155,7 @@ module Splash
123
155
  end
124
156
 
125
157
  print "* Creating/Checking pid file path : #{config[:pid_path]} : "
126
- if make_folder path: config[:pid_path], mode: "644", owner: "root", group: "wheel" then
158
+ if make_folder path: config[:pid_path], mode: "644", owner: config.user_root, group: config.group_root then
127
159
  puts "[OK]"
128
160
  else
129
161
  full_res =+ 1
@@ -131,7 +163,7 @@ module Splash
131
163
  end
132
164
 
133
165
  print "* Creating/Checking trace file path : #{config[:trace_path]} : "
134
- if make_folder path: config[:trace_path], mode: "777", owner: config.daemon_user, group: config.daemon_group then
166
+ if make_folder path: config[:trace_path], mode: "644", owner: config.user_root, group: config.group_root then
135
167
  puts "[OK]"
136
168
  else
137
169
  full_res =+ 1
@@ -148,12 +180,14 @@ module Splash
148
180
 
149
181
  end
150
182
 
183
+ # Sanitycheck action method for testing installation of Splash
184
+ # @return [Integer] an errorcode value
151
185
  def checkconfig
152
186
  puts "Splash -> sanitycheck : "
153
187
  config = get_config
154
188
  full_res = 0
155
189
  print "* Config file : #{CONFIG_FILE} : "
156
- res = verify_file(name: CONFIG_FILE, mode: "644", owner: "root", group: "wheel")
190
+ res = verify_file(name: CONFIG_FILE, mode: "644", owner: config.user_root, group: config.group_root)
157
191
  if res.empty? then
158
192
  print "[OK]\n"
159
193
  else
@@ -163,7 +197,7 @@ module Splash
163
197
  end
164
198
 
165
199
  print "* PID Path : #{config[:pid_path]} : "
166
- res = verify_folder(name: config[:pid_path], mode: "644", owner: "root", group: "wheel")
200
+ res = verify_folder(name: config[:pid_path], mode: "644", owner: config.user_root, group: config.group_root)
167
201
  if res.empty? then
168
202
  print "[OK]\n"
169
203
  else
@@ -174,7 +208,7 @@ module Splash
174
208
  end
175
209
 
176
210
  print "* trace Path : #{config[:trace_path]} : "
177
- res = verify_folder(name: config[:trace_path], mode: "777", owner: config.daemon_user, group: config.daemon_group)
211
+ res = verify_folder(name: config[:trace_path], mode: "777", owner: config.user_root, group: config.group_root)
178
212
  if res.empty? then
179
213
  print "[OK]\n"
180
214
  else
@@ -202,6 +236,11 @@ module Splash
202
236
 
203
237
  private
204
238
 
239
+ # facilities to find a file in gem path
240
+ # @param [String] _gem a Gem name
241
+ # @param [String] _file a file relative path in the gem
242
+ # @return [String] the path of the file, if found.
243
+ # @return [False] if not found
205
244
  def search_file_in_gem(_gem,_file)
206
245
  if Gem::Specification.respond_to?(:find_by_name)
207
246
  begin
@@ -1,22 +1,35 @@
1
1
  module Splash
2
2
  module Constants
3
- VERSION = "0.0.2"
3
+ VERSION = "0.0.3"
4
+
4
5
  CONFIG_FILE = "/etc/splash.yml"
5
- DAEMON_USER = "root"
6
- DAEMON_GROUP = "wheel"
7
- PID_PATH="/var/run"
8
6
  TRACE_PATH="/var/run/splash"
9
- PID_FILE="splash.pid"
10
- STDOUT_TRACE="stdout.txt"
11
- STDERR_TRACE="stderr.txt"
12
- DAEMON_PROCESS_NAME="Splash : Prometheus logs monitoring."
7
+
8
+ DAEMON_LOGMON_SCHEDULING={ :every => '20s'}
9
+ DAEMON_PROCESS_NAME="Splash : daemon."
10
+ DAEMON_PID_PATH="/var/run"
11
+ DAEMON_PID_FILE="splash.pid"
12
+ DAEMON_STDOUT_TRACE="stdout.txt"
13
+ DAEMON_STDERR_TRACE="stderr.txt"
14
+
13
15
  AUTHOR="Romain GEORGES"
14
16
  EMAIL = "gems@ultragreen.net"
15
17
  COPYRIGHT="Ultragreen (c) 2020"
16
18
  LICENSE="BSD-2-Clause"
19
+
17
20
  PROMETHEUS_PUSHGATEWAY_HOST = "localhost"
18
21
  PROMETHEUS_PUSHGATEWAY_PORT = "9091"
22
+
19
23
  EXECUTION_TEMPLATE="/etc/splash_execution_report.tpl"
20
- TOKENS_LIST = [:date,:cmd_name,:cmd_line,:stdout,:stderr,:desc,:status]
24
+ EXECUTION_TEMPLATE_TOKENS_LIST = [:date,:cmd_name,:cmd_line,:stdout,:stderr,:desc,:status,:exec_time]
25
+
26
+ BACKENDS_STRUCT = { :list => [:file,:redis],
27
+ :stores => { :execution_trace => { :type => :file, :path => "/var/run/splash" }}}
28
+ TRANSPORTS_STRUCT = { :list => [:rabbitmq],
29
+ :active => :rabbitmq,
30
+ :rabbitmq => { :url => 'amqp://localhost/'} }
31
+
32
+
33
+
21
34
  end
22
35
  end
@@ -5,6 +5,7 @@ module Splash
5
5
  include Splash::Constants
6
6
  include Splash::Helpers
7
7
  include Splash::Config
8
+ include Splash::Orchestrator
8
9
 
9
10
  def startdaemon(options = {})
10
11
  config = get_config
@@ -17,21 +18,9 @@ module Splash
17
18
  unless File::exist? config.full_pid_path then
18
19
  res = daemonize :description => config.daemon_process_name,
19
20
  :pid_file => config.full_pid_path,
20
- :daemon_user => config.daemon_user,
21
- :daemon_group => config.daemon_group,
22
21
  :stdout_trace => config.full_stdout_trace_path,
23
22
  :stderr_trace => config.full_stderr_trace_path do
24
- result = LogScanner::new
25
- while true
26
- begin
27
- sleep 5
28
- puts "Notify"
29
- result.analyse
30
- result.notify
31
- rescue Errno::ECONNREFUSED
32
- $stderr.puts "PushGateway seems to be done, please start it."
33
- end
34
- end
23
+ Scheduler::new
35
24
  end
36
25
  if res == 0 then
37
26
  pid = `cat #{config.full_pid_path}`.to_i
@@ -7,7 +7,10 @@ module Splash
7
7
  module Helpers
8
8
 
9
9
 
10
-
10
+ # facilité pour récupérer un PID depuis une regexp
11
+ # @param [Hash] options
12
+ # @option options [String] :pattern une regexp
13
+ # @return [String] le PID
11
14
  def get_process(options = {})
12
15
  pattern = options[:pattern]
13
16
  res = `ps aux|grep '#{pattern}'|grep -v grep`.to_s
@@ -18,7 +21,8 @@ module Splash
18
21
  end
19
22
  end
20
23
 
21
-
24
+ # facilité pour vérifier si le process actif est root
25
+ # @return [Bool] vrai ou faux
22
26
  def is_root?
23
27
  case (Process.uid)
24
28
  when 0
@@ -28,6 +32,9 @@ module Splash
28
32
  end
29
33
  end
30
34
 
35
+ # facilité pour s'assurer qu'on execute une méthode avec les droits root
36
+ # @param [Symbol] method a method name th wrap
37
+ # @return [void] le retour de la méthode wrappée
31
38
  def run_as_root(method)
32
39
  unless is_root?
33
40
  $stderr.puts "You need to be root to execute this subcommands : #{method.to_s}"
@@ -39,13 +46,18 @@ module Splash
39
46
  end
40
47
 
41
48
  # method for daemonize blocks
42
- # @param [Hash] _options the list of options, keys are symbols
43
- # @option _options [String] :description the description of the process, use for $0
44
- # @option _options [String] :pid_file the pid filenam
49
+ # @param [Hash] options the list of options, keys are symbols
50
+ # @option options [String] :description the description of the process, use for $0
51
+ # @option options [String] :pid_file the pid filename
52
+ # @option options [String] :daemon_user the user to change privileges
53
+ # @option options [String] :daemon_group the group to change privileges
54
+ # @option options [String] :stderr_trace the path of the file where to redirect STDERR
55
+ # @option options [String] :stdout_trace the path of the file where to redirect STDOUT
56
+ # @option options [Bool] :debug option to run foreground
45
57
  # @yield a process definion or block given
46
58
  # @example usage inline
47
59
  # class Test
48
- # include Splash::Helpers::Application
60
+ # include Splash::Helpers
49
61
  # private :daemonize
50
62
  # def initialize
51
63
  # @loop = Proc::new do
@@ -62,7 +74,7 @@ module Splash
62
74
  #
63
75
  # @example usage block
64
76
  # class Test
65
- # include Splash::Helpers::Application
77
+ # include Splash::Helpers
66
78
  # include Dorsal::Privates
67
79
  # private :daemonize
68
80
  # def initialize
@@ -88,15 +100,17 @@ module Splash
88
100
  fork do
89
101
  #Process.daemon
90
102
  File.open(options[:pid_file],"w"){|f| f.puts Process.pid } if options[:pid_file]
91
- uid = Etc.getpwnam(options[:daemon_user]).uid
92
- gid = Etc.getgrnam(options[:daemon_group]).gid
93
- Process::UID.change_privilege(uid)
94
- # Process::GID.change_privilege(gid)
95
- $stdout.reopen(options[:stdout_trace], "w")
96
- $stderr.reopen(options[:stderr_trace], "w")
103
+ if options[:daemon_user] and options[:daemon_group] then
104
+ uid = Etc.getpwnam(options[:daemon_user]).uid
105
+ gid = Etc.getgrnam(options[:daemon_group]).gid
106
+ Process::UID.change_privilege(uid)
107
+ # Process::GID.change_privilege(gid)
108
+ end
109
+ $stdout.reopen(options[:stdout_trace], "w") if options[:stdout_trace]
110
+ $stderr.reopen(options[:stderr_trace], "w") if options[:stderr_trace]
97
111
 
98
112
  #$0 = options[:description]
99
- Process.setproctitle options[:description]
113
+ Process.setproctitle options[:description] if options[:description]
100
114
 
101
115
  yield
102
116
 
@@ -110,6 +124,9 @@ module Splash
110
124
  # @param [Hash] options
111
125
  # @option options [String] :source le chemin source du fichier
112
126
  # @option options [String] :target le chemin cible du fichier
127
+ # @option options [String] :mode les droits du fichier du type Octal "XXX"
128
+ # @option options [String] :owner le owner du fichier
129
+ # @option options [String] :group le groupe du fichier
113
130
  def install_file(options = {})
114
131
  #begin
115
132
  FileUtils::copy options[:source], options[:target] #unless File::exist? options[:target]
@@ -124,6 +141,9 @@ module Splash
124
141
  # facilité de création de répertoire
125
142
  # @param [Hash] options
126
143
  # @option options [String] :path le répertoire à créer (relatif ou absolut)
144
+ # @option options [String] :mode les droits du fichier du type Octal "XXX"
145
+ # @option options [String] :owner le owner du fichier
146
+ # @option options [String] :group le groupe du fichier
127
147
  def make_folder(options = {})
128
148
  begin
129
149
  FileUtils::mkdir_p options[:path] unless File::exist? options[:path]
@@ -1,3 +1,5 @@
1
+ require 'socket'
2
+
1
3
  module Splash
2
4
  class LogScanner
3
5
  include Splash::Constants
@@ -5,10 +7,14 @@ module Splash
5
7
 
6
8
  def initialize
7
9
  @logs_target = get_config.logs
8
-
10
+ @config = get_config
9
11
  @registry = Prometheus::Client.registry
10
- @metric = Prometheus::Client::Gauge.new(:logerror, docstring: 'SPLASH metric log error', labels: [:log ])
11
- @registry.register(@metric)
12
+ @metric_count = Prometheus::Client::Gauge.new(:logerrors, docstring: 'SPLASH metric log error', labels: [:log ])
13
+ @metric_missing = Prometheus::Client::Gauge.new(:logmissing, docstring: 'SPLASH metric log missing', labels: [:log ])
14
+ @metric_lines = Prometheus::Client::Gauge.new(:loglines, docstring: 'SPLASH metric log lines numbers', labels: [:log ])
15
+ @registry.register(@metric_count)
16
+ @registry.register(@metric_missing)
17
+ @registry.register(@metric_lines)
12
18
  end
13
19
 
14
20
  def analyse
@@ -18,8 +24,9 @@ module Splash
18
24
  if File.exist?(record[:log]) then
19
25
  record[:count] = File.readlines(record[:log]).grep(/#{record[:pattern]}/).size
20
26
  record[:status] = :matched if record[:count] > 0
27
+ record[:lines] = `wc -l "#{record[:log]}"`.strip.split(/\s+/)[0].to_i unless record[:status] == :missing
21
28
  else
22
- record[:status] = :mssing
29
+ record[:status] = :missing
23
30
  end
24
31
  end
25
32
  end
@@ -29,10 +36,24 @@ module Splash
29
36
  end
30
37
 
31
38
  def notify
39
+ unless verify_service host: @config.prometheus_pushgateway_host ,port: @config.prometheus_pushgateway_port then
40
+ $stderr.puts "Prometheus PushGateway Service IS NOT running"
41
+ $stderr.puts "Exit without notification."
42
+ exit 30
43
+ end
44
+ puts "Sending metrics to Prometheus Pushgateway"
32
45
  @logs_target.each do |item|
33
- @metric.set(item[:count], labels: { log: item[:log] })
46
+ missing = (item[:status] == :missing)? 1 : 0
47
+ puts " * Sending metrics for #{item[:log]}"
48
+ @metric_count.set(item[:count], labels: { log: item[:log] })
49
+ @metric_missing.set(missing, labels: { log: item[:log] })
50
+ lines = (item[:lines])? item[:lines] : 0
51
+ @metric_lines.set(lines, labels: { log: item[:log] })
34
52
  end
35
- Prometheus::Client::Push.new('Splash').add(@registry)
53
+ hostname = Socket.gethostname
54
+ url = "http://#{@config.prometheus_pushgateway_host}:#{@config.prometheus_pushgateway_port}"
55
+ Prometheus::Client::Push.new('Splash',hostname, url).add(@registry)
56
+ puts "Sending done."
36
57
  end
37
58
 
38
59
  end
@@ -0,0 +1,49 @@
1
+ module Splash
2
+ module Orchestrator
3
+
4
+ module SchedulerHooks
5
+ def on_pre_trigger(job, trigger_time)
6
+
7
+ end
8
+
9
+ def on_post_trigger(job, trigger_time)
10
+
11
+ end
12
+
13
+ def init_log
14
+
15
+ end
16
+ end
17
+
18
+
19
+ class Scheduler
20
+ include Splash::Constants
21
+ include Splash::Helpers
22
+ include Splash::Config
23
+ def initialize
24
+ @server = Rufus::Scheduler::new
25
+ @server.extend SchedulerHooks
26
+ @server.init_log
27
+ @result = LogScanner::new
28
+ @server.every '20s' do
29
+ begin
30
+ puts "Notify"
31
+ @result.analyse
32
+ @result.notify
33
+ $stdout.flush
34
+ rescue Errno::ECONNREFUSED
35
+ $stderr.puts "PushGateway seems to be done, please start it."
36
+ end
37
+ end
38
+ @server.join
39
+ end
40
+
41
+ def terminate
42
+ end
43
+
44
+ end
45
+
46
+
47
+ end
48
+
49
+ end
@@ -0,0 +1,18 @@
1
+ Dir[File.dirname(__FILE__) + '/transports/*.rb'].each {|file| require file }
2
+
3
+ module Splash
4
+ module Transports
5
+ include Splash::Config
6
+
7
+ def get_default_subscriber
8
+ aclass = "Splash::Transports::#{get_config[:transports][:active].to_s.capitalize}::Suscriber"
9
+ return Kernel.const_get(aclass)::new
10
+ end
11
+
12
+ def get_default_client
13
+ aclass = "Splash::Transports::#{get_config[:transports][:active].to_s.capitalize}::Client"
14
+ return Kernel.const_get(aclass)::new
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,45 @@
1
+ require 'bunny'
2
+ module Splash
3
+ module Transports
4
+ module RabbitMQ
5
+
6
+ class Subscriber
7
+ def initialize
8
+
9
+ end
10
+ end
11
+
12
+
13
+ class Client
14
+ def initialize
15
+ @connection = Bunny.new
16
+ @connection.start
17
+ @channel = @connection.create_channel
18
+ end
19
+
20
+
21
+ def publish(options ={})
22
+ return @channel.default_exchange.publish(options[:message], :routing_key => options[:queue])
23
+ end
24
+
25
+ def ack
26
+ return @channel.acknowledge(delivery_info.delivery_tag, false)
27
+ end
28
+
29
+
30
+ def get(options ={})
31
+ queue = @channel.queue(options[:queue])
32
+ delivery_info, properties, payload = queue.pop
33
+ res = {:message => payload}
34
+ res[:ack] = delivery_info.delivery_tag if options[:noack]
35
+ return res
36
+ end
37
+
38
+ def close
39
+ @connection.close
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+ end
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Splash::Constants::VERSION
9
9
  spec.authors = [Splash::Constants::AUTHOR]
10
10
  spec.email = [Splash::Constants::EMAIL]
11
- spec.description = %q{Prometheus Logs and Batchs supervision over PushGateway}
12
- spec.summary = %q{Supervision with Prometheus of Logs and Asynchronous tasks for Services or Hosts }
11
+ spec.description = %q{Prometheus Logs and Batchs supervision over PushGateway and commands orchestration}
12
+ spec.summary = %q{Supervision with Prometheus of Logs and Asynchronous tasks orchestration for Services or Hosts }
13
13
  spec.homepage = "http://www.ultragreen.net"
14
14
  spec.license = Splash::Constants::LICENSE
15
15
  spec.require_paths << 'bin'
@@ -21,6 +21,8 @@ Gem::Specification.new do |spec|
21
21
  spec.require_paths = ["lib"]
22
22
  spec.add_runtime_dependency 'thor','~> 1.0.1'
23
23
  spec.add_runtime_dependency 'prometheus-client','~> 2.0.0'
24
+ spec.add_runtime_dependency 'rufus-scheduler','~> 3.6.0'
25
+ spec.add_runtime_dependency 'redis','~> 4.1.3'
24
26
  spec.add_development_dependency 'rake', '~> 13.0.1'
25
27
  spec.add_development_dependency 'rspec', '~> 3.9.0'
26
28
  spec.add_development_dependency 'yard', '~> 0.9.24'
@@ -0,0 +1,72 @@
1
+ require_relative '../lib/splash/templates'
2
+
3
+ include Splash::Templates
4
+
5
+ describe Template do
6
+ $template_file = "/tmp/template.txt"
7
+ $nonexistantfile = "/tmp/nonexistant.txt"
8
+ $template = "Hello %%NAME%% !!"
9
+ $result = "Hello Romain !!"
10
+ $goodtoken = :name
11
+ $badtoken = :surname
12
+ $value = 'Romain'
13
+ before :all do
14
+ `echo "#{$template}" > #{$template_file}`
15
+ File::unlink($nonexistantfile) if File::exist?($nonexistantfile)
16
+ end
17
+ subject { Template }
18
+ specify { should be_an_instance_of Class }
19
+ context "Exception case" do
20
+ it "should raise NoTemplateFile if template file not exist" do
21
+ expect { Template::new({:list_token => [$goodtoken] , :template_file => $nonexistantfile}) }.to raise_error NoTemplateFile
22
+ end
23
+ it "should raise NotAToken if try to send ##{$badtoken} and '#{$badtoken}' not a valid token" do
24
+ expect { Template::new({ :list_token => [$goodtoken], :template_file => $template_file}).send($badtoken.to_sym)}.to raise_error NotAToken
25
+ end
26
+ it "should raise InvalidTokenList if initialized with ['#{$goodtoken}','#{$badtoken}'] tokens list" do
27
+ expect { Template::new({ :list_token => [$goodtoken,$badtoken] , :template_file => $template_file})}.to raise_error InvalidTokenList
28
+ end
29
+ it "should raise NoTemplateFile if template file not exist AND initialized with ['#{$goodtoken}','#{$badtoken}'] tokens list" do
30
+ expect { Template::new({ :list_token => [$goodtoken,$badtoken] , :template_file => $nonexistantfile})}.to raise_error NoTemplateFile
31
+ end
32
+ end
33
+
34
+ context "Template <execution> with token '#{$goodtoken}', content = '#{$content}', and ##{$goodtoken}='#{$value}'" do
35
+ before :all do
36
+ $test = Template::new({ :list_token => [$goodtoken] , :template_file => $template_file})
37
+ end
38
+ context "#content" do
39
+ specify {expect($test.content).to be_an_instance_of String }
40
+ it "should have '#{$template}' in #content" do
41
+ expect( $test.content).to eq($template)
42
+ end
43
+ specify {expect($test).to_not respond_to 'content=' }
44
+ end
45
+ context "#token_list" do
46
+ specify {expect($test.list_token).to be_an_instance_of Array }
47
+ it "should have ['#{$goodtoken}'] in #list_token" do
48
+ expect($test.list_token).to eq([$goodtoken])
49
+ end
50
+ specify { expect($test).to_not respond_to 'token_list=' }
51
+ end
52
+ context "virtual (methode_missing) #{$goodtoken}" do
53
+ specify { expect($test.send($goodtoken.to_sym)).to be_an_instance_of String }
54
+ specify { expect($test).to respond_to(:name) }
55
+ specify { $test.name = $value; expect($test.name).to eq($value) }
56
+ it "should raise ArgumentError if virtual methode '#name=' got non String arguement (accessor)" do
57
+ expect { $test.name = 1 }.to raise_error ArgumentError
58
+ end
59
+ end
60
+ context "#output" do
61
+ it "should #output 'Hello Romain !!' if set #name = 'Romain' and msg send #output" do
62
+ $test.name = 'Romain'
63
+ expect( $test.output).to eq('Hello Romain !!')
64
+ end
65
+ specify { expect($test).to_not respond_to 'output=' }
66
+ end
67
+ after :all do
68
+ File::unlink($template_file) if File::exist?($template_file)
69
+ $test = nil
70
+ end
71
+ end
72
+ end
@@ -6,6 +6,7 @@ Command : %%CMD_NAME%%
6
6
  full command line : %%CMD_LINE%%
7
7
  Description : %%DESC%%
8
8
  errorcode : %%STATUS%%
9
+ Execution time (sec) : %%EXEC_TIME%%
9
10
 
10
11
  STDOUT:
11
12
  -------
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prometheus-splash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Romain GEORGES
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-04 00:00:00.000000000 Z
11
+ date: 2020-04-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -38,6 +38,34 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 2.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rufus-scheduler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.6.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.6.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: redis
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 4.1.3
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 4.1.3
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: rake
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -136,7 +164,8 @@ dependencies:
136
164
  - - "~>"
137
165
  - !ruby/object:Gem::Version
138
166
  version: '0.1'
139
- description: Prometheus Logs and Batchs supervision over PushGateway
167
+ description: Prometheus Logs and Batchs supervision over PushGateway and commands
168
+ orchestration
140
169
  email:
141
170
  - gems@ultragreen.net
142
171
  executables:
@@ -150,14 +179,21 @@ files:
150
179
  - Rakefile
151
180
  - bin/splash
152
181
  - config/splash.yml
182
+ - lib/splash/backends.rb
183
+ - lib/splash/backends/file.rb
184
+ - lib/splash/backends/redis.rb
153
185
  - lib/splash/commands.rb
154
186
  - lib/splash/config.rb
155
187
  - lib/splash/constants.rb
156
188
  - lib/splash/controller.rb
157
189
  - lib/splash/helpers.rb
158
190
  - lib/splash/logs.rb
191
+ - lib/splash/orchestrator.rb
159
192
  - lib/splash/templates.rb
193
+ - lib/splash/transports.rb
194
+ - lib/splash/transports/rabbitmq.rb
160
195
  - prometheus-splash.gemspec
196
+ - spec/templates_spec.rb
161
197
  - templates/report.txt
162
198
  - templates/splashd.service
163
199
  - ultragreen_roodi_coding_convention.yml
@@ -183,6 +219,7 @@ requirements: []
183
219
  rubygems_version: 3.1.2
184
220
  signing_key:
185
221
  specification_version: 4
186
- summary: Supervision with Prometheus of Logs and Asynchronous tasks for Services or
187
- Hosts
188
- test_files: []
222
+ summary: Supervision with Prometheus of Logs and Asynchronous tasks orchestration
223
+ for Services or Hosts
224
+ test_files:
225
+ - spec/templates_spec.rb