prometheus-splash 0.8.4 → 0.9.0

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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/README.md +1 -1
  4. data/config/splash.yml +14 -12
  5. data/lib/splash/cli/commands.rb +23 -22
  6. data/lib/splash/cli/daemon.rb +1 -1
  7. data/lib/splash/cli/webadmin.rb +2 -1
  8. data/lib/splash/commands.rb +31 -22
  9. data/lib/splash/config.rb +6 -2
  10. data/lib/splash/constants.rb +1 -1
  11. data/lib/splash/daemon/orchestrator/grammar.rb +1 -1
  12. data/lib/splash/daemon/orchestrator.rb +8 -9
  13. data/lib/splash/dependencies.rb +1 -0
  14. data/lib/splash/helpers.rb +1 -1
  15. data/lib/splash/monkeys.rb +5 -0
  16. data/lib/splash/sequences.rb +6 -1
  17. data/lib/splash/webadmin/api/routes/commands.rb +13 -1
  18. data/lib/splash/webadmin/api/routes/config.rb +45 -0
  19. data/lib/splash/webadmin/main.rb +13 -1
  20. data/lib/splash/webadmin/portal/controllers/commands.rb +99 -1
  21. data/lib/splash/webadmin/portal/controllers/logs.rb +16 -2
  22. data/lib/splash/webadmin/portal/controllers/processes.rb +16 -2
  23. data/lib/splash/webadmin/portal/views/command_form.slim +45 -0
  24. data/lib/splash/webadmin/portal/views/command_history.slim +27 -0
  25. data/lib/splash/webadmin/portal/views/commands.slim +69 -19
  26. data/lib/splash/webadmin/portal/views/log_form.slim +3 -0
  27. data/lib/splash/webadmin/portal/views/log_history.slim +2 -2
  28. data/lib/splash/webadmin/portal/views/logs.slim +8 -6
  29. data/lib/splash/webadmin/portal/views/process_form.slim +4 -1
  30. data/lib/splash/webadmin/portal/views/process_history.slim +4 -4
  31. data/lib/splash/webadmin/portal/views/processes.slim +7 -4
  32. data/lib/splash/webadmin.rb +3 -1
  33. data/templates/.env +0 -0
  34. data/templates/Dockerfile +5 -0
  35. data/templates/docker-compose.yml +14 -0
  36. metadata +11 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 285fc8b213dd02cccc8f43153f9e63ba261d96a6f29dd87b0c7f3194130b09d5
4
- data.tar.gz: be38d7d3804b186ed62f9e3a50b18dd46ccf37c2fe9406b22fbab8df6ccc7af7
3
+ metadata.gz: 13eaca07cd4d8de11c4eb5b54798a59d2a16d2b258eab9e800405b9333b7caba
4
+ data.tar.gz: 00170e2f5a7e8b51ec9b4b638e75ed8a5dd53ba6f5a644a752f83f0c0eb77179
5
5
  SHA512:
6
- metadata.gz: 9a91bf0cd11d39881f49cb81e3b070da161d8cf24664025360dd1036842c448ce4b86d2498f6d881ec190213780c93b6b15b90a19a4b0410da3a72aa961b2250
7
- data.tar.gz: 1c86c9ba9933d8031e5df00543e254cce43732f2f400f729bd2740f4a7f7ec765bc7d14610bd811cf1b8ceeab2d039d791267e9837db4132e6e193e069a2c2fd
6
+ metadata.gz: 848fcec8f9d390cbd59fdd5104d32667fe03a581ee6597de6bcdd64dc923863d1a821ec417285816bcf093a955b668fa563934b599691292eceee9bfa8e3affa
7
+ data.tar.gz: 5541a02ed39ae1a86e1602886a9a0eb1590d6bae431517fd8d0a2b91ce1a62092dd641f0dac8a6d496b5b46490cf176cb2cb7707c997b1e671ca40ae55984109
data/CHANGELOG.md CHANGED
@@ -185,3 +185,12 @@
185
185
  ### FIX
186
186
 
187
187
  * always missing status for log history #65
188
+
189
+
190
+ ## V 0.8.5
191
+
192
+ ### FEATURE
193
+
194
+ * WebUI R/W commands, logs, processes
195
+ * cosmetics
196
+ * multiples fix, debugging
data/README.md CHANGED
@@ -9,7 +9,7 @@ SPLASH is **Supervision with Prometheus of Logs and Asynchronous tasks orchestra
9
9
  * Web : http://www.ultragreen.net
10
10
  * Github : https://github.com/Ultragreen/prometheus-splash
11
11
  * Rubygems : https://rubygems.org/gems/prometheus-splash
12
- * DOC yardoc : https://www.rubydoc.info/gems/prometheus-splash/0.8.4
12
+ * DOC yardoc : https://www.rubydoc.info/gems/prometheus-splash/0.8.5
13
13
 
14
14
  Prometheus Logs and Batchs supervision over PushGateway
15
15
 
data/config/splash.yml CHANGED
@@ -73,49 +73,51 @@
73
73
 
74
74
  ### Sample configuration of commands and scheduling
75
75
  :commands:
76
- :id_root:
76
+ - :name: :id_root
77
77
  :desc: run id command on root
78
78
  :command: id root
79
- :true_test:
79
+ - :name: :true_test
80
80
  :desc: "test command returning true : 0"
81
81
  :command: "true"
82
82
  :schedule:
83
83
  :every: "1h"
84
84
  :on_failure: :ls_slash_tmp
85
85
  :on_success: :pwd
86
- :false_test:
86
+ - :name: :false_test
87
87
  :desc: "test command returning false > 0"
88
88
  :command: "false"
89
89
  :schedule:
90
90
  :every: "1h"
91
91
  :on_failure: :ls_slash_tmp
92
92
  :on_success: :pwd
93
- :ls_slash_tmp:
93
+ - :name: :ls_slash_tmp
94
94
  :desc: list file in /tmp
95
95
  :command: ls -al /tmp
96
96
  :user: daemon
97
97
  :on_success: :echo1
98
- :pwd:
98
+ - :name: :pwd
99
99
  :desc: run pwd
100
100
  :command: pwd
101
101
  :on_success: :echo1
102
102
  :on_failure: :echo2
103
- :echo1:
103
+ - :name: :echo1
104
104
  :desc: echo 'foo'
105
105
  :command: echo foo
106
106
  :on_failure: :echo3
107
- :echo2:
107
+ - :name: :echo2
108
108
  :desc: echo 'bar'
109
109
  :command: echo bar
110
- :echo3:
110
+ - :name: :echo3
111
111
  :desc: echo 'been'
112
112
  :command: echo been
113
- :rand_sleep_5:
113
+ - :name: :rand_sleep_5
114
114
  :desc: sleep on a rand 5
115
115
  :command: ruby -e 'sleep rand(5)'
116
116
  :schedule:
117
- :every: "10s"
118
- :test_remote_call:
117
+ :every: "30s"
118
+ :retention:
119
+ :hours: 1
120
+ - :name: :test_remote_call
119
121
  :desc: remote call test
120
122
  :delegate_to:
121
123
  :host: omicron
@@ -138,7 +140,7 @@
138
140
 
139
141
  ### configuration of monitored processes
140
142
  :processes:
141
- - :process: cron
143
+ - :process: :cron
142
144
  :patterns:
143
145
  - cron
144
146
  :retention:
@@ -159,7 +159,7 @@ module CLISplash
159
159
  end
160
160
  log.info "Command : #{command.to_s}" if depht == 0
161
161
  aproc = Proc::new do |command,depht|
162
- cmd = commands[command.to_sym]
162
+ cmd = commands.select{|item| item[:name] == command.to_sym}.first
163
163
  if cmd[:on_failure] then
164
164
  spacer= " " * depht + " "
165
165
  log.flat "#{spacer}* on failure => #{cmd[:on_failure]}"
@@ -211,16 +211,16 @@ module CLISplash
211
211
  list = get_config.commands
212
212
  end
213
213
  log.info "Splash configured commands :"
214
- log.ko 'No configured commands found' if list.keys.empty?
215
- list.keys.each do |command|
216
- log.item "#{command.to_s}"
214
+ log.ko 'No configured commands found' if list.empty?
215
+ list.each do |command|
216
+ log.item "#{command[:name].to_s}"
217
217
  if options[:detail] then
