puppet 2.7.18 → 2.7.19

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

Files changed (137) hide show
  1. data/CHANGELOG +82 -0
  2. data/CONTRIBUTING.md +114 -171
  3. data/README.md +8 -0
  4. data/README_DEVELOPER.md +38 -3
  5. data/Rakefile +19 -3
  6. data/conf/osx/createpackage.sh +3 -1
  7. data/conf/redhat/logrotate +1 -1
  8. data/conf/redhat/puppet.spec +35 -8
  9. data/lib/puppet.rb +1 -1
  10. data/lib/puppet/application/agent.rb +2 -0
  11. data/lib/puppet/application/master.rb +2 -0
  12. data/lib/puppet/configurer.rb +2 -3
  13. data/lib/puppet/defaults.rb +6 -5
  14. data/lib/puppet/face/module/install.rb +2 -1
  15. data/lib/puppet/file_bucket/dipper.rb +1 -1
  16. data/lib/puppet/indirector/file_content.rb +2 -2
  17. data/lib/puppet/indirector/file_metadata.rb +2 -2
  18. data/lib/puppet/indirector/indirection.rb +3 -4
  19. data/lib/puppet/indirector/rest.rb +12 -6
  20. data/lib/puppet/interface/action_manager.rb +1 -2
  21. data/lib/puppet/module_tool/applications/unpacker.rb +22 -3
  22. data/lib/puppet/network/handler/fileserver.rb +2 -2
  23. data/lib/puppet/parser/ast/resource.rb +9 -2
  24. data/lib/puppet/parser/functions/fqdn_rand.rb +2 -1
  25. data/lib/puppet/parser/functions/md5.rb +2 -2
  26. data/lib/puppet/parser/functions/sha1.rb +2 -2
  27. data/lib/puppet/parser/functions/template.rb +0 -2
  28. data/lib/puppet/parser/type_loader.rb +1 -2
  29. data/lib/puppet/provider/augeas/augeas.rb +19 -1
  30. data/lib/puppet/provider/confine.rb +1 -1
  31. data/lib/puppet/provider/package/msi.rb +97 -51
  32. data/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +1 -0
  33. data/lib/puppet/provider/service/gentoo.rb +0 -2
  34. data/lib/puppet/provider/service/openrc.rb +69 -0
  35. data/lib/puppet/provider/service/windows.rb +6 -4
  36. data/lib/puppet/provider/user/aix.rb +8 -4
  37. data/lib/puppet/provider/user/useradd.rb +6 -0
  38. data/lib/puppet/rails/benchmark.rb +2 -2
  39. data/lib/puppet/reports/store.rb +9 -9
  40. data/lib/puppet/resource/catalog.rb +2 -1
  41. data/lib/puppet/resource/type_collection.rb +2 -1
  42. data/lib/puppet/ssl/base.rb +1 -2
  43. data/lib/puppet/ssl/certificate_authority/interface.rb +1 -0
  44. data/lib/puppet/test/test_helper.rb +2 -1
  45. data/lib/puppet/type.rb +1 -1
  46. data/lib/puppet/type/augeas.rb +1 -1
  47. data/lib/puppet/type/file.rb +4 -2
  48. data/lib/puppet/type/scheduled_task.rb +8 -10
  49. data/lib/puppet/type/tidy.rb +1 -1
  50. data/lib/puppet/util.rb +63 -25
  51. data/lib/puppet/util/autoload.rb +6 -4
  52. data/lib/puppet/util/checksums.rb +3 -8
  53. data/lib/puppet/util/diff.rb +2 -1
  54. data/lib/puppet/util/filetype.rb +1 -3
  55. data/lib/puppet/util/run_mode.rb +2 -1
  56. data/lib/puppet/util/suidmanager.rb +1 -1
  57. data/lib/puppet/util/windows.rb +1 -0
  58. data/lib/puppet/util/windows/file.rb +27 -0
  59. data/lib/puppet/util/windows/user.rb +1 -2
  60. data/man/man8/puppet-agent.8 +4 -0
  61. data/man/man8/puppet-master.8 +4 -0
  62. data/man/man8/puppetmasterd.8 +4 -0
  63. data/spec/fixtures/unit/provider/augeas/augeas/augeas/lenses/test.aug +13 -0
  64. data/spec/fixtures/unit/provider/augeas/augeas/etc/fstab +10 -0
  65. data/spec/fixtures/unit/provider/augeas/augeas/etc/hosts +6 -0
  66. data/spec/fixtures/unit/provider/augeas/augeas/etc/test +3 -0
  67. data/spec/fixtures/unit/provider/augeas/augeas/test.aug +13 -0
  68. data/spec/fixtures/unit/provider/service/openrc/rcservice_list +8 -0
  69. data/spec/fixtures/unit/provider/service/openrc/rcstatus +43 -0
  70. data/spec/integration/defaults_spec.rb +3 -3
  71. data/spec/integration/network/server/mongrel_spec.rb +8 -6
  72. data/spec/integration/parser/parser_spec.rb +1 -1
  73. data/spec/integration/type/file_spec.rb +49 -12
  74. data/spec/lib/puppet_spec/database.rb +5 -3
  75. data/spec/lib/puppet_spec/files.rb +2 -1
  76. data/spec/monkey_patches/alias_should_to_must.rb +15 -2
  77. data/spec/shared_behaviours/file_serving_model.rb +9 -6
  78. data/spec/shared_behaviours/path_parameters.rb +5 -5
  79. data/spec/shared_behaviours/things_that_declare_options.rb +5 -5
  80. data/spec/unit/application/facts_spec.rb +1 -1
  81. data/spec/unit/application_spec.rb +10 -8
  82. data/spec/unit/configurer_spec.rb +11 -2
  83. data/spec/unit/face/ca_spec.rb +15 -15
  84. data/spec/unit/face/help_spec.rb +5 -5
  85. data/spec/unit/face/module/install_spec.rb +13 -2
  86. data/spec/unit/face/node_spec.rb +7 -6
  87. data/spec/unit/indirector/certificate_request/ca_spec.rb +1 -1
  88. data/spec/unit/indirector/envelope_spec.rb +0 -13
  89. data/spec/unit/indirector/facts/inventory_service_spec.rb +1 -1
  90. data/spec/unit/indirector/queue_spec.rb +3 -3
  91. data/spec/unit/indirector/rest_spec.rb +31 -20
  92. data/spec/unit/indirector_spec.rb +5 -5
  93. data/spec/unit/interface/action_builder_spec.rb +3 -2
  94. data/spec/unit/interface/action_manager_spec.rb +1 -1
  95. data/spec/unit/interface/action_spec.rb +4 -3
  96. data/spec/unit/interface/face_collection_spec.rb +1 -1
  97. data/spec/unit/interface/option_spec.rb +13 -9
  98. data/spec/unit/interface_spec.rb +5 -5
  99. data/spec/unit/module_tool/applications/unpacker_spec.rb +61 -0
  100. data/spec/unit/network/handler/fileserver_spec.rb +3 -3
  101. data/spec/unit/other/transbucket_spec.rb +6 -9
  102. data/spec/unit/parser/ast/resource_spec.rb +27 -0
  103. data/spec/unit/parser/functions/create_resources_spec.rb +12 -12
  104. data/spec/unit/parser/lexer_spec.rb +5 -5
  105. data/spec/unit/provider/augeas/augeas_spec.rb +78 -0
  106. data/spec/unit/provider/nameservice/directoryservice_spec.rb +6 -6
  107. data/spec/unit/provider/package/freebsd_spec.rb +2 -2
  108. data/spec/unit/provider/package/msi_spec.rb +181 -114
  109. data/spec/unit/provider/package/openbsd_spec.rb +1 -0
  110. data/spec/unit/provider/package/pkgdmg_spec.rb +3 -3
  111. data/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb +1 -1
  112. data/spec/unit/provider/service/openrc_spec.rb +209 -0
  113. data/spec/unit/provider/service/windows_spec.rb +57 -59
  114. data/spec/unit/provider/user/useradd_spec.rb +7 -0
  115. data/spec/unit/reports/store_spec.rb +13 -13
  116. data/spec/unit/resource/catalog_spec.rb +29 -24
  117. data/spec/unit/resource_spec.rb +13 -13
  118. data/spec/unit/simple_graph_spec.rb +12 -12
  119. data/spec/unit/ssl/certificate_authority/interface_spec.rb +3 -3
  120. data/spec/unit/ssl/certificate_authority_spec.rb +11 -10
  121. data/spec/unit/transaction_spec.rb +3 -3
  122. data/spec/unit/type/cron_spec.rb +171 -171
  123. data/spec/unit/type/exec_spec.rb +29 -27
  124. data/spec/unit/type/file_spec.rb +22 -13
  125. data/spec/unit/type/interface_spec.rb +1 -1
  126. data/spec/unit/type/scheduled_task_spec.rb +15 -14
  127. data/spec/unit/type/tidy_spec.rb +2 -2
  128. data/spec/unit/type/user_spec.rb +15 -15
  129. data/spec/unit/type/vlan_spec.rb +1 -1
  130. data/spec/unit/type_spec.rb +22 -25
  131. data/spec/unit/util/autoload_spec.rb +13 -7
  132. data/spec/unit/util/backups_spec.rb +36 -67
  133. data/spec/unit/util/storage_spec.rb +2 -9
  134. data/spec/unit/util/suidmanager_spec.rb +1 -1
  135. data/spec/unit/util_spec.rb +20 -28
  136. data/test/ral/manager/attributes.rb +1 -1
  137. metadata +1553 -1542
