puppet 6.13.0 → 6.14.0

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 (118) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +7 -13
  3. data/Gemfile.lock +6 -6
  4. data/README.md +15 -22
  5. data/lib/puppet.rb +1 -1
  6. data/lib/puppet/application/agent.rb +9 -11
  7. data/lib/puppet/application/describe.rb +7 -5
  8. data/lib/puppet/application/device.rb +2 -2
  9. data/lib/puppet/application/filebucket.rb +14 -1
  10. data/lib/puppet/application/ssl.rb +1 -1
  11. data/lib/puppet/configurer.rb +30 -41
  12. data/lib/puppet/configurer/plugin_handler.rb +10 -1
  13. data/lib/puppet/defaults.rb +7 -1
  14. data/lib/puppet/face/plugin.rb +1 -1
  15. data/lib/puppet/functions/eyaml_lookup_key.rb +13 -8
  16. data/lib/puppet/http.rb +1 -0
  17. data/lib/puppet/http/client.rb +69 -34
  18. data/lib/puppet/http/resolver/server_list.rb +2 -2
  19. data/lib/puppet/http/resolver/settings.rb +1 -1
  20. data/lib/puppet/http/resolver/srv.rb +1 -1
  21. data/lib/puppet/http/response.rb +6 -1
  22. data/lib/puppet/http/service.rb +30 -11
  23. data/lib/puppet/http/service/ca.rb +8 -8
  24. data/lib/puppet/http/service/compiler.rb +41 -10
  25. data/lib/puppet/http/service/file_server.rb +40 -20
  26. data/lib/puppet/http/service/report.rb +12 -15
  27. data/lib/puppet/http/session.rb +39 -1
  28. data/lib/puppet/indirector/catalog/rest.rb +33 -0
  29. data/lib/puppet/indirector/facts/rest.rb +41 -0
  30. data/lib/puppet/indirector/file_content/rest.rb +30 -0
  31. data/lib/puppet/indirector/file_metadata/rest.rb +50 -0
  32. data/lib/puppet/indirector/node/rest.rb +23 -0
  33. data/lib/puppet/indirector/report/rest.rb +19 -0
  34. data/lib/puppet/indirector/rest.rb +6 -0
  35. data/lib/puppet/indirector/status/rest.rb +17 -0
  36. data/lib/puppet/loaders.rb +6 -0
  37. data/lib/puppet/network/http/base_pool.rb +1 -1
  38. data/lib/puppet/network/http/pool.rb +6 -1
  39. data/lib/puppet/provider/group/groupadd.rb +9 -4
  40. data/lib/puppet/runtime.rb +8 -1
  41. data/lib/puppet/settings.rb +2 -0
  42. data/lib/puppet/settings/http_extra_headers_setting.rb +25 -0
  43. data/lib/puppet/ssl/state_machine.rb +4 -0
  44. data/lib/puppet/test/test_helper.rb +3 -1
  45. data/lib/puppet/type/file.rb +13 -0
  46. data/lib/puppet/type/file/source.rb +47 -58
  47. data/lib/puppet/version.rb +1 -1
  48. data/locales/puppet.pot +167 -160
  49. data/man/man5/puppet.conf.5 +11 -3
  50. data/man/man8/puppet-agent.8 +6 -6
  51. data/man/man8/puppet-apply.8 +1 -1
  52. data/man/man8/puppet-catalog.8 +1 -1
  53. data/man/man8/puppet-config.8 +1 -1
  54. data/man/man8/puppet-describe.8 +1 -1
  55. data/man/man8/puppet-device.8 +2 -2
  56. data/man/man8/puppet-doc.8 +1 -1
  57. data/man/man8/puppet-epp.8 +1 -1
  58. data/man/man8/puppet-facts.8 +1 -1
  59. data/man/man8/puppet-filebucket.8 +17 -2
  60. data/man/man8/puppet-generate.8 +1 -1
  61. data/man/man8/puppet-help.8 +1 -1
  62. data/man/man8/puppet-key.8 +1 -1
  63. data/man/man8/puppet-lookup.8 +1 -1
  64. data/man/man8/puppet-man.8 +1 -1
  65. data/man/man8/puppet-module.8 +1 -1
  66. data/man/man8/puppet-node.8 +1 -1
  67. data/man/man8/puppet-parser.8 +1 -1
  68. data/man/man8/puppet-plugin.8 +1 -1
  69. data/man/man8/puppet-report.8 +1 -1
  70. data/man/man8/puppet-resource.8 +1 -1
  71. data/man/man8/puppet-script.8 +1 -1
  72. data/man/man8/puppet-ssl.8 +2 -2
  73. data/man/man8/puppet-status.8 +1 -1
  74. data/man/man8/puppet.8 +2 -2
  75. data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_md5/should_fetch_if_not_on_the_local_disk.yml +1 -67
  76. data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_md5/should_not_update_if_content_on_disk_is_up-to-date.yml +1 -69
  77. data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_md5/should_update_if_content_differs_on_disk.yml +1 -69
  78. data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_mtime/should_fetch_if_mtime_is_older_on_disk.yml +1 -67
  79. data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_mtime/should_fetch_if_no_header_specified.yml +1 -65
  80. data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_mtime/should_fetch_if_not_on_the_local_disk.yml +1 -67
  81. data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_mtime/should_not_update_if_mtime_is_newer_on_disk.yml +1 -67
  82. data/spec/integration/faces/plugin_spec.rb +3 -1
  83. data/spec/integration/http/client_spec.rb +11 -0
  84. data/spec/integration/network/http_pool_spec.rb +9 -1
  85. data/spec/unit/application/describe_spec.rb +88 -50
  86. data/spec/unit/configurer/plugin_handler_spec.rb +36 -19
  87. data/spec/unit/configurer_spec.rb +16 -14
  88. data/spec/unit/face/plugin_spec.rb +12 -10
  89. data/spec/unit/functions/lookup_spec.rb +13 -0
  90. data/spec/unit/http/client_spec.rb +172 -1
  91. data/spec/unit/http/resolver_spec.rb +14 -2
  92. data/spec/unit/http/response_spec.rb +69 -0
  93. data/spec/unit/http/service/ca_spec.rb +28 -9
  94. data/spec/unit/http/service/compiler_spec.rb +151 -24
  95. data/spec/unit/http/service/file_server_spec.rb +65 -8
  96. data/spec/unit/http/service/report_spec.rb +17 -8
  97. data/spec/unit/http/service_spec.rb +92 -3
  98. data/spec/unit/http/session_spec.rb +104 -1
  99. data/spec/unit/indirector/catalog/rest_spec.rb +59 -2
  100. data/spec/unit/indirector/facts/rest_spec.rb +79 -24
  101. data/spec/unit/indirector/file_content/rest_spec.rb +53 -2
  102. data/spec/unit/indirector/file_metadata/rest_spec.rb +109 -2
  103. data/spec/unit/indirector/node/rest_spec.rb +57 -2
  104. data/spec/unit/indirector/report/rest_spec.rb +58 -51
  105. data/spec/unit/indirector/resource/ral_spec.rb +7 -8
  106. data/spec/unit/indirector/status/rest_spec.rb +43 -2
  107. data/spec/unit/network/http/pool_spec.rb +57 -11
  108. data/spec/unit/provider/group/groupadd_spec.rb +22 -8
  109. data/spec/unit/settings/autosign_setting_spec.rb +1 -1
  110. data/spec/unit/settings/http_extra_headers_spec.rb +64 -0
  111. data/spec/unit/ssl/state_machine_spec.rb +10 -0
  112. data/spec/unit/transaction_spec.rb +0 -2
  113. data/spec/unit/type/file/ensure_spec.rb +1 -2
  114. data/spec/unit/type/file/source_spec.rb +86 -35
  115. data/spec/unit/util/at_fork_spec.rb +1 -0
  116. data/spec/unit/util/pidlock_spec.rb +36 -24
  117. metadata +7 -3
  118. data/COMMITTERS.md +0 -244
