puppet 5.5.14 → 5.5.16

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 (83) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/Gemfile.lock +18 -17
  4. data/ext/solaris/smf/puppet.xml +2 -0
  5. data/lib/hiera/scope.rb +7 -0
  6. data/lib/puppet.rb +1 -1
  7. data/lib/puppet/application/device.rb +22 -10
  8. data/lib/puppet/configurer.rb +23 -38
  9. data/lib/puppet/network/http/connection.rb +2 -0
  10. data/lib/puppet/pops/types/types.rb +5 -3
  11. data/lib/puppet/provider.rb +1 -2
  12. data/lib/puppet/provider/cron/crontab.rb +1 -1
  13. data/lib/puppet/provider/package.rb +2 -0
  14. data/lib/puppet/provider/package/dpkg.rb +15 -2
  15. data/lib/puppet/provider/package/gem.rb +65 -29
  16. data/lib/puppet/provider/package/pip.rb +136 -111
  17. data/lib/puppet/provider/package/pip3.rb +1 -1
  18. data/lib/puppet/provider/package/puppet_gem.rb +1 -1
  19. data/lib/puppet/provider/package/rpm.rb +27 -16
  20. data/lib/puppet/provider/package/yum.rb +1 -1
  21. data/lib/puppet/provider/package_targetable.rb +68 -0
  22. data/lib/puppet/provider/service/upstart.rb +8 -8
  23. data/lib/puppet/provider/user/useradd.rb +16 -13
  24. data/lib/puppet/settings/server_list_setting.rb +9 -0
  25. data/lib/puppet/ssl/validator/default_validator.rb +30 -0
  26. data/lib/puppet/type/package.rb +46 -9
  27. data/lib/puppet/util/pidlock.rb +15 -1
  28. data/lib/puppet/util/windows/process.rb +70 -0
  29. data/lib/puppet/util/windows/registry.rb +7 -1
  30. data/lib/puppet/util/windows/user.rb +14 -4
  31. data/lib/puppet/version.rb +1 -1
  32. data/locales/puppet.pot +81 -78
  33. data/man/man5/puppet.conf.5 +2 -2
  34. data/man/man8/puppet-agent.8 +1 -1
  35. data/man/man8/puppet-apply.8 +1 -1
  36. data/man/man8/puppet-ca.8 +1 -1
  37. data/man/man8/puppet-catalog.8 +1 -1
  38. data/man/man8/puppet-cert.8 +1 -1
  39. data/man/man8/puppet-certificate.8 +1 -1
  40. data/man/man8/puppet-certificate_request.8 +1 -1
  41. data/man/man8/puppet-certificate_revocation_list.8 +1 -1
  42. data/man/man8/puppet-config.8 +1 -1
  43. data/man/man8/puppet-describe.8 +1 -1
  44. data/man/man8/puppet-device.8 +1 -1
  45. data/man/man8/puppet-doc.8 +1 -1
  46. data/man/man8/puppet-epp.8 +1 -1
  47. data/man/man8/puppet-facts.8 +1 -1
  48. data/man/man8/puppet-filebucket.8 +1 -1
  49. data/man/man8/puppet-generate.8 +1 -1
  50. data/man/man8/puppet-help.8 +1 -1
  51. data/man/man8/puppet-key.8 +1 -1
  52. data/man/man8/puppet-lookup.8 +1 -1
  53. data/man/man8/puppet-man.8 +1 -1
  54. data/man/man8/puppet-master.8 +1 -1
  55. data/man/man8/puppet-module.8 +1 -1
  56. data/man/man8/puppet-node.8 +1 -1
  57. data/man/man8/puppet-parser.8 +1 -1
  58. data/man/man8/puppet-plugin.8 +1 -1
  59. data/man/man8/puppet-report.8 +1 -1
  60. data/man/man8/puppet-resource.8 +1 -1
  61. data/man/man8/puppet-script.8 +1 -1
  62. data/man/man8/puppet-status.8 +1 -1
  63. data/man/man8/puppet.8 +2 -2
  64. data/spec/integration/network/http_pool_spec.rb +120 -0
  65. data/spec/integration/type/package_spec.rb +1 -1
  66. data/spec/integration/util/windows/registry_spec.rb +52 -0
  67. data/spec/integration/util/windows/user_spec.rb +19 -0
  68. data/spec/lib/puppet_spec/https.rb +166 -0
  69. data/spec/unit/configurer_spec.rb +49 -13
  70. data/spec/unit/functions/new_spec.rb +15 -0
  71. data/spec/unit/hiera/scope_spec.rb +7 -0
  72. data/spec/unit/network/http/connection_spec.rb +0 -130
  73. data/spec/unit/provider/package/dpkg_spec.rb +18 -1
  74. data/spec/unit/provider/package/gem_spec.rb +101 -48
  75. data/spec/unit/provider/package/pip3_spec.rb +17 -0
  76. data/spec/unit/provider/package/pip_spec.rb +59 -68
  77. data/spec/unit/provider/package/puppet_gem_spec.rb +22 -6
  78. data/spec/unit/provider/package/rpm_spec.rb +116 -27
  79. data/spec/unit/provider/service/upstart_spec.rb +3 -19
  80. data/spec/unit/settings/server_list_setting_spec.rb +21 -0
  81. data/spec/unit/ssl/validator_spec.rb +2 -0
  82. data/spec/unit/util/pidlock_spec.rb +46 -0
  83. metadata +9 -2
@@ -221,19 +221,30 @@ describe Puppet::Type.type(:package).provider(:dpkg) do
221
221
  allow(Tempfile).to receive(:new).and_return(tempfile)
222
222
  end
223
223
 
