chef 12.16.42 → 12.17.44
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -1
- data/README.md +20 -5
- data/Rakefile +17 -0
- data/VERSION +1 -1
- data/acceptance/Gemfile.lock +32 -23
- data/distro/common/markdown/man1/knife-configure.mkd +3 -2
- data/lib-backcompat/chef/chef_fs/file_system/already_exists_error.rb +1 -1
- data/lib-backcompat/chef/chef_fs/file_system/cookbook_frozen_error.rb +1 -1
- data/lib-backcompat/chef/chef_fs/file_system/default_environment_cannot_be_modified_error.rb +1 -1
- data/lib-backcompat/chef/chef_fs/file_system/file_system_error.rb +1 -1
- data/lib-backcompat/chef/chef_fs/file_system/must_delete_recursively_error.rb +1 -1
- data/lib-backcompat/chef/chef_fs/file_system/not_found_error.rb +1 -1
- data/lib-backcompat/chef/chef_fs/file_system/operation_failed_error.rb +1 -1
- data/lib-backcompat/chef/chef_fs/file_system/operation_not_allowed_error.rb +1 -1
- data/lib-backcompat/chef/chef_fs/file_system/repository/chef_repository_file_system_entry.rb +1 -1
- data/lib-backcompat/chef/chef_fs/file_system/repository/file_system_root_dir.rb +1 -1
- data/lib/chef/api_client.rb +1 -1
- data/lib/chef/application.rb +1 -1
- data/lib/chef/application/exit_code.rb +3 -3
- data/lib/chef/chef_class.rb +15 -5
- data/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb +12 -1
- data/lib/chef/chef_fs/file_system/repository/nodes_dir.rb +19 -0
- data/lib/chef/client.rb +1 -0
- data/lib/chef/cookbook/metadata.rb +2 -2
- data/lib/chef/cookbook_version.rb +4 -4
- data/lib/chef/data_bag.rb +1 -1
- data/lib/chef/data_bag_item.rb +1 -1
- data/lib/chef/data_collector.rb +20 -13
- data/lib/chef/data_collector/messages.rb +0 -1
- data/lib/chef/data_collector/messages/helpers.rb +2 -2
- data/lib/chef/decorator/unchain.rb +2 -2
- data/lib/chef/deprecated.rb +190 -0
- data/lib/chef/deprecation/provider/remote_directory.rb +1 -1
- data/lib/chef/deprecation/warnings.rb +3 -4
- data/lib/chef/dsl/method_missing.rb +2 -2
- data/lib/chef/dsl/resources.rb +2 -2
- data/lib/chef/environment.rb +1 -1
- data/lib/chef/exceptions.rb +1 -1
- data/lib/chef/formatters/base.rb +11 -1
- data/lib/chef/formatters/doc.rb +13 -4
- data/lib/chef/key.rb +1 -1
- data/lib/chef/knife/client_delete.rb +12 -9
- data/lib/chef/knife/configure.rb +1 -1
- data/lib/chef/knife/core/bootstrap_context.rb +25 -1
- data/lib/chef/knife/core/subcommand_loader.rb +3 -3
- data/lib/chef/knife/core/ui.rb +1 -1
- data/lib/chef/knife/node_delete.rb +6 -6
- data/lib/chef/log.rb +1 -1
- data/lib/chef/mixin/deprecation.rb +4 -10
- data/lib/chef/mixin/powershell_type_coercions.rb +19 -19
- data/lib/chef/mixin/shell_out.rb +1 -1
- data/lib/chef/node.rb +2 -2
- data/lib/chef/node/attribute.rb +3 -4
- data/lib/chef/node/common_api.rb +1 -1
- data/lib/chef/node/mixin/state_tracking.rb +5 -2
- data/lib/chef/node_map.rb +2 -2
- data/lib/chef/org.rb +1 -1
- data/lib/chef/platform/rebooter.rb +3 -1
- data/lib/chef/policy_builder/expand_node_object.rb +1 -1
- data/lib/chef/property.rb +5 -5
- data/lib/chef/provider.rb +4 -4
- data/lib/chef/provider/launchd.rb +1 -1
- data/lib/chef/provider/link.rb +6 -0
- data/lib/chef/provider/mount.rb +2 -0
- data/lib/chef/provider/mount/mount.rb +1 -1
- data/lib/chef/provider/ohai.rb +5 -3
- data/lib/chef/provider/package/cab.rb +1 -1
- data/lib/chef/provider/package/chocolatey.rb +2 -2
- data/lib/chef/provider/package/easy_install.rb +2 -2
- data/lib/chef/provider/package/msu.rb +162 -0
- data/lib/chef/provider/package/powershell.rb +114 -0
- data/lib/chef/provider/package/yum.rb +1 -1
- data/lib/chef/provider/yum_repository.rb +6 -7
- data/lib/chef/provider_resolver.rb +2 -2
- data/lib/chef/providers.rb +2 -0
- data/lib/chef/resource.rb +3 -5
- data/lib/chef/resource/apt_update.rb +1 -1
- data/lib/chef/resource/chef_gem.rb +2 -3
- data/lib/chef/resource/file/verification.rb +1 -1
- data/lib/chef/resource/launchd.rb +48 -8
- data/lib/chef/resource/mount.rb +1 -1
- data/lib/chef/resource/msu_package.rb +47 -0
- data/lib/chef/resource/ohai.rb +5 -25
- data/lib/chef/resource/powershell_package.rb +41 -0
- data/lib/chef/resource/reboot.rb +1 -1
- data/lib/chef/resource/user.rb +2 -2
- data/lib/chef/resource_builder.rb +4 -4
- data/lib/chef/resource_resolver.rb +2 -3
- data/lib/chef/resources.rb +2 -0
- data/lib/chef/rest.rb +1 -1
- data/lib/chef/role.rb +1 -1
- data/lib/chef/run_context.rb +3 -3
- data/lib/chef/shell/ext.rb +2 -2
- data/lib/chef/user.rb +3 -3
- data/lib/chef/user_v1.rb +1 -1
- data/lib/chef/version.rb +1 -1
- data/lib/chef/win32/api/security.rb +12 -12
- data/spec/data/sample_msu1.xml +10 -0
- data/spec/data/sample_msu2.xml +14 -0
- data/spec/data/sample_msu3.xml +16 -0
- data/spec/functional/rebooter_spec.rb +3 -3
- data/spec/functional/resource/link_spec.rb +62 -1
- data/spec/functional/resource/msu_package_spec.rb +84 -0
- data/spec/functional/resource/registry_spec.rb +3 -3
- data/spec/functional/resource/rpm_spec.rb +7 -10
- data/spec/integration/solo/solo_spec.rb +50 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/support/platform_helpers.rb +16 -8
- data/spec/unit/application/exit_code_spec.rb +3 -15
- data/spec/unit/data_collector_spec.rb +6 -16
- data/spec/unit/deprecated_spec.rb +59 -0
- data/spec/unit/deprecation_spec.rb +1 -8
- data/spec/unit/handler_spec.rb +2 -2
- data/spec/unit/knife/client_delete_spec.rb +16 -0
- data/spec/unit/knife/configure_spec.rb +1 -1
- data/spec/unit/knife/cookbook_metadata_spec.rb +116 -113
- data/spec/unit/knife/core/bootstrap_context_spec.rb +55 -5
- data/spec/unit/knife/node_delete_spec.rb +19 -10
- data/spec/unit/mixin/shell_out_spec.rb +0 -1
- data/spec/unit/node/immutable_collections_spec.rb +5 -0
- data/spec/unit/node/vivid_mash_spec.rb +11 -0
- data/spec/unit/node_spec.rb +2 -2
- data/spec/unit/provider/launchd_spec.rb +81 -3
- data/spec/unit/provider/mount/mount_spec.rb +1 -1
- data/spec/unit/provider/mount_spec.rb +7 -0
- data/spec/unit/provider/package/chocolatey_spec.rb +5 -5
- data/spec/unit/provider/package/easy_install_spec.rb +6 -6
- data/spec/unit/provider/package/msu_spec.rb +283 -0
- data/spec/unit/provider/package/powershell_spec.rb +337 -0
- data/spec/unit/provider/service/macosx_spec.rb +1 -1
- data/spec/unit/provider/subversion_spec.rb +9 -0
- data/spec/unit/provider/user/linux_spec.rb +7 -1
- data/spec/unit/recipe_spec.rb +43 -11
- data/spec/unit/resource/apt_update_spec.rb +17 -25
- data/spec/unit/resource/file/verification_spec.rb +1 -1
- data/spec/unit/resource/mount_spec.rb +2 -1
- data/spec/unit/resource/msu_package_spec.rb +49 -0
- data/spec/unit/resource/ohai_spec.rb +1 -1
- data/spec/unit/resource/powershell_package_spec.rb +68 -0
- data/spec/unit/resource_reporter_spec.rb +4 -4
- data/spec/unit/run_status_spec.rb +1 -1
- data/tasks/announce.rb +58 -0
- data/tasks/changelog.rb +26 -6
- data/tasks/templates/prerelease.md.erb +35 -0
- data/tasks/templates/release.md.erb +34 -0
- 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 =
|
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
|
-
|
32
|
-
|
33
|
-
|
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
|
45
|
-
expect(Chef::Node).to receive(:load).with("adam").and_return(@
|
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
|
50
|
-
expect(@
|
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(@
|
63
|
-
expect(@knife).to receive(:
|
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
|
@@ -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 } ]
|
data/spec/unit/node_spec.rb
CHANGED
@@ -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(:
|
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(:
|
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>
|
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
|
-
"
|
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 "
|
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
|
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
|
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
|
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
|
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
|
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(:
|
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(:
|
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(:
|
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(:
|
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(:
|
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(:
|
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
|