sensu 0.23.3-java → 0.24.0.beta-java

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: 9f197ec03894f0815699318f4128a805ac1a9441
4
- data.tar.gz: 3964f6784af42fcf1f5084f386f776b850602eb1
3
+ metadata.gz: 922e2887ce2fcb1972a0faa2b87534d2f96ac910
4
+ data.tar.gz: 6123658a2f976bbbd9f9e9997625927e7eaae47f
5
5
  SHA512:
6
- metadata.gz: 5d5d12a58075b3be711fe37ee87f05c87c54909c81bb90fc6cc9e26db6d2dac107097e5ce87e7d7ff284c3a6c8f297dd2e15ae33d707b0a2aa27d86cccdd35b4
7
- data.tar.gz: a9414e45ee80bc22632b470eb464e3a312716b10774003406d14453f548a25fc3420db3a44f6090b31bf16b22018e26c04107cef722cd79b764d1ab3f0bf92b5
6
+ metadata.gz: 2b03d9bb20ba265a82404a19e8d6b9e6a8b6b39e3a893cf8ff154a662dd9da4d24910f4a5c9cb3d3342d9633856659d3deae50a6191fa4530a0d91f25a1409af
7
+ data.tar.gz: d41d20ee9937d8fe7c2f74a4927472c5c3daf743264ccf253231f14129733dd83f54c88c7a387b9224d83719a2f13d8e96708295e8db33678bd0163d6994027c
data/CHANGELOG.md CHANGED
@@ -1,3 +1,61 @@
1
+ ## 0.24.0 - TBD
2
+
3
+ ### Important
4
+
5
+ Sensu check ["Aggregates 2.0"](https://github.com/sensu/sensu/issues/1218)
6
+ breaks the existing Sensu API aggregate endpoints.
7
+
8
+ Sensu API GET /health endpoint, failed health checks now respond with a
9
+ `412` (preconditions failed) instead of a `503`.
10
+
11
+ ### Features
12
+
13
+ Persistent Sensu event IDs, event occurrences for a client/check pair will
14
+ now have the same event ID until the event is resolved.
15
+
16
+ Added a CLI option/argument to cause the Sensu service to validate its
17
+ compiled configuration settings and exit with the appropriate exit
18
+ code, e.g. `2` for invalid. The CLI option is `--validate_config`. This
19
+ feature is now used when restarting a Sensu service to first validate the
20
+ new configuration before stopping the running service.
21
+
22
+ Improved tracking of in progress check result processing, no longer
23
+ potentially losing check results when restarting the Sensu server service.
24
+
25
+ Event data check type now explicitly defaults to "standard".
26
+
27
+ Check results for proxy clients (a.k.a JIT clients) will now have a check
28
+ "origin" set to the client name of the result producer.
29
+
30
+ Configurable Sensu Spawn concurrent child process limit (checks, mutators,
31
+ & pipe handlers). The default limit is still `12` and the EventMachine
32
+ threadpool size is automatically adjusted to accommodate a larger limit.
33
+
34
+ Sensu check ["Aggregates 2.0"](https://github.com/sensu/sensu/issues/1218).
35
+
36
+ Sensu client token substitution is now supported in every check definition
37
+ attribute value, no longer just the check command.
38
+
39
+ ### Other
40
+
41
+ Sensu API GET /health endpoint, failed health check now responds with a
42
+ `412` (preconditions failed) instead of a `503`.
43
+
44
+ Sensu API POST /clients endpoint can now create clients in the registry
45
+ that are expected to produce keepalives, and validates clients with the
46
+ Sensu Settings client definition validator.
47
+
48
+ Updated Thin (used by Sensu API) to the latest version, 1.6.4.
49
+
50
+ JrJackson is now used to parse JSON when Sensu is running on JRuby.
51
+
52
+ The Sensu API now listens immediately on service start, even before it has
53
+ successfully connected to Redis and the Sensu Transport. It will now
54
+ respond with a `500` response, with a descriptive error message, when it
55
+ has not yet initialized its connections or it is reconnecting to either
56
+ Redis or the Sensu Transport. The API /info and /health endpoints will
57
+ still respond normally while reconnecting.
58
+
1
59
  ## 0.23.3 - 2016-05-26
2
60
 
3
61
  ### Fixes
@@ -1,10 +1,11 @@
1
1
  require "sensu/daemon"
2
+ require "sensu/api/validators"
2
3
 
3
4
  gem "sinatra", "1.4.6"
4
5
  gem "async_sinatra", "1.2.0"
5
6
 
6
7
  unless RUBY_PLATFORM =~ /java/
7
- gem "thin", "1.6.3"
8
+ gem "thin", "1.6.4"
8
9
  require "thin"
9
10
  end
10
11
 
@@ -22,10 +23,9 @@ module Sensu
22
23
  bootstrap(options)
23
24
  setup_process(options)
24
25
  EM::run do
25
- setup_connections do
26
- start
27
- setup_signal_traps
28
- end
26
+ setup_connections
27
+ start
28
+ setup_signal_traps
29
29
  end
30
30
  end
31
31
 
@@ -84,8 +84,8 @@ module Sensu
84
84
  def stop
85
85
  @logger.warn("stopping")
86
86
  stop_server do
87
- settings.redis.close if settings.redis
88
- settings.transport.close if settings.transport
87
+ settings.redis.close if settings.respond_to?(:redis)
88
+ settings.transport.close if settings.respond_to?(:transport)
89
89
  super
90
90
  end
91
91
  end
@@ -124,11 +124,18 @@ module Sensu
124
124
  env["rack.input"].rewind
125
125
  end
126
126
 
127
- def protected!
128
- if settings.api[:user] && settings.api[:password]
129
- return if !(settings.api[:user] && settings.api[:password]) || authorized?
130
- headers["WWW-Authenticate"] = 'Basic realm="Restricted Area"'
131
- unauthorized!
127
+ def connected?
128
+ if settings.respond_to?(:redis) && settings.respond_to?(:transport)
129
+ unless ["/info", "/health"].include?(env["REQUEST_PATH"])
130
+ unless settings.redis.connected?
131
+ not_connected!("not connected to redis")
132
+ end
133
+ unless settings.transport.connected?
134
+ not_connected!("not connected to transport")
135
+ end
136
+ end
137
+ else
138
+ not_connected!("redis and transport connections not initialized")
132
139
  end
133
140
  end
134
141
 
@@ -140,6 +147,22 @@ module Sensu
140
147
  @auth.credentials == [settings.api[:user], settings.api[:password]]
141
148
  end
142
149
 
150
+ def protected!
151
+ if settings.api[:user] && settings.api[:password]
152
+ return if authorized?
153
+ headers["WWW-Authenticate"] = 'Basic realm="Restricted Area"'
154
+ unauthorized!
155
+ end
156
+ end
157
+
158
+ def error!(body="")
159
+ throw(:halt, [500, body])
160
+ end
161
+
162
+ def not_connected!(message)
163
+ error!(Sensu::JSON.dump(:error => message))
164
+ end
165
+
143
166
  def bad_request!
144
167
  ahalt 400
145
168
  end
@@ -152,8 +175,8 @@ module Sensu
152
175
  ahalt 404
153
176
  end
154
177
 
155
- def unavailable!
156
- ahalt 503
178
+ def precondition_failed!
179
+ ahalt 412
157
180
  end
158
181
 
159
182
  def created!(response)
@@ -306,6 +329,7 @@ module Sensu
306
329
  settings.cors.each do |header, value|
307
330
  headers["Access-Control-Allow-#{header}"] = value
308
331
  end
332
+ connected?
309
333
  protected! unless env["REQUEST_METHOD"] == "OPTIONS"
310
334
  end
311
335
 
@@ -342,27 +366,27 @@ module Sensu
342
366
  healthy << (info[:keepalives][:messages] <= max_messages)
343
367
  healthy << (info[:results][:messages] <= max_messages)
344
368
  end
345
- healthy.all? ? no_content! : unavailable!
369
+ healthy.all? ? no_content! : precondition_failed!
346
370
  end
347
371
  else
348
- unavailable!
372
+ precondition_failed!
349
373
  end
350
374
  end
351
375
 
352
376
  apost "/clients/?" do
353
- rules = {
354
- :name => {:type => String, :nil_ok => false, :regex => /\A[\w\.-]+\z/},
355
- :address => {:type => String, :nil_ok => false},
356
- :subscriptions => {:type => Array, :nil_ok => false}
357
- }
358
- read_data(rules) do |data|
359
- data[:keepalives] = false
377
+ read_data do |data|
378
+ data[:keepalives] = data.fetch(:keepalives, false)
360
379
  data[:version] = VERSION
361
380
  data[:timestamp] = Time.now.to_i
362
- settings.redis.set("client:#{data[:name]}", Sensu::JSON.dump(data)) do
363
- settings.redis.sadd("clients", data[:name]) do
364
- created!(Sensu::JSON.dump(:name => data[:name]))
381
+ validator = Validators::Client.new
382
+ if validator.valid?(data)
383
+ settings.redis.set("client:#{data[:name]}", Sensu::JSON.dump(data)) do
384
+ settings.redis.sadd("clients", data[:name]) do
385
+ created!(Sensu::JSON.dump(:name => data[:name]))
386
+ end
365
387
  end
388
+ else
389
+ bad_request!
366
390
  end
367
391
  end
368
392
  end
@@ -582,102 +606,172 @@ module Sensu
582
606
  end
583
607
 
584
608
  aget "/aggregates/?" do
585
- response = Array.new
586
- settings.redis.smembers("aggregates") do |checks|
587
- unless checks.empty?
588
- checks.each_with_index do |check_name, index|
589
- settings.redis.smembers("aggregates:#{check_name}") do |aggregates|
590
- aggregates.reverse!
591
- aggregates.map! do |issued|
592
- issued.to_i
609
+ settings.redis.smembers("aggregates") do |aggregates|
610
+ aggregates.map! do |aggregate|
611
+ {:name => aggregate}
612
+ end
613
+ body Sensu::JSON.dump(aggregates)
614
+ end
615
+ end
616
+
617
+ aget %r{^/aggregates/([\w\.-]+)/?$} do |aggregate|
618
+ response = {
619
+ :clients => 0,
620
+ :checks => 0,
621
+ :results => {
622
+ :ok => 0,
623
+ :warning => 0,
624
+ :critical => 0,
625
+ :unknown => 0,
626
+ :total => 0,
627
+ :stale => 0
628
+ }
629
+ }
630
+ settings.redis.smembers("aggregates:#{aggregate}") do |aggregate_members|
631
+ unless aggregate_members.empty?
632
+ clients = []
633
+ checks = []
634
+ results = []
635
+ aggregate_members.each_with_index do |member, index|
636
+ client_name, check_name = member.split(":")
637
+ clients << client_name
638
+ checks << check_name
639
+ result_key = "result:#{client_name}:#{check_name}"
640
+ settings.redis.get(result_key) do |result_json|
641
+ unless result_json.nil?
642
+ results << Sensu::JSON.load(result_json)
643
+ else
644
+ settings.redis.srem("aggregates:#{aggregate}", member)
593
645
  end
594
- item = {
595
- :check => check_name,
596
- :issued => aggregates
597
- }
598
- response << item
599
- if index == checks.length - 1
646
+ if index == aggregate_members.length - 1
647
+ response[:clients] = clients.uniq.length
648
+ response[:checks] = checks.uniq.length
649
+ max_age = integer_parameter(params[:max_age])
650
+ if max_age
651
+ result_count = results.length
652
+ timestamp = Time.now.to_i - max_age
653
+ results.reject! do |result|
654
+ result[:executed] < timestamp
655
+ end
656
+ response[:results][:stale] = result_count - results.length
657
+ end
658
+ response[:results][:total] = results.length
659
+ results.each do |result|
660
+ severity = (SEVERITIES[result[:status]] || "unknown")
661
+ response[:results][severity.to_sym] += 1
662
+ end
600
663
  body Sensu::JSON.dump(response)
601
664
  end
602
665
  end
603
666
  end
604
667
  else
605
- body Sensu::JSON.dump(response)
668
+ not_found!
606
669
  end
607
670
  end
608
671
  end
609
672
 
610
- aget %r{^/aggregates/([\w\.-]+)/?$} do |check_name|
611
- settings.redis.smembers("aggregates:#{check_name}") do |aggregates|
612
- unless aggregates.empty?
613
- aggregates.reverse!
614
- aggregates.map! do |issued|
615
- issued.to_i
616
- end
617
- age = integer_parameter(params[:age])
618
- if age
619
- timestamp = Time.now.to_i - age
620
- aggregates.reject! do |issued|
621
- issued > timestamp
673
+ adelete %r{^/aggregates/([\w\.-]+)/?$} do |aggregate|
674
+ settings.redis.smembers("aggregates") do |aggregates|
675
+ if aggregates.include?(aggregate)
676
+ settings.redis.srem("aggregates", aggregate) do
677
+ settings.redis.del("aggregates:#{aggregate}") do
678
+ no_content!
622
679
  end
623
680
  end
624
- body Sensu::JSON.dump(pagination(aggregates))
625
681
  else
626
682
  not_found!
627
683
  end
628
684
  end
629
685
  end
630
686
 
631
- adelete %r{^/aggregates/([\w\.-]+)/?$} do |check_name|
632
- settings.redis.smembers("aggregates:#{check_name}") do |aggregates|
633
- unless aggregates.empty?
634
- aggregates.each do |check_issued|
635
- result_set = "#{check_name}:#{check_issued}"
636
- settings.redis.del("aggregation:#{result_set}")
637
- settings.redis.del("aggregate:#{result_set}")
687
+ aget %r{^/aggregates/([\w\.-]+)/clients/?$} do |aggregate|
688
+ response = Array.new
689
+ settings.redis.smembers("aggregates:#{aggregate}") do |aggregate_members|
690
+ unless aggregate_members.empty?
691
+ clients = Hash.new
692
+ aggregate_members.each do |member|
693
+ client_name, check_name = member.split(":")
694
+ clients[client_name] ||= []
695
+ clients[client_name] << check_name
638
696
  end
639
- settings.redis.del("aggregates:#{check_name}") do
640
- settings.redis.srem("aggregates", check_name) do
641
- no_content!
642
- end
697
+ clients.each do |client_name, checks|
698
+ response << {
699
+ :name => client_name,
700
+ :checks => checks
701
+ }
643
702
  end
703
+ body Sensu::JSON.dump(response)
644
704
  else
645
705
  not_found!
646
706
  end
647
707
  end
648
708
  end
649
709
 
650
- aget %r{^/aggregates?/([\w\.-]+)/([\w\.-]+)/?$} do |check_name, check_issued|
651
- result_set = "#{check_name}:#{check_issued}"
652
- settings.redis.hgetall("aggregate:#{result_set}") do |aggregate|
653
- unless aggregate.empty?
654
- response = aggregate.inject(Hash.new) do |totals, (status, count)|
655
- totals[status] = Integer(count)
656
- totals
710
+ aget %r{^/aggregates/([\w\.-]+)/checks/?$} do |aggregate|
711
+ response = Array.new
712
+ settings.redis.smembers("aggregates:#{aggregate}") do |aggregate_members|
713
+ unless aggregate_members.empty?
714
+ checks = Hash.new
715
+ aggregate_members.each do |member|
716
+ client_name, check_name = member.split(":")
717
+ checks[check_name] ||= []
718
+ checks[check_name] << client_name
657
719
  end
658
- settings.redis.hgetall("aggregation:#{result_set}") do |results|
659
- parsed_results = results.inject(Array.new) do |parsed, (client_name, check_json)|
660
- check = Sensu::JSON.load(check_json)
661
- parsed << check.merge(:client => client_name)
662
- end
663
- if params[:summarize]
664
- options = params[:summarize].split(",")
665
- if options.include?("output")
666
- outputs = Hash.new(0)
667
- parsed_results.each do |result|
668
- outputs[result[:output]] += 1
720
+ checks.each do |check_name, clients|
721
+ response << {
722
+ :name => check_name,
723
+ :clients => clients
724
+ }
725
+ end
726
+ body Sensu::JSON.dump(response)
727
+ else
728
+ not_found!
729
+ end
730
+ end
731
+ end
732
+
733
+ aget %r{^/aggregates/([\w\.-]+)/results/([\w\.-]+)/?$} do |aggregate, severity|
734
+ response = Array.new
735
+ if SEVERITIES.include?(severity)
736
+ settings.redis.smembers("aggregates:#{aggregate}") do |aggregate_members|
737
+ unless aggregate_members.empty?
738
+ summaries = Hash.new
739
+ max_age = integer_parameter(params[:max_age])
740
+ current_timestamp = Time.now.to_i
741
+ aggregate_members.each_with_index do |member, index|
742
+ client_name, check_name = member.split(":")
743
+ result_key = "result:#{client_name}:#{check_name}"
744
+ settings.redis.get(result_key) do |result_json|
745
+ unless result_json.nil?
746
+ result = Sensu::JSON.load(result_json)
747
+ if SEVERITIES[result[:status]] == severity &&
748
+ (max_age.nil? || result[:executed] >= (current_timestamp - max_age))
749
+ summaries[check_name] ||= {}
750
+ summaries[check_name][result[:output]] ||= {:total => 0, :clients => []}
751
+ summaries[check_name][result[:output]][:total] += 1
752
+ summaries[check_name][result[:output]][:clients] << client_name
753
+ end
754
+ end
755
+ if index == aggregate_members.length - 1
756
+ summaries.each do |check_name, outputs|
757
+ summary = outputs.map do |output, output_summary|
758
+ {:output => output}.merge(output_summary)
759
+ end
760
+ response << {
761
+ :check => check_name,
762
+ :summary => summary
763
+ }
764
+ end
765
+ body Sensu::JSON.dump(response)
669
766
  end
670
- response[:outputs] = outputs
671
767
  end
672
768
  end
673
- if params[:results]
674
- response[:results] = parsed_results
675
- end
676
- body Sensu::JSON.dump(response)
769
+ else
770
+ not_found!
677
771
  end
678
- else
679
- not_found!
680
772
  end
773
+ else
774
+ bad_request!
681
775
  end
682
776
  end
683
777