224
- it "installs first if holding" do
224
+ it "installs first if package is not present and ensure holding" do
225
+
225
226
  allow(provider).to receive(:execute)
227
+ allow(provider).to receive(:package_not_installed?).and_return(true)
226
228
  expect(provider).to receive(:install).once
227
229
  provider.hold
228
230
  end
229
231
 
232
+ it "skips install new package if package is allready installed" do
233
+ allow(provider).to receive(:execute)
234
+ allow(provider).to receive(:package_not_installed?).and_return(false)
235
+ expect(provider).not_to receive(:install)
236
+ provider.hold
237
+ end
238
+
230
239
  it "executes dpkg --set-selections when holding" do
240
+ allow(provider).to receive(:package_not_installed?).and_return(false)
231
241
  allow(provider).to receive(:install)
232
242
  expect(provider).to receive(:execute).with([:dpkg, '--set-selections'], {:failonfail => false, :combine => false, :stdinfile => tempfile.path}).once
233
243
  provider.hold
234
244
  end
235
245
 
236
246
  it "executes dpkg --set-selections when unholding" do
247
+ allow(provider).to receive(:package_not_installed?).and_return(false)
237
248
  allow(provider).to receive(:install)
238
249
  expect(provider).to receive(:execute).with([:dpkg, '--set-selections'], {:failonfail => false, :combine => false, :stdinfile => tempfile.path}).once
239
250
  provider.hold
@@ -275,4 +286,10 @@ describe Puppet::Type.type(:package).provider(:dpkg) do
275
286
  expect(provider).to receive(:dpkg).with("--purge", resource_name)
276
287
  provider.purge
277
288
  end
289
+
290
+ it "raises error if package name is nil" do
291
+ expect {provider.package_not_installed?(nil)}.to raise_error(ArgumentError,"Package name is nil or empty")
292
+ expect {provider.package_not_installed?("")}.to raise_error(ArgumentError,"Package name is nil or empty")
293
+ end
278
294
  end
295
+
@@ -2,7 +2,15 @@ require 'spec_helper'
2
2
 
3
3
  context Puppet::Type.type(:package).provider(:gem) do
4
4
 
5
+ it { is_expected.to be_installable }
6
+ it { is_expected.to be_uninstallable }
7
+ it { is_expected.to be_upgradeable }
8
+ it { is_expected.to be_versionable }
9
+ it { is_expected.to be_install_options }
10
+ it { is_expected.to be_targetable }
11
+
5
12
  let(:provider_gem_cmd) { '/provider/gem' }
13
+ let(:execute_options) { {:failonfail => true, :combine => true, :custom_environment => {"HOME"=>ENV["HOME"]}} }
6
14
 
7
15
  context 'installing myresource' do
8
16
  let(:resource) do
@@ -18,8 +26,6 @@ context Puppet::Type.type(:package).provider(:gem) do
18
26
  provider
19
27
  end
20
28
 
21
- let(:execute_options) { {:failonfail => true, :combine => true, :custom_environment => {"HOME"=>ENV["HOME"]}} }
22
-
23
29
  before :each do
24
30
  resource.provider = provider
25
31
  allow(described_class).to receive(:command).with(:gemcmd).and_return(provider_gem_cmd)
@@ -31,45 +37,45 @@ context Puppet::Type.type(:package).provider(:gem) do
31
37
  end
32
38
 
33
39
  it "should use the path to the gem command" do
34
- allow(described_class).to receive(:which).with(provider_gem_cmd).and_return(provider_gem_cmd)
40
+ allow(described_class).to receive(:validate_command).with(provider_gem_cmd)
35
41
  expect(described_class).to receive(:execute).with(be_a(Array), execute_options) { |args| expect(args[0]).to eq(provider_gem_cmd) }.and_return("")
36
42
  provider.install
37
43
  end
38
44
 
39
45
  it "should specify that the gem is being installed" do
40
- expect(described_class).to receive(:execute_gem_command).with(be_a(Array)) { |args| expect(args[0]).to eq("install") }.and_return("")
46
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, be_a(Array)) { |cmd, args| expect(args[0]).to eq("install") }.and_return("")
41
47
  provider.install
42
48
  end
43
49
 
44
50
  it "should specify that --rdoc should not be included when gem version is < 2.0.0" do
45
- expect(described_class).to receive(:execute_gem_command).with(be_a(Array)) { |args| expect(args[1]).to eq("--no-rdoc") }.and_return("")
51
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, be_a(Array)) { |cmd, args| expect(args[1]).to eq("--no-rdoc") }.and_return("")
46
52
  provider.install
47
53
  end
48
54
 
49
55
  it "should specify that --ri should not be included when gem version is < 2.0.0" do
50
- expect(described_class).to receive(:execute_gem_command).with(be_a(Array)) { |args| expect(args[2]).to eq("--no-ri") }.and_return("")
56
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, be_a(Array)) { |cmd, args| expect(args[2]).to eq("--no-ri") }.and_return("")
51
57
  provider.install
52
58
  end
53
59
 
54
60
  it "should specify that --document should not be included when gem version is >= 2.0.0" do
55
61
  allow(provider).to receive(:rubygem_version).and_return('2.0.0')
56
- expect(described_class).to receive(:execute_gem_command).with(be_a(Array)) { |args| expect(args[1]).to eq("--no-document") }.and_return("")
62
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, be_a(Array)) { |cmd, args| expect(args[1]).to eq("--no-document") }.and_return("")
57
63
  provider.install
58
64
  end
59
65
 
60
66
  it "should specify the package name" do
61
- expect(described_class).to receive(:execute_gem_command).with(be_a(Array)) { |args| expect(args[3]).to eq("myresource") }.and_return("")
67
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, be_a(Array)) { |cmd, args| expect(args[3]).to eq("myresource") }.and_return("")
62
68
  provider.install
