interferon 0.2.2 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b94afa9f628189dc66075b34239930dcfa60fa37
4
- data.tar.gz: 2d566d59b5c4ac62784c359925df1e74f7711fb5
3
+ metadata.gz: e832b3eccfa9cec75b1e26dba0384209817c3e7e
4
+ data.tar.gz: 7d3673b1f98c3109f5a2b389c20cf91f6d5ddfe5
5
5
  SHA512:
6
- metadata.gz: 5f458bfc7b930b91519e1b94098ba92eac52e2c0c4af9b63493d77e9230b8b787e2be63a89e0a0af7f5bc5b0edb07284dbbe1a037bf1a72914e0af32ab870730
7
- data.tar.gz: 0c875b39a8df08c93588a8ea3c4726df280eb6d93a5f8e808ce58404859d6d71a22e130c5587f4412c183815be63069103d3e6a12cce85e02008f63e2f361a65
6
+ metadata.gz: 84ad9260f477f30a7711a7807f3f09df804a43c77493d931febbc9eb98d888441370046f3a7093c78b863b22ec625bd4eeec1c8241376710828fb7c85df591ea
7
+ data.tar.gz: 3fd09fa405794191e7398297511ae86e7f5d63255adf9828088351955aa339a058780801cdb3108672fed97dbb8ebf936b5db7e7866b9d3e636404cb88841330
data/.travis.yml CHANGED
@@ -2,6 +2,9 @@
2
2
  language: ruby
3
3
  sudo: false
4
4
  cache: bundler
5
+ # Update bundler before proceeding
6
+ # Travis CI uses an old version that may cause a bunch of errors
7
+ before_install: gem install bundler
5
8
  script:
6
9
  - bundle exec rspec
7
10
  - bundle exec rubocop
data/config.example.yaml CHANGED
@@ -36,3 +36,4 @@ destinations:
36
36
  app_key: "fillmein"
37
37
  api_key: "alsomissing"
38
38
  api_timeout: 15
39
+ max_mute_minutes: 20160 # 14 days
@@ -29,12 +29,6 @@ module Interferon
29
29
  @dsl.name(name)
30
30
  end
31
31
 
32
- def silence
33
- raise 'This alert has not yet been evaluated' unless @dsl
34
-
35
- @dsl.silenced(true)
36
- end
37
-
38
32
  def [](attr)
39
33
  raise 'This alert has not yet been evaluated' unless @dsl
40
34
 
@@ -126,6 +126,10 @@ module Interferon
126
126
  def recovery(v = nil, &block)
127
127
  get_or_set(:@recovery, v, block, true)
128
128
  end
129
+
130
+ def include_tags(v = nil, &block)
131
+ get_or_set(:@include_tags, v, block, nil)
132
+ end
129
133
  end
130
134
 
131
135
  class MetricDSL
@@ -37,6 +37,7 @@ module Interferon::Destinations
37
37
  @dog = Dogapi::Client.new(*args)
38
38
 
39
39
  @existing_alerts = nil
40
+ @max_mute_minutes = options['max_mute_minutes']
40
41
  @dry_run = options['dry_run']
41
42
 
42
43
  # Datadog communication threads
@@ -154,6 +155,10 @@ module Interferon::Destinations
154
155
  timeout_h: alert['timeout_h'],
155
156
  }
156
157
 
158
+ unless alert['notify']['include_tags'].nil?
159
+ alert_options[:include_tags] = alert['notify']['include_tags']
160
+ end
161
+
157
162
  unless alert['evaluation_delay'].nil?
158
163
  alert_options[:evaluation_delay] = alert['evaluation_delay']
159
164
  end
@@ -271,9 +276,15 @@ EOM
271
276
  monitor_options
272
277
  )
273
278
 
274
- # Unmute existing alerts that have been unsilenced.
279
+ # Unmute existing alerts that exceed the max silenced time
275
280
  # Datadog does not allow updates to silencing via the update_alert API call.
