chef-handler-datadog 0.12.0 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +158 -0
  3. data/.gitignore +0 -1
  4. data/.rubocop.yml +5 -0
  5. data/CHANGELOG.md +35 -1
  6. data/CONTRIBUTING.md +14 -0
  7. data/Gemfile +1 -0
  8. data/Gemfile.lock +296 -0
  9. data/README.md +1 -3
  10. data/chef-handler-datadog.gemspec +10 -10
  11. data/lib/chef/handler/datadog.rb +5 -5
  12. data/lib/chef/handler/datadog_chef_events.rb +3 -0
  13. data/lib/chef/handler/datadog_chef_metrics.rb +1 -1
  14. data/lib/chef/handler/datadog_chef_tags.rb +2 -1
  15. data/lib/chef_handler_datadog.rb +1 -1
  16. data/spec/datadog_spec.rb +198 -166
  17. data/spec/support/cassettes/Chef_Handler_Datadog/failed_Chef_run/sets_alert_handles_when_specified.yml +239 -181
  18. data/spec/support/cassettes/Chef_Handler_Datadog/failed_Chef_run/sets_event_title_correctly.yml +119 -90
  19. data/spec/support/cassettes/Chef_Handler_Datadog/failed_Chef_run/sets_priority_correctly.yml +119 -90
  20. data/spec/support/cassettes/Chef_Handler_Datadog/hostname/uses_the_node_name_when_no_config_specified.yml +119 -89
  21. data/spec/support/cassettes/Chef_Handler_Datadog/hostname/uses_the_specified_hostname_when_provided.yml +119 -89
  22. 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 +119 -89
  23. data/spec/support/cassettes/Chef_Handler_Datadog/reports_correct_hostname_on_an_ec2_node/uses_the_instance_id_when_config_is_specified.yml +119 -89
  24. data/spec/support/cassettes/Chef_Handler_Datadog/reports_correct_hostname_on_an_ec2_node/uses_the_instance_id_when_no_config_specified.yml +119 -89
  25. data/spec/support/cassettes/Chef_Handler_Datadog/reports_metrics_event_and_sets_tags/emits_events/posts_an_event.yml +119 -89
  26. data/spec/support/cassettes/Chef_Handler_Datadog/reports_metrics_event_and_sets_tags/emits_events/sets_priority_correctly.yml +119 -89
  27. data/spec/support/cassettes/Chef_Handler_Datadog/reports_metrics_event_and_sets_tags/emits_metrics/reports_metrics.yml +119 -89
  28. data/spec/support/cassettes/Chef_Handler_Datadog/reports_metrics_event_and_sets_tags/sets_tags/puts_the_tags_for_the_current_node.yml +119 -89
  29. data/spec/support/cassettes/Chef_Handler_Datadog/resources/failure_during_compile_phase/only_emits_the_run_status_metrics.yml +74 -56
  30. data/spec/support/cassettes/Chef_Handler_Datadog/resources/failure_during_compile_phase/posts_an_event.yml +74 -56
  31. data/spec/support/cassettes/Chef_Handler_Datadog/resources/failure_during_compile_phase_with_an_elapsed_time_and_incomplete_resource_collection/only_emits_the_run_status_metrics.yml +73 -55
  32. data/spec/support/cassettes/Chef_Handler_Datadog/resources/failure_during_compile_phase_with_an_elapsed_time_and_incomplete_resource_collection/posts_an_event.yml +73 -55
  33. data/spec/support/cassettes/Chef_Handler_Datadog/tags/when_policy_tags_are_enabled/sets_the_policy_name_and_policy_group_tags.yml +120 -90
  34. data/spec/support/cassettes/Chef_Handler_Datadog/tags/when_policy_tags_are_not_enabled/does_not_set_the_policy_name_and_policy_group_tags.yml +111 -81
  35. data/spec/support/cassettes/Chef_Handler_Datadog/tags/when_specified/allows_for_empty_scope_prefix.yml +119 -90
  36. data/spec/support/cassettes/Chef_Handler_Datadog/tags/when_specified/allows_for_empty_tag_prefix.yml +117 -127
  37. data/spec/support/cassettes/Chef_Handler_Datadog/tags/when_specified/allows_for_user-specified_scope_prefix.yml +119 -90
  38. data/spec/support/cassettes/Chef_Handler_Datadog/tags/when_specified/allows_for_user-specified_tag_prefix.yml +121 -92
  39. data/spec/support/cassettes/Chef_Handler_Datadog/tags/when_specified/sets_the_role_and_env_and_tags.yml +119 -90
  40. data/spec/support/cassettes/Chef_Handler_Datadog/tags/when_tag_blacklist_is_specified/does_not_include_the_tag_s_specified.yml +118 -88
  41. data/spec/support/cassettes/Chef_Handler_Datadog/tags/when_tag_blacklist_is_unspecified/should_include_all_of_the_tag_s_.yml +118 -88
  42. data/spec/support/cassettes/Chef_Handler_Datadog/tags/when_unspecified/sets_role_env_and_nothing_else.yml +119 -90
  43. data/spec/support/cassettes/Chef_Handler_Datadog/tags_submission_retries/when_not_specified/does_not_retry_after_a_failed_submission.yml +112 -124
  44. data/spec/support/cassettes/Chef_Handler_Datadog/tags_submission_retries/when_specified_as_2_retries/retries_no_more_than_twice.yml +108 -210
  45. data/spec/support/cassettes/Chef_Handler_Datadog/tags_submission_retries/when_specified_as_2_retries/stops_retrying_once_submission_is_successful.yml +110 -168
  46. data/spec/support/cassettes/Chef_Handler_Datadog/updated_resources/posts_an_event.yml +119 -89
  47. metadata +9 -21
  48. data/.travis.yml +0 -34
  49. data/gemfiles/chef_12.7.gemfile +0 -16
  50. data/gemfiles/chef_12.gemfile +0 -16
  51. data/gemfiles/chef_13.gemfile +0 -16
  52. data/gemfiles/chef_14.gemfile +0 -16
  53. data/spec/support/cassettes/Chef_Handler_Datadog/handles_no_application_key/fails_when_no_application_key_is_provided.yml +0 -143
  54. data/spec/support/cassettes/Chef_Handler_Datadog/when_reporting_to_multiple_endpoints/emits_events/posts_an_event.yml +0 -575
  55. data/spec/support/cassettes/Chef_Handler_Datadog/when_reporting_to_multiple_endpoints/emits_metrics/reports_metrics.yml +0 -575
  56. data/spec/support/cassettes/Chef_Handler_Datadog/when_reporting_to_multiple_endpoints/sets_tags/puts_the_tags_for_the_current_node.yml +0 -575