63
69
  end
64
70
 
65
71
  it "should not append install_options by default" do
66
- expect(described_class).to receive(:execute_gem_command).with(be_a(Array)) { |args| expect(args.length).to eq(4) }.and_return("")
72
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, be_a(Array)) { |cmd, args| expect(args.length).to eq(4) }.and_return("")
67
73
  provider.install
68
74
  end
69
75
 
70
76
  it "should allow setting an install_options parameter" do
71
77
  resource[:install_options] = [ '--force', {'--bindir' => '/usr/bin' } ]
72
- expect(described_class).to receive(:execute_gem_command).with(be_a(Array)) do |args|
78
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, be_a(Array)) do |cmd, args|
73
79
  expect(args[1]).to eq('--force')
74
80
  expect(args[2]).to eq('--bindir=/usr/bin')
75
81
  end.and_return("")
@@ -80,7 +86,7 @@ context Puppet::Type.type(:package).provider(:gem) do
80
86
  context "as a normal file" do
81
87
  it "should use the file name instead of the gem name" do
82
88
  resource[:source] = "/my/file"
83
- expect(described_class).to receive(:execute_gem_command).with(be_a(Array)) { |args| expect(args[3]).to eq("/my/file") }.and_return("")
89
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, array_including("/my/file")).and_return("")
84
90
  provider.install
85
91
  end
86
92
  end
@@ -88,7 +94,7 @@ context Puppet::Type.type(:package).provider(:gem) do
88
94
  context "as a file url" do
89
95
  it "should use the file name instead of the gem name" do
90
96
  resource[:source] = "file:///my/file"
91
- expect(described_class).to receive(:execute_gem_command).with(be_a(Array)) { |args| expect(args[3]).to eq("/my/file") }.and_return("")
97
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, array_including("/my/file")).and_return("")
92
98
  provider.install
93
99
  end
94
100
  end
@@ -103,7 +109,7 @@ context Puppet::Type.type(:package).provider(:gem) do
103
109
  context "as a non-file and non-puppet url" do
104
110
  it "should treat the source as a gem repository" do
105
111
  resource[:source] = "http://host/my/file"
106
- expect(described_class).to receive(:execute_gem_command).with(be_a(Array)) { |args| expect(args[3..5]).to eq(["--source", "http://host/my/file", "myresource"]) }.and_return("")
112
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, be_a(Array)) { |cmd, args| expect(args[3..5]).to eq(["--source", "http://host/my/file", "myresource"]) }.and_return("")
107
113
  provider.install
108
114
  end
109
115
  end
@@ -111,7 +117,7 @@ context Puppet::Type.type(:package).provider(:gem) do
111
117
  context "as a windows path on windows", :if => Puppet.features.microsoft_windows? do
112
118
  it "should treat the source as a local path" do
113
119
  resource[:source] = "c:/this/is/a/path/to/a/gem.gem"
114
- expect(described_class).to receive(:execute_gem_command).with(be_a(Array)) { |args| expect(args[3]).to eq("c:/this/is/a/path/to/a/gem.gem") }.and_return("")
120
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, array_including("c:/this/is/a/path/to/a/gem.gem")).and_return("")
115
121
  provider.install
116
122
  end
117
123
  end
@@ -131,7 +137,7 @@ context Puppet::Type.type(:package).provider(:gem) do
131
137
  #gemlist is used for retrieving both local and remote version numbers, and there are cases
132
138
  # (particularly local) where it makes sense for it to return an array. That doesn't make
133
139
  # sense for '#latest', though.
