sensu 0.20.6 → 0.21.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8db94deef76774c21c9200b21055c0cedc6c1907
4
- data.tar.gz: 067c5f4dedbb6315d62c77a1dbe769bd18b6442d
3
+ metadata.gz: e7241998f1b395c09ed021c94e1391de71b1a1b3
4
+ data.tar.gz: 8ed7240bf31290a27826d17584a6e13f3ebe1e56
5
5
  SHA512:
6
- metadata.gz: 0a620e6977eabe3657cfa23409f5732fe9d7a79985752290eafd939b5f0966b3885ded2d47c14c9a9ade611a464cd9ff483fa8f79e14d5ccdd64ddb124c7b01a
7
- data.tar.gz: 4d40cdcb998419822642090121c34aded2a47e7c094c4b084516ff0ad7893701ff0598cdaa6a0a5c4922bf686b099086bb9db7f3e739d52a11d7d090fd86a085
6
+ metadata.gz: 46e0e42fb84c441414534f9f40fd2074cc90ee66964ebef97c72184b2af6c034244686f89d914ef21b70c527638dac7163f2e2049d760f28ef807152d8400dea
7
+ data.tar.gz: f9effb8a3907bf25952761c07a058e2df972c43454fe1256086e5c41e11266e4736e9c0a454d70934b00acb55499192632245096764314c968b6e4412f39ad97
@@ -1,7 +1,56 @@
1
+ ## 0.21.0 - 2015-11-13
2
+
3
+ ### Features
4
+
5
+ Added a Sensu plugin installation tool, `sensu-install`, making it easier
6
+ to install Sensu community plugins. The `sensu-install` tool will use the
7
+ appropriate Ruby when installing plugins. The tool aims to produce verbose
8
+ and useful output to help when debugging plugin installation issues.
9
+
10
+ Added the Sensu API DELETE /results/:client/:check endpoint, supporting
11
+ check result deletion via the Sensu API. This feature allows users to
12
+ clean up "stale" check result data for checks that have been removed.
13
+
14
+ Added the Sensu API POST /results endpoint, supporting check result input
15
+ via the Sensu API. The JIT client feature added in 0.20 enabled this
16
+ functionality. Services that do not have access to a local Sensu client
17
+ socket can make use of this feature.
18
+
19
+ ### Other
20
+
21
+ Improved the Sensu test suite to reduce the number of timeout triggered
22
+ failures. These changes make Sensu development much more pleasant.
23
+
24
+ Fixed a few inline documentation typos, e.g. sbuded -> subdued.
25
+
26
+ Moved the Sensu bins (e.g. `sensu-client`) from `bin` to `exe` to avoid
27
+ the conflict with Ruby bundler bin stubs.
28
+
29
+ Fixed Sensu API and client socket input validation, no longer accepting
30
+ multi-line values.
31
+
32
+ Fixed check request publishing for checks that make use of check
33
+ extensions, e.g. `"extension": "check_http_endpoints`.
34
+
35
+ Fixed the handler `"filters"` bug that caused Sensu to mutate handler
36
+ definitions, removing filters for successive executions.
37
+
38
+ Fixed Sensu API POST /request endpoint check request publishing to
39
+ round-robin client subscriptions.
40
+
41
+ Fixed the Windows job handle leak when spawning processes for checks.
42
+
43
+ Updated the Redis client library (em-redis-unified) to remove duplicate
44
+ Ruby hash key warnings.
45
+
1
46
  ## 0.20.6 - 2015-09-22
2
47
 
3
48
  ### Other
4
49
 
50
+ Removed the use of `EM::Iterator` from event filtering, replacing it with
51
+ `Proc` and `EM::next_tick`. `EM::Iterator` creates anonymous classes that
52
+ cannot be garbage collected on JRuby.
53
+
5
54
  Removed sensu-em as a dependency, now using upstream EventMachine 1.0.8.
6
55
 
7
56
  The Sensu API will remove a client immediately if there are no current