data/README.md CHANGED
@@ -3,9 +3,7 @@
3
3
  An Exception and Report Handler for Chef.
4
4
 
5
5
  [![Gem Version](https://badge.fury.io/rb/chef-handler-datadog.svg)](http://badge.fury.io/rb/chef-handler-datadog)
6
- [![Build Status](https://travis-ci.com/DataDog/chef-handler-datadog.svg?branch=master)](https://travis-ci.com/DataDog/chef-handler-datadog)
7
- [![Code Climate](https://codeclimate.com/github/DataDog/chef-handler-datadog/badges/gpa.svg)](https://codeclimate.com/github/DataDog/chef-handler-datadog)
8
- [![Dependency Status](https://gemnasium.com/DataDog/chef-handler-datadog.svg)](https://gemnasium.com/DataDog/chef-handler-datadog)
6
+ [![Build Status](https://img.shields.io/circleci/build/gh/DataDog/chef-handler-datadog.svg)](https://circleci.com/gh/DataDog/chef-handler-datadog)
9
7
 
10
8
  ## Using chef-handler-datadog
11
9
 
@@ -3,19 +3,19 @@
3
3
  require File.expand_path('lib/chef_handler_datadog', __dir__)
4
4
 
5
5
  Gem::Specification.new do |gem|
6
- gem.name = 'chef-handler-datadog'
7
- gem.summary = 'Chef Handler reports events and metrics to Datadog'
8
- gem.description = 'This Handler will report the events and metrics for a chef-client run to Datadog.'
9
- gem.license = 'BSD'
10
- gem.version = ChefHandlerDatadog::VERSION
6
+ gem.name = 'chef-handler-datadog'
7
+ gem.summary = 'Chef Handler reports events and metrics to Datadog'
8
+ gem.description = 'This Handler will report the events and metrics for a chef-client run to Datadog.'
9
+ gem.license = 'BSD'
10
+ gem.version = ChefHandlerDatadog::VERSION
11
11
 
12
- gem.files = `git ls-files`.split($\) # rubocop:disable SpecialGlobalVars
13
- gem.executables = gem.files.grep(%r{^bin\/}).map { |f| File.basename(f) }
14
- gem.test_files = gem.files.grep(%r{^(test|spec|features)\/})
15
- gem.require_paths = ['lib']
12
+ gem.files = `git ls-files`.split($\) # rubocop:disable Style/SpecialGlobalVars
13
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
14
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
+ gem.require_paths = ['lib']
16
16
  gem.extra_rdoc_files = ['README.md', 'LICENSE.txt']
17
17
 
18
- gem.add_dependency 'dogapi', '>= 1.31'
18
+ gem.add_dependency 'dogapi', '~> 1.42.0'
19
19
 
20
20
  gem.add_development_dependency 'appraisal', '~> 2.0.1'
21
21
  gem.add_development_dependency 'bundler'
@@ -78,9 +78,9 @@ class Chef
78
78
  @metrics.emit_to_datadog dog
79
79
  @event.emit_to_datadog dog
80
80
  @tags.send_update_to_datadog dog
81
- rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT => e
82
- Chef::Log.error("Could not connect to Datadog. Connection error:\n" + e)
83
- Chef::Log.error('Data to be submitted was:')
81
+ rescue => e
82
+ Chef::Log.error("Could not send/emit to Datadog:\n" + e.to_s)
83
+ Chef::Log.error('Event data to be submitted was:')
84
84
  Chef::Log.error(@event.event_title)
85
85
  Chef::Log.error(@event.event_body)
86
86
  Chef::Log.error('Tags to be set for this run:')
@@ -134,7 +134,7 @@ class Chef
134
134
  app_key,
135
135
  nil, # host
136
136
  nil, # device
137
- true, # silent
137
+ false, # silent
138
138
  nil, # timeout
139
139
  url
140
140
  ))
@@ -159,7 +159,7 @@ class Chef
159
159
  # then add extra endpoints
160
160
  extra_endpoints = @config[:extra_endpoints] || []
161
161
  extra_endpoints.each do |endpoint|
162
- url = endpoint[:url] || config_url()
162
+ url = endpoint[:api_url] || endpoint[:url] || config_url()
163
163
  api_key = endpoint[:api_key]
164
164
  app_key = endpoint[:application_key]
165
165
  endpoints << [url, api_key, app_key] if validate_keys(api_key, app_key, false)
@@ -10,6 +10,9 @@ require_relative 'datadog_util'
10
10
  class DatadogChefEvents
11
11
  include DatadogUtil
12
12
 
13
+ attr_reader :event_title
14
+ attr_reader :event_body
15
+
13
16
  def initialize
14
17
  @hostname = nil
15
18
  @run_status = nil
@@ -50,6 +50,6 @@ class DatadogChefMetrics
50
50
  rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT => e
51
51
  Chef::Log.warn("Could not send metrics to Datadog. Connection error:\n" + e)
52
52
  rescue StandardError => e
53
- Chef::Log.warn("Could not determine whether chef run metrics were successfully submitted to Datadog: #{evt}. Error:\n#{e}")
53
+ Chef::Log.warn("Could not determine whether chef run metrics were successfully submitted to Datadog. Error:\n#{e}")
54
54
  end
55
55
  end # end class DatadogChefMetrics
@@ -92,6 +92,7 @@ class DatadogChefTags
92
92
  def send_update_to_datadog(dog)
93
93
  tags = combined_host_tags
94
94
  retries = @retries
95
+ rc = []
95
96
  begin
96
97
  loop do
97
98
  should_retry = false
@@ -114,7 +115,7 @@ class DatadogChefTags
114
115
  break unless should_retry
115
116
  end
116
117
  rescue StandardError => e
117
- Chef::Log.warn("Could not determine whether #{@hostname}'s tags were successfully submitted to Datadog: #{rc}. Error:\n#{e}")
118
+ Chef::Log.warn("Could not determine whether #{@hostname}'s tags were successfully submitted to Datadog: #{rc.inspect}. Error:\n#{e}")
118
119
  end
119
120
  end
120
121
 
@@ -2,5 +2,5 @@
2
2
  # Helper module for version number only.
3
3
  # Real deal in 'chef/handler/datadog.rb'
4
4
  module ChefHandlerDatadog
5
- VERSION = '0.12.0'
5
+ VERSION = '0.14.0'
6
6
  end
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
  require 'spec_helper'
3
3
 
4
- describe Chef::Handler::Datadog, :vcr => :new_episodes do
4
+ describe Chef::Handler::Datadog, vcr: :new_episodes do
5
5
  # The #report method currently long and clunky, and we need to simulate a
6
6
  # Chef run to test all aspects of this, as well as push values into the test.
7
7
  before(:all) do
@@ -18,22 +18,31 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
18
18
 
19
19
  before(:each) do
20
20
  @handler = Chef::Handler::Datadog.new(
21
- :api_key => API_KEY,
22
- :application_key => APPLICATION_KEY,
21
+ api_key: API_KEY,
22
+ application_key: APPLICATION_KEY,
23
23
  )
24
24
  end
25
25
 
26
26
  describe 'initialize' do
27
27
  it 'should allow config hash to have string keys' do
28
28
  Chef::Handler::Datadog.new(
29
- 'api_key' => API_KEY,
30
- 'application_key' => APPLICATION_KEY,
31
- 'tag_prefix' => 'tag',
32
- 'scope_prefix' => nil
29
+ api_key: API_KEY,
30
+ application_key: APPLICATION_KEY,
31
+ tag_prefix: 'tag',
32
+ scope_prefix: nil
33
33
  )
34
34
  end
35
+
36
+ it 'should create a Dogapi client for the endpoint' do
37
+ dogs = @handler.instance_variable_get(:@dogs)
38
+
39
+ # Check that we do have a Dogapi client
40
+ expect(dogs.length).to eq(1)
41
+ end
35
42
  end
36
43
 
44
+
45
+
37
46
  describe 'reports metrics event and sets tags' do
38
47
  # Construct a good run_status
39
48
  before(:each) do
@@ -57,7 +66,7 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
57
66
  context 'emits metrics' do
58
67
  it 'reports metrics' do
59
68
  expect(a_request(:post, METRICS_ENDPOINT).with(
60
- :query => { 'api_key' => @handler.config[:api_key] }
69
+ query: { api_key: @handler.config[:api_key] }
61
70
  )).to have_been_made.times(5)
62
71
  end
63
72
  end
@@ -65,17 +74,18 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
65
74
  context 'emits events' do
66
75
  it 'posts an event' do
67
76
  expect(a_request(:post, EVENTS_ENDPOINT).with(
68
- :query => { 'api_key' => @handler.config[:api_key] },
69
- :body => hash_including(:msg_text => 'Chef updated 0 resources out of 0 resources total.'),
70
- :body => hash_including(:msg_title => "Chef completed in 5 seconds on #{@node.name} "),
71
- :body => hash_including(:tags => ['env:testing']),
77
+ query: { api_key: @handler.config[:api_key] },
78
+ body: hash_including(msg_text: 'Chef updated 0 resources out of 0 resources total.',
79
+ msg_title: "Chef completed in 5 seconds on #{@node.name} ",
80
+ tags: ['env:testing']),
72
81
  )).to have_been_made.times(1)
73
82
  end
74
83
 
75
84
  it 'sets priority correctly' do
76
85
  expect(a_request(:post, EVENTS_ENDPOINT).with(
77
- :query => { 'api_key' => @handler.config[:api_key] },
78
- :body => hash_including(:priority => 'low'),
86
+ query: { api_key: @handler.config[:api_key] },
87
+ body: hash_including(alert_type: 'success',
88
+ priority: 'low'),
79
89
  )).to have_been_made.times(1)
80
90
  end
81
91
  end
@@ -85,15 +95,15 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
85
95
  # We no longer need to query the tag api for current tags,
86
96
  # rather udpate only the tags for the designated source type
87
97
  expect(a_request(:get, HOST_TAG_ENDPOINT + @node.name).with(
88
- :query => { 'api_key' => @handler.config[:api_key],
89
- 'application_key' => @handler.config[:application_key] },
98
+ headers: { 'Dd-Api-Key' => @handler.config[:api_key],
99
+ 'Dd-Application-Key' => @handler.config[:application_key] },
90
100
  )).to have_been_made.times(0)
91
101
 
92
102
  expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
93
- :query => { 'api_key' => @handler.config[:api_key],
94
- 'application_key' => @handler.config[:application_key],
95
- 'source' => 'chef' },
96
- :body => { 'tags' => ['env:testing'] },
103
+ headers: { 'Dd-Api-Key' => @handler.config[:api_key],
104
+ 'Dd-Application-Key' => @handler.config[:application_key] },
105
+ query: { source: 'chef' },
106
+ body: { tags: ['env:testing'] },
97
107
  )).to have_been_made.times(1)
98
108
  end
99
109
  end
@@ -104,7 +114,7 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
104
114
  @node = Chef::Node.build('chef.handler.datadog.test-ec2')
105
115
  @node.send(:chef_environment, 'testing')
106
116
 
107
- @node.automatic_attrs['ec2'] = { :instance_id => 'i-123456' }
117
+ @node.automatic_attrs['ec2'] = { instance_id: 'i-123456' }
108
118
 
109
119
  @run_context = Chef::RunContext.new(@node, {}, @events)
110
120
  @run_status = Chef::RunStatus.new(@node, @events)
@@ -119,9 +129,9 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
119
129
  @handler.run_report_unsafe(@run_status)
120
130
 
121
131
  expect(a_request(:post, EVENTS_ENDPOINT).with(
122
- :query => { 'api_key' => @handler.config[:api_key] },
123
- :body => hash_including(:msg_title => 'Chef completed in 5 seconds on i-123456 '),
124
- :body => hash_including(:host => 'i-123456'),
132
+ query: { api_key: @handler.config[:api_key] },
133
+ body: hash_including(msg_title: 'Chef completed in 5 seconds on i-123456 ',
134
+ host: 'i-123456'),
125
135
  )).to have_been_made.times(1)
126
136
  end
127
137
 
@@ -130,9 +140,9 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
130
140
  @handler.run_report_unsafe(@run_status)
131
141
 
132
142
  expect(a_request(:post, EVENTS_ENDPOINT).with(
133
- :query => { 'api_key' => @handler.config[:api_key] },
134
- :body => hash_including(:msg_title => 'Chef completed in 5 seconds on i-123456 '),
135
- :body => hash_including(:host => 'i-123456'),
143
+ query: { api_key: @handler.config[:api_key] },
144
+ body: hash_including(msg_title: 'Chef completed in 5 seconds on i-123456 ',
145
+ host: 'i-123456'),
136
146
  )).to have_been_made.times(1)
137
147
  end
138
148
 
@@ -141,9 +151,9 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
141
151
  @handler.run_report_unsafe(@run_status)
142
152
 
143
153
  expect(a_request(:post, EVENTS_ENDPOINT).with(
144
- :query => { 'api_key' => @handler.config[:api_key] },
145
- :body => hash_including(:msg_title => "Chef completed in 5 seconds on #{@node.name} "),
146
- :body => hash_including(:host => @node.name),
154
+ query: { api_key: @handler.config[:api_key] },
155
+ body: hash_including(msg_title: "Chef completed in 5 seconds on #{@node.name} ",
156
+ host: @node.name),
147
157
  )).to have_been_made.times(1)
148
158
  end
149
159
  end
@@ -166,9 +176,9 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
166
176
  @handler.run_report_unsafe(@run_status)
167
177
 
168
178
  expect(a_request(:post, EVENTS_ENDPOINT).with(
169
- :query => { 'api_key' => @handler.config[:api_key] },
170
- :body => hash_including(:msg_title => "Chef completed in 5 seconds on #{@node.name}"),
171
- :body => hash_including(:host => @node.name),
179
+ query: { api_key: @handler.config[:api_key] },
180
+ body: hash_including(msg_title: "Chef completed in 5 seconds on #{@node.name} ",
181
+ host: @node.name),
172
182
  )).to have_been_made.times(1)
173
183
  end
174
184
 
@@ -177,9 +187,9 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
177
187
  @handler.run_report_unsafe(@run_status)
178
188
 
179
189
  expect(a_request(:post, EVENTS_ENDPOINT).with(
180
- :query => { 'api_key' => @handler.config[:api_key] },
181
- :body => hash_including(:msg_title => 'Chef completed in 5 seconds on my-imaginary-hostname.local'),
182
- :body => hash_including(:host => 'my-imaginary-hostname.local'),
190
+ query: { api_key: @handler.config[:api_key] },
191
+ body: hash_including(msg_title: 'Chef completed in 5 seconds on my-imaginary-hostname.local ',
192
+ host: 'my-imaginary-hostname.local'),
183
193
  )).to have_been_made.times(1)
184
194
  end
185
195
  end
@@ -209,10 +219,10 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
209
219
  @handler.run_report_unsafe(@run_status)
210
220
 
211
221
  expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
212
- :query => { 'api_key' => @handler.config[:api_key],
213
- 'application_key' => @handler.config[:application_key],
214
- 'source' => 'chef' },
215
- :body => hash_including(:tags => [
222
+ headers: { 'Dd-Api-Key' => @handler.config[:api_key],
223
+ 'Dd-Application-Key' => @handler.config[:application_key] },
224
+ query: { source: 'chef' },
225
+ body: hash_including(tags: [
216
226
  'env:hostile', 'role:highlander', 'tag:the_one_and_only', 'tag:datacenter:my-cloud'
217
227
  ]),
218
228
  )).to have_been_made.times(1)
@@ -224,10 +234,10 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
224
234
  @handler.run_report_unsafe(@run_status)
225
235
 
226
236
  expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
227
- :query => { 'api_key' => @handler.config[:api_key],
228
- 'application_key' => @handler.config[:application_key],
229
- 'source' => 'chef' },
230
- :body => hash_including(:tags => [
237
+ headers: { 'Dd-Api-Key' => @handler.config[:api_key],
238
+ 'Dd-Application-Key' => @handler.config[:application_key] },
239
+ query: { source: 'chef' },
240
+ body: hash_including(tags: [
231
241
  'env:hostile', 'role:highlander', 'custom-prefix-the_one_and_only', 'custom-prefix-datacenter:my-cloud'
232
242
  ]),
233
243
  )).to have_been_made.times(1)
@@ -239,10 +249,10 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
239
249
  @handler.run_report_unsafe(@run_status)
240
250
 
241
251
  expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
242
- :query => { 'api_key' => @handler.config[:api_key],
243
- 'application_key' => @handler.config[:application_key],
244
- 'source' => 'chef' },
245
- :body => hash_including(:tags => [
252
+ headers: { 'Dd-Api-Key' => @handler.config[:api_key],
253
+ 'Dd-Application-Key' => @handler.config[:application_key] },
254
+ query: { source: 'chef' },
255
+ body: hash_including(tags: [
246
256
  'env:hostile', 'role:highlander', 'the_one_and_only', 'datacenter:my-cloud'
247
257
  ]),
248
258
  )).to have_been_made.times(1)
@@ -253,10 +263,10 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
253
263
  @handler.run_report_unsafe(@run_status)
254
264
 
255
265
  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 => [
266
+ headers: { 'Dd-Api-Key' => @handler.config[:api_key],
267
+ 'Dd-Application-Key' => @handler.config[:application_key] },
268
+ query: { source: 'chef' },
269
+ body: hash_including(tags: [
260
270
  'custom-prefix-env:hostile', 'custom-prefix-role:highlander'
261
271
  ]),
262
272
  )).to have_been_made.times(1)
@@ -267,10 +277,10 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
267
277
  @handler.run_report_unsafe(@run_status)
268
278
 
269
279
  expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
270
- :query => { 'api_key' => @handler.config[:api_key],
271
- 'application_key' => @handler.config[:application_key],
272
- 'source' => 'chef' },
273
- :body => hash_including(:tags => [
280
+ headers: { 'Dd-Api-Key' => @handler.config[:api_key],
281
+ 'Dd-Application-Key' => @handler.config[:application_key] },
282
+ query: { source: 'chef' },
283
+ body: hash_including(tags: [
274
284
  'env:hostile', 'role:highlander'
275
285
  ]),
276
286
  )).to have_been_made.times(1)
@@ -282,10 +292,10 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
282
292
  @handler.run_report_unsafe(@run_status)
283
293
 
284
294
  expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
285
- :query => { 'api_key' => @handler.config[:api_key],
286
- 'application_key' => @handler.config[:application_key],
287
- 'source' => 'chef' },
288
- :body => hash_including(:tags => [
295
+ headers: { 'Dd-Api-Key' => @handler.config[:api_key],
296
+ 'Dd-Application-Key' => @handler.config[:application_key] },
297
+ query: { source: 'chef' },
298
+ body: hash_including(tags: [
289
299
  'env:hostile', 'role:highlander'
290
300
  ]),
291
301
  )).to have_been_made.times(1)
@@ -299,10 +309,10 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
299
309
  @handler.run_report_unsafe(@run_status)
300
310
 
301
311
  expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
302
- :query => { 'api_key' => @handler.config[:api_key],
303
- 'application_key' => @handler.config[:application_key],
304
- 'source' => 'chef' },
305
- :body => hash_including(:tags => [
312
+ headers: { 'Dd-Api-Key' => @handler.config[:api_key],
313
+ 'Dd-Application-Key' => @handler.config[:application_key] },
314
+ query: { source: 'chef' },
315
+ body: hash_including(tags: [
306
316
  'env:hostile', 'role:highlander', 'tag:allowed_tag'
307
317
  ]),
308
318
  )).to have_been_made.times(1)
@@ -315,10 +325,10 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
315
325
  @handler.run_report_unsafe(@run_status)
316
326
 
317
327
  expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
318
- :query => { 'api_key' => @handler.config[:api_key],
319
- 'application_key' => @handler.config[:application_key],
320
- 'source' => 'chef' },
321
- :body => hash_including(:tags => [
328
+ headers: { 'Dd-Api-Key' => @handler.config[:api_key],
329
+ 'Dd-Application-Key' => @handler.config[:application_key] },
330
+ query: { source: 'chef' },
331
+ body: hash_including(tags: [
322
332
  'env:hostile', 'role:highlander', 'tag:allowed_tag', 'tag:not_allowed_tag'
323
333
  ]),
324
334
  )).to have_been_made.times(1)
@@ -336,10 +346,10 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
336
346
  @handler.run_report_unsafe(@run_status)
337
347
 
338
348
  expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
339
- :query => { 'api_key' => @handler.config[:api_key],
340
- 'application_key' => @handler.config[:application_key],
341
- 'source' => 'chef' },
342
- :body => hash_including(:tags => [
349
+ headers: { 'Dd-Api-Key' => @handler.config[:api_key],
350
+ 'Dd-Application-Key' => @handler.config[:application_key] },
351
+ query: { source: 'chef' },
352
+ body: hash_including(tags: [
343
353
  'env:hostile', 'role:highlander'
344
354
  ]),
345
355
  )).to have_been_made.times(1)
@@ -358,10 +368,10 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
358
368
  @handler.run_report_unsafe(@run_status)
359
369
 
360
370
  expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
361
- :query => { 'api_key' => @handler.config[:api_key],
362
- 'application_key' => @handler.config[:application_key],
363
- 'source' => 'chef' },
364
- :body => hash_including(:tags => [
371
+ headers: { 'Dd-Api-Key' => @handler.config[:api_key],
372
+ 'Dd-Application-Key' => @handler.config[:application_key] },
373
+ query: { source: 'chef' },
374
+ body: hash_including(tags: [
365
375
  'env:hostile', 'role:highlander', 'policy_group:the_policy_group', 'policy_name:the_policy_name'
366
376
  ]),
367
377
  )).to have_been_made.times(1)
@@ -370,6 +380,10 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
370
380
  end
371
381
 
372
382
  context 'tags submission retries' do
383
+ let(:dog) do
384
+ @handler.instance_variable_get(:@dogs)[0]
385
+ end
386
+
373
387
  before(:each) do
374
388
  @node = Chef::Node.build('chef.handler.datadog.test-tags-retries')
375
389
 
@@ -380,7 +394,6 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
380
394
  @events = Chef::EventDispatch::Dispatcher.new
381
395
  @run_context = Chef::RunContext.new(@node, {}, @events)
382
396
  @run_status = Chef::RunStatus.new(@node, @events)
383
-
384
397
  @expected_time = Time.now
385
398
  allow(Time).to receive(:now).and_return(@expected_time, @expected_time + 5)
386
399
  @run_status.start_clock
@@ -397,44 +410,30 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
397
410
  end
398
411
 
399
412
  it 'retries no more than twice' do
400
- @handler.run_report_unsafe(@run_status)
413
+ # Define mock update_tags function which returns the result of an HTTP 404 error
414
+ allow(dog).to receive(:update_tags).and_return([404, 'Not Found'])
401
415
 
402
- expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
403
- :query => { 'api_key' => @handler.config[:api_key],
404
- 'application_key' => @handler.config[:application_key],
405
- 'source' => 'chef' },
406
- :body => hash_including(:tags => [
407
- 'env:hostile', 'role:highlander', 'tag:the_one_and_only'
408
- ]),
409
- )).to have_been_made.times(3)
416
+ expect(dog).to receive(:update_tags).exactly(3).times
417
+ @handler.run_report_unsafe(@run_status)
410
418
  end
411
419
 
412
420
  it 'stops retrying once submission is successful' do
413
- @handler.run_report_unsafe(@run_status)
421
+ # Define mock update_tags function which returns the result of an HTTP 404 error once
422
+ allow(dog).to receive(:update_tags).and_return([404, 'Not Found'], [201, 'Created'])
414
423
 
415
- expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
416
- :query => { 'api_key' => @handler.config[:api_key],
417
- 'application_key' => @handler.config[:application_key],
418
- 'source' => 'chef' },
419
- :body => hash_including(:tags => [
420
- 'env:hostile', 'role:highlander', 'tag:the_one_and_only'
421
- ]),
422
- )).to have_been_made.times(2)
424
+ expect(dog).to receive(:update_tags).exactly(2).times
425
+ @handler.run_report_unsafe(@run_status)
423
426
  end
424
427
  end
425
428
 
426
429
  describe 'when not specified' do
427
- it 'does not retry after a failed submission' do
428
- @handler.run_report_unsafe(@run_status)
430
+ it 'does not retry after a failed submission' do
431
+ # Define mock update_tags function which returns the result of an HTTP 404 error
432
+ allow(dog).to receive(:update_tags).and_return([404, 'Not Found'])
429
433
 
430
- expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
431
- :query => { 'api_key' => @handler.config[:api_key],
432
- 'application_key' => @handler.config[:application_key],
433
- 'source' => 'chef' },
434
- :body => hash_including(:tags => [
435
- 'env:hostile', 'role:highlander', 'tag:the_one_and_only'
436
- ]),
437
- )).to have_been_made.times(1)
434
+
435
+ expect(dog).to receive(:update_tags).exactly(:once)
436
+ @handler.run_report_unsafe(@run_status)
438
437
  end
