chef-handler-datadog 0.6.0 → 0.7.0

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.
@@ -0,0 +1,174 @@
1
+ # encoding: utf-8
2
+ require 'rubygems'
3
+ require 'chef/handler'
4
+ require 'chef/mash'
5
+ require 'dogapi'
6
+
7
+ # helper class for sending events about chef runs
8
+ class DatadogChefEvents
9
+ def initialize
10
+ @dog = nil
11
+ @hostname = nil
12
+ @run_status = nil
13
+ @failure_notfications = nil
14
+
15
+ @alert_type = ''
16
+ @event_priority = ''
17
+ @event_title = ''
18
+ # TODO: refactor how event_body is constructed in the class methods
19
+ # handling of the event_body is a bit clunky and depends on the order of
20
+ # method calls
21
+ @event_body = ''
22
+ end
23
+
24
+ # set the dogapi client handle
25
+ #
26
+ # @param dogapi_client [Dogapi::Client] datadog api client handle
27
+ # @return [DatadogChefTags] instance reference to self enabling method chaining
28
+ def with_dogapi_client(dogapi_client)
29
+ @dog = dogapi_client
30
+ self
31
+ end
32
+
33
+ # set the target hostname (chef node name)
34
+ #
35
+ # @param hostname [String] hostname to use for the handler report
36
+ # @return [DatadogChefTags] instance reference to self enabling method chaining
37
+ def with_hostname(hostname)
38
+ @hostname = hostname
39
+ self
40
+ end
41
+
42
+ # set the chef run status used for the report
43
+ #
44
+ # @param run_status [Chef::RunStatus] current chef run status
45
+ # @return [DatadogChefTags] instance reference to self enabling method chaining
46
+ def with_run_status(run_status)
47
+ @run_status = run_status
48
+ self
49
+ end
50
+
51
+ # set the failure notification list
52
+ #
53
+ # @param failure_notifications [Array] set of datadog notification handles
54
+ # @return [DatadogChefTags] instance reference to self enabling method chaining
55
+ def with_failure_notifications(failure_notifications)
56
+ @failure_notifications = failure_notifications
57
+ self
58
+ end
59
+
60
+ # set the datadog host tags associated with the event
61
+ #
62
+ # @param [Array] the set of host tags
63
+ # @return [DatadogChefTags] instance reference to self enabling method chaining
64
+ def with_tags(tags)
65
+ @tags = tags
66
+ self
67
+ end
68
+
69
+ # Emit Chef event to Datadog
70
+ def emit_to_datadog
71
+ @event_body = ''
72
+ build_event_data
73
+ evt = @dog.emit_event(Dogapi::Event.new(@event_body,
74
+ msg_title: @event_title,
75
+ event_type: 'config_management.run',
76
+ event_object: @hostname,
77
+ alert_type: @alert_type,
78
+ priority: @event_priority,
79
+ source_type_name: 'chef',
80
+ tags: @tags
81
+ ), host: @hostname)
82
+
83
+ begin
84
+ # FIXME: nice-to-have: abstract format of return value away a bit
85
+ # in dogapi directly. See https://github.com/DataDog/dogapi-rb/issues/18
86
+ if evt.length < 2
87
+ Chef::Log.warn("Unexpected response from Datadog Event API: #{evt}")
88
+ else
89
+ # [http_response_code, {"event" => {"url" => "...", ...}}]
90
+ # 2xx means ok
91
+ if evt[0].to_i / 100 != 2
92
+ Chef::Log.warn("Could not submit event to Datadog (HTTP call failed): #{evt[0]}")
93
+ else
94
+ Chef::Log.debug("Successfully submitted Chef event to Datadog for #{@hostname} at #{evt[1]['event']['url']}")
95
+ end
96
+ end
97
+ rescue
98
+ Chef::Log.warn("Could not determine whether chef run was successfully submitted to Datadog: #{evt}")
99
+ end
100
+ end
101
+
102
+ private
103
+
104
+ def pluralize(number, noun)
105
+ case number
106
+ when 0..1
107
+ "less than 1 #{noun}"
108
+ else
109
+ "#{number.round} #{noun}s"
110
+ end
111
+ rescue
112
+ Chef::Log.warn("Cannot make #{number} more legible")
113
+ "#{number} #{noun}s"
114
+ end
115
+
116
+ # Compose a list of resources updated during a run.
117
+ def update_resource_list
118
+ # No resources updated?
119
+ return unless @run_status.updated_resources.length.to_i > 0
120
+
121
+ if @run_status.failed?
122
+ # Shorten the list when there is a failure for stacktrace debugging
123
+ report_resources = @run_status.updated_resources.last(5)
124
+ else
125
+ report_resources = @run_status.updated_resources
126
+ end
127
+
128
+ @event_body = "\n$$$\n"
129
+ report_resources.each do |r|
130
+ @event_body << "- #{r} (#{r.defined_at})\n"
131
+ end
132
+ @event_body << "\n$$$\n"
133
+ end
134
+
135
+ # Marshal the Event data for submission
136
+ def build_event_data
137
+ # bail early in case of a compiletime failure
138
+ # OPTIMIZE: Use better inspectors to handle failure scenarios, refactor needed.
139
+ if @run_status.elapsed_time.nil?
140
+ @alert_type = 'error'
141
+ @event_title = "Chef failed during compile phase on #{@hostname} "
142
+ @event_priority = 'normal'
143
+ @event_body = 'Chef was unable to complete a run, an error during compilation may have occurred.'
144
+ else
145
+ run_time = pluralize(@run_status.elapsed_time, 'second')
146
+
147
+ # This is the first line of the Event body, the rest is appended here.
148
+ @event_body = "Chef updated #{@run_status.updated_resources.length} resources out of #{@run_status.all_resources.length} resources total."
149
+
150
+ # Update resource list, truncated when failed to 5
151
+ # update will add to the event_body
152
+ update_resource_list
153
+
154
+ if @run_status.success?
155
+ @alert_type = 'success'
156
+ @event_priority = 'low'
157
+ @event_title = "Chef completed in #{run_time} on #{@hostname} "
158
+ else
159
+ @alert_type = 'error'
160
+ @event_priority = 'normal'
161
+ @event_title = "Chef failed in #{run_time} on #{@hostname} "
162
+
163
+ if @failure_notifications
164
+ handles = @failure_notifications
165
+ # convert the notification handle array to a string
166
+ @event_body << "\nAlerting: #{handles.join(' ')}\n"
167
+ end
168
+
169
+ @event_body << "\n$$$\n#{@run_status.formatted_exception}\n$$$\n"
170
+ @event_body << "\n$$$\n#{@run_status.backtrace.join("\n")}\n$$$\n"
171
+ end
172
+ end
173
+ end
174
+ end # end module DatadogChefEvent
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+ require 'dogapi'
3
+
4
+ # helper class for sending datadog metrics from a chef run
5
+ class DatadogChefMetrics
6
+ def initialize
7
+ @dog = nil
8
+ @hostname = ''
9
+ @run_status = nil
10
+ end
11
+
12
+ # set the dogapi client handle
13
+ #
14
+ # @param dogapi_client [Dogapi::Client] datadog api client
15
+ # @return [DatadogChefMetrics] instance reference to self enabling method chaining
16
+ def with_dogapi_client(dogapi_client)
17
+ @dog = dogapi_client
18
+ self
19
+ end
20
+
21
+ # set the target hostname (chef node name)
22
+ #
23
+ # @param hostname [String] hostname used for reporting metrics
24
+ # @return [DatadogChefMetrics] instance reference to self enabling method chaining
25
+ def with_hostname(hostname)
26
+ @hostname = hostname
27
+ self
28
+ end
29
+
30
+ # set the chef run status used for the report
31
+ #
32
+ # @param run_status [Chef::RunStatus] current run status
33
+ # @return [DatadogChefMetrics] instance reference to self enabling method chaining
34
+ def with_run_status(run_status)
35
+ @run_status = run_status
36
+ self
37
+ end
38
+
39
+ # Emit Chef metrics to Datadog
40
+ def emit_to_datadog
41
+ # If there is a failure during compile phase, a large portion of
42
+ # run_status may be unavailable. Bail out here
43
+ warn_msg = 'Error during compile phase, no Datadog metrics available.'
44
+ return Chef::Log.warn(warn_msg) if @run_status.elapsed_time.nil?
45
+
46
+ @dog.emit_point('chef.resources.total', @run_status.all_resources.length, host: @hostname)
47
+ @dog.emit_point('chef.resources.updated', @run_status.updated_resources.length, host: @hostname)
48
+ @dog.emit_point('chef.resources.elapsed_time', @run_status.elapsed_time, host: @hostname)
49
+ Chef::Log.debug('Submitted Chef metrics back to Datadog')
50
+ rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT => e
51
+ Chef::Log.error("Could not send metrics to Datadog. Connection error:\n" + e)
52
+ end
53
+ end # end class DatadogChefMetrics
@@ -0,0 +1,111 @@
1
+ # encoding: utf-8
2
+ require 'rubygems'
3
+ require 'chef/handler'
4
+ require 'chef/mash'
5
+ require 'dogapi'
6
+
7
+ # helper class for sending datadog tags from chef runs
8
+ class DatadogChefTags
9
+ def initialize
10
+ @node = nil
11
+ @run_status = nil
12
+ @application_key = nil
13
+ @combined_host_tags = nil
14
+ end
15
+
16
+ # set the dogapi client handle
17
+ #
18
+ # @param dogapi_client [Dogapi::Client] datadog api client handle
19
+ # @return [DatadogChefTags] instance reference to self enabling method chaining
20
+ def with_dogapi_client(dogapi_client)
21
+ @dog = dogapi_client
22
+ self
23
+ end
24
+
25
+ # attribute accessor for combined array of tags
26
+ #
27
+ # @return [Array] the set of host tags based off the chef run
28
+ attr_reader :combined_host_tags
29
+
30
+ # set the chef run status used for the report
31
+ #
32
+ # @param run_status [Chef::RunStatus] current chef run status
33
+ # @return [DatadogChefTags] instance reference to self enabling method chaining
34
+ def with_run_status(run_status)
35
+ @run_status = run_status
36
+ # Build up an array of Chef tags that will be sent back
37
+ # Selects all [env, roles, tags] from the Node's object and reformats
38
+ # them to `key:value` e.g. `role:database-master`.
39
+ @node = run_status.node
40
+ # generate the combined tags
41
+ chef_env = node_env.split # converts a string into an array
42
+ chef_roles = node_roles
43
+ chef_tags = node_tags
44
+
45
+ # Combine (union) all arrays. Removes duplicates if found.
46
+ @combined_host_tags = chef_env | chef_roles | chef_tags
47
+ self
48
+ end
49
+
50
+ # set the target hostname (chef node name)
51
+ #
52
+ # @param hostname [String] hostname to use for the handler report
53
+ # @return [DatadogChefTags] instance reference to self enabling method chaining
54
+ def with_hostname(hostname)
55
+ @hostname = hostname
56
+ self
57
+ end
58
+
59
+ # set the datadog application key
60
+ #
61
+ # TODO: the application key is only needed for error checking, e.g. an app key exists
62
+ # would be cleaner to push this check up to the data prep method in the
63
+ # calling handler class
64
+ #
65
+ # @param application_key [String] datadog application key used for chef reports
66
+ # @return [DatadogChefTags] instance reference to self enabling method chaining
67
+ def with_application_key(application_key)
68
+ @application_key = application_key
69
+ if @application_key.nil?
70
+ Chef::Log.warn('You need an application key to let Chef tag your nodes ' \
71
+ 'in Datadog. Visit https://app.datadoghq.com/account/settings#api to ' \
72
+ 'create one and update your datadog attributes in the datadog cookbook.'
73
+ )
74
+ fail ArgumentError, 'Missing Datadog Application Key'
75
+ end
76
+ self
77
+ end
78
+
79
+ # send updated chef run generated tags to Datadog
80
+ def send_update_to_datadog
81
+ rc = @dog.update_tags(@hostname, combined_host_tags, 'chef')
82
+ begin
83
+ # See FIXME above about why I feel dirty repeating this code here
84
+ if rc.length < 2
85
+ Chef::Log.warn("Unexpected response from Datadog Event API: #{rc}")
86
+ else
87
+ if rc[0].to_i / 100 != 2
88
+ Chef::Log.warn("Could not submit #{combined_host_tags} tags for #{@hostname} to Datadog: #{rc}")
89
+ else
90
+ Chef::Log.debug("Successfully updated #{@hostname}'s tags to #{combined_host_tags.join(', ')}")
91
+ end
92
+ end
93
+ rescue
94
+ Chef::Log.warn("Could not determine whether #{@hostname}'s tags were successfully submitted to Datadog: #{rc}")
95
+ end
96
+ end
97
+
98
+ private
99
+
100
+ def node_roles
101
+ @node.run_list.roles.map! { |role| 'role:' + role }
102
+ end
103
+
104
+ def node_env
105
+ 'env:' + @node.chef_environment if @node.respond_to?('chef_environment')
106
+ end
107
+
108
+ def node_tags
109
+ @node.tags.map! { |tag| 'tag:' + tag } if @node.tags
110
+ end
111
+ end # end class DatadogChefTags
@@ -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.6.0'
5
+ VERSION = '0.7.0'
6
6
  end