@@ -98,7 +98,7 @@ describe Puppet::Parser::Lexer::TokenList do
98
98
 
99
99
  it "should fail to add tokens sharing a name with an existing token" do
100
100
  @list.add_token :name, "whatever"
101
- lambda { @list.add_token :name, "whatever" }.should raise_error(ArgumentError)
101
+ expect { @list.add_token :name, "whatever" }.to raise_error(ArgumentError)
102
102
  end
103
103
 
104
104
  it "should set provided options on tokens being added" do
@@ -633,11 +633,11 @@ describe "Puppet::Parser::Lexer in the old tests" do
633
633
  end
634
634
 
635
635
  it "should fail usefully" do
636
- lambda { tokens_scanned_from('^') }.should raise_error(RuntimeError)
636
+ expect { tokens_scanned_from('^') }.to raise_error(RuntimeError)
637
637
  end
638
638
 
639
639
  it "should fail if the string is not set" do
640
- lambda { @lexer.fullscan }.should raise_error(Puppet::LexError)
640
+ expect { @lexer.fullscan }.to raise_error(Puppet::LexError)
641
641
  end
642
642
 
643
643
  it "should correctly identify keywords" do
@@ -662,7 +662,7 @@ describe "Puppet::Parser::Lexer in the old tests" do
662
662
  end