439
438
  end
440
439
  end
@@ -507,16 +506,16 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
507
506
 
508
507
  it 'sets event title correctly' do
509
508
  expect(a_request(:post, EVENTS_ENDPOINT).with(
510
- :query => { 'api_key' => @handler.config[:api_key] },
511
- :body => hash_including(:msg_title => "Chef failed in 2 seconds on #{@node.name} "),
509
+ query: { api_key: @handler.config[:api_key] },
510
+ body: hash_including(msg_title: "Chef failed in 2 seconds on #{@node.name} "),
512
511
  )).to have_been_made.times(1)
513
512
  end
514
513
 
515
514
  it 'sets priority correctly' do
516
515
  expect(a_request(:post, EVENTS_ENDPOINT).with(
517
- :query => { 'api_key' => @handler.config[:api_key] },
518
- :body => hash_including(:alert_type => 'success'),
519
- :body => hash_including(:priority => 'normal'),
516
+ query: { api_key: @handler.config[:api_key] },
517
+ body: hash_including(alert_type: 'error',
518
+ priority: 'normal'),
520
519
  )).to have_been_made.times(1)
521
520
  end
522
521
 
@@ -525,8 +524,8 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
525
524
  @handler.run_report_unsafe(@run_status)
526
525
 
527
526
  expect(a_request(:post, EVENTS_ENDPOINT).with(
528
- :query => { 'api_key' => @handler.config[:api_key] },
529
- :body => /Alerting: @alice @bob/
527
+ query: { api_key: @handler.config[:api_key] },
528
+ body: /Alerting: @alice @bob/
530
529
  )).to have_been_made.times(1)
