chef 12.16.42 → 12.17.44

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -1
  3. data/README.md +20 -5
  4. data/Rakefile +17 -0
  5. data/VERSION +1 -1
  6. data/acceptance/Gemfile.lock +32 -23
  7. data/distro/common/markdown/man1/knife-configure.mkd +3 -2
  8. data/lib-backcompat/chef/chef_fs/file_system/already_exists_error.rb +1 -1
  9. data/lib-backcompat/chef/chef_fs/file_system/cookbook_frozen_error.rb +1 -1
  10. data/lib-backcompat/chef/chef_fs/file_system/default_environment_cannot_be_modified_error.rb +1 -1
  11. data/lib-backcompat/chef/chef_fs/file_system/file_system_error.rb +1 -1
  12. data/lib-backcompat/chef/chef_fs/file_system/must_delete_recursively_error.rb +1 -1
  13. data/lib-backcompat/chef/chef_fs/file_system/not_found_error.rb +1 -1
  14. data/lib-backcompat/chef/chef_fs/file_system/operation_failed_error.rb +1 -1
  15. data/lib-backcompat/chef/chef_fs/file_system/operation_not_allowed_error.rb +1 -1
  16. data/lib-backcompat/chef/chef_fs/file_system/repository/chef_repository_file_system_entry.rb +1 -1
  17. data/lib-backcompat/chef/chef_fs/file_system/repository/file_system_root_dir.rb +1 -1
  18. data/lib/chef/api_client.rb +1 -1
  19. data/lib/chef/application.rb +1 -1
  20. data/lib/chef/application/exit_code.rb +3 -3
  21. data/lib/chef/chef_class.rb +15 -5
  22. data/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb +12 -1
  23. data/lib/chef/chef_fs/file_system/repository/nodes_dir.rb +19 -0
  24. data/lib/chef/client.rb +1 -0
  25. data/lib/chef/cookbook/metadata.rb +2 -2
  26. data/lib/chef/cookbook_version.rb +4 -4
  27. data/lib/chef/data_bag.rb +1 -1
  28. data/lib/chef/data_bag_item.rb +1 -1
  29. data/lib/chef/data_collector.rb +20 -13
  30. data/lib/chef/data_collector/messages.rb +0 -1
  31. data/lib/chef/data_collector/messages/helpers.rb +2 -2
  32. data/lib/chef/decorator/unchain.rb +2 -2
  33. data/lib/chef/deprecated.rb +190 -0
  34. data/lib/chef/deprecation/provider/remote_directory.rb +1 -1
  35. data/lib/chef/deprecation/warnings.rb +3 -4
  36. data/lib/chef/dsl/method_missing.rb +2 -2
  37. data/lib/chef/dsl/resources.rb +2 -2
  38. data/lib/chef/environment.rb +1 -1
  39. data/lib/chef/exceptions.rb +1 -1
  40. data/lib/chef/formatters/base.rb +11 -1
  41. data/lib/chef/formatters/doc.rb +13 -4
  42. data/lib/chef/key.rb +1 -1
  43. data/lib/chef/knife/client_delete.rb +12 -9
  44. data/lib/chef/knife/configure.rb +1 -1
  45. data/lib/chef/knife/core/bootstrap_context.rb +25 -1
  46. data/lib/chef/knife/core/subcommand_loader.rb +3 -3
  47. data/lib/chef/knife/core/ui.rb +1 -1
  48. data/lib/chef/knife/node_delete.rb +6 -6
  49. data/lib/chef/log.rb +1 -1
  50. data/lib/chef/mixin/deprecation.rb +4 -10
  51. data/lib/chef/mixin/powershell_type_coercions.rb +19 -19
  52. data/lib/chef/mixin/shell_out.rb +1 -1
  53. data/lib/chef/node.rb +2 -2
  54. data/lib/chef/node/attribute.rb +3 -4
  55. data/lib/chef/node/common_api.rb +1 -1
  56. data/lib/chef/node/mixin/state_tracking.rb +5 -2
  57. data/lib/chef/node_map.rb +2 -2
  58. data/lib/chef/org.rb +1 -1
  59. data/lib/chef/platform/rebooter.rb +3 -1
  60. data/lib/chef/policy_builder/expand_node_object.rb +1 -1
  61. data/lib/chef/property.rb +5 -5
  62. data/lib/chef/provider.rb +4 -4
  63. data/lib/chef/provider/launchd.rb +1 -1
  64. data/lib/chef/provider/link.rb +6 -0
  65. data/lib/chef/provider/mount.rb +2 -0
  66. data/lib/chef/provider/mount/mount.rb +1 -1
  67. data/lib/chef/provider/ohai.rb +5 -3
  68. data/lib/chef/provider/package/cab.rb +1 -1
  69. data/lib/chef/provider/package/chocolatey.rb +2 -2
  70. data/lib/chef/provider/package/easy_install.rb +2 -2
  71. data/lib/chef/provider/package/msu.rb +162 -0
  72. data/lib/chef/provider/package/powershell.rb +114 -0
  73. data/lib/chef/provider/package/yum.rb +1 -1
  74. data/lib/chef/provider/yum_repository.rb +6 -7
  75. data/lib/chef/provider_resolver.rb +2 -2
  76. data/lib/chef/providers.rb +2 -0
  77. data/lib/chef/resource.rb +3 -5
  78. data/lib/chef/resource/apt_update.rb +1 -1
  79. data/lib/chef/resource/chef_gem.rb +2 -3
  80. data/lib/chef/resource/file/verification.rb +1 -1
  81. data/lib/chef/resource/launchd.rb +48 -8
  82. data/lib/chef/resource/mount.rb +1 -1
  83. data/lib/chef/resource/msu_package.rb +47 -0
  84. data/lib/chef/resource/ohai.rb +5 -25
  85. data/lib/chef/resource/powershell_package.rb +41 -0
  86. data/lib/chef/resource/reboot.rb +1 -1
  87. data/lib/chef/resource/user.rb +2 -2
  88. data/lib/chef/resource_builder.rb +4 -4
  89. data/lib/chef/resource_resolver.rb +2 -3
  90. data/lib/chef/resources.rb +2 -0
  91. data/lib/chef/rest.rb +1 -1
  92. data/lib/chef/role.rb +1 -1
  93. data/lib/chef/run_context.rb +3 -3
  94. data/lib/chef/shell/ext.rb +2 -2
  95. data/lib/chef/user.rb +3 -3
  96. data/lib/chef/user_v1.rb +1 -1
  97. data/lib/chef/version.rb +1 -1
  98. data/lib/chef/win32/api/security.rb +12 -12
  99. data/spec/data/sample_msu1.xml +10 -0
  100. data/spec/data/sample_msu2.xml +14 -0
  101. data/spec/data/sample_msu3.xml +16 -0
  102. data/spec/functional/rebooter_spec.rb +3 -3
  103. data/spec/functional/resource/link_spec.rb +62 -1
  104. data/spec/functional/resource/msu_package_spec.rb +84 -0
  105. data/spec/functional/resource/registry_spec.rb +3 -3
  106. data/spec/functional/resource/rpm_spec.rb +7 -10
  107. data/spec/integration/solo/solo_spec.rb +50 -0
  108. data/spec/spec_helper.rb +3 -0
  109. data/spec/support/platform_helpers.rb +16 -8
  110. data/spec/unit/application/exit_code_spec.rb +3 -15
  111. data/spec/unit/data_collector_spec.rb +6 -16
  112. data/spec/unit/deprecated_spec.rb +59 -0
  113. data/spec/unit/deprecation_spec.rb +1 -8
  114. data/spec/unit/handler_spec.rb +2 -2
  115. data/spec/unit/knife/client_delete_spec.rb +16 -0
  116. data/spec/unit/knife/configure_spec.rb +1 -1
  117. data/spec/unit/knife/cookbook_metadata_spec.rb +116 -113
  118. data/spec/unit/knife/core/bootstrap_context_spec.rb +55 -5
  119. data/spec/unit/knife/node_delete_spec.rb +19 -10
  120. data/spec/unit/mixin/shell_out_spec.rb +0 -1
  121. data/spec/unit/node/immutable_collections_spec.rb +5 -0
  122. data/spec/unit/node/vivid_mash_spec.rb +11 -0
  123. data/spec/unit/node_spec.rb +2 -2
  124. data/spec/unit/provider/launchd_spec.rb +81 -3
  125. data/spec/unit/provider/mount/mount_spec.rb +1 -1
  126. data/spec/unit/provider/mount_spec.rb +7 -0
  127. data/spec/unit/provider/package/chocolatey_spec.rb +5 -5
  128. data/spec/unit/provider/package/easy_install_spec.rb +6 -6
  129. data/spec/unit/provider/package/msu_spec.rb +283 -0
  130. data/spec/unit/provider/package/powershell_spec.rb +337 -0
  131. data/spec/unit/provider/service/macosx_spec.rb +1 -1
  132. data/spec/unit/provider/subversion_spec.rb +9 -0
  133. data/spec/unit/provider/user/linux_spec.rb +7 -1
  134. data/spec/unit/recipe_spec.rb +43 -11
  135. data/spec/unit/resource/apt_update_spec.rb +17 -25
  136. data/spec/unit/resource/file/verification_spec.rb +1 -1
  137. data/spec/unit/resource/mount_spec.rb +2 -1
  138. data/spec/unit/resource/msu_package_spec.rb +49 -0
  139. data/spec/unit/resource/ohai_spec.rb +1 -1
  140. data/spec/unit/resource/powershell_package_spec.rb +68 -0
  141. data/spec/unit/resource_reporter_spec.rb +4 -4
  142. data/spec/unit/run_status_spec.rb +1 -1
  143. data/tasks/announce.rb +58 -0
  144. data/tasks/changelog.rb +26 -6
  145. data/tasks/templates/prerelease.md.erb +35 -0
  146. data/tasks/templates/release.md.erb +34 -0
  147. metadata +21 -4