134
- expect(provider.class).to receive(:gemlist).with({:justme => 'myresource'}).and_return({
140
+ expect(provider.class).to receive(:gemlist).with({:command => provider_gem_cmd, :justme => 'myresource'}).and_return({
135
141
  :name => 'myresource',
136
142
  :ensure => ["3.0"],
137
143
  :provider => :gem,
@@ -142,7 +148,7 @@ context Puppet::Type.type(:package).provider(:gem) do
142
148
  it "should list from the specified source repository" do
143
149
  resource[:source] = "http://foo.bar.baz/gems"
144
150
  expect(provider.class).to receive(:gemlist).
145
- with({:justme => 'myresource', :source => "http://foo.bar.baz/gems"}).
151
+ with({:command => provider_gem_cmd, :justme => 'myresource', :source => "http://foo.bar.baz/gems"}).
146
152
  and_return({
147
153
  :name => 'myresource',
148
154
  :ensure => ["3.0"],
@@ -158,67 +164,67 @@ context Puppet::Type.type(:package).provider(:gem) do
158
164
  end
159
165
 
160
166
  it "should return an empty array when no gems installed" do
161
- expect(described_class).to receive(:execute_gem_command).with(%w{list --local}).and_return("\n")
167
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, %w{list --local}).and_return("\n")
162
168
  expect(described_class.instances).to eq([])
163
169
  end
164
170
 
165
171
  it "should return ensure values as an array of installed versions" do
166
- expect(described_class).to receive(:execute_gem_command).with(%w{list --local}).and_return(<<-HEREDOC.gsub(/ /, ''))
172
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, %w{list --local}).and_return(<<-HEREDOC.gsub(/ /, ''))
167
173
  systemu (1.2.0)
168
174
  vagrant (0.8.7, 0.6.9)
169
175
  HEREDOC
170
176
 
171
177
  expect(described_class.instances.map {|p| p.properties}).to eq([
172
- {:ensure => ["1.2.0"], :provider => :gem, :name => 'systemu'},
173
- {:ensure => ["0.8.7", "0.6.9"], :provider => :gem, :name => 'vagrant'}
178
+ {:name => "systemu", :provider => :gem, :command => provider_gem_cmd, :ensure => ["1.2.0"]},
179
+ {:name => "vagrant", :provider => :gem, :command => provider_gem_cmd, :ensure => ["0.8.7", "0.6.9"]}
174
180
  ])
175
181
  end
176
182
 
177
183
  it "should ignore platform specifications" do
178
- expect(described_class).to receive(:execute_gem_command).with(%w{list --local}).and_return(<<-HEREDOC.gsub(/ /, ''))
184
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, %w{list --local}).and_return(<<-HEREDOC.gsub(/ /, ''))
179
185
  systemu (1.2.0)
180
186
  nokogiri (1.6.1 ruby java x86-mingw32 x86-mswin32-60, 1.4.4.1 x86-mswin32)
181
187
  HEREDOC
182
188
 
183
189
  expect(described_class.instances.map {|p| p.properties}).to eq([
184
- {:ensure => ["1.2.0"], :provider => :gem, :name => 'systemu'},
185
- {:ensure => ["1.6.1", "1.4.4.1"], :provider => :gem, :name => 'nokogiri'}
190
+ {:name => "systemu", :provider => :gem, :command => provider_gem_cmd, :ensure => ["1.2.0"]},
191
+ {:name => "nokogiri", :provider => :gem, :command => provider_gem_cmd, :ensure => ["1.6.1", "1.4.4.1"]}
186
192
  ])
187
193
  end
188
194
 
189
195
  it "should not list 'default: ' text from rubygems''" do
190
- expect(described_class).to receive(:execute_gem_command).with(%w{list --local}).and_return(<<-HEREDOC.gsub(/ /, ''))
196
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, %w{list --local}).and_return(<<-HEREDOC.gsub(/ /, ''))
191
197
  bundler (1.16.1, default: 1.16.0, 1.15.1)
192
198
  HEREDOC
193
199
 
194
200
  expect(described_class.instances.map {|p| p.properties}).to eq([
195
- {:name => 'bundler', :ensure => ["1.16.1", "1.16.0", "1.15.1"], :provider => :gem}
201
+ {:name => "bundler", :provider => :gem, :command => provider_gem_cmd, :ensure => ["1.16.1", "1.16.0", "1.15.1"]}
196
202
  ])
197
203
  end
198
204
 
199
205
  it "should not fail when an unmatched line is returned" do
200
- expect(described_class).to receive(:execute_gem_command).with(%w{list --local}).and_return(File.read(my_fixture('line-with-1.8.5-warning')))
206
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, %w{list --local}).and_return(File.read(my_fixture('line-with-1.8.5-warning')))
201
207
 
202
208
  expect(described_class.instances.map {|p| p.properties}).
203
- to eq([{provider: :gem, ensure: ["0.3.2"], name: "columnize"},
204
- {provider: :gem, ensure: ["1.1.3"], name: "diff-lcs"},
205
- {provider: :gem, ensure: ["0.0.1"], name: "metaclass"},
206
- {provider: :gem, ensure: ["0.10.5"], name: "mocha"},
207
- {provider: :gem, ensure: ["0.8.7"], name: "rake"},
208
- {provider: :gem, ensure: ["2.9.0"], name: "rspec-core"},
209
- {provider: :gem, ensure: ["2.9.1"], name: "rspec-expectations"},
210
- {provider: :gem, ensure: ["2.9.0"], name: "rspec-mocks"},
211
- {provider: :gem, ensure: ["0.9.0"], name: "rubygems-bundler"},
212
- {provider: :gem, ensure: ["1.11.3.3"], name: "rvm"}])
209
+ to eq([{:name=>"columnize", :provider=>:gem, :command => provider_gem_cmd, :ensure=>["0.3.2"]},
210
+ {:name=>"diff-lcs", :provider=>:gem, :command => provider_gem_cmd, :ensure=>["1.1.3"]},
211
+ {:name=>"metaclass", :provider=>:gem, :command => provider_gem_cmd, :ensure=>["0.0.1"]},
212
+ {:name=>"mocha", :provider=>:gem, :command => provider_gem_cmd, :ensure=>["0.10.5"]},
213
+ {:name=>"rake", :provider=>:gem, :command => provider_gem_cmd, :ensure=>["0.8.7"]},
214
+ {:name=>"rspec-core", :provider=>:gem, :command => provider_gem_cmd, :ensure=>["2.9.0"]},
215
+ {:name=>"rspec-expectations", :provider=>:gem, :command => provider_gem_cmd, :ensure=>["2.9.1"]},
216
+ {:name=>"rspec-mocks", :provider=>:gem, :command => provider_gem_cmd, :ensure=>["2.9.0"]},
217
+ {:name=>"rubygems-bundler", :provider=>:gem, :command => provider_gem_cmd, :ensure=>["0.9.0"]},
218
+ {:name=>"rvm", :provider=>:gem, :command => provider_gem_cmd, :ensure=>["1.11.3.3"]}])
213
219
  end
214
220
  end
215
221
 
216
222
  context "listing gems" do
217
223
  context "searching for a single package" do
218
224
  it "searches for an exact match" do
219
- expect(described_class).to receive(:execute_gem_command).with(include('\Abundler\z')).and_return(File.read(my_fixture('gem-list-single-package')))
220
- expected = {:name => 'bundler', :ensure => %w[1.6.2], :provider => :gem}
221
- expect(described_class.gemlist({:justme => 'bundler'})).to eq(expected)
225
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, array_including('\Abundler\z')).and_return(File.read(my_fixture('gem-list-single-package')))
226
+ expected = {:name=>"bundler", :provider=>:gem, :ensure=>["1.6.2"]}
227
+ expect(described_class.gemlist({:command => provider_gem_cmd, :justme => 'bundler'})).to eq(expected)
222
228
  end