531
530
  end
532
531
  end
@@ -556,9 +555,10 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
556
555
 
557
556
  it 'posts an event' do
558
557
  expect(a_request(:post, EVENTS_ENDPOINT).with(
559
- :query => { 'api_key' => @handler.config[:api_key] },
560
- :body => hash_including(:msg_text => 'Chef updated 1 resources out of 2 resources total.'),
561
- :body => hash_including(:msg_title => "Chef completed in 8 seconds on #{@node.name} "),
558
+ query: { api_key: @handler.config[:api_key] },
559
+ # FIXME: msg_text is "\n$$$\n- [whiskers] (dynamically defined)\n\n$$$\n" - is this a bug?
560
+ body: hash_including(#msg_text: 'Chef updated 1 resources out of 2 resources total.',
561
+ msg_title: "Chef completed in 8 seconds on #{@node.name} "),
562
562
  )).to have_been_made.times(1)
563
563
  end
564
564
  end
@@ -578,15 +578,15 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
578
578
 
579
579
  it 'only emits the run status metrics' do
580
580
  expect(a_request(:post, METRICS_ENDPOINT).with(
581
- :query => { 'api_key' => @handler.config[:api_key] }
581
+ query: { api_key: @handler.config[:api_key] }
582
582
  )).to have_been_made.times(2)