276
- if !existing_alert['options']['silenced'].empty? && alert_options[:silenced].empty?
281
+ silenced = existing_alert['options']['silenced']
282
+ if !@max_mute_minutes.nil?
283
+ silenced = silenced.values.reject do |t|
284
+ t.nil? || t == '*' || t > Time.now.to_i + @max_mute_minutes * 60
285
+ end
286
+ @dog.unmute_monitor(id) if alert_options[:silenced].empty? && silenced.empty?
287
+ elsif alert_options[:silenced].empty? && !silenced.empty?
277
288
  @dog.unmute_monitor(id)
278
289
  end
279
290
  else
@@ -338,6 +349,7 @@ EOM
338
349
  query: alert_api_json['query'].strip,
339
350
  message: alert_api_json['message'].strip,
340
351
  evaluation_delay: alert_api_json['options']['evaluation_delay'],
352
+ include_tags: alert_api_json['options']['include_tags'],
341
353
  notify_no_data: alert_api_json['options']['notify_no_data'],
342
354
  notify_audit: alert_api_json['options']['notify_audit'],
343
355
  no_data_timeframe: alert_api_json['options']['no_data_timeframe'],
@@ -355,6 +367,7 @@ EOM
355
367
  notify_recovery: alert['notify']['recovery']
356
368
  ).strip,
357
369
  evaluation_delay: alert['evaluation_delay'],
370
+ include_tags: alert['notify']['include_tags'],
358
371
  notify_no_data: alert['notify_no_data'],
359
372
  notify_audit: alert['notify']['audit'],
360
373
  no_data_timeframe: alert['no_data_timeframe'],
@@ -1,3 +1,3 @@
1
1
  module Interferon
2
- VERSION = '0.2.2'.freeze
2
+ VERSION = '0.2.4'.freeze
3
3
  end
data/lib/interferon.rb CHANGED
@@ -148,7 +148,7 @@ module Interferon
148
148
  def update_alerts(destinations, hosts, alerts, groups)
149
149
  alerts_queue, alert_errors = build_alerts_queue(hosts, alerts, groups)
150
150
  if @dry_run && !alert_errors.empty?
151
- erroneous_alert_files = alerts_errors.map(&:to_s).join(', ')
151
+ erroneous_alert_files = alert_errors.map(&:to_s).join(', ')
152
152
  raise "Alerts failed to apply or evaluate for all hosts: #{erroneous_alert_files}"
153
153
  end
154
154
 
@@ -3,19 +3,27 @@ require 'interferon/destinations/datadog'
3
3
 
4
4
  describe Interferon::Destinations::Datadog do
5
5
  let(:retries) { 3 }