223
229
  end
224
230
  end
@@ -294,6 +300,39 @@ context Puppet::Type.type(:package).provider(:gem) do
294
300
  end
295
301
  end
296
302
 
303
+ context 'installing myresource with a target command' do
304
+ let(:resource_gem_cmd) { '/resource/gem' }
305
+
306
+ let(:resource) do
307
+ Puppet::Type.type(:package).new(
308
+ :name => "myresource",
309
+ :ensure => :installed,
310
+ )
311
+ end
312
+
313
+ let(:provider) do
314
+ provider = described_class.new
315
+ provider.resource = resource
316
+ provider
317
+ end
318
+
319
+ before :each do
320
+ resource.provider = provider
321
+ end
322
+
323
+ context "when installing with a target command" do
324
+ before :each do
325
+ allow(described_class).to receive(:which).with(resource_gem_cmd).and_return(resource_gem_cmd)
326
+ end
327
+
328
+ it "should use the path to the other gem" do
329
+ resource::original_parameters[:command] = resource_gem_cmd
330
+ expect(described_class).to receive(:execute_gem_command).with(resource_gem_cmd, be_a(Array)).twice.and_return("")
331
+ provider.install
332
+ end
333
+ end
334
+ end
335
+
297
336
  context 'uninstalling myresource' do
298
337
  let(:resource) do
299
338
  Puppet::Type.type(:package).new(
@@ -308,8 +347,6 @@ context Puppet::Type.type(:package).provider(:gem) do
308
347
  provider
309
348
  end
310
349
 
311
- let(:execute_options) { {:failonfail => true, :combine => true, :custom_environment => {"HOME"=>ENV["HOME"]}} }
312
-
313
350
  before :each do
314
351
  resource.provider = provider
315
352
  allow(described_class).to receive(:command).with(:gemcmd).and_return(provider_gem_cmd)
@@ -317,39 +354,39 @@ context Puppet::Type.type(:package).provider(:gem) do
317
354
 
318
355
  context "when uninstalling" do
319
356
  it "should use the path to the gem command" do
320
- allow(described_class).to receive(:which).with(provider_gem_cmd).and_return(provider_gem_cmd)
357
+ allow(described_class).to receive(:validate_command).with(provider_gem_cmd)
321
358
  expect(described_class).to receive(:execute).with(be_a(Array), execute_options) { |args| expect(args[0]).to eq(provider_gem_cmd) }.and_return("")
322
359
  provider.uninstall
323
360
  end
324
361
 
325
362
  it "should specify that the gem is being uninstalled" do
326
- expect(described_class).to receive(:execute_gem_command).with(be_a(Array)) { |args| expect(args[0]).to eq("uninstall") }.and_return("")
363
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, be_a(Array)) { |cmd, args| expect(args[0]).to eq("uninstall") }.and_return("")
327
364
  provider.uninstall
328
365
  end
329
366
 
330
367
  it "should specify that the relevant executables should be removed without confirmation" do
331
- expect(described_class).to receive(:execute_gem_command).with(be_a(Array)) { |args| expect(args[1]).to eq("--executables") }.and_return("")
368
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, be_a(Array)) { |cmd, args| expect(args[1]).to eq("--executables") }.and_return("")
332
369
  provider.uninstall
333
370
  end
334
371
 
335
372
  it "should specify that all the matching versions should be removed" do
336
- expect(described_class).to receive(:execute_gem_command).with(be_a(Array)) { |args| expect(args[2]).to eq("--all") }.and_return("")
373
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, be_a(Array)) { |cmd, args| expect(args[2]).to eq("--all") }.and_return("")
337
374
  provider.uninstall
338
375
  end
339
376
 
340
377
  it "should specify the package name" do
341
- expect(described_class).to receive(:execute_gem_command).with(be_a(Array)) { |args| expect(args[3]).to eq("myresource") }.and_return("")
378
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, be_a(Array)) { |cmd, args| expect(args[3]).to eq("myresource") }.and_return("")
342
379
  provider.uninstall
343
380
  end
344
381
 
345
382
  it "should not append uninstall_options by default" do
346
- expect(described_class).to receive(:execute_gem_command).with(be_a(Array)) { |args| expect(args.length).to eq(4) }.and_return("")
383
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, be_a(Array)) { |cmd, args| expect(args.length).to eq(4) }.and_return("")
347
384
  provider.uninstall
348
385
  end
349
386
 
350
387
  it "should allow setting an uninstall_options parameter" do
351
388
  resource[:uninstall_options] = [ '--ignore-dependencies', {'--version' => '0.1.1' } ]
352
- expect(described_class).to receive(:execute_gem_command).with(be_a(Array)) do |args|
389
+ expect(described_class).to receive(:execute_gem_command).with(provider_gem_cmd, be_a(Array)) do |cmd, args|
353
390
  expect(args[4]).to eq('--ignore-dependencies')
354
391
  expect(args[5]).to eq('--version=0.1.1')
355
392
  end.and_return('')
@@ -357,4 +394,20 @@ context Puppet::Type.type(:package).provider(:gem) do
357
394
  end
358
395
  end
359
396
  end
397
+
398
+ context 'calculated specificity' do
399
+ context 'when is not defaultfor' do
400
+ subject { described_class.specificity }
401
+ it { is_expected.to eql 1 }
402
+ end
403
+
404
+ context 'when is defaultfor' do
405
+ let(:os) { Facter.value(:operatingsystem) }
406
+ subject do
407
+ described_class.defaultfor(operatingsystem: os)
408
+ described_class.specificity
409
+ end
410
+ it { is_expected.to be > 100 }
411
+ end
412
+ end
360
413
  end
