chef 12.15.19 → 12.16.42

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -1
  3. data/VERSION +1 -1
  4. data/acceptance/.shared/kitchen_acceptance/.kitchen.ec2.yml +3 -1
  5. data/acceptance/Gemfile.lock +14 -14
  6. data/acceptance/data-collector/test/integration/default/serverspec/default_spec.rb +3 -11
  7. data/distro/common/html/knife_bootstrap.html +1 -1
  8. data/distro/common/man/man1/README.md +2 -2
  9. data/distro/common/man/man1/knife-client.1 +1 -1
  10. data/lib/chef/application.rb +7 -15
  11. data/lib/chef/application/client.rb +2 -2
  12. data/lib/chef/application/solo.rb +1 -1
  13. data/lib/chef/chef_class.rb +1 -0
  14. data/lib/chef/chef_fs/file_system/chef_server/cookbook_file.rb +3 -7
  15. data/lib/chef/chef_fs/file_system/chef_server/versioned_cookbook_dir.rb +1 -1
  16. data/lib/chef/data_collector.rb +83 -9
  17. data/lib/chef/data_collector/messages.rb +2 -1
  18. data/lib/chef/dsl/core.rb +1 -1
  19. data/lib/chef/dsl/declare_resource.rb +10 -4
  20. data/lib/chef/dsl/method_missing.rb +1 -1
  21. data/lib/chef/dsl/recipe.rb +1 -1
  22. data/lib/chef/dsl/universal.rb +1 -1
  23. data/lib/chef/event_dispatch/base.rb +3 -0
  24. data/lib/chef/http.rb +3 -4
  25. data/lib/chef/knife.rb +20 -2
  26. data/lib/chef/knife/core/generic_presenter.rb +18 -4
  27. data/lib/chef/knife/node_show.rb +0 -5
  28. data/lib/chef/knife/osc_user_show.rb +0 -1
  29. data/lib/chef/knife/ssl_fetch.rb +9 -5
  30. data/lib/chef/mixin/powershell_out.rb +1 -1
  31. data/lib/chef/mixin/shell_out.rb +1 -1
  32. data/lib/chef/node.rb +1 -5
  33. data/lib/chef/node/attribute.rb +70 -98
  34. data/lib/chef/node/attribute_collections.rb +28 -19
  35. data/lib/chef/node/common_api.rb +0 -6
  36. data/lib/chef/node/immutable_collections.rb +16 -79
  37. data/lib/chef/node/mixin/deep_merge_cache.rb +61 -0
  38. data/lib/chef/node/mixin/immutablize_array.rb +67 -0
  39. data/lib/chef/node/mixin/immutablize_hash.rb +54 -0
  40. data/lib/chef/node/mixin/state_tracking.rb +93 -0
  41. data/lib/chef/property.rb +4 -4
  42. data/lib/chef/provider/cron.rb +1 -1
  43. data/lib/chef/provider/group/suse.rb +23 -4
  44. data/lib/chef/provider/package.rb +43 -5
  45. data/lib/chef/provider/package/apt.rb +20 -0
  46. data/lib/chef/provider/package/windows/exe.rb +4 -3
  47. data/lib/chef/provider/package/windows/msi.rb +4 -3
  48. data/lib/chef/provider/package/yum.rb +20 -0
  49. data/lib/chef/provider/package/zypper.rb +20 -0
  50. data/lib/chef/provider/ruby_block.rb +1 -1
  51. data/lib/chef/provider/service/upstart.rb +25 -9
  52. data/lib/chef/provider/user.rb +4 -6
  53. data/lib/chef/provider/user/dscl.rb +8 -3
  54. data/lib/chef/provider/user/solaris.rb +5 -12
  55. data/lib/chef/resource.rb +19 -0
  56. data/lib/chef/resource/file.rb +1 -1
  57. data/lib/chef/resource/package.rb +1 -1
  58. data/lib/chef/resource/scm.rb +1 -7
  59. data/lib/chef/resource/yum_repository.rb +1 -1
  60. data/lib/chef/rest.rb +1 -0
  61. data/lib/chef/run_context.rb +12 -0
  62. data/lib/chef/version.rb +1 -1
  63. data/spec/data/trusted_certs/example_no_cn.crt +36 -0
  64. data/spec/functional/resource/group_spec.rb +1 -0
  65. data/spec/functional/resource/user/useradd_spec.rb +4 -2
  66. data/spec/integration/knife/data_bag_create_spec.rb +0 -3
  67. data/spec/integration/knife/environment_show_spec.rb +24 -4
  68. data/spec/integration/knife/node_environment_set_spec.rb +4 -1
  69. data/spec/integration/recipes/accumulator_spec.rb +232 -0
  70. data/spec/integration/recipes/resource_action_spec.rb +1 -1
  71. data/spec/spec_helper.rb +2 -2
  72. data/spec/support/shared/context/client.rb +12 -3
  73. data/spec/support/shared/integration/app_server_support.rb +1 -1
  74. data/spec/support/shared/integration/knife_support.rb +4 -1
  75. data/spec/unit/data_collector/messages_spec.rb +2 -0
  76. data/spec/unit/data_collector_spec.rb +158 -21
  77. data/spec/unit/http_spec.rb +1 -1
  78. data/spec/unit/knife/core/gem_glob_loader_spec.rb +1 -1
  79. data/spec/unit/knife/core/ui_spec.rb +10 -0
  80. data/spec/unit/knife/ssl_fetch_spec.rb +38 -0
  81. data/spec/unit/knife_spec.rb +31 -0
  82. data/spec/unit/mixin/powershell_out_spec.rb +25 -1
  83. data/spec/unit/node/attribute_spec.rb +46 -1
  84. data/spec/unit/node/vivid_mash_spec.rb +27 -89
  85. data/spec/unit/node_spec.rb +134 -3
  86. data/spec/unit/provider/deploy_spec.rb +1 -1
  87. data/spec/unit/provider/group/suse_spec.rb +90 -0
  88. data/spec/unit/provider/package/apt_spec.rb +22 -0
  89. data/spec/unit/provider/package/windows/msi_spec.rb +13 -4
  90. data/spec/unit/provider/package/windows_spec.rb +3 -3
  91. data/spec/unit/provider/package/yum_spec.rb +18 -0
  92. data/spec/unit/provider/package/zypper_spec.rb +64 -0
  93. data/spec/unit/provider/package_spec.rb +58 -0
  94. data/spec/unit/provider/remote_file/content_spec.rb +1 -1
  95. data/spec/unit/provider/service/upstart_service_spec.rb +13 -6
  96. data/spec/unit/provider/user/solaris_spec.rb +36 -9
  97. data/spec/unit/provider/user_spec.rb +6 -0
  98. data/spec/unit/resource/apt_repository_spec.rb +1 -1
  99. metadata +12 -5