@@ -182,13 +182,12 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
182
182
  end
183
183
  end
184
184
 
185
- describe 'handles tags correctly' do
185
+ context 'tags' do
186
186
  before(:each) do
187
187
  @node = Chef::Node.build('chef.handler.datadog.test-tags')
188
188
 
189
189
  @node.send(:chef_environment, 'hostile')
190
190
  @node.send(:run_list, 'role[highlander]')
191
- @node.normal.tags = ['the_one_and_only']
192
191
 
193
192
  @events = Chef::EventDispatch::Dispatcher.new
194
193
  @run_context = Chef::RunContext.new(@node, {}, @events)
@@ -200,20 +199,37 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
200
199
  @run_status.stop_clock
201
200
 
202
201
  @run_status.run_context = @run_context
202
+ end
203
203
 
204
- # Run the report
205
- @handler.run_report_unsafe(@run_status)
204
+ describe 'when specified' do
205
+ it 'sets the role and env and tags' do
206
+ @node.normal.tags = ['the_one_and_only']
207
+ @handler.run_report_unsafe(@run_status)
208
+
209
+ expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
210
+ :query => { 'api_key' => @handler.config[:api_key],
211
+ 'application_key' => @handler.config[:application_key],
212
+ 'source' => 'chef' },
213
+ :body => hash_including(:tags => [
214
+ 'env:hostile', 'role:highlander', 'tag:the_one_and_only'
215
+ ]),
216
+ )).to have_been_made.times(1)
217
+ end
206
218
  end