@@ -7,6 +7,7 @@ describe Puppet::Type.type(:package).provider(:pip3) do
7
7
  it { is_expected.to be_upgradeable }
8
8
  it { is_expected.to be_versionable }
9
9
  it { is_expected.to be_install_options }
10
+ it { is_expected.to be_targetable }
10
11
 
11
12
  it "should inherit most things from pip provider" do
12
13
  expect(described_class < Puppet::Type.type(:package).provider(:pip))
@@ -16,4 +17,20 @@ describe Puppet::Type.type(:package).provider(:pip3) do
16
17
  expect(described_class.cmd).to eq(["pip3"])
17
18
  end
18
19
 
20
+ context 'calculated specificity' do
21
+ context 'when is not defaultfor' do
22
+ subject { described_class.specificity }
23
+ it { is_expected.to eql 1 }
24
+ end
25
+
26
+ context 'when is defaultfor' do
27
+ let(:os) { Facter.value(:operatingsystem) }
28
+ subject do
29
+ described_class.defaultfor(operatingsystem: os)
30
+ described_class.specificity
31
+ end
32
+ it { is_expected.to be > 100 }
33
+ end
34
+ end
35
+
19
36
  end
@@ -3,8 +3,17 @@ require 'spec_helper'
3
3
  osfamilies = { 'windows' => ['pip.exe'], 'other' => ['pip', 'pip-python'] }
4
4
 
5
5
  describe Puppet::Type.type(:package).provider(:pip) do
6
- before do
6
+
7
+ it { is_expected.to be_installable }
8
+ it { is_expected.to be_uninstallable }
9
+ it { is_expected.to be_upgradeable }
10
+ it { is_expected.to be_versionable }
11
+ it { is_expected.to be_install_options }
12
+ it { is_expected.to be_targetable }
13
+
14
+ before do
7
15
  @resource = Puppet::Resource.new(:package, "fake_package")
16
+ allow(@resource).to receive(:original_parameters).and_return({})
8
17
  @provider = described_class.new(@resource)
9
18
  @client = double('client')
10
19
  allow(@client).to receive(:call).with('package_releases', 'real_package').and_return(["1.3", "1.2.5", "1.2.4"])
@@ -46,17 +55,17 @@ describe Puppet::Type.type(:package).provider(:pip) do
46
55
  osfamilies.each do |osfamily, pip_cmds|
47
56
  it "should return an array on #{osfamily} systems when #{pip_cmds.join(' or ')} is present" do
48
57
  allow(Puppet.features).to receive(:microsoft_windows?).and_return(osfamily == 'windows')
49
- pip_cmds.each do |pip_cmd|
58
+ pip_cmds.each do |pip_cmd|
50
59
  pip_cmds.each do |cmd|
51
60
  unless cmd == pip_cmd
52
61
  expect(described_class).to receive(:which).with(cmd).and_return(nil)
53
62
  end
54
63
  end
55
- allow(described_class).to receive(:pip_version).and_return('8.0.1')
56
- expect(described_class).to receive(:which).with(pip_cmd).and_return("/fake/bin/#{pip_cmd}")
64
+ allow(described_class).to receive(:pip_version).with(pip_cmd).and_return('8.0.1')
65
+ expect(described_class).to receive(:which).with(pip_cmd).and_return(pip_cmd)
57
66
  p = double("process")
58
67
  expect(p).to receive(:collect).and_yield("real_package==1.2.5")
59
- expect(described_class).to receive(:execpipe).with(["/fake/bin/#{pip_cmd}", "freeze"]).and_yield(p)
68
+ expect(described_class).to receive(:execpipe).with([pip_cmd, ["freeze"]]).and_yield(p)
60
69
  described_class.instances
61
70
  end
62
71
  end
@@ -66,11 +75,11 @@ describe Puppet::Type.type(:package).provider(:pip) do
66
75
  versions.each do |version|
67
76
  it "should use the --all option when version is '#{version}'" do
68
77
  allow(Puppet.features).to receive(:microsoft_windows?).and_return(osfamily == 'windows')
69
- allow(described_class).to receive(:pip_cmd).and_return('/fake/bin/pip')
70
- allow(described_class).to receive(:pip_version).and_return(version)
78
+ allow(described_class).to receive(:provider_command).and_return('/fake/bin/pip')
79
+ allow(described_class).to receive(:pip_version).with('/fake/bin/pip').and_return(version)
71
80
  p = double("process")
72
81
  expect(p).to receive(:collect).and_yield("real_package==1.2.5")
73
- expect(described_class).to receive(:execpipe).with(["/fake/bin/pip", "freeze", "--all"]).and_yield(p)
82
+ expect(described_class).to receive(:execpipe).with(["/fake/bin/pip", ["freeze", "--all"]]).and_yield(p)
74
83
  described_class.instances
75
84
  end
76
85
  end
@@ -89,6 +98,8 @@ describe Puppet::Type.type(:package).provider(:pip) do
89
98
  context "query" do
90
99
  before do
91
100
  @resource[:name] = "real_package"
101
+ allow(described_class).to receive(:provider_command).and_return('/fake/bin/pip')
102
+ allow(described_class).to receive(:validate_command).with('/fake/bin/pip')
92
103
  end
93
104
 
94
105
  it "should return a hash when pip and the package are present" do
@@ -96,12 +107,14 @@ describe Puppet::Type.type(:package).provider(:pip) do
96
107
  :ensure => "1.2.5",
97
108
  :name => "real_package",
98
109
  :provider => :pip,
110
+ :command => '/fake/bin/pip',
99
111
  })])
100
112
 