583
583
  end
584
584
 
585
585
  it 'posts an event' do
586
586
  expect(a_request(:post, EVENTS_ENDPOINT).with(
587
- :query => { 'api_key' => @handler.config[:api_key] },
588
- :body => hash_including(:msg_text => 'Chef was unable to complete a run, an error during compilation may have occured.'),
589
- :body => hash_including(:msg_title => "Chef failed during compile phase on #{@node.name} "),
587
+ query: { api_key: @handler.config[:api_key] },
588
+ body: hash_including(msg_text: 'Chef was unable to complete a run, an error during compilation may have occurred.',
589
+ msg_title: "Chef failed during compile phase on #{@node.name} "),
590
590
  )).to have_been_made.times(1)
591
591
  end
592
592
  end
@@ -608,15 +608,15 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
608
608
 
609
609
  it 'only emits the run status metrics' do
610
610
  expect(a_request(:post, METRICS_ENDPOINT).with(
611
- :query => { 'api_key' => @handler.config[:api_key] }
611
+ query: { api_key: @handler.config[:api_key] }
612
612
  )).to have_been_made.times(2)
613
613
  end
614
614
 
615
615
  it 'posts an event' do
616
616
  expect(a_request(:post, EVENTS_ENDPOINT).with(
617
- :query => { 'api_key' => @handler.config[:api_key] },
618
- :body => hash_including(:msg_text => 'Chef was unable to complete a run, an error during compilation may have occured.'),
619
- :body => hash_including(:msg_title => "Chef failed during compile phase on #{@node.name} "),
617
+ query: { api_key: @handler.config[:api_key] },
618
+ body: hash_including(msg_text: 'Chef was unable to complete a run, an error during compilation may have occurred.',
619
+ msg_title: "Chef failed during compile phase on #{@node.name} "),
620
620
  )).to have_been_made.times(1)