218
- log.arrow "command line : '#{list[command][:command]}'"
219
- log.arrow "command description : '#{list[command][:desc]}'"
220
- log.arrow "command failure callback : '#{list[command.to_sym][:on_failure]}'" if list[command.to_sym][:on_failure]
221
- log.arrow "command success callback : '#{list[command.to_sym][:on_success]}'" if list[command.to_sym][:on_success]
222
- if list[command.to_sym][:schedule]
223
- sched,val = list[command.to_sym][:schedule].flatten
218
+ log.arrow "command line : '#{command[:command]}'"
219
+ log.arrow "command description : '#{command[:desc]}'"
220
+ log.arrow "command failure callback : '#{command[:on_failure]}'" if command[:on_failure]
221
+ log.arrow "command success callback : '#{command[:on_success]}'" if command[:on_success]
222
+ if command[:schedule] then
223
+ sched,val = command[:schedule].flatten
224
224
  log.arrow "command scheduled : #{sched} #{val}."
225
225
  end
226
226
  end
@@ -235,7 +235,7 @@ module CLISplash
235
235
  with --hostname <HOSTNAME>, an other Splash monitored server (only with Redis backend configured)
236
236
  LONGDESC
237
237
  option :hostname, :type => :string, :aliases => "-H"
238
- def show(command)
238
+ def show(name)
239
239
  unless is_root? then
240
240
  splash_exit case: :not_root, :more => "Command show specifications"
241
241
  end
@@ -261,14 +261,15 @@ module CLISplash
261
261
  else
262
262
  list = get_config.commands
263
263
  end
264
- if list.keys.include? command.to_sym then
265
- log.info "Splash command : #{command}"
266
- log.item "command line : '#{list[command.to_sym][:command]}'"
267
- log.item "command description : '#{list[command.to_sym][:desc]}'"
268
- log.item "command failure callback : '#{list[command.to_sym][:on_failure]}'" if list[command.to_sym][:on_failure]
269
- log.item "command success callback : '#{list[command.to_sym][:on_success]}'" if list[command.to_sym][:on_success]
270
- if list[command.to_sym][:schedule]
271
- sched,val = list[command.to_sym][:schedule].flatten
264
+ command = list.select{|item| item[:name] == name.to_sym}.first
265
+ unless command.nil? then
266
+ log.info "Splash command : #{command[:name]}"
267
+ log.item "command line : '#{command[:command]}'"
268
+ log.item "command description : '#{command[:desc]}'"
269
+ log.item "command failure callback : '#{command[:on_failure]}'" if command[:on_failure]
270
+ log.item "command success callback : '#{command[:on_success]}'" if command[:on_success]
271
+ if command[:schedule]
272
+ sched,val = command[:schedule].flatten
272
273
  log.item "command scheduled : #{sched} #{val}."
273
274
  end
274
275
  splash_exit case: :quiet_exit
@@ -301,7 +302,7 @@ module CLISplash
301
302
  value[:end_date],
302
303
  value[:exec_time],
303
304
  value[:stdout].empty?,
304
- value[:stdout].empty?]
305
+ value[:stderr].empty?]
305
306
  end
306
307
  end
307
308
  if check_unicode_term then
@@ -349,12 +350,12 @@ module CLISplash
349
350
  splash_exit case: :specific_config_required, :more => "Redis backend is requiered for Remote execution report request"
350
351
  end
351
352
  splash_exit case: :not_root if not is_root? and not redis
352
- list = get_config.commands.keys
353
+ list = get_config.commands
353
354
  if options[:hostname] then
354
355
  options[:hostname] = Socket.gethostname if options[:hostname] == 'hostname'
355
356
  list = backend.list("*", options[:hostname]).map(&:to_sym)
356
357
  end
357
- if list.include? command.to_sym then
358
+ if list.select{|cmd| cmd[:name] == command.to_sym}.count > 0 then
358
359
  log.info "Splash command #{command} previous execution report:\n"
359
360
  req = { :key => command}
360
361
  req[:hostname] = options[:hostname] if options[:hostname]
@@ -99,7 +99,7 @@ module CLISplash
99
99
  end
100
100
 
101
101
  # Thor method : sending reset verb over transport in the input queue of Splashd
102
- desc "getjobs", "send a reset verb to HOSTNAME daemon over transport (need an active tranport), Typicallly RabbitMQ"
102
+ desc "reset", "send a reset verb to HOSTNAME daemon over transport (need an active tranport), Typicallly RabbitMQ"
103
103
  def reset(hostname=Socket.gethostname)
104
104
  log = get_logger
105
105
  log.info "ctrl+c for interrupt"
@@ -35,9 +35,10 @@ module CLISplash
35
35
  long_desc <<-LONGDESC
36
36
  Starting Splash Daemon\n
37
37
  LONGDESC
38
+ option :foreground, :type => :boolean, :aliases => "-F"
38
39
  desc "start", "Splash WebAdmin Daemon status"
39
40
  def start
40
- acase = run_as_root :startweb
41
+ acase = run_as_root :startweb, options
41
42
  splash_exit acase
42
43
  end
43
44
 
@@ -48,6 +48,11 @@ module Splash
48
48
  @backend = get_backend :execution_trace
49
49
  end
50
50
 
51
+
52
+ def clear
53
+ @backend.del({:key => @name}) if @backend.exist?({key: @name})
54
+ end
55
+
51
56
  def purge(retention)
52
57
  retention = {} if retention.nil?
53
58
  if retention.include? :hours then
@@ -96,7 +101,7 @@ module Splash
96
101
  @config = get_config
97
102
  @url = @config.prometheus_pushgateway_url
98
103
  @name = name
99
- unless @config.commands.keys.include? @name.to_sym then
104
+ unless @config.commands.select{|cmd| cmd[:name] == @name.to_sym }.count > 0 then
100
105
  splash_exit case: :not_found, more: "command #{@name} is not defined in configuration"
101
106
  end
102
107
  end
@@ -139,18 +144,20 @@ module Splash
139
144
  session = (options[:session])? options[:session] : get_session
140
145
  acase = { :case => :quiet_exit }
141
146
  exit_code = 0
142
- if @config.commands[@name.to_sym][:delegate_to] then
147
+ command = @config.commands.select{|command| command[:name] == @name.to_sym}.first
148
+ if command[:delegate_to] then
143
149
  return { :case => :options_incompatibility, :more => '--hostname forbidden with delagate commands'} if options[:hostname]
144
- log.send "Remote command : #{@name} execution delegate to : #{@config.commands[@name.to_sym][:delegate_to][:host]} as : #{@config.commands[@name.to_sym][:delegate_to][:remote_command]}", session
150
+ log.send "Remote command : #{@name} execution delegate to : #{command[:delegate_to][:host]} as : #{command[:delegate_to][:remote_command]}", session
151
+ log.warn "Local command : #{command[:command]} defined but ignored, because delegate have the priority"
145
152
  begin
146
153
  transport = get_default_client
147
154
  if transport.class == Hash and transport.include? :case then
148
155
  return transport
149
156
  else
150
157
  res = transport.execute({ :verb => :execute_command,
151
- payload: {:name => @config.commands[@name.to_sym][:delegate_to][:remote_command].to_s},
158
+ payload: {:name => command[:delegate_to][:remote_command].to_s},
152
159
  :return_to => "splash.#{Socket.gethostname}.return",
153
- :queue => "splash.#{@config.commands[@name.to_sym][:delegate_to][:host]}.input" })
160
+ :queue => "splash.#{command[:delegate_to][:host]}.input" })
154
161
  exit_code = res[:exit_code]
155
162
  log.receive "return with exitcode #{exit_code}", session
156
163
 
@@ -164,35 +171,35 @@ module Splash
164
171
  start_date = DateTime.now.to_s
165
172
  unless options[:trace] then
166
173
  log.item "Traceless execution", session
