chef-handler-datadog-demo 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/.env.example +2 -0
  3. data/.gitignore +63 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +44 -0
  6. data/.travis.yml +25 -0
  7. data/Appraisals +16 -0
  8. data/CHANGELOG.md +102 -0
  9. data/CONTRIBUTING.md +23 -0
  10. data/Gemfile +14 -0
  11. data/Guardfile +37 -0
  12. data/LICENSE.txt +20 -0
  13. data/README.md +40 -0
  14. data/Rakefile +23 -0
  15. data/chef-handler-datadog-demo.gemspec +33 -0
  16. data/gemfiles/chef_10.14.4.gemfile +17 -0
  17. data/gemfiles/chef_10.gemfile +16 -0
  18. data/gemfiles/chef_11.gemfile +16 -0
  19. data/gemfiles/chef_12.gemfile +16 -0
  20. data/lib/chef/handler/datadog_demo.rb +123 -0
  21. data/lib/chef/handler/datadog_demo_chef_events.rb +174 -0
  22. data/lib/chef/handler/datadog_demo_chef_metrics.rb +62 -0
  23. data/lib/chef/handler/datadog_demo_chef_tags.rb +140 -0
  24. data/lib/chef_handler_datadog_demo.rb +6 -0
  25. data/spec/datadog_spec.rb +495 -0
  26. data/spec/spec_helper.rb +47 -0
  27. data/spec/support/cassettes/Chef_Handler_Datadog/failed_Chef_run/sets_alert_handles_when_specified.yml +513 -0
  28. data/spec/support/cassettes/Chef_Handler_Datadog/failed_Chef_run/sets_event_title_correctly.yml +258 -0
  29. data/spec/support/cassettes/Chef_Handler_Datadog/failed_Chef_run/sets_priority_correctly.yml +258 -0
  30. data/spec/support/cassettes/Chef_Handler_Datadog/handles_no_application_key/fails_when_no_application_key_is_provided.yml +143 -0
  31. data/spec/support/cassettes/Chef_Handler_Datadog/hostname/uses_the_node_name_when_no_config_specified.yml +250 -0
  32. data/spec/support/cassettes/Chef_Handler_Datadog/hostname/uses_the_specified_hostname_when_provided.yml +250 -0
  33. data/spec/support/cassettes/Chef_Handler_Datadog/reports_correct_hostname_on_an_ec2_node/does_not_use_the_instance_id_when_config_specified_to_false.yml +250 -0
  34. data/spec/support/cassettes/Chef_Handler_Datadog/reports_correct_hostname_on_an_ec2_node/uses_the_instance_id_when_config_is_specified.yml +250 -0
  35. data/spec/support/cassettes/Chef_Handler_Datadog/reports_correct_hostname_on_an_ec2_node/uses_the_instance_id_when_no_config_specified.yml +250 -0
  36. data/spec/support/cassettes/Chef_Handler_Datadog/reports_metrics_event_and_sets_tags/emits_events/posts_an_event.yml +250 -0
  37. data/spec/support/cassettes/Chef_Handler_Datadog/reports_metrics_event_and_sets_tags/emits_events/sets_priority_correctly.yml +250 -0
  38. data/spec/support/cassettes/Chef_Handler_Datadog/reports_metrics_event_and_sets_tags/emits_metrics/reports_metrics.yml +250 -0
  39. data/spec/support/cassettes/Chef_Handler_Datadog/reports_metrics_event_and_sets_tags/sets_tags/puts_the_tags_for_the_current_node.yml +250 -0
  40. data/spec/support/cassettes/Chef_Handler_Datadog/resources/failure_during_compile_phase/does_not_emit_metrics.yml +82 -0
  41. data/spec/support/cassettes/Chef_Handler_Datadog/resources/failure_during_compile_phase/only_emits_a_failure_metric.yml +134 -0
  42. data/spec/support/cassettes/Chef_Handler_Datadog/resources/failure_during_compile_phase/posts_an_event.yml +134 -0
  43. data/spec/support/cassettes/Chef_Handler_Datadog/tags/when_specified/allows_for_empty_tag_prefix.yml +251 -0
  44. data/spec/support/cassettes/Chef_Handler_Datadog/tags/when_specified/allows_for_user-specified_tag_prefix.yml +251 -0
  45. data/spec/support/cassettes/Chef_Handler_Datadog/tags/when_specified/sets_the_role_and_env_and_tags.yml +251 -0
  46. data/spec/support/cassettes/Chef_Handler_Datadog/tags/when_unspecified/sets_role_env_and_nothing_else.yml +251 -0
  47. data/spec/support/cassettes/Chef_Handler_Datadog/tags_submission_retries/when_not_specified/does_not_retry_after_a_failed_submission.yml +241 -0
  48. data/spec/support/cassettes/Chef_Handler_Datadog/tags_submission_retries/when_specified_as_2_retries/retries_no_more_than_twice.yml +331 -0
  49. data/spec/support/cassettes/Chef_Handler_Datadog/tags_submission_retries/when_specified_as_2_retries/stops_retrying_once_submission_is_successful.yml +287 -0
  50. data/spec/support/cassettes/Chef_Handler_Datadog/updated_resources/posts_an_event.yml +250 -0
  51. metadata +285 -0
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+ # Helper module for version number only.
3
+ # Real deal in 'chef/handler/datadog.rb'
4
+ module ChefHandlerDatadogDemo
5
+ VERSION = '0.1.0'
6
+ end
@@ -0,0 +1,495 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe Chef::Handler::Datadog, :vcr => :new_episodes do
5
+ # The #report method currently long and clunky, and we need to simulate a
6
+ # Chef run to test all aspects of this, as well as push values into the test.
7
+ before(:all) do
8
+ # This is used in validating that requests have actually been made,
9
+ # as in a 'Fucntional test'. We've recorded the tests with VCR, and use
10
+ # these to assert that the final product is correct. This is also
11
+ # exercising the API client, which may be helpful as well.
12
+ # There is a fair amount of duplication in the repsonse returned.
13
+ BASE_URL = 'https://app.datadoghq.com'
14
+ EVENTS_ENDPOINT = BASE_URL + '/api/v1/events'
15
+ HOST_TAG_ENDPOINT = BASE_URL + '/api/v1/tags/hosts/'
16
+ METRICS_ENDPOINT = BASE_URL + '/api/v1/series'
17
+ end
18
+
19
+ before(:each) do
20
+ @handler = Chef::Handler::Datadog.new(
21
+ :api_key => API_KEY,
22
+ :application_key => APPLICATION_KEY,
23
+ )
24
+ end
25
+
26
+ describe 'initialize' do
27
+ it 'should allow config hash to have string keys' do
28
+ Chef::Handler::Datadog.new(
29
+ 'api_key' => API_KEY,
30
+ 'application_key' => APPLICATION_KEY,
31
+ 'tag_prefix' => 'tag',
32
+ )
33
+ end
34
+ end
35
+
36
+ describe 'reports metrics event and sets tags' do
37
+ # Construct a good run_status
38
+ before(:each) do
39
+ @node = Chef::Node.build('chef.handler.datadog.test')
40
+ @node.send(:chef_environment, 'testing')
41
+ @events = Chef::EventDispatch::Dispatcher.new
42
+ @run_context = Chef::RunContext.new(@node, {}, @events)
43
+ @run_status = Chef::RunStatus.new(@node, @events)
44
+
45
+ @expected_time = Time.now
46
+ allow(Time).to receive(:now).and_return(@expected_time, @expected_time + 5)
47
+ @run_status.start_clock
48
+ @run_status.stop_clock
49
+
50
+ @run_status.run_context = @run_context
51
+
52
+ # Run the report
53
+ @handler.run_report_unsafe(@run_status)
54
+ end
55
+
56
+ context 'emits metrics' do
57
+ it 'reports metrics' do
58
+ expect(a_request(:post, METRICS_ENDPOINT).with(
59
+ :query => { 'api_key' => @handler.config[:api_key] }
60
+ )).to have_been_made.times(4)
61
+ end
62
+ end
63
+
64
+ context 'emits events' do
65
+ it 'posts an event' do
66
+ expect(a_request(:post, EVENTS_ENDPOINT).with(
67
+ :query => { 'api_key' => @handler.config[:api_key] },
68
+ :body => hash_including(:msg_text => 'Chef updated 0 resources out of 0 resources total.'),
69
+ :body => hash_including(:msg_title => "Chef completed in 5 seconds on #{@node.name} "),
70
+ :body => hash_including(:tags => ['env:testing']),
71
+ )).to have_been_made.times(1)
72
+ end
73
+
74
+ it 'sets priority correctly' do
75
+ expect(a_request(:post, EVENTS_ENDPOINT).with(
76
+ :query => { 'api_key' => @handler.config[:api_key] },
77
+ :body => hash_including(:priority => 'low'),
78
+ )).to have_been_made.times(1)
79
+ end
80
+ end
81
+
82
+ context 'sets tags' do
83
+ it 'puts the tags for the current node' do
84
+ # We no longer need to query the tag api for current tags,
85
+ # rather udpate only the tags for the designated source type
86
+ expect(a_request(:get, HOST_TAG_ENDPOINT + @node.name).with(
87
+ :query => { 'api_key' => @handler.config[:api_key],
88
+ 'application_key' => @handler.config[:application_key] },
89
+ )).to have_been_made.times(0)
90
+
91
+ expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
92
+ :query => { 'api_key' => @handler.config[:api_key],
93
+ 'application_key' => @handler.config[:application_key],
94
+ 'source' => 'chef' },
95
+ :body => { 'tags' => ['env:testing'] },
96
+ )).to have_been_made.times(1)
97
+ end
98
+ end
99
+ end
100
+
101
+ describe 'reports correct hostname on an ec2 node' do
102
+ before(:each) do
103
+ @node = Chef::Node.build('chef.handler.datadog.test-ec2')
104
+ @node.send(:chef_environment, 'testing')
105
+
106
+ @node.automatic_attrs['ec2'] = { :instance_id => 'i-123456' }
107
+
108
+ @run_context = Chef::RunContext.new(@node, {}, @events)
109
+ @run_status = Chef::RunStatus.new(@node, @events)
110
+ @expected_time = Time.now
111
+ allow(Time).to receive(:now).and_return(@expected_time, @expected_time + 5)
112
+ @run_status.start_clock
113
+ @run_status.stop_clock
114
+ @run_status.run_context = @run_context
115
+ end
116
+
117
+ it 'uses the instance id when no config specified' do
118
+ @handler.run_report_unsafe(@run_status)
119
+
120
+ expect(a_request(:post, EVENTS_ENDPOINT).with(
121
+ :query => { 'api_key' => @handler.config[:api_key] },
122
+ :body => hash_including(:msg_title => 'Chef completed in 5 seconds on i-123456 '),
123
+ :body => hash_including(:host => 'i-123456'),
124
+ )).to have_been_made.times(1)
125
+ end
126
+
127
+ it 'uses the instance id when config is specified' do
128
+ @handler.config[:use_ec2_instance_id] = true
129
+ @handler.run_report_unsafe(@run_status)
130
+
131
+ expect(a_request(:post, EVENTS_ENDPOINT).with(
132
+ :query => { 'api_key' => @handler.config[:api_key] },
133
+ :body => hash_including(:msg_title => 'Chef completed in 5 seconds on i-123456 '),
134
+ :body => hash_including(:host => 'i-123456'),
135
+ )).to have_been_made.times(1)
136
+ end
137
+
138
+ it 'does not use the instance id when config specified to false' do
139
+ @handler.config[:use_ec2_instance_id] = false
140
+ @handler.run_report_unsafe(@run_status)
141
+
142
+ expect(a_request(:post, EVENTS_ENDPOINT).with(
143
+ :query => { 'api_key' => @handler.config[:api_key] },
144
+ :body => hash_including(:msg_title => "Chef completed in 5 seconds on #{@node.name} "),
145
+ :body => hash_including(:host => @node.name),
146
+ )).to have_been_made.times(1)
147
+ end
148
+ end
149
+
150
+ context 'hostname' do
151
+ before(:each) do
152
+ @node = Chef::Node.build('chef.handler.datadog.test-hostname')
153
+ @node.send(:chef_environment, 'testing')
154
+
155
+ @run_context = Chef::RunContext.new(@node, {}, @events)
156
+ @run_status = Chef::RunStatus.new(@node, @events)
157
+ @expected_time = Time.now
158
+ allow(Time).to receive(:now).and_return(@expected_time, @expected_time + 5)
159
+ @run_status.start_clock
160
+ @run_status.stop_clock
161
+ @run_status.run_context = @run_context
162
+ end
163
+
164
+ it 'uses the node.name when no config specified' do
165
+ @handler.run_report_unsafe(@run_status)
166
+
167
+ expect(a_request(:post, EVENTS_ENDPOINT).with(
168
+ :query => { 'api_key' => @handler.config[:api_key] },
169
+ :body => hash_including(:msg_title => "Chef completed in 5 seconds on #{@node.name}"),
170
+ :body => hash_including(:host => @node.name),
171
+ )).to have_been_made.times(1)
172
+ end
173
+
174
+ it 'uses the specified hostname when provided' do
175
+ @handler.config[:hostname] = 'my-imaginary-hostname.local'
176
+ @handler.run_report_unsafe(@run_status)
177
+
178
+ expect(a_request(:post, EVENTS_ENDPOINT).with(
179
+ :query => { 'api_key' => @handler.config[:api_key] },
180
+ :body => hash_including(:msg_title => 'Chef completed in 5 seconds on my-imaginary-hostname.local'),
181
+ :body => hash_including(:host => 'my-imaginary-hostname.local'),
182
+ )).to have_been_made.times(1)
183
+ end
184
+ end
185
+
186
+ context 'tags' do
187
+ before(:each) do
188
+ @node = Chef::Node.build('chef.handler.datadog.test-tags')
189
+
190
+ @node.send(:chef_environment, 'hostile')
191
+ @node.send(:run_list, 'role[highlander]')
192
+
193
+ @events = Chef::EventDispatch::Dispatcher.new
194
+ @run_context = Chef::RunContext.new(@node, {}, @events)
195
+ @run_status = Chef::RunStatus.new(@node, @events)
196
+
197
+ @expected_time = Time.now
198
+ allow(Time).to receive(:now).and_return(@expected_time, @expected_time + 5)
199
+ @run_status.start_clock
200
+ @run_status.stop_clock
201
+
202
+ @run_status.run_context = @run_context
203
+ end
204
+
205
+ describe 'when specified' do
206
+ it 'sets the role and env and tags' do
207
+ @node.normal.tags = ['the_one_and_only', 'datacenter:my-cloud']
208
+ @handler.run_report_unsafe(@run_status)
209
+
210
+ expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
211
+ :query => { 'api_key' => @handler.config[:api_key],
212
+ 'application_key' => @handler.config[:application_key],
213
+ 'source' => 'chef' },
214
+ :body => hash_including(:tags => [
215
+ 'env:hostile', 'role:highlander', 'tag:the_one_and_only', 'tag:datacenter:my-cloud'
216
+ ]),
217
+ )).to have_been_made.times(1)
218
+ end
219
+
220
+ it 'allows for user-specified tag prefix' do
221
+ @node.normal.tags = ['the_one_and_only', 'datacenter:my-cloud']
222
+ @handler.config[:tag_prefix] = 'custom-prefix-'
223
+ @handler.run_report_unsafe(@run_status)
224
+
225
+ expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
226
+ :query => { 'api_key' => @handler.config[:api_key],
227
+ 'application_key' => @handler.config[:application_key],
228
+ 'source' => 'chef' },
229
+ :body => hash_including(:tags => [
230
+ 'env:hostile', 'role:highlander', 'custom-prefix-the_one_and_only', 'custom-prefix-datacenter:my-cloud'
231
+ ]),
232
+ )).to have_been_made.times(1)
233
+ end
234
+
235
+ it 'allows for empty tag prefix' do
236
+ @node.normal.tags = ['the_one_and_only', 'datacenter:my-cloud']
237
+ @handler.config[:tag_prefix] = ''
238
+ @handler.run_report_unsafe(@run_status)
239
+
240
+ expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
241
+ :query => { 'api_key' => @handler.config[:api_key],
242
+ 'application_key' => @handler.config[:application_key],
243
+ 'source' => 'chef' },
244
+ :body => hash_including(:tags => [
245
+ 'env:hostile', 'role:highlander', 'the_one_and_only', 'datacenter:my-cloud'
246
+ ]),
247
+ )).to have_been_made.times(1)
248
+ end
249
+ end
250
+
251
+ describe 'when unspecified' do
252
+ it 'sets role, env and nothing else' do
253
+ @handler.run_report_unsafe(@run_status)
254
+
255
+ expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
256
+ :query => { 'api_key' => @handler.config[:api_key],
257
+ 'application_key' => @handler.config[:application_key],
258
+ 'source' => 'chef' },
259
+ :body => hash_including(:tags => [
260
+ 'env:hostile', 'role:highlander'
261
+ ]),
262
+ )).to have_been_made.times(1)
263
+ end
264
+ end
265
+ end
266
+
267
+ context 'tags submission retries' do
268
+ before(:each) do
269
+ @node = Chef::Node.build('chef.handler.datadog.test-tags-retries')
270
+
271
+ @node.send(:chef_environment, 'hostile')
272
+ @node.send(:run_list, 'role[highlander]')
273
+ @node.normal.tags = ['the_one_and_only']
274
+
275
+ @events = Chef::EventDispatch::Dispatcher.new
276
+ @run_context = Chef::RunContext.new(@node, {}, @events)
277
+ @run_status = Chef::RunStatus.new(@node, @events)
278
+
279
+ @expected_time = Time.now
280
+ allow(Time).to receive(:now).and_return(@expected_time, @expected_time + 5)
281
+ @run_status.start_clock
282
+ @run_status.stop_clock
283
+
284
+ @run_status.run_context = @run_context
285
+ end
286
+
287
+ describe 'when specified as 2 retries' do
288
+ before(:each) do
289
+ @handler.config[:tags_submission_retries] = 2
290
+ # Stub `sleep` to avoid slowing down the execution
291
+ allow_any_instance_of(DatadogChefTags).to receive(:sleep)
292
+ end
293
+
294
+ it 'retries no more than twice' do
295
+ @handler.run_report_unsafe(@run_status)
296
+
297
+ expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
298
+ :query => { 'api_key' => @handler.config[:api_key],
299
+ 'application_key' => @handler.config[:application_key],
300
+ 'source' => 'chef' },
301
+ :body => hash_including(:tags => [
302
+ 'env:hostile', 'role:highlander', 'tag:the_one_and_only'
303
+ ]),
304
+ )).to have_been_made.times(3)
305
+ end
306
+
307
+ it 'stops retrying once submission is successful' do
308
+ @handler.run_report_unsafe(@run_status)
309
+
310
+ expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
311
+ :query => { 'api_key' => @handler.config[:api_key],
312
+ 'application_key' => @handler.config[:application_key],
313
+ 'source' => 'chef' },
314
+ :body => hash_including(:tags => [
315
+ 'env:hostile', 'role:highlander', 'tag:the_one_and_only'
316
+ ]),
317
+ )).to have_been_made.times(2)
318
+ end
319
+ end
320
+
321
+ describe 'when not specified' do
322
+ it 'does not retry after a failed submission' do
323
+ @handler.run_report_unsafe(@run_status)
324
+
325
+ expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
326
+ :query => { 'api_key' => @handler.config[:api_key],
327
+ 'application_key' => @handler.config[:application_key],
328
+ 'source' => 'chef' },
329
+ :body => hash_including(:tags => [
330
+ 'env:hostile', 'role:highlander', 'tag:the_one_and_only'
331
+ ]),
332
+ )).to have_been_made.times(1)
333
+ end
334
+ end
335
+ end
336
+
337
+ describe 'handles no application_key' do
338
+ before(:each) do
339
+ @node = Chef::Node.build('chef.handler.datadog.test-noapp')
340
+
341
+ @node.send(:chef_environment, 'hostile')
342
+ @node.send(:run_list, 'role[highlander]')
343
+ @node.normal.tags = ['the_one_and_only']
344
+
345
+ @events = Chef::EventDispatch::Dispatcher.new
346
+ @run_context = Chef::RunContext.new(@node, {}, @events)
347
+ @run_status = Chef::RunStatus.new(@node, @events)
348
+
349
+ @expected_time = Time.now
350
+ allow(Time).to receive(:now).and_return(@expected_time, @expected_time + 5)
351
+ @run_status.start_clock
352
+ @run_status.stop_clock
353
+
354
+ @run_status.run_context = @run_context
355
+ end
356
+
357
+ it 'fails when no application key is provided' do
358
+ @handler.config[:application_key] = nil
359
+
360
+ # TODO: figure out how to capture output of Chef::Log
361
+ # Run the report, catch the error
362
+ expect { @handler.run_report_unsafe(@run_status) }.to raise_error
363
+ end
364
+ end
365
+
366
+ describe 'failed Chef run' do
367
+ before(:each) do
368
+ @node = Chef::Node.build('chef.handler.datadog.test-failed')
369
+
370
+ @node.send(:chef_environment, 'hostile')
371
+ @node.send(:run_list, 'role[highlander]')
372
+ @node.normal.tags = ['the_one_and_only']
373
+
374
+ @events = Chef::EventDispatch::Dispatcher.new
375
+ @run_context = Chef::RunContext.new(@node, {}, @events)
376
+ @run_status = Chef::RunStatus.new(@node, @events)
377
+
378
+ all_resources = [
379
+ Chef::Resource.new('whiskers'),
380
+ Chef::Resource.new('paws'),
381
+ Chef::Resource.new('ears'),
382
+ Chef::Resource.new('nose'),
383
+ Chef::Resource.new('tail'),
384
+ Chef::Resource.new('fur')
385
+ ]
386
+ all_resources.map { |r| r.updated_by_last_action(true) }
387
+ @run_context.resource_collection.all_resources.replace(all_resources)
388
+
389
+ @expected_time = Time.now
390
+ allow(Time).to receive(:now).and_return(@expected_time, @expected_time + 2)
391
+ @run_status.start_clock
392
+ @run_status.stop_clock
393
+
394
+ @run_status.run_context = @run_context
395
+
396
+ # Construct an exception
397
+ exception = Chef::Exceptions::UnsupportedAction.new('Something awry.')
398
+ exception.set_backtrace(['whiskers.rb:2', 'paws.rb:1', 'file.rb:2', 'file.rb:1'])
399
+ @run_status.exception = exception
400
+
401
+ # Run the report
402
+ @handler.run_report_unsafe(@run_status)
403
+ end
404
+
405
+ it 'sets event title correctly' do
406
+ expect(a_request(:post, EVENTS_ENDPOINT).with(
407
+ :query => { 'api_key' => @handler.config[:api_key] },
408
+ :body => hash_including(:msg_title => "Chef failed in 2 seconds on #{@node.name} "),
409
+ )).to have_been_made.times(1)
410
+ end
411
+
412
+ it 'sets priority correctly' do
413
+ expect(a_request(:post, EVENTS_ENDPOINT).with(
414
+ :query => { 'api_key' => @handler.config[:api_key] },
415
+ :body => hash_including(:alert_type => 'success'),
416
+ :body => hash_including(:priority => 'normal'),
417
+ )).to have_been_made.times(1)
418
+ end
419
+
420
+ it 'sets alert handles when specified' do
421
+ @handler.config[:notify_on_failure] = ['@alice', '@bob']
422
+ @handler.run_report_unsafe(@run_status)
423
+
424
+ expect(a_request(:post, EVENTS_ENDPOINT).with(
425
+ :query => { 'api_key' => @handler.config[:api_key] },
426
+ :body => /Alerting: @alice @bob/
427
+ )).to have_been_made.times(1)
428
+ end
429
+ end
430
+
431
+ describe 'updated resources' do
432
+ before(:each) do
433
+ @node = Chef::Node.build('chef.handler.datadog.test-resources')
434
+ @node.send(:chef_environment, 'resources')
435
+ @events = Chef::EventDispatch::Dispatcher.new
436
+ @run_context = Chef::RunContext.new(@node, {}, @events)
437
+ @run_status = Chef::RunStatus.new(@node, @events)
438
+
439
+ all_resources = [Chef::Resource.new('whiskers'), Chef::Resource.new('paws')]
440
+ all_resources.first.updated_by_last_action(true)
441
+ @run_context.resource_collection.all_resources.replace(all_resources)
442
+
443
+ @expected_time = Time.now
444
+ allow(Time).to receive(:now).and_return(@expected_time, @expected_time + 8)
445
+ @run_status.start_clock
446
+ @run_status.stop_clock
447
+
448
+ @run_status.run_context = @run_context
449
+
450
+ # Run the report
451
+ @handler.run_report_unsafe(@run_status)
452
+ end
453
+
454
+ it 'posts an event' do
455
+ expect(a_request(:post, EVENTS_ENDPOINT).with(
456
+ :query => { 'api_key' => @handler.config[:api_key] },
457
+ :body => hash_including(:msg_text => 'Chef updated 1 resources out of 2 resources total.'),
458
+ :body => hash_including(:msg_title => "Chef completed in 8 seconds on #{@node.name} "),
459
+ )).to have_been_made.times(1)
460
+ end
461
+ end
462
+
463
+ describe 'resources' do
464
+ before(:each) do
465
+ @node = Chef::Node.build('chef.handler.datadog.test-resources')
466
+ @node.send(:chef_environment, 'resources')
467
+ @events = Chef::EventDispatch::Dispatcher.new
468
+ @run_context = Chef::RunContext.new(@node, {}, @events)
469
+ @run_status = Chef::RunStatus.new(@node, @events)
470
+ end
471
+
472
+ context 'failure during compile phase' do
473
+ before(:each) do
474
+ @handler.run_report_unsafe(@run_status)
475
+ end
476
+
477
+ it 'only emits a failure metric' do
478
+ expect(a_request(:post, METRICS_ENDPOINT).with(
479
+ :query => { 'api_key' => @handler.config[:api_key] }
480
+ )).to have_been_made.times(1)
481
+ end
482
+
483
+ it 'posts an event' do
484
+ expect(a_request(:post, EVENTS_ENDPOINT).with(
485
+ :query => { 'api_key' => @handler.config[:api_key] },
486
+ :body => hash_including(:msg_text => 'Chef was unable to complete a run, an error during compilation may have occured.'),
487
+ :body => hash_including(:msg_title => "Chef failed during compile phase on #{@node.name} "),
488
+ )).to have_been_made.times(1)
489
+ end
490
+ end
491
+ end
492
+
493
+ # TODO: test failures:
494
+ # @run_status.exception = Exception.new('Boy howdy!')
495
+ end