621
621
  end
622
622
  end
@@ -734,6 +734,31 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
734
734
  expect(handler.send(:endpoints)).to eq(triplets[0..1])
735
735
  end
736
736
  end
737
+
738
+ context 'when using api url instead of url' do
739
+ it 'returns available triplets' do
740
+ triplets = [
741
+ ['https://app.datadoghq.com', 'api_key_2' , 'app_key_2'],
742
+ ['https://app.example.com', 'api_key_3', 'app_key_3'],
743
+ ['https://app.example.com', 'api_key_4', 'app_key_4']
744
+ ]
745
+ handler = Chef::Handler::Datadog.new api_key: triplets[0][1],
746
+ application_key: triplets[0][2],
747
+ url: triplets[0][0],
748
+ extra_endpoints: [{
749
+ api_url: triplets[1][0],
750
+ url: triplets[0][0],
751
+ api_key: triplets[1][1],
752
+ application_key: triplets[1][2]
753
+ }, {
754
+ api_url: triplets[2][0],
755
+ url:triplets[0][0],
756
+ api_key: triplets[2][1],
757
+ application_key: triplets[2][2]
758
+ }]
759
+ expect(handler.send(:endpoints)).to eq(triplets)
760
+ end
761
+ end
737
762
  end
738
763
 
