portertech-sensu 1.10.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 (51) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +961 -0
  3. data/MIT-LICENSE.txt +20 -0
  4. data/README.md +65 -0
  5. data/exe/sensu-api +10 -0
  6. data/exe/sensu-client +10 -0
  7. data/exe/sensu-install +195 -0
  8. data/exe/sensu-server +10 -0
  9. data/lib/sensu/api/http_handler.rb +434 -0
  10. data/lib/sensu/api/process.rb +79 -0
  11. data/lib/sensu/api/routes/aggregates.rb +196 -0
  12. data/lib/sensu/api/routes/checks.rb +44 -0
  13. data/lib/sensu/api/routes/clients.rb +171 -0
  14. data/lib/sensu/api/routes/events.rb +86 -0
  15. data/lib/sensu/api/routes/health.rb +45 -0
  16. data/lib/sensu/api/routes/info.rb +37 -0
  17. data/lib/sensu/api/routes/request.rb +44 -0
  18. data/lib/sensu/api/routes/resolve.rb +32 -0
  19. data/lib/sensu/api/routes/results.rb +153 -0
  20. data/lib/sensu/api/routes/settings.rb +23 -0
  21. data/lib/sensu/api/routes/silenced.rb +182 -0
  22. data/lib/sensu/api/routes/stashes.rb +107 -0
  23. data/lib/sensu/api/routes.rb +88 -0
  24. data/lib/sensu/api/utilities/filter_response_content.rb +44 -0
  25. data/lib/sensu/api/utilities/publish_check_request.rb +107 -0
  26. data/lib/sensu/api/utilities/publish_check_result.rb +39 -0
  27. data/lib/sensu/api/utilities/resolve_event.rb +29 -0
  28. data/lib/sensu/api/utilities/servers_info.rb +43 -0
  29. data/lib/sensu/api/utilities/transport_info.rb +43 -0
  30. data/lib/sensu/api/validators/check.rb +55 -0
  31. data/lib/sensu/api/validators/client.rb +35 -0
  32. data/lib/sensu/api/validators/invalid.rb +8 -0
  33. data/lib/sensu/cli.rb +69 -0
  34. data/lib/sensu/client/http_socket.rb +217 -0
  35. data/lib/sensu/client/process.rb +655 -0
  36. data/lib/sensu/client/socket.rb +207 -0
  37. data/lib/sensu/client/utils.rb +53 -0
  38. data/lib/sensu/client/validators/check.rb +53 -0
  39. data/lib/sensu/constants.rb +17 -0
  40. data/lib/sensu/daemon.rb +396 -0
  41. data/lib/sensu/sandbox.rb +19 -0
  42. data/lib/sensu/server/filter.rb +227 -0
  43. data/lib/sensu/server/handle.rb +201 -0
  44. data/lib/sensu/server/mutate.rb +92 -0
  45. data/lib/sensu/server/process.rb +1646 -0
  46. data/lib/sensu/server/socket.rb +54 -0
  47. data/lib/sensu/server/tessen.rb +170 -0
  48. data/lib/sensu/utilities.rb +398 -0
  49. data/lib/sensu.rb +3 -0
  50. data/sensu.gemspec +36 -0
  51. metadata +322 -0