@@ -31,7 +31,10 @@ describe "knife node environment set", :workstation do
31
31
 
32
32
  it "sets an environment on a node" do
33
33
  knife("node environment set cons lisp").should_succeed /chef_environment:.*lisp/
34
- knife("node show cons -a chef_environment").should_succeed /Environment:.*lisp/
34
+ knife("node show cons -a chef_environment").should_succeed <<EOM
35
+ cons:
36
+ chef_environment: lisp
37
+ EOM
35
38
  end
36
39
 
37
40
  it "with no environment" do
@@ -0,0 +1,232 @@
1
+ require "support/shared/integration/integration_helper"
2
+ require "chef/mixin/shell_out"
3
+
4
+ describe "Accumulators" do
5
+ include IntegrationSupport
6
+ include Chef::Mixin::ShellOut
7
+
8
+ let(:chef_dir) { File.expand_path("../../../../bin", __FILE__) }
9
+
10
+ # Invoke `chef-client` as `ruby PATH/TO/chef-client`. This ensures the
11
+ # following constraints are satisfied:
12
+ # * Windows: windows can only run batch scripts as bare executables. Rubygems
13
+ # creates batch wrappers for installed gems, but we don't have batch wrappers
14
+ # in the source tree.
15
+ # * Other `chef-client` in PATH: A common case is running the tests on a
16
+ # machine that has omnibus chef installed. In that case we need to ensure
17
+ # we're running `chef-client` from the source tree and not the external one.
18
+ # cf. CHEF-4914
19
+ let(:chef_client) { "ruby '#{chef_dir}/chef-client' --minimal-ohai" }
20
+
21
+ let(:aliases_temppath) do
22
+ t = Tempfile.new("chef_accumulator_test")
23
+ path = t.path
24
+ t.close
25
+ t.unlink
26
+ path
27
+ end
28
+
29
+ when_the_repository "edit_resource-based delayed accumulators work" do
30
+ before do
31
+ directory "cookbooks/x" do
32
+ file "resources/email_alias.rb", <<-EOM
33
+ provides :email_alias
34
+ resource_name :email_alias
35
+
36
+ property :address, String, name_property: true, identity: true
37
+ property :recipients, Array
38
+
39
+ default_action :create
40
+
41
+ action :create do
42
+ with_run_context :root do
43
+ edit_resource(:template, "#{aliases_temppath}") do |new_resource|
44
+ source "aliases.erb"
45
+ variables[:aliases] ||= {}
46
+ variables[:aliases][new_resource.address] ||= []
47
+ variables[:aliases][new_resource.address] += new_resource.recipients
48
+ action :nothing
49
+ delayed_action :create
50
+ end
51
+ end
52
+ end
53
+ EOM
54
+
55
+ file "resources/nested.rb", <<-EOM
56
+ provides :nested
57
+ resource_name :nested
58
+
59
+ property :address, String, name_property: true, identity: true
60
+ property :recipients, Array
61
+
62
+ default_action :create
63
+
64
+ action :create do
65
+ email_alias address do
66
+ recipients new_resource.recipients
67
+ end
68
+ end
69
+ EOM
70
+
71
+ file "resources/doubly_nested.rb", <<-EOM
72
+ provides :doubly_nested
73
+ resource_name :doubly_nested
74
+
75
+ property :address, String, name_property: true, identity: true
76
+ property :recipients, Array
77
+
78
+ default_action :create
79
+
80
+ action :create do
81
+ nested address do
82
+ recipients new_resource.recipients
83
+ end
84
+ end
85
+ EOM
86
+
87
+ file "recipes/default.rb", <<-EOM
88
+ email_alias "outer1" do
89
+ recipients [ "out1a", "out1b" ]
90
+ end
91
+
92
+ nested "nested1" do
93
+ recipients [ "nested1a", "nested1b" ]
94
+ end
95
+
96
+ email_alias "outer2" do
97
+ recipients [ "out2a", "out2b" ]
98
+ end
99
+
100
+ doubly_nested "nested2" do
101
+ recipients [ "nested2a", "nested2b" ]
102
+ end
103
+
104
+ email_alias "outer3" do
105
+ recipients [ "out3a", "out3b" ]
106
+ end
107
+ EOM
108
+
109
+ file "templates/aliases.erb", <<-EOM.gsub(/^\s+/, "")
110
+ <%= pp @aliases %>
111
+ EOM
112
+ end # directory 'cookbooks/x'
113
+ end
114
+
115
+ it "should complete with success" do
116
+ file "config/client.rb", <<-EOM
117
+ local_mode true
118
+ cookbook_path "#{path_to('cookbooks')}"
119
+ log_level :warn
120
+ EOM
121
+
122
+ result = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" --no-color -F doc -o 'x::default'", :cwd => chef_dir)
123
+ result.error!
124
+ # runs only a single template resource (in the outer run context, as a delayed resource)
125
+ expect(result.stdout.scan(/template\S+ action create/).size).to eql(1)
126
+ # hash order is insertion order in ruby >= 1.9, so this next line does test that all calls were in the correct order
127
+ expect(IO.read(aliases_temppath).chomp).to eql('{"outer1"=>["out1a", "out1b"], "nested1"=>["nested1a", "nested1b"], "outer2"=>["out2a", "out2b"], "nested2"=>["nested2a", "nested2b"], "outer3"=>["out3a", "out3b"]}')
128
+ end
129
+ end
130
+
131
+ when_the_repository "find_resource-based delayed accumulators work" do
132
+ before do
133
+ directory "cookbooks/x" do
134
+ file "resources/email_alias.rb", <<-EOM
135
+ provides :email_alias
136
+ resource_name :email_alias
137
+
138
+ property :address, String, name_property: true, identity: true
139
+ property :recipients, Array
140
+
141
+ default_action :create
142
+
143
+ action :create do
144
+ r = with_run_context :root do
145
+ find_resource(:template, "#{aliases_temppath}") do
146
+ source "aliases.erb"
147
+ variables[:aliases] = {}
148
+ action :nothing
149
+ delayed_action :create
150
+ end
151
+ end
152
+ r.variables[:aliases][address] ||= []
153
+ r.variables[:aliases][address] += new_resource.recipients
154
+ end
155
+ EOM
156
+
157
+ file "resources/nested.rb", <<-EOM
158
+ provides :nested
159
+ resource_name :nested
160
+
161
+ property :address, String, name_property: true, identity: true
162
+ property :recipients, Array
163
+
164
+ default_action :create
165
+
166
+ action :create do
167
+ email_alias address do
168
+ recipients new_resource.recipients
169
+ end
170
+ end
171
+ EOM
172
+
173
+ file "resources/doubly_nested.rb", <<-EOM
174
+ provides :doubly_nested
175
+ resource_name :doubly_nested
176
+
177
+ property :address, String, name_property: true, identity: true
178
+ property :recipients, Array
179
+
180
+ default_action :create
181
+
182
+ action :create do
183
+ nested address do
184
+ recipients new_resource.recipients
185
+ end
186
+ end
187
+ EOM
188
+
189
+ file "recipes/default.rb", <<-EOM
190
+ email_alias "outer1" do
191
+ recipients [ "out1a", "out1b" ]
192
+ end
193
+
194
+ nested "nested1" do
195
+ recipients [ "nested1a", "nested1b" ]
196
+ end
197
+
198
+ email_alias "outer2" do
199
+ recipients [ "out2a", "out2b" ]
200
+ end
201
+
202
+ doubly_nested "nested2" do
203
+ recipients [ "nested2a", "nested2b" ]
204
+ end
205
+
206
+ email_alias "outer3" do
207
+ recipients [ "out3a", "out3b" ]
208
+ end
209
+ EOM
210
+
211
+ file "templates/aliases.erb", <<-EOM.gsub(/^\s+/, "")
212
+ <%= pp @aliases %>
213
+ EOM
214
+ end # directory 'cookbooks/x'
215
+ end
216
+
217
+ it "should complete with success" do
218
+ file "config/client.rb", <<-EOM
219
+ local_mode true
220
+ cookbook_path "#{path_to('cookbooks')}"
221
+ log_level :warn
222
+ EOM
223
+
224
+ result = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" --no-color -F doc -o 'x::default'", :cwd => chef_dir)
225
+ result.error!
226
+ # runs only a single template resource (in the outer run context, as a delayed resource)
227
+ expect(result.stdout.scan(/template\S+ action create/).size).to eql(1)
228
+ # hash order is insertion order in ruby >= 1.9, so this next line does test that all calls were in the correct order
229
+ expect(IO.read(aliases_temppath).chomp).to eql('{"outer1"=>["out1a", "out1b"], "nested1"=>["nested1a", "nested1b"], "outer2"=>["out2a", "out2b"], "nested2"=>["nested2a", "nested2b"], "outer3"=>["out3a", "out3b"]}')
230
+ end
231
+ end
232
+ end
@@ -498,7 +498,7 @@ module ResourceActionSpec
498
498
  it "Raises an error when attempting to use a template in the action" do