@@ -30,6 +30,8 @@ describe Chef::Knife::Core::BootstrapContext do
30
30
  let(:run_list) { Chef::RunList.new("recipe[tmux]", "role[base]") }
31
31
  let(:chef_config) do
32
32
  {
33
+ :config_log_level => "info",
34
+ :config_log_location => "/tmp/log",
33
35
  :validation_key => File.join(CHEF_SPEC_DATA, "ssl", "private_key.pem"),
34
36
  :chef_server_url => "http://chef.example.com:4444",
35
37
  :validation_client_name => "chef-validator-testing",
@@ -68,18 +70,15 @@ describe Chef::Knife::Core::BootstrapContext do
68
70
 
69
71
  it "generates the config file data" do
70
72
  expected = <<-EXPECTED
71
- log_location STDOUT
72
73
  chef_server_url "http://chef.example.com:4444"
73
74
  validation_client_name "chef-validator-testing"
75
+ log_level :info
76
+ log_location "/tmp/log"
74
77
  # Using default node name (fqdn)
75
78
  EXPECTED
76
79
  expect(bootstrap_context.config_content).to eq expected
77
80
  end
78
81
 
79
- it "does not set a default log_level" do
80
- expect(bootstrap_context.config_content).not_to match(/log_level/)
81
- end
82
-
83
82
  describe "alternate chef-client path" do
84
83
  let(:chef_config) { { :chef_client_path => "/usr/local/bin/chef-client" } }
85
84
  it "runs chef-client from another path when specified" do
@@ -254,4 +253,55 @@ EXPECTED
254
253
  end
255
254
  end
256
255
 
256
+ describe "#config_log_location" do
257
+ context "when config_log_location is nil" do
258
+ let(:chef_config) { { :config_log_location => nil } }
259
+ it "sets the default config_log_location in the client.rb" do
260
+ expect(bootstrap_context.get_log_location).to eq "STDOUT"
261
+ end
262
+ end
263
+
264
+ context "when config_log_location is empty" do
265
+ let(:chef_config) { { :config_log_location => "" } }
266
+ it "sets the default config_log_location in the client.rb" do
267
+ expect(bootstrap_context.get_log_location).to eq "STDOUT"
268
+ end
269
+ end
270
+
271
+ context "when config_log_location is :win_evt" do
272
+ let(:chef_config) { { :config_log_location => :win_evt } }
273
+ it "raise error when config_log_location is :win_evt " do
274
+ expect { bootstrap_context.get_log_location }.to raise_error("The value :win_evt is not supported for config_log_location on Linux Platforms \n")
275
+ end
276
+ end
277
+
278
+ context "when config_log_location is :syslog" do
279
+ let(:chef_config) { { :config_log_location => :syslog } }
280
+ it "sets the config_log_location value as :syslog in the client.rb" do
281
+ expect(bootstrap_context.get_log_location).to eq ":syslog"
282
+ end
283
+ end
284
+
285
+ context "When config_log_location is STDOUT" do
286
+ let(:chef_config) { { :config_log_location => STDOUT } }
287
+ it "Sets the config_log_location value as STDOUT in the client.rb" do
288
+ expect(bootstrap_context.get_log_location).to eq "STDOUT"
289
+ end
290
+ end
291
+
292
+ context "when config_log_location is STDERR" do
293
+ let(:chef_config) { { :config_log_location => STDERR } }
294
+ it "sets the config_log_location value as STDERR in the client.rb" do
295
+ expect(bootstrap_context.get_log_location).to eq "STDERR"
296
+ end
297
+ end
298
+
299
+ context "when config_log_location is a path" do
300
+ let(:chef_config) { { :config_log_location => "/tmp/ChefLogFile" } }
301
+ it "sets the config_log_location path in the client.rb" do
302
+ expect(bootstrap_context.get_log_location).to eq "\"/tmp/ChefLogFile\""
303
+ end
304
+ end
305
+
306
+ end
257
307
  end
@@ -25,12 +25,17 @@ describe Chef::Knife::NodeDelete do
25
25
  @knife.config = {
26
26
  :print_after => nil,
27
27
  }
28
- @knife.name_args = [ "adam" ]
28
+ @knife.name_args = %w{ adam ben }
29
29
  allow(@knife).to receive(:output).and_return(true)
30
30
  allow(@knife).to receive(:confirm).and_return(true)
31
- @node = Chef::Node.new()
32
- allow(@node).to receive(:destroy).and_return(true)
33
- allow(Chef::Node).to receive(:load).and_return(@node)
31
+
32
+ @adam_node = Chef::Node.new()
33
+ @ben_node = Chef::Node.new()
34
+ allow(@ben_node).to receive(:destroy).and_return(true)
35
+ allow(@adam_node).to receive(:destroy).and_return(true)
36
+ allow(Chef::Node).to receive(:load).with("adam").and_return(@adam_node)
37
+ allow(Chef::Node).to receive(:load).with("ben").and_return(@ben_node)
38
+
34
39
  @stdout = StringIO.new
35
40
  allow(@knife.ui).to receive(:stdout).and_return(@stdout)
36
41
  end
@@ -41,13 +46,15 @@ describe Chef::Knife::NodeDelete do
41
46
  @knife.run
42
47
  end
43
48
 
44
- it "should load the node" do
45
- expect(Chef::Node).to receive(:load).with("adam").and_return(@node)
49
+ it "should load the nodes" do
50
+ expect(Chef::Node).to receive(:load).with("adam").and_return(@adam_node)
51
+ expect(Chef::Node).to receive(:load).with("ben").and_return(@ben_node)
46
52
  @knife.run
47
53
  end
48
54
 
49
- it "should delete the node" do
50
- expect(@node).to receive(:destroy).and_return(@node)
55
+ it "should delete the nodes" do
56
+ expect(@adam_node).to receive(:destroy).and_return(@adam_node)
57
+ expect(@ben_node).to receive(:destroy).and_return(@ben_node)
51
58
  @knife.run
52
59
  end
53
60
 
@@ -59,8 +66,10 @@ describe Chef::Knife::NodeDelete do
59
66
  describe "with -p or --print-after" do
60
67
  it "should pretty print the node, formatted for display" do
61
68
  @knife.config[:print_after] = true
62
- expect(@knife).to receive(:format_for_display).with(@node).and_return("poop")
63
- expect(@knife).to receive(:output).with("poop")
69
+ expect(@knife).to receive(:format_for_display).with(@adam_node).and_return("adam")
70
+ expect(@knife).to receive(:format_for_display).with(@ben_node).and_return("ben")
71
+ expect(@knife).to receive(:output).with("adam")
72
+ expect(@knife).to receive(:output).with("ben")
64
73
  @knife.run
65
74
  end
66
75
  end
@@ -59,7 +59,6 @@ describe Chef::Mixin::ShellOut do
59
59
  it "should emit a deprecation warning" do
60
60
  assume_deprecation_log_level && capture_log_output
61
61
  subject
62
- expect(output.string).to match /DEPRECATION:/
63
62
  expect(output.string).to match Regexp.escape(old_option.to_s)
64
63
  expect(output.string).to match Regexp.escape(new_option.to_s)
65
64
  end
@@ -198,4 +198,9 @@ describe Chef::Node::ImmutableArray do
198
198
  end
199
199
  end
200
200
 
201
+ describe "#[]" do
202
+ it "works with array slices" do
203
+ expect(@immutable_array[1, 2]).to eql(%w{bar baz})
204
+ end
205
+ end
201
206
  end
@@ -47,7 +47,18 @@ describe Chef::Node::VividMash do
47
47
  end
48
48
  end
49
49
 
50
+ context "#[]" do
51
+ it "works with array slices" do
52
+ expect(vivid["array"][1, 2]).to eql([1, 2])
53
+ end
54
+ end
55
+
50
56
  context "#[]=" do
57
+ it "works with array slices" do
58
+ vivid["array"][3, 2] = [ 3, 4 ]
59
+ expect(vivid["array"]).to eql([0, 1, 2, 3, 4])
60
+ end
61
+
51
62
  it "deep converts values through arrays" do
52
63
  expect(root).to receive(:reset_cache).with("foo")
53
64
  vivid["foo"] = [ { :bar => true } ]
@@ -335,14 +335,14 @@ describe Chef::Node do
335
335
 
336
336
  it "set is a deprecated alias for normal" do
337
337
  Chef::Config[:treat_deprecation_warnings_as_errors] = false
338
- expect(Chef).to receive(:log_deprecation).with(/set is deprecated/)
338
+ expect(Chef).to receive(:deprecated).with(:attributes, /set is deprecated/)
339
339
  node.set[:snoopy][:is_a_puppy] = true
340
340
  expect(node[:snoopy][:is_a_puppy]).to eq(true)
341
341
  end
342
342
 
343
343
  it "set_unless is a deprecated alias for normal_unless" do
344
344
  Chef::Config[:treat_deprecation_warnings_as_errors] = false
345
- expect(Chef).to receive(:log_deprecation).with(/set_unless is deprecated/)
345
+ expect(Chef).to receive(:deprecated).with(:attributes, /set_unless is deprecated/)
346
346
  node.set_unless[:snoopy][:is_a_puppy] = false
347
347
  expect(node[:snoopy][:is_a_puppy]).to eq(false)
348
348
  end
@@ -40,7 +40,7 @@ describe Chef::Provider::Launchd do
40
40
  \t<string>/Library/scripts/call_mom.sh</string>
41
41
  \t<key>StartCalendarInterval</key>
42
42
  \t<dict>
43
- \t\t<key>Hourly</key>
43
+ \t\t<key>Hour</key>
44
44
  \t\t<integer>10</integer>
45
45
  \t\t<key>Weekday</key>
46
46
  \t\t<integer>7</integer>
@@ -49,6 +49,35 @@ describe Chef::Provider::Launchd do
49
49
  \t<integer>300</integer>
50
50
  </dict>
51
51
  </plist>
52
+ XML
53
+ let(:test_plist_multiple_intervals) { String.new <<-XML }
54
+ <?xml version="1.0" encoding="UTF-8"?>
55
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
56
+ <plist version="1.0">
57
+ <dict>
58
+ \t<key>Label</key>
59
+ \t<string>call.mom.weekly</string>
60
+ \t<key>Program</key>
61
+ \t<string>/Library/scripts/call_mom.sh</string>
62
+ \t<key>StartCalendarInterval</key>
63
+ \t<array>
64
+ \t\t<dict>
65
+ \t\t\t<key>Hour</key>
66
+ \t\t\t<integer>11</integer>
67
+ \t\t\t<key>Weekday</key>
68
+ \t\t\t<integer>1</integer>
69
+ \t\t</dict>
70
+ \t\t<dict>
71
+ \t\t\t<key>Hour</key>
72
+ \t\t\t<integer>12</integer>
73
+ \t\t\t<key>Weekday</key>
74
+ \t\t\t<integer>2</integer>
75
+ \t\t</dict>
76
+ \t</array>
77
+ \t<key>TimeOut</key>
78
+ \t<integer>300</integer>
79
+ </dict>
80
+ </plist>
52
81
  XML
53
82
 
54
83
  let(:test_hash) do
@@ -56,7 +85,7 @@ XML
56
85
  "Label" => "call.mom.weekly",
57
86
  "Program" => "/Library/scripts/call_mom.sh",
58
87
  "StartCalendarInterval" => {
59
- "Hourly" => 10,
88
+ "Hour" => 10,
60
89
  "Weekday" => 7,
61
90
  },
62
91
  "TimeOut" => 300,
@@ -100,12 +129,61 @@ XML
100
129
  it "should produce the test_plist from properties" do
101
130
  new_resource.program "/Library/scripts/call_mom.sh"
102
131
  new_resource.time_out 300
103
- new_resource.start_calendar_interval "Hourly" => 10, "Weekday" => 7
132
+ new_resource.start_calendar_interval "Hour" => 10, "Weekday" => 7
104
133
  expect(provider.content?).to be_truthy
105
134
  expect(provider.content).to eql(test_plist)
106
135
  end
107
136
  end
108
137
 
138
+ describe "start_calendar_interval is passed" do
139
+ it "should allow array of Hashes" do
140
+ allowed = (1..2).collect do |num|
141
+ {
142
+ "Hour" => 10 + num,
143
+ "Weekday" => num,
144
+ }
145
+ end
146
+ new_resource.program "/Library/scripts/call_mom.sh"
147
+ new_resource.time_out 300
148
+ new_resource.start_calendar_interval allowed
149
+ expect(provider.content?).to be_truthy
150
+ expect(provider.content).to eql(test_plist_multiple_intervals)
151
+ end
152
+
153
+ it "should allow all StartCalendarInterval keys" do
154
+ allowed = {
155
+ "Minute" => 1,
156
+ "Hour" => 1,
157
+ "Day" => 1,
158
+ "Weekday" => 1,
159
+ "Month" => 1,
160
+ }
161
+ new_resource.program "/Library/scripts/call_mom.sh"
162
+ new_resource.time_out 300
163
+ new_resource.start_calendar_interval allowed
164
+ expect(provider.content?).to be_truthy
165
+ %w{Minute Hour Day Weekday Month}.each do |key|
166
+ expect(provider.content).to include("<key>#{key}</key>")
167
+ end
168
+ end
169
+
170
+ it "should not allow invalid ShowCalendarInterval keys" do
171
+ new_resource.program "/Library/scripts/call_mom.sh"
172
+ new_resource.time_out 300
173
+ expect do
174
+ new_resource.start_calendar_interval "Hourly" => 1
175
+ end.to raise_error(/Hourly are invalid/)
176
+ end
177
+
178
+ it "should not allow non-integer values" do
179
+ new_resource.program "/Library/scripts/call_mom.sh"
180
+ new_resource.time_out 300
181
+ expect do
182
+ new_resource.start_calendar_interval "Weekday" => "1-2"
183
+ end.to raise_error(/Invalid value.*\(1-2\)/)
184
+ end
185
+ end
186
+
109
187
  describe "hash is passed" do
110
188
  it "should produce the test_plist from the hash" do
111
189
  new_resource.hash test_hash
@@ -107,7 +107,7 @@ describe Chef::Provider::Mount::Mount do
107
107
  expect { @provider.load_current_resource(); @provider.mountable? }.to raise_error(Chef::Exceptions::Mount)
108
108
  end
109
109
 
110
- %w{tmpfs fuse cgroup}.each do |fstype|
110
+ %w{tmpfs fuse cgroup vboxsf zfs}.each do |fstype|
111
111
  it "does not expect the device to exist for #{fstype}" do
112
112
  @new_resource.fstype(fstype)
113
113
  @new_resource.device("whatever")
@@ -70,6 +70,13 @@ describe Chef::Provider::Mount do
70
70
  expect(new_resource).to be_updated_by_last_action
71
71
  end
72
72
 
73
+ it "should unmount the filesystem if it is mounted" do
74
+ allow(current_resource).to receive(:mounted).and_return(true)
75
+ expect(provider).to receive(:umount_fs).and_return(true)
76
+ provider.run_action(:unmount)
77
+ expect(new_resource).to be_updated_by_last_action
78
+ end
79
+
73
80
  it "should not umount the filesystem if it is not mounted" do
74
81
  allow(current_resource).to receive(:mounted).and_return(false)
75
82
  expect(provider).not_to receive(:umount_fs)
@@ -220,7 +220,7 @@ munin-node|1.6.1.20130823
220
220
  new_resource.package_name("ConEmu")
221
221
  new_resource.version("15.10.25.1")
222
222
  provider.load_current_resource
223
- expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y -version 15.10.25.1 conemu", { :timeout => timeout }).and_return(double)
223
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y --version 15.10.25.1 conemu", { :timeout => timeout }).and_return(double)
224
224
  provider.run_action(:install)
225
225
  expect(new_resource).to be_updated_by_last_action
226
226
  end
@@ -233,7 +233,7 @@ munin-node|1.6.1.20130823
233
233
  new_resource.package_name(%w{chocolatey ConEmu})
234
234
  new_resource.version([nil, "15.10.25.1"])
235
235
  provider.load_current_resource
236
- expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y -version 15.10.25.1 conemu", { :timeout => timeout }).and_return(double)
236
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y --version 15.10.25.1 conemu", { :timeout => timeout }).and_return(double)
237
237
  provider.run_action(:install)
238
238
  expect(new_resource).to be_updated_by_last_action
239
239
  end
@@ -243,7 +243,7 @@ munin-node|1.6.1.20130823
243
243
  new_resource.package_name("conemu")
244
244
  new_resource.version("15.10.25.1")
245
245
  provider.load_current_resource
246
- expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y -version 15.10.25.1 conemu", { :timeout => timeout }).and_return(double)
246
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y --version 15.10.25.1 conemu", { :timeout => timeout }).and_return(double)
247
247
  provider.run_action(:install)
248
248
  expect(new_resource).to be_updated_by_last_action
249
249
  end
@@ -253,7 +253,7 @@ munin-node|1.6.1.20130823
253
253
  new_resource.package_name(%w{ConEmu git})
254
254
  new_resource.version(["15.10.25.1", nil])
255
255
  provider.load_current_resource
256
- expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y -version 15.10.25.1 conemu", { :timeout => timeout }).and_return(double)
256
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y --version 15.10.25.1 conemu", { :timeout => timeout }).and_return(double)
257
257
  expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y git", { :timeout => timeout }).and_return(double)
258
258
  provider.run_action(:install)
259
259
  expect(new_resource).to be_updated_by_last_action
@@ -353,7 +353,7 @@ munin-node|1.6.1.20130823
353
353
  allow_remote_list(["git"])
354
354
  new_resource.version("2.6.2")
355
355
  provider.load_current_resource
356
- expect(provider).to receive(:shell_out!).with("#{choco_exe} upgrade -y -version 2.6.2 git", { :timeout => timeout })
356
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} upgrade -y --version 2.6.2 git", { :timeout => timeout })
357
357
  provider.run_action(:upgrade)