167
- if @config.commands[@name.to_sym][:user] then
168
- log.item "Execute with user : #{@config.commands[@name.to_sym][:user]}.", session
169
- system("sudo -u #{@config.commands[@name.to_sym][:user]} #{@config.commands[@name.to_sym][:command]} > /dev/null 2>&1")
174
+ if command[:user] then
175
+ log.item "Execute with user : #{command[:user]}.", session
176
+ system("sudo -u #{command[:user]} #{command[:command]} > /dev/null 2>&1")
170
177
  else
171
- system("#{@config.commands[@name.to_sym][:command]} > /dev/null 2>&1")
178
+ system("#{command[:command]} > /dev/null 2>&1")
172
179
  end
173
180
  time = Time.now - start
174
181
  exit_code = $?.exitstatus
175
182
  else
176
183
  log.item "Tracefull execution", session
177
- if @config.commands[@name.to_sym][:user] then
178
- log.item "Execute with user : #{@config.commands[@name.to_sym][:user]}.", session
179
- stdout, stderr, status = Open3.capture3("sudo -u #{@config.commands[@name.to_sym][:user]} #{@config.commands[@name.to_sym][:command]}")
184
+ if command[:user] then
185
+ log.item "Execute with user : #{command[:user]}.", session
186
+ stdout, stderr, status = Open3.capture3("sudo -u #{command[:user]} #{command[:command]}")
180
187
  else
181
- stdout, stderr, status = Open3.capture3(@config.commands[@name.to_sym][:command])
188
+ stdout, stderr, status = Open3.capture3(command[:command])
182
189
  end
183
190
  time = Time.now - start
184
191
  data = Hash::new
185
192
  data[:start_date] = start_date
186
193
  data[:end_date] = DateTime.now.to_s
187
194
  data[:cmd_name] = @name
188
- data[:cmd_line] = @config.commands[@name.to_sym][:command]
189
- data[:desc] = @config.commands[@name.to_sym][:desc]
195
+ data[:cmd_line] = command[:command]
196
+ data[:desc] = command[:desc]
190
197
  data[:status] = status.to_s
191
198
  data[:stdout] = stdout
192
199
  data[:stderr] = stderr
193
200
  data[:exec_time] = time.to_s
194
201
  cmdrec = CmdRecords::new @name
195
- cmdrec.purge(@config.commands[@name.to_sym][:retention])
202
+ cmdrec.purge(command[:retention])
196
203
  cmdrec.add_record data
197
204
  exit_code = status.exitstatus
198
205
  end
@@ -205,24 +212,26 @@ module Splash
205
212
  end
206
213
  end
207
214
  if options[:callback] then
208
- on_failure = (@config.commands[@name.to_sym][:on_failure])? @config.commands[@name.to_sym][:on_failure] : false
209
- on_success = (@config.commands[@name.to_sym][:on_success])? @config.commands[@name.to_sym][:on_success] : false
215
+ on_failure = (command[:on_failure])? command[:on_failure] : false
216
+ on_success = (command[:on_success])? command[:on_success] : false
210
217
  if on_failure and exit_code > 0 then
211
218
  log.item "On failure callback : #{on_failure}", session
212
- if @config.commands.keys.include? on_failure then
219
+ if @config.commands.select {|item| item[:name] == on_failure}.count > 0 then
213
220
  @name = on_failure.to_s
214
221
  call_and_notify options
215
222
  else
216
- acase = { :case => :configuration_error , :more => "on_failure call error : #{on_failure} command inexistant."}
223
+ log.error "on_failure call error : #{on_failure.to_s} command inexistant.", session
224
+ acase = { :case => :configuration_error , :more => "Command #{command[:name]} callback coniguration error"}
217
225
  end
218
226
  end
219
227
  if on_success and exit_code == 0 then
220
228
  log.item "On success callback : #{on_success}", session
221
- if @config.commands.keys.include? on_success then
229
+ if @config.commands.select {|item| item[:name] == on_success}.count > 0 then
222
230
  @name = on_success.to_s
223
231
  call_and_notify options
224
232
  else
225
- acase = { :case => :configuration_error , :more => "on_success call error : #{on_failure} command inexistant."}
233
+ log.error "on_success call error : #{on_success.to_s} command inexistant."
234
+ acase = { :case => :configuration_error , :more => "Command #{command[:name]} callback coniguration error"}
226
235
  end
227
236
  end
228
237
  else
data/lib/splash/config.rb CHANGED
@@ -14,9 +14,13 @@ module Splash
14
14
  class ConfigLinter
15
15
  def initialize
16
16
  @lints_present = {:logs => [:label, :log, :pattern ],
17
- :processes => [:process, :patterns ]}
17
+ :processes => [:process, :patterns ],
18
+ :commands => [:name, :desc, :command ]}
18
19
  @lints_types = {:logs => {:label => Symbol, :log => String, :pattern => String, :retention => Hash},
19
- :processes => {:process => Symbol, :patterns => Array, :retention => Hash}}
20
+ :processes => {:process => Symbol, :patterns => Array, :retention => Hash},
21
+ :commands => {:name => Symbol, :desc => String, :command => String, :schedule => Hash,
22
+ :retention => Hash, :on_failure => Symbol, :on_success => Symbol,
23
+ :user => String, :delegate_to => Hash}}
20
24
  end
21
25
 
22
26
  def verify(options ={})
@@ -7,7 +7,7 @@ module Splash
7
7
  module Constants
8
8
 
9
9
  # Current splash version
10
- VERSION = "0.8.4"
10
+ VERSION = "0.9.0"
11
11
  # the path to th config file, not overridable by config
12
12
  CONFIG_FILE = "/etc/splash.yml"
13
13
  # the default execution trace_path if backend file
@@ -66,7 +66,7 @@ module Splash
66
66
  # @return [Hash] Exiter case
67
67
  def execute_command(content)
68
68
  payload = content[:payload]
69
- unless get_config.commands.include? payload[:name].to_sym
69
+ unless get_config.commands.select {|cmd| cmd[:name] == payload[:name].to_sym}.count > 0 then
70
70
  @log.item "Command not found", content[:session]
71
71
  return { :case => :not_found }
72
72
  end
@@ -84,7 +84,7 @@ module Splash
84
84
  if VERBS.include? content[:verb]
85
85
  @log.receive "Valid remote order, verb : #{content[:verb].to_s}", session
86
86
  res = self.send content[:verb], content
87
- get_default_client.publish queue: content[:return_to], message: res.to_yaml
87
+ get_default_client.publish queue: content[:return_to], message: res.to_yaml unless content[:return_to] == :ignore
88
88
  @log.send "Result to #{content[:return_to]}.", session
89
89
  else
90
90
  @log.receive "INVALID remote order, verb : #{content[:verb].to_s}", session
@@ -100,9 +100,9 @@ module Splash
100
100
  else
101
101
  sched,value = @config.daemon_procmon_scheduling.flatten
102
102
  @log.item "Initializing logs monitorings & notifications."
103
- @log_result = LogScanner::new
104
103
  @server.send sched,value do
105
104
  begin
105
+ @log_result = LogScanner::new
106
106
  session = get_session
107
107
  @metric_manager.inc_logs_monitoring
108
108
  @log.trigger "Logs monitoring for Scheduling : #{sched.to_s} #{value.to_s}", session
@@ -122,9 +122,9 @@ module Splash
122
122
  else
123
123
  sched,value = @config.daemon_logmon_scheduling.flatten
124
124
  @log.item "Initializing processes monitorings & notifications."
125
- @process_result = ProcessScanner::new
126
125
  @server.send sched,value do
127
126
  begin
127
+ @process_result = ProcessScanner::new
128
128
  session = get_session
129
129
  @metric_manager.inc_processes_monitoring
130
130
  @log.trigger "Processes monitoring for Scheduling : #{sched.to_s} #{value.to_s}", session
@@ -155,15 +155,14 @@ module Splash
155
155
 
156
156
  # prepare commands Scheduling
157
157
  def init_commands_scheduling
158
- config = get_config.commands
159
- commands = config.select{|key,value| value.include? :schedule}.keys
158
+ commands = @config.commands.select{|command| command.include? :schedule}
160
159
  commands.each do |command|
161
- sched,value = config[command][:schedule].flatten
162
- @log.arrow "Scheduling command #{command.to_s}"
160
+ sched,value = command[:schedule].flatten
161
+ @log.arrow "Scheduling command #{command[:name].to_s}"
163
162
  @server.send sched,value do