663
663
 
664
664
  it "should correctly parse empty strings" do
665
- lambda { tokens_scanned_from('$var = ""') }.should_not raise_error
665
+ expect { tokens_scanned_from('$var = ""') }.to_not raise_error
666
666
  end
667
667
 
668
668
  it "should correctly parse virtual resources" do
@@ -724,7 +724,7 @@ describe "Puppet::Parser::Lexer in the old tests when lexing example files" do
724
724
  it "should correctly lex #{file}" do
725
725
  lexer = Puppet::Parser::Lexer.new
726
726
  lexer.file = file
727
- expect { lexer.fullscan }.should_not raise_error
727
+ expect { lexer.fullscan }.to_not raise_error
728
728
  end
729
729
  end
730
730
  end
@@ -606,4 +606,82 @@ describe provider_class do
606
606
  File.read(target).should =~ /PermitRootLogin no/
607
607
  end
608
608
  end
609
+
610
+ # Run initialisation tests of the real Augeas library to test our open_augeas
611
+ # method. This relies on Augeas and ruby-augeas on the host to be
612
+ # functioning.
613
+ describe "augeas lib initialisation", :if => Puppet.features.augeas? do
614
+ # Expect lenses for fstab and hosts
615
+ it "should have loaded standard files by default" do
616
+ aug = @provider.open_augeas
617
+ aug.should_not == nil
618
+ aug.match("/files/etc/fstab").should == ["/files/etc/fstab"]
619
+ aug.match("/files/etc/hosts").should == ["/files/etc/hosts"]
620
+ aug.match("/files/etc/test").should == []
621
+ end
622
+
623
+ # Only the file specified should be loaded
624
+ it "should load one file if incl/lens used" do
625
+ @resource[:incl] = "/etc/hosts"
626
+ @resource[:lens] = "Hosts.lns"
627
+
628
+ aug = @provider.open_augeas
629
+ aug.should_not == nil
630
+ aug.match("/files/etc/fstab").should == []
631
+ aug.match("/files/etc/hosts").should == ["/files/etc/hosts"]
632
+ aug.match("/files/etc/test").should == []
633
+ end
634
+
635
+ it "should also load lenses from load_path" do
636
+ @resource[:load_path] = my_fixture_dir
637
+
638
+ aug = @provider.open_augeas
639
+ aug.should_not == nil
640
+ aug.match("/files/etc/fstab").should == ["/files/etc/fstab"]
641
+ aug.match("/files/etc/hosts").should == ["/files/etc/hosts"]
642
+ aug.match("/files/etc/test").should == ["/files/etc/test"]
643
+ end
644
+
645
+ it "should also load lenses from pluginsync'd path" do
646
+ Puppet[:libdir] = my_fixture_dir
647
+
648
+ aug = @provider.open_augeas
649
+ aug.should_not == nil
650
+ aug.match("/files/etc/fstab").should == ["/files/etc/fstab"]
651
+ aug.match("/files/etc/hosts").should == ["/files/etc/hosts"]
652
+ aug.match("/files/etc/test").should == ["/files/etc/test"]
653
+ end
654
+ end
655
+
656
+ describe "get_load_path" do
657
+ it "should offer no load_path by default" do
658
+ @provider.get_load_path(@resource).should == ""
659
+ end
660
+
661
+ it "should offer one path from load_path" do
662
+ @resource[:load_path] = "/foo"
663
+ @provider.get_load_path(@resource).should == "/foo"
664
+ end
665
+
666
+ it "should offer multiple colon-separated paths from load_path" do
667
+ @resource[:load_path] = "/foo:/bar:/baz"
668
+ @provider.get_load_path(@resource).should == "/foo:/bar:/baz"
669
+ end
670
+
671
+ it "should offer multiple paths in array from load_path" do
672
+ @resource[:load_path] = ["/foo", "/bar", "/baz"]
673
+ @provider.get_load_path(@resource).should == "/foo:/bar:/baz"
674
+ end
675
+
676
+ it "should offer pluginsync augeas/lenses subdir" do
677
+ Puppet[:libdir] = my_fixture_dir
678
+ @provider.get_load_path(@resource).should == "#{my_fixture_dir}/augeas/lenses"
679
+ end
680
+
681
+ it "should offer both pluginsync and load_path paths" do
682
+ Puppet[:libdir] = my_fixture_dir
683
+ @resource[:load_path] = ["/foo", "/bar", "/baz"]
684
+ @provider.get_load_path(@resource).should == "/foo:/bar:/baz:#{my_fixture_dir}/augeas/lenses"
685
+ end
686
+ end
609
687
  end