358
358
  expect(new_resource).to be_updated_by_last_action
359
359
  end
@@ -61,7 +61,7 @@ describe Chef::Provider::Package::EasyInstall do
61
61
 
62
62
  describe "actions_on_package" do
63
63
  it "should run easy_install with the package name and version" do
64
- expect(Chef).to receive(:log_deprecation).with(/easy_install package provider is deprecated/)
64
+ expect(Chef).to receive(:deprecated).with(:easy_install, /easy_install package provider is deprecated/)
65
65
  expect(@provider).to receive(:run_command).with({
66
66
  :command => "easy_install \"boto==1.8d\"",
67
67
  })
@@ -69,7 +69,7 @@ describe Chef::Provider::Package::EasyInstall do
69
69
  end
70
70
 
71
71
  it "should run easy_install with the package name and version and specified options" do
72
- expect(Chef).to receive(:log_deprecation).with(/easy_install package provider is deprecated/)
72
+ expect(Chef).to receive(:deprecated).with(:easy_install, /easy_install package provider is deprecated/)
73
73
  expect(@provider).to receive(:run_command).with({
74
74
  :command => "easy_install --always-unzip \"boto==1.8d\"",
75
75
  })
@@ -78,7 +78,7 @@ describe Chef::Provider::Package::EasyInstall do
78
78
  end