499
499
  expect_converge do
500
500
  has_property_named_template "hi"
501
- end.to raise_error(/Property template of has_property_named_template\[hi\] cannot be passed a block! If you meant to create a resource named template instead, you'll need to first rename the property./)
501
+ end.to raise_error(/Property `template` of `has_property_named_template\[hi\]` was incorrectly passed a block. Possible property-resource collision. To call a resource named `template` either rename the property or else use `declare_resource\(:template, ...\)`/)
502
502
  end
503
503
  end
504
504
 
@@ -174,13 +174,13 @@ RSpec.configure do |config|
174
174
 
175
175
  running_platform_arch = `uname -m`.strip unless windows?
176
176
 
177
- config.filter_run_excluding :arch => lambda {|target_arch|
177
+ config.filter_run_excluding :arch => lambda { |target_arch|
178
178
  running_platform_arch != target_arch
179
179
  }
180
180
 
181
181
  # Functional Resource tests that are provider-specific:
182
182
  # context "on platforms that use useradd", :provider => {:user => Chef::Provider::User::Useradd}} do #...
183
- config.filter_run_excluding :provider => lambda {|criteria|
183
+ config.filter_run_excluding :provider => lambda { |criteria|
184
184
  type, target_provider = criteria.first
185
185
 
186
186
  node = TEST_NODE.dup
@@ -68,9 +68,10 @@ shared_context "a client run" do
68
68
  let(:api_client_exists?) { false }
69
69
  let(:enable_fork) { false }
70
70
 
71
- let(:http_cookbook_sync) { double("Chef::ServerAPI (cookbook sync)") }
72
- let(:http_node_load) { double("Chef::ServerAPI (node)") }
73
- let(:http_node_save) { double("Chef::ServerAPI (node save)") }
71
+ let(:http_data_collector) { double("Chef::ServerAPI (data collector)") }
72
+ let(:http_cookbook_sync) { double("Chef::ServerAPI (cookbook sync)") }
73
+ let(:http_node_load) { double("Chef::ServerAPI (node)") }
74
+ let(:http_node_save) { double("Chef::ServerAPI (node save)") }
74
75
  let(:reporting_rest_client) { double("Chef::ServerAPI (reporting client)") }
75
76
 
76
77
  let(:runner) { instance_double("Chef::Runner") }
@@ -92,6 +93,13 @@ shared_context "a client run" do
92
93
  end
93
94
  end
94
95
 
96
+ def stub_for_data_collector_init
97
+ expect(Chef::ServerAPI).to receive(:new).
98
+ with(Chef::Config[:data_collector][:server_url]).
99
+ exactly(:once).
100
+ and_return(http_data_collector)
101
+ end
102
+
95
103
  def stub_for_node_load
96
104
  # Client.register will then turn around create another
97
105
  # Chef::ServerAPI object, this time with the client key it got from the
@@ -154,6 +162,7 @@ shared_context "a client run" do
154
162
 
155
163
  stub_rest_clean
156
164
  stub_for_register
165
+ stub_for_data_collector_init
157
166
  stub_for_node_load
158
167
  stub_for_sync_cookbooks
159
168
  stub_for_converge
@@ -1,7 +1,7 @@
1
1
  #
2
2
  # Author:: John Keiser (<jkeiser@chef.io>)
3
3
  # Author:: Ho-Sheng Hsiao (<hosh@chef.io>)
4
- # Copyright:: Copyright 2012-2016, 2013-2015 Chef Software, Inc.
4
+ # Copyright:: Copyright 2012-2016 Chef Software, Inc.
5
5
  # License:: Apache License, Version 2.0
6
6
  #
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -64,8 +64,11 @@ module KnifeSupport
64
64
  subcommand_class.load_deps
65
65
  instance = subcommand_class.new(args)
66
66
 
67
+ # Load configs
68
+ instance.merge_configs
69
+
67
70
  # Capture stdout/stderr
68
- instance.ui = Chef::Knife::UI.new(stdout, stderr, stdin, disable_editing: true)
71
+ instance.ui = Chef::Knife::UI.new(stdout, stderr, stdin, instance.config.merge(disable_editing: true))
69
72
 
70
73
  # Don't print stuff
71
74
  Chef::Config[:verbosity] = ( DEBUG ? 2 : 0 )
@@ -113,6 +113,7 @@ describe Chef::DataCollector::Messages do
113
113
  status
114
114
  total_resource_count
115
115
  updated_resource_count
116
+ deprecations
116
117
  }
117
118
  end
118
119
  let(:optional_fields) { %w{error} }
@@ -164,6 +165,7 @@ describe Chef::DataCollector::Messages do
164
165
  status
165
166
  total_resource_count
166
167
  updated_resource_count
168
+ deprecations
167
169
  }
168
170
  end
169
171
  let(:optional_fields) { [] }
@@ -23,6 +23,7 @@ require "chef/data_collector"
23
23
  require "chef/resource_builder"
24
24
 
25
25
  describe Chef::DataCollector do
26
+
26
27
  describe ".register_reporter?" do
27
28
  context "when no data collector URL is configured" do
28
29
  it "returns false" do
@@ -44,23 +45,93 @@ describe Chef::DataCollector do
44
45
  end
45
46
 
46
47
  context "when not operating in why_run mode" do
48
+
47
49
  before do
48
50
  Chef::Config[:why_run] = false
51
+ Chef::Config[:data_collector][:token] = token
49
52
  end
50
53
 
51
- context "when report is enabled for current mode" do
52
- it "returns true" do
53
- allow(Chef::DataCollector).to receive(:reporter_enabled_for_current_mode?).and_return(true)
54
- expect(Chef::DataCollector.register_reporter?).to be_truthy
54
+ context "when a token is configured" do
55
+
56
+ let(:token) { "supersecrettoken" }
57
+
58
+ context "when report is enabled for current mode" do
59
+ it "returns true" do
60
+ allow(Chef::DataCollector).to receive(:reporter_enabled_for_current_mode?).and_return(true)
61
+ expect(Chef::DataCollector.register_reporter?).to be_truthy
62
+ end
55
63
  end
64
+
65
+ context "when report is disabled for current mode" do
66
+ it "returns false" do
67
+ allow(Chef::DataCollector).to receive(:reporter_enabled_for_current_mode?).and_return(false)
68
+ expect(Chef::DataCollector.register_reporter?).to be_falsey
69
+ end
70
+ end
71
+
56
72
  end
57
73
 
58
- context "when report is disabled for current mode" do
59
- it "returns false" do
60
- allow(Chef::DataCollector).to receive(:reporter_enabled_for_current_mode?).and_return(false)
61
- expect(Chef::DataCollector.register_reporter?).to be_falsey
74
+ # `Chef::Config[:data_collector][:server_url]` defaults to a URL
75
+ # relative to the `chef_server_url`, so we use configuration of the
76
+ # token to infer whether a solo/local mode user intends for data
77
+ # collection to be enabled.
78
+ context "when a token is not configured" do
79
+
80
+ let(:token) { nil }
81
+
82
+ context "when report is enabled for current mode" do
83
+
84
+ before do
85
+ allow(Chef::DataCollector).to receive(:reporter_enabled_for_current_mode?).and_return(true)
86
+ end
87
+
88
+ context "when the current mode is solo" do
89
+
90
+ before do
91
+ Chef::Config[:solo] = true
92
+ end
93
+
94
+ it "returns true" do
95
+ expect(Chef::DataCollector.register_reporter?).to be(true)
96
+ end
97
+
98
+ end
99
+
100
+ context "when the current mode is local mode" do
101
+
102
+ before do
103
+ Chef::Config[:local_mode] = true
104
+ end
105
+
106
+ it "returns false" do
107
+ expect(Chef::DataCollector.register_reporter?).to be(true)
108
+ end
109
+ end
110
+
111
+ context "when the current mode is client mode" do
112
+
113
+ before do
114
+ Chef::Config[:local_mode] = false
115
+ Chef::Config[:solo] = false
116
+ end
117
+
118
+ it "returns true" do
119
+ expect(Chef::DataCollector.register_reporter?).to be_truthy
120
+ end
121
+
122
+ end
123
+
124
+ end
125
+
126
+ context "when report is disabled for current mode" do
127
+ it "returns false" do
128
+ allow(Chef::DataCollector).to receive(:reporter_enabled_for_current_mode?).and_return(false)
129
+ expect(Chef::DataCollector.register_reporter?).to be_falsey
130
+ end
62
131
  end
132
+
63
133
  end
134
+
64
135
  end
65
136
  end
66
137
  end
@@ -150,14 +221,52 @@ describe Chef::DataCollector do
150
221
  end
151
222
  end
152
223
  end
224
+
153
225
  end
154
226
 
155
227
  describe Chef::DataCollector::Reporter do
156
228
  let(:reporter) { described_class.new }
157
229
  let(:run_status) { Chef::RunStatus.new(Chef::Node.new, Chef::EventDispatch::Dispatcher.new) }
158
230
 
231
+ let(:token) { "supersecrettoken" }
232
+
159
233
  before do
160
234
  Chef::Config[:data_collector][:server_url] = "http://my-data-collector-server.mycompany.com"
235
+ Chef::Config[:data_collector][:token] = token
236
+ end
237
+
238
+ describe "selecting token or signed header authentication" do
239
+
240
+ context "when the token is set in the config" do
241
+
242
+ before do
243
+ Chef::Config[:client_key] = "/no/key/should/exist/at/this/path.pem"
244
+ end
245
+
246
+ it "configures an HTTP client that doesn't do signed header auth" do
247
+ # Initializing with the wrong kind of HTTP class should cause Chef::Exceptions::PrivateKeyMissing
248
+ expect { reporter.http }.to_not raise_error
249
+ end
250
+
251
+ end
252
+
253
+ context "when no token is set in the config" do
254
+
255
+ let(:token) { nil }
256
+
257
+ let(:client_key) { File.join(CHEF_SPEC_DATA, "ssl", "private_key.pem") }
258
+
259
+ before do
260
+ Chef::Config[:client_key] = client_key
261
+ end
262
+
263
+ it "configures an HTTP client that does signed header auth" do
264
+ expect { reporter.http }.to_not raise_error
265
+ expect(reporter.http.options).to have_key(:signing_key_filename)
266
+ expect(reporter.http.options[:signing_key_filename]).to eq(client_key)
267
+ end
268
+ end
269
+
161
270
  end
162
271
 
163
272
  describe "#run_started" do
@@ -177,24 +286,52 @@ describe Chef::DataCollector::Reporter do
177
286
  .to receive(:run_start_message)
178
287
  .with(run_status)
179
288
  .and_return(key: "value")
180
- expect(reporter).to receive(:send_to_data_collector).with('{"key":"value"}')
289
+ expect(reporter).to receive(:send_to_data_collector).with({ key: "value" })
181
290
  reporter.run_started(run_status)
182
291
  end
183
292
  end
184
293
 
185
- describe "#run_completed" do
186
- it "sends the run completion" do
187
- node = Chef::Node.new
294
+ describe "when sending a message at chef run completion" do
188
295
 
189
- expect(reporter).to receive(:send_run_completion).with(status: "success")
190
- reporter.run_completed(node)
296
+ let(:node) { Chef::Node.new }
297
+
298
+ let(:run_status) do
299
+ instance_double("Chef::RunStatus",
300
+ run_id: "run_id",
301
+ node: node,
302
+ start_time: Time.new,
303
+ end_time: Time.new,
304
+ exception: exception)
191
305
  end
192
- end
193
306
 
194
- describe "#run_failed" do
195
- it "updates the exception and sends the run completion" do
196
- expect(reporter).to receive(:send_run_completion).with(status: "failure")
197
- reporter.run_failed("test_exception")
307
+ before do
308
+ reporter.send(:update_run_status, run_status)
309
+ end
310
+
311
+ describe "#run_completed" do
312
+
313
+ let(:exception) { nil }
314
+
315
+ it "sends the run completion" do
316
+ expect(reporter).to receive(:send_to_data_collector) do |message|
317
+ expect(message).to be_a(Hash)
318
+ expect(message["status"]).to eq("success")
319
+ end
320
+ reporter.run_completed(node)
321
+ end
322
+ end
323
+
324
+ describe "#run_failed" do
325
+
326
+ let(:exception) { StandardError.new("oops") }
327
+
328
+ it "updates the exception and sends the run completion" do
329
+ expect(reporter).to receive(:send_to_data_collector) do |message|
330
+ expect(message).to be_a(Hash)
331
+ expect(message["status"]).to eq("failure")
332
+ end
333
+ reporter.run_failed("test_exception")
334
+ end
198
335
  end
199
336
  end
200
337
 
@@ -511,9 +648,9 @@ describe Chef::DataCollector::Reporter do
511
648
  end
512
649
 
513
650
  context "when raise-on-failure is disabled" do
514
- it "logs a warning and does not raise an exception" do
651
+ it "logs an info message and does not raise an exception" do
515
652
  Chef::Config[:data_collector][:raise_on_failure] = false
516
- expect(Chef::Log).to receive(:warn)
653
+ expect(Chef::Log).to receive(:info)
517
654
  expect { reporter.send(:disable_reporter_on_error) { raise exception_class.new("bummer") } }.not_to raise_error
518
655
  end
519
656
  end