prometheus-splash 0.1.0 → 0.1.1

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.
@@ -0,0 +1,20 @@
1
+ # coding: utf-8
2
+ Dir[File.dirname(__FILE__) + '/cli/*.rb'].each {|file| require file }
3
+
4
+ class CLI < Thor
5
+ def self.exit_on_failure?
6
+ true
7
+ end
8
+
9
+ include CLISplash
10
+ desc "commands SUBCOMMAND ...ARGS", "Managing commands/batchs supervision"
11
+ subcommand "commands", Commands
12
+ desc "logs SUBCOMMAND ...ARGS", "Managing Files/Logs supervision"
13
+ subcommand "logs", Logs
14
+ desc "daemon SUBCOMMAND ...ARGS", "Logs monitor daemon contoller"
15
+ subcommand "daemon", CLIController
16
+ desc "config SUBCOMMAND ...ARGS", "config tools for Splash"
17
+ subcommand "config", Config
18
+ desc "documentation SUBCOMMAND ...ARGS", "Documentation for Splash"
19
+ subcommand "documentation", Documentation
20
+ end
@@ -0,0 +1,164 @@
1
+ # coding: utf-8
2
+ module CLISplash
3
+
4
+
5
+ class Commands < Thor
6
+ include Splash::Config
7
+ include Splash::Backends
8
+ include Splash::Exiter
9
+
10
+ desc "execute NAME", "run for command/sequence or ack result"
11
+ long_desc <<-LONGDESC
12
+ execute command or sequence or ack result
13
+ with --no-trace prevent storing execution trace in configured backend (see config file)
14
+ with --ack, notify errorcode=0 to Prometheus PushGateway
15
+ with --no-notify, bypass Prometheus notification
16
+ with --no-callback, never execute callback (:on_failure, :on_success)
17
+ never follow sequences
18
+ LONGDESC
19
+ option :trace, :type => :boolean, :default => true
20
+ option :ack, :type => :boolean, negate: false
21
+ option :notify, :type => :boolean, :default => true
22
+ option :callback, :type => :boolean, :default => true
23
+ def execute(name)
24
+ if is_root? then
25
+ command = Splash::CommandWrapper::new(name)
26
+ if options[:ack] then
27
+ splash_exit command.ack
28
+ end
29
+ acase = command.call_and_notify trace: options[:trace], notify: options[:notify], callback: options[:callback]
30
+ splash_exit acase
31
+ else
32
+ splash_exit case: :not_root, :more => "Command execution"
33
+ end
34
+ end
35
+
36
+
37
+ desc "treeview", "Show commands sequence tree"
38
+ def treeview(command, depht = 0)
39
+ puts "Command : #{command.to_s}" if depht == 0
40
+ cmd = get_config.commands[command.to_sym]
41
+ if cmd[:on_failure] then
42
+ print " " * depht + " "
43
+ puts "* on failure => #{cmd[:on_failure]}"
44
+ treeview(cmd[:on_failure], depht+2)
45
+ end
46
+ if cmd[:on_success] then
47
+ print " " * depht + " "
48
+ puts "* on success => #{cmd[:on_success]}"
49
+ treeview(cmd[:on_success],depht+2)
50
+ end
51
+ splash_exit case: :quiet_exit
52
+ end
53
+
54
+
55
+ desc "list", "Show configured commands"
56
+ long_desc <<-LONGDESC
57
+ Show configured commands
58
+ with --detail, show command details
59
+ LONGDESC
60
+ option :detail, :type => :boolean
61
+ def list
62
+ puts "Splash configured commands :"
63
+ list = get_config.commands
64
+ puts 'No configured commands found' if list.keys.empty?
65
+ list.keys.each do |command|
66
+ puts " * #{command.to_s}"
67
+ if options[:detail] then
68
+ puts " - command line : '#{list[command][:command]}'"
69
+ puts " - command description : '#{list[command][:desc]}'"
70
+ puts " - command failure callback : '#{list[command.to_sym][:on_failure]}'" if list[command.to_sym][:on_failure]
71
+ puts " - command success callback : '#{list[command.to_sym][:on_success]}'" if list[command.to_sym][:on_success]
72
+ end
73
+ end
74
+ splash_exit case: :quiet_exit
75
+ end
76
+
77
+
78
+ desc "show COMMAND", "Show specific configured command COMMAND"
79
+ def show(command)
80
+ list = get_config.commands
81
+ if list.keys.include? command.to_sym then
82
+ puts "Splash command : #{command}"
83
+ puts " - command line : '#{list[command.to_sym][:command]}'"
84
+ puts " - command description : '#{list[command.to_sym][:desc]}'"
85
+ puts " - command failure callback : '#{list[command.to_sym][:on_failure]}'" if list[command.to_sym][:on_failure]
86
+ puts " - command success callback : '#{list[command.to_sym][:on_success]}'" if list[command.to_sym][:on_success]
87
+ splash_exit case: :quiet_exit
88
+ else
89
+ splash_exit case: :not_found, :more => 'Command not configured'
90
+ end
91
+ end
92
+
93
+
94
+ desc "lastrun COMMAND", "Show last running result for specific configured command COMMAND"
95
+ long_desc <<-LONGDESC
96
+ Show last running result for specific configured command COMMAND
97
+ with --hostname <HOSTNAME>, an other Splash monitored server (only with Redis backend configured)
98
+ LONGDESC
99
+ option :hostname, :type => :string
100
+ def lastrun(command)
101
+ backend = get_backend :execution_trace
102
+ redis = (backend.class == Splash::Backends::Redis)? true : false
103
+ if not redis and options[:hostname] then
104
+ splash_exit case: :specific_config_required, :more => "Redis backend is requiered for Remote execution report request"
105
+ end
106
+ list = get_config.commands
107
+ if list.keys.include? command.to_sym then
108
+ print "Splash command #{command} previous execution report:\n\n"
109
+ req = { :key => command}
110
+ req[:hostname] = options[:hostname] if options[:hostname]
111
+ if backend.exist? req then
112
+ print backend.get req
113
+ else
114
+ puts "Command not already runned."
115
+ end
116
+ splash_exit case: :quiet_exit
117
+ else
118
+ splash_exit case: :command_not_configured
119
+ end
120
+ end
121
+
122
+ desc "getreportlist", "list all executions report results "
123
+ long_desc <<-LONGDESC
124
+ list all executions report results
125
+ with --pattern <SEARCH>, search type string, wilcard * (group) ? (char)\n
126
+ with --hostname <HOSTNAME>, an other Splash monitored server (only with Redis backend configured)\n
127
+ with --all, get all execution report for all servers (only with Redis backend configured)\n
128
+ --all and --hostname are exclusives
129
+ LONGDESC
130
+ option :pattern, :type => :string
131
+ option :hostname, :type => :string
132
+ option :all, :type => :boolean, :negate => false
133
+ def getreportlist
134
+ if options[:hostname] and options[:all] then
135
+ splash_exit case: :options_incompatibility, more: "--all, --hostname"
136
+ end
137
+ backend = get_backend :execution_trace
138
+ redis = (backend.class == Splash::Backends::Redis)? true : false
139
+ if not redis and (options[:hostname] or options[:all]) then
140
+ splash_exit case: :redis_back_required, more: "Remote execution report Request"
141
+ end
142
+ pattern = (options[:pattern])? options[:pattern] : '*'
143
+ if options[:all] then
144
+ res = backend.listall pattern
145
+ elsif options[:hostname]
146
+ res = backend.list pattern, options[:hostname]
147
+ else
148
+ res = backend.list pattern
149
+ end
150
+ print "List of Executions reports :\n\n"
151
+ puts "Not reports found" if res.empty?
152
+ res.each do |item|
153
+ if options[:all]
154
+ host,command = item.split('#')
155
+ puts " * Command : #{command} @ host : #{host}"
156
+ else
157
+ puts " * Command : #{item}"
158
+ end
159
+ end
160
+ splash_exit case: :quiet_exit
161
+ end
162
+
163
+ end
164
+ end
@@ -0,0 +1,37 @@
1
+ # coding: utf-8
2
+ module CLISplash
3
+
4
+ class Config < Thor
5
+ include Splash::Config
6
+ include Splash::Helpers
7
+ include Splash::Exiter
8
+
9
+
10
+ desc "setup", "Setup installation fo Splash"
11
+ long_desc <<-LONGDESC
12
+ Setup installation fo Splash
13
+ with --preserve, preserve from reinstallation of the config
14
+ LONGDESC
15
+ option :preserve, :type => :boolean
16
+ def setup
17
+ acase = run_as_root :setupsplash
18
+ splash_exit acase
19
+ end
20
+
21
+ desc "sanitycheck", "Verify installation fo Splash"
22
+ def sanitycheck
23
+ acase = run_as_root :checkconfig
24
+ splash_exit acase
25
+ end
26
+
27
+ desc "version", "display current Splash version"
28
+ def version
29
+ config = get_config
30
+ puts "Splash version : #{config.version}, Author : #{config.author}"
31
+ puts config.copyright
32
+ splash_exit case: :quiet_exit
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,52 @@
1
+ # coding: utf-8
2
+ module CLISplash
3
+
4
+ class CLIController < Thor
5
+ include Splash::LogsMonitor::DaemonController
6
+ include Splash::Transports
7
+ include Splash::Exiter
8
+
9
+
10
+ option :foreground, :type => :boolean
11
+ desc "start", "Starting Logs Monitor Daemon"
12
+ def start
13
+ acase = run_as_root :startdaemon
14
+ splash_exit acase
15
+ end
16
+
17
+ desc "stop", "Stopping Logs Monitor Daemon"
18
+ def stop
19
+ acase = run_as_root :stopdaemon
20
+ splash_exit acase
21
+ end
22
+
23
+ desc "status", "Logs Monitor Daemon status"
24
+ def status
25
+ acase = run_as_root :statusdaemon
26
+ splash_exit acase
27
+ end
28
+
29
+ desc "ping HOSTNAME", "send a ping to HOSTNAME daemon over transport (need an active tranport), Typicallly RabbitMQ"
30
+ def ping(hostname=Socket.gethostname)
31
+ puts "ctrl+c for interrupt"
32
+ queue = "splash.#{Socket.gethostname}.returncli"
33
+ order = {:verb => :ping, :payload => {:hostname => Socket.gethostname}, :return_to => queue}
34
+
35
+ lock = Mutex.new
36
+ condition = ConditionVariable.new
37
+ begin
38
+ get_default_subscriber(queue: queue).subscribe(timeout: 10) do |delivery_info, properties, payload|
39
+ puts YAML::load(payload)
40
+ lock.synchronize { condition.signal }
41
+ end
42
+ get_default_client.publish queue: "splash.#{hostname}.input", message: order.to_yaml
43
+ lock.synchronize { condition.wait(lock) }
44
+ splash_exit case: :quiet_exit
45
+ rescue Interrupt
46
+ splash_exit status: :error, case: :interrupt, more: "Ping Command"
47
+ end
48
+ end
49
+
50
+ end
51
+
52
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ module CLISplash
3
+
4
+ class Documentation < Thor
5
+ include Splash::Config
6
+ include Splash::Exiter
7
+
8
+
9
+ desc "readme", "Display README file"
10
+ option :formatted, :type => :boolean, :default => true
11
+ def readme
12
+ filename = search_file_in_gem("prometheus-splash","README.md")
13
+
14
+ if options[:formatted] then
15
+ content = TTY::Markdown.parse_file(filename)
16
+ else
17
+ conten = File::readlines(filename).join
18
+ end
19
+ pager = TTY::Pager.new
20
+ pager.page(content)
21
+ splash_exit case: :quiet_exit
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,72 @@
1
+ # coding: utf-8
2
+ module CLISplash
3
+
4
+ class Logs < Thor
5
+ include Splash::Config
6
+ include Splash::Exiter
7
+
8
+
9
+ desc "analyse", "analyze logs in config"
10
+ def analyse
11
+ results = Splash::LogScanner::new
12
+ res = results.analyse
13
+ puts "SPlash Configured logs status :"
14
+ full_status = true
15
+ results.output.each do |result|
16
+ status = (result[:status] == :clean)? "OK": "KO"
17
+ puts " * Log : #{result[:log]} : [#{status}]"
18
+ puts " - Detected pattern : #{result[:pattern]}"
19
+ puts " - detailled Status : #{result[:status].to_s}"
20
+ puts " count = #{result[:count]}" if result[:status] == :matched
21
+ puts " nb lines = #{result[:lines]}" if result[:status] != :missing
22
+ full_status = false unless result[:status] == :clean
23
+ end
24
+ display_status = (full_status)? "OK": "KO"
25
+ puts "Global Status : [#{display_status}]"
26
+ splash_exit case: :quiet_exit
27
+ end
28
+
29
+ desc "monitor", "monitor logs in config"
30
+ def monitor
31
+ result = Splash::LogScanner::new
32
+ result.analyse
33
+ result.notify
34
+ splash_exit result.notify
35
+
36
+ end
37
+
38
+ desc "show LOG", "show configured log monitoring for LOG"
39
+ def show(log)
40
+ log_record_set = get_config.logs.select{|item| item[:log] == log }
41
+ unless log_record_set.empty? then
42
+ record = log_record_set.first
43
+ puts "Splash log monitor : #{record[:log]}"
44
+ puts " -> pattern : /#{record[:pattern]}/"
45
+ splash_exit case: :quiet_exit
46
+ else
47
+ splash_exit case: :not_found, :more => "log not configured"
48
+ end
49
+ end
50
+
51
+ desc "list", "Show configured logs monitoring"
52
+ long_desc <<-LONGDESC
53
+ Show configured logs monitoring
54
+ with --detail, show logs monitor details
55
+ LONGDESC
56
+ option :detail, :type => :boolean
57
+ def list
58
+ puts "Splash configured log monitoring :"
59
+ log_record_set = get_config.logs
60
+ puts 'No configured commands found' if log_record_set.empty?
61
+ log_record_set.each do |record|
62
+ puts " * log monitor : #{record[:log]}"
63
+ if options[:detail] then
64
+ puts " -> pattern : /#{record[:pattern]}/"
65
+ end
66
+ end
67
+ splash_exit case: :quiet_exit
68
+ end
69
+
70
+ end
71
+
72
+ end
@@ -1,20 +1,17 @@
1
- require 'open3'
2
- require 'date'
3
- require 'socket'
4
-
1
+ # coding: utf-8
5
2
  module Splash