@@ -1,5 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'puppet/type/user'
3
2
  require 'puppet/indirector/resource/ral'
4
3
 
5
4
  describe "Puppet::Resource::Ral" do
@@ -18,7 +17,7 @@ describe "Puppet::Resource::Ral" do
18
17
  wrong_instance = double("wrong user", :name => "bob")
19
18
  my_instance = double("my user", :name => "root", :to_resource => my_resource)
20
19
 
21
- expect(Puppet::Type::User).to receive(:instances).and_return([ wrong_instance, my_instance, wrong_instance ])
20
+ expect(Puppet::Type.type(:user)).to receive(:instances).and_return([ wrong_instance, my_instance, wrong_instance ])
22
21
  expect(Puppet::Resource::Ral.new.find(@request)).to eq(my_resource)
23
22
  end
24
23
 
@@ -32,8 +31,8 @@ describe "Puppet::Resource::Ral" do
32
31
  root = double("Root User")
33
32
  root_resource = double("Root Resource")
34
33
 
35
- expect(Puppet::Type::User).to receive(:instances).and_return([ wrong_instance, wrong_instance ])
36
- expect(Puppet::Type::User).to receive(:new).with(hash_including(name: "root")).and_return(root)
34
+ expect(Puppet::Type.type(:user)).to receive(:instances).and_return([ wrong_instance, wrong_instance ])
35
+ expect(Puppet::Type.type(:user)).to receive(:new).with(hash_including(name: "root")).and_return(root)
37
36
  expect(root).to receive(:to_resource).and_return(root_resource)
38
37
 
39
38
  result = Puppet::Resource::Ral.new.find(@request)
@@ -51,7 +50,7 @@ describe "Puppet::Resource::Ral" do
51
50
  my_resource = double("my user resource", :title => "my user resource")