File without changes
File without changes
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "optparse"
4
+
5
+ module Sensu
6
+ class Install
7
+ class << self
8
+ def cli_options(arguments=ARGV)
9
+ options = {
10
+ :verbose => false,
11
+ :plugins => []
12
+ }
13
+ optparse = OptionParser.new do |opts|
14
+ opts.on("-h", "--help", "Display this message") do
15
+ puts opts
16
+ exit
17
+ end
18
+ opts.on("-v", "--verbose", "Enable verbose logging") do
19
+ options[:verbose] = true
20
+ end
21
+ opts.on("-p", "--plugin PLUGIN", "Install a Sensu PLUGIN") do |plugin|
22
+ options[:plugins] << plugin
23
+ end
24
+ opts.on("-P", "--plugins PLUGIN[,PLUGIN]", "PLUGIN or comma-delimited list of Sensu plugins to install") do |plugins|
25
+ options[:plugins].concat(plugins.split(","))
26
+ end
27
+ opts.on("-s", "--source SOURCE", "Install Sensu plugins from a custom SOURCE") do |source|
28
+ options[:source] = source
29
+ end
30
+ end
31
+ optparse.parse!(arguments)
32
+ options
33
+ end
34
+
35
+ def log(message)
36
+ puts "[SENSU-INSTALL] #{message}"
37
+ end
38
+
39
+ def install_plugins(plugins, options={})
40
+ log "installing Sensu plugins ..."
41
+ log "provided Sensu plugins: #{plugins}" if options[:verbose]
42
+ gems = plugins.map do |plugin|
43
+ if plugin.start_with?("sensu-plugins-")
44
+ plugin
45
+ else
46
+ "sensu-plugins-#{plugin}"
47
+ end
48
+ end
49
+ log "Sensu plugin gems to be installed: #{gems}" if options[:verbose]
50
+ gem_options = "--no-ri --no-rdoc"
51
+ gem_options << " --verbose" if options[:verbose]
52
+ gem_options << " --source #{options[:source]}" if options[:source]
53
+ gems.each do |gem|
54
+ log "installing Sensu plugin gem: #{gem}"
55
+ gem_command = "gem install #{gem} #{gem_options}"
56
+ log gem_command if options[:verbose]
57
+ unless system(gem_command)
58
+ log "failed to install Sensu plugin gem: #{gem}"
59
+ log "you can run the sensu-install command again with --verbose for more info" unless options[:verbose]
60
+ log "please take note of any failure messages above"
61
+ log "make sure you have build tools installed (e.g. gcc)"
62
+ log "trying to determine Sensu plugin homepage for #{gem} ..."
63
+ clean_gem = gem.split(":").first
64
+ system("gem specification #{clean_gem} -r | grep homepage")
65
+ exit 2
66
+ end
67
+ end
68
+ log "successfully install Sensu plugins: #{plugins}"
69
+ end
70
+
71
+ def run
72
+ options = cli_options
73
+ unless options[:plugins].empty?
74
+ install_plugins(options[:plugins], options)
75
+ else
76
+ log "nothing to do"
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ Sensu::Install.run
File without changes
@@ -177,7 +177,8 @@ module Sensu
177
177
  valid = rules.all? do |key, rule|
178
178
  value = data[key]
179
179
  (value.is_a?(rule[:type]) || (rule[:nil_ok] && value.nil?)) &&
180
- rule[:regex].nil? || (rule[:regex] && (value =~ rule[:regex]) == 0)
180
+ (value.nil? || rule[:regex].nil?) ||
181
+ (rule[:regex] && (value =~ rule[:regex]) == 0)
181
182
  end
182
183
  if valid
183
184
  callback.call(data)
@@ -190,7 +191,7 @@ module Sensu
190
191
  end
191
192
 
192
193
  def integer_parameter(parameter)
193
- parameter =~ /^[0-9]+$/ ? parameter.to_i : nil
194
+ parameter =~ /\A[0-9]+\z/ ? parameter.to_i : nil
194
195
  end
195
196
 
196
197
  def pagination(items)
@@ -234,18 +235,12 @@ module Sensu
234
235
  end
235
236
  end
236
237
 