6
3
  class CommandWrapper
7
4
  include Splash::Templates
8
5
  include Splash::Config
9
6
  include Splash::Helpers
10
7
  include Splash::Backends
8
+ include Splash::Exiter
11
9
 
12
10
  def initialize(name)
13
11
  @config = get_config
14
12
  @name = name
15
13
  unless @config.commands.keys.include? @name.to_sym then
16
- $stderr.puts "Splash : command #{@name} is not defined in configuration"
17
- exit 40
14
+ splash_exit case: :not_found, more: "command #{@name} is not defined in configuration"
18
15
  end
19
16
  @registry = Prometheus::Client.registry
20
17
  @url = "http://#{@config.prometheus_pushgateway_host}:#{@config.prometheus_pushgateway_port}"
@@ -26,26 +23,25 @@ module Splash
26
23
 
27
24
  def ack
28
25
  puts "Sending ack for command : '#{@name}'"
29
- notify(0)
30
- exit 0
26
+ notify(0,0)
31
27
  end
32
28
 
33
29
  def notify(value,time)
34
30
  unless verify_service host: @config.prometheus_pushgateway_host ,port: @config.prometheus_pushgateway_port then
35
- $stderr.puts "Prometheus PushGateway Service IS NOT running"
36
- $stderr.puts "Exit without notification."
37
- exit 30
31
+ return { :case => :service_dependence_missing, :more => "Prometheus Notification not send."}
38
32
  end