52
51
  my_instance = double("my user", :name => "root", :to_resource => my_resource)
53
52
 
54
- expect(Puppet::Type::User).to receive(:instances).and_return([ my_instance ])
53
+ expect(Puppet::Type.type(:user)).to receive(:instances).and_return([ my_instance ])
55
54
  expect(Puppet::Resource::Ral.new.search(@request)).to eq([my_resource])
56
55
  end
57
56
 
@@ -69,7 +68,7 @@ describe "Puppet::Resource::Ral" do
69
68
 
70
69
  @request = double('request', :key => "user/root", :options => {})
71
70
 
72
- expect(Puppet::Type::User).to receive(:instances).and_return([ my_instance, wrong_instance ])
71
+ expect(Puppet::Type.type(:user)).to receive(:instances).and_return([ my_instance, wrong_instance ])
73
72
  expect(Puppet::Resource::Ral.new.search(@request)).to eq([my_resource])
74
73
  end
75
74
 
@@ -87,7 +86,7 @@ describe "Puppet::Resource::Ral" do
87
86
 
88
87
  @request = double('request', :key => "user/", :options => {:name => "bob"})
89
88
 
90
- expect(Puppet::Type::User).to receive(:instances).and_return([ my_instance, wrong_instance ])
89
+ expect(Puppet::Type.type(:user)).to receive(:instances).and_return([ my_instance, wrong_instance ])
91
90
  expect(Puppet::Resource::Ral.new.search(@request)).to eq([my_resource])
92
91
  end
93
92
 
@@ -105,7 +104,7 @@ describe "Puppet::Resource::Ral" do
105
104
 
106
105
  @request = double('request', :key => "user/", :options => {})
107
106
 
108
- expect(Puppet::Type::User).to receive(:instances).and_return([ b_instance, a_instance ])
107
+ expect(Puppet::Type.type(:user)).to receive(:instances).and_return([ b_instance, a_instance ])
109
108
  expect(Puppet::Resource::Ral.new.search(@request)).to eq([a_resource, b_resource])
110
109
  end
111
110
  end
@@ -3,7 +3,48 @@ require 'spec_helper'
3
3
  require 'puppet/indirector/status/rest'
4
4
 
5
5
  describe Puppet::Indirector::Status::Rest do
6
- it "should be a subclass of Puppet::Indirector::REST" do
7
- expect(Puppet::Indirector::Status::Rest.superclass).to equal(Puppet::Indirector::REST)
6
+ let(:certname) { 'ziggy' }
7
+ let(:uri) { %r{/puppet/v3/status/ziggy} }
8
+ let(:formatter) { Puppet::Network::FormatHandler.format(:json) }
9
+
10
+ before :each do
11
+ Puppet[:server] = 'compiler.example.com'
12
+ Puppet[:masterport] = 8140
13
+
14
+ described_class.indirection.terminus_class = :rest
15
+ end
16
+
17
+ def status_response(node)
18
+ { body: formatter.render(node), headers: {'Content-Type' => formatter.mime } }
19
+ end
20
+
21
+ it 'finds server status' do
22
+ node = Puppet::Status.new(certname)
23
+
24
+ stub_request(:get, uri).to_return(**status_response(node))
25
+
26
+ expect(described_class.indirection.find(certname)).to be_a(Puppet::Status)
27
+ end
28
+
29
+ it 'returns nil if the node does not exist' do
30
+ stub_request(:get, uri).to_return(status: 404, headers: { 'Content-Type' => 'application/json' }, body: "{}")
31
+
32
+ expect(described_class.indirection.find(certname)).to be_nil
33
+ end
34
+
35
+ it 'raises if fail_on_404 is specified' do
36
+ stub_request(:get, uri).to_return(status: 404, headers: { 'Content-Type' => 'application/json' }, body: "{}")
37
+
38
+ expect{
39
+ described_class.indirection.find(certname, fail_on_404: true)
40
+ }.to raise_error(Puppet::Error, %r{Find /puppet/v3/status/ziggy resulted in 404 with the message: {}})
41
+ end
42
+
43
+ it 'raises Net::HTTPError on 500' do
44
+ stub_request(:get, uri).to_return(status: 500)
45
+
46
+ expect{
47
+ described_class.indirection.find(certname)
48
+ }.to raise_error(Net::HTTPError, %r{Error 500 on SERVER: })
8
49
  end
9
50
  end
@@ -37,6 +37,14 @@ describe Puppet::Network::HTTP::Pool do
37
37
  pool
38
38
  end
39
39
 
40
+ def create_pool_with_http_connections(site, *connections)
41
+ pool = Puppet::Network::HTTP::Pool.new
42
+ connections.each do |conn|
43
+ pool.release(site, nil, conn)
44
+ end
45
+ pool
46
+ end
47
+
40
48
  def create_pool_with_expired_connections(site, *connections)