164
163
  session = get_session
165
- @log.trigger "Executing Scheduled command #{command.to_s} for Scheduling : #{sched.to_s} #{value.to_s}", session
166
- execute command: command.to_s, session: session
164
+ @log.trigger "Executing Scheduled command #{command[:name].to_s} for Scheduling : #{sched.to_s} #{value.to_s}", session
165
+ execute command: command[:name].to_s, session: session
167
166
  end
168
167
  end
169
168
  end
@@ -50,6 +50,7 @@ module Splash
50
50
 
51
51
 
52
52
  # Splash
53
+ require 'splash/monkeys'
53
54
  require 'splash/constants'
54
55
  require 'splash/helpers'
55
56
  require 'splash/config'
@@ -358,7 +358,7 @@ module Splash
358
358
  # @return [Boolean]
359
359
  def check_unicode_term
360
360
  return false unless ENV.include? "TERM"
361
- if ENV.values_at("LC_ALL","LC_CTYPE","LANG").compact.first.include?("UTF-8") and ENV.values_at('TERM').first.include? "xterm" then
361
+ if ENV.values_at("LC_ALL","LC_CTYPE","LANG").compact.include?("UTF-8") and ENV.values_at('TERM').include? "xterm" then
362
362
  return true
363
363
  else
364
364
  return false
@@ -0,0 +1,5 @@
1
+ class Object
2
+ def blank?
3
+ respond_to?(:empty?) ? !!empty? : !self
4
+ end
5
+ end
@@ -25,12 +25,17 @@ module Splash
25
25
  list[name][:definition].each do |step|
26
26
  log.info "STEP : #{step[:step]}",session
27
27
  if step[:on_host].nil? then
28
- command = CommandWrapper::new(step[:command].to_s)
28
+ if get_config.commands.select{|cmd| cmd[:name] == step[:command]}.count > 0 then
29
+ command = CommandWrapper::new(step[:command].to_s)
29
30
  step[:callback] = true if step[:callback].nil?
30
31
  step[:trace] = true if step[:trace].nil?
31
32
  step[:notify] = true if step[:notify].nil?
32
33
  step[:session] = session
33
34
  acase = command.call_and_notify step
35
+ else
36
+ log.error "Commmand #{step[:command]} not found, for STEP : #{step[:step]}", session
37
+ acase = splash_return :not_found
38
+ end
34
39
  else
35
40
  log.info "Remote execution of #{step[:command]} on #{step[:on_host]}", session
36
41
  begin
@@ -16,7 +16,7 @@ WebAdminApp.get '/api/commands/show/:name.?:format?' do
16
16
  log = get_logger
17
17
  format = (params[:format])? format_by_extensions(params[:format]) : format_by_extensions('json')
18
18
  log.call "API : commands, verb : GET, route : show, item : #{params[:name]} , format : #{format}"
19
- commands_recordset = get_config.commands[params[:name].to_sym]
19
+ commands_recordset = get_config.commands.select {|command| command[:name] == params[:name].to_sym}.first
20
20
  unless commands_recordset.nil? then
21
21
  obj = splash_return case: :quiet_exit
22
22
  obj[:data] = commands_recordset
@@ -26,3 +26,15 @@ WebAdminApp.get '/api/commands/show/:name.?:format?' do
26
26
  content_type format
27
27
  format_response(obj, (params[:format])? format_by_extensions(params[:format]): request.accept.first)
28
28
  end
29
+
30
+ WebAdminApp.get '/api/commands/history/:name.?:format?' do
31
+ log = get_logger
32
+ format = (params[:format])? format_by_extensions(params[:format]) : format_by_extensions('json')
33
+ log.call "API : commands, verb : GET, route : history, format : #{format}"
34
+ record = Splash::Commands::CmdRecords::new(params[:name]).get_all_records
35
+ history = splash_return case: :quiet_exit, :more => "command monitoring history"
36
+ history[:data] = record
37
+ content_type format
38
+ status 201
39
+ format_response(history, (params[:format])? format_by_extensions(params[:format]): request.accept.first)
40
+ end
@@ -30,6 +30,7 @@ WebAdminApp.post '/api/config/addlog.?:format?' do
30
30
  res = get_config.add_record :record => YAML::load(request.body.read), :key => :label, :type => :logs, :clean => true
31
31
  case res[:status]
32
32
  when :success
33
+ rehash_daemon
33
34
  addlog = splash_return case: :quiet_exit, :more => "add log done"
34
35
  when :already_exist
35
36
  addlog = splash_return case: :already_exist, :more => "add log twice nto allowed"
@@ -49,6 +50,7 @@ WebAdminApp.post '/api/config/addprocess.?:format?' do
49
50
  res = get_config.add_record :record => YAML::load(request.body.read), :type => :processes, :key => :process, :clean => true
50
51
  case res[:status]
51
52
  when :success
53
+ rehash_daemon
52
54
  addprocess = splash_return case: :quiet_exit, :more => "add process done"
53
55
  when :already_exist
54
56
  addprocess = splash_return case: :already_exist, :more => "add process twice not allowed"
@@ -60,6 +62,26 @@ WebAdminApp.post '/api/config/addprocess.?:format?' do
60
62
  format_response(addprocess, (params[:format])? format_by_extensions(params[:format]): request.accept.first)
61
63
  end
62
64
 
65
+ WebAdminApp.post '/api/config/addcommand.?:format?' do
66
+ log = get_logger
67
+ addcommand = {}
68
+ format = (params[:format])? format_by_extensions(params[:format]) : format_by_extensions('json')
69
+ log.call "API : config, verb : POST, route : addcommand, format : #{format}"
70
+ res = get_config.add_record :record => YAML::load(request.body.read), :type => :commands, :key => :name, :clean => true
71
+ case res[:status]
72
+ when :success
73
+ rehash_daemon
74
+ addcommand = splash_return case: :quiet_exit, :more => "add command done"
75
+ when :already_exist
76
+ addcommand = splash_return case: :already_exist, :more => "add command twice not allowed"
77
+ when :failure
78
+ addpraddcommandocess = splash_return case: :configuration_error, :more => "add command failed"
79
+ addcommand[:data] = res
80
+ end
81
+ content_type format
82
+ format_response(addcommand, (params[:format])? format_by_extensions(params[:format]): request.accept.first)
83
+ end
84
+
63
85
 
64
86
 
65
87
  WebAdminApp.delete '/api/config/deletelog/:label.?:format?' do
@@ -72,6 +94,7 @@ WebAdminApp.delete '/api/config/deletelog/:label.?:format?' do
72
94
  res = get_config.delete_record :type => :logs, key: :label, label: params[:label].to_sym
73
95
  case res[:status]
74
96
  when :success
97
+ rehash_daemon
75
98
  deletelog = splash_return case: :quiet_exit, :more => "delete log done"
76
99
  when :not_found
77
100
  deletelog = splash_return case: :not_found, :more => "nothing done for logs"
@@ -92,6 +115,7 @@ WebAdminApp.delete '/api/config/deleteprocess/:process.?:format?' do
92
115
  res = get_config.delete_record :type => :processes, :key => :process, process: params[:process].to_sym
93
116
  case res[:status]
94
117
  when :success
118
+ rehash_daemon
95
119
  deleteprocess = splash_return case: :quiet_exit, :more => "delete process done"
96
120
  when :not_found
97
121
  deleteprocess = splash_return case: :not_found, :more => "nothing done for processes"
@@ -101,3 +125,24 @@ WebAdminApp.delete '/api/config/deleteprocess/:process.?:format?' do
101
125
  content_type format
102
126
  format_response(deleteprocess, (params[:format])? format_by_extensions(params[:format]): request.accept.first)
103
127
  end