@@ -31,7 +31,7 @@ require 'spec_helper'
31
31
  with([:dseditgroup, '-o', 'edit', '-n', '.', '-a', add, group])
32
32
  end
33
33
 
34
- expect { @provider.set(:members, desired) }.should_not raise_error
34
+ expect { @provider.set(:members, desired) }.to_not raise_error
35
35
  end
36
36
  end
37
37
  end
@@ -40,9 +40,9 @@ describe 'DirectoryService.single_report' do
40
40
  it 'should fail on OS X < 10.4' do
41
41
  Puppet::Provider::NameService::DirectoryService.stubs(:get_macosx_version_major).returns("10.3")
42
42
 
43
- lambda {
43
+ expect {
44
44
  Puppet::Provider::NameService::DirectoryService.single_report('resource_name')
45
- }.should raise_error(RuntimeError, "Puppet does not support OS X versions < 10.4")
45
+ }.to raise_error(RuntimeError, "Puppet does not support OS X versions < 10.4")
46
46
  end
47
47
 
48
48
  it 'should use url data on 10.4' do
@@ -76,9 +76,9 @@ describe 'DirectoryService.get_exec_preamble' do
76
76
  it 'should fail on OS X < 10.4' do
77
77
  Puppet::Provider::NameService::DirectoryService.stubs(:get_macosx_version_major).returns("10.3")
78
78
 
79
- lambda {
79
+ expect {
80
80
  Puppet::Provider::NameService::DirectoryService.get_exec_preamble('-list')
81
- }.should raise_error(RuntimeError, "Puppet does not support OS X versions < 10.4")
81
+ }.to raise_error(RuntimeError, "Puppet does not support OS X versions < 10.4")
82
82
  end
83
83
 
84
84
  it 'should use url data on 10.4' do