207
219
 
208
- it 'sets the role and env and tags' do
209
- expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
210
- :query => { 'api_key' => @handler.config[:api_key],
211
- 'application_key' => @handler.config[:application_key],
212
- 'source' => 'chef' },
213
- :body => hash_including(:tags => [
214
- 'env:hostile', 'role:highlander', 'tag:the_one_and_only'
215
- ]),
216
- )).to have_been_made.times(1)
220
+ describe 'when unspecified' do
221
+ it 'sets role, env and nothing else' do
222
+ @handler.run_report_unsafe(@run_status)
223
+
224
+ expect(a_request(:put, HOST_TAG_ENDPOINT + @node.name).with(
225
+ :query => { 'api_key' => @handler.config[:api_key],
226
+ 'application_key' => @handler.config[:application_key],
227
+ 'source' => 'chef' },
228
+ :body => hash_including(:tags => [
229
+ 'env:hostile', 'role:highlander'
230
+ ]),
231
+ )).to have_been_made.times(1)
232
+ end
217
233
  end
218
234
  end
219
235
 
@@ -5,10 +5,12 @@ http_interactions:
5
5
  uri: https://app.datadoghq.com/api/v1/series?api_key=<API_KEY>
6
6
  body:
7
7
  encoding: UTF-8
8
- string: ! '{"series":[{"metric":"chef.resources.total","points":[[1410264919,0.0]],"type":"gauge","host":"chef.handler.datadog.test-tags","device":null}]}'
8
+ string: '{"series":[{"metric":"chef.resources.total","points":[[1428248966,0.0]],"type":"gauge","host":"chef.handler.datadog.test-tags","device":null}]}'
9
9
  headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