128
+
129
+ WebAdminApp.delete '/api/config/deletecommand/:command.?:format?' do
130
+ log = get_logger
131
+ format = (params[:format])? format_by_extensions(params[:format]) : format_by_extensions('json')
132
+ log.call "API : config, verb : DELETE, route : deletecommand, format : #{format}"
133
+ deletecommand = {}
134
+ cmdrec = Splash::Commands::CmdRecords::new params[:command].to_sym
135
+ cmdrec.clear
136
+ res = get_config.delete_record :type => :commands, :key => :name, name: params[:command].to_sym
137
+ case res[:status]
138
+ when :success
139
+ rehash_daemon
140
+ deletecommand = splash_return case: :quiet_exit, :more => "delete command done"
141
+ when :not_found
142
+ deletecommand = splash_return case: :not_found, :more => "nothing done for commands"
143
+ else
144
+ deletecommand = splash_return case: :configuration_error, :more => "delete command failed"
145
+ end
146
+ content_type format
147
+ format_response(deletecommand, (params[:format])? format_by_extensions(params[:format]): request.accept.first)
148
+ end
@@ -9,6 +9,7 @@ class WebAdminApp < Sinatra::Base
9
9
  include Splash::Daemon::Controller
10
10
  include Splash::Logs
11
11
  include Splash::Processes
12
+ include Splash::Transports
12
13
 
13
14
  set :server, 'thin'
14
15
  set :port, get_config.webadmin_port
@@ -21,7 +22,18 @@ class WebAdminApp < Sinatra::Base
21
22
  rehash_config
22
23
  end
23
24
 
24
-
25
+ def rehash_daemon
26
+ status = get_processes({ :pattern => get_config.daemon_process_name}).empty?
27
+ if status == false then
28
+ transport = get_default_client
29
+ unless transport.class == Hash and transport.include? :case then
30
+ transport.publish queue: "splash.#{Socket.gethostname}.input",
31
+ message: { :verb => :reset,
32
+ :return_to => :ignore,
33
+ :queue => "splash.#{Socket.gethostname}.input" }.to_yaml
34
+ end
35
+ end
36
+ end
25
37
 
26
38
  end
27
39
 
@@ -1,9 +1,107 @@
1
- WebAdminApp.get '/commands' do
1
+ WebAdminApp.get '/commands/?:status?/?:command?' do
2
2
  get_menu 2
3
3
  log = get_logger
4
4
  log.call "WEB : commands, verb : GET, controller : /commands"
5
5
  url = "http://#{get_config.webadmin_ip}:#{get_config.webadmin_port}/api/commands/list.yml"
6
6
  raw = RestClient::Request.execute(method: 'GET', url: url,timeout: 10)
7
7
  @data = YAML::load(raw)[:data]
8
+ @command_failed = params[:command] if params[:status] == 'failure'
9
+ @command_saved = params[:command] if params[:status] == 'success'
8
10
  slim :commands, :format => :html
9
11
  end
12
+
13
+ WebAdminApp.get '/get_command_history/:command' do
14
+ get_menu 2
15
+ log = get_logger
16
+ log.call "WEB : commands, verb : GET, controller : /get_command_history/:command"
17
+ @data = {}
18
+ url = "http://#{get_config.webadmin_ip}:#{get_config.webadmin_port}/api/commands/history/#{params[:command].to_s}.yml"
19
+ raw = RestClient::Request.execute(method: 'GET', url: url,timeout: 10)
20
+ res = YAML::load(raw)
21
+ @data = res[:data] if res[:status] == :success
22
+ @command = params[:command].to_s
23
+ slim :command_history, :format => :html
24
+ end
25
+
26
+ WebAdminApp.get '/add_modify_command/?:command?' do
27
+ get_menu 2
28
+ log = get_logger
29
+ log.call "WEB : commands, verb : GET, controller : /add_modify_command/?:command?"
30
+ @data = {}
31
+ if params[:command] then
32
+ url = "http://#{get_config.webadmin_ip}:#{get_config.webadmin_port}/api/commands/show/#{params[:command].to_s}.yml"
33
+ raw = RestClient::Request.execute(method: 'GET', url: url,timeout: 10)
34
+ res = YAML::load(raw)
35
+ @data = res[:data] if res[:status] == :success
36
+ if @data[:retention].class == Hash then
37
+ prov = @data[:retention].flatten.reverse.join(' ')
38
+ @data[:retention] = prov
39
+ end
40
+ if @data[:schedule].class == Hash then
41
+ prov = @data[:schedule].flatten.join(' ')
42
+ @data[:schedule] = prov
43
+ end
44
+ if @data[:delegate_to].class == Hash then
45
+ prov = "#{@data[:delegate_to][:remote_command]}@#{@data[:delegate_to][:host]}"
46
+ @data[:delegate_to] = prov
47
+ end
48
+ @data[:old_command] = params[:command].to_s
49
+ end
50
+ slim :command_form, :format => :html
51
+ end
52
+
53
+
54
+ WebAdminApp.post '/save_command' do
55
+ get_menu 2
56
+ log = get_logger
57
+ log.call "WEB : commands, verb : POST, controller : /save_command"
58
+ data = {}
59
+ unless params[:retention].blank?
60
+ value, key = params[:retention].split(' ')
61
+ key = (key.nil?)? :days : key.to_sym
62
+ value = value.to_i
63
+ key = :days if key == :day
64
+ key = :hours if key == :hour
65
+ if [:hours,:days].include? key then
66
+ data[:retention] = {key => value}
67
+ end
68
+ end
69
+
70
+ unless params[:schedule].blank?
71
+ key, value = params[:schedule].split(' ')
72
+ key = key.to_sym unless key.nil?
73
+ value = '' if value.nil?
74
+ if [:in,:every,:at].include? key and value.match(/\d+[m,d,s,h]/) then
75
+ data[:schedule] = {key => value }
76
+ end
77
+ end
78
+
79
+ unless params[:delegate_to].blank?
80
+ key, value = params[:delegate_to].split('@')
81
+ unless key.blank? or value.blank? then
82
+ data[:delegate_to] = {:remote_command => key.to_sym, :host => value.to_sym }
83
+ end
84
+ end
85
+
86
+ data[:desc] = params[:desc]
87
+ data[:command] = params[:command] unless params[:command].blank?
88
+ data[:on_failure] = params[:on_failure].to_sym unless params[:on_failure].blank?
89
+ data[:on_success] = params[:on_success].to_sym unless params[:on_success].blank?
90
+ data[:user] = params[:user] unless params[:user].blank?
91
+ data[:name] = params[:name].split(' ').first.to_sym
92
+ puts params.to_yaml
93
+ puts data.to_yaml
94
+ redirect "/command/failure/#{params[:name].to_s}" if data[:command].blank? and data[:delegate_to].blank?
95
+ if params[:update] then
96
+ url = "http://#{get_config.webadmin_ip}:#{get_config.webadmin_port}/api/config/deletecommand/#{params[:old_command]}"
97
+ raw = RestClient::Request.execute(method: 'DELETE', url: url,timeout: 10)
98
+ end
99
+ url = "http://#{get_config.webadmin_ip}:#{get_config.webadmin_port}/api/config/addcommand.yml"
100
+ raw = RestClient::Request.execute(method: 'POST', url: url,timeout: 10, payload: data.to_yaml)
101
+ res = YAML::load(raw)
102
+ if res[:status] == :success then
103
+ redirect "/commands/success/#{params[:name].to_s}"
104
+ else
105
+ redirect "/commands/failure/#{params[:name].to_s}"
106
+ end
107
+ end
@@ -29,6 +29,10 @@ WebAdminApp.get '/add_modify_log/?:label?' do
29
29
  res = YAML::load(raw)
30
30
  @data = res[:data] if res[:status] == :success
31
31
  @data[:old_label] = params[:label].to_s
32
+ if @data[:retention].class == Hash then
33
+ prov = @data[:retention].flatten.reverse.join(' ')
34
+ @data[:retention] = prov
35
+ end
32
36
  end
33
37
  slim :log_form, :format => :html
34
38
  end
@@ -50,11 +54,21 @@ end
50
54
  WebAdminApp.post '/save_log' do
51
55
  get_menu 0
52
56
  log = get_logger
53
- log.call "WEB : logs, verb : POST, controller : /save_log/?:label?"
57
+ log.call "WEB : logs, verb : POST, controller : /save_log "
54
58
  data = {}