@@ -140,7 +140,7 @@ describe 'DirectoryService password behavior' do
140
140
  it 'should fail if a salted-SHA512 password hash is not passed in >= 10.7' do
141
141
  expect {
142
142
  subject.set_password('jeff', 'uid', 'badpassword')
143
- }.should raise_error(RuntimeError, /OS X 10.7 requires a Salted SHA512 hash password of 136 characters./)
143
+ }.to raise_error(RuntimeError, /OS X 10.7 requires a Salted SHA512 hash password of 136 characters./)
144
144
  end
145
145
 
146
146
  it 'should convert xml-to-binary and binary-to-xml when setting the pw on >= 10.7' do
@@ -36,7 +36,7 @@ describe provider_class do
36
36
  Puppet::Util::Execution.expects(:withenv).once.with({:PKG_PATH => path}).yields
37
37
  @provider.expects(:pkgadd).once.with("mypackage")
38
38
 
39
- expect { @provider.install }.should_not raise_error
39
+ expect { @provider.install }.to_not raise_error
40
40
  end
41
41
 
42
42
  %w{http https ftp}.each do |protocol|
@@ -47,7 +47,7 @@ describe provider_class do
47
47
  Puppet::Util::Execution.expects(:withenv).once.with({:PACKAGESITE => path}).yields
48
48
  @provider.expects(:pkgadd).once.with('-r', "mypackage")
49
49
 
50
- expect { @provider.install }.should_not raise_error
50
+ expect { @provider.install }.to_not raise_error
51
51
  end
52
52
  end
53
53
  end
@@ -1,170 +1,237 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'Puppet::Provider::Package::Msi' do
4
- include PuppetSpec::Files
3
+ describe Puppet::Type.type(:package).provider(:msi) do
4
+ let (:name) { 'mysql-5.1.58-win-x64' }
5
+ let (:source) { 'E:\mysql-5.1.58-win-x64.msi' }
6
+ let (:productcode) { '{E437FFB6-5C49-4DAC-ABAE-33FF065FE7CC}' }
7
+ let (:packagecode) { '{5A6FD560-763A-4BC1-9E03-B18DFFB7C72C}' }
8
+ let (:resource) { Puppet::Type.type(:package).new(:name => name, :provider => :msi, :source => source) }
9
+ let (:provider) { resource.provider }
10
+ let (:execute_options) do {:combine => true} end
11
+
12
+ def installer(productcodes)
13
+ installer = mock
14
+ installer.expects(:UILevel=).with(2)
15
+
16
+ installer.stubs(:ProductState).returns(5)
17
+ installer.stubs(:Products).returns(productcodes)
18
+ productcodes.each do |guid|
19
+ installer.stubs(:ProductInfo).with(guid, 'ProductName').returns("name-#{guid}")
20
+ installer.stubs(:ProductInfo).with(guid, 'PackageCode').returns("package-#{guid}")
21
+ end
22
+
23
+ MsiPackage.stubs(:installer).returns(installer)
24
+ end
5
25
 
6
26
  before :each do
7
- Puppet::Type.type(:package).stubs(:defaultprovider).returns(Puppet::Type.type(:package).provider(:msi))
8
- Puppet[:vardir] = tmpdir('msi')
9
- @state_dir = File.join(Puppet[:vardir], 'db', 'package', 'msi')
27
+ # make sure we never try to execute msiexec
28
+ provider.expects(:execute).never
29
+ end
30
+
31
+ describe 'provider features' do
32
+ it { should be_installable }
33
+ it { should be_uninstallable }
34
+ it { should be_install_options }
10
35
  end
11
36
 
12
- describe 'when installing' do
13
- it 'should create a state file' do
14
- resource = Puppet::Type.type(:package).new(
15
- :name => 'mysql-5.1.58-winx64',
16
- :source => 'E:\mysql-5.1.58-winx64.msi'
17
- )
18
- resource.provider.stubs(:execute)
19
- resource.provider.install
37
+ context '::instances' do
38
+ it 'should return an array of provider instances' do
39
+ installer([1, 2])
20
40
 
21
- File.should be_exists File.join(@state_dir, 'mysql-5.1.58-winx64.yml')
41
+ MsiPackage.map do |pkg|
42
+ pkg[:name].should == "name-#{pkg[:productcode]}"
43
+ pkg[:ensure].should == :installed
44
+ pkg[:provider].should == :msi
45
+ pkg[:packagecode].should == "package-#{pkg[:productcode]}"
46
+ end.count.should == 2
22
47
  end