101
113
  expect(@provider.query).to eq({
102
114
  :ensure => "1.2.5",
103
115
  :name => "real_package",
104
116
  :provider => :pip,
117
+ :command => '/fake/bin/pip',
105
118
  })
106
119
  end
107
120
 
@@ -117,12 +130,14 @@ describe Puppet::Type.type(:package).provider(:pip) do
117
130
  :ensure => "1.2.5",
118
131
  :name => "real_package",
119
132
  :provider => :pip,
133
+ :command => '/fake/bin/pip',
120
134
  })])
121
135
 
122
136
  expect(@provider.query).to eq({
123
137
  :ensure => "1.2.5",
124
138
  :name => "real_package",
125
139
  :provider => :pip,
140
+ :command => '/fake/bin/pip',
126
141
  })
127
142
  end
128
143
  end
@@ -130,10 +145,12 @@ describe Puppet::Type.type(:package).provider(:pip) do
130
145
  context "latest" do
131
146
  context "with pip version < 1.5.4" do
132
147
  before :each do
133
- allow(described_class).to receive(:pip_version).and_return('1.0.1')
148
+ allow(described_class).to receive(:pip_version).with("/fake/bin/pip").and_return('1.0.1')
134
149
  allow(described_class).to receive(:which).with('pip').and_return("/fake/bin/pip")
135
150
  allow(described_class).to receive(:which).with('pip-python').and_return("/fake/bin/pip")
136
151
  allow(described_class).to receive(:which).with('pip.exe').and_return("/fake/bin/pip")
152
+ allow(described_class).to receive(:provider_command).and_return('/fake/bin/pip')
153
+ allow(described_class).to receive(:validate_command).with('/fake/bin/pip')
137
154
  end
138
155
 
139
156
  it "should find a version number for new_pip_package" do
@@ -186,10 +203,12 @@ describe Puppet::Type.type(:package).provider(:pip) do
186
203
  # For Pip 1.5.4 and above, you can get a version list from CLI - which allows for native pip behavior
187
204
  # with regards to custom repositories, proxies and the like
188
205
  before :each do
189
- allow(described_class).to receive(:pip_version).and_return('1.5.4')
206
+ allow(described_class).to receive(:pip_version).with("/fake/bin/pip").and_return('1.5.4')
190
207
  allow(described_class).to receive(:which).with('pip').and_return("/fake/bin/pip")
191
208
  allow(described_class).to receive(:which).with('pip-python').and_return("/fake/bin/pip")
192
209
  allow(described_class).to receive(:which).with('pip.exe').and_return("/fake/bin/pip")
210
+ allow(described_class).to receive(:provider_command).and_return('/fake/bin/pip')
211
+ allow(described_class).to receive(:validate_command).with('/fake/bin/pip')
193
212
  end
194
213
 
195
214
  it "should find a version number for real_package" do
@@ -239,12 +258,14 @@ describe Puppet::Type.type(:package).provider(:pip) do
239
258
  before do
240
259
  @resource[:name] = "fake_package"
241
260
  @url = "git+https://example.com/fake_package.git"
261
+ allow(described_class).to receive(:provider_command).and_return('/fake/bin/pip')
262
+ allow(described_class).to receive(:validate_command).with('/fake/bin/pip')
242
263
  end
243
264
 
244
265
  it "should install" do
245
266
  @resource[:ensure] = :installed
246
267
  @resource[:source] = nil
247
- expect(@provider).to receive(:lazy_pip).with("install", '-q', "fake_package")
268
+ expect(@provider).to receive(:execute).with(["/fake/bin/pip", ["install", "-q", "fake_package"]])
248
269
  @provider.install
249
270
  end
250
271
 
@@ -252,7 +273,8 @@ describe Puppet::Type.type(:package).provider(:pip) do
252
273
  # The -e flag makes the provider non-idempotent
253
274
  @resource[:ensure] = :installed
254
275
  @resource[:source] = @url
255
- expect(@provider).to receive(:lazy_pip) do |*args|
276
+ # TJK
277
+ expect(@provider).to receive(:execute) do |*args|
256
278
  expect(args).not_to include("-e")
257
279
  end
258
280
  @provider.install
@@ -261,28 +283,31 @@ describe Puppet::Type.type(:package).provider(:pip) do
261
283
  it "should install from SCM" do
262
284
  @resource[:ensure] = :installed
263
285
  @resource[:source] = @url
264
- expect(@provider).to receive(:lazy_pip).with("install", '-q', "#{@url}#egg=fake_package")
286
+ expect(@provider).to receive(:execute).with(["/fake/bin/pip", ["install", "-q", "#{@url}#egg=fake_package"]])
265
287
  @provider.install
266
288
  end
267
289
 
268
290
  it "should install a particular SCM revision" do
269
291
  @resource[:ensure] = "0123456"
270
292
  @resource[:source] = @url
271
- expect(@provider).to receive(:lazy_pip).with("install", "-q", "#{@url}@0123456#egg=fake_package")
293
+ # TJK
294
+ expect(@provider).to receive(:execute).with(["/fake/bin/pip", ["install", "-q", "#{@url}@0123456#egg=fake_package"]])
272
295
  @provider.install
273
296
  end
274
297
 
275
298
  it "should install a particular version" do
276
299
  @resource[:ensure] = "0.0.0"
277
300
  @resource[:source] = nil
278
- expect(@provider).to receive(:lazy_pip).with("install", "-q", "fake_package==0.0.0")
301
+ # TJK
302
+ expect(@provider).to receive(:execute).with(["/fake/bin/pip", ["install", "-q", "fake_package==0.0.0"]])
279
303
  @provider.install
280
304
  end
281
305
 
282
306
  it "should upgrade" do
283
307
  @resource[:ensure] = :latest