59
+ unless params[:retention].blank?
60
+ value, key = params[:retention].split(' ')
61
+ key = (key.nil?)? :days : key.to_sym
62
+ value = value.to_i
63
+ key = :days if key == :day
64
+ key = :hours if key == :hour
65
+ if [:hours,:days].include? key then
66
+ data[:retention] = {key => value}
67
+ end
68
+ end
55
69
  data[:log] = params[:log]
56
70
  data[:pattern] = params[:pattern]
57
- data[:label] = params[:label].to_sym
71
+ data[:label] = params[:label].split(' ').first.to_sym
58
72
  if params[:update] then
59
73
  url = "http://#{get_config.webadmin_ip}:#{get_config.webadmin_port}/api/config/deletelog/#{params[:old_label]}"
60
74
  raw = RestClient::Request.execute(method: 'DELETE', url: url,timeout: 10)
@@ -27,6 +27,10 @@ WebAdminApp.get '/add_modify_process/?:process?' do
27
27
  raw = RestClient::Request.execute(method: 'GET', url: url,timeout: 10)
28
28
  res = YAML::load(raw)
29
29
  @data = res[:data] if res[:status] == :success
30
+ if @data[:retention].class == Hash then
31
+ prov = @data[:retention].flatten.reverse.join(' ')
32
+ @data[:retention] = prov
33
+ end
30
34
  if @data[:patterns].class == Array then
31
35
  prov = @data[:patterns].join('|')
32
36
  @data[:patterns] = prov
@@ -53,10 +57,20 @@ end
53
57
  WebAdminApp.post '/save_process' do
54
58
  get_menu 1
55
59
  log = get_logger
56
- log.call "WEB : processes, verb : POST, controller : /save_process/?:process?"
60
+ log.call "WEB : processes, verb : POST, controller : /save_process"
57
61
  data = {}
58
62
  data[:patterns] = params[:patterns].split('|')
59
- data[:process] = params[:process].to_sym
63
+ data[:process] = params[:process].split(' ').first.to_sym
64
+ unless params[:retention].blank?
65
+ value, key = params[:retention].split(' ')
66
+ key = (key.nil?)? :days : key.to_sym
67
+ value = value.to_i
68
+ key = :days if key == :day
69
+ key = :hours if key == :hour
70
+ if [:hours,:days].include? key then
71
+ data[:retention] = {key => value}
72
+ end
73
+ end
60
74
  if params[:update] then
61
75
  url = "http://#{get_config.webadmin_ip}:#{get_config.webadmin_port}/api/config/deleteprocess/#{params[:old_process]}"
62
76
  raw = RestClient::Request.execute(method: 'DELETE', url: url,timeout: 10)
@@ -0,0 +1,45 @@
1
+ - unless @data.empty?
2
+ h2.uk-text-success <i class="uk-icon-#{@menu_icons[@current_item]} uk-icon-medium "></i>&nbsp;&nbsp;Modify Splash command definition : #{@data[:process]}
3
+ - else
4
+ h2.uk-text-success <i class="uk-icon-#{@menu_icons[@current_item]} uk-icon-medium "></i>&nbsp;&nbsp;Add new Splash command definition
5
+
6
+ script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.2/jquery.validate.min.js"
7
+
8
+ form.uk-form.uk-form-horizontal#query action="/save_command" method="POST"
9
+ div.uk-text-bold Definition
10
+ label.uk-form-label for="name" Name
11
+ <input class="uk-form-width-large" id="name" type="text" placeholder="name" name="name" value="#{@data[:name].to_s}" required>
12
+ div &nbsp;
13
+ label.uk-form-label for="command" Command
14
+ <input class="uk-form-width-large" id="command" type="text" placeholder="command" name="command" value="#{@data[:command].to_s}">
15
+ div &nbsp;
16
+ label.uk-form-label for="desc" Description
17
+ <input class="uk-form-width-large" id="desc" type="text" placeholder="description" name="desc" value="#{@data[:desc]}" required>
18
+ div &nbsp;
19
+ label.uk-form-label for="desc" Become User
20
+ <input class="uk-form-width-large" id="user" type="text" placeholder="user" name="user" value="#{@data[:user]}">
21
+ div &nbsp;
22
+ label.uk-form-label for="retention" Retention (Like "2 hours, 2 days")
23
+ <input class="uk-form-width-large" id="retention" type="text" placeholder="retention" name="retention" value="#{@data[:retention]}">
24
+ div &nbsp;
25
+ label.uk-form-label for="schedule" Scheduling (Like "'every 10m', 'in 1h', 'at 12:00'")
26
+ <input class="uk-form-width-large" id="schedule" type="text" placeholder="scheduling" name="schedule" value="#{@data[:schedule]}">
27
+ div &nbsp;
28
+ label.uk-form-label for="delegate_to" Delegation (Like "task_name@hostname")
29
+ <input class="uk-form-width-large" id="delegate_to" type="text" placeholder="delegation" name="delegate_to" value="#{@data[:delegate_to]}">
30
+ div &nbsp;
31
+ div &nbsp;
32
+ div.uk-text-bold Callbacks
33
+ label.uk-form-label for="on_success" On success
34
+ <input class="uk-form-width-large" id="on_success" type="text" placeholder="on success" name="on_success" value="#{@data[:on_success]}">
35
+ div &nbsp;
36
+ label.uk-form-label for="on_success" On failure
37
+ <input class="uk-form-width-large" id="on_failure" type="text" placeholder="on failure" name="on_failure" value="#{@data[:on_failure]}">
38
+ div &nbsp;
39
+ - unless @data.empty?
40
+ input type="hidden" name="update" value="true"
41
+ input type="hidden" name="old_command" value="#{@data[:old_command].to_s}"
42
+ div.uk-align-right
43
+ input.uk-button.uk-button-small-primary type="submit" value="Submit"
44
+ javascript:
45
+ $("#query").validate();
@@ -0,0 +1,27 @@
1
+ h2.uk-text-success <i class="uk-icon-#{@menu_icons[@current_item]} uk-icon-medium "></i>&nbsp;&nbsp;History for command #{@command} executions and monitoring
2
+
3
+
4
+ -
5
+ div.uk-width-medium-1-1
6
+ div.uk-panel.uk-panel-box
7
+ span.uk-text-large.uk-text-bold List of records
8
+ br
9
+ table#logrecords.uk-table.uk-table-hover.uk-table-striped
10
+ thead
11
+ tr
12
+ th Start Date
13
+ th End Date
14
+ th Execution time (sec)
15
+ th Status
16
+ th STDOUT empty ?
17
+ th STDERR empty ?
18
+
19
+ tbody
20
+ - @data.reverse.each do |key|
21
+ tr class="#{(key[key.keys.first][:status].to_s.split.last == "0")? 'uk-text-success' : 'uk-text-danger'}"
22
+ td #{key.keys.first}
23
+ td #{key[key.keys.first][:end_date]}
24
+ td #{key[key.keys.first][:exec_time]}
25
+ td #{key[key.keys.first][:status].to_s}
26
+ td #{key[key.keys.first][:stdout].empty?}
27
+ td #{key[key.keys.first][:stderr].empty?}
@@ -1,14 +1,49 @@
1
1
  h2.uk-text-success <i class="uk-icon-#{@menu_icons[@current_item]} uk-icon-medium "></i>&nbsp;&nbsp;Commands configured in Splash
2
2
 
3
+ - unless @log_saved.nil?
4
+ javascript:
5
+ UIkit.notify("Command definition #{@command_saved} saved", {status:'success'});
6
+ - unless @log_failed.nil?
7
+ javascript:
8
+ UIkit.notify("Command definition #{@command_saved} not saved", {status:'danger'});
9
+
10
+ javascript:
11
+ $(document).on( 'click','input.delete-command',function(){
12
+ var id = this.id;
13
+ var url = "/api/config/deletecommand/" + id + ".json";
14
+ UIkit.modal.confirm('Are you sure?', function(){
15
+ console.debug(url)
16
+ $.ajax({
17
+ url: url,
18
+ type: 'DELETE',
19
+ success: function( data ) {
20
+ console.debug(data)
21
+ if (data['status'] == 'success') {
22
+ $('div#commandrecords h3#' + id).remove();
23
+ $('div#commandrecords div#' + id).remove();
24
+ UIkit.notify("Deleting log for " + id + " done", {status:'success'});
25
+ }
26
+ else
27
+ {
28
+ UIkit.notify("Deleting log for " + id + " failed !", {status:'danger'});
29
+ }
30
+ },
31
+ error: function(e) {
32
+ UIkit.notify("Deleting log for " + id + " failed !", {status:'danger'});
33
+ }
34
+ });
35
+ });
36
+ });
37
+
3
38
  div.uk-width-medium-1-1