79
79
 
80
80
  it "should run easy_install with the package name and version" do
81
- expect(Chef).to receive(:log_deprecation).with(/easy_install package provider is deprecated/)
81
+ expect(Chef).to receive(:deprecated).with(:easy_install, /easy_install package provider is deprecated/)
82
82
  expect(@provider).to receive(:run_command).with({
83
83
  :command => "easy_install \"boto==1.8d\"",
84
84
  })
@@ -86,7 +86,7 @@ describe Chef::Provider::Package::EasyInstall do
86
86
  end
87
87
 
88
88
  it "should run easy_install -m with the package name and version" do
89
- expect(Chef).to receive(:log_deprecation).with(/easy_install package provider is deprecated/)
89
+ expect(Chef).to receive(:deprecated).with(:easy_install, /easy_install package provider is deprecated/)
90
90
  expect(@provider).to receive(:run_command).with({
91
91
  :command => "easy_install -m boto",
92
92
  })
@@ -94,7 +94,7 @@ describe Chef::Provider::Package::EasyInstall do
94
94
  end
95
95
 
96
96
  it "should run easy_install -m with the package name and version and specified options" do
97
- expect(Chef).to receive(:log_deprecation).with(/easy_install package provider is deprecated/)
97
+ expect(Chef).to receive(:deprecated).with(:easy_install, /easy_install package provider is deprecated/)
98
98
  expect(@provider).to receive(:run_command).with({
99
99
  :command => "easy_install -x -m boto",
100
100
  })
