sensu 0.28.6 → 0.29.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: a1ea1cfa413a927a75a9acdbfb0a6ab81c7d8b9f
4
- data.tar.gz: fd3e79ae3331d1128f69d4830e1cd42e17535ddd
3
+ metadata.gz: 31731ea9a2311f9aecc12057e03442fb2dffca7e
4
+ data.tar.gz: ee7b95c65a89a73693717c5220bf7a515ee54634
5
5
  SHA512:
6
- metadata.gz: 230f849a14b5f777a9a022b8282dc438098f468e36bd0b0b016393927945244b6e30374a9e2362223bf6bded7692ac826380f836a04f3f77bf6997ec8ee6e9ef
7
- data.tar.gz: fed7831e688c6d1743f99bbba2cfa30daa719b8dfd2c3f5ba82890d9b61a995a0a4f6db09fdf81f0fc249eb28a1bf3cc989557cb98584447a4349987cf2a5c31
6
+ metadata.gz: b1a0e54b2e28998c7653b78f54278ec6f28c2a716fedfc8ab24b59108d33ff9998d60b77776c05e48e556b1decf43c15a2c95ee06842528ae3671cbd7957349a
7
+ data.tar.gz: d7ed4d7d2cb4794ab2933237d383eb37331dda2adaed120117c25ce36cacb7d4a4cd6e8249439d5f08c1ed52e2e63b5e48e2594603078bcf9f120ca6a52d936b
@@ -1,3 +1,74 @@
1
+ ## 0.29.0 - 2017-03-29
2
+
3
+ ### Features
4
+
5
+ Sensu server tasks, replacing the Sensu server leader functionality,
6
+ distributing certain server responsibilities amongst the running Sensu
7
+ servers. A server task can only run on one Sensu server at a time. Sensu
8
+ servers partake in an election process to become responsible for one or
9
+ more tasks. A task can failover to another Sensu server.
10
+
11
+ Sensu API response object filtering for any GET request. Filtering is done
12
+ with one or more dot notation query parameters, beginning with `filter.`,
13
+ to specify object attributes to filter by, e.g.
14
+ `/events?filter.client.environment=production&filter.check.contact=ops`.
15
+
16
+ Added API endpoint GET `/settings` to provided the APIs running
17
+ configuration. Sensitive setting values are redacted by default, unless
18
+ the query parameter `redacted` is set to `false`, e.g.
19
+ `/settings?redacted=false`.
20
+
21
+ Added support for invalidating a Sensu client when deleting it via the
22
+ Sensu API DELETE `/clients/:name` endpoint, disallowing further client
23
+ keepalives and check results until the client is either successfully
24
+ removed from the client registry or for a specified duration of time. To
25
+ invalidate a Sensu client until it is deleted, the query parameter
26
+ `invalidate` must be set to `true`, e.g.
27
+ `/clients/app01.example.com?invalidate=true`. To invalidate the client for
28
+ a certain amount of time (in seconds), the query parameter
29
+ `invalidate_expire` must be set as well, e.g.
30
+ `/clients/app01.example.com?invalidate=true&invalidate_expire=300`.
31
+
32
+ Added a Sensu settings hexdigest, exposed via the Sensu API GET `/info`
33
+ endpoint, providing a means to determine if a Sensu server's configuration
34
+ differs from the rest.
35
+
36
+ Added a proxy argument to `sensu-install`. To use a proxy for Sensu plugin
37
+ and extension installation with `sensu-install`, use the `-x` or
38
+ `--proxy` argument, e.g. `sensu-install -e statsd --proxy
39
+ http://proxy.example.com:8080`.
40
+
41
+ Added support for issuing proxy check requests via the Sensu API POST
42
+ `/request` endpoint.
43
+
44
+ The Sensu API now logs response times.
45
+
46
+ The Sensu API now returns a 405 (Method Not Allowed) when an API endpoint
47
+ does not support a HTTP request method, e.g. `PUT`, and sets the HTTP
48
+ header "Allow" to indicate which HTTP request methods are supported by the
49
+ requested endpoint.
50
+
51
+ Added a built-in filter for check dependencies, `check_dependencies`,
52
+ which implements the check dependency filtering logic in the Sensu Plugin
53
+ library.
54
+
55
+ Added default values for Sensu CLI options `config_file`
56
+ (`"/etc/sensu/config.json"`) and `config_dirs` (`["/etc/sensu/conf.d"]`).
57
+ These defaults are only applied when the associated file and/or directory
58
+ exist.
59
+
60
+ ### Other
61
+
62
+ Added a Rubocop configuration file and rake tasks for a slow introduction.
63
+
64
+ ### Fixes
65
+
66
+ The built-in filter `occurrences` now supports `refresh` for flapping
67
+ events (action `flapping`).
68
+
69
+ Force the configured Redis port to be an integer, as some users make the
70
+ mistake of using a string.
71
+
1
72
  ## 0.28.5 - 2017-03-23
2
73
 
3
74
  ### Fixes
@@ -10,7 +10,8 @@ module Sensu
10
10
  :verbose => false,
11
11
  :plugins => [],
12
12
  :extensions => [],
13
- :clean => false
13
+ :clean => false,
14
+ :proxy => nil
14
15
  }
15
16
  optparse = OptionParser.new do |opts|
16
17
  opts.on("-h", "--help", "Display this message") do
@@ -38,6 +39,9 @@ module Sensu
38
39
  opts.on("-c", "--clean", "Clean up (remove) other installed versions of the plugin(s) and/or extension(s)") do
39
40
  options[:clean] = true
40
41
  end
42
+ opts.on("-x", "--proxy PROXY", "Install Sensu plugins and extensions via a PROXY URL") do |proxy|
43
+ options[:proxy] = proxy
44
+ end
41
45
  end
42
46
  optparse.parse!(arguments)
43
47
  options
@@ -70,6 +74,7 @@ module Sensu
70
74
  gem_command << " --no-ri --no-rdoc"
71
75
  gem_command << " --verbose" if options[:verbose]
72
76
  gem_command << " --source #{options[:source]}" if options[:source]
77
+ gem_command << " --http-proxy #{options[:proxy]}" if options[:proxy]
73
78
  log gem_command if options[:verbose]
74
79
  unless system(gem_command)
75
80
  log "failed to install Sensu gem '#{gem_name}'"
@@ -1,4 +1,5 @@
1
1
  require "sensu/api/routes"