4
39
  div.uk-panel.uk-panel-box
5
40
  span.uk-text-large.uk-text-bold List of commands availables
6
41
  br
7
42
 
8
- div.uk-accordion(data-uk-accordion)
9
- - @data.each do |command,content|
10
- h3.uk-accordion-title <b>Name</b> : #{command}
11
- div.uk-accordion-content
43
+ div#commandrecords.uk-accordion(data-uk-accordion)
44
+ - @data.reverse.each do |command|
45
+ h3.uk-accordion-title id="#{command[:name].to_s}" <i class="uk-icon-play-circle-o"></i>&nbsp;<b>Name</b> : #{command[:name]}
46
+ div.uk-accordion-content id="#{command[:name].to_s} "
12
47
  table.uk-table.uk-table-hover.uk-table-striped
13
48
  thead
14
49
  tr
@@ -19,31 +54,46 @@ div.uk-width-medium-1-1
19
54
  td
20
55
  dl.uk-description-list-horizontal
21
56
  dt <i class="uk-icon-th-list"></i>&nbsp;Description
22
- dd #{content[:desc]}
23
- - if content[:command]
57
+ dd #{command[:desc]}
58
+ - if command[:command]
24
59
  dt <i class="uk-icon-cog"></i>&nbsp;Command Line
25
- dd #{content[:command]}
26
- - if content[:schedule]
60
+ - if command[:delegate_to]
61
+ dd.uk-text-danger #{command[:command]} <i>(ignored because delegate_to is set)</i>
62
+ - else
63
+ dd #{command[:command]}
64
+ - if command[:schedule]
27
65
  dt <i class="uk-icon-calendar"></i>&nbsp;Schedule
28
66
  dd
29
67
  <ul>
30
- <li> <b><i>Type</b></i> : #{content[:schedule].keys.first}</li>
31
- <li> <b><i>Value</b></i> : #{content[:schedule].values.first}</li>
68
+ <li> <b><i>Type</b></i> : #{command[:schedule].keys.first}</li>
69
+ <li> <b><i>Value</b></i> : #{command[:schedule].values.first}</li>
32
70
  </ul>
33
- - if content[:on_success]
71
+ - if command[:on_success]
34
72
  dt <i class="uk-icon-check"></i>&nbsp;Execute on success
35
- dd #{content[:on_success]}
36
- - if content[:on_failure]
73
+ dd #{command[:on_success]}
74
+ - if command[:on_failure]
37
75
  dt <i class="uk-icon-bolt"></i>&nbsp;Execute on failure
38
- dd #{content[:on_failure]}
39
- - if content[:user]
76
+ dd #{command[:on_failure]}
77
+ - if command[:user]
40
78
  dt <i class="uk-icon-user"></i>&nbsp;become user
41
- dd #{content[:user]}
42
- - if content[:delegate_to]
79
+ dd #{command[:user]}
80
+ - if command[:delegate_to]
43
81
  dt <i class="uk-icon-chevron-circle-right"></i>&nbsp;Remote delegation
44
82
  dd
45
83
  <ul>
46
- <li> <i><b>Host</b></i> : #{content[:delegate_to][:host]}</li>
47
- <li> <b><i>Remote Command</b></i> : #{content[:delegate_to][:remote_command]}</li>
84
+ <li> <i><b>Host</b></i> : #{command[:delegate_to][:host]}</li>
85
+ <li> <b><i>Remote Command</b></i> : #{command[:delegate_to][:remote_command]}</li>
48
86
  </ul>
87
+ - if command[:retention].class == Hash
88
+ dt <i class="uk-icon-calendar-minus-o"></i>&nbsp;History retention
89
+ dd #{command[:retention].flatten.reverse.join(' ')}
49
90
  td
91
+ input.delete-command.uk-button.uk-button-mini.uk-button-danger id="#{command[:name].to_s}" value="Delete"
92
+ br
93
+ input.modify-process.uk-button.uk-button-mini.uk-button-primary id="#{command[:name].to_s}" value="Modify" onclick="location.href='/add_modify_command/#{command[:name].to_s}';"
94
+ br
95
+ input.history-command.uk-button.uk-button-mini.uk-button-primary id="#{command[:name].to_s}" value="History" onclick="location.href='/get_command_history/#{command[:name].to_s}';"
96
+ div.uk-align-right
97
+ form.uk-form.uk-form-horizontal#query action="/add_modify_command" method="GET"
98
+ div &nbsp;
99
+ input.add-process.uk-button type="submit" value="Add new process"
@@ -15,6 +15,9 @@ form.uk-form.uk-form-horizontal#query action="/save_log" method="POST"
15
15
  label.uk-form-label for="log" Log file
16
16
  <input class="uk-form-width-large" id="log" type="text" placeholder="log" name="log" value="#{@data[:log]}" required>
17
17
  div &nbsp;
18
+ label.uk-form-label for="retention" Retention (Like "2 hours, 2 days")
19
+ <input class="uk-form-width-large" id="retention" type="text" placeholder="retention" name="retention" value="#{@data[:retention]}">
20
+ div &nbsp;
18
21
  - unless @data.empty?
19
22
  input type="hidden" name="update" value="true"
20
23
  input type="hidden" name="old_label" value="#{@data[:old_label].to_s}"
@@ -15,8 +15,8 @@ div.uk-width-medium-1-1
15
15
  th Nb Errors
16
16
  th Full Nb of lines
17
17
  tbody
18
- - @data.each do |key|
19
- tr
18
+ - @data.reverse.each do |key|
19
+ tr class="#{(key[key.keys.first][:status] == :clean)? 'uk-text-success' : 'uk-text-danger'}"
20
20
  td #{key.keys.first}
21
21
  td #{key[key.keys.first][:file]}
22
22
  td #{key[key.keys.first][:status]}
@@ -74,23 +74,25 @@ div.uk-width-medium-1-1
74
74
  tbody
75
75
  - @data.each do |log|
76
76
  tr id="#{log[:label].to_s}"
77
- td <b>Label</b> : #{log[:label]}
77
+ td <i class="uk-icon-tag"></i>&nbsp;<b>Label</b> : #{log[:label]}
78
78
  td
79
79
  ul
80
- li <b>File</b> : #{log[:log]}
81
- li <b>Pattern</b> : #{log[:pattern]}
80
+ li <i class="uk-icon-file"></i>&nbsp;<b>File</b> : #{log[:log]}
81
+ li <i class="uk-icon-binoculars"></i>&nbsp;<b>Pattern</b> : #{log[:pattern]}
82
+ - if log[:retention].class == Hash
83
+ li <i class="uk-icon-calendar-minus-o"></i>&nbsp;<b>History retention</b> : #{log[:retention].flatten.reverse.join(' ')}
82
84
  td
83
85
  - if @result[log[:label]][:status] == :missing
84
86
  div.uk-badge.uk-badge-warning missing
85
87
  - if @result[log[:label]][:status] == :clean
86
88
  div.uk-badge.uk-badge-success success
87
89
  ul
88
- li <b>Lines count</b> : #{@result[log[:label]][:lines]}
90
+ li <i class="uk-icon-asterisk"></i>&nbsp;<b>Lines count</b> : #{@result[log[:label]][:lines]}
89
91
  - if @result[log[:label]][:status] == :matched
90
92
  div.uk-badge.uk-badge-danger matched
91
93
  ul
92
- li <b>Lines count</b> : #{@result[log[:label]][:lines]}
93
- li <b class="uk-text-danger">Matchs count : #{@result[log[:label]][:count]} </b>
94
+ li <i class="uk-icon-asterisk"></i>&nbsp;<b>Lines count</b> : #{@result[log[:label]][:lines]}
95
+ li <i class="uk-icon-bolt"></i>&nbsp;<b class="uk-text-danger">Matchs count : #{@result[log[:label]][:count]} </b>
94
96
  td
