interferon 0.2.2 → 0.2.4

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: 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