41
49
  # setting keepalive timeout to -1 ensures any newly added
42
50
  # connections have already expired
@@ -51,6 +59,10 @@ describe Puppet::Network::HTTP::Pool do
51
59
  double(site.addr, :started? => false, :start => nil, :finish => nil, :use_ssl? => true, :verify_mode => OpenSSL::SSL::VERIFY_PEER)
52
60
  end
53
61
 
62
+ def create_http_connection(site)
63
+ double(site.addr, :started? => false, :start => nil, :finish => nil, :use_ssl? => false)
64
+ end
65
+
54
66
  context 'when yielding a connection' do
55
67
  it 'yields a connection' do
56
68
  conn = create_connection(site)
@@ -174,7 +186,7 @@ describe Puppet::Network::HTTP::Pool do
174
186
  pool.with_connection(site, verifier) {|c| }
175
187
  end
176
188
 
177
- it "doesn't add a closed connection back to the pool" do
189
+ it "doesn't add a closed connection back to the pool" do
178
190
  http = Net::HTTP.new(site.addr)
179
191
  http.use_ssl = true
180
192
  http.verify_mode = OpenSSL::SSL::VERIFY_PEER
@@ -184,7 +196,7 @@ describe Puppet::Network::HTTP::Pool do
184
196
 
185
197
  pool.with_connection(site, verifier) {|c| c.finish}
186
198
 
187
- expect(pool.pool[site]).to be_empty
199
+ expect(pool.pool[site]).to be_nil
188
200
  end
189
201
  end
190
202
  end
@@ -194,7 +206,6 @@ describe Puppet::Network::HTTP::Pool do
194
206
  conn = create_connection(site)
195
207
  pool = create_pool
196
208
  expect(pool.factory).to receive(:create_connection).with(site).and_return(conn)
197
- expect(pool).to receive(:setsockopts)
198
209
 
199
210
  expect(pool.borrow(site, verifier)).to eq(conn)
200
211
  end
@@ -214,15 +225,37 @@ describe Puppet::Network::HTTP::Pool do
214
225
 
215
226
  conn = create_connection(site)
216
227
  expect(pool.factory).to receive(:create_connection).with(site).and_return(conn)
217
- expect(pool).to receive(:setsockopts)
218
228
 
219
229
  expect(pool.borrow(site, verifier)).to eq(conn)
220
230
  end
221
231
 
232
+ it 'returns a new HTTP connection if the cached connection is HTTPS' do
233
+ https_site = Puppet::Network::HTTP::Site.new('https', 'www.example.com', 443)
234
+ old_conn = create_connection(https_site)
235
+ pool = create_pool_with_connections(https_site, old_conn)
236
+
237
+ http_site = Puppet::Network::HTTP::Site.new('http', 'www.example.com', 443)
238
+ new_conn = create_http_connection(http_site)
239
+ allow(pool.factory).to receive(:create_connection).with(http_site).and_return(new_conn)
240
+
241
+ expect(pool.borrow(http_site, nil)).to eq(new_conn)
242
+ end
243
+
244
+ it 'returns a new HTTPS connection if the cached connection is HTTP' do
245
+ http_site = Puppet::Network::HTTP::Site.new('http', 'www.example.com', 443)
246
+ old_conn = create_http_connection(http_site)
247
+ pool = create_pool_with_http_connections(http_site, old_conn)
248
+
249
+ https_site = Puppet::Network::HTTP::Site.new('https', 'www.example.com', 443)
250
+ new_conn = create_connection(https_site)
251
+ allow(pool.factory).to receive(:create_connection).with(https_site).and_return(new_conn)
252
+
253
+ expect(pool.borrow(https_site, verifier)).to eq(new_conn)
254
+ end
255
+
222
256
  it 'returns a new connection if the ssl contexts are different' do
223
257
  old_conn = create_connection(site)
224
258
  pool = create_pool_with_connections(site, old_conn)
225
- allow(pool).to receive(:setsockopts)
226
259
 
227
260
  new_conn = create_connection(site)
228
261
  allow(pool.factory).to receive(:create_connection).with(site).and_return(new_conn)
@@ -237,7 +270,6 @@ describe Puppet::Network::HTTP::Pool do
237
270
  it 'returns a cached connection if the ssl contexts are the same' do
238
271
  old_conn = create_connection(site)
239
272
  pool = create_pool_with_connections(site, old_conn)
240
- allow(pool).to receive(:setsockopts)
241
273
 
242
274
  expect(pool.factory).not_to receive(:create_connection)
243
275
 
@@ -246,13 +278,21 @@ describe Puppet::Network::HTTP::Pool do
246
278
  expect(pool.borrow(site, new_verifier)).to equal(old_conn)
247
279
  end
248
280
 