95
97
  input.delete-log.uk-button.uk-button-mini.uk-button-danger id="#{log[:label].to_s}" value="Delete"
96
98
  br
@@ -9,9 +9,12 @@ form.uk-form.uk-form-horizontal#query action="/save_process" method="POST"
9
9
  label.uk-form-label for="process" Process
10
10
  <input class="uk-form-width-large" id="process" type="text" placeholder="process" name="process" value="#{@data[:process].to_s}" required>
11
11
  div &nbsp;
12
- label.uk-form-label for="patterns" Patterns
12
+ label.uk-form-label for="patterns" Patterns (separator is "|")
13
13
  <input class="uk-form-width-large" id="patterns" type="text" placeholder="patterns" name="patterns" value="#{@data[:patterns]}" required>
14
14
  div &nbsp;
15
+ label.uk-form-label for="retention" Retention (Like "2 hours, 2 days")
16
+ <input class="uk-form-width-large" id="retention" type="text" placeholder="retention" name="retention" value="#{@data[:retention]}">
17
+ div &nbsp;
15
18
  - unless @data.empty?
16
19
  input type="hidden" name="update" value="true"
17
20
  input type="hidden" name="old_process" value="#{@data[:old_process].to_s}"
@@ -15,10 +15,10 @@ div.uk-width-medium-1-1
15
15
  th % CPU
16
16
  th % MEM
17
17
  tbody
18
- - @data.each do |key|
19
- tr
18
+ - @data.reverse.each do |key|
19
+ tr class="#{(key[key.keys.first][:status] == :running)? 'uk-text-success' : 'uk-text-danger'}"
20
20
  td #{key.keys.first}
21
21
  td #{key[key.keys.first][:process]}
22
22
  td #{key[key.keys.first][:status]}
23
- td #{key[key.keys.first][:cpu]}
24
- td #{key[key.keys.first][:mem]}
23
+ td #{key[key.keys.first][:cpu_percent]}
24
+ td #{key[key.keys.first][:mem_percent]}
@@ -72,20 +72,23 @@ div.uk-width-medium-1-1
72
72
  tbody
73
73
  - @data.each do |process|
74
74
  tr id="#{process[:process].to_s}"
75
- td <b>Process</b> : #{process[:process]}
75
+ td <i class="uk-icon-cog"></i>&nbsp;<b>Process</b> : #{process[:process]}
76
76
  td
77
- span.uk-text-bold Patterns
77
+ - if process[:retention].class == Hash
78
+ div <i class="uk-icon-calendar-minus-o"></i>&nbsp;<b>History retention</b> : #{process[:retention].flatten.reverse.join(' ')}
79
+ span.uk-text-bold <i class="uk-icon-binoculars"></i>&nbsp; Patterns
78
80
  ul
79
81
  - process[:patterns].each do |pattern|
80
82
  li= pattern
83
+
81
84
  td
82
85
  - if @result[process[:process]][:status] == :inexistant
83
86
  div.uk-badge.uk-badge-danger not running
84
87
  - if @result[process[:process]][:status] == :running
85
88
  div.uk-badge.uk-badge-success running
86
89
  ul
87
- li <b>CPU usage</b> : #{@result[process[:process]][:cpu]}
88
- li <b>MEM usage</b> : #{@result[process[:process]][:mem]}
90
+ li <i class="uk-icon-percent"></i>&nbsp;<b>CPU usage</b> : #{@result[process[:process]][:cpu]}
91
+ li <i class="uk-icon-percent"></i>&nbsp;<b>MEM usage</b> : #{@result[process[:process]][:mem]}
89
92
  td
90
93
  input.delete-process.uk-button.uk-button-mini.uk-button-danger id="#{process[:process].to_s}" value="Delete"
91
94
  br
@@ -20,6 +20,7 @@ module Splash
20
20
  # Start the Splash Daemon
21
21
  # @param [Hash] options
22
22
  # @option options [Symbol] :quiet activate quiet mode for log (limit to :fatal)
23
+ # @option options [Symbol] :foreground run webadmin in foreground
23
24
  # @return [Hash] Exiter Case (:quiet_exit, :already_exist, :unknown_error or other)
24
25
  def startweb(options = {})
25
26
  require 'splash/webadmin/main'
@@ -37,7 +38,8 @@ module Splash
37
38
  daemon_config = {:description => config.webadmin_process_name,
38
39
  :pid_file => config.webadmin_full_pid_path,
39
40
  :stdout_trace => config.webadmin_full_stdout_trace_path,
40
- :stderr_trace => config.webadmin_full_stderr_trace_path
41
+ :stderr_trace => config.webadmin_full_stderr_trace_path,
42
+ :foreground => options[:foreground]
41
43
  }
42
44
 
43
45
  ["int","term","hup"].each do |type| daemon_config["sig#{type}_handler".to_sym] = Proc::new { WebAdminApp.quit! } end
data/templates/.env ADDED
File without changes
@@ -0,0 +1,5 @@
1
+ FROM ruby:latest
2
+ RUN gem install prometheus-splash
3
+ RUN splash conf set
4
+ EXPOSE 9234
5
+ CMD ["splash","web", "start" ,"-F"]
@@ -0,0 +1,14 @@
1
+ version: "3"
2
+
3
+ services:
4
+ redis:
5
+ image: redis:latest
6
+
7
+ splash:
8
+ build: .
9
+ env_file: .env
10
+ ports:
11
+ - 9234:9234
12
+ depends_on:
13
+ - redis
14
+
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.8.4
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Romain GEORGES
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-02 00:00:00.000000000 Z
11
+ date: 2022-05-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -431,6 +431,7 @@ files:
431
431
  - lib/splash/loggers/dual.rb
432
432
  - lib/splash/loggers/web.rb
433
433
  - lib/splash/logs.rb
434
+ - lib/splash/monkeys.rb
434
435
  - lib/splash/processes.rb
435
436
  - lib/splash/sequences.rb
436
437
  - lib/splash/templates.rb
@@ -464,6 +465,8 @@ files:
464
465
  - lib/splash/webadmin/portal/public/images/logo_splash.png
465
466
  - lib/splash/webadmin/portal/public/images/logo_splash_reduce.png
466
467
  - lib/splash/webadmin/portal/public/images/logo_splash_tiny.png
468
+ - lib/splash/webadmin/portal/views/command_form.slim
469
+ - lib/splash/webadmin/portal/views/command_history.slim
467
470
  - lib/splash/webadmin/portal/views/commands.slim
468
471
  - lib/splash/webadmin/portal/views/documentation.slim
469
472
  - lib/splash/webadmin/portal/views/home.slim
@@ -483,6 +486,8 @@ files:
483
486
  - prometheus-splash.gemspec
484
487
  - spec/helpers_spec.rb
485
488
  - spec/templates_spec.rb
489
+ - templates/.env
490
+ - templates/Dockerfile
486
491
  - templates/ansible-splash/Vagrantfile
487
492
  - templates/ansible-splash/deploy.yml
488
493
  - templates/ansible-splash/group_vars/DEV.yml
@@ -505,6 +510,7 @@ files:
505
510
  - templates/ansible-splash/roles/supervision_master/tasks/main.yml
506
511
  - templates/ansible-splash/roles/supervision_master/templates/alertmanager.yml.j2
507
512
  - templates/ansible-splash/roles/supervision_master/templates/prometheus.yml.j2
513
+ - templates/docker-compose.yml
508
514
  - templates/report.txt
509
515
  - templates/splashd.service
510
516
  - test.sh
@@ -513,7 +519,7 @@ homepage: https://github.com/Ultragreen/prometheus-splash
513
519
  licenses:
514
520
  - BSD-2-Clause
515
521
  metadata: {}
516
- post_install_message:
522
+ post_install_message:
517
523
  rdoc_options: []
518
524
  require_paths:
519
525
  - lib
@@ -529,7 +535,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
529
535
  version: '0'
530
536
  requirements: []
531
537
  rubygems_version: 3.1.2
532
- signing_key:
538
+ signing_key:
533
539
  specification_version: 4
534
540
  summary: Supervision with Prometheus of Logs and Asynchronous tasks orchestration
535
541
  for Services or Hosts