23
48
 
24
- it 'should use the install_options as parameter/value pairs' do
25
- resource = Puppet::Type.type(:package).new(
26
- :name => 'mysql-5.1.58-winx64',
27
- :source => 'E:\mysql-5.1.58-winx64.msi',
28
- :install_options => { 'INSTALLDIR' => 'C:\mysql-here' }
29
- )
49
+ it 'should return an empty array of none found' do
50
+ installer([])
30
51
 
31
- resource.provider.expects(:execute).with('msiexec.exe /qn /norestart /i E:\mysql-5.1.58-winx64.msi INSTALLDIR=C:\mysql-here')
32
- resource.provider.install
52
+ MsiPackage.to_a.size.should == 0
33
53
  end
54
+ end
34
55
 
35
- it 'should only quote the value when an install_options value has a space in it' do
36
- resource = Puppet::Type.type(:package).new(
37
- :name => 'mysql-5.1.58-winx64',
38
- :source => 'E:\mysql-5.1.58-winx64.msi',
39
- :install_options => { 'INSTALLDIR' => 'C:\mysql here' }
40
- )
56
+ context '#query' do
57
+ let (:package) do {
58
+ :name => name,
59
+ :ensure => :installed,
60
+ :provider => :msi,
61
+ :productcode => productcode,
62
+ :packagecode => packagecode.upcase
63
+ }
64
+ end
41
65
 
42
- resource.provider.expects(:execute).with('msiexec.exe /qn /norestart /i E:\mysql-5.1.58-winx64.msi INSTALLDIR="C:\mysql here"')
43
- resource.provider.install
66
+ before :each do
67
+ MsiPackage.stubs(:each).yields(package)
44
68
  end
45
69
 
46
- it 'should escape embedded quotes in install_options values with spaces' do
47
- resource = Puppet::Type.type(:package).new(
48
- :name => 'mysql-5.1.58-winx64',
49
- :source => 'E:\mysql-5.1.58-winx64.msi',
50
- :install_options => { 'INSTALLDIR' => 'C:\mysql "here"' }
51
- )
70
+ it 'should match package codes case-insensitively' do
71
+ resource[:name] = packagecode.downcase
72
+
73
+ provider.query.should == package
74
+ end
52
75
 
53
- resource.provider.expects(:execute).with('msiexec.exe /qn /norestart /i E:\mysql-5.1.58-winx64.msi INSTALLDIR="C:\mysql \"here\""')
54
- resource.provider.install
76
+ it 'should match product name' do
77
+ resource[:name] = name
78
+
79
+ provider.query.should == package
55
80
  end
56
81
 
57
- it 'should not create a state file, if the installation fails' do
58
- resource = Puppet::Type.type(:package).new(
59
- :name => 'mysql-5.1.58-winx64',
60
- :source => 'E:\mysql-5.1.58-winx64.msi'
61
- )
62
- resource.provider.stubs(:execute).raises(Puppet::ExecutionFailure.new("Execution of 'msiexec.exe' returned 128: Blargle"))
63
- expect { resource.provider.install }.to raise_error(Puppet::ExecutionFailure, /msiexec\.exe/)
82
+ it 'should return nil if none found' do
83
+ resource[:name] = 'not going to find it'
64
84
 
65
- File.should_not be_exists File.join(@state_dir, 'mysql-5.1.58-winx64.yml')
85
+ provider.query.should be_nil
66
86
  end
87
+ end
88
+
89
+ context '#install' do
90
+ before :each do
91
+ provider.stubs(:execute)
92
+ end
93
+
94
+ it 'should require the source parameter' do
95
+ resource = Puppet::Type.type(:package).new(:name => name, :provider => :msi)
67
96
 
68
- it 'should fail if the source parameter is not set' do
69
97
  expect do
70
- resource = Puppet::Type.type(:package).new(
71
- :name => 'mysql-5.1.58-winx64'
72
- ).provider.install
98
+ resource.provider.install
73
99
  end.to raise_error(Puppet::Error, /The source parameter is required when using the MSI provider/)
74
100
  end
75
101
 