6
- let(:datadog) do
7
- Interferon::Destinations::Datadog.new(
6
+ let(:max_mute_minutes) { 60 }
7
+ let(:base_datadog_config) do
8
+ {
8
9
  'api_key' => 'TEST_API_KEY',
9
10
  'app_key' => 'TEST_APP_KEY',
10
- 'retries' => retries
11
+ 'retries' => retries,
12
+ }
13
+ end
14
+ let(:datadog) do
15
+ Interferon::Destinations::Datadog.new(
16
+ base_datadog_config
11
17
  )
12
18
  end
13
19
  let(:datadog_dry_run) do
14
20
  Interferon::Destinations::Datadog.new(
15
- 'api_key' => 'TEST_API_KEY',
16
- 'app_key' => 'TEST_APP_KEY',
17
- 'retries' => retries,
18
- 'dry_run' => true
21
+ base_datadog_config.merge('dry_run' => true)
22
+ )
23
+ end
24
+ let(:datadog_max_mute) do
25
+ Interferon::Destinations::Datadog.new(
26
+ base_datadog_config.merge('max_mute_minutes' => max_mute_minutes)
19
27
  )
20
28
  end
21
29
  let(:mock_alert_id) { 123 }
@@ -80,7 +88,7 @@ describe Interferon::Destinations::Datadog do
80
88
  datadog.create_alert(mock_alert, mock_people)
81
89
  end
82
90
 
83
- it 'calls dogapi to unmute when exiting alert is muted' do
91
+ it 'calls dogapi to unmute when existing alert is muted' do
84
92
  expect_any_instance_of(Dogapi::Client).to receive(:update_monitor).and_return([200, ''])
85
93
  expect_any_instance_of(Dogapi::Client).to receive(:unmute_monitor).and_return([200, ''])
86
94
  mock_response['Test Alert']['options']['silenced'] = { '*' => nil }
@@ -88,6 +96,26 @@ describe Interferon::Destinations::Datadog do
88
96
  datadog.create_alert(mock_alert, mock_people)
89
97
  end
90
98
 
99
+ it 'calls dogapi to unmute when existing mute exceed max_mute_minutes' do
100
+ expect_any_instance_of(Dogapi::Client).to receive(:update_monitor).and_return([200, ''])
101
+ expect_any_instance_of(Dogapi::Client).to receive(:unmute_monitor).and_return([200, ''])
102
+ mock_response['Test Alert']['options']['silenced'] = {
103
+ '*' => Time.now.to_i + max_mute_minutes * 60 + 10,
104
+ }
105
+ expect(datadog_max_mute).to receive(:existing_alerts).and_return(mock_response)
106
+ datadog_max_mute.create_alert(mock_alert, mock_people)
107
+ end
108
+
109
+ it 'calls dogapi to keep mute when existing mute does not exceed max_mute_minutes' do
110
+ expect_any_instance_of(Dogapi::Client).to receive(:update_monitor).and_return([200, ''])
111
+ expect_any_instance_of(Dogapi::Client).not_to receive(:unmute_monitor)
112
+ mock_response['Test Alert']['options']['silenced'] = {
113
+ '*' => Time.now.to_i + max_mute_minutes * 60 - 10,
114
+ }
115
+ expect(datadog_max_mute).to receive(:existing_alerts).and_return(mock_response)
116
+ datadog_max_mute.create_alert(mock_alert, mock_people)
117
+ end
118
+
91
119
  it 'calls validate monitor in dry-run' do
92
120
  expect_any_instance_of(Dogapi::Client).to receive(:validate_monitor).and_return([200, ''])
93
121
  expect(datadog_dry_run).to receive(:existing_alerts).and_return(mock_response)
@@ -8,62 +8,107 @@ describe Interferon::Destinations::Datadog do
8
8
  let(:the_existing_alerts) { mock_existing_alerts }
9
9
  let(:dest) { MockDest.new(the_existing_alerts) }
10
10
 
11
- context 'when checking alerts have changed' do
11
+ shared_examples_for 'alert_option' do |alert_option, same_value, different_value, alert_dsl|
12
+ let(:json_message) { 'message' + "\n#{Interferon::Destinations::Datadog::ALERT_KEY}" }
13
+ let(:alert) do
14
+ alert_dsl_path = alert_dsl.nil? ? alert_option : alert_dsl
15
+ create_test_alert('name1', 'testquery', 'message', alert_dsl_path => same_value)
16
+ end
17
+ let(:alert_same) do
18
+ mock_alert_json(
19
+ 'name2', 'testquery', json_message, 'metric alert', [1], alert_option => same_value
20
+ )
21
+ end
22
+ let(:alert_diff) do
23
+ mock_alert_json(
24
+ 'name2', 'testquery', json_message, 'metric_alert', [1], alert_option => different_value
25
+ )
26
+ end
27
+
28
+ context 'when the options are the same' do
29
+ it 'should return true' do
30
+ expect(Interferon::Destinations::Datadog.same_alerts(alert, [], alert_same)).to be true
31
+ end
32
+ end
33
+
34
+ context 'when the options are the different' do
35
+ it 'should return false' do
36
+ expect(Interferon::Destinations::Datadog.same_alerts(alert, [], alert_diff)).to be false
37
+ end
38
+ end
39
+ end
40
+
41
+ describe '#same_alerts' do
42
+ let(:json_message) { 'message' + "\n#{Interferon::Destinations::Datadog::ALERT_KEY}" }
43
+
44
+ it 'detects a no change if alert message is the same' do
45
+ alert1 = create_test_alert('name1', 'testquery', 'message')
46
+ alert2 = mock_alert_json('name2', 'testquery', json_message)
47
+
48
+ expect(Interferon::Destinations::Datadog.same_alerts(alert1, [], alert2)).to be true
49
+ end
50
+
12
51
  it 'detects a change if alert message is different' do
13
- alert1 = create_test_alert('name1', 'testquery', 'message1')
14
- alert2 = mock_alert_json('name2', 'testquery', 'message2')
52
+ alert1 = create_test_alert('name1', 'testquery', 'message2')
53
+ alert2 = mock_alert_json('name2', 'testquery', json_message)
15
54
 
16
55
  expect(Interferon::Destinations::Datadog.same_alerts(alert1, [], alert2)).to be false
17
56
  end
18
57
 
19
- it 'detects a change if datadog query is different' do
20
- alert1 = create_test_alert('name1', 'testquery1', 'message1')
21
- alert2 = mock_alert_json('name2', 'testquery2', 'message2')
58
+ it 'detects no change if datadog query is the same' do
59
+ alert1 = create_test_alert('name1', 'testquery', 'message')
60
+ alert2 = mock_alert_json('name2', 'testquery', json_message)
22
61
 
23
- expect(Interferon::Destinations::Datadog.same_alerts(alert1, [], alert2)).to be false
62
+ expect(Interferon::Destinations::Datadog.same_alerts(alert1, [], alert2)).to be true
24
63
  end
25
64
 
26
- it 'detects a change if alert notify_no_data is different' do
27
- alert1 = create_test_alert('name1', 'testquery1', 'message1', notify_no_data: false)
28
- alert2 = mock_alert_json('name2', 'testquery2', 'message2', nil, [1], notify_no_data: true)
65
+ it 'detects a change if datadog query is different' do
66
+ alert1 = create_test_alert('name1', 'testquery1', 'message')
67
+ alert2 = mock_alert_json('name2', 'testquery2', json_message)
29
68
 
30
69
  expect(Interferon::Destinations::Datadog.same_alerts(alert1, [], alert2)).to be false
31
70
  end
32
71
 
33
- it 'detects a change if alert silenced is different' do
34
- alert1 = create_test_alert('name1', 'testquery1', 'message1', silenced: true)
35
- alert2 = mock_alert_json('name2', 'testquery2', 'message2', nil, [1], silenced: {})
72
+ context 'notify_no_data option' do
73
+ it_behaves_like('alert_option', 'notify_no_data', true, false)
74
+ end
36
75
 
37
- expect(Interferon::Destinations::Datadog.same_alerts(alert1, [], alert2)).to be false
76
+ context 'silenced option' do
77
+ it_behaves_like('alert_option', 'silenced', { 'silenced' => '*' }, false)
38
78
  end
39
79
 
40
- it 'detects a change if alert no_data_timeframe is different' do
41
- alert1 = create_test_alert('name1', 'testquery1', 'message1', no_data_timeframe: nil)
42
- alert2 = mock_alert_json('name2', 'testquery2', 'message2', nil, [1], no_data_timeframe: 60)
80
+ context 'no_data_timeframe option' do
81
+ it_behaves_like('alert_option', 'no_data_timeframe', nil, 60)
82
+ end
43
83
 
44
- expect(Interferon::Destinations::Datadog.same_alerts(alert1, [], alert2)).to be false
84
+ context 'require_full_window option' do
85
+ it_behaves_like('alert_option', 'require_full_window', false, true)
45
86
  end
46
87
 
47
- it 'detects a change if alert require_full_window is different' do
48
- alert1 = create_test_alert('name1', 'testquery1', 'message1', require_full_window: false)
49
- alert2 = mock_alert_json(
50
- 'name2', 'testquery2', 'message2', nil, [1], require_full_window: true
51
- )
88
+ context 'evaluation_delay option' do
89
+ it_behaves_like('alert_option', 'evaluation_delay', nil, 300)
90
+ end
52
91
 
53
- expect(Interferon::Destinations::Datadog.same_alerts(alert1, [], alert2)).to be false
92
+ context 'thresholds option' do
93
+ it_behaves_like('alert_option', 'thresholds', nil, 'critical' => 1)
54
94
  end
55
95
 
56
- it 'detects a change if alert evaluation_delay is different' do
57
- alert1 = create_test_alert('name1', 'testquery1', 'message1', evaluation_delay: nil)
58
- alert2 = mock_alert_json('name2', 'testquery2', 'message2', nil, [1], evaluation_delay: 300)
96
+ context 'timeout_h option' do
97
+ it_behaves_like('alert_option', 'timeout_h', nil, 300)
98
+ end
59
99
 
60
- expect(Interferon::Destinations::Datadog.same_alerts(alert1, [], alert2)).to be false
100
+ context 'include_tags option' do
101
+ it_behaves_like('alert_option', 'include_tags', true, false, 'notify' => 'include_tags')
61
102
  end
62
103
 
63
- it 'does not detect a change when alert datadog query and message are the same' do
64
- alert1 = create_test_alert('name1', 'testquery1', 'message1')
104
+ context 'notify_audit option' do
105
+ it_behaves_like('alert_option', 'notify_audit', true, false, 'notify' => 'audit')
106
+ end
107
+
108
+ it 'detects no change if alert silenced is true compared to wildcard hash' do
109
+ alert1 = create_test_alert('name1', 'testquery', 'message', 'silenced' => true)
65
110
  alert2 = mock_alert_json(
66
- 'name1', 'testquery1', "message1\nThis alert was created via the alerts framework"
111
+ 'name2', 'testquery', json_message, 'metric alert', [1], 'silenced' => { '*' => nil }
67
112
  )
68
113
 
69
114
  expect(Interferon::Destinations::Datadog.same_alerts(alert1, [], alert2)).to be true
@@ -271,7 +316,6 @@ describe Interferon::Destinations::Datadog do
271
316
 
272
317
  def mock_alert_json(name, datadog_query, message, type = 'metric alert', id = nil, options = {})
273
318
  options = DEFAULT_OPTIONS.merge(options)
274
-
275
319
  {
276
320
  'name' => name,
277
321
  'query' => datadog_query,
@@ -302,6 +346,9 @@ describe Interferon::Destinations::Datadog do
302
346
 
303
347
  notify_dsl = NotifyDSL.new({})
304
348
  notify_dsl.groups(['a'])
349
+ notify_dsl.audit(options['notify' => 'audit'])
350
+ notify_dsl.include_tags(options['notify' => 'include_tags'])
351
+
305
352
  alert_dsl.instance_variable_set(:@notify, notify_dsl)
306
353
 
307
354
  alert_dsl.name(name)
data/spec/spec_helper.rb CHANGED
@@ -35,7 +35,7 @@ RSpec.configure do |config|
35
35
 
36
36
  # This setting enables warnings. It's recommended, but in some cases may
37
37
  # be too noisy due to issues in dependencies.
38
- config.warnings = true
38
+ config.warnings = false
39
39
 
40
40
  # Many RSpec users commonly either run the entire suite or an individual
41
41
  # file, and it's useful to allow more verbose output when running an
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: interferon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Igor Serebryany
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-09-18 00:00:00.000000000 Z
12
+ date: 2017-09-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: dogapi