281
+ it 'returns a cached connection if both connections are http' do
282
+ http_site = Puppet::Network::HTTP::Site.new('http', 'www.example.com', 80)
283
+ old_conn = create_http_connection(http_site)
284
+ pool = create_pool_with_http_connections(http_site, old_conn)
285
+
286
+ # 'equal' tests that it's the same object
287
+ expect(pool.borrow(http_site, nil)).to equal(old_conn)
288
+ end
289
+
249
290
  it 'returns started connections' do
250
291
  conn = create_connection(site)
251
292
  expect(conn).to receive(:start)
252
293
 
253
294
  pool = create_pool
254
295
  expect(pool.factory).to receive(:create_connection).with(site).and_return(conn)
255
- expect(pool).to receive(:setsockopts)
256
296
 
257
297
  expect(pool.borrow(site, verifier)).to eq(conn)
258
298
  end
@@ -279,8 +319,7 @@ describe Puppet::Network::HTTP::Pool do
279
319
  expect(conn).to receive(:finish)
280
320
 
281
321
  pool = create_pool_with_expired_connections(site, conn)
282
- expect(pool.factory).to receive(:create_connection).and_return(double('conn', :start => nil))
283
- expect(pool).to receive(:setsockopts)
322
+ expect(pool.factory).to receive(:create_connection).and_return(double('conn', :start => nil, :use_ssl? => true))
284
323
 
285
324
  pool.borrow(site, verifier)
286
325
  end
@@ -293,11 +332,18 @@ describe Puppet::Network::HTTP::Pool do
293
332
  expect(conn).to receive(:finish).and_raise(IOError, 'read timeout')
294
333
 
295
334
  pool = create_pool_with_expired_connections(site, conn)
296
- expect(pool.factory).to receive(:create_connection).and_return(double('open_conn', :start => nil))
297
- expect(pool).to receive(:setsockopts)
335
+ expect(pool.factory).to receive(:create_connection).and_return(double('open_conn', :start => nil, :use_ssl? => true))
298
336
 
299
337
  pool.borrow(site, verifier)
300
338
  end
339
+
340
+ it 'deletes the session when the last connection is borrowed' do
341
+ conn = create_connection(site)
342
+ pool = create_pool_with_connections(site, conn)
343
+ pool.borrow(site, verifier)
344
+
345
+ expect(pool.pool[site]).to be_nil
346
+ end
301
347
  end
302
348
 
303
349
  context 'when releasing a connection' do
@@ -163,6 +163,28 @@ describe Puppet::Type.type(:group).provider(:groupadd) do
163
163
  provider.members = new_members
164
164
  end
165
165
  end
166
+
167
+ it "should validate members" do
168
+ expect(Etc).to receive(:getpwnam).with('user3').and_return(true)
169
+ provider.modifycmd(:members, ['user3'])
170
+ end
171
+
172
+ it "should validate members list " do
173
+ expect(Etc).to receive(:getpwnam).with('user3').and_return(true)
174
+ expect(Etc).to receive(:getpwnam).with('user4').and_return(true)
175
+ provider.modifycmd(:members, ['user3', 'user4'])
176
+ end
177
+
178
+ it "should validate members list separated by commas" do
179
+ expect(Etc).to receive(:getpwnam).with('user3').and_return(true)
180
+ expect(Etc).to receive(:getpwnam).with('user4').and_return(true)
181
+ provider.modifycmd(:members, ['user3, user4'])
182
+ end
183
+
184
+ it "should raise is validation fails" do
185
+ expect(Etc).to receive(:getpwnam).with('user3').and_throw(ArgumentError)
186
+ expect { provider.modifycmd(:members, ['user3']) }.to raise_error(ArgumentError)
187
+ end
166
188
  end
167
189
  end
168
190
  end
@@ -235,14 +257,6 @@ describe Puppet::Type.type(:group).provider(:groupadd) do
235
257
  end
236
258
 
237
259
  describe "group type :members property helpers" do
238
- describe "#member_valid?" do
239
- it "should return true if a member exists" do
240
- passwd = Struct::Passwd.new('existinguser', nil, 1100)
241
- allow(Etc).to receive(:getpwnam).with('existinguser').and_return(passwd)
242
- expect(provider.member_valid?('existinguser')).to eq(true)
243
- end
244
- end
245
-
246
260
  describe "#members_to_s" do
247
261
  it "should return an empty string on non-array input" do
248
262
  [Object.new, {}, 1, :symbol, ''].each do |input|
@@ -2,7 +2,6 @@ require 'spec_helper'
2
2
 
3
3
  require 'puppet/settings'
4
4
  require 'puppet/settings/autosign_setting'
5
- require 'puppet/type/file'
6
5
 
7
6
  describe Puppet::Settings::AutosignSetting do
8
7
  let(:settings) do
@@ -75,6 +74,7 @@ describe Puppet::Settings::AutosignSetting do
75
74
  it "converts the file path to a file resource", :if => !Puppet::Util::Platform.windows? do
76
75
  path = File.expand_path('/path/to/autosign.conf')