76
- it 'should fail if the source parameter is empty' do
102
+ it 'should install using the source and install_options' do
103
+ resource[:install_options] = { 'INSTALLDIR' => 'C:\mysql-5.1' }
104
+
105
+ provider.expects(:execute).with("msiexec.exe /qn /norestart /i #{source} INSTALLDIR=C:\\mysql-5.1", execute_options)
106
+ provider.expects(:exit_status).returns(0)
107
+
108
+ provider.install
109
+ end
110
+
111
+ it 'should warn if the package requests a reboot' do
112
+ provider.stubs(:exit_status).returns(194)
113
+
114
+ provider.expects(:warning).with('The package requested a reboot to finish the operation.')
115
+
116
+ provider.install
117
+ end
118
+
119
+ it 'should warn if reboot initiated' do
120
+ provider.stubs(:exit_status).returns(1641)
121
+
122
+ provider.expects(:warning).with('The package installed successfully and the system is rebooting now.')
123
+
124
+ provider.install
125
+ end
126
+
127
+ it 'should warn if reboot required' do
128
+ provider.stubs(:exit_status).returns(3010)
129
+
130
+ provider.expects(:warning).with('The package installed successfully, but the system must be rebooted.')
131
+
132
+ provider.install
133
+ end
134
+
135
+ it 'should fail otherwise', :if => Puppet.features.microsoft_windows? do
136
+ provider.stubs(:execute)
137
+ provider.stubs(:exit_status).returns(5)
138
+
77
139
  expect do
78
- resource = Puppet::Type.type(:package).new(
79
- :name => 'mysql-5.1.58-winx64',
80
- :source => ''
81
- )
82
- end.to raise_error(Puppet::Error, /The source parameter cannot be empty when using the MSI provider/)
140
+ provider.install
141
+ end.to raise_error(Puppet::Util::Windows::Error, /Access is denied/)
83
142
  end
84
143
  end
85
144
 
86
- describe 'when uninstalling' do
145
+ context '#uninstall' do
87
146
  before :each do
88
- FileUtils.mkdir_p(@state_dir)
89
- File.open(File.join(@state_dir, 'mysql-5.1.58-winx64.yml'), 'w') {|f| f.puts 'Hello'}
147
+ resource[:ensure] = :absent
148
+ provider.set(:productcode => productcode)
149
+ end
150
+
151
+ it 'should require the productcode' do
152
+ provider.set(:productcode => nil)
153
+ expect do
154
+ provider.uninstall
155
+ end.to raise_error(Puppet::Error, /The productcode property is missing./)
90
156
  end
91
157
 
92
- it 'should remove the state file' do
93
- resource = Puppet::Type.type(:package).new(
94
- :name => 'mysql-5.1.58-winx64',
95
- :source => 'E:\mysql-5.1.58-winx64.msi'
96
- )
97
- resource.provider.stubs(:msiexec)
98
- resource.provider.uninstall
158
+ it 'should uninstall using the productcode' do
159
+ provider.expects(:execute).with("msiexec.exe /qn /norestart /x #{productcode}", execute_options)
160
+ provider.expects(:exit_status).returns(0)
161
+
162
+ provider.uninstall
163
+ end
164
+
165
+ it 'should warn if the package requests a reboot' do
166
+ provider.stubs(:execute)
167
+ provider.stubs(:exit_status).returns(194)
168
+
169
+ provider.expects(:warning).with('The package requested a reboot to finish the operation.')
170
+
171
+ provider.uninstall
172
+ end
173
+
174
+ it 'should warn if reboot initiated' do
175
+ provider.stubs(:execute)
176
+ provider.stubs(:exit_status).returns(1641)
177
+
178
+ provider.expects(:warning).with('The package uninstalled successfully and the system is rebooting now.')
99
179
 
100
- File.should_not be_exists File.join(Puppet[:vardir], 'db', 'package', 'msi', 'mysql-5.1.58-winx64.yml')
180
+ provider.uninstall
101
181
  end
102
182
 
103
- it 'should leave the state file if uninstalling fails' do
104
- resource = Puppet::Type.type(:package).new(
105
- :name => 'mysql-5.1.58-winx64',
106
- :source => 'E:\mysql-5.1.58-winx64.msi'
107
- )
108
- resource.provider.stubs(:msiexec).raises(Puppet::ExecutionFailure.new("Execution of 'msiexec.exe' returned 128: Blargle"))
109
- expect { resource.provider.uninstall }.to raise_error(Puppet::ExecutionFailure, /msiexec\.exe/)
183
+ it 'should warn if reboot required' do
184
+ provider.stubs(:execute)
185
+ provider.stubs(:exit_status).returns(3010)
110
186
 