739
764
  context 'when reporting to multiple endpoints' do
@@ -744,17 +769,29 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
744
769
  let(:host_tag_endpoint2) { base_url2 + '/api/v1/tags/hosts/' }
745
770
  let(:metrics_endpoint2) { base_url2 + '/api/v1/series' }
746
771
  let(:handler) do
747
- Chef::Handler::Datadog.new api_key: API_KEY,
748
- application_key: APPLICATION_KEY,
749
- url: BASE_URL,
750
- extra_endpoints: [{
751
- api_key: api_key2,
752
- application_key: application_key2,
753
- url: base_url2
754
- }]
772
+ Chef::Handler::Datadog.new(api_key: API_KEY,
773
+ application_key: APPLICATION_KEY,
774
+ url: BASE_URL,
775
+ extra_endpoints: [{
776
+ api_key: api_key2,
777
+ application_key: application_key2,
778
+ url: base_url2
779
+ }])
780
+ end
781
+
782
+ let(:dogs) do
783
+ handler.instance_variable_get(:@dogs)
755
784
  end
785
+
756
786
  # Construct a good run_status
757
787
  before(:each) do
788
+ dogs.each do |dog|
789
+ # Define mock functions to avoid failures when connecting to the app.example.com endpoint
790
+ allow(dog).to receive(:emit_point).and_return(true)
791
+ allow(dog).to receive(:emit_event).and_return([200, "{'event': 'My event'}"])
792
+ allow(dog).to receive(:update_tags).and_return([201, "Created"])
793
+ end
794
+
758
795
  @node = Chef::Node.build('chef.handler.datadog.test')