237
- def resolve_event(event_json)
238
- event = MultiJson.load(event_json)
239
- check = event[:check].merge(
240
- :output => "Resolving on request of the API",
241
- :status => 0,
242
- :issued => Time.now.to_i,
243
- :executed => Time.now.to_i,
244
- :force_resolve => true
245
- )
246
- check.delete(:history)
238
+ def publish_check_result(client_name, check)
239
+ check[:issued] = Time.now.to_i
240
+ check[:executed] = Time.now.to_i
241
+ check[:status] ||= 0
247
242
  payload = {
248
- :client => event[:client][:name],
243
+ :client => client_name,
249
244
  :check => check
250
245
  }
251
246
  settings.logger.info("publishing check result", :payload => payload)
@@ -258,6 +253,47 @@ module Sensu
258
253
  end
259
254
  end
260
255
  end
256
+
257
+ def resolve_event(event_json)
258
+ event = MultiJson.load(event_json)
259
+ check = event[:check].merge(
260
+ :output => "Resolving on request of the API",
261
+ :status => 0,
262
+ :force_resolve => true
263
+ )
264
+ check.delete(:history)
265
+ publish_check_result(event[:client][:name], check)
266
+ end
267
+
268
+ def transport_publish_options(subscription, message)
269
+ _, raw_type = subscription.split(":", 2).reverse
270
+ case raw_type
271
+ when "direct", "roundrobin"
272
+ [:direct, subscription, message]
273
+ else
274
+ [:fanout, subscription, message]
275
+ end
276
+ end
277
+
278
+ def publish_check_request(check)
279
+ payload = check.merge(:issued => Time.now.to_i)
280
+ settings.logger.info("publishing check request", {
281
+ :payload => payload,
282
+ :subscribers => check[:subscribers]
283
+ })
284
+ check[:subscribers].each do |subscription|
285
+ options = transport_publish_options(subscription.to_s, MultiJson.dump(payload))
286
+ settings.transport.publish(*options) do |info|
287
+ if info[:error]
288
+ settings.logger.error("failed to publish check request", {
289
+ :subscription => subscription,
290
+ :payload => payload,
291
+ :error => info[:error].to_s
292
+ })
293
+ end
294
+ end
295
+ end
296
+ end
261
297
  end
262
298
 
263
299
  before do
@@ -311,7 +347,7 @@ module Sensu
311
347
 
312
348
  apost "/clients/?" do
313
349
  rules = {
314
- :name => {:type => String, :nil_ok => false, :regex => /^[\w\.-]+$/},
350
+ :name => {:type => String, :nil_ok => false, :regex => /\A[\w\.-]+\z/},
315
351
  :address => {:type => String, :nil_ok => false},
316
352
  :subscriptions => {:type => Array, :nil_ok => false}
317
353
  }
@@ -459,28 +495,11 @@ module Sensu
459
495
  }
460
496
  read_data(rules) do |data|
461
497
  if settings.checks[data[:check]]
462
- check = settings.checks[data[:check]]
463
- subscribers = data[:subscribers] || check[:subscribers] || Array.new
464
- payload = {
465
- :name => data[:check],
466
- :command => check[:command],
467
- :issued => Time.now.to_i
468
- }
469
- settings.logger.info("publishing check request", {
470
- :payload => payload,
471
- :subscribers => subscribers
472
- })
473
- subscribers.uniq.each do |exchange_name|
474
- settings.transport.publish(:fanout, exchange_name.to_s, MultiJson.dump(payload)) do |info|
475
- if info[:error]
476
- settings.logger.error("failed to publish check request", {
477
- :exchange_name => exchange_name,
478
- :payload => payload,
479
- :error => info[:error].to_s
480
- })
481
- end
482
- end
483
- end
498
+ check = settings.checks[data[:check]].dup
499
+ check[:name] = data[:check]
500
+ check[:subscribers] ||= Array.new
501
+ check[:subscribers] = data[:subscribers] if data[:subscribers]
502
+ publish_check_request(check)
484
503
  issued!
485
504
  else
486
505
  not_found!
@@ -743,6 +762,19 @@ module Sensu
743
762
  end
744
763
  end
745
764
 