@@ -103,7 +103,7 @@ describe Chef::Provider::Package::EasyInstall do
103
103
  end
104
104
 
105
105
  it "should run easy_install -m with the package name and version" do
106
- expect(Chef).to receive(:log_deprecation).with(/easy_install package provider is deprecated/)
106
+ expect(Chef).to receive(:deprecated).with(:easy_install, /easy_install package provider is deprecated/)
107
107
  expect(@provider).to receive(:run_command).with({
108
108
  :command => "easy_install -m boto",
109
109
  })
@@ -0,0 +1,283 @@
1
+ #
2
+ # Author:: Nimisha Sharad (<nimisha.sharad@msystechnologies.com>)
3
+ # Copyright:: Copyright 2008-2016, Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require "spec_helper"
20
+
21
+ describe Chef::Provider::Package::Msu, :windows_only do
22
+ let(:timeout) {}
23
+
24
+ let(:new_resource) { Chef::Resource::MsuPackage.new("windows_test_pkg") }
25
+
26
+ let(:provider) do
27
+ node = Chef::Node.new
28
+ events = Chef::EventDispatch::Dispatcher.new
29
+ run_context = Chef::RunContext.new(node, {}, events)
30
+ Chef::Provider::Package::Msu.new(new_resource, run_context)
31
+ end
32
+
33
+ let(:installed_package_list_stdout) do
34
+ <<-EOF
35
+ Packages listing:
36
+ Package Identity : Package_for_KB2999486~31bf3856ad364e35~amd64~~6.1.9768.0
37
+ Package Identity : Package_for_KB2994825~31bf3856ad364e35~amd64~~6.1.7601.0
38
+ EOF
39
+ end
40
+
41
+ let(:package_version_stdout) do
42
+ <<-EOF
43
+ Package information:
44
+ Package Identity : Package_for_KB2664825~31bf3856ad364e35~amd64~~6.1.3.0
45
+ State : Installed
46
+ Dependency : Language Pack
47
+ The operation completed successfully
48
+ EOF
49
+ end
50
+
51
+ let(:get_package_info_stdout) do
52
+ <<-EOF
53
+ Deployment Image Servicing and Management tool
54
+ Version: 6.1.7600.16385
55
+
56
+ Image Version: 6.1.7600.16385
57
+
58
+ Package information:
59
+ Package Identity : Package_for_KB2664825~31bf3856ad364e35~amd64~~6.1.3.0
60
+ Applicable : Yes
61
+ Copyright : Microsoft Corporation
62
+ Company : Microsoft Corporation
63
+ State : Installed
64
+ Dependency : Language Pack
65
+ The operation completed successfully
66
+ EOF
67
+ end
68
+
69
+ def allow_get_packages
70
+ get_packages_stdout = <<-EOF
71
+ Deployment Image Servicing and Management tool
72
+ Version: 6.1.7600.16385
73
+
74
+ Image Version: 6.1.7600.16385
75
+
76
+ Packages listing:
77
+
78
+ Package Identity : Package_for_KB2999486~31bf3856ad364e35~amd64~~6.1.9768.0
79
+ State : Installed
80
+ Release Type : Language Pack
81
+ Install Time : 2/11/2015 11:33 PM
82
+
83
+ Package Identity : Package_for_KB2994825~31bf3856ad364e35~amd64~~6.1.7601.0
84
+ State : Installed
85
+ Release Type : Language Pack
86
+ Install Time : 2/11/2015 11:33 PM
87
+
88
+ Package Identity : Package_for_KB2664825~31bf3856ad364e35~amd64~~6.1.3.0
89
+ State : Installed
90
+ Release Type : Feature Pack
91
+ Install Time : 11/21/2010 3:40 AM
92
+
93
+ The operation completed successfully.
94
+ EOF
95
+ get_packages_obj = double(stdout: get_packages_stdout)
96
+ allow_any_instance_of(Chef::Provider::Package::Cab).to receive(:dism_command).with("/Get-Packages").and_return(get_packages_obj)
97
+ end
98
+
99
+ before do
100
+ allow(Dir).to receive(:mktmpdir)
101
+ allow(provider).to receive(:cleanup_after_converge)
102
+ end
103
+
104
+ describe "#initialize" do
105
+ it "returns the correct class" do
106
+ expect(provider).to be_kind_of(Chef::Provider::Package::Msu)
107
+ end
108
+ end
109
+
110
+ describe "#load_current_resource" do
111
+ before do
112
+ new_resource.source = "C:\\Temp\\Test6.1-KB2664825-v3-x64.msu"
113
+ cab_file = "c:\\temp\\test6.1-kb2664825-v3-x64.cab"
114
+ allow(provider).to receive(:extract_msu_contents)
115
+ allow(provider).to receive(:read_cab_files_from_xml).and_return([cab_file])
116
+ installed_package_list_obj = double(stdout: installed_package_list_stdout)
117
+ allow_any_instance_of(Chef::Provider::Package::Cab).to receive(:dism_command).with("/Get-Packages").and_return(installed_package_list_obj)
118
+ package_version_obj = double(stdout: package_version_stdout)
119
+ allow_any_instance_of(Chef::Provider::Package::Cab).to receive(:dism_command).with("/Get-PackageInfo /PackagePath:\"#{cab_file}\"").and_return(package_version_obj)
120
+ end
121
+
122
+ it "returns a current_resource" do
123
+ expect(provider.load_current_resource).to be_kind_of(Chef::Resource::MsuPackage)
124
+ end
125
+
126
+ it "sets the current_resource.version to nil when the package is not installed" do
127
+ provider.load_current_resource
128
+ expect(provider.current_resource.version).to eql([nil])
129
+ end
130
+
131
+ it "calls download_source_file method if source is a URL" do
132
+ new_resource.source = "https://www.something.com/Test6.1-KB2664825-v3-x64.msu"
133
+ expect(provider).to receive(:download_source_file)
134
+ provider.load_current_resource
135
+ end
136
+ end
137
+
138
+ describe "#source_resource" do
139
+ before do
140
+ new_resource.source = "C:\\Temp\\Test6.1-KB2664825-v3-x64.msu"
141
+ new_resource.cookbook_name = "Msu_package"
142
+ end
143
+
144
+ it "sets the desired parameters of downloades msu file" do
145
+ allow(provider).to receive(:default_download_cache_path).and_return("C:\\chef\\cache\\package")
146
+ source_resource = provider.source_resource
147
+ expect(source_resource.path).to be == "C:\\chef\\cache\\package"
148
+ expect(source_resource.name).to be == "windows_test_pkg"
149
+ expect(source_resource.source).to be == [new_resource.source]
150
+ expect(source_resource.cookbook_name).to be == "Msu_package"
151
+ expect(source_resource.checksum).to be == nil
152
+ end
153
+ end
154
+
155
+ describe "#default_download_cache_path" do
156
+ before do
157
+ new_resource.source = "https://www.something.com/Test6.1-KB2664825-v3-x64.msu"
158
+ end
159
+
160
+ it "returns a clean cache path where the msu file is downloaded" do
161
+ allow(Chef::FileCache).to receive(:create_cache_path).and_return("C:\\chef\\abc\\package")
162
+ path = provider.default_download_cache_path
163
+ expect(path).to be == "C:\\chef\\abc\\package\\Test6.1-KB2664825-v3-x64.msu"
164
+ end
165
+ end
166
+
167
+ describe "action specs" do
168
+ before do
169
+ new_resource.source = "C:\\Temp\\Test6.1-KB2664825-v3-x64.msu"
170
+ cab_file = "c:\\temp\\test6.1-kb2664825-v3-x64.cab"
171
+ allow(provider).to receive(:extract_msu_contents)
172
+ allow(provider).to receive(:read_cab_files_from_xml).and_return([cab_file])
173
+ installed_package_list_obj = double(stdout: installed_package_list_stdout)
174
+ allow_any_instance_of(Chef::Provider::Package::Cab).to receive(:dism_command).with("/Get-Packages").and_return(installed_package_list_obj)
175
+ package_version_obj = double(stdout: package_version_stdout)
176
+ allow_any_instance_of(Chef::Provider::Package::Cab).to receive(:dism_command).with("/Get-PackageInfo /PackagePath:\"#{cab_file}\"").and_return(package_version_obj)
177
+ end
178
+
179
+ describe "#action_install" do
180
+ it "installs package if not already installed" do
181
+ provider.load_current_resource
182
+ expect(provider.current_resource.version).to eql([nil])
183
+ expect(provider).to receive(:install_package)
184
+ provider.run_action(:install)
185
+ expect(new_resource).to be_updated_by_last_action
186
+ end
187
+
188
+ it "does not install package if already installed" do
189
+ get_package_info_obj = double(stdout: get_package_info_stdout)
190
+ allow_any_instance_of(Chef::Provider::Package::Cab).to receive(:dism_command).with("/Get-PackageInfo /PackagePath:\"#{new_resource.source}\"").and_return(get_package_info_obj)
191
+ allow_get_packages
192
+ allow_any_instance_of(Chef::Provider::Package::Cab).to receive(:dism_command).with("/Get-PackageInfo /PackageName:\"Package_for_KB2664825~31bf3856ad364e35~amd64~~6.1.3.0\"").and_return(get_package_info_obj)
193
+ provider.load_current_resource
194
+ expect(provider.current_resource.version).to eql(["6.1.3.0"])
195
+ expect(provider).not_to receive(:install_package)
196
+ provider.run_action(:install)
197
+ expect(new_resource).not_to be_updated_by_last_action
198
+ end
199
+ end
200
+
201
+ describe "#action_remove" do
202
+ it "does nothing when the package is not present" do
203
+ provider.load_current_resource
204
+ expect(provider).not_to receive(:remove_package)
205
+ provider.run_action(:remove)
206
+ expect(new_resource).not_to be_updated_by_last_action
207
+ end
208
+
209
+ it "removes packages if package is installed" do
210
+ get_package_info_obj = double(stdout: get_package_info_stdout)
211
+ allow_any_instance_of(Chef::Provider::Package::Cab).to receive(:dism_command).with("/Get-PackageInfo /PackagePath:\"#{new_resource.source}\"").and_return(get_package_info_obj)
212
+ allow_get_packages
213
+ allow_any_instance_of(Chef::Provider::Package::Cab).to receive(:dism_command).with("/Get-PackageInfo /PackageName:\"Package_for_KB2664825~31bf3856ad364e35~amd64~~6.1.3.0\"").and_return(get_package_info_obj)
214
+ provider.load_current_resource
215
+ expect(provider.current_resource.version).to eql(["6.1.3.0"])
216
+ expect(provider).to receive(:remove_package)
217
+ provider.run_action(:remove)
218
+ expect(new_resource).to be_updated_by_last_action
219
+ end
220
+ end
221
+
222
+ context "Invalid package source" do
223
+ def package_version_stdout
224
+ package_version_stdout = <<-EOF
225
+
226
+ Deployment Image Servicing and Management tool
227
+ Version: 6.1.7600.16385
228
+
229
+ Image Version: 6.1.7600.16385
230
+
231
+ An error occurred trying to open - c:\\temp\\test6.1-KB2664825-v3-x64.cab Error: 0x80070003
232
+ Error: 3
233
+ The system cannot find the path specified.
234
+ The DISM log file can be found at C:\\Windows\\Logs\\DISM\\dism.log.
235
+ EOF
236
+ end
237
+
238
+ it "raises error for invalid source path or file" do
239
+ expect { provider.load_current_resource }.to raise_error(Chef::Exceptions::Package, "DISM: The system cannot find the path or file specified.")
240
+ end
241
+ end
242
+ end
243
+
244
+ describe "#extract_msu_contents" do
245
+ it "extracts the msu contents by using mixlib shellout" do
246
+ expect(provider).to receive(:shell_out_with_timeout!).with("#{ENV['SYSTEMROOT']}\\system32\\expand.exe -f:* msu_file destination")
247
+ provider.extract_msu_contents("msu_file", "destination")
248
+ end
249
+ end
250
+
251
+ describe "#read_cab_files_from_xml" do
252
+ it "raises error if the xml file is not present" do
253
+ allow(Dir).to receive(:glob).and_return([])
254
+ expect { provider.read_cab_files_from_xml("msu_dir") }.to raise_error(Chef::Exceptions::Package)
255
+ end
256
+
257
+ it "parses xml file with single cab file" do
258
+ xml_file = File.join(CHEF_SPEC_DATA, "sample_msu1.xml")
259
+ allow(Dir).to receive(:glob).and_return([xml_file])
260
+ cab_files = provider.read_cab_files_from_xml("msu_dir")
261
+ expect(cab_files).to eql(["msu_dir/IE10-Windows6.1-KB2859903-x86.CAB"])
262
+ end
263
+
264
+ # We couldn't find any msu file with multiple cab files in it.
265
+ # So we are not 100% sure about the structure of XML file in this case
266
+ # The specs below cover 2 possible XML formats
267
+ context "handles different xml formats for multiple cab files in the msu package" do
268
+ it "parses xml file with multiple <package> tags" do
269
+ xml_file = File.join(CHEF_SPEC_DATA, "sample_msu2.xml")
270
+ allow(Dir).to receive(:glob).and_return([xml_file])
271
+ cab_files = provider.read_cab_files_from_xml("msu_dir")
272
+ expect(cab_files).to eql(["msu_dir/IE10-Windows6.1-KB2859903-x86.CAB", "msu_dir/abc.CAB"])
273
+ end
274
+
275
+ it "parses xml file with multiple <servicing> tags" do
276
+ xml_file = File.join(CHEF_SPEC_DATA, "sample_msu3.xml")
277
+ allow(Dir).to receive(:glob).and_return([xml_file])
278
+ cab_files = provider.read_cab_files_from_xml("msu_dir")
279
+ expect(cab_files).to eql(["msu_dir/IE10-Windows6.1-KB2859903-x86.CAB", "msu_dir/abc.CAB"])
280
+ end
281
+ end
282
+ end
283
+ end