10
12
  Accept:
11
- - ! '*/*'
13
+ - "*/*"
12
14
  User-Agent:
13
15
  - Ruby
14
16
  Content-Type:
@@ -21,27 +23,31 @@ http_interactions:
21
23
  Content-Type:
22
24
  - text/json; charset=UTF-8
23
25
  Date:
24
- - Tue, 09 Sep 2014 12:15:14 GMT
26
+ - Sun, 05 Apr 2015 15:49:21 GMT
25
27
  Server:
26
- - dogdispatcher/5.2.0
28
+ - dogdispatcher/6.1.23
29
+ Strict-Transport-Security:
30
+ - max-age=15724800;
27
31
  Content-Length:
28
32
  - '15'
29
33
  Connection:
30
34
  - keep-alive
31
35
  body:
32
- encoding: US-ASCII
33
- string: ! '{"status":"ok"}'
36
+ encoding: UTF-8
37
+ string: '{"status":"ok"}'
34
38
  http_version:
35
- recorded_at: Tue, 09 Sep 2014 12:15:19 GMT
39
+ recorded_at: Sun, 05 Apr 2015 15:49:26 GMT
36
40
  - request:
37
41
  method: post
38
42
  uri: https://app.datadoghq.com/api/v1/series?api_key=<API_KEY>