77
76
  allow(settings).to receive(:value).with('autosign', nil, false).and_return(path)
77
+ allow(Puppet::FileSystem).to receive(:exist?).and_call_original
78
78
  allow(Puppet::FileSystem).to receive(:exist?).with(path).and_return(true)
79
79
  expect(Puppet.features).to receive(:root?).and_return(true)
80
80
 
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ require 'puppet/settings'
4
+ require 'puppet/settings/http_extra_headers_setting'
5
+
6
+ describe Puppet::Settings::HttpExtraHeadersSetting do
7
+ subject { described_class.new(:settings => double('settings'), :desc => "test") }
8
+
9
+ it "is of type :http_extra_headers" do
10
+ expect(subject.type).to eq :http_extra_headers
11
+ end
12
+
13
+ describe "munging the value" do
14
+ let(:final_value) { [['header1', 'foo'], ['header2', 'bar']] }
15
+
16
+ describe "when given a string" do
17
+ it "splits multiple values into an array" do
18
+ expect(subject.munge("header1:foo,header2:bar")).to match_array(final_value)
19
+ end
20
+
21
+ it "strips whitespace between elements" do
22
+ expect(subject.munge("header1:foo , header2:bar")).to match_array(final_value)
23
+ end
24
+
25
+ it "creates an array when one item is given" do
26
+ expect(subject.munge("header1:foo")).to match_array([['header1', 'foo']])
27
+ end
28
+ end
29
+
30
+ describe "when given an array of strings" do
31
+ it "returns an array of arrays" do
32
+ expect(subject.munge(['header1:foo', 'header2:bar'])).to match_array(final_value)
33
+ end
34
+ end
35
+
36
+ describe "when given an array of arrays" do
37
+ it "returns an array of arrays" do
38
+ expect(subject.munge([['header1', 'foo'], ['header2', 'bar']])).to match_array(final_value)
39
+ end
40
+ end
41
+
42
+ describe "when given a hash" do
43
+ it "returns the hash" do
44
+ expect(subject.munge({'header1' => 'foo', 'header2' => 'bar'})).to match_array(final_value)
45
+ end
46
+ end
47
+
48
+ describe 'raises an error when' do
49
+
50
+ # Ruby 2.3 reports the class of these objects as Fixnum, whereas later ruby versions report them as Integer
51
+ it 'is given an unexpected object type' do
52
+ expect {
53
+ subject.munge(65)
54
+ }.to raise_error(ArgumentError, /^Expected an Array, String, or Hash, got a (Integer|Fixnum)/)
55
+ end
56
+
57
+ it 'is given an array of unexpected object types' do
58
+ expect {
59
+ subject.munge([65, 82])
60
+ }.to raise_error(ArgumentError, /^Expected an Array or String, got a (Integer|Fixnum)/)
61
+ end
62
+ end
63
+ end
64
+ end
@@ -877,6 +877,16 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
877
877
  }.to exit_with(1)
878
878
  }.to output(/Couldn't fetch certificate from CA server; you might still need to sign this agent's certificate \(.*\). Exiting now because the maxwaitforcert timeout has been exceeded./).to_stdout
879
879
  end
880
+
881
+ it 'closes the pool before sleeping' do
882
+ machine = described_class.new(waitforcert: 15)
883
+
884
+ state = Puppet::SSL::StateMachine::Wait.new(machine)
885
+ expect(Puppet.runtime['http'].pool).to receive(:close).and_call_original
886
+ expect(Kernel).to receive(:sleep).with(15).ordered
887
+
888
+ state.next_state
889
+ end
880
890
  end
881
891
  end
882
892
  end
@@ -3,8 +3,6 @@ require 'matchers/include_in_order'
3
3
  require 'puppet_spec/compiler'
4
4
 
5
5
  require 'puppet/transaction'
6
- require 'puppet/type/exec'
7
- require 'puppet/type/notify'
8
6
  require 'fileutils'
9
7
 
10
8
  describe Puppet::Transaction do
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
- require 'puppet/type/file/ensure'
3
2
 
4
- describe Puppet::Type::File::Ensure do
3
+ describe Puppet::Type.type(:file).attrclass(:ensure) do
5
4
  include PuppetSpec::Files
6
5
 
7
6
  let(:path) { tmpfile('file_ensure') }
@@ -533,20 +533,54 @@ describe Puppet::Type.type(:file).attrclass(:source), :uses_checksums => true do
533
533
  describe "when writing" do
534
534
  describe "as puppet apply" do
535
535
  let(:source_content) { "source file content\r\n"*10 }
536
+ let(:modulepath) { File.join(Puppet[:environmentpath], 'testing', 'modules') }
537
+ let(:env) { Puppet::Node::Environment.create(:testing, [modulepath]) }
538
+ let(:catalog) { Puppet::Resource::Catalog.new(:test, env) }
539
+
536
540
  before do
