chef-handler-datadog 0.4.0 → 0.5.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.
Files changed (45) hide show
  1. checksums.yaml +8 -8
  2. data/.gitignore +3 -0
  3. data/.rubocop.yml +4 -0
  4. data/.travis.yml +2 -1
  5. data/Appraisals +2 -1
  6. data/CHANGELOG.md +13 -1
  7. data/CONTRIBUTING.md +23 -0
  8. data/Gemfile +4 -0
  9. data/Guardfile +37 -0
  10. data/README.md +12 -20
  11. data/Rakefile +1 -1
  12. data/chef-handler-datadog.gemspec +4 -4
  13. data/gemfiles/chef_10.26.0.gemfile +4 -0
  14. data/gemfiles/chef_10.32.2.gemfile +4 -0
  15. data/gemfiles/chef_11.10.4.gemfile +4 -0
  16. data/gemfiles/{chef_11.12.2.gemfile → chef_11.12.8.gemfile} +5 -1
  17. data/gemfiles/chef_11.14.2.gemfile +16 -0
  18. data/gemfiles/chef_11.8.2.gemfile +4 -0
  19. data/lib/chef/handler/datadog.rb +47 -12
  20. data/lib/chef_handler_datadog.rb +1 -1
  21. data/spec/datadog_spec.rb +58 -8
  22. data/spec/spec_helper.rb +0 -1
  23. data/spec/support/cassettes/Chef_Handler_Datadog/failed_Chef_run/sets_alert_handles_when_specified.yml +69 -57
  24. data/spec/support/cassettes/Chef_Handler_Datadog/failed_Chef_run/sets_event_title_correctly.yml +35 -29
  25. data/spec/support/cassettes/Chef_Handler_Datadog/failed_Chef_run/sets_priority_correctly.yml +35 -29
  26. data/spec/support/cassettes/Chef_Handler_Datadog/handles_no_application_key/fails_when_no_application_key_is_provided.yml +20 -20
  27. data/spec/support/cassettes/Chef_Handler_Datadog/handles_tags_correctly/sets_the_role_and_env_and_tags.yml +23 -23
  28. data/spec/support/cassettes/Chef_Handler_Datadog/hostname/uses_the_node_name_when_no_config_specified.yml +23 -23
  29. data/spec/support/cassettes/Chef_Handler_Datadog/hostname/uses_the_specified_hostname_when_provided.yml +23 -23
  30. 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 +23 -23
  31. data/spec/support/cassettes/Chef_Handler_Datadog/reports_correct_hostname_on_an_ec2_node/uses_the_instance_id_when_config_is_specified.yml +23 -23
  32. data/spec/support/cassettes/Chef_Handler_Datadog/reports_correct_hostname_on_an_ec2_node/uses_the_instance_id_when_no_config_specified.yml +23 -23
  33. data/spec/support/cassettes/Chef_Handler_Datadog/reports_metrics_event_and_sets_tags/emits_events/posts_an_event.yml +23 -23
  34. data/spec/support/cassettes/Chef_Handler_Datadog/reports_metrics_event_and_sets_tags/emits_events/sets_priority_correctly.yml +23 -23
  35. data/spec/support/cassettes/Chef_Handler_Datadog/reports_metrics_event_and_sets_tags/emits_metrics/reports_metrics.yml +23 -23
  36. data/spec/support/cassettes/Chef_Handler_Datadog/reports_metrics_event_and_sets_tags/sets_tags/puts_the_tags_for_the_current_node.yml +23 -23
  37. data/spec/support/cassettes/Chef_Handler_Datadog/resources/failure_during_compile_phase/does_not_emit_metrics.yml +81 -0
  38. data/spec/support/cassettes/Chef_Handler_Datadog/resources/failure_during_compile_phase/posts_an_event.yml +81 -0
  39. data/spec/support/cassettes/Chef_Handler_Datadog/updated_resources/posts_an_event.yml +28 -28
  40. metadata +18 -16
  41. data/gemfiles/chef_10.26.0.gemfile.lock +0 -140
  42. data/gemfiles/chef_10.32.2.gemfile.lock +0 -140
  43. data/gemfiles/chef_11.10.4.gemfile.lock +0 -143
  44. data/gemfiles/chef_11.12.2.gemfile.lock +0 -139
  45. data/gemfiles/chef_11.8.2.gemfile.lock +0 -143
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZGY5NzgzNTc5ZDY5YjA3ZGZkNWY4OTRhM2U4NmE4ZWI0NGYyNDBhMg==
4
+ Y2VjMTZmYjcxMGU0ZTk3MTZkNWM3NzYzNWU1Y2VlMjI5ZjI4MGQ4Zg==
5
5
  data.tar.gz: !binary |-