2
+ require "sensu/api/utilities/filter_response_content"
2
3
 
3
4
  gem "em-http-server", "0.1.8"
4
5
 
@@ -9,6 +10,7 @@ module Sensu
9
10
  module API
10
11
  class HTTPHandler < EM::HttpServer::Server
11
12
  include Routes
13
+ include Utilities::FilterResponseContent
12
14
 
13
15
  attr_accessor :logger, :settings, :redis, :transport
14
16
 
@@ -19,6 +21,7 @@ module Sensu
19
21
  # @result [Hash]
20
22
  def request_details
21
23
  return @request_details if @request_details
24
+ @request_start_time = Time.now.to_f
22
25
  _, remote_address = Socket.unpack_sockaddr_in(get_peername)
23
26
  @request_details = {
24
27
  :remote_address => remote_address,
@@ -40,12 +43,14 @@ module Sensu
40
43
  @logger.debug("api request", request_details)
41
44
  end
42
45
 
43
- # Log the HTTP response.
46
+ # Log the HTTP response. This method calculates the
47
+ # request/response time.
44
48
  def log_response
45
49
  @logger.info("api response", {
46
50
  :request => request_details,
47
51
  :status => @response.status,
48
- :content_length => @response.content.to_s.bytesize
52
+ :content_length => @response.content.to_s.bytesize,
53
+ :time => (Time.now.to_f - @request_start_time).round(3)
49
54
  })
50
55
  end
51
56
 
@@ -61,13 +66,20 @@ module Sensu
61
66
 
62
67
  # Parse the HTTP request query string for parameters. This
63
68
  # method creates `@params`, a hash of parsed query parameters,
64
- # used by the API routes.
69
+ # used by the API routes. This method also creates
70
+ # `@filter_params`, a hash of parsed response content filter
71
+ # parameters.
65
72
  def parse_parameters
66
73
  @params = {}
67
74
  if @http_query_string
68
75
  @http_query_string.split("&").each do |pair|
69
76
  key, value = pair.split("=")
70
77
  @params[key.to_sym] = value
78
+ if key.start_with?("filter.")
79
+ filter_param = key.sub(/^filter\./, "")
80
+ @filter_params ||= {}
81
+ @filter_params[filter_param] = value
82
+ end
71
83
  end
72
84
  end
73
85
  end
@@ -166,13 +178,17 @@ module Sensu
166
178
  # Respond to an HTTP request. The routes set `@response_status`,
167
179
  # `@response_status_string`, and `@response_content`
168
180
  # appropriately. The HTTP response status defaults to `200` with
169
- # the status string `OK`. The Sensu API only returns JSON
170
- # response content, `@response_content` is assumed to be a Ruby
171
- # object that can be serialized as JSON.
181
+ # the status string `OK`. If filter params were provided,
182
+ # `@response_content` is filtered (mutated). The Sensu API only
183
+ # returns JSON response content, `@response_content` is assumed
184
+ # to be a Ruby object that can be serialized as JSON.
172
185
  def respond
173
186
  @response.status = @response_status || 200
174
187
  @response.status_string = @response_status_string || "OK"
175
188
  if @response_content && @http_request_method != HEAD_METHOD
189
+ if @http_request_method == GET_METHOD && @filter_params
190
+ filter_response_content!
191
+ end
176
192
  @response.content_type "application/json"
177
193
  @response.content = Sensu::JSON.dump(@response_content)
178
194
  end
@@ -281,6 +297,14 @@ module Sensu
281
297
  respond
282
298
  end
283
299
 
300
+ # Respond to the HTTP request with a `405` (Method Not Allowed) response.
301
+ def method_not_allowed!(allowed_http_methods=[])
302
+ @response.headers["Allow"] = allowed_http_methods.join(", ")
303
+ @response_status = 405
304
+ @response_status_string = "Method Not Allowed"
305
+ respond
306
+ end
307
+
284
308
  # Respond to the HTTP request with a `412` (Precondition Failed)
285
309
  # response.
286
310
  def precondition_failed!
@@ -297,25 +321,63 @@ module Sensu
297
321
  respond
298
322
  end
299
323
 
324
+ # Determine the allowed HTTP methods for a route. The route
325
+ # regular expressions and associated route method calls are
326
+ # provided by `ROUTES`. This method returns an array of HTTP
327
+ # methods that have a route that matches the HTTP request URI.
328
+ #
329
+ # @return [Array]
330
+ def allowed_http_methods?
331
+ ROUTES.map { |http_method, routes|
332
+ match = routes.detect do |route|
333
+ @http_request_uri =~ route[0]
334
+ end
335
+ match ? http_method : nil
336
+ }.flatten.compact
337
+ end
338
+
339
+ # Determine the route method for the HTTP request method and
340
+ # URI. The route regular expressions and associated route method
341
+ # calls are provided by `ROUTES`. This method will return the
342
+ # first route method name (Ruby symbol) that has matching URI
343
+ # regular expression. If an HTTP method is not supported, or
344
+ # there is not a matching regular expression, `nil` will be
345
+ # returned.
346
+ #
347
+ # @return [Symbol]
348
+ def determine_route_method
349
+ if ROUTES.has_key?(@http_request_method)
350
+ route = ROUTES[@http_request_method].detect do |route|
351
+ @http_request_uri =~ route[0]
352
+ end
353
+ route ? route[1] : nil
354
+ else
355
+ nil
356
+ end
357
+ end
358
+
300
359
  # Route the HTTP request. OPTIONS HTTP requests will always
301
- # return a `200` with no response content. The route regular
302
- # expressions and associated route method calls are provided by
303
- # `ROUTES`. If a route match is not found, this method responds
304
- # with a `404` (Not Found) HTTP response.
360
+ # return a `200` with no response content. This method uses
361
+ # `determine_route_method()` to determine the symbolized route
362
+ # method to send/call. If a route method does not exist for the
363
+ # HTTP request method and URI, this method uses
364
+ # `allowed_http_methods?()` to determine if a 404 (Not Found) or
365
+ # 405 (Method Not Allowed) HTTP response should be used.
305
366
  def route_request
306
367
  if @http_request_method == OPTIONS_METHOD
307
368
  respond
308
- elsif ROUTES.has_key?(@http_request_method)
309
- route = ROUTES[@http_request_method].detect do |route|
310
- @http_request_uri =~ route[0]
311
- end
312
- unless route.nil?
313
- send(route[1])
369
+ else
370
+ route_method = determine_route_method
371
+ if route_method
372
+ send(route_method)
314
373
  else
315
- not_found!
374
+ allowed_http_methods = allowed_http_methods?
375
+ if allowed_http_methods.empty?
376
+ not_found!
377
+ else
378
+ method_not_allowed!(allowed_http_methods)
379
+ end
316
380
  end
317
- else
318
- not_found!
319
381
  end
320
382
  end
321
383
 
@@ -1,3 +1,4 @@
1
+ require "sensu/api/routes/settings"
1
2
  require "sensu/api/routes/info"
2
3
  require "sensu/api/routes/health"
3
4
  require "sensu/api/routes/clients"
@@ -13,6 +14,7 @@ require "sensu/api/routes/silenced"
13
14
  module Sensu
14
15
  module API
15
16
  module Routes
17
+ include Settings
16
18
  include Info
17
19
  include Health
18
20
  include Clients
@@ -32,6 +34,7 @@ module Sensu
32
34
  OPTIONS_METHOD = "OPTIONS".freeze
33
35
 
34
36
  GET_ROUTES = [
37
+ [SETTINGS_URI, :get_settings],
35
38
  [INFO_URI, :get_info],
36
39
  [HEALTH_URI, :get_health],
37
40
  [CLIENTS_URI, :get_clients],
@@ -113,8 +113,11 @@ module Sensu
113
113
  # DELETE /clients/:client_name
114
114
  def delete_client
115
115
  client_name = parse_uri(CLIENT_URI).first
116
- @redis.get("client:#{client_name}") do |client_json|
116
+ client_key = "client:#{client_name}"
117
+ signature_key = "#{client_key}:signature"
118
+ @redis.get(client_key) do |client_json|
117
119
  unless client_json.nil?
120
+ @redis.set(signature_key, "invalidated") if @params[:invalidate]
118
121
  @redis.hgetall("events:#{client_name}") do |events|
119
122
  events.each do |check_name, event_json|
120
123
  resolve_event(event_json)
@@ -125,8 +128,13 @@ module Sensu
125
128
  if events.empty? || attempts == 5
126
129
  @logger.info("deleting client from registry", :client_name => client_name)
127
130
  @redis.srem("clients", client_name) do
128
- @redis.del("client:#{client_name}")
129
- @redis.del("client:#{client_name}:signature")
131
+ @redis.del(client_key)
132
+ invalidate_expire = integer_parameter(@params[:invalidate_expire])
133
+ if @params[:invalidate] && invalidate_expire
134
+ @redis.expire(signature_key, invalidate_expire)
135
+ else
136
+ @redis.del(signature_key)
137
+ end
130
138
  @redis.del("events:#{client_name}")
131
139
  @redis.smembers("result:#{client_name}") do |checks|
132
140
  checks.each do |check_name|
@@ -16,7 +16,10 @@ module Sensu
16
16
  servers_info do |servers|
17
17
  @response_content = {
18
18
  :sensu => {
19
- :version => VERSION
19
+ :version => VERSION,
20
+ :settings => {
21
+ :hexdigest => @settings.hexdigest
22
+ }
20
23
  },
21
24
  :transport => transport,
22
25
  :redis => {
@@ -26,7 +26,11 @@ module Sensu
26
26
  :reason => data[:reason],
27
27
  :creator => data[:creator]
28
28
  }
29
- publish_check_request(check)
29
+ if check[:proxy_requests]
30
+ publish_proxy_check_requests(check)
31
+ else
32
+ publish_check_request(check)
33
+ end
30
34
  @response_content = {:issued => Time.now.to_i}
31
35
  accepted!
32
36
  else
@@ -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
@@ -0,0 +1,44 @@
1
+ require "sensu/utilities"
2
+
3
+ module Sensu
4
+ module API
5
+ module Utilities
6
+ module FilterResponseContent
7
+ include Sensu::Utilities
8
+
9
+ # Create a nested hash from a dot notation key and value.
10
+ #
11
+ # @param dot_notation [String]
12
+ # @param value [Object]
13
+ # @return [Hash]
14
+ def dot_notation_to_hash(dot_notation, value)
15
+ hash = {}
16
+ dot_notation.split(".").reverse.each do |key|
17
+ if hash.empty?
18
+ hash = {key.to_sym => value}
19
+ else
20
+ hash = {key.to_sym => hash}
21
+ end
22
+ end
23
+ hash
24
+ end
25
+
26
+ # Filter the response content if filter parameters have been
27
+ # provided. This method mutates `@response_content`, only
28
+ # retaining array items that match the attributes provided via
29
+ # filter parameters.
30
+ def filter_response_content!
31
+ if @response_content.is_a?(Array) && !@filter_params.empty?
32
+ attributes = {}
33
+ @filter_params.each do |key, value|
34
+ attributes = deep_merge(attributes, dot_notation_to_hash(key, value))
35
+ end
36
+ @response_content.select! do |object|
37
+ attributes_match?(object, attributes, false)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,7 +1,11 @@
1
+ require "sensu/utilities"
2
+
1
3
  module Sensu
2
4
  module API
3
5
  module Utilities
4
6
  module PublishCheckRequest
7
+ include Sensu::Utilities
8
+
5
9
  # Determine the Sensu Transport publish options for a
6
10
  # subscription. If a subscription begins with a Transport pipe
7
11
  # type, either "direct:" or "roundrobin:", the subscription uses
@@ -33,7 +37,10 @@ module Sensu
33
37
  #
34
38
  # @param check [Hash] definition.
35
39
  def publish_check_request(check)
36
- payload = check.merge(:issued => Time.now.to_i)
40
+ payload = check.reject do |key, value|
41
+ [:subscribers, :interval].include?(key)
42
+ end
43
+ payload[:issued] = Time.now.to_i
37
44
  @logger.info("publishing check request", {
38
45
  :payload => payload,
39
46
  :subscribers => check[:subscribers]
@@ -51,6 +58,49 @@ module Sensu
51
58
  end
52
59
  end
53
60
  end
61
+
62
+ # Create and publish one or more proxy check requests. This
63
+ # method iterates through the Sensu client registry for clients
64
+ # that matched provided proxy request client attributes. A proxy
65
+ # check request is created for each client in the registry that
66
+ # matches the proxy request client attributes. Proxy check
67
+ # requests have their client tokens subsituted by the associated
68
+ # client attributes values. The check requests are published to
69
+ # the Transport via `publish_check_request()`.
70
+ #
71
+ # @param check [Hash] definition.
72
+ def publish_proxy_check_requests(check)
73
+ client_attributes = check[:proxy_requests][:client_attributes]
74
+ unless client_attributes.empty?
75
+ @redis.smembers("clients") do |clients|
76
+ clients.each do |client_name|
77
+ @redis.get("client:#{client_name}") do |client_json|
78
+ unless client_json.nil?
79
+ client = Sensu::JSON.load(client_json)
80
+ if attributes_match?(client, client_attributes)
81
+ @logger.debug("creating a proxy check request", {
82
+ :client => client,
83
+ :check => check
84
+ })
85
+ proxy_check, unmatched_tokens = object_substitute_tokens(check.dup, client)
86
+ if unmatched_tokens.empty?
87
+ proxy_check[:source] ||= client[:name]
88
+ publish_check_request(proxy_check)
89
+ else
90
+ @logger.warn("failed to publish a proxy check request", {
91
+ :reason => "unmatched client tokens",
92
+ :unmatched_tokens => unmatched_tokens,
93
+ :client => client,
94
+ :check => check
95
+ })
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
54
104
  end
55
105
  end
56
106
  end
@@ -11,6 +11,12 @@ module Sensu
11
11
  # @return [Hash] options
12
12
  def self.read(arguments=ARGV)
13
13
  options = {}
14
+ if File.exist?("/etc/sensu/config.json")
15
+ options[:config_file] = "/etc/sensu/config.json"
16
+ end
17
+ if Dir.exist?("/etc/sensu/conf.d")
18
+ options[:config_dirs] = ["/etc/sensu/conf.d"]
19
+ end
14
20
  optparse = OptionParser.new do |opts|
15
21
  opts.on("-h", "--help", "Display this message") do
16
22
  puts opts
@@ -20,10 +26,10 @@ module Sensu
20
26
  puts VERSION
21
27
  exit
22
28
  end
23
- opts.on("-c", "--config FILE", "Sensu JSON config FILE") do |file|
29
+ opts.on("-c", "--config FILE", "Sensu JSON config FILE. Default: /etc/sensu/config.json (if exists)") do |file|
24
30
  options[:config_file] = file
25
31
  end
26
- opts.on("-d", "--config_dir DIR[,DIR]", "DIR or comma-delimited DIR list for Sensu JSON config files") do |dir|
32
+ opts.on("-d", "--config_dir DIR[,DIR]", "DIR or comma-delimited DIR list for Sensu JSON config files. Default: /etc/sensu/conf.d (if exists)") do |dir|
27
33
  options[:config_dirs] = dir.split(",")
28
34
  end
29
35
  opts.on("--validate_config", "Validate the compiled configuration and exit") do
@@ -1,7 +1,7 @@
1
1
  module Sensu
2
2
  unless defined?(Sensu::VERSION)
3
3
  # Sensu release version.
4
- VERSION = "0.28.6".freeze
4
+ VERSION = "0.29.0".freeze
5
5
 
6
6
  # Sensu check severities.
7
7
  SEVERITIES = %w[ok warning critical unknown].freeze
@@ -4,12 +4,12 @@ gem "eventmachine", "1.2.2"
4
4
 
5
5
  gem "sensu-json", "2.1.0"
6
6
  gem "sensu-logger", "1.2.1"
7
- gem "sensu-settings", "9.9.0"
7
+ gem "sensu-settings", "10.0.0"
8
8
  gem "sensu-extension", "1.5.1"
9
- gem "sensu-extensions", "1.7.1"
9
+ gem "sensu-extensions", "1.9.0"
10
10
  gem "sensu-transport", "7.0.2"
11
11
  gem "sensu-spawn", "2.2.1"
12
- gem "sensu-redis", "2.1.0"
12
+ gem "sensu-redis", "2.1.1"
13
13
 
14
14
  require "time"
15
15
  require "uri"
@@ -142,6 +142,7 @@ module Sensu
142
142
  @logger.fatal("SENSU NOT RUNNING!")
143
143
  exit 2
144
144
  end
145
+ @settings.set_env!
145
146
  end
146
147
 
147
148
  # Load Sensu extensions and log any notices. Set the logger and
@@ -11,7 +11,9 @@ module Sensu
11
11
  include Mutate
12
12
  include Handle
13
13
 
14
- attr_reader :is_leader, :in_progress
14
+ attr_reader :tasks, :in_progress
15
+
16
+ TASKS = ["check_request_publisher", "client_monitor", "check_result_monitor"]
15
17
 
16
18
  STANDARD_CHECK_TYPE = "standard".freeze
17
19
 
@@ -34,14 +36,17 @@ module Sensu
34
36
  end
35
37
  end
36
38
 
37
- # Override Daemon initialize() to support Sensu server leader
38
- # election and the handling event count.
39
+ # Override Daemon initialize() to support Sensu server tasks and
40
+ # the handling event count.
39
41
  #
40
42
  # @param options [Hash]
41
43
  def initialize(options={})
42
44
  super
43
- @is_leader = false
44
- @timers[:leader] = Array.new
45
+ @tasks = []
46
+ @timers[:tasks] = {}
47
+ TASKS.each do |task|
48
+ @timers[:tasks][task.to_sym] = []
49
+ end
45
50
  @in_progress = Hash.new(0)
46
51
  end
47
52
 
@@ -150,7 +155,7 @@ module Sensu
150
155
  if (signature.nil? || signature.empty?) && client[:signature]
151
156
  @redis.set(signature_key, client[:signature])
152
157
  end
153
- if signature.nil? || signature.empty? || (client[:signature] == signature)
158
+ if signature.nil? || signature.empty? || client[:signature] == signature
154
159
  @redis.multi
155
160
  @redis.set(client_key, Sensu::JSON.dump(client))
156
161
  @redis.sadd("clients", client[:name])
@@ -429,18 +434,11 @@ module Sensu
429
434
  # @return [TrueClass, FalseClass]
430
435
  def check_flapping?(stored_event, check)
431
436
  if check.has_key?(:low_flap_threshold) && check.has_key?(:high_flap_threshold)
432
- if check[:low_flap_threshold].is_a?(Integer) && check[:high_flap_threshold].is_a?(Integer)
433
- was_flapping = stored_event && stored_event[:action] == EVENT_FLAPPING_ACTION
434
- if was_flapping
435
- check[:total_state_change] > check[:low_flap_threshold]
436
- else
437
- check[:total_state_change] >= check[:high_flap_threshold]
438
- end
437
+ was_flapping = stored_event && stored_event[:action] == EVENT_FLAPPING_ACTION
438
+ if was_flapping
439
+ check[:total_state_change] > check[:low_flap_threshold]
439
440
  else
440
- details = {:check => check}
441
- details[:client] = stored_event[:client] if stored_event
442
- @logger.error("invalid check flap thresholds", details)
443
- false
441
+ check[:total_state_change] >= check[:high_flap_threshold]
444
442
  end
445
443
  else
446
444
  false
@@ -607,7 +605,10 @@ module Sensu
607
605
  # `client_key` as the client name. Dynamically create client
608
606
  # data can be updated using the API (POST /clients/:client). If
609
607
  # a client does exist and it has a client signature, the check
610
- # result must have a matching signature or it is discarded.
608
+ # result must have a matching signature or it is discarded. If
609
+ # the client does not exist, but a client signature exists, the
610
+ # check result must have a matching signature or it is
611
+ # discarded.
611
612
  #
612
613
  # @param result [Hash] data.
613
614
  # @yield [client] callback/block to be called with client data,
@@ -633,10 +634,20 @@ module Sensu
633
634
  yield(client)
634
635
  end
635
636
  else
636
- client = create_client(client_key)
637
- client[:type] = "proxy" if result[:check][:source]
638
- update_client_registry(client) do
639
- yield(client)
637
+ @redis.get("client:#{client_key}:signature") do |signature|
638
+ if signature.nil? || signature.empty? || result[:signature] == signature
639
+ client = create_client(client_key)
640
+ client[:type] = "proxy" if result[:check][:source]
641
+ update_client_registry(client) do
642
+ yield(client)
643
+ end
644
+ else
645
+ @logger.warn("invalid check result signature", {
646
+ :result => result,
647
+ :signature => signature
648
+ })
649
+ yield(nil)
650
+ end
640
651
  end
641
652
  end
642
653
  end
@@ -843,18 +854,16 @@ module Sensu
843
854
  # creats an EventMachine timer for the request. This method will
844
855
  # be called after every check cron request for subsequent
845
856
  # requests. The timer is stored in the timer hash under
846
- # `:leader`, as check request publishing is a task for only the
847
- # Sensu server leader, so it can be cancelled etc. The check
848
- # cron request timer object is removed from the timer hash after
849
- # the request is published, to stop the timer hash from growing
850
- # infinitely.
857
+ # `:tasks`, so it can be cancelled etc. The check cron request
858
+ # timer object is removed from the timer hash after the request
859
+ # is published, to stop the timer hash from growing infinitely.
851
860
  #
852
861
  # @param check [Hash] definition.
853
862
  def schedule_check_cron_request(check)
854
863
  cron_time = determine_check_cron_time(check)
855
- @timers[:leader] << EM::Timer.new(cron_time) do |timer|
864
+ @timers[:tasks][:check_request_publisher] << EM::Timer.new(cron_time) do |timer|
856
865
  create_check_request_proc(check).call
857
- @timers[:leader].delete(timer)
866
+ @timers[:tasks][:check_request_publisher].delete(timer)
858
867
  schedule_check_cron_request(check)
859
868
  end
860
869
  end
@@ -874,17 +883,16 @@ module Sensu
874
883
  # using an intial calculated request splay EventMachine timer
875
884
  # and an EventMachine periodic timer for subsequent check
876
885
  # requests. The timers are stored in the timers hash under
877
- # `:leader`, as check request publishing is a task for only the
878
- # Sensu server leader, so they can be cancelled etc.
886
+ # `:tasks`, so they can be cancelled etc.
879
887
  #
880
888
  # @param check [Hash] definition.
881
889
  def schedule_check_interval_requests(check)
882
890
  request_splay = testing? ? 0 : calculate_check_request_splay(check)
883
891
  interval = testing? ? 0.5 : check[:interval]
884
- @timers[:leader] << EM::Timer.new(request_splay) do
892
+ @timers[:tasks][:check_request_publisher] << EM::Timer.new(request_splay) do
885
893
  create_check_request = create_check_request_proc(check)
886
894
  create_check_request.call
887
- @timers[:leader] << EM::PeriodicTimer.new(interval, &create_check_request)
895
+ @timers[:tasks][:check_request_publisher] << EM::PeriodicTimer.new(interval, &create_check_request)
888
896
  end
889
897
  end
890
898
 
@@ -1041,10 +1049,10 @@ module Sensu
1041
1049
 
1042
1050
  # Set up the client monitor, a periodic timer to run
1043
1051
  # `determine_stale_clients()` every 30 seconds. The timer is
1044
- # stored in the timers hash under `:leader`.
1052
+ # stored in the timers hash under `:tasks`.
1045
1053
  def setup_client_monitor
1046
1054
  @logger.debug("monitoring client keepalives")
1047
- @timers[:leader] << EM::PeriodicTimer.new(30) do
1055
+ @timers[:tasks][:client_monitor] << EM::PeriodicTimer.new(30) do
1048
1056
  determine_stale_clients
1049
1057
  end
1050
1058
  end
@@ -1087,31 +1095,21 @@ module Sensu
1087
1095
 
1088
1096
  # Set up the check result monitor, a periodic timer to run
1089
1097
  # `determine_stale_check_results()` every 30 seconds. The timer
1090
- # is stored in the timers hash under `:leader`.
1098
+ # is stored in the timers hash under `:tasks`.
1091
1099
  def setup_check_result_monitor(interval = 30)
1092
1100
  @logger.debug("monitoring check results")
1093
- @timers[:leader] << EM::PeriodicTimer.new(interval) do
1101
+ @timers[:tasks][:check_result_monitor] << EM::PeriodicTimer.new(interval) do
1094
1102
  determine_stale_check_results(interval)
1095
1103
  end
1096
1104
  end
1097
1105
 
1098
- # Set up the leader duties, tasks only performed by a single
1099
- # Sensu server at a time. The duties include publishing check
1100
- # requests, monitoring for stale clients, and pruning check
1101
- # result aggregations.
1102
- def leader_duties
1103
- setup_check_request_publisher
1104
- setup_client_monitor
1105
- setup_check_result_monitor
1106
- end
1107
-
1108
1106
  # Create a lock timestamp (integer), current time including
1109
- # milliseconds. This method is used by Sensu server leader
1107
+ # milliseconds. This method is used by Sensu server task
1110
1108
  # election.
1111
1109
  #
1112
1110
  # @return [Integer]
1113
1111
  def create_lock_timestamp
1114
- (Time.now.to_f * 1000).to_i
1112
+ (Time.now.to_f * 10000000).to_i
1115
1113
  end
1116
1114
 
1117
1115
  # Create/return the unique Sensu server ID for the current
@@ -1122,122 +1120,168 @@ module Sensu
1122
1120
  @server_id ||= random_uuid
1123
1121
  end
1124
1122
 
1125
- # Become the Sensu server leader, responsible for specific
1126
- # duties (`leader_duties()`). Unless the current process is
1127
- # already the leader, this method sets the leader ID stored in
1128
- # Redis to the unique random server ID for the process. If the
1129
- # leader ID in Redis is successfully updated, `@is_leader` is
1130
- # set to true and `leader_duties()` is called to begin the
1131
- # tasks/duties of the Sensu server leader.
1132
- def become_the_leader
1133
- unless @is_leader
1134
- @redis.set("leader", server_id) do
1135
- @logger.info("i am now the leader")
1136
- @is_leader = true
1137
- leader_duties
1123
+ # Setup a Sensu server task. Unless the current process is
1124
+ # already responsible for the task, this method sets the tasks
1125
+ # server ID stored in Redis to the unique random server ID for
1126
+ # the process. If the tasks server ID is successfully updated,
1127
+ # the task is added to `@tasks` for tracking purposes and the
1128
+ # task setup method is called.
1129
+ #
1130
+ # @param task [String]
1131
+ # @yield callback/block called after setting up the task.
1132
+ def setup_task(task)
1133
+ unless @tasks.include?(task)
1134
+ @redis.set("task:#{task}:server", server_id) do
1135
+ @logger.info("i am now responsible for a server task", :task => task)
1136
+ @tasks << task
1137
+ self.send("setup_#{task}".to_sym)
1138
+ yield if block_given?
1138
1139
  end
1139
1140
  else
1140
- @logger.debug("i am already the leader")
1141
+ @logger.debug("i am already responsible for a server task", :task => task)
1141
1142
  end
1142
1143
  end
1143
1144
 
1144
- # Resign as leader, if the current process is the Sensu server
1145
- # leader. This method cancels and clears the leader timers,
1146
- # those with references stored in the timers hash under
1147
- # `:leader`, and `@is_leader` is set to `false`. The leader ID
1148
- # and leader lock are not removed from Redis, as they will be
1149
- # updated when another server is elected to be the leader, this
1150
- # method does not need to handle Redis connectivity issues.
1151
- def resign_as_leader
1152
- if @is_leader
1153
- @logger.warn("resigning as leader")
1154
- @timers[:leader].each do |timer|
1145
+ # Relinquish a Sensu server task. This method cancels and
1146
+ # clears the associated task timers, those with references
1147
+ # stored in the timers hash under `:tasks`, and removes the task
1148
+ # from `@tasks`. The task server ID and lock are not removed
1149
+ # from Redis, as they will be updated when another server takes
1150
+ # reponsibility for the task, this method does not need to
1151
+ # handle Redis connectivity issues.
1152
+ #
1153
+ # @param task [String]
1154
+ def relinquish_task(task)
1155
+ if @tasks.include?(task)
1156
+ @logger.warn("relinquishing server task", :task => task)
1157
+ @timers[:tasks][task.to_sym].each do |timer|
1155
1158
  timer.cancel
1156
1159
  end
1157
- @timers[:leader].clear
1158
- @is_leader = false
1160
+ @timers[:tasks][task.to_sym].clear
1161
+ @tasks.delete(task)
1159
1162
  else
1160
- @logger.debug("not currently the leader")
1163
+ @logger.debug("not currently responsible for a server task", :task => task)
1161
1164
  end
1162
1165
  end
1163
1166
 
1164
- # Updates the Sensu server leader lock timestamp. The current
1165
- # leader ID is retrieved from Redis and compared with the server
1166
- # ID of the current process to determine if it is still the
1167
- # Sensu server leader. If the current process is still the
1168
- # leader, the leader lock timestamp is updated. If the current
1169
- # process is no longer the leader (regicide),
1170
- # `resign_as_leader()` is called for cleanup, so there is not
1171
- # more than one leader.
1172
- def update_leader_lock
1173
- @redis.get("leader") do |current_leader_id|
1174
- if current_leader_id == server_id
1175
- @redis.set("lock:leader", create_lock_timestamp) do
1176
- @logger.debug("updated leader lock timestamp")
1167
+ # Relinquish all Sensu server tasks, if any.
1168
+ def relinquish_tasks
1169
+ unless @tasks.empty?
1170
+ @tasks.dup.each do |task|
1171
+ relinquish_task(task)
1172
+ end
1173
+ else
1174
+ @logger.debug("not currently responsible for a server task")
1175
+ end
1176
+ end
1177
+
1178
+ # Updates a Sensu server task lock timestamp. The current task
1179
+ # server ID is retrieved from Redis and compared with the server
1180
+ # ID of the current process to determine if it is still
1181
+ # responsible for the task. If the current process is still
1182
+ # responsible, the task lock timestamp is updated. If the
1183
+ # current process is no longer responsible, `relinquish_task()`
1184
+ # is called for cleanup.
1185
+ #
1186
+ # @param task [String]
1187
+ def update_task_lock(task)
1188
+ @redis.get("task:#{task}:server") do |current_server_id|
1189
+ if current_server_id == server_id
1190
+ @redis.set("lock:task:#{task}", create_lock_timestamp) do
1191
+ @logger.debug("updated task lock timestamp", :task => task)
1177
1192
  end
1178
1193
  else
1179
- @logger.warn("another sensu server has been elected as leader")
1180
- resign_as_leader
1194
+ @logger.warn("another sensu server is responsible for the task", :task => task)
1195
+ relinquish_task(task)
1181
1196
  end
1182
1197
  end
1183
1198
  end
1184
1199
 
1185
- # Request a leader election, a process to determine if the
1186
- # current process is the Sensu server leader, with its
1187
- # own/unique duties. A Redis key/value is used as a central
1188
- # lock, using the "SETNX" Redis command to set the key/value if
1189
- # it does not exist, using a timestamp for the value. If the
1190
- # current process was able to create the key/value, it is the
1191
- # leader, and must do the duties of the leader. If the current
1192
- # process was not able to create the key/value, but the current
1193
- # timestamp value is equal to or over 30 seconds ago, the
1194
- # "GETSET" Redis command is used to set a new timestamp and
1195
- # fetch the previous value to compare them, to determine if it
1196
- # was set by the current process. If the current process is able
1197
- # to set the timestamp value, it becomes the leader.
1198
- def request_leader_election
1199
- @redis.setnx("lock:leader", create_lock_timestamp) do |created|
1200
+ # Set up a Sensu server task lock updater. This method uses a
1201
+ # periodic timer to update a task lock timestamp in Redis, every
1202
+ # 10 seconds. If the current process fails to keep the lock
1203
+ # timestamp updated for a task that it is responsible for,
1204
+ # another Sensu server will claim responsibility. This method is
1205
+ # called after task setup.
1206
+ #
1207
+ # @param task [String]
1208
+ def setup_task_lock_updater(task)
1209
+ @timers[:run] << EM::PeriodicTimer.new(10) do
1210
+ update_task_lock(task)
1211
+ end
1212
+ end
1213
+
1214
+ # Request a Sensu server task election, a process to determine
1215
+ # if the current process is to be responsible for the task. A
1216
+ # Redis key/value is used as a central lock, using the "SETNX"
1217
+ # Redis command to set the key/value if it does not exist, using
1218
+ # a timestamp for the value. If the current process was able to
1219
+ # create the key/value, it is elected, and is then responsible
1220
+ # for the task. If the current process was not able to create
1221
+ # the key/value, but the current timestamp value is equal to or
1222
+ # over 30 seconds ago, the "GETSET" Redis command is used to set
1223
+ # a new timestamp and fetch the previous value to compare them,
1224
+ # to determine if it was set by the current process. If the
1225
+ # current process is able to set the timestamp value, it is
1226
+ # elected. If elected, the current process sets up the task and
1227
+ # the associated task lock updater.
1228
+ #
1229
+ # @param task [String]
1230
+ # @yield callback/block called either after being elected and
1231
+ # setting up the task, or after failing to be elected.
1232
+ def request_task_election(task, &callback)
1233
+ @redis.setnx("lock:task:#{task}", create_lock_timestamp) do |created|
1200
1234
  if created
1201
- become_the_leader
1235
+ setup_task(task, &callback)
1236
+ setup_task_lock_updater(task)
1202
1237
  else
1203
- @redis.get("lock:leader") do |current_lock_timestamp|
1238
+ @redis.get("lock:task:#{task}") do |current_lock_timestamp|
1204
1239
  new_lock_timestamp = create_lock_timestamp
1205
- if new_lock_timestamp - current_lock_timestamp.to_i >= 30000
1206
- @redis.getset("lock:leader", new_lock_timestamp) do |previous_lock_timestamp|
1240
+ if new_lock_timestamp - current_lock_timestamp.to_i >= 300000000
1241
+ @redis.getset("lock:task:#{task}", new_lock_timestamp) do |previous_lock_timestamp|
1207
1242
  if previous_lock_timestamp == current_lock_timestamp
1208
- become_the_leader
1243
+ setup_task(task, &callback)
1244
+ setup_task_lock_updater(task)
1209
1245
  end
1210
1246
  end
1247
+ else
1248
+ yield if block_given?
1211
1249
  end
1212
1250
  end
1213
1251
  end
1214
1252
  end
1215
1253
  end
1216
1254
 
1217
- # Set up the leader monitor. A one-time timer is used to run
1218
- # `request_leader_exection()` in 2 seconds. A periodic timer is
1219
- # used to update the leader lock timestamp if the current
1220
- # process is the leader, or to run `request_leader_election(),
1221
- # every 10 seconds. The timers are stored in the timers hash
1222
- # under `:run`.
1223
- def setup_leader_monitor
1224
- @timers[:run] << EM::Timer.new(2) do
1225
- request_leader_election
1226
- end
1227
- @timers[:run] << EM::PeriodicTimer.new(10) do
1228
- if @is_leader
1229
- update_leader_lock
1255
+ # Request Sensu server task elections. The task list is ordered
1256
+ # by prioity. This method works through the task list serially,
1257
+ # increasing the election request delay as the current process
1258
+ # becomes responsible for one or more tasks, this is to improve
1259
+ # the initial distribution of tasks amongst Sensu servers.
1260
+ #
1261
+ # @param splay [Integer]
1262
+ def setup_task_elections(splay=10)
1263
+ tasks = TASKS.dup - @tasks
1264
+ next_task = Proc.new do
1265
+ task = tasks.shift
1266
+ if task
1267
+ delay = splay * @tasks.size
1268
+ @timers[:run] << EM::Timer.new(delay) do
1269
+ request_task_election(task, &next_task)
1270
+ end
1230
1271
  else
1231
- request_leader_election
1272
+ @timers[:run] << EM::Timer.new(10) do
1273
+ setup_task_elections(splay)
1274
+ end
1232
1275
  end
1233
1276
  end
1277
+ next_task.call
1234
1278
  end
1235
1279
 
1236
1280
  # Update the Sensu server registry, stored in Redis. This method
1237
1281
  # adds the local/current Sensu server info to the registry,
1238
- # including its id, hostname, address, if its the current
1239
- # leader, and some metrics. Sensu server registry entries expire
1240
- # in 30 seconds unless updated.
1282
+ # including its id, hostname, address, its server tasks, and
1283
+ # some metrics. Sensu server registry entries expire in 30
1284
+ # seconds unless updated.
1241
1285
  #
1242
1286
  # @yield [success] passes success status to optional
1243
1287
  # callback/block.
@@ -1250,13 +1294,19 @@ module Sensu
1250
1294
  :id => server_id,
1251
1295
  :hostname => system_hostname,
1252
1296
  :address => system_address,
1253
- :is_leader => @is_leader,
1297
+ :tasks => @tasks,
1254
1298
  :metrics => {
1255
1299
  :cpu => {
1256
1300
  :user => cpu_user,
1257
1301
  :system => cpu_system
1258
1302
  }
1259
1303
  },
1304
+ :sensu => {
1305
+ :version => VERSION,
1306
+ :settings => {
1307
+ :hexdigest => @settings.hexdigest
1308
+ }
1309
+ },
1260
1310
  :timestamp => Time.now.to_i
1261
1311
  }
1262
1312
  @redis.sadd("servers", server_id)
@@ -1304,13 +1354,13 @@ module Sensu
1304
1354
  end
1305
1355
 
1306
1356
  # Bootstrap the Sensu server process, setting up the keepalive
1307
- # and check result consumers, and attemping to become the leader
1308
- # to carry out its duties. This method sets the process/daemon
1309
- # `@state` to `:running`.
1357
+ # and check result consumers, and attemping to carry out Sensu
1358
+ # server tasks. This method sets the process/daemon `@state` to
1359
+ # `:running`.
1310
1360
  def bootstrap
1311
1361
  setup_keepalives
1312
1362
  setup_results
1313
- setup_leader_monitor
1363
+ setup_task_elections
1314
1364
  setup_server_registry_updater
1315
1365
  @state = :running
1316
1366
  end
@@ -1330,8 +1380,8 @@ module Sensu
1330
1380
  # set to `:pausing`, to indicate that it's in progress. All run
1331
1381
  # timers are cancelled, and the references are cleared. The
1332
1382
  # Sensu server will unsubscribe from all transport
1333
- # subscriptions, resign as leader (if currently the leader),
1334
- # then set the process/daemon `@state` to `:paused`.
1383
+ # subscriptions, relinquish any Sensu server tasks, then set the
1384
+ # process/daemon `@state` to `:paused`.
1335
1385
  def pause
1336
1386
  unless @state == :pausing || @state == :paused
1337
1387
  @state = :pausing
@@ -1340,7 +1390,7 @@ module Sensu
1340
1390
  end
1341
1391
  @timers[:run].clear
1342
1392
  unsubscribe
1343
- resign_as_leader
1393
+ relinquish_tasks
1344
1394
  @state = :paused
1345
1395
  end
1346
1396
  end
@@ -259,9 +259,10 @@ module Sensu
259
259
  #
260
260
  # @param object [Hash]
261
261
  # @param match_attributes [Object]
262
+ # @param support_eval [TrueClass, FalseClass]
262
263
  # @param object_attributes [Object]
263
264
  # @return [TrueClass, FalseClass]
264
- def attributes_match?(object, match_attributes, object_attributes=nil)
265
+ def attributes_match?(object, match_attributes, support_eval=true, object_attributes=nil)
265
266
  object_attributes ||= object
266
267
  match_attributes.all? do |key, value_one|
267
268
  value_two = object_attributes[key]
@@ -269,10 +270,10 @@ module Sensu
269
270
  when value_one == value_two
270
271
  true
271
272
  when value_one.is_a?(Hash) && value_two.is_a?(Hash)
272
- attributes_match?(object, value_one, value_two)
273
+ attributes_match?(object, value_one, support_eval, value_two)
273
274
  when value_one.to_s == value_two.to_s
274
275
  true
275
- when value_one.is_a?(String) && value_one.start_with?(EVAL_PREFIX)
276
+ when value_one.is_a?(String) && value_one.start_with?(EVAL_PREFIX) && support_eval
276
277
  eval_attribute_value(object, value_one, value_two)
277
278
  else
278
279
  false
@@ -15,12 +15,12 @@ Gem::Specification.new do |s|
15
15
  s.add_dependency "eventmachine", "1.2.2"
16
16
  s.add_dependency "sensu-json", "2.1.0"
17
17
  s.add_dependency "sensu-logger", "1.2.1"
18
- s.add_dependency "sensu-settings", "9.9.0"
18
+ s.add_dependency "sensu-settings", "10.0.0"
19
19
  s.add_dependency "sensu-extension", "1.5.1"
20
- s.add_dependency "sensu-extensions", "1.7.1"
20
+ s.add_dependency "sensu-extensions", "1.9.0"
21
21
  s.add_dependency "sensu-transport", "7.0.2"
22
22
  s.add_dependency "sensu-spawn", "2.2.1"
23
- s.add_dependency "sensu-redis", "2.1.0"
23
+ s.add_dependency "sensu-redis", "2.1.1"
24
24
  s.add_dependency "em-http-server", "0.1.8"
25
25
  s.add_dependency "parse-cron", "0.1.4"
26
26
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sensu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.28.6
4
+ version: 0.29.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Porter
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2017-04-28 00:00:00.000000000 Z
12
+ date: 2017-03-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: eventmachine
@@ -59,14 +59,14 @@ dependencies:
59
59
  requirements:
60
60
  - - '='
61
61
  - !ruby/object:Gem::Version
62
- version: 9.9.0
62
+ version: 10.0.0
63
63
  type: :runtime
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
67
  - - '='
68
68
  - !ruby/object:Gem::Version
69
- version: 9.9.0
69
+ version: 10.0.0
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: sensu-extension
72
72
  requirement: !ruby/object:Gem::Requirement
@@ -87,14 +87,14 @@ dependencies:
87
87
  requirements:
88
88
  - - '='
89
89
  - !ruby/object:Gem::Version
90
- version: 1.7.1
90
+ version: 1.9.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.7.1
97
+ version: 1.9.0
98
98
  - !ruby/object:Gem::Dependency
99
99
  name: sensu-transport
100
100
  requirement: !ruby/object:Gem::Requirement
@@ -129,14 +129,14 @@ dependencies:
129
129
  requirements:
130
130
  - - '='
131
131
  - !ruby/object:Gem::Version
132
- version: 2.1.0
132
+ version: 2.1.1
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: 2.1.0
139
+ version: 2.1.1
140
140
  - !ruby/object:Gem::Dependency
141
141
  name: em-http-server
142
142
  requirement: !ruby/object:Gem::Requirement
@@ -253,8 +253,10 @@ files:
253
253
  - lib/sensu/api/routes/request.rb
254
254
  - lib/sensu/api/routes/resolve.rb
255
255
  - lib/sensu/api/routes/results.rb
256
+ - lib/sensu/api/routes/settings.rb
256
257
  - lib/sensu/api/routes/silenced.rb
257
258
  - lib/sensu/api/routes/stashes.rb
259
+ - lib/sensu/api/utilities/filter_response_content.rb
258
260
  - lib/sensu/api/utilities/publish_check_request.rb
259
261
  - lib/sensu/api/utilities/publish_check_result.rb
260
262
  - lib/sensu/api/utilities/resolve_event.rb