765
+ apost "/results/?" do
766
+ rules = {
767
+ :name => {:type => String, :nil_ok => false, :regex => /\A[\w\.-]+\z/},
768
+ :output => {:type => String, :nil_ok => false},
769
+ :status => {:type => Integer, :nil_ok => true},
770
+ :source => {:type => String, :nil_ok => true, :regex => /\A[\w\.-]+\z/}
771
+ }
772
+ read_data(rules) do |data|
773
+ publish_check_result("sensu-api", data)
774
+ issued!
775
+ end
776
+ end
777
+
746
778
  aget "/results/?" do
747
779
  response = Array.new
748
780
  settings.redis.smembers("clients") do |clients|
@@ -807,6 +839,21 @@ module Sensu
807
839
  end
808
840
  end
809
841
  end
842
+
843
+ adelete %r{^/results?/([\w\.-]+)/([\w\.-]+)/?$} do |client_name, check_name|
844
+ result_key = "result:#{client_name}:#{check_name}"
845
+ settings.redis.exists(result_key) do |result_exists|
846
+ if result_exists
847
+ settings.redis.srem("result:#{client_name}", check_name) do
848
+ settings.redis.del(result_key) do |result_json|
849
+ no_content!
850
+ end
851
+ end
852
+ else
853
+ not_found!
854
+ end
855
+ end
856
+ end
810
857
  end
811
858
  end
812
859
  end
@@ -116,10 +116,10 @@ module Sensu
116
116
  #
117
117
  # @param [Hash] check result to validate.
118
118
  def validate_check_result(check)
119
- unless check[:name] =~ /^[\w\.-]+$/
119
+ unless check[:name] =~ /\A[\w\.-]+\z/
120
120
  raise DataError, "check name must be a string and cannot contain spaces or special characters"
121
121
  end
122
- unless check[:source].nil? || check[:source] =~ /^[\w\.-]+$/
122
+ unless check[:source].nil? || check[:source] =~ /\A[\w\.-]+\z/
123
123
  raise DataError, "check source must be a string and cannot contain spaces or special characters"
124
124
  end
125
125
  unless check[:output].is_a?(String)
@@ -1,7 +1,7 @@
1
1
  module Sensu
2
2
  unless defined?(Sensu::VERSION)
3
3
  # Sensu release version.
4
- VERSION = "0.20.6"
4
+ VERSION = "0.21.0"
5
5
 
6
6
  # Sensu check severities.
7
7
  SEVERITIES = %w[ok warning critical unknown]
@@ -5,10 +5,10 @@ gem "eventmachine", "1.0.8"
5
5
 
6
6
  gem "sensu-logger", "1.1.0"
7
7
  gem "sensu-settings", "3.1.0"
8
- gem "sensu-extension", "1.2.0"
9
- gem "sensu-extensions", "1.3.0"
8
+ gem "sensu-extension", "1.3.0"
9
+ gem "sensu-extensions", "1.4.0"
10
10
  gem "sensu-transport", "3.3.0"
11
- gem "sensu-spawn", "1.5.0"
11
+ gem "sensu-spawn", "1.6.0"
12
12
 
13
13
  require "time"
14
14
  require "uri"
@@ -1,4 +1,4 @@
1
- gem "em-redis-unified", "1.0.0"
1
+ gem "em-redis-unified", "1.0.1"
2
2
 
3
3
  require "em-redis-unified"
4
4
 
@@ -179,7 +179,7 @@ module Sensu
179
179
  # @return [TrueClass, FalseClass]
180
180
  def eval_attribute_value(raw_eval_string, value)
181
181
  begin
182
- eval_string = raw_eval_string.gsub(/^eval:(\s+)?/, "")
182
+ eval_string = raw_eval_string.gsub(/\Aeval:(\s+)?/, "")
183
183
  !!Sandbox.eval(eval_string, value)
184
184
  rescue => error