759
796
  @node.send(:chef_environment, 'testing')
760
797
  @events = Chef::EventDispatch::Dispatcher.new
@@ -767,56 +804,51 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
767
804
  @run_status.stop_clock
768
805
 
769
806
  @run_status.run_context = @run_context
807
+ end
770
808
 
771
- # Run the report
772
- handler.run_report_unsafe(@run_status)
809
+ it 'should create multiple Dogapi clients' do
810
+ expect(dogs.length).to eq(2)
773
811
  end
774
812
 
775
813
  context 'emits metrics' do
776
- it 'reports metrics' do
777
- expect(a_request(:post, METRICS_ENDPOINT).with(
778
- :query => { 'api_key' => API_KEY }
779
- )).to have_been_made.times(5)
814
+ it 'reports metrics to the first endpoint' do
815
+ expect(dogs[0]).to receive(:emit_point).exactly(5).times
780
816
 
781
- expect(a_request(:post, metrics_endpoint2).with(
782
- :query => { 'api_key' => api_key2 }
783
- )).to have_been_made.times(5)
817
+ handler.run_report_unsafe(@run_status)
818
+ end
819
+
820
+ it 'reports metrics to the second endpoint' do
821
+ expect(dogs[1]).to receive(:emit_point).exactly(5).times
822
+
823
+ handler.run_report_unsafe(@run_status)
784
824
  end
785
825
  end
786
826
 
787
827
  context 'emits events' do
788
- it 'posts an event' do
789
- expect(a_request(:post, EVENTS_ENDPOINT).with(
790
- :query => { 'api_key' => API_KEY },
791
- :body => hash_including(:msg_text => 'Chef updated 0 resources out of 0 resources total.'),
792
- :body => hash_including(:msg_title => "Chef completed in 5 seconds on #{@node.name} "),
793
- :body => hash_including(:tags => ['env:testing']),
794
- )).to have_been_made.times(1)
828
+ it 'posts an event to the first endpoint' do
829
+ expect(dogs[0]).to receive(:emit_event).exactly(:once)
795
830
 
796
- expect(a_request(:post, events_endpoint2).with(
797
- :query => { 'api_key' => api_key2 },
798
- :body => hash_including(:msg_text => 'Chef updated 0 resources out of 0 resources total.'),
799
- :body => hash_including(:msg_title => "Chef completed in 5 seconds on #{@node.name} "),
800
- :body => hash_including(:tags => ['env:testing']),
801
- )).to have_been_made.times(1)
831
+ handler.run_report_unsafe(@run_status)
832
+ end
833
+
834
+ it 'posts an event to the second endpoint' do
835
+ expect(dogs[1]).to receive(:emit_event).exactly(:once)
836
+
837
+ handler.run_report_unsafe(@run_status)
802
838
  end
803
839
  end
804
840
 
805
841
  context 'sets tags' do
806
- it 'puts the tags for the current node' do
807
- expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
808
- :query => { 'api_key' => API_KEY,
809
- 'application_key' => APPLICATION_KEY,
810
- 'source' => 'chef' },
811
- :body => { 'tags' => ['env:testing'] },
812
- )).to have_been_made.times(1)
842
+ it 'puts the tags for the current node on the first endpoint' do
843
+ expect(dogs[0]).to receive(:update_tags).exactly(:once)
813
844
 
814
- expect(a_request(:put, host_tag_endpoint2 + @node.name).with(
815
- :query => { 'api_key' => api_key2,
816
- 'application_key' => application_key2,
817
- 'source' => 'chef' },
818
- :body => { 'tags' => ['env:testing'] },
819
- )).to have_been_made.times(1)
845
+ handler.run_report_unsafe(@run_status)
846
+ end
847
+
848
+ it 'puts the tags for the current node on the second endpoint' do
849
+ expect(dogs[1]).to receive(:update_tags).exactly(:once)
850
+
851
+ handler.run_report_unsafe(@run_status)
820
852
  end
821
853
  end
822
854
  end