111
- File.should be_exists File.join(@state_dir, 'mysql-5.1.58-winx64.yml')
187
+ provider.expects(:warning).with('The package uninstalled successfully, but the system must be rebooted.')
188
+
189
+ provider.uninstall
112
190
  end
113
191
 
114
- it 'should fail if the source parameter is not set' do
192
+ it 'should fail otherwise', :if => Puppet.features.microsoft_windows? do
193
+ provider.stubs(:execute)
194
+ provider.stubs(:exit_status).returns(5)
195
+
115
196
  expect do
116
- resource = Puppet::Type.type(:package).new(
117
- :name => 'mysql-5.1.58-winx64'
118
- ).provider.install
119
- end.to raise_error(Puppet::Error, /The source parameter is required when using the MSI provider/)
197
+ provider.uninstall
198
+ end.to raise_error(Puppet::Util::Windows::Error, /Failed to uninstall.*Access is denied/)
120
199
  end
200
+ end
121
201
 
202
+ context '#validate_source' do
122
203
  it 'should fail if the source parameter is empty' do
123
204
  expect do
124
- resource = Puppet::Type.type(:package).new(
125
- :name => 'mysql-5.1.58-winx64',
126
- :source => ''
127
- )
205
+ resource[:source] = ''
128
206
  end.to raise_error(Puppet::Error, /The source parameter cannot be empty when using the MSI provider/)
129
207
  end
130
- end
131
208
 
132
- describe 'when enumerating instances' do
133
- it 'should consider the base of the state file name to be the name of the package' do
134
- FileUtils.mkdir_p(@state_dir)
135
- package_names = ['GoogleChromeStandaloneEnterprise', 'mysql-5.1.58-winx64', 'postgresql-8.3']
209
+ it 'should accept a source' do
210
+ resource[:source] = source
211
+ end
212
+ end
136
213
 
137
- package_names.each do |state_file|
138
- File.open(File.join(@state_dir, "#{state_file}.yml"), 'w') {|f| f.puts 'Hello'}
139
- end
214
+ context '#install_options' do
215
+ it 'should return nil by default' do
216
+ provider.install_options.should be_nil
217
+ end
140
218
 
141
- installed_package_names = Puppet::Type.type(:package).provider(:msi).instances.collect {|p| p.name}
219
+ it 'should use the install_options as parameter/value pairs' do
220
+ resource[:install_options] = { 'INSTALLDIR' => 'C:\mysql-here' }
142
221
 
143
- installed_package_names.should =~ package_names
222
+ provider.install_options.should == ['INSTALLDIR=C:\mysql-here']
144
223
  end
145
- end
146
224
 
147
- it 'should consider the package installed if the state file is present' do
148
- FileUtils.mkdir_p(@state_dir)
149
- File.open(File.join(@state_dir, 'mysql-5.1.58-winx64.yml'), 'w') {|f| f.puts 'Hello'}
150
-
151
- resource = Puppet::Type.type(:package).new(
152
- :name => 'mysql-5.1.58-winx64',
153
- :source => 'E:\mysql-5.1.58-winx64.msi'
154
- )
225
+ it 'should only quote the value when an install_options value has a space in it' do
226
+ resource[:install_options] = { 'INSTALLDIR' => 'C:\mysql here' }
155
227
 
156
- resource.provider.query.should == {
157
- :name => 'mysql-5.1.58-winx64',
158
- :ensure => :installed
159
- }
160
- end
228
+ provider.install_options.should == ['INSTALLDIR="C:\mysql here"']
229
+ end
161
230
 
162
- it 'should consider the package absent if the state file is missing' do
163
- resource = Puppet::Type.type(:package).new(
164
- :name => 'mysql-5.1.58-winx64',
165
- :source => 'E:\mysql-5.1.58-winx64.msi'
166
- )
231
+ it 'should escape embedded quotes in install_options values with spaces' do
232
+ resource[:install_options] = { 'INSTALLDIR' => 'C:\mysql "here"' }
167
233
 
168
- resource.provider.query.should be_nil
234
+ provider.install_options.should == ['INSTALLDIR="C:\mysql \"here\""']
235
+ end
169
236
  end
170
237
  end