@@ -0,0 +1,44 @@
1
+ module Sensu
2
+ module API
3
+ module Routes
4
+ module Checks
5
+ CHECKS_URI = /^\/checks$/
6
+ CHECK_URI = /^\/checks\/([\w\.-]+)$/
7
+
8
+ # GET /checks
9
+ def get_checks
10
+ checks = @settings.checks.reject { |check| check[:standalone] }
11
+ @response_content = pagination(checks)
12
+ respond
13
+ end
14
+
15
+ # GET /checks/:check_name
16
+ def get_check
17
+ check_name = parse_uri(CHECK_URI).first
18
+ if @settings[:checks][check_name] && !@settings[:checks][check_name][:standalone]
19
+ @response_content = @settings[:checks][check_name].merge(:name => check_name)
20
+ respond
21
+ else
22
+ not_found!
23
+ end
24
+ end
25
+
26
+ # DELETE /checks/:check_name
27
+ def delete_check
28
+ check_name = parse_uri(CHECK_URI).first
29
+ @redis.smembers("clients") do |clients|
30
+ result_keys = clients.map {|client_name| "result:#{client_name}:#{check_name}"}
31
+ history_keys = clients.map {|client_name| "history:#{client_name}:#{check_name}"}
32
+ last_ok_keys = clients.map {|client_name| "history:#{client_name}:#{check_name}:last_ok"}
33
+ keys = result_keys.concat(history_keys).concat(last_ok_keys)
34
+ keys.each do |key|
35
+ @redis.del(key)
36
+ end
37
+ end
38
+ @response_content = {:issued => Time.now.to_i}
39
+ accepted!
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,171 @@
1
+ require "sensu/api/validators/client"
2
+ require "sensu/api/utilities/resolve_event"
3
+
4
+ module Sensu
5
+ module API
6
+ module Routes
7
+ module Clients
8
+ include Utilities::ResolveEvent
9
+
10
+ CLIENTS_URI = /^\/clients$/
11
+ CLIENT_URI = /^\/clients\/([\w\.-]+)$/
12
+ CLIENT_HISTORY_URI = /^\/clients\/([\w\.-]+)\/history$/
13
+
14
+ # POST /clients
15
+ def post_clients
16
+ read_data do |client|
17
+ client[:keepalives] = client.fetch(:keepalives, false)
18
+ client[:version] = VERSION
19
+ client[:timestamp] = Time.now.to_i
20
+ client[:subscriptions] ||= []
21
+ validator = Validators::Client.new
22
+ if validator.valid?(client)
23
+ client[:subscriptions] = (client[:subscriptions] + ["client:#{client[:name]}"]).uniq
24
+ @redis.set("client:#{client[:name]}", Sensu::JSON.dump(client)) do
25
+ @redis.sadd("clients", client[:name]) do
26
+ @response_content = {:name => client[:name]}
27
+ created!
28
+ end
29
+ end
30
+ else
31
+ bad_request!
32
+ end
33
+ end
34
+ end
35
+
36
+ # GET /clients
37
+ def get_clients
38
+ @response_content = []
39
+ @redis.smembers("clients") do |clients|
40
+ clients = pagination(clients)
41
+ unless clients.empty?
42
+ clients.each_with_index do |client_name, index|
43
+ @redis.get("client:#{client_name}") do |client_json|
44
+ unless client_json.nil?
45
+ client = Sensu::JSON.load(client_json)
46
+ @response_content << redact_sensitive(client, client[:redact])
47
+ else
48
+ @logger.error("client data missing from registry", :client_name => client_name)
49
+ @redis.srem("clients", client_name)
50
+ end
51
+ if index == clients.length - 1
52
+ respond
53
+ end
54
+ end
55
+ end
56
+ else
57
+ respond
58
+ end
59
+ end
60
+ end
61
+
62
+ # GET /clients/:client_name
63
+ def get_client
64
+ client_name = parse_uri(CLIENT_URI).first
65
+ @redis.get("client:#{client_name}") do |client_json|
66
+ unless client_json.nil?
67
+ client = Sensu::JSON.load(client_json)
68
+ @response_content = redact_sensitive(client, client[:redact])
69
+ respond
70
+ else
71
+ not_found!
72
+ end
73
+ end
74
+ end
75
+
76
+ # GET /clients/:client_name/history
77
+ def get_client_history
78
+ client_name = parse_uri(CLIENT_HISTORY_URI).first
79
+ @response_content = []
80
+ @redis.smembers("result:#{client_name}") do |checks|
81
+ unless checks.empty?
82
+ checks.each_with_index do |check_name, index|
83
+ result_key = "#{client_name}:#{check_name}"
84
+ history_key = "history:#{result_key}"
85
+ @redis.lrange(history_key, -21, -1) do |history|
86
+ history.map! do |status|
87
+ status.to_i
88
+ end
89
+ @redis.get("result:#{result_key}") do |result_json|
90
+ unless result_json.nil?
91
+ result = Sensu::JSON.load(result_json)
92
+ last_execution = result[:executed]
93
+ unless history.empty? || last_execution.nil?
94
+ item = {
95
+ :check => check_name,
96
+ :history => history,
97
+ :last_execution => last_execution.to_i,
98
+ :last_status => history.last,
99
+ :last_result => result
100
+ }
101
+ @response_content << item
102
+ end
103
+ end
104
+ if index == checks.length - 1
105
+ respond
106
+ end
107
+ end
108
+ end
109
+ end
110
+ else
111
+ respond
112
+ end
113
+ end
114
+ end
115
+
116
+ # DELETE /clients/:client_name
117
+ def delete_client
118
+ client_name = parse_uri(CLIENT_URI).first
119
+ client_key = "client:#{client_name}"
120
+ signature_key = "#{client_key}:signature"
121
+ @redis.get(client_key) do |client_json|
122
+ unless client_json.nil?
123
+ @redis.set(signature_key, "invalidated") if @params[:invalidate]
124
+ @redis.hgetall("events:#{client_name}") do |events|
125
+ events.each do |check_name, event_json|
126
+ resolve_event(event_json)
127
+ end
128
+ delete_client = Proc.new do |attempts|
129
+ attempts += 1
130
+ @redis.hgetall("events:#{client_name}") do |events|
131
+ if events.empty? || attempts == 5
132
+ @logger.info("deleting client from registry", :client_name => client_name)
133
+ @redis.srem("clients", client_name) do
134
+ @redis.del(client_key)
135
+ invalidate_expire = integer_parameter(@params[:invalidate_expire])
136
+ if @params[:invalidate] && invalidate_expire
137
+ @redis.expire(signature_key, invalidate_expire)
138
+ else
139
+ @redis.del(signature_key)
140
+ end
141
+ @redis.del("events:#{client_name}")
142
+ @redis.smembers("result:#{client_name}") do |checks|
143
+ checks.each do |check_name|
144
+ result_key = "#{client_name}:#{check_name}"
145
+ @redis.del("result:#{result_key}")
146
+ @redis.del("history:#{result_key}")
147
+ @redis.del("history:#{result_key}:last_ok")
148
+ end
149
+ @redis.del("result:#{client_name}")
150
+ end
151
+ end
152
+ else
153
+ EM::Timer.new(1) do
154
+ delete_client.call(attempts)
155
+ end
156
+ end
157
+ end
158
+ end
159
+ delete_client.call(0)
160
+ @response_content = {:issued => Time.now.to_i}
161
+ accepted!
162
+ end
163
+ else
164
+ not_found!
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,86 @@
1
+ require "sensu/api/utilities/resolve_event"
2
+
3
+ module Sensu
4
+ module API
5
+ module Routes
6
+ module Events
7
+ include Utilities::ResolveEvent
8
+
9
+ EVENTS_URI = /^\/(?:events|incidents)$/
10
+ EVENTS_CLIENT_URI = /^\/(?:events|incidents)\/([\w\.-]+)$/
11
+ EVENT_URI = /^\/(?:events|incidents)\/([\w\.-]+)\/([\w\.-]+)$/
12
+
13
+ # GET /events
14
+ def get_events
15
+ @response_content = []
16
+ raw_event_json = []
17
+ @redis.smembers("clients") do |clients|
18
+ unless clients.empty?
19
+ clients.each_with_index do |client_name, index|
20
+ @redis.hgetall("events:#{client_name}") do |events|
21
+ events.each do |check_name, event_json|
22
+ raw_event_json << event_json
23
+ end
24
+ if index == clients.length - 1
25
+ raw_event_json = pagination(raw_event_json)
26
+ raw_event_json.each do |event_json|
27
+ @response_content << Sensu::JSON.load(event_json)
28
+ end
29
+ respond
30
+ end
31
+ end
32
+ end
33
+ else
34
+ respond
35
+ end
36
+ end
37
+ end
38
+
39
+ # GET /events/:client_name
40
+ def get_events_client
41
+ client_name = parse_uri(EVENTS_CLIENT_URI).first
42
+ @response_content = []
43
+ raw_event_json = []
44
+ @redis.hgetall("events:#{client_name}") do |events|
45
+ events.each do |check_name, event_json|
46
+ raw_event_json << event_json
47
+ end
48
+ raw_event_json = pagination(raw_event_json)
49
+ raw_event_json.each do |event_json|
50
+ @response_content << Sensu::JSON.load(event_json)
51
+ end
52
+ respond
53
+ end
54
+ end
55
+
56
+ # GET /events/:client_name/:check_name
57
+ def get_event
58
+ client_name, check_name = parse_uri(EVENT_URI)
59
+ @redis.hgetall("events:#{client_name}") do |events|
60
+ event_json = events[check_name]
61
+ unless event_json.nil?
62
+ @response_content = Sensu::JSON.load(event_json)
63
+ respond
64
+ else
65
+ not_found!
66
+ end
67
+ end
68
+ end
69
+
70
+ # DELETE /events/:client_name/:check_name
71
+ def delete_event
72
+ client_name, check_name = parse_uri(EVENT_URI)
73
+ @redis.hgetall("events:#{client_name}") do |events|
74
+ if events.include?(check_name)
75
+ resolve_event(events[check_name])
76
+ @response_content = {:issued => Time.now.to_i}
77
+ accepted!
78
+ else
79
+ not_found!
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,45 @@
1
+ require "sensu/api/utilities/transport_info"
2
+
3
+ module Sensu
4
+ module API
5
+ module Routes
6
+ module Health
7
+ include Utilities::TransportInfo
8
+
9
+ HEALTH_URI = /^\/health$/
10
+
11
+ # GET /health
12
+ def get_health
13
+ @response_content = []
14
+ if @redis.connected? && @transport.connected?
15
+ min_consumers = integer_parameter(@params[:consumers])
16
+ max_messages = integer_parameter(@params[:messages])
17
+ transport_info do |info|
18
+ if min_consumers
19
+ if info[:keepalives][:consumers] < min_consumers
20
+ @response_content << "keepalive consumers (#{info[:keepalives][:consumers]}) less than min_consumers (#{min_consumers})"
21
+ end
22
+ if info[:results][:consumers] < min_consumers
23
+ @response_content << "result consumers (#{info[:results][:consumers]}) less than min_consumers (#{min_consumers})"
24
+ end
25
+ end
26
+ if max_messages
27
+ if info[:keepalives][:messages] > max_messages
28
+ @response_content << "keepalive messages (#{info[:keepalives][:messages]}) greater than max_messages (#{max_messages})"
29
+ end
30
+ if info[:results][:messages] > max_messages
31
+ @response_content << "result messages (#{info[:results][:messages]}) greater than max_messages (#{max_messages})"
32
+ end
33
+ end
34
+ @response_content.empty? ? no_content! : precondition_failed!
35
+ end
36
+ else
37
+ @response_content << "not connected to redis" unless @redis.connected?
38
+ @response_content << "not connected to transport" unless @transport.connected?
39
+ precondition_failed!
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,37 @@
1
+ require "sensu/api/utilities/transport_info"
2
+ require "sensu/api/utilities/servers_info"
3
+
4
+ module Sensu
5
+ module API
6
+ module Routes
7
+ module Info
8
+ include Utilities::TransportInfo
9
+ include Utilities::ServersInfo
10
+
11
+ INFO_URI = /^\/info$/
12
+
13
+ # GET /info
14
+ def get_info
15
+ transport_info do |transport|
16
+ servers_info do |servers|
17
+ sensu = RELEASE_INFO.merge(
18
+ :settings => {
19
+ :hexdigest => @settings.hexdigest
20
+ }
21
+ )
22
+ @response_content = {
23
+ :sensu => sensu,
24
+ :transport => transport,
25
+ :redis => {
26
+ :connected => @redis.connected?
27
+ },
28
+ :servers => servers
29
+ }
30
+ respond
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,44 @@
1
+ require "sensu/api/utilities/publish_check_request"
2
+
3
+ module Sensu
4
+ module API
5
+ module Routes
6
+ module Request
7
+ include Utilities::PublishCheckRequest
8
+
9
+ REQUEST_URI = /^\/request$/
10
+
11
+ # POST /request
12
+ def post_request
13
+ rules = {
14
+ :check => {:type => String, :nil_ok => false},
15
+ :subscribers => {:type => Array, :nil_ok => true},
16
+ :reason => {:type => String, :nil_ok => true},
17
+ :creator => {:type => String, :nil_ok => true}
18
+ }
19
+ read_data(rules) do |data|
20
+ if @settings[:checks][data[:check]]
21
+ check = @settings[:checks][data[:check]].dup
22
+ check[:name] = data[:check]
23
+ check[:subscribers] ||= Array.new
24
+ check[:subscribers] = data[:subscribers] if data[:subscribers]
25
+ check[:api_requested] = {
26
+ :reason => data[:reason],
27
+ :creator => data[:creator]
28
+ }
29
+ if check[:proxy_requests]
30
+ publish_proxy_check_requests(check)
31
+ else
32
+ publish_check_request(check)
33
+ end
34
+ @response_content = {:issued => Time.now.to_i}
35
+ accepted!
36
+ else
37
+ not_found!
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,32 @@
1
+ require "sensu/api/utilities/resolve_event"
2
+
3
+ module Sensu
4
+ module API
5
+ module Routes
6
+ module Resolve
7
+ include Utilities::ResolveEvent
8
+
9
+ RESOLVE_URI = /^\/resolve$/
10
+
11
+ # POST /resolve
12
+ def post_resolve
13
+ rules = {
14
+ :client => {:type => String, :nil_ok => false},
15
+ :check => {:type => String, :nil_ok => false}
16
+ }
17
+ read_data(rules) do |data|
18
+ @redis.hgetall("events:#{data[:client]}") do |events|
19
+ if events.include?(data[:check])
20
+ resolve_event(events[data[:check]])
21
+ @response_content = {:issued => Time.now.to_i}
22
+ accepted!
23
+ else
24
+ not_found!
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,153 @@
1
+ require "sensu/api/validators/check"
2
+ require "sensu/api/utilities/publish_check_result"
3
+
4
+ module Sensu
5
+ module API
6
+ module Routes
7
+ module Results
8
+ include Utilities::PublishCheckResult
9
+
10
+ RESULTS_URI = /^\/results$/
11
+ RESULTS_CLIENT_URI = /^\/results\/([\w\.-]+)$/
12
+ RESULT_URI = /^\/results\/([\w\.-]+)\/([\w\.-]+)$/
13
+
14
+ # POST /results
15
+ def post_results
16
+ read_data do |check|
17
+ check[:status] ||= 0
18
+ check[:executed] ||= Time.now.to_i
19
+ validator = Validators::Check.new
20
+ if validator.valid?(check)
21
+ publish_check_result("sensu-api", check)
22
+ @response_content = {:issued => Time.now.to_i}
23
+ accepted!
24
+ else
25
+ bad_request!
26
+ end
27
+ end
28
+ end
29
+
30
+ # GET /results
31
+ def get_results
32
+ @response_content = []
33
+ @redis.smembers("clients") do |clients|
34
+ unless clients.empty?
35
+ result_keys = []
36
+ clients.each_with_index do |client_name, client_index|
37
+ @redis.smembers("result:#{client_name}") do |checks|
38
+ checks.each do |check_name|
39
+ result_keys << "result:#{client_name}:#{check_name}"
40
+ end
41
+ if client_index == clients.length - 1
42
+ result_keys = pagination(result_keys)
43
+ unless result_keys.empty?
44
+ result_keys.each_with_index do |result_key, result_key_index|
45
+ @redis.get(result_key) do |result_json|
46
+ history_key = result_key.sub(/^result:/, "history:")
47
+ @redis.lrange(history_key, -21, -1) do |history|
48
+ history.map! do |status|
49
+ status.to_i
50
+ end
51
+ unless result_json.nil?
52
+ client_name = history_key.split(":")[1]
53
+ check = Sensu::JSON.load(result_json)
54
+ check[:history] = history
55
+ @response_content << {:client => client_name, :check => check}
56
+ end
57
+ if result_key_index == result_keys.length - 1
58
+ respond
59
+ end
60
+ end
61
+ end
62
+ end
63
+ else
64
+ respond
65
+ end
66
+ end
67
+ end
68
+ end
69
+ else
70
+ respond
71
+ end
72
+ end
73
+ end
74
+
75
+ # GET /results/:client_name
76
+ def get_results_client
77
+ client_name = parse_uri(RESULTS_CLIENT_URI).first
78
+ @response_content = []
79
+ @redis.smembers("result:#{client_name}") do |checks|
80
+ checks = pagination(checks)
81
+ unless checks.empty?
82
+ checks.each_with_index do |check_name, check_index|
83
+ result_key = "result:#{client_name}:#{check_name}"
84
+ @redis.get(result_key) do |result_json|
85
+ history_key = "history:#{client_name}:#{check_name}"
86
+ @redis.lrange(history_key, -21, -1) do |history|
87
+ history.map! do |status|
88
+ status.to_i
89
+ end
90
+ unless result_json.nil?
91
+ check = Sensu::JSON.load(result_json)
92
+ check[:history] = history
93
+ @response_content << {:client => client_name, :check => check}
94
+ end
95
+ if check_index == checks.length - 1
96
+ respond
97
+ end
98
+ end
99
+ end
100
+ end
101
+ else
102
+ respond
103
+ end
104
+ end
105
+ end
106
+
107
+ # GET /results/:client_name/:check_name
108
+ def get_result
109
+ client_name, check_name = parse_uri(RESULT_URI)
110
+ result_key = "result:#{client_name}:#{check_name}"
111
+ @redis.get(result_key) do |result_json|
112
+ unless result_json.nil?
113
+ history_key = "history:#{client_name}:#{check_name}"
114
+ @redis.lrange(history_key, -21, -1) do |history|
115
+ history.map! do |status|
116
+ status.to_i
117
+ end
118
+ check = Sensu::JSON.load(result_json)
119
+ check[:history] = history
120
+ @response_content = {:client => client_name, :check => check}
121
+ respond
122
+ end
123
+ else
124
+ not_found!
125
+ end
126
+ end
127
+ end
128
+
129
+ # DELETE /results/:client_name/:check_name
130
+ def delete_result
131
+ client_name, check_name = parse_uri(RESULT_URI)
132
+ result_key = "result:#{client_name}:#{check_name}"
133
+ @redis.exists(result_key) do |result_exists|
134
+ if result_exists
135
+ @redis.srem("result:#{client_name}", check_name) do
136
+ @redis.del(result_key) do
137
+ history_key = "history:#{client_name}:#{check_name}"
138
+ @redis.del(history_key) do
139
+ @redis.del("#{history_key}:last_ok") do
140
+ no_content!
141
+ end
142
+ end
143
+ end
144
+ end
145
+ else
146
+ not_found!
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,23 @@
1
+ require "sensu/utilities"
2
+
3
+ module Sensu
4
+ module API
5
+ module Routes
6
+ module Settings
7
+ include Utilities
8
+
9
+ SETTINGS_URI = /^\/settings$/
10
+
11
+ # GET /settings
12
+ def get_settings
13
+ if @params[:redacted] == "false"
14
+ @response_content = @settings.to_hash
15
+ else
16
+ @response_content = redact_sensitive(@settings.to_hash)
17
+ end
18
+ respond
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end