185
185
  @logger.error("filter attribute eval error", {
@@ -258,7 +258,7 @@ module Sensu
258
258
  # @param callback [Proc]
259
259
  def event_filtered?(handler, event, &callback)
260
260
  if handler.has_key?(:filters) || handler.has_key?(:filter)
261
- filter_list = Array(handler[:filters] || handler[:filter])
261
+ filter_list = Array(handler[:filters] || handler[:filter]).dup
262
262
  filter = Proc.new do |filter_list|
263
263
  filter_name = filter_list.shift
264
264
  if filter_name.nil?
@@ -278,7 +278,7 @@ module Sensu
278
278
  # Attempt to filter an event for a handler. This method will
279
279
  # check to see if handling is disabled, if the event action is
280
280
  # handled, if the event check severity is handled, if the
281
- # handler is sbuded, and if the event is filtered by any of the
281
+ # handler is subdued, and if the event is filtered by any of the
282
282
  # filters specified in the handler definition.
283
283
  #
284
284
  # @param handler [Hash] definition.
@@ -483,12 +483,12 @@ module Sensu
483
483
  end
484
484
 
485
485
  # Publish a check request to the transport. A check request is
486
- # composted of a check `:name`, an `:issued` timestamp, and a
487
- # check `:command` if available. The check request is published
488
- # to a transport pipe, for each of the check `:subscribers` in
489
- # its definition, eg. "webserver". JSON serialization is used
490
- # when publishing the check request payload to the transport
491
- # pipes. Transport errors are logged.
486
+ # composed of a check `:name`, an `:issued` timestamp, a check
487
+ # `:command` if available, and a check `:extension if available.
488
+ # The check request is published to a transport pipe, for each
489
+ # of the check `:subscribers` in its definition, eg. "webserver".
490
+ # JSON serialization is used when publishing the check request
491
+ # payload to the transport pipes. Transport errors are logged.
492
492
  #
493
493
  # @param check [Hash] definition.
494
494
  def publish_check_request(check)
@@ -498,6 +498,7 @@ module Sensu
498
498
  }
499
499
  payload[:command] = check[:command] if check.has_key?(:command)
500
500
  payload[:source] = check[:source] if check.has_key?(:source)
501
+ payload[:extension] = check[:extension] if check.has_key?(:extension)
501
502
  @logger.info("publishing check request", {
502
503
  :payload => payload,
503
504
  :subscribers => check[:subscribers]
@@ -19,11 +19,11 @@ Gem::Specification.new do |s|
19
19
  s.add_dependency "eventmachine", "1.0.8"
20
20
  s.add_dependency "sensu-logger", "1.1.0"
21
21
  s.add_dependency "sensu-settings", "3.1.0"
22
- s.add_dependency "sensu-extension", "1.2.0"
23
- s.add_dependency "sensu-extensions", "1.3.0"
22
+ s.add_dependency "sensu-extension", "1.3.0"
23
+ s.add_dependency "sensu-extensions", "1.4.0"
24
24
  s.add_dependency "sensu-transport", "3.3.0"
25
- s.add_dependency "sensu-spawn", "1.5.0"
26
- s.add_dependency "em-redis-unified", "1.0.0"
25
+ s.add_dependency "sensu-spawn", "1.6.0"
26
+ s.add_dependency "em-redis-unified", "1.0.1"
27
27
  s.add_dependency "sinatra", "1.4.6"
28
28
  s.add_dependency "async_sinatra", "1.2.0"
29
29
  s.add_dependency "thin", "1.6.3" unless RUBY_PLATFORM =~ /java/
@@ -32,7 +32,8 @@ Gem::Specification.new do |s|
32
32
  s.add_development_dependency "rspec", "~> 3.0.0"
33
33
  s.add_development_dependency "em-http-request", "~> 1.1"
34
34
 
35
- s.files = Dir.glob("{bin,lib}/**/*") + %w[sensu.gemspec README.md CHANGELOG.md MIT-LICENSE.txt]
36
- s.executables = Dir.glob("bin/**/*").map { |file| File.basename(file) }
35
+ s.files = Dir.glob("{exe,lib}/**/*") + %w[sensu.gemspec README.md CHANGELOG.md MIT-LICENSE.txt]
36
+ s.executables = s.files.grep(%r{^exe/}) { |file| File.basename(file) }
37
+ s.bindir = "exe"
37
38
  s.require_paths = ["lib"]
38
39
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sensu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.20.6
4
+ version: 0.21.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Porter
8
8
  - Justin Kolberg
9
9
  autorequire:
10
- bindir: bin
10
+ bindir: exe
11
11
  cert_chain: []
12
- date: 2015-09-22 00:00:00.000000000 Z
12
+ date: 2015-11-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: multi_json
@@ -87,28 +87,28 @@ dependencies:
87
87
  requirements:
88
88
  - - '='
89
89
  - !ruby/object:Gem::Version
90
- version: 1.2.0
90
+ version: 1.3.0
91
91
  type: :runtime
92
92
  prerelease: false
93
93
  version_requirements: !ruby/object:Gem::Requirement
94
94
  requirements:
95
95
  - - '='
96
96
  - !ruby/object:Gem::Version
97
- version: 1.2.0
97
+ version: 1.3.0
98
98
  - !ruby/object:Gem::Dependency
99
99
  name: sensu-extensions
100
100
  requirement: !ruby/object:Gem::Requirement
101
101
  requirements:
102
102
  - - '='
103
103
  - !ruby/object:Gem::Version
104
- version: 1.3.0
104
+ version: 1.4.0
105
105
  type: :runtime
106
106
  prerelease: false
107
107
  version_requirements: !ruby/object:Gem::Requirement
108
108
  requirements:
109
109
  - - '='
110
110
  - !ruby/object:Gem::Version
111
- version: 1.3.0
111
+ version: 1.4.0
112
112
  - !ruby/object:Gem::Dependency
113
113
  name: sensu-transport
114
114
  requirement: !ruby/object:Gem::Requirement
@@ -129,28 +129,28 @@ dependencies:
129
129
  requirements:
130
130
  - - '='
131
131
  - !ruby/object:Gem::Version
132
- version: 1.5.0
132
+ version: 1.6.0
133
133
  type: :runtime
134
134
  prerelease: false
135
135
  version_requirements: !ruby/object:Gem::Requirement
136
136
  requirements:
137
137
  - - '='
138
138
  - !ruby/object:Gem::Version
139
- version: 1.5.0
139
+ version: 1.6.0
140
140
  - !ruby/object:Gem::Dependency
141
141
  name: em-redis-unified
142
142
  requirement: !ruby/object:Gem::Requirement
143
143
  requirements:
144
144
  - - '='
145
145
  - !ruby/object:Gem::Version
146
- version: 1.0.0
146
+ version: 1.0.1
147
147
  type: :runtime
148
148
  prerelease: false
149
149
  version_requirements: !ruby/object:Gem::Requirement
150
150
  requirements:
151
151
  - - '='
152
152
  - !ruby/object:Gem::Version
153
- version: 1.0.0
153
+ version: 1.0.1
154
154
  - !ruby/object:Gem::Dependency
155
155
  name: sinatra
156
156
  requirement: !ruby/object:Gem::Requirement
@@ -240,18 +240,20 @@ email:
240
240
  - portertech@gmail.com
241
241
  - amdprophet@gmail.com
242
242
  executables:
243
- - sensu-server
244
- - sensu-client
245
243
  - sensu-api
244
+ - sensu-client
245
+ - sensu-install
246
+ - sensu-server
246
247
  extensions: []
247
248
  extra_rdoc_files: []
248
249
  files:
249
250
  - CHANGELOG.md
250
251
  - MIT-LICENSE.txt
251
252
  - README.md
252
- - bin/sensu-api
253
- - bin/sensu-client
254
- - bin/sensu-server
253
+ - exe/sensu-api
254
+ - exe/sensu-client
255
+ - exe/sensu-install
256
+ - exe/sensu-server
255
257
  - lib/sensu.rb
256
258
  - lib/sensu/api/process.rb
257
259
  - lib/sensu/cli.rb
@@ -288,9 +290,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
288
290
  version: '0'
289
291
  requirements: []
290
292
  rubyforge_project:
291
- rubygems_version: 2.2.2
293
+ rubygems_version: 2.4.5.1
292
294
  signing_key:
293
295
  specification_version: 4
294
296
  summary: A monitoring framework
295
297
  test_files: []
296
- has_rdoc: false