6
- ZjkxZDg0ZDUyOGMxOWY5YWZhMjNlNmZmMTIxN2NmMjE3ZGU5Y2Y1MA==
6
+ ZGE2NGJjZjYwMGQ1MDczZjhlYjM5Yjg5N2ZmODU5NzYzN2EzMDBkYQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ODRiMjJhZTAyMDAzZDljN2M3NWRhYmI4NTRmZTQzM2U4YzQwNmY1ZWRhZjZh
10
- ZmMzNTBkOWM4ZjIyN2NjOWZmMzcyYmZiYjc5ZTEyOWIzZWVkODQ3ZTNjMzEz
11
- NmE2NTYxNTM5NWEyMGY4NTBmZjdkYTM5MDIyNGQ1YzVmMzVhODA=
9
+ Y2UwYTVkMTc3MzE0ZjFhMTM3ZDQ5YjcwMDg2NTM1MTQwMDY1YmIwMGY0OWI2
10
+ N2IxZmFhZTFiMTI2YjljYTA2ODJhOTlhZTkwZjMwN2Y5Y2Q1NmM5MGY4YmE3
11
+ ZTllNTZhZjFhODAzYjJiYTJjODY5YmM2ZWQxYjNlODhjOWZlNzc=
12
12
  data.tar.gz: !binary |-
13
- MmNjZGRmYjc1Mzg3YjJmM2E0ZjJhNzZkNDViYWVkNTZhMGFkMTg1YjhkMjI2
14
- NGIzZDkxZGQyMzZiNDYyYTVmOTI0MDk4N2M0MmZlODQyYmU5NGUzOTBmOTY2
15
- N2I4YjhlMDFiYjkxYmE1ODVkN2IwNjIwYmQ2MDdlMzA2NDNkODY=
13
+ Y2Q5MjczZDBiYmM5MTg3YzNkMzcyYTBlNzkxZWUwMTk3MGQ1NzEzM2ZiOTJi
14
+ ZTQ0MjQ2MjM0NWY3MjUzMTQzOTM2ODFhOTcyOGQ2Njg5Mjg2MDczZDA4M2Vi
15
+ YjdhYTNiMmY1Y2FiNjE4YzliNDVlYmFhOGJhNzdkMTZmMDcxYWM=
data/.gitignore CHANGED
@@ -58,3 +58,6 @@ Gemfile.lock
58
58
 
59
59
  # Any environment-specific files
60
60
  .env