39
33
  @metric_exitcode.set(value)
40
34
  @metric_time.set(time)
41
35
  hostname = Socket.gethostname
42
36
  Prometheus::Client::Push.new(@name, hostname, @url).add(@registry)
43
37
  puts " * Prometheus Gateway notified."
38
+ return { :case => :quiet_exit}
44
39
  end
45
40
 
46
41
 
47
42
  def call_and_notify(options)
48
43
  puts "Executing command : '#{@name}' "
44
+ acase = { :case => :quiet_exit }
49
45
  start = Time.now
50
46
  start_date = DateTime.now.to_s
51
47
  unless options[:trace] then
@@ -89,7 +85,7 @@ module Splash
89
85
 
90
86
  puts " => exitcode #{exit_code}"
91
87
  if options[:notify] then
92
- notify(exit_code,time.to_i)
88
+ acase = notify(exit_code,time.to_i)
93
89
  else
94
90
  puts " * Without Prometheus notification"
95
91
  end
@@ -103,7 +99,7 @@ module Splash
103
99
  @name = on_failure.to_s
104
100
  call_and_notify options
105
101
  else
106
- $stderr.puts "on_failure call error : configuration mistake : #{on_failure} command inexistant."
102
+ acase = { :case => :configuration_error , :more => "on_failure call error : #{on_failure} command inexistant."}
107
103
  end
108
104
  end
109
105
  if on_success and exit_code == 0 then
@@ -118,8 +114,7 @@ module Splash
118
114
  else
119
115
  puts " * Without callbacks sequences"
120
116
  end
121
-
122
- exit exit_code
117
+ return acase
123
118
  end
124
119
  end
125
120
  end