39
43
  body:
40
44
  encoding: UTF-8
41
- string: ! '{"series":[{"metric":"chef.resources.updated","points":[[1410264919,0.0]],"type":"gauge","host":"chef.handler.datadog.test-tags","device":null}]}'
45
+ string: '{"series":[{"metric":"chef.resources.updated","points":[[1428248966,0.0]],"type":"gauge","host":"chef.handler.datadog.test-tags","device":null}]}'
42
46
  headers:
47
+ Accept-Encoding:
48
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
43
49
  Accept:
44
- - ! '*/*'
50
+ - "*/*"
45
51
  User-Agent:
46
52
  - Ruby
47
53
  Content-Type:
@@ -54,27 +60,31 @@ http_interactions:
54
60
  Content-Type:
55
61
  - text/json; charset=UTF-8
56
62
  Date:
57
- - Tue, 09 Sep 2014 12:15:15 GMT
63
+ - Sun, 05 Apr 2015 15:49:22 GMT
58
64
  Server:
59
- - dogdispatcher/5.1.1
65
+ - dogdispatcher/6.1.23
66
+ Strict-Transport-Security:
67
+ - max-age=15724800;
60
68
  Content-Length:
61
69
  - '15'
62
70
  Connection:
63
71
  - keep-alive
64
72
  body:
65
- encoding: US-ASCII
66
- string: ! '{"status":"ok"}'
73
+ encoding: UTF-8
74
+ string: '{"status":"ok"}'
67
75
  http_version:
68
- recorded_at: Tue, 09 Sep 2014 12:15:19 GMT
76
+ recorded_at: Sun, 05 Apr 2015 15:49:26 GMT
69
77
  - request:
70
78
  method: post
71
79
  uri: https://app.datadoghq.com/api/v1/series?api_key=<API_KEY>
72
80
  body:
73
81
  encoding: UTF-8
74
- string: ! '{"series":[{"metric":"chef.resources.elapsed_time","points":[[1410264919,5.0]],"type":"gauge","host":"chef.handler.datadog.test-tags","device":null}]}'
82
+ string: '{"series":[{"metric":"chef.resources.elapsed_time","points":[[1428248966,5.0]],"type":"gauge","host":"chef.handler.datadog.test-tags","device":null}]}'
75
83
  headers:
84
+ Accept-Encoding:
85
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
76
86
  Accept:
77
- - ! '*/*'
87
+ - "*/*"
78
88
  User-Agent:
79
89
  - Ruby
80
90
  Content-Type:
@@ -87,30 +97,34 @@ http_interactions:
87
97
  Content-Type:
88
98
  - text/json; charset=UTF-8
89
99
  Date:
90
- - Tue, 09 Sep 2014 12:15:15 GMT
100
+ - Sun, 05 Apr 2015 15:49:23 GMT
91
101
  Server:
92
- - dogdispatcher/5.1.1
102
+ - dogdispatcher/6.1.23
103
+ Strict-Transport-Security:
104
+ - max-age=15724800;
93
105
  Content-Length:
94
106
  - '15'
95
107
  Connection:
96
108
  - keep-alive
97
109
  body:
98
- encoding: US-ASCII
99
- string: ! '{"status":"ok"}'
110
+ encoding: UTF-8
111
+ string: '{"status":"ok"}'
100
112
  http_version:
101
- recorded_at: Tue, 09 Sep 2014 12:15:19 GMT
113
+ recorded_at: Sun, 05 Apr 2015 15:49:26 GMT
102
114
  - request:
103
115
  method: post
104
116
  uri: https://app.datadoghq.com/api/v1/events?api_key=<API_KEY>
105
117
  body:
106
118
  encoding: UTF-8
107
- string: ! '{"msg_text":"Chef updated 0 resources out of 0 resources total.","date_happened":1410264919,"msg_title":"Chef
119
+ string: '{"msg_text":"Chef updated 0 resources out of 0 resources total.","date_happened":1428248966,"msg_title":"Chef
108
120
  completed in 5 seconds on chef.handler.datadog.test-tags ","priority":"low","parent":null,"tags":["env:hostile","role:highlander","tag:the_one_and_only"],"aggregation_key":"chef.handler.datadog.test-tags","alert_type":"success","event_type":"config_management.run","source_type_name":"chef","title":"Chef