537
541
  Puppet[:default_file_terminus] = "file_server"
538
- resource[:source] = file_containing('apply', source_content)
539
542
  end
540
543
 
541
544
  it "should copy content from the source to the file" do
545
+ resource = Puppet::Type.type(:file).new(path: filename, catalog: catalog, source: file_containing('apply', source_content))
542
546
  source = resource.parameter(:source)
543
547
  resource.write(source)
544
548
 
545
549
  expect(Puppet::FileSystem.binread(filename)).to eq(source_content)
546
550
  end
547
551
 
552
+ it 'should use the in-process fileserver if source starts with puppet:///' do
553
+ path = File.join(modulepath, 'mymodule', 'files', 'path')
554
+ Puppet::FileSystem.dir_mkpath(path)
555
+ File.open(path, 'wb') { |f| f.write(source_content) }
556
+ resource = Puppet::Type.type(:file).new(path: filename, catalog: catalog, source: 'puppet:///modules/mymodule/path')
557
+
558
+ source = resource.parameter(:source)
559
+ resource.write(source)
560
+
561
+ expect(Puppet::FileSystem.binread(filename)).to eq(source_content)
562
+ end
563
+
564
+ it 'follows symlinks when retrieving content from the in-process fileserver' do
565
+ # create a 'link' that points to 'target' in the 'mymodule' module
566
+ link = File.join(modulepath, 'mymodule', 'files', 'link')
567
+ target = File.join(modulepath, 'mymodule', 'files', 'target')
568
+ Puppet::FileSystem.dir_mkpath(target)
569
+ File.open(target, 'wb') { |f| f.write(source_content) }
570
+ Puppet::FileSystem.symlink(target, link)
571
+ resource = Puppet::Type.type(:file).new(path: filename, catalog: catalog, source: 'puppet:///modules/mymodule/link')
572
+
573
+ source = resource.parameter(:source)
574
+ resource.write(source)
575
+
576
+ # 'filename' should be a file containing the contents of the followed link
577
+ expect(Puppet::FileSystem.binread(filename)).to eq(source_content)
578
+ end
579
+
548
580
  with_digest_algorithms do
549
581
  it "should return the checksum computed" do
582
+ resource = Puppet::Type.type(:file).new(path: filename, catalog: catalog, source: file_containing('apply', source_content))
583
+
550
584
  File.open(filename, 'wb') do |file|
551
585
  source = resource.parameter(:source)
552
586
  resource[:checksum] = digest_algorithm
@@ -583,53 +617,73 @@ describe Puppet::Type.type(:file).attrclass(:source), :uses_checksums => true do
583
617
 
584
618
  describe 'from remote source' do
585
619
  let(:source_content) { "source file content\n"*10 }
586
- let(:source) { resource.newattr(:source) }
587
- let(:response) { double('response', :[] => nil, :body => nil, :message => nil) }
588
- let(:conn) { double('connection') }
620
+ let(:source) {
621
+ attr = resource.newattr(:source)
622
+ attr.metadata = metadata
623
+ attr
624
+ }
625
+ let(:metadata) {
626
+ Puppet::FileServing::Metadata.new(
627
+ '/modules/:module/foo',
628
+ {
629
+ 'type' => 'file',
630
+ 'source' => 'puppet:///modules/:module/foo'
631
+ }
632
+ )
633
+ }
589
634
 
590
635
  before do
591
636
  resource[:backup] = false
592
-
593
- expectation = receive(:read_body)
594
- source_content.lines.each { |line| expectation = expectation.and_yield(line) }
595
- allow(response).to expectation
596
- allow(conn).to receive(:request_get).and_yield(response)
597
637
  end
598
638
 
599
639
  it 'should use an explicit fileserver if source starts with puppet://' do