61
+
62
+ # Ignore Appraisal lock files
63
+ gemfiles/*.gemfile.lock
@@ -36,3 +36,7 @@ CyclomaticComplexity:
36
36
  # be a little lofty.
37
37
  MethodLength:
38
38
  Max: 78
39
+
40
+ # TODO: select_hostname, report are both higher than the default of 7
41
+ PerceivedComplexity:
42
+ Max: 9
@@ -7,6 +7,7 @@ gemfile:
7
7
  - gemfiles/chef_10.32.2.gemfile
8
8
  - gemfiles/chef_11.8.2.gemfile
9
9
  - gemfiles/chef_11.10.4.gemfile
10
- - gemfiles/chef_11.12.2.gemfile
10
+ - gemfiles/chef_11.12.8.gemfile
11
+ - gemfiles/chef_11.14.2.gemfile
11
12
  env:
12
13
  - API_KEY=somefakeapikey APPLICATION_KEY=somefakeapplicationkey
data/Appraisals CHANGED
@@ -4,7 +4,8 @@
4
4
  %w(
5
5
  11.8.2
6
6
  11.10.4
7
- 11.12.2
7
+ 11.12.8
8
+ 11.14.2
8
9
  ).each do |tv|
9
10
  appraise "chef-#{tv}" do
10
11
  gem 'chef', tv
@@ -1,7 +1,15 @@
1
1
  Changes
2
2
  =======
3
3
 
4
- # 0.4.0 / Unreleased
4
+ # 0.5.0 / 2014-08-21
5
+
6
+ * [FEATURE] Place recent updated resources above stacktrace on failure, [#46][] [@miketheman][]
7
+ * [BUGFIX] Handle cases where Chef fails during compile phase, [#51][] [@miketheman][]
8
+ * [FEATURE] Allow credentials to be passed as string keys vs symbols, [#50][] [@dwradcliffe][]
9
+ * [MISC] Testing framework updates, [@miketheman][]
10
+ * [MISC] Doc updates
11
+
12
+ # 0.4.0 / 2014-05-08
5
13
 
6
14
  * [FEATURE] Allow specification of a `:hostname` to config to override `node.name`, [#41][] [@miketheman][]
7
15
  * [FEATURE] Allow passing an array of handles in config to alert when Chef fails, [#29][] [@miketheman][]
@@ -46,6 +54,10 @@ And all other versions were prior to this. See git history for more.
46
54
  [#37]: https://github.com/DataDog/chef-handler-datadog/issues/37
47
55
  [#39]: https://github.com/DataDog/chef-handler-datadog/issues/39
48
56
  [#41]: https://github.com/DataDog/chef-handler-datadog/issues/41
57
+ [#46]: https://github.com/DataDog/chef-handler-datadog/issues/46
58
+ [#50]: https://github.com/DataDog/chef-handler-datadog/issues/50
59
+ [#51]: https://github.com/DataDog/chef-handler-datadog/issues/51
49
60
  [@alq]: https://github.com/alq
61
+ [@dwradcliffe]: https://github.com/dwradcliffe
50
62
  [@miketheman]: https://github.com/miketheman
51
63
  [@remh]: https://github.com/remh
@@ -0,0 +1,23 @@
1
+ # Contributing
2
+
3
+ If you'd like to run the test suite, fix a bug or add a feature, please follow these steps:
4
+
5
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
6
+ * Check out the latest `master` branch to make sure the feature hasn't been implemented or the bug hasn't been fixed
7
+ * Fork the project
8
+ * Install all dependencies: `bundle install`
9
+ * Start a feature/bugfix branch: `git checkout -b my_feature_name`
10
+ * Place a `.env` file in the root of the project with `API_KEY` and `APPLICATION_KEY`:
11
+
12
+ API_KEY: myapikey
13
+ APPLICATION_KEY: chefhandlerspecificapplicationkey
14
+
15
+ This file is intentionally .gitignored to prevent security exposure.
16
+ You may use your own Datadog account keys, as the keys are filtered from the test recordings.
17
+ Running the test suite will _not_ make calls to Datadog for existing tests, see `spec/support/cassettes/` for more.
18
+
19
+ * Run `rake` to execute tests, ensure they pass
20
+ * Commit and push until you are happy with your contribution
21
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
22
+ * Please try not to mess with the `Rakefile`, version, or history.
23
+ If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
data/Gemfile CHANGED
@@ -5,6 +5,10 @@ source 'http://rubygems.org'
5
5
  gemspec
6
6
 
7
7
  group :localdev do
8
+ gem 'guard'
9
+ gem 'guard-rspec'
10
+ gem 'guard-rubocop'
8
11
  gem 'pry'
12
+ gem 'terminal-notifier-guard'
9
13
  gem 'travis-lint'
10
14
  end
@@ -0,0 +1,37 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rubocop do
5
+ watch(%r{.+\.rb$})
6
+ watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
7
+ end
8
+
9
+ # Note: The cmd option is now required due to the increasing number of ways
10
+ # rspec may be run, below are examples of the most common uses.
11
+ # * bundler: 'bundle exec rspec'
12
+ # * bundler binstubs: 'bin/rspec'
13
+ # * spring: 'bin/rsspec' (This will use spring if running and you have
14
+ # installed the spring binstubs per the docs)
15
+ # * zeus: 'zeus rspec' (requires the server to be started separetly)
16
+ # * 'just' rspec: 'rspec'
17
+ guard :rspec, cmd: 'bundle exec rspec' do
18
+ watch(%r{^spec/.+_spec\.rb$})
19
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
20
+ watch('spec/spec_helper.rb') { "spec" }
21
+
22
+ # Rails example
23
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
24
+ watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
25
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
26
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
27
+ watch('config/routes.rb') { "spec/routing" }
28
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
29
+ watch('spec/rails_helper.rb') { "spec" }
30
+
31
+ # Capybara features specs
32
+ watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
33
+
34
+ # Turnip features and steps
35
+ watch(%r{^spec/acceptance/(.+)\.feature$})
36
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
37
+ end
data/README.md CHANGED
@@ -2,35 +2,27 @@
2
2
 
3
3
  An Exception and Report Handler for Chef.
4
4
 
5
- [![Gem Version](https://badge.fury.io/rb/chef-handler-datadog.png)](http://badge.fury.io/rb/chef-handler-datadog)
6
- [![Build Status](https://secure.travis-ci.org/DataDog/chef-handler-datadog.png?branch=master)](http://travis-ci.org/DataDog/chef-handler-datadog)
7
- [![Code Climate](https://codeclimate.com/github/DataDog/chef-handler-datadog.png)](https://codeclimate.com/github/DataDog/chef-handler-datadog)
8
- [![Dependency Status](https://gemnasium.com/DataDog/chef-handler-datadog.png)](https://gemnasium.com/DataDog/chef-handler-datadog)
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.org/DataDog/chef-handler-datadog.svg?branch=master)](https://travis-ci.org/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)
9
9
 
10
10
  ## Using chef-handler-datadog
11
11
 
12
- The Datadog Docs on [Chef](http://docs.datadoghq.com/guides/chef/#deployhandler) has detailed instructions.
13
-
14
- ## Contributing to chef-handler-datadog
12
+ This can be installed by using the `dd-handler` recipe from the [datadog cookbook][cookbook].
15
13
 
16
- * Check out the latest `master` to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
17
- * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
18
- * Fork the project
19
- * Start a feature/bugfix branch
20
- * Place a `.env` file in the root of the project with `API_KEY` and `APPLICATION_KEY`:
14
+ ```ruby
15
+ run_list 'foo::bar', 'datadog::dd-handler'
16
+ ```
21
17
 
22
- API_KEY: myapikey
23
- APPLICATION_KEY: chefhandlerspecificapplicationkey
18
+ The Datadog Docs on [Chef](http://docs.datadoghq.com/guides/chef/#deployhandler) has detailed instructions.
24
19
 
25
- This file is intentionally .gitignored to prevent security exposure.
20
+ ## Contributing to chef-handler-datadog
26
21
 
27
- * Run `rake` to execute tests, ensure they pass
28
- * Commit and push until you are happy with your contribution
29
- * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
30
- * Please try not to mess with the `Rakefile`, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
22
+ See [CONTRIBUTING.md](CONTRIBUTING.md)
31
23
 
32
24
  ## Copyright
33
25
 
34
26
  Copyright (c) 2012-2014 Datadog, Inc. See LICENSE.txt for further details.
35
27
 
36
- [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/DataDog/chef-handler-datadog/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
28
+ [cookbook]: https://supermarket.getchef.com/cookbooks/datadog
data/Rakefile CHANGED
@@ -14,4 +14,4 @@ CLEAN.include(['coverage/', 'doc/', 'pkg/'])
14
14
 
15
15
  RSpec::Core::RakeTask.new(:spec)
16
16
 
17
- Rubocop::RakeTask.new(:cops)
17
+ RuboCop::RakeTask.new(:cops)
@@ -3,8 +3,8 @@ require File.expand_path('../lib/chef_handler_datadog', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |gem|
5
5
  gem.name = 'chef-handler-datadog'
6
- gem.summary = %q(Chef Handler for DataDog events and metrics)
7
- gem.description = %q(This Handler will report the events and metrics for a chef-client run to DataDog.)
6
+ gem.summary = 'Chef Handler reports events and metrics to Datadog'
7
+ gem.description = 'This Handler will report the events and metrics for a chef-client run to Datadog.'
8
8
  gem.license = 'BSD'
9
9
  gem.version = ChefHandlerDatadog::VERSION
10
10
 
@@ -21,8 +21,8 @@ Gem::Specification.new do |gem|
21
21
  gem.add_development_dependency 'chef', '>= 10', '<= 12'
22
22
  gem.add_development_dependency 'dotenv'
23
23
  gem.add_development_dependency 'rake'
24
- gem.add_development_dependency 'rspec'
25
- gem.add_development_dependency 'rubocop', '~> 0.21.0'
24
+ gem.add_development_dependency 'rspec', '~> 3.0.0'
25
+ gem.add_development_dependency 'rubocop', '~> 0.25.0'
26
26
  gem.add_development_dependency 'simplecov'
27
27
  gem.add_development_dependency 'vcr'
28
28
  gem.add_development_dependency 'webmock'
@@ -6,7 +6,11 @@ gem "chef", "10.26.0"
6
6
  gem "json", "1.7.7"
7
7
 
8
8
  group :localdev do
9
+ gem "guard"
10
+ gem "guard-rspec"
11
+ gem "guard-rubocop"
9
12
  gem "pry"
13
+ gem "terminal-notifier-guard"
10
14
  gem "travis-lint"
11
15
  end
12
16
 
@@ -6,7 +6,11 @@ gem "chef", "10.32.2"
6
6
  gem "json", "1.7.7"
7
7
 
8
8
  group :localdev do
9
+ gem "guard"
10
+ gem "guard-rspec"
11
+ gem "guard-rubocop"
9
12
  gem "pry"
13
+ gem "terminal-notifier-guard"
10
14
  gem "travis-lint"
11
15
  end
12
16
 
@@ -5,7 +5,11 @@ source "http://rubygems.org"
5
5
  gem "chef", "11.10.4"
6
6
 
7
7
  group :localdev do
8
+ gem "guard"
9
+ gem "guard-rspec"
10
+ gem "guard-rubocop"
8
11
  gem "pry"
12
+ gem "terminal-notifier-guard"
9
13
  gem "travis-lint"
10
14
  end
11
15
 
@@ -2,10 +2,14 @@
2
2
 
3
3
  source "http://rubygems.org"
4
4
 
5
- gem "chef", "11.12.2"
5
+ gem "chef", "11.12.8"
6
6
 
7
7
  group :localdev do
8
+ gem "guard"
9
+ gem "guard-rspec"
10
+ gem "guard-rubocop"
8
11
  gem "pry"
12
+ gem "terminal-notifier-guard"
9
13
  gem "travis-lint"
10
14
  end
11
15
 
@@ -0,0 +1,16 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "chef", "11.14.2"
6
+
7
+ group :localdev do
8
+ gem "guard"
9
+ gem "guard-rspec"
10
+ gem "guard-rubocop"
11
+ gem "pry"
12
+ gem "terminal-notifier-guard"
13
+ gem "travis-lint"
14
+ end
15
+
16
+ gemspec :path => "../"
@@ -5,7 +5,11 @@ source "http://rubygems.org"
5
5
  gem "chef", "11.8.2"
6
6
 
7
7
  group :localdev do
8
+ gem "guard"
9
+ gem "guard-rspec"
10
+ gem "guard-rubocop"
8
11
  gem "pry"
12
+ gem "terminal-notifier-guard"
9
13
  gem "travis-lint"
10
14
  end
11
15
 
@@ -1,6 +1,7 @@
1
1
  # encoding: utf-8
2
2
  require 'rubygems'
3
3
  require 'chef/handler'
4
+ require 'chef/mash'
4
5
  require 'dogapi'
5
6
 
6
7
  class Chef
@@ -13,9 +14,9 @@ class Chef
13
14
  # "Account Settings" page here: https://app.datadoghq.com/account/settings
14
15
  # It should be passed along from the node/role/environemnt attributes, as the default is nil.
15
16
  def initialize(config = {})
16
- @config = config
17
+ @config = Mash.new(config)
17
18
  # If *any* api_key is not provided, this will fail immediately.
18
- @dog = Dogapi::Client.new(config[:api_key], config[:application_key])
19
+ @dog = Dogapi::Client.new(@config[:api_key], @config[:application_key])
19
20
  end
20
21
 
21
22
  def report
@@ -78,11 +79,26 @@ class Chef
78
79
  # @param run_status [Chef::RunStatus] current run status
79
80
  # @return [Array] alert_type, event_priority, event_title, event_body
80
81
  def build_event_data(hostname, run_status)
82
+ # bail early in case of a compiletime failure
83
+ # OPTIMIZE: Use better inspectors to handle failure scenarios, refactor needed.
84
+ if run_status.elapsed_time.nil?
85
+
86
+ alert_type = 'error'
87
+ event_title = "Chef failed during compile phase on #{hostname} "
88
+ event_priority = 'normal'
89
+ event_body = 'Chef was unable to complete a run, an error during compilation may have occurred.'
90
+
91
+ return [alert_type, event_priority, event_title, event_body]
92
+ end
93
+
81
94
  run_time = pluralize(run_status.elapsed_time, 'second')
82
95
 
83
96
  # This is the first line of the Event body, the rest is appended here.
84
97
  event_body = "Chef updated #{run_status.updated_resources.length} resources out of #{run_status.all_resources.length} resources total."
85
98
 
99
+ # Show the updated resource list, truncated when failed to 5
100
+ event_body << updated_resource_list(run_status)
101
+
86
102
  if run_status.success?
87
103
  alert_type = 'success'
88
104
  event_priority = 'low'
@@ -98,22 +114,36 @@ class Chef
98
114
  event_body << "\nAlerting: #{handles.join(' ')}\n"
99
115
  end
100
116
 
101
- event_body << "\n@@@\n#{run_status.formatted_exception}\n@@@\n"
102
- event_body << "\n@@@\n#{run_status.backtrace.join("\n")}\n@@@\n"
103
- end
104
-
105
- if run_status.updated_resources.length.to_i > 0
106
- event_body << "\n@@@\n"
107
- run_status.updated_resources.each do |r|
108
- event_body << "- #{r} (#{r.defined_at})\n"
109
- end
110
- event_body << "\n@@@\n"
117
+ event_body << "\n$$$\n#{run_status.formatted_exception}\n$$$\n"
118
+ event_body << "\n$$$\n#{run_status.backtrace.join("\n")}\n$$$\n"
111
119
  end
112
120
 
113
121
  # Return resolved data
114
122
  [alert_type, event_priority, event_title, event_body]
115
123
  end
116
124
 
125
+ # Compose a list of resources updated during a run.
126
+ # Shorten the list when there is a failure for stacktrace debugging
127
+ #
128
+ # @param run_status [Chef::RunStatus] current run status
129
+ # @return [String] formatted list of resources updated, truncated on failure
130
+ def updated_resource_list(run_status)
131
+ # No resources updated? Go away.
132
+ return '' unless run_status.updated_resources.length.to_i > 0
133
+
134
+ if run_status.failed?
135
+ report_resources = run_status.updated_resources.last(5)
136
+ else
137
+ report_resources = run_status.updated_resources
138
+ end
139
+
140
+ event_body = "\n$$$\n"
141
+ report_resources.each do |r|
142
+ event_body << "- #{r} (#{r.defined_at})\n"
143
+ end
144
+ event_body << "\n$$$\n"
145
+ end
146
+
117
147
  # Emit Event to Datadog Event Stream
118
148
  #
119
149
  # @param hostname [String] resolved hostname to attach to Event
@@ -154,6 +184,11 @@ class Chef
154
184
  # @param hostname [String] resolved hostname to attach to series
155
185
  # @param run_status [Chef::RunStatus] current run status
156
186
  def emit_metrics_to_datadog(hostname, run_status)
187
+ # If there is a failure during compile phase, a large portion of
188
+ # run_status may be unavailable. Bail out here
189
+ warn_msg = 'Error during compile phase, no Datadog metrics available.'
190
+ return Chef::Log.warn(warn_msg) if run_status.elapsed_time.nil?
191
+
157
192
  @dog.emit_point('chef.resources.total', run_status.all_resources.length, :host => hostname)
158
193
  @dog.emit_point('chef.resources.updated', run_status.updated_resources.length, :host => hostname)
159
194
  @dog.emit_point('chef.resources.elapsed_time', run_status.elapsed_time, :host => hostname)
@@ -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.4.0'
5
+ VERSION = '0.5.0'
6
6
  end
@@ -23,6 +23,15 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
23
23
  )
24
24
  end
25
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
+ )
32
+ end
33
+ end
34
+
26
35
  describe 'reports metrics event and sets tags' do
27
36
  # Construct a good run_status
28
37
  before(:each) do
@@ -33,7 +42,7 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
33
42
  @run_status = Chef::RunStatus.new(@node, @events)
34
43
 
35
44
  @expected_time = Time.now
36
- Time.stub(:now).and_return(@expected_time, @expected_time + 5)
45
+ allow(Time).to receive(:now).and_return(@expected_time, @expected_time + 5)
37
46
  @run_status.start_clock
38
47
  @run_status.stop_clock
39
48
 
@@ -97,7 +106,7 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
97
106
  @run_context = Chef::RunContext.new(@node, {}, @events)
98
107
  @run_status = Chef::RunStatus.new(@node, @events)
99
108
  @expected_time = Time.now
100
- Time.stub(:now).and_return(@expected_time, @expected_time + 5)
109
+ allow(Time).to receive(:now).and_return(@expected_time, @expected_time + 5)
101
110
  @run_status.start_clock
102
111
  @run_status.stop_clock
103
112
  @run_status.run_context = @run_context
@@ -144,7 +153,7 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
144
153
  @run_context = Chef::RunContext.new(@node, {}, @events)
145
154
  @run_status = Chef::RunStatus.new(@node, @events)
146
155
  @expected_time = Time.now
147
- Time.stub(:now).and_return(@expected_time, @expected_time + 5)
156
+ allow(Time).to receive(:now).and_return(@expected_time, @expected_time + 5)
148
157
  @run_status.start_clock
149
158
  @run_status.stop_clock
150
159
  @run_status.run_context = @run_context
@@ -185,7 +194,7 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
185
194
  @run_status = Chef::RunStatus.new(@node, @events)
186
195
 
187
196
  @expected_time = Time.now
188
- Time.stub(:now).and_return(@expected_time, @expected_time + 5)
197
+ allow(Time).to receive(:now).and_return(@expected_time, @expected_time + 5)
189
198
  @run_status.start_clock
190
199
  @run_status.stop_clock
191
200
 
@@ -220,7 +229,7 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
220
229
  @run_status = Chef::RunStatus.new(@node, @events)
221
230
 
222
231
  @expected_time = Time.now
223
- Time.stub(:now).and_return(@expected_time, @expected_time + 5)
232
+ allow(Time).to receive(:now).and_return(@expected_time, @expected_time + 5)
224
233
  @run_status.start_clock
225
234
  @run_status.stop_clock
226
235
 
@@ -248,8 +257,19 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
248
257
  @run_context = Chef::RunContext.new(@node, {}, @events)
249
258
  @run_status = Chef::RunStatus.new(@node, @events)
250
259
 
260
+ all_resources = [
261
+ Chef::Resource.new('whiskers'),
262
+ Chef::Resource.new('paws'),
263
+ Chef::Resource.new('ears'),
264
+ Chef::Resource.new('nose'),
265
+ Chef::Resource.new('tail'),
266
+ Chef::Resource.new('fur')
267
+ ]
268
+ all_resources.map { |r| r.updated_by_last_action(true) }
269
+ @run_context.resource_collection.all_resources.replace(all_resources)
270
+
251
271
  @expected_time = Time.now
252
- Time.stub(:now).and_return(@expected_time, @expected_time + 2)
272
+ allow(Time).to receive(:now).and_return(@expected_time, @expected_time + 2)
253
273
  @run_status.start_clock
254
274
  @run_status.stop_clock
255
275
 
@@ -257,7 +277,7 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
257
277
 
258
278
  # Construct an exception
259
279
  exception = Chef::Exceptions::UnsupportedAction.new('Something awry.')
260
- exception.set_backtrace(['file.rb:2', 'file.rb:1'])
280
+ exception.set_backtrace(['whiskers.rb:2', 'paws.rb:1', 'file.rb:2', 'file.rb:1'])
261
281
  @run_status.exception = exception
262
282
 
263
283
  # Run the report
@@ -303,7 +323,7 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
303
323
  @run_context.resource_collection.all_resources.replace(all_resources)
304
324
 
305
325
  @expected_time = Time.now
306
- Time.stub(:now).and_return(@expected_time, @expected_time + 8)
326
+ allow(Time).to receive(:now).and_return(@expected_time, @expected_time + 8)
307
327
  @run_status.start_clock
308
328
  @run_status.stop_clock
309
329
 
@@ -322,6 +342,36 @@ describe Chef::Handler::Datadog, :vcr => :new_episodes do
322
342
  end
323
343
  end
324
344
 
345
+ describe 'resources' do
346
+ before(:each) do
347
+ @node = Chef::Node.build('chef.handler.datadog.test-resources')
348
+ @node.send(:chef_environment, 'resources')
349
+ @events = Chef::EventDispatch::Dispatcher.new
350
+ @run_context = Chef::RunContext.new(@node, {}, @events)
351
+ @run_status = Chef::RunStatus.new(@node, @events)
352
+ end
353
+
354
+ context 'failure during compile phase' do
355
+ before(:each) do
356
+ @handler.run_report_unsafe(@run_status)
357
+ end
358
+
359
+ it 'does not emit metrics' do
360
+ expect(a_request(:post, METRICS_ENDPOINT).with(
361
+ :query => { 'api_key' => @handler.config[:api_key] }
362
+ )).to_not have_been_made
363
+ end
364
+
365
+ it 'posts an event' do
366
+ expect(a_request(:post, EVENTS_ENDPOINT).with(
367
+ :query => { 'api_key' => @handler.config[:api_key] },
368
+ :body => hash_including(:msg_text => 'Chef was unable to complete a run, an error during compilation may have occured.'),
369
+ :body => hash_including(:msg_title => "Chef failed during compile phase on #{@node.name} "),
370
+ )).to have_been_made.times(1)
371
+ end
372
+ end
373
+ end
374
+
325
375
  # TODO: test failures:
326
376
  # @run_status.exception = Exception.new('Boy howdy!')
327
377
  end