prometheus-splash 0.0.1 → 0.0.2
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/Rakefile +7 -1
- data/bin/splash +96 -18
- data/config/splash.yml +23 -0
- data/lib/splash/commands.rb +79 -0
- data/lib/splash/config.rb +87 -7
- data/lib/splash/constants.rb +5 -1
- data/lib/splash/controller.rb +69 -13
- data/lib/splash/helpers.rb +39 -7
- data/lib/splash/templates.rb +68 -0
- data/{splash.gemspec → prometheus-splash.gemspec} +0 -0
- data/templates/report.txt +19 -0
- metadata +5 -3
- data/lib/splash/command.rb +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e6fae61b205672ab555b7cd28f0c0bfc0c48bacbaa81f9696a7ce16ef9eaa2e
|
4
|
+
data.tar.gz: e9167d60ea4537298014c7af7ee5214ff124d66b1b880925b18069e3a2e5db88
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b7e241e27d99e1ca480d387a1c87a86583113d2393756200dc1b167b069b7c24253c911a6dfd05c352f821c3d5e4c691a74a2ace2611f6adf08c545d76019aa
|
7
|
+
data.tar.gz: 6c5c3579c210e000bdac1f9220b0b89d5bb6e0f1997ea48061d7fe8734546689f18b22fa5d083c4a3fb36e6333b7cdf05637f3dd4c4b5d62ed0988050d758b26
|
data/Rakefile
CHANGED
@@ -24,7 +24,7 @@ CLEAN.include('*.tmp','*.old')
|
|
24
24
|
CLOBBER.include('*.tmp', 'build/*','#*#')
|
25
25
|
|
26
26
|
|
27
|
-
content = File::readlines(File.join(File.dirname(__FILE__), 'splash.gemspec')).join
|
27
|
+
content = File::readlines(File.join(File.dirname(__FILE__), 'prometheus-splash.gemspec')).join
|
28
28
|
spec = eval(content)
|
29
29
|
|
30
30
|
RSpec::Core::RakeTask.new('spec')
|
@@ -59,3 +59,9 @@ Rake::RDocTask.new('rdoc') do |d|
|
|
59
59
|
end
|
60
60
|
|
61
61
|
task :default => [:gem]
|
62
|
+
|
63
|
+
task :stage do
|
64
|
+
Rake::Task["clean"].invoke
|
65
|
+
Rake::Task["clobber"].invoke
|
66
|
+
Rake::Task["install"].invoke
|
67
|
+
end
|
data/bin/splash
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
#!/usr/bin/env ruby -W:no-deprecated
|
2
2
|
|
3
|
-
require 'prometheus/client'
|
4
|
-
require 'prometheus/client/push'
|
5
3
|
|
6
4
|
begin
|
5
|
+
require 'prometheus/client'
|
6
|
+
require 'prometheus/client/push'
|
7
7
|
require 'thor'
|
8
8
|
rescue Gem::GemNotFoundException
|
9
9
|
$stderr.puts "Loadind error, it's like you try to run Splash, with a lake of dependencies."
|
@@ -16,8 +16,9 @@ require 'yaml'
|
|
16
16
|
require 'splash/constants'
|
17
17
|
require 'splash/helpers'
|
18
18
|
require 'splash/config'
|
19
|
+
require 'splash/templates'
|
19
20
|
|
20
|
-
require 'splash/
|
21
|
+
require 'splash/commands'
|
21
22
|
require 'splash/logs'
|
22
23
|
require 'splash/controller'
|
23
24
|
|
@@ -30,14 +31,79 @@ module CLISplash
|
|
30
31
|
|
31
32
|
|
32
33
|
class Commands < Thor
|
34
|
+
include Splash::Config
|
33
35
|
|
34
|
-
option :ack, :type => :boolean
|
35
36
|
desc "wrap NAME", "wrapping for command or ack result"
|
37
|
+
long_desc <<-LONGDESC
|
38
|
+
wrapping for command or ack result
|
39
|
+
with --no-trace prevent storing execution trace in TRACE_PATH (see config file)
|
40
|
+
with --ack, notify errorcode=0 to Prometheus PushGateway
|
41
|
+
LONGDESC
|
42
|
+
option :trace, :type => :boolean, :default => true
|
43
|
+
option :ack, :type => :boolean, negate: false
|
36
44
|
def wrap(name)
|
37
|
-
|
38
|
-
|
39
|
-
|
45
|
+
if is_root? then
|
46
|
+
command = Splash::CommandWrapper::new(name)
|
47
|
+
command.ack if options[:ack]
|
48
|
+
command.call_and_notify trace: options[:trace]
|
49
|
+
else
|
50
|
+
$stderr.puts "Command wrapping need to be run as root"
|
51
|
+
exit 60
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
desc "list", "Show configured commands"
|
57
|
+
long_desc <<-LONGDESC
|
58
|
+
Show configured commands
|
59
|
+
with --detail, show command details
|
60
|
+
LONGDESC
|
61
|
+
option :detail, :type => :boolean
|
62
|
+
def list
|
63
|
+
puts "Splash configured commands :"
|
64
|
+
list = get_config.commands
|
65
|
+
puts 'No configured commands found' if list.keys.empty?
|
66
|
+
listc.keys.each do |command|
|
67
|
+
puts " * #{command.to_s}"
|
68
|
+
if options[:detail] then
|
69
|
+
puts " - command line : '#{list[command][:command]}'"
|
70
|
+
puts " - command description : '#{list[command][:desc]}'"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
desc "show COMMAND", "Show specific configured command COMMAND"
|
77
|
+
def show(command)
|
78
|
+
list = get_config.commands
|
79
|
+
if list.keys.include? command.to_sym then
|
80
|
+
puts "Splash command : #{command}"
|
81
|
+
puts " - command line : '#{list[command.to_sym][:command]}'"
|
82
|
+
puts " - command description : '#{list[command.to_sym][:desc]}'"
|
83
|
+
else
|
84
|
+
$stderr.puts "Command not configured"
|
85
|
+
exit 50
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
desc "lastrun COMMAND", "Show last running result for specific configured command COMMAND"
|
91
|
+
def lastrun(command)
|
92
|
+
list = get_config.commands
|
93
|
+
if list.keys.include? command.to_sym then
|
94
|
+
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}")
|
98
|
+
else
|
99
|
+
puts "Command not already runned."
|
100
|
+
end
|
101
|
+
else
|
102
|
+
$stderr.puts "Command not configured"
|
103
|
+
exit 50
|
104
|
+
end
|
40
105
|
end
|
106
|
+
|
41
107
|
end
|
42
108
|
|
43
109
|
|
@@ -47,37 +113,49 @@ module CLISplash
|
|
47
113
|
option :foreground, :type => :boolean
|
48
114
|
desc "start", "Starting Logs Monitor Daemon"
|
49
115
|
def start
|
50
|
-
run_as_root :startdaemon
|
116
|
+
errorcode = run_as_root :startdaemon
|
117
|
+
exit errorcode
|
51
118
|
end
|
52
119
|
|
53
120
|
desc "stop", "Stopping Logs Monitor Daemon"
|
54
121
|
def stop
|
55
|
-
run_as_root :stopdaemon
|
122
|
+
errorcode = run_as_root :stopdaemon
|
123
|
+
exit errorcode
|
124
|
+
end
|
125
|
+
|
126
|
+
desc "status", "Logs Monitor Daemon status"
|
127
|
+
def status
|
128
|
+
errorcode = run_as_root :statusdaemon
|
129
|
+
exit errorcode
|
56
130
|
end
|
57
131
|
|
58
132
|
|
59
133
|
end
|
60
134
|
|
135
|
+
|
136
|
+
|
137
|
+
|
61
138
|
class Config < Thor
|
62
139
|
include Splash::Config
|
63
140
|
include Splash::Helpers
|
64
141
|
|
65
142
|
desc "setup", "Setup installation fo Splash"
|
66
143
|
def setup
|
67
|
-
run_as_root :setupsplash
|
68
|
-
|
144
|
+
errorcode = run_as_root :setupsplash
|
145
|
+
exit errorcode
|
69
146
|
end
|
70
147
|
|
71
148
|
desc "sanitycheck", "Verify installation fo Splash"
|
72
149
|
def sanitycheck
|
73
|
-
run_as_root :checkconfig
|
150
|
+
errorcode = run_as_root :checkconfig
|
151
|
+
exit errorcode
|
74
152
|
end
|
75
153
|
|
76
154
|
desc "version", "display current Splash version"
|
77
155
|
def version
|
78
|
-
|
79
|
-
|
80
|
-
|
156
|
+
config = get_config
|
157
|
+
puts "Splash version : #{config.version}, Author : #{config.author}"
|
158
|
+
puts config.copyright
|
81
159
|
end
|
82
160
|
|
83
161
|
|
@@ -105,9 +183,9 @@ module CLISplash
|
|
105
183
|
end
|
106
184
|
|
107
185
|
class CLI < Thor
|
108
|
-
|
109
|
-
|
110
|
-
|
186
|
+
def self.exit_on_failure?
|
187
|
+
true
|
188
|
+
end
|
111
189
|
|
112
190
|
include CLISplash
|
113
191
|
desc "commands SUBCOMMAND ...ARGS", "Managing commands/batchs supervision"
|
data/config/splash.yml
CHANGED
@@ -1,9 +1,32 @@
|
|
1
1
|
:splash:
|
2
|
+
:templates:
|
3
|
+
:execution:
|
4
|
+
:path: /etc/splash_execution_report.tpl
|
5
|
+
:tokens:
|
6
|
+
- :date
|
7
|
+
- :cmd_name
|
8
|
+
- :cmd_line
|
9
|
+
- :stdout
|
10
|
+
- :stderr
|
11
|
+
- :desc
|
12
|
+
- :status
|
2
13
|
:logs:
|
3
14
|
- :log: /tmp/test
|
4
15
|
:pattern: ERROR
|
5
16
|
- :log: /var/log/message
|
6
17
|
:pattern: error
|
18
|
+
:prometheus:
|
19
|
+
:pushgateway:
|
20
|
+
:host: "localhost"
|
21
|
+
:port: 9091
|
22
|
+
:commands:
|
23
|
+
:false_test:
|
24
|
+
:desc: "test command"
|
25
|
+
:command: "false"
|
26
|
+
:ls_slash_tmp:
|
27
|
+
:desc: list file in /tmp
|
28
|
+
:command: ls -al /tmp
|
29
|
+
:user: daemon
|
7
30
|
:daemon:
|
8
31
|
:user: daemon
|
9
32
|
:group: daemon
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'open3'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
|
5
|
+
module Splash
|
6
|
+
class CommandWrapper
|
7
|
+
include Splash::Templates
|
8
|
+
include Splash::Config
|
9
|
+
include Splash::Helpers
|
10
|
+
|
11
|
+
def initialize(name)
|
12
|
+
@config = get_config
|
13
|
+
@name = name
|
14
|
+
unless @config.commands.keys.include? @name.to_sym then
|
15
|
+
$stderr.puts "Splash : command #{@name} is not defined in configuration"
|
16
|
+
exit 40
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def ack
|
21
|
+
puts "Sending ack for command : '#{@name}'"
|
22
|
+
notify(0)
|
23
|
+
exit 0
|
24
|
+
end
|
25
|
+
|
26
|
+
def notify(value)
|
27
|
+
unless verify_service host: @config.prometheus_pushgateway_host ,port: @config.prometheus_pushgateway_port then
|
28
|
+
$stderr.puts "Prometheus PushGateway Service IS NOT running"
|
29
|
+
$stderr.puts "Exit without notification."
|
30
|
+
exit 30
|
31
|
+
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
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
def call_and_notify(options)
|
43
|
+
puts "Executing command : '#{@name}' "
|
44
|
+
unless options[:trace] then
|
45
|
+
puts "Traceless execution"
|
46
|
+
if @config.commands[@name.to_sym][:user] then
|
47
|
+
system("sudo -u #{@config.commands[@name.to_sym][:user]} #{@config.commands[@name.to_sym][:command]} > /dev/null 2>&1")
|
48
|
+
else
|
49
|
+
system("#{@config.commands[@name.to_sym][:command]} > /dev/null 2>&1")
|
50
|
+
end
|
51
|
+
exit_code = $?.exitstatus
|
52
|
+
else
|
53
|
+
puts "Tracefull execution"
|
54
|
+
if @config.commands[@name.to_sym][:user] then
|
55
|
+
stdout, stderr, status = Open3.capture3("sudo -u #{@config.commands[@name.to_sym][:user]} #{@config.commands[@name.to_sym][:command]}")
|
56
|
+
else
|
57
|
+
stdout, stderr, status = Open3.capture3(@config.commands[@name.to_sym][:command])
|
58
|
+
end
|
59
|
+
tp = Template::new(
|
60
|
+
list_token: @config.execution_template_tokens,
|
61
|
+
template_file: @config.execution_template_path)
|
62
|
+
|
63
|
+
tp.date = DateTime.now.to_s
|
64
|
+
tp.cmd_name = @name
|
65
|
+
tp.cmd_line = @config.commands[@name.to_sym][:command]
|
66
|
+
tp.desc = @config.commands[@name.to_sym][:desc]
|
67
|
+
tp.status = status.to_s
|
68
|
+
tp.stdout = stdout
|
69
|
+
tp.stderr = stderr
|
70
|
+
filename = "#{@config[:trace_path]}/#{@name}_trace.last"
|
71
|
+
File.open(filename, 'w') { |file| file.write(tp.output) }
|
72
|
+
exit_code = status.exitstatus
|
73
|
+
end
|
74
|
+
|
75
|
+
notify(exit_code)
|
76
|
+
exit exit_code
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/splash/config.rb
CHANGED
@@ -12,8 +12,12 @@ module Splash
|
|
12
12
|
self[:version] = VERSION
|
13
13
|
self[:author] = "#{AUTHOR} <#{EMAIL}>"
|
14
14
|
self[:copyright] = "#{COPYRIGHT} #{LICENSE}"
|
15
|
+
self[:prometheus_pushgateway_host] = (config_from_file[:prometheus][:pushgateway][:host])? config_from_file[:prometheus][:pushgateway][:host] : PROMETHEUS_PUSHGATEWAY_HOST
|
16
|
+
self[:prometheus_pushgateway_port] = (config_from_file[:prometheus][:pushgateway][:port])? config_from_file[:prometheus][:pushgateway][:port] : PROMETHEUS_PUSHGATEWAY_PORT
|
15
17
|
self[:daemon_process_name] = (config_from_file[:daemon][:process_name])? config_from_file[:daemon][:process_name] : DAEMON_PROCESS_NAME
|
16
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[:execution_template_path] = (config_from_file[:templates][:execution][:path])? config_from_file[:templates][:execution][:path] : EXECUTION_TEMPLATE
|
17
21
|
self[:daemon_group] = (config_from_file[:daemon][:group])? config_from_file[:daemon][:group] : DAEMON_GROUP
|
18
22
|
self[:pid_path] = (config_from_file[:daemon][:paths][:pid_path])? config_from_file[:daemon][:paths][:pid_path] : PID_PATH
|
19
23
|
self[:trace_path] = (config_from_file[:daemon][:paths][:trace_path])? config_from_file[:daemon][:paths][:trace_path] : TRACE_PATH
|
@@ -21,12 +25,25 @@ module Splash
|
|
21
25
|
self[:stdout_trace] = (config_from_file[:daemon][:files][:stdout_trace])? config_from_file[:daemon][:files][:stdout_trace] : STDOUT_TRACE
|
22
26
|
self[:stderr_trace] = (config_from_file[:daemon][:files][:stderr_trace])? config_from_file[:daemon][:files][:stderr_trace] : STDERR_TRACE
|
23
27
|
self[:logs] = (config_from_file[:logs])? config_from_file[:logs] : {}
|
28
|
+
self[:commands] = (config_from_file[:commands])? config_from_file[:commands] : {}
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
def execution_template_path
|
33
|
+
return self[:execution_template_path]
|
24
34
|
end
|
25
35
|
|
36
|
+
def execution_template_tokens
|
37
|
+
return self[:execution_template_tokens]
|
38
|
+
end
|
26
39
|
def logs
|
27
40
|
return self[:logs]
|
28
41
|
end
|
29
42
|
|
43
|
+
def commands
|
44
|
+
return self[:commands]
|
45
|
+
end
|
46
|
+
|
30
47
|
def author
|
31
48
|
return self[:author]
|
32
49
|
end
|
@@ -43,6 +60,13 @@ module Splash
|
|
43
60
|
return self[:daemon_process_name]
|
44
61
|
end
|
45
62
|
|
63
|
+
def prometheus_pushgateway_host
|
64
|
+
return self[:prometheus_pushgateway_host]
|
65
|
+
end
|
66
|
+
def prometheus_pushgateway_port
|
67
|
+
return self[:prometheus_pushgateway_port]
|
68
|
+
end
|
69
|
+
|
46
70
|
def daemon_user
|
47
71
|
return self[:daemon_user]
|
48
72
|
end
|
@@ -78,46 +102,102 @@ module Splash
|
|
78
102
|
|
79
103
|
|
80
104
|
def setupsplash
|
81
|
-
conf_in_path = search_file_in_gem "splash", "config/splash.yml"
|
82
|
-
|
105
|
+
conf_in_path = search_file_in_gem "prometheus-splash", "config/splash.yml"
|
106
|
+
full_res = 0
|
107
|
+
puts "Splash -> setup : "
|
83
108
|
print "* Installing Configuration file : #{CONFIG_FILE} : "
|
84
109
|
if install_file source: conf_in_path, target: CONFIG_FILE, mode: "644", owner: "root", group: "wheel" then
|
85
110
|
puts "[OK]"
|
86
111
|
else
|
112
|
+
full_res =+ 1
|
87
113
|
puts "[KO]"
|
88
114
|
end
|
89
115
|
config = get_config
|
116
|
+
report_in_path = search_file_in_gem "prometheus-splash", "templates/report.txt"
|
117
|
+
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
|
119
|
+
puts "[OK]"
|
120
|
+
else
|
121
|
+
full_res =+ 1
|
122
|
+
puts "[KO]"
|
123
|
+
end
|
90
124
|
|
91
|
-
print "* Checking pid file path : #{config[:pid_path]}"
|
125
|
+
print "* Creating/Checking pid file path : #{config[:pid_path]} : "
|
92
126
|
if make_folder path: config[:pid_path], mode: "644", owner: "root", group: "wheel" then
|
93
127
|
puts "[OK]"
|
94
128
|
else
|
129
|
+
full_res =+ 1
|
95
130
|
puts "[KO]"
|
96
131
|
end
|
97
132
|
|
98
|
-
print "* Checking trace file path : #{config[:trace_path]}"
|
133
|
+
print "* Creating/Checking trace file path : #{config[:trace_path]} : "
|
99
134
|
if make_folder path: config[:trace_path], mode: "777", owner: config.daemon_user, group: config.daemon_group then
|
100
135
|
puts "[OK]"
|
101
136
|
else
|
137
|
+
full_res =+ 1
|
102
138
|
puts "[KO]"
|
103
139
|
end
|
104
140
|
|
105
|
-
|
141
|
+
if full_res > 0 then
|
142
|
+
$stderr.puts "Splash config done with #{full_res} errors"
|
143
|
+
return 25
|
144
|
+
else
|
145
|
+
puts "Splash config successfully done."
|
146
|
+
return 0
|
147
|
+
end
|
106
148
|
|
107
149
|
end
|
108
150
|
|
109
151
|
def checkconfig
|
152
|
+
puts "Splash -> sanitycheck : "
|
110
153
|
config = get_config
|
111
|
-
|
154
|
+
full_res = 0
|
155
|
+
print "* Config file : #{CONFIG_FILE} : "
|
112
156
|
res = verify_file(name: CONFIG_FILE, mode: "644", owner: "root", group: "wheel")
|
113
157
|
if res.empty? then
|
114
158
|
print "[OK]\n"
|
115
159
|
else
|
116
160
|
print "[KO]\n"
|
117
|
-
|
161
|
+
full_res =+ 1
|
162
|
+
puts " pbm => #{res.map {|p| p.to_s}.join(',')}"
|
118
163
|
end
|
119
164
|
|
165
|
+
print "* PID Path : #{config[:pid_path]} : "
|
166
|
+
res = verify_folder(name: config[:pid_path], mode: "644", owner: "root", group: "wheel")
|
167
|
+
if res.empty? then
|
168
|
+
print "[OK]\n"
|
169
|
+
else
|
170
|
+
print "[KO]\n"
|
171
|
+
full_res =+ 1
|
172
|
+
puts " pbm => #{res.map {|p| p.to_s}.join(',')}"
|
120
173
|
|
174
|
+
end
|
175
|
+
|
176
|
+
print "* trace Path : #{config[:trace_path]} : "
|
177
|
+
res = verify_folder(name: config[:trace_path], mode: "777", owner: config.daemon_user, group: config.daemon_group)
|
178
|
+
if res.empty? then
|
179
|
+
print "[OK]\n"
|
180
|
+
else
|
181
|
+
print "[KO]\n"
|
182
|
+
full_res =+ 1
|
183
|
+
puts " pbm => #{res.map {|p| p.to_s}.join(',')}"
|
184
|
+
end
|
185
|
+
|
186
|
+
print "* Prometheus PushGateway Service running : "
|
187
|
+
if verify_service host: config.prometheus_pushgateway_host ,port: config.prometheus_pushgateway_port then
|
188
|
+
print "[OK]\n"
|
189
|
+
else
|
190
|
+
print "[KO]\n"
|
191
|
+
full_res =+ 1
|
192
|
+
end
|
193
|
+
|
194
|
+
if full_res > 0 then
|
195
|
+
$stderr.puts "Sanitycheck finished with #{full_res} errors"
|
196
|
+
return 20
|
197
|
+
else
|
198
|
+
puts "Sanitycheck finished with no errors"
|
199
|
+
return 0
|
200
|
+
end
|
121
201
|
end
|
122
202
|
|
123
203
|
private
|
data/lib/splash/constants.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Splash
|
2
2
|
module Constants
|
3
|
-
VERSION = "0.0.
|
3
|
+
VERSION = "0.0.2"
|
4
4
|
CONFIG_FILE = "/etc/splash.yml"
|
5
5
|
DAEMON_USER = "root"
|
6
6
|
DAEMON_GROUP = "wheel"
|
@@ -14,5 +14,9 @@ module Splash
|
|
14
14
|
EMAIL = "gems@ultragreen.net"
|
15
15
|
COPYRIGHT="Ultragreen (c) 2020"
|
16
16
|
LICENSE="BSD-2-Clause"
|
17
|
+
PROMETHEUS_PUSHGATEWAY_HOST = "localhost"
|
18
|
+
PROMETHEUS_PUSHGATEWAY_PORT = "9091"
|
19
|
+
EXECUTION_TEMPLATE="/etc/splash_execution_report.tpl"
|
20
|
+
TOKENS_LIST = [:date,:cmd_name,:cmd_line,:stdout,:stderr,:desc,:status]
|
17
21
|
end
|
18
22
|
end
|
data/lib/splash/controller.rb
CHANGED
@@ -8,39 +8,95 @@ module Splash
|
|
8
8
|
|
9
9
|
def startdaemon(options = {})
|
10
10
|
config = get_config
|
11
|
+
unless verify_service host: config.prometheus_pushgateway_host ,port: config.prometheus_pushgateway_port then
|
12
|
+
$stderr.puts "Prometheus PushGateway Service is not running,"
|
13
|
+
$stderr.puts " please start before running Splash daemon."
|
14
|
+
exit 11
|
15
|
+
end
|
16
|
+
|
11
17
|
unless File::exist? config.full_pid_path then
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
+
res = daemonize :description => config.daemon_process_name,
|
19
|
+
:pid_file => config.full_pid_path,
|
20
|
+
:daemon_user => config.daemon_user,
|
21
|
+
:daemon_group => config.daemon_group,
|
22
|
+
:stdout_trace => config.full_stdout_trace_path,
|
23
|
+
:stderr_trace => config.full_stderr_trace_path do
|
18
24
|
result = LogScanner::new
|
19
25
|
while true
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
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
|
24
34
|
end
|
25
35
|
end
|
36
|
+
if res == 0 then
|
37
|
+
pid = `cat #{config.full_pid_path}`.to_i
|
38
|
+
puts "Splash Daemon Started, with PID : #{pid}"
|
39
|
+
else
|
40
|
+
$stderr.puts "Splash Daemon loading error"
|
41
|
+
end
|
42
|
+
return res
|
43
|
+
|
44
|
+
else
|
45
|
+
$stderr.puts "Pid File already exist, please verify if Splash daemon is running."
|
46
|
+
return 14
|
26
47
|
end
|
27
48
|
end
|
28
49
|
|
29
50
|
def stopdaemon(options = {})
|
30
51
|
config = get_config
|
52
|
+
errorcode = 0
|
31
53
|
if File.exist?(config.full_pid_path) then
|
32
54
|
|
33
55
|
begin
|
34
56
|
pid = `cat #{config.full_pid_path}`.to_i
|
35
57
|
Process.kill("TERM", pid)
|
58
|
+
puts 'Splash stopped succesfully'
|
36
59
|
rescue Errno::ESRCH
|
37
60
|
$stderr.puts "Process of PID : #{pid} not found"
|
61
|
+
errorcode = 12
|
38
62
|
end
|
39
|
-
|
40
|
-
return true
|
63
|
+
FileUtils::rm config.full_pid_path if File::exist? config.full_pid_path
|
41
64
|
else
|
42
|
-
|
65
|
+
$stderr.puts "Splash is not running"
|
66
|
+
errorcode = 13
|
43
67
|
end
|
68
|
+
return errorcode
|
69
|
+
end
|
70
|
+
|
71
|
+
def statusdaemon
|
72
|
+
config = get_config
|
73
|
+
pid = realpid = ''
|
74
|
+
pid = `cat #{config.full_pid_path}`.to_s if File.exist?(config.full_pid_path)
|
75
|
+
realpid = get_process pattern: get_config.daemon_process_name
|
76
|
+
pid.chomp!
|
77
|
+
realpid.chomp!
|
78
|
+
unless realpid.empty? then
|
79
|
+
print "Splash Process is running with PID #{realpid} "
|
80
|
+
else
|
81
|
+
print 'Splash Process not found '
|
82
|
+
end
|
83
|
+
unless pid.empty? then
|
84
|
+
puts "and PID file exist with PID #{pid}"
|
85
|
+
else
|
86
|
+
puts "and PID file don't exist"
|
87
|
+
end
|
88
|
+
if pid == realpid then
|
89
|
+
puts 'Status OK'
|
90
|
+
return 0
|
91
|
+
elsif pid.empty? then
|
92
|
+
$stderr.puts "PID File error, you have to kill process manualy, with : '(sudo )kill -TERM #{realpid}'"
|
93
|
+
$stderr.puts "Status KO"
|
94
|
+
return 16
|
95
|
+
elsif realpid.empty? then
|
96
|
+
$stderr.puts "Process Splash Dameon missing, run 'splash daemon stop' to reload properly"
|
97
|
+
$stderr.puts "Status KO"
|
98
|
+
return 17
|
99
|
+
end
|
44
100
|
end
|
45
101
|
|
46
102
|
end
|
data/lib/splash/helpers.rb
CHANGED
@@ -6,6 +6,19 @@ require 'etc'
|
|
6
6
|
module Splash
|
7
7
|
module Helpers
|
8
8
|
|
9
|
+
|
10
|
+
|
11
|
+
def get_process(options = {})
|
12
|
+
pattern = options[:pattern]
|
13
|
+
res = `ps aux|grep '#{pattern}'|grep -v grep`.to_s
|
14
|
+
unless res.empty? then
|
15
|
+
return res.split(/\s+/)[1]
|
16
|
+
else
|
17
|
+
return ''
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
9
22
|
def is_root?
|
10
23
|
case (Process.uid)
|
11
24
|
when 0
|
@@ -21,7 +34,7 @@ module Splash
|
|
21
34
|
$stderr.puts "Please execute with sudo, or rvmsudo."
|
22
35
|
exit 10
|
23
36
|
else
|
24
|
-
self.send method
|
37
|
+
return self.send method
|
25
38
|
end
|
26
39
|
end
|
27
40
|
|
@@ -88,7 +101,7 @@ module Splash
|
|
88
101
|
yield
|
89
102
|
|
90
103
|
end
|
91
|
-
return
|
104
|
+
return 0
|
92
105
|
end
|
93
106
|
|
94
107
|
# @!group facilités sur le système de fichier
|
@@ -141,11 +154,27 @@ module Splash
|
|
141
154
|
#@!group Vérifiers de l'application
|
142
155
|
|
143
156
|
# verifier d'existence d'un repertoire
|
144
|
-
# @return [
|
157
|
+
# @return [Array] of Symbol with error type : [:inexistant,:mode,:owner,:group]
|
145
158
|
# @param [Hash] options
|
146
|
-
# @option options [String] :path le répertoire
|
159
|
+
# @option options [String] :path le répertoire (relatif ou absolut) obligatoire
|
160
|
+
# @option options [String] :mode droit du répertoire optionnel
|
161
|
+
# @option options [String] :owner owner du répertoire optionnel
|
162
|
+
# @option options [String] :group groupe du répertoire optionnel
|
147
163
|
def verify_folder(options ={})
|
148
|
-
|
164
|
+
res = Array::new
|
165
|
+
return [:inexistant] unless File.directory?(options[:name])
|
166
|
+
stat = File.stat(options[:name])
|
167
|
+
if options[:mode] then
|
168
|
+
mode = "%o" % stat.mode
|
169
|
+
res << :mode if mode[-3..-1] != options[:mode]
|
170
|
+
end
|
171
|
+
if options[:owner] then
|
172
|
+
res << :owner if Etc.getpwuid(stat.uid).name != options[:owner]
|
173
|
+
end
|
174
|
+
if options[:group] then
|
175
|
+
res << :group if Etc.getgrgid(stat.gid).name != options[:group]
|
176
|
+
end
|
177
|
+
return res
|
149
178
|
end
|
150
179
|
|
151
180
|
# verifier d'existence d'un lien
|
@@ -157,9 +186,12 @@ module Splash
|
|
157
186
|
end
|
158
187
|
|
159
188
|
# verifier d'existence d'un fichier
|
160
|
-
# @return [
|
189
|
+
# @return [Array] of Symbol with error type : [:inexistant,:mode,:owner,:group]
|
161
190
|
# @param [Hash] options
|
162
|
-
# @option options [String] :name path du fichier
|
191
|
+
# @option options [String] :name path du fichier obligatoire
|
192
|
+
# @option options [String] :mode droit du fichier optionnel
|
193
|
+
# @option options [String] :owner owner du fichier optionnel
|
194
|
+
# @option options [String] :group groupe du fichier optionnel
|
163
195
|
def verify_file(options ={})
|
164
196
|
res = Array::new
|
165
197
|
return [:inexistant] unless File.file?(options[:name])
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Splash
|
2
|
+
module Templates
|
3
|
+
class Template
|
4
|
+
|
5
|
+
attr_reader :list_token
|
6
|
+
attr_reader :template_file
|
7
|
+
attr_reader :content
|
8
|
+
|
9
|
+
def initialize(_options)
|
10
|
+
|
11
|
+
|
12
|
+
@template_file = _options[:template_file]
|
13
|
+
raise NoTemplateFile::new('No template file found') unless File::exist?(@template_file)
|
14
|
+
begin
|
15
|
+
@content = IO::readlines(@template_file).join.chomp
|
16
|
+
rescue
|
17
|
+
raise NoTemplateFile::new('No template file found')
|
18
|
+
end
|
19
|
+
token_from_template = @content.scan(/%%(\w+)%%/).flatten.uniq.map{ |item| item.downcase.to_sym}
|
20
|
+
begin
|
21
|
+
@list_token = _options[:list_token]
|
22
|
+
@hash_token = Hash::new; @list_token.each{|_item| @hash_token[_item.to_s] = String::new('')}
|
23
|
+
rescue
|
24
|
+
raise InvalidTokenList::new("Token list malformation")
|
25
|
+
end
|
26
|
+
raise InvalidTokenList::new("Token list doesn't match the template") unless token_from_template.sort == @list_token.sort
|
27
|
+
@list_token.each{|_token| eval("def #{_token}=(_value); raise ArgumentError::new('Not a String') unless _value.class == String; @hash_token['#{_token}'] = _value ;end")}
|
28
|
+
@list_token.each{|_token| eval("def #{_token}; @hash_token['#{_token}'] ;end")}
|
29
|
+
end
|
30
|
+
|
31
|
+
def token(_token,_value)
|
32
|
+
raise ArgumentError::new('Not a String') unless _value.class == String
|
33
|
+
@hash_token[_token.to_s] = _value
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
def map(_hash)
|
38
|
+
_data = {}
|
39
|
+
_hash.each { |item,val|
|
40
|
+
raise ArgumentError::new("#{item} : Not a String") unless val.class == String
|
41
|
+
_data[item.to_s.downcase] = val
|
42
|
+
}
|
43
|
+
raise InvalidTokenList::new("Token list malformation") unless _data.keys.sort == @list_token.map{|_token| _token.to_s }.sort
|
44
|
+
@hash_token = _data
|
45
|
+
end
|
46
|
+
|
47
|
+
def method_missing(_name,*_args)
|
48
|
+
raise NotAToken
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def output
|
53
|
+
_my_res = String::new('')
|
54
|
+
_my_res = @content
|
55
|
+
@list_token.each{|_token|
|
56
|
+
_my_res.gsub!(/%%#{_token.to_s.upcase}%%/,@hash_token[_token.to_s])
|
57
|
+
}
|
58
|
+
return _my_res
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
class InvalidTokenList < Exception; end
|
64
|
+
class NotAToken < Exception; end
|
65
|
+
class NoTemplateFile < Exception; end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
File without changes
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Command Execution report
|
2
|
+
========================
|
3
|
+
|
4
|
+
Date : %%DATE%%
|
5
|
+
Command : %%CMD_NAME%%
|
6
|
+
full command line : %%CMD_LINE%%
|
7
|
+
Description : %%DESC%%
|
8
|
+
errorcode : %%STATUS%%
|
9
|
+
|
10
|
+
STDOUT:
|
11
|
+
-------
|
12
|
+
|
13
|
+
%%STDOUT%%
|
14
|
+
|
15
|
+
|
16
|
+
STDERR:
|
17
|
+
-------
|
18
|
+
|
19
|
+
%%STDERR%%
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prometheus-splash
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Romain GEORGES
|
@@ -150,13 +150,15 @@ files:
|
|
150
150
|
- Rakefile
|
151
151
|
- bin/splash
|
152
152
|
- config/splash.yml
|
153
|
-
- lib/splash/
|
153
|
+
- lib/splash/commands.rb
|
154
154
|
- lib/splash/config.rb
|
155
155
|
- lib/splash/constants.rb
|
156
156
|
- lib/splash/controller.rb
|
157
157
|
- lib/splash/helpers.rb
|
158
158
|
- lib/splash/logs.rb
|
159
|
-
- splash.
|
159
|
+
- lib/splash/templates.rb
|
160
|
+
- prometheus-splash.gemspec
|
161
|
+
- templates/report.txt
|
160
162
|
- templates/splashd.service
|
161
163
|
- ultragreen_roodi_coding_convention.yml
|
162
164
|
homepage: http://www.ultragreen.net
|
data/lib/splash/command.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
module Splash
|
2
|
-
class CommandWrapper
|
3
|
-
def initialize(name)
|
4
|
-
@name = name
|
5
|
-
end
|
6
|
-
|
7
|
-
def ack
|
8
|
-
puts "Sending ack for command : '#{@name}'"
|
9
|
-
notify(0)
|
10
|
-
exit 0
|
11
|
-
end
|
12
|
-
|
13
|
-
def notify(value)
|
14
|
-
registry = Prometheus::Client.registry
|
15
|
-
metric = Prometheus::Client::Gauge.new(:errorcode, docstring: 'SPLASH metric batch errorcode')
|
16
|
-
registry.register(metric)
|
17
|
-
metric.set(value)
|
18
|
-
Prometheus::Client::Push.new(@name).add(registry)
|
19
|
-
end
|
20
|
-
|
21
|
-
|
22
|
-
def call_and_notify
|
23
|
-
puts "Executing command : '#{@name}' and notify Prometheus PushGateway"
|
24
|
-
system("#{@name} > /dev/null")
|
25
|
-
exit_code = $?.exitstatus
|
26
|
-
notify(exit_code)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|