600
- allow(response).to receive(:code).and_return('200')
601
- allow(source).to receive(:metadata).and_return(double('metadata', :source => 'puppet://somehostname/test/foo', :ftype => 'file', :content_uri => nil))
602
- expect(Puppet::Network::HttpPool).to receive(:connection).with('somehostname', 8140, anything).and_return(conn)
640
+ metadata.source = "puppet://somehostname:8140/modules/:module/foo"
641
+
642
+ stub_request(:get, %r{https://somehostname:8140/puppet/v3/file_content/modules/:module/foo})
643
+ .to_return(status: 200, body: metadata.to_json, headers: { 'Content-Type' => 'application/json' })
603
644
 
604
645
  resource.write(source)
605
646
  end
606
647
 
607
648
  it 'should use the default fileserver if source starts with puppet:///' do
608
- allow(response).to receive(:code).and_return('200')
609
- allow(source).to receive(:metadata).and_return(double('metadata', :source => 'puppet:///test/foo', :ftype => 'file', :content_uri => nil))
610
- expect(Puppet::Network::HttpPool).to receive(:connection).with(Puppet[:server], 8140, anything).and_return(conn)
649
+ stub_request(:get, %r{https://#{Puppet[:server]}:8140/puppet/v3/file_content/modules/:module/foo})
650
+ .to_return(status: 200, body: metadata.to_json, headers: { 'Content-Type' => 'application/json' })
611
651
 
612
652
  resource.write(source)
613
653
  end
614
654
 
615
655
  it 'should percent encode reserved characters' do
616
- allow(response).to receive(:code).and_return('200')
617
- allow(Puppet::Network::HttpPool).to receive(:connection).and_return(conn)
618
- allow(source).to receive(:metadata).and_return(double('metadata', :source => 'puppet:///test/foo bar', :ftype => 'file', :content_uri => nil))
656
+ metadata.source = 'puppet:///modules/:module/foo bar'
619
657
 
620
- expect(conn).to receive(:request_get).with("#{Puppet::Network::HTTP::MASTER_URL_PREFIX}/v3/file_content/test/foo%20bar?environment=myenv&", anything).and_yield(response)
658
+ stub_request(:get, %r{/puppet/v3/file_content/modules/:module/foo%20bar})
659
+ .to_return(status: 200, body: metadata.to_json, headers: { 'Content-Type' => 'application/json' })
621
660
 
622
661
  resource.write(source)
623
662
  end
624
663
 
625
664
  it 'should request binary content' do
626
- allow(response).to receive(:code).and_return('200')
627
- allow(Puppet::Network::HttpPool).to receive(:connection).and_return(conn)
628
- allow(source).to receive(:metadata).and_return(double('metadata', :source => 'puppet:///test/foo bar', :ftype => 'file', :content_uri => nil))
665
+ stub_request(:get, %r{/puppet/v3/file_content/modules/:module/foo}) do |request|
666
+ expect(request.headers).to include({'Accept' => 'application/octet-stream'})
667
+ end.to_return(status: 200, body: '', headers: { 'Content-Type' => 'application/octet-stream' })
629
668
 
630
- expect(conn).to receive(:request_get) do |_, options|
631
- expect(options).to include('Accept' => 'application/octet-stream')
632
- end.and_yield(response)
669
+ resource.write(source)
670
+ end
671
+
672
+ it "should request file content from the catalog's environment" do
673
+ Puppet[:environment] = 'doesntexist'
674
+
675
+ stub_request(:get, %r{/puppet/v3/file_content})
676
+ .with(query: hash_including("environment" => "myenv"))
677
+ .to_return(status: 200, body: '', headers: { 'Content-Type' => 'application/octet-stream' })
678
+
679
+ resource.write(source)
680
+ end
681
+
682
+ it 'should request static file content' do
683
+ metadata.content_uri = "puppet://#{Puppet[:server]}:8140/path/to/file"
684
+
685
+ stub_request(:get, %r{/puppet/v3/static_file_content/path/to/file})
686
+ .to_return(status: 200, body: '', headers: { 'Content-Type' => 'application/octet-stream' })
633
687
 
634
688
  resource.write(source)
635
689
  end
@@ -639,26 +693,23 @@ describe Puppet::Type.type(:file).attrclass(:source), :uses_checksums => true do
639
693
  File.open(filename, 'w') {|f| f.write "initial file content"}
640
694
  end
641
695
 
642
- before(:each) do
643
- allow(Puppet::Network::HttpPool).to receive(:connection).and_return(conn)
644
- allow(source).to receive(:metadata).and_return(double('metadata', :source => 'puppet:///test/foo', :ftype => 'file', :content_uri => nil))
645
- end
646
-
647
696
  it 'should not write anything if source is not found' do
648
- allow(response).to receive(:code).and_return('404')
697
+ stub_request(:get, %r{/puppet/v3/file_content/modules/:module/foo}).to_return(status: 404)
649
698
 
650
- expect { resource.write(source) }.to raise_error(Net::HTTPError, /404/)
699
+ expect { resource.write(source) }.to raise_error(Net::HTTPError, /Error 404 on SERVER:/)
651
700
  expect(File.read(filename)).to eq('initial file content')
652
701
  end
653
702
 
654
703
  it 'should raise an HTTP error in case of server error' do
655
- allow(response).to receive(:code).and_return('500')
704
+ stub_request(:get, %r{/puppet/v3/file_content/modules/:module/foo}).to_return(status: 500)
656
705
 
657
- expect { resource.write(source) }.to raise_error(Net::HTTPError, /500/)
706
+ expect { resource.write(source) }.to raise_error(Net::HTTPError, /Error 500 on SERVER/)
658
707
  end
659
708
 
660
709
  context 'and the request was successful' do
661
- before(:each) { allow(response).to receive(:code).and_return('200') }
710
+ before do
711
+ stub_request(:get, %r{/puppet/v3/file_content/modules/:module/foo}).to_return(status: 200, body: source_content)
712
+ end
662
713
 
663
714
  it 'should write the contents to the file' do
664
715
  resource.write(source)