109
121
  completed in 5 seconds on chef.handler.datadog.test-tags ","text":"Chef updated
110
122
  0 resources out of 0 resources total.","host":"chef.handler.datadog.test-tags","device":null}'
111
123
  headers:
124
+ Accept-Encoding:
125
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
112
126
  Accept:
113
- - ! '*/*'
127
+ - "*/*"
114
128
  User-Agent:
115
129
  - Ruby
116
130
  Content-Type:
@@ -123,32 +137,36 @@ http_interactions:
123
137
  Content-Type:
124
138
  - text/json; charset=UTF-8
125
139
  Date:
126
- - Tue, 09 Sep 2014 12:15:16 GMT
140
+ - Sun, 05 Apr 2015 15:49:23 GMT
127
141
  Server:
128
- - dogdispatcher/5.1.1
142
+ - dogdispatcher/6.1.23
143
+ Strict-Transport-Security:
144
+ - max-age=15724800;
129
145
  Content-Length:
130
- - '428'
146
+ - '420'
131
147
  Connection:
132
148
  - keep-alive
133
149
  body:
134
- encoding: US-ASCII
135
- string: ! '{"status": "ok", "event": {"priority": "low", "date_happened": 1410264919,
150
+ encoding: UTF-8
151
+ string: '{"status": "ok", "event": {"priority": "low", "date_happened": 1428248966,
136
152
  "handle": null, "title": "Chef completed in 5 seconds on chef.handler.datadog.test-tags
137
- ", "url": "https://app.datadoghq.com/event/jump_to?event_id=2449507933236142332",
153
+ ", "url": "https://app.datadoghq.com/event/event?id=2751230185062799345",
138
154
  "text": "Chef updated 0 resources out of 0 resources total.", "tags": ["env:hostile",
139
155
  "role:highlander", "tag:the_one_and_only"], "related_event_id": null, "id":
140
- 2449507933236142332}}'
156
+ 2751230185062799345}}'
141
157
  http_version:
142
- recorded_at: Tue, 09 Sep 2014 12:15:19 GMT
158
+ recorded_at: Sun, 05 Apr 2015 15:49:26 GMT
143
159
  - request:
144
160
  method: put
145
161
  uri: https://app.datadoghq.com/api/v1/tags/hosts/chef.handler.datadog.test-tags?api_key=<API_KEY>&application_key=<APPLICATION_KEY>&source=chef
146
162
  body:
147
163
  encoding: UTF-8
148
- string: ! '{"tags":["env:hostile","role:highlander","tag:the_one_and_only"]}'
164
+ string: '{"tags":["env:hostile","role:highlander","tag:the_one_and_only"]}'
149
165
  headers:
166
+ Accept-Encoding:
167
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
150
168
  Accept:
151
- - ! '*/*'
169
+ - "*/*"
152
170
  User-Agent:
153
171
  - Ruby
154
172
  Content-Type:
@@ -163,19 +181,25 @@ http_interactions:
163
181
  Content-Type:
164
182
  - application/json
165
183
  Date:
166
- - Tue, 09 Sep 2014 12:15:16 GMT
184
+ - Sun, 05 Apr 2015 15:49:24 GMT
167
185
  Pragma:
168
186
  - no-cache
169
187
  Server:
170
188
  - gunicorn/19.1.0
189
+ Strict-Transport-Security:
190
+ - max-age=15724800;
191
+ X-Dd-Debug:
192
+ - mPU4gm+hKkKT8ia9ZdY5CzVKb87xvoCEvNtumo6b6Z8=
193
+ X-Frame-Options:
194
+ - SAMEORIGIN
171
195
  Content-Length:
172
196
  - '110'
173
197
  Connection:
174
198
  - keep-alive
175
199
  body:
176
- encoding: US-ASCII
177
- string: ! '{"host": "chef.handler.datadog.test-tags", "tags": ["env:hostile",
200
+ encoding: UTF-8
201
+ string: '{"host": "chef.handler.datadog.test-tags", "tags": ["env:hostile",
178
202
  "role:highlander", "tag:the_one_and_only"]}'
179
203
  http_version:
180
- recorded_at: Tue, 09 Sep 2014 12:15:19 GMT
181
- recorded_with: VCR 2.9.2
204
+ recorded_at: Sun, 05 Apr 2015 15:49:26 GMT
205
+ recorded_with: VCR 2.9.3