284
308
  @resource[:source] = nil
285
- expect(@provider).to receive(:lazy_pip).with("install", "-q", "--upgrade", "fake_package")
309
+ # TJK
310
+ expect(@provider).to receive(:execute).with(["/fake/bin/pip", ["install", "-q", "--upgrade", "fake_package"]])
286
311
  @provider.install
287
312
  end
288
313
 
@@ -290,15 +315,20 @@ describe Puppet::Type.type(:package).provider(:pip) do
290
315
  @resource[:ensure] = :installed
291
316
  @resource[:source] = nil
292
317
  @resource[:install_options] = [{"--timeout" => "10"}, "--no-index"]
293
- expect(@provider).to receive(:lazy_pip).with("install", "-q", "--timeout=10", "--no-index", "fake_package")
318
+ expect(@provider).to receive(:execute).with(["/fake/bin/pip", ["install", "-q", "--timeout=10", "--no-index", "fake_package"]])
294
319
  @provider.install
295
320
  end
296
321
  end
297
322
 
298
323
  context "uninstall" do
324
+ before do
325
+ allow(described_class).to receive(:provider_command).and_return('/fake/bin/pip')
326
+ allow(described_class).to receive(:validate_command).with('/fake/bin/pip')
327
+ end
328
+
299
329
  it "should uninstall" do
300
330
  @resource[:name] = "fake_package"
301
- expect(@provider).to receive(:lazy_pip).with('uninstall', '-y', '-q', 'fake_package')
331
+ expect(@provider).to receive(:execute).with(["/fake/bin/pip", ["uninstall", "-y", "-q", "fake_package"]])
302
332
  @provider.uninstall
303
333
  end
304
334
  end
@@ -311,67 +341,28 @@ describe Puppet::Type.type(:package).provider(:pip) do
311
341
  end
312
342
 
313
343
  context "pip_version" do
314
- it "should return nil on missing pip" do
315
- allow(described_class).to receive(:pip_cmd).and_return(nil)
316
- expect(described_class.pip_version).to eq(nil)
317
- end
318
-
319
344
  it "should look up version if pip is present" do
320
345
  allow(described_class).to receive(:pip_cmd).and_return('/fake/bin/pip')
321
346
  p = double("process")
322
347
  expect(p).to receive(:collect).and_yield('pip 8.0.2 from /usr/local/lib/python2.7/dist-packages (python 2.7)')
323
348
  expect(described_class).to receive(:execpipe).with(['/fake/bin/pip', '--version']).and_yield(p)
324
- expect(described_class.pip_version).to eq('8.0.2')
349
+ expect(described_class.pip_version('/fake/bin/pip')).to eq('8.0.2')
325
350
  end
326
351
  end
327
352
 
328
- context "lazy_pip" do
329
- after(:each) do
330
- Puppet::Type::Package::ProviderPip.instance_variable_set(:@confine_collection, nil)
331
- end
332
-
333
- it "should succeed if pip is present" do
334
- allow(@provider).to receive(:pip).and_return(nil)
335
- @provider.method(:lazy_pip).call "freeze"
353
+ context 'calculated specificity' do
354
+ context 'when is not defaultfor' do
355
+ subject { described_class.specificity }
356
+ it { is_expected.to eql 1 }
336
357
  end
337
358
 
338
- osfamilies.each do |osfamily, pip_cmds|
339
- pip_cmds.each do |pip_cmd|
340
- it "should retry on #{osfamily} systems if #{pip_cmd} has not yet been found" do
341
- allow(Puppet.features).to receive(:microsoft_windows?).and_return(osfamily == 'windows')
342
- times_called = 0
343
- expect(@provider).to receive(:pip).twice.with('freeze') do
344
- times_called += 1
345
- raise NoMethodError if times_called == 1
346
- end
347
- pip_cmds.each do |cmd|
348
- unless cmd == pip_cmd
349
- expect(@provider).to receive(:which).with(cmd).and_return(nil)
350
- end
351
- end
352
- expect(@provider).to receive(:which).with(pip_cmd).and_return("/fake/bin/#{pip_cmd}")
353
- @provider.method(:lazy_pip).call "freeze"
354
- end
355
- end
356
-
357
- it "should fail on #{osfamily} systems if #{pip_cmds.join(' and ')} are missing" do
358
- allow(Puppet.features).to receive(:microsoft_windows?).and_return(osfamily == 'windows')
359
- expect(@provider).to receive(:pip).with('freeze').and_raise(NoMethodError)
360
- pip_cmds.each do |pip_cmd|
361
- expect(@provider).to receive(:which).with(pip_cmd).and_return(nil)
362
- end
363
- expect { @provider.method(:lazy_pip).call("freeze") }.to raise_error(NoMethodError)
364
- end
365
-
366
- it "should output a useful error message on #{osfamily} systems if #{pip_cmds.join(' and ')} are missing" do
367
- allow(Puppet.features).to receive(:microsoft_windows?).and_return(osfamily == 'windows')
368
- expect(@provider).to receive(:pip).with('freeze').and_raise(NoMethodError)
369
- pip_cmds.each do |pip_cmd|
370
- expect(@provider).to receive(:which).with(pip_cmd).and_return(nil)
371
- end
372
- expect { @provider.method(:lazy_pip).call("freeze") }.
373
- to raise_error(NoMethodError, "Could not locate command #{pip_cmds.join(' and ')}.")
359
+ context 'when is defaultfor' do
360
+ let(:os) { Facter.value(:operatingsystem) }
361
+ subject do
362
+ described_class.defaultfor(operatingsystem: os)
363
+ described_class.specificity
374
364
  end
365
+ it { is_expected.to be > 100 }
375
366
  end
376
367
  end
377
368
  end