puppet 6.23.0-x64-mingw32 → 6.24.0-x64-mingw32

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 (119) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +5 -5
  3. data/Gemfile.lock +8 -8
  4. data/README.md +4 -4
  5. data/ext/project_data.yaml +1 -0
  6. data/lib/puppet.rb +3 -3
  7. data/lib/puppet/application/filebucket.rb +1 -0
  8. data/lib/puppet/application/resource.rb +15 -2
  9. data/lib/puppet/application/ssl.rb +1 -0
  10. data/lib/puppet/environments.rb +10 -0
  11. data/lib/puppet/face/help/action.erb +1 -0
  12. data/lib/puppet/face/help/face.erb +1 -0
  13. data/lib/puppet/face/node/clean.rb +11 -0
  14. data/lib/puppet/file_system/file_impl.rb +1 -1
  15. data/lib/puppet/file_system/windows.rb +2 -2
  16. data/lib/puppet/forge.rb +3 -3
  17. data/lib/puppet/functions/empty.rb +8 -0
  18. data/lib/puppet/functions/strftime.rb +1 -0
  19. data/lib/puppet/functions/unwrap.rb +17 -2
  20. data/lib/puppet/indirector/resource/ral.rb +6 -1
  21. data/lib/puppet/interface/documentation.rb +1 -0
  22. data/lib/puppet/module_tool/applications/installer.rb +4 -0
  23. data/lib/puppet/module_tool/errors/shared.rb +17 -0
  24. data/lib/puppet/pops/types/type_mismatch_describer.rb +1 -1
  25. data/lib/puppet/provider/exec/posix.rb +16 -4
  26. data/lib/puppet/provider/package/pip.rb +15 -3
  27. data/lib/puppet/provider/parsedfile.rb +3 -0
  28. data/lib/puppet/settings.rb +30 -7
  29. data/lib/puppet/type/exec.rb +16 -3
  30. data/lib/puppet/type/file/mode.rb +6 -0
  31. data/lib/puppet/type/tidy.rb +1 -1
  32. data/lib/puppet/util/symbolic_file_mode.rb +29 -17
  33. data/lib/puppet/util/windows/sid.rb +3 -1
  34. data/lib/puppet/version.rb +1 -1
  35. data/locales/puppet.pot +154 -134
  36. data/man/man5/puppet.conf.5 +2 -2
  37. data/man/man8/puppet-agent.8 +1 -1
  38. data/man/man8/puppet-apply.8 +1 -1
  39. data/man/man8/puppet-catalog.8 +9 -9
  40. data/man/man8/puppet-config.8 +1 -1
  41. data/man/man8/puppet-describe.8 +1 -1
  42. data/man/man8/puppet-device.8 +1 -1
  43. data/man/man8/puppet-doc.8 +1 -1
  44. data/man/man8/puppet-epp.8 +1 -1
  45. data/man/man8/puppet-facts.8 +8 -8
  46. data/man/man8/puppet-filebucket.8 +1 -1
  47. data/man/man8/puppet-generate.8 +1 -1
  48. data/man/man8/puppet-help.8 +1 -1
  49. data/man/man8/puppet-key.8 +7 -7
  50. data/man/man8/puppet-lookup.8 +1 -1
  51. data/man/man8/puppet-man.8 +1 -1
  52. data/man/man8/puppet-module.8 +1 -1
  53. data/man/man8/puppet-node.8 +5 -5
  54. data/man/man8/puppet-parser.8 +1 -1
  55. data/man/man8/puppet-plugin.8 +1 -1
  56. data/man/man8/puppet-report.8 +5 -5
  57. data/man/man8/puppet-resource.8 +1 -1
  58. data/man/man8/puppet-script.8 +1 -1
  59. data/man/man8/puppet-ssl.8 +1 -1
  60. data/man/man8/puppet-status.8 +4 -4
  61. data/man/man8/puppet.8 +2 -2
  62. data/spec/fixtures/ssl/127.0.0.1-key.pem +106 -106
  63. data/spec/fixtures/ssl/127.0.0.1.pem +48 -48
  64. data/spec/fixtures/ssl/bad-basic-constraints.pem +54 -54
  65. data/spec/fixtures/ssl/bad-int-basic-constraints.pem +51 -51
  66. data/spec/fixtures/ssl/ca.pem +52 -52
  67. data/spec/fixtures/ssl/crl.pem +25 -25
  68. data/spec/fixtures/ssl/ec-key.pem +11 -11
  69. data/spec/fixtures/ssl/ec.pem +32 -32
  70. data/spec/fixtures/ssl/encrypted-ec-key.pem +12 -12
  71. data/spec/fixtures/ssl/encrypted-key.pem +107 -107
  72. data/spec/fixtures/ssl/intermediate-agent-crl.pem +25 -25
  73. data/spec/fixtures/ssl/intermediate-agent.pem +54 -54
  74. data/spec/fixtures/ssl/intermediate-crl.pem +28 -28
  75. data/spec/fixtures/ssl/intermediate.pem +51 -51
  76. data/spec/fixtures/ssl/oid-key.pem +117 -0
  77. data/spec/fixtures/ssl/oid.pem +69 -0
  78. data/spec/fixtures/ssl/pluto-key.pem +106 -106
  79. data/spec/fixtures/ssl/pluto.pem +50 -50
  80. data/spec/fixtures/ssl/request-key.pem +106 -106
  81. data/spec/fixtures/ssl/request.pem +45 -45
  82. data/spec/fixtures/ssl/revoked-key.pem +106 -106
  83. data/spec/fixtures/ssl/revoked.pem +49 -49
  84. data/spec/fixtures/ssl/signed-key.pem +106 -106
  85. data/spec/fixtures/ssl/signed.pem +47 -47
  86. data/spec/fixtures/ssl/tampered-cert.pem +49 -49
  87. data/spec/fixtures/ssl/tampered-csr.pem +45 -45
  88. data/spec/fixtures/ssl/trusted_oid_mapping.yaml +5 -0
  89. data/spec/fixtures/ssl/unknown-127.0.0.1-key.pem +106 -106
  90. data/spec/fixtures/ssl/unknown-127.0.0.1.pem +48 -48
  91. data/spec/fixtures/ssl/unknown-ca-key.pem +106 -106
  92. data/spec/fixtures/ssl/unknown-ca.pem +52 -52
  93. data/spec/integration/application/filebucket_spec.rb +11 -0
  94. data/spec/integration/application/module_spec.rb +21 -0
  95. data/spec/integration/application/resource_spec.rb +35 -1
  96. data/spec/integration/application/ssl_spec.rb +20 -0
  97. data/spec/integration/environments/settings_interpolation_spec.rb +0 -4
  98. data/spec/integration/indirector/facts/facter_spec.rb +90 -36
  99. data/spec/integration/type/exec_spec.rb +70 -45
  100. data/spec/lib/puppet/test_ca.rb +5 -0
  101. data/spec/lib/puppet_spec/settings.rb +1 -0
  102. data/spec/unit/environments_spec.rb +35 -0
  103. data/spec/unit/file_system_spec.rb +6 -0
  104. data/spec/unit/functions/assert_type_spec.rb +1 -1
  105. data/spec/unit/functions/empty_spec.rb +10 -0
  106. data/spec/unit/functions/unwrap_spec.rb +8 -0
  107. data/spec/unit/functions4_spec.rb +2 -2
  108. data/spec/unit/indirector/resource/ral_spec.rb +40 -75
  109. data/spec/unit/module_tool/applications/installer_spec.rb +12 -0
  110. data/spec/unit/parser/templatewrapper_spec.rb +12 -2
  111. data/spec/unit/provider/package/pip_spec.rb +37 -0
  112. data/spec/unit/provider/parsedfile_spec.rb +10 -0
  113. data/spec/unit/settings_spec.rb +97 -56
  114. data/spec/unit/type/exec_spec.rb +76 -29
  115. data/spec/unit/type/file/source_spec.rb +4 -4
  116. data/spec/unit/type/tidy_spec.rb +7 -0
  117. data/spec/unit/util/windows/sid_spec.rb +39 -4
  118. data/tasks/generate_cert_fixtures.rake +10 -1
  119. metadata +12 -3
@@ -46,6 +46,11 @@ module Puppet
46
46
  ext = ef.create_extension(["subjectAltName", opts[:subject_alt_names], false])
47
47
  cert.add_extension(ext)
48
48
  end
49
+ if exts = opts[:extensions]
50
+ exts.each do |e|
51
+ cert.add_extension(OpenSSL::X509::Extension.new(*e))
52
+ end
53
+ end
49
54
  cert.sign(issuer_key, @digest)
50
55
  { private_key: key, cert: cert }
51
56
  end
@@ -20,6 +20,7 @@ module PuppetSpec::Settings
20
20
  end.freeze
21
21
 
22
22
  def set_puppet_conf(confdir, settings)
23
+ FileUtils.mkdir_p(confdir)
23
24
  write_file(File.join(confdir, "puppet.conf"), settings)
24
25
  end
25
26
 
@@ -5,6 +5,14 @@ require 'puppet/file_system'
5
5
  describe Puppet::Environments do
6
6
  FS = Puppet::FileSystem
7
7
 
8
+ module FsRemove
9
+ def remove
10
+ @properties[:directory?] = false
11
+ @properties[:exist?] = false
12
+ @properties[:executable?] = false
13
+ end
14
+ end
15
+
8
16
  before(:each) do
9
17
  Puppet.settings.initialize_global_settings
10
18
  Puppet[:environment_timeout] = "unlimited"
@@ -607,6 +615,33 @@ config_version=$vardir/random/scripts
607
615
  cached.get(:cached)
608
616
  end
609
617
 
618
+ it "does not list deleted environments" do
619
+ env3 = FS::MemoryFile.a_directory("env3", [
620
+ FS::MemoryFile.a_regular_file_containing("environment.conf", '')
621
+ ])
622
+
623
+ envdir = FS::MemoryFile.a_directory(File.expand_path("envdir"), [
624
+ FS::MemoryFile.a_directory("env1", [
625
+ FS::MemoryFile.a_regular_file_containing("environment.conf", '')
626
+ ]),
627
+ FS::MemoryFile.a_directory("env2", [
628
+ FS::MemoryFile.a_regular_file_containing("environment.conf", '')
629
+ ]),
630
+ env3
631
+ ])
632
+
633
+ loader_from(:filesystem => [envdir], :directory => envdir) do |loader|
634
+ cached = Puppet::Environments::Cached.new(loader)
635
+ cached.get(:env1)
636
+ cached.get(:env2)
637
+ cached.get(:env3)
638
+ env3.extend(FsRemove).remove
639
+
640
+ expect(cached.list).to contain_exactly(environment(:env1),environment(:env2))
641
+ expect(cached.get(:env3)).to be_nil
642
+ end
643
+ end
644
+
610
645
  it "returns nil if env not found" do
611
646
  cached_loader_from(:filesystem => [directory_tree], :directory => directory_tree.children.first) do |loader|
612
647
  expect(loader.get(:doesnotexist)).to be_nil
@@ -290,6 +290,12 @@ describe "Puppet::FileSystem" do
290
290
  expect(Puppet::FileSystem.read_preserve_line_endings(file)).to eq("file content \r\nsecond line \n")
291
291
  end
292
292
  end
293
+
294
+ it "should ignore leading BOM" do
295
+ with_file_content("\uFEFFfile content \n") do |file|
296
+ expect(Puppet::FileSystem.read_preserve_line_endings(file)).to eq("file content \n")
297
+ end
298
+ end
293
299
  end
294
300
 
295
301
  context "read without an encoding specified" do
@@ -28,7 +28,7 @@ describe 'the assert_type function' do
28
28
  it 'checks that first argument is a type' do
29
29
  expect do
30
30
  func.call({}, 10, 10)
31
- end.to raise_error(ArgumentError, "'assert_type' expects one of:
31
+ end.to raise_error(ArgumentError, "The function 'assert_type' was called with arguments it does not accept. It expects one of:
32
32
  (Type type, Any value, Callable[Type, Type] block?)
33
33
  rejected: parameter 'type' expects a Type value, got Integer
34
34
  (String type_string, Any value, Callable[Type, Type] block?)
@@ -56,6 +56,16 @@ describe 'the empty function' do
56
56
  end
57
57
  end
58
58
 
59
+ context 'for a sensitive string it' do
60
+ it 'returns true when empty' do
61
+ expect(compile_to_catalog("notify { String(empty(Sensitive(''))): }")).to have_resource('Notify[true]')
62
+ end
63
+
64
+ it 'returns false when not empty' do
65
+ expect(compile_to_catalog("notify { String(empty(Sensitive(' '))): }")).to have_resource('Notify[false]')
66
+ end
67
+ end
68
+
59
69
  context 'for a binary it' do
60
70
  it 'returns true when empty' do
61
71
  expect(compile_to_catalog("notify { String(empty(Binary(''))): }")).to have_resource('Notify[true]')
@@ -15,6 +15,14 @@ describe 'the unwrap function' do
15
15
  expect(eval_and_collect_notices(code)).to eq(['unwrapped value is 12345'])
16
16
  end
17
17
 
18
+ it 'just returns a non-sensitive value' do
19
+ code = <<-CODE
20
+ $non_sensitive = "12345"
21
+ notice("value is still ${non_sensitive.unwrap}")
22
+ CODE
23
+ expect(eval_and_collect_notices(code)).to eq(['value is still 12345'])
24
+ end
25
+
18
26
  it 'unwraps a sensitive value when given a code block' do
19
27
  code = <<-CODE
20
28
  $sensitive = Sensitive.new("12345")
@@ -160,7 +160,7 @@ describe 'the 4x function api' do
160
160
  expect(func.is_a?(Puppet::Functions::Function)).to be_truthy
161
161
  expect do
162
162
  func.call({}, 3, 10, 3, "4")
163
- end.to raise_error(ArgumentError, "'min' expects one of:
163
+ end.to raise_error(ArgumentError, "The function 'min' was called with arguments it does not accept. It expects one of:
164
164
  (Numeric x, Numeric y, Numeric a?, Numeric b?, Numeric c*)
165
165
  rejected: parameter 'b' expects a Numeric value, got String
166
166
  (String x, String y, String a+)
@@ -231,7 +231,7 @@ describe 'the 4x function api' do
231
231
  expect(func.is_a?(Puppet::Functions::Function)).to be_truthy
232
232
  expect do
233
233
  func.call({}, 10, '20')
234
- end.to raise_error(ArgumentError, "'min' expects one of:
234
+ end.to raise_error(ArgumentError, "The function 'min' was called with arguments it does not accept. It expects one of:
235
235
  (Numeric a, Numeric b)
236
236
  rejected: parameter 'b' expects a Numeric value, got String
237
237
  (String s1, String s2)
@@ -1,120 +1,85 @@
1
1
  require 'spec_helper'
2
2
  require 'puppet/indirector/resource/ral'
3
3
 
4
- describe "Puppet::Resource::Ral" do
4
+ describe Puppet::Resource::Ral do
5
+ let(:my_instance) { Puppet::Type.type(:user).new(:name => "root") }
6
+ let(:wrong_instance) { Puppet::Type.type(:user).new(:name => "bob")}
7
+
8
+ def stub_retrieve(*instances)
9
+ instances.each do |i|
10
+ allow(i).to receive(:retrieve).and_return(Puppet::Resource.new(i, nil))
11
+ end
12
+ end
13
+
14
+ before do
15
+ described_class.indirection.terminus_class = :ral
16
+
17
+ # make sure we don't try to retrieve current state
18
+ allow_any_instance_of(Puppet::Type.type(:user)).to receive(:retrieve).never
19
+ stub_retrieve(my_instance, wrong_instance)
20
+ end
21
+
5
22
  it "disallows remote requests" do
6
23
  expect(Puppet::Resource::Ral.new.allow_remote_requests?).to eq(false)
7
24
  end
8
25
 
9
26
  describe "find" do
10
- before do
11
- @request = double('request', :key => "user/root")
12
- end
13
-
14
27
  it "should find an existing instance" do
15
- my_resource = double("my user resource")
28
+ allow(Puppet::Type.type(:user)).to receive(:instances).and_return([ wrong_instance, my_instance, wrong_instance ])
16
29
 
17
- wrong_instance = double("wrong user", :name => "bob")
18
- my_instance = double("my user", :name => "root", :to_resource => my_resource)
19
-
20
- expect(Puppet::Type.type(:user)).to receive(:instances).and_return([ wrong_instance, my_instance, wrong_instance ])
21
- expect(Puppet::Resource::Ral.new.find(@request)).to eq(my_resource)
30
+ actual_resource = described_class.indirection.find('user/root')
31
+ expect(actual_resource.name).to eq('User/root')
22
32
  end
23
33
 
24
34
  it "should produce Puppet::Error instead of ArgumentError" do
25
- @bad_request = double('thiswillcauseanerror', :key => "thiswill/causeanerror")
26
- expect{Puppet::Resource::Ral.new.find(@bad_request)}.to raise_error(Puppet::Error)
35
+ expect{described_class.indirection.find('thiswill/causeanerror')}.to raise_error(Puppet::Error)
27
36
  end
28
37
 
29
38
  it "if there is no instance, it should create one" do
30
- wrong_instance = double("wrong user", :name => "bob")
31
- root = double("Root User")
32
- root_resource = double("Root Resource")
33
-
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)
36
- expect(root).to receive(:to_resource).and_return(root_resource)
37
-
38
- result = Puppet::Resource::Ral.new.find(@request)
39
+ allow(Puppet::Type.type(:user)).to receive(:instances).and_return([wrong_instance])
39
40
 
40
- expect(result).to eq(root_resource)
41
+ expect(Puppet::Type.type(:user)).to receive(:new).with(hash_including(name: "root")).and_return(my_instance)
42
+ expect(described_class.indirection.find('user/root')).to be
41
43
  end
42
44
  end
43
45
 
44
46
  describe "search" do
45
- before do
46
- @request = double('request', :key => "user/", :options => {})
47
- end
48
-
49
47
  it "should convert ral resources into regular resources" do
50
- my_resource = double("my user resource", :title => "my user resource")
51
- my_instance = double("my user", :name => "root", :to_resource => my_resource)
48
+ allow(Puppet::Type.type(:user)).to receive(:instances).and_return([ my_instance ])
52
49
 
53
- expect(Puppet::Type.type(:user)).to receive(:instances).and_return([ my_instance ])
54
- expect(Puppet::Resource::Ral.new.search(@request)).to eq([my_resource])
50
+ actual = described_class.indirection.search('user')
51
+ expect(actual).to contain_exactly(an_instance_of(Puppet::Resource))
55
52
  end
56
53
 
57
54
  it "should filter results by name if there's a name in the key" do
58
- my_resource = double("my user resource", title: "my user resource")
59
- allow(my_resource).to receive(:to_resource).and_return(my_resource)
60
- allow(my_resource).to receive(:[]).with(:name).and_return("root")
61
-
62
- wrong_resource = double("wrong resource")
63
- allow(wrong_resource).to receive(:to_resource).and_return(wrong_resource)
64
- allow(wrong_resource).to receive(:[]).with(:name).and_return("bad")
55
+ allow(Puppet::Type.type(:user)).to receive(:instances).and_return([ my_instance, wrong_instance ])
65
56
 
66
- my_instance = double("my user", :to_resource => my_resource)
67
- wrong_instance = double("wrong user", :to_resource => wrong_resource)
68
-
69
- @request = double('request', :key => "user/root", :options => {})
70
-
71
- expect(Puppet::Type.type(:user)).to receive(:instances).and_return([ my_instance, wrong_instance ])
72
- expect(Puppet::Resource::Ral.new.search(@request)).to eq([my_resource])
57
+ actual = described_class.indirection.search('user/root')
58
+ expect(actual).to contain_exactly(an_object_having_attributes(name: 'User/root'))
73
59
  end
74
60
 
75
61
  it "should filter results by query parameters" do
76
- wrong_resource = double("my user resource", title: "my user resource")
77
- allow(wrong_resource).to receive(:to_resource).and_return(wrong_resource)
78
- allow(wrong_resource).to receive(:[]).with(:name).and_return("root")
79
-
80
- my_resource = double("wrong resource", title: "wrong resource")
81
- allow(my_resource).to receive(:to_resource).and_return(my_resource)
82
- allow(my_resource).to receive(:[]).with(:name).and_return("bob")
62
+ allow(Puppet::Type.type(:user)).to receive(:instances).and_return([ my_instance, wrong_instance ])
83
63
 
84
- my_instance = double("my user", :to_resource => my_resource)
85
- wrong_instance = double("wrong user", :to_resource => wrong_resource)
86
-
87
- @request = double('request', :key => "user/", :options => {:name => "bob"})
88
-
89
- expect(Puppet::Type.type(:user)).to receive(:instances).and_return([ my_instance, wrong_instance ])
90
- expect(Puppet::Resource::Ral.new.search(@request)).to eq([my_resource])
64
+ actual = described_class.indirection.search('user', name: 'bob')
65
+ expect(actual).to contain_exactly(an_object_having_attributes(name: 'User/bob'))
91
66
  end
92
67
 
93
68
  it "should return sorted results" do
94
- a_resource = double("alice resource")
95
- allow(a_resource).to receive(:to_resource).and_return(a_resource)
96
- allow(a_resource).to receive(:title).and_return("alice")
97
-
98
- b_resource = double("bob resource")
99
- allow(b_resource).to receive(:to_resource).and_return(b_resource)
100
- allow(b_resource).to receive(:title).and_return("bob")
101
-
102
- a_instance = double("alice user", :to_resource => a_resource)
103
- b_instance = double("bob user", :to_resource => b_resource)
104
-
105
- @request = double('request', :key => "user/", :options => {})
69
+ a_instance = Puppet::Type.type(:user).new(:name => "alice")
70
+ b_instance = Puppet::Type.type(:user).new(:name => "bob")
71
+ stub_retrieve(a_instance, b_instance)
72
+ allow(Puppet::Type.type(:user)).to receive(:instances).and_return([ b_instance, a_instance ])
106
73
 
107
- expect(Puppet::Type.type(:user)).to receive(:instances).and_return([ b_instance, a_instance ])
108
- expect(Puppet::Resource::Ral.new.search(@request)).to eq([a_resource, b_resource])
74
+ expect(described_class.indirection.search('user').map(&:title)).to eq(['alice', 'bob'])
109
75
  end
110
76
  end
111
77
 
112
78
  describe "save" do
113
79
  it "returns a report covering the application of the given resource to the system" do
114
80
  resource = Puppet::Resource.new(:notify, "the title")
115
- ral = Puppet::Resource::Ral.new
116
81
 
117
- applied_resource, report = ral.save(Puppet::Indirector::Request.new(:ral, :save, 'testing', resource, :environment => Puppet::Node::Environment.remote(:testing)))
82
+ applied_resource, report = described_class.indirection.save(resource, nil, environment: Puppet::Node::Environment.remote(:testing))
118
83
 
119
84
  expect(applied_resource.title).to eq("the title")
120
85
  expect(report.environment).to eq("testing")
@@ -66,6 +66,18 @@ describe Puppet::ModuleTool::Applications::Installer, :unless => RUBY_PLATFORM =
66
66
  graph_should_include 'pmtacceptance-stdlib', nil => v('4.1.0')
67
67
  end
68
68
 
69
+ it 'reports a meaningful error if the name is invalid' do
70
+ app = installer('ntp', install_dir, options)
71
+ results = app.run
72
+ expect(results).to include :result => :failure
73
+ expect(results[:error][:oneline]).to eq("Could not install 'ntp', did you mean 'puppetlabs-ntp'?")
74
+ expect(results[:error][:multiline]).to eq(<<~END.chomp)
75
+ Could not install module 'ntp'
76
+ The name 'ntp' is invalid
77
+ Did you mean `puppet module install puppetlabs-ntp`?
78
+ END
79
+ end
80
+
69
81
  context 'with a tarball file' do
70
82
  let(:module) { fixtures('stdlib.tgz') }
71
83
 
@@ -2,6 +2,8 @@ require 'spec_helper'
2
2
  require 'puppet/parser/templatewrapper'
3
3
 
4
4
  describe Puppet::Parser::TemplateWrapper do
5
+ include PuppetSpec::Files
6
+
5
7
  let(:known_resource_types) { Puppet::Resource::TypeCollection.new("env") }
6
8
  let(:scope) do
7
9
  compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("mynode"))
@@ -41,6 +43,13 @@ describe Puppet::Parser::TemplateWrapper do
41
43
  expect(tw.result).to eq(full_file_name)
42
44
  end
43
45
 
46
+ it "ignores a leading BOM" do
47
+ full_file_name = given_a_template_file("bom_template", "\uFEFF<%= file %>")
48
+
49
+ tw.file = "bom_template"
50
+ expect(tw.result).to eq(full_file_name)
51
+ end
52
+
44
53
  it "evaluates a given string as a template" do
45
54
  expect(tw.result("template contents")).to eql("template contents")
46
55
  end
@@ -90,11 +99,12 @@ describe Puppet::Parser::TemplateWrapper do
90
99
  end
91
100
 
92
101
  def given_a_template_file(name, contents)
93
- full_name = "/full/path/to/#{name}"
102
+ full_name = tmpfile("template_#{name}")
103
+ File.binwrite(full_name, contents)
104
+
94
105
  allow(Puppet::Parser::Files).to receive(:find_template).
95
106
  with(name, anything()).
96
107
  and_return(full_name)
97
- allow(Puppet::FileSystem).to receive(:read_preserve_line_endings).with(full_name).and_return(contents)
98
108
 
99
109
  full_name
100
110
  end
@@ -266,6 +266,43 @@ describe Puppet::Type.type(:package).provider(:pip) do
266
266
  let(:pip_version) { '1.5.4' }
267
267
  let(:pip_path) { '/fake/bin/pip' }
268
268
 
269
+ context "with pip version >= 20.3 and < 21.1" do
270
+ let(:pip_version) { '20.3.1' }
271
+ let(:pip_path) { '/fake/bin/pip' }
272
+
273
+ it "should use legacy-resolver argument" do
274
+ p = StringIO.new(
275
+ <<-EOS
276
+ Collecting real-package==versionplease
277
+ Could not find a version that satisfies the requirement real-package==versionplease (from versions: 1.1.3, 1.0, 1.9b1)
278
+ No matching distribution found for real-package==versionplease
279
+ EOS
280
+ )
281
+ expect(Puppet::Util::Execution).to receive(:execpipe).with(["/fake/bin/pip", "install", "real_package==versionplease",
282
+ "--use-deprecated=legacy-resolver"]).and_yield(p).once
283
+ @resource[:name] = "real_package"
284
+ @provider.latest
285
+ end
286
+ end
287
+
288
+ context "with pip version >= 21.1" do
289
+ let(:pip_version) { '21.1' }
290
+ let(:pip_path) { '/fake/bin/pip' }
291
+
292
+ it "should not use legacy-resolver argument" do
293
+ p = StringIO.new(
294
+ <<-EOS
295
+ Collecting real-package==versionplease
296
+ Could not find a version that satisfies the requirement real-package==versionplease (from versions: 1.1.3, 1.0, 1.9b1)
297
+ No matching distribution found for real-package==versionplease
298
+ EOS
299
+ )
300
+ expect(Puppet::Util::Execution).to receive(:execpipe).with(["/fake/bin/pip", "install", "real_package==versionplease"]).and_yield(p).once
301
+ @resource[:name] = "real_package"
302
+ @provider.latest
303
+ end
304
+ end
305
+
269
306
  it "should find a version number for real_package" do
270
307
  p = StringIO.new(
271
308
  <<-EOS
@@ -79,6 +79,16 @@ describe Puppet::Provider::ParsedFile do
79
79
 
80
80
  provider.instances
81
81
  end
82
+
83
+ it "should raise if parsing returns nil" do
84
+ expect(provider).to receive(:targets).and_return(%w{/one})
85
+ expect_any_instance_of(Puppet::Util::FileType::FileTypeFlat).to receive(:read).and_return('a=b')
86
+ expect(provider).to receive(:parse).and_return(nil)
87
+
88
+ expect {
89
+ provider.instances
90
+ }.to raise_error(Puppet::DevError, %r{Prefetching /one for provider parsedfile_provider returned nil})
91
+ end
82
92
  end
83
93
 
84
94
  describe "when matching resources to existing records" do
@@ -29,6 +29,17 @@ describe Puppet::Settings do
29
29
  end
30
30
  end
31
31
 
32
+ def stub_config_with(content)
33
+ allow(Puppet.features).to receive(:root?).and_return(false)
34
+ expect(Puppet::FileSystem).to receive(:exist?).
35
+ with(user_config_file_default_location).
36
+ and_return(true).ordered
37
+ expect(@settings).to receive(:read_file).
38
+ with(user_config_file_default_location).
39
+ and_return(content).ordered
40
+ @settings.send(:parse_config_files)
41
+ end
42
+
32
43
  describe "when specifying defaults" do
33
44
  before do
34
45
  @settings = Puppet::Settings.new
@@ -264,23 +275,31 @@ describe Puppet::Settings do
264
275
  expect(@settings[:myval]).to eq("")
265
276
  end
266
277
 
267
- it "should flag string settings from the CLI" do
278
+ it "should retrieve numeric settings from the CLI" do
268
279
  @settings.handlearg("--myval", "12")
269
- expect(@settings.set_by_cli?(:myval)).to be_truthy
280
+ expect(@settings.set_by_cli(:myval)).to eq(12)
281
+ expect(@settings.set_by_cli?(:myval)).to be true
270
282
  end
271
283
 
272
- it "should flag bool settings from the CLI" do
284
+ it "should retrieve string settings from the CLI" do
285
+ @settings.handlearg("--myval", "something")
286
+ expect(@settings.set_by_cli(:myval)).to eq("something")
287
+ expect(@settings.set_by_cli?(:myval)).to be true
288
+ end
289
+
290
+ it "should retrieve bool settings from the CLI" do
273
291
  @settings.handlearg("--bool")
274
- expect(@settings.set_by_cli?(:bool)).to be_truthy
292
+ expect(@settings.set_by_cli(:bool)).to be true
293
+ expect(@settings.set_by_cli?(:bool)).to be true
275
294
  end
276
295
 
277
- it "should not flag settings memory as from CLI" do
296
+ it "should not retrieve settings set in memory as from CLI" do
278
297
  @settings[:myval] = "12"
279
- expect(@settings.set_by_cli?(:myval)).to be_falsey
298
+ expect(@settings.set_by_cli?(:myval)).to be false
280
299
  end
281
300
 
282
301
  it "should find no configured settings by default" do
283
- expect(@settings.set_by_config?(:myval)).to be_falsey
302
+ expect(@settings.set_by_config?(:myval)).to be false
284
303
  end
285
304
 
286
305
  it "should identify configured settings in memory" do
@@ -304,64 +323,66 @@ describe Puppet::Settings do
304
323
  expect(@settings.set_by_config?(:manifest, Puppet[:environment])).to be_truthy
305
324
  end
306
325
 
307
- it "should identify configured settings from the preferred run mode" do
308
- user_config_text = "[#{@settings.preferred_run_mode}]\nmyval = foo"
326
+ context "when handling puppet.conf" do
327
+ describe "#set_by_config?" do
328
+ it "should identify configured settings from the preferred run mode" do
329
+ stub_config_with(<<~CONFIG)
330
+ [#{@settings.preferred_run_mode}]
331
+ myval = foo
332
+ CONFIG
309
333
 
310
- allow(Puppet.features).to receive(:root?).and_return(false)
311
- expect(Puppet::FileSystem).to receive(:exist?).
312
- with(user_config_file_default_location).
313
- and_return(true).ordered
314
- expect(@settings).to receive(:read_file).
315
- with(user_config_file_default_location).
316
- and_return(user_config_text).ordered
334
+ expect(@settings.set_by_config?(:myval)).to be_truthy
335
+ end
317
336
 
318
- @settings.send(:parse_config_files)
319
- expect(@settings.set_by_config?(:myval)).to be_truthy
320
- end
337
+ it "should identify configured settings from the specified run mode" do
338
+ stub_config_with(<<~CONFIG)
339
+ [server]
340
+ myval = foo
341
+ CONFIG
321
342
 
322
- it "should identify configured settings from the specified run mode" do
323
- user_config_text = "[server]\nmyval = foo"
343
+ expect(@settings.set_by_config?(:myval, nil, :server)).to be_truthy
344
+ end
324
345
 
325
- allow(Puppet.features).to receive(:root?).and_return(false)
326
- expect(Puppet::FileSystem).to receive(:exist?).
327
- with(user_config_file_default_location).
328
- and_return(true).ordered
329
- expect(@settings).to receive(:read_file).
330
- with(user_config_file_default_location).
331
- and_return(user_config_text).ordered
346
+ it "should not identify configured settings from an unspecified run mode" do
347
+ stub_config_with(<<~CONFIG)
348
+ [zaz]
349
+ myval = foo
350
+ CONFIG
332
351
 
333
- @settings.send(:parse_config_files)
334
- expect(@settings.set_by_config?(:myval, nil, :server)).to be_truthy
335
- end
352
+ expect(@settings.set_by_config?(:myval)).to be_falsey
353
+ end
336
354
 
337
- it "should not identify configured settings from an unspecified run mode" do
338
- user_config_text = "[zaz]\nmyval = foo"
355
+ it "should identify configured settings from the main section" do
356
+ stub_config_with(<<~CONFIG)
357
+ [main]
358
+ myval = foo
359
+ CONFIG
339
360
 
340
- allow(Puppet.features).to receive(:root?).and_return(false)
341
- expect(Puppet::FileSystem).to receive(:exist?).
342
- with(user_config_file_default_location).
343
- and_return(true).ordered
344
- expect(@settings).to receive(:read_file).
345
- with(user_config_file_default_location).
346
- and_return(user_config_text).ordered
361
+ expect(@settings.set_by_config?(:myval)).to be_truthy
362
+ end
363
+ end
347
364
 
348
- @settings.send(:parse_config_files)
349
- expect(@settings.set_by_config?(:myval)).to be_falsey
350
- end
365
+ describe "#set_in_section" do
366
+ it "should retrieve configured settings from the specified section" do
367
+ stub_config_with(<<~CONFIG)
368
+ [agent]
369
+ myval = foo
370
+ CONFIG
351
371
 
352
- it "should identify configured settings from the main section" do
353
- user_config_text = "[main]\nmyval = foo"
372
+ expect(@settings.set_in_section(:myval, :agent)).to eq("foo")
373
+ expect(@settings.set_in_section?(:myval, :agent)).to be true
374
+ end
354
375
 
355
- allow(Puppet.features).to receive(:root?).and_return(false)
356
- expect(Puppet::FileSystem).to receive(:exist?).
357
- with(user_config_file_default_location).
358
- and_return(true).ordered
359
- expect(@settings).to receive(:read_file).
360
- with(user_config_file_default_location).
361
- and_return(user_config_text).ordered
376
+ it "should not retrieve configured settings from a different section" do
377
+ stub_config_with(<<~CONFIG)
378
+ [main]
379
+ myval = foo
380
+ CONFIG
362
381
 
363
- @settings.send(:parse_config_files)
364
- expect(@settings.set_by_config?(:myval)).to be_truthy
382
+ expect(@settings.set_in_section(:myval, :agent)).to be nil
383
+ expect(@settings.set_in_section?(:myval, :agent)).to be false
384
+ end
385
+ end
365
386
  end
366
387
 
367
388
  it "should clear the cache when setting getopt-specific values" do
@@ -2120,7 +2141,7 @@ describe Puppet::Settings do
2120
2141
  end
2121
2142
 
2122
2143
  def a_user_type_for(username)
2123
- user = double('user')
2144
+ user = double('user', 'suitable?': true, to_s: "User[#{username}]")
2124
2145
  expect(Puppet::Type.type(:user)).to receive(:new).with(hash_including(name: username)).and_return(user)
2125
2146
  user
2126
2147
  end
@@ -2153,6 +2174,16 @@ describe Puppet::Settings do
2153
2174
 
2154
2175
  expect(settings).to be_service_user_available
2155
2176
  end
2177
+
2178
+ it "raises if the user is not suitable" do
2179
+ settings[:user] = "foo"
2180
+
2181
+ expect(a_user_type_for("foo")).to receive(:suitable?).and_return(false)
2182
+
2183
+ expect {
2184
+ settings.service_user_available?
2185
+ }.to raise_error(Puppet::Error, /Cannot manage owner permissions, because the provider for 'User\[foo\]' is not functional/)
2186
+ end
2156
2187
  end
2157
2188
 
2158
2189
  describe "when determining if the service group is available" do
@@ -2163,7 +2194,7 @@ describe Puppet::Settings do
2163
2194
  end
2164
2195
 
2165
2196
  def a_group_type_for(groupname)
2166
- group = double('group')
2197
+ group = double('group', 'suitable?': true, to_s: "Group[#{groupname}]")
2167
2198
  expect(Puppet::Type.type(:group)).to receive(:new).with(hash_including(name: groupname)).and_return(group)
2168
2199
  group
2169
2200
  end
@@ -2196,6 +2227,16 @@ describe Puppet::Settings do
2196
2227
 
2197
2228
  expect(settings).to be_service_group_available
2198
2229
  end
2230
+
2231
+ it "raises if the group is not suitable" do
2232
+ settings[:group] = "foo"
2233
+
2234
+ expect(a_group_type_for("foo")).to receive(:suitable?).and_return(false)
2235
+
2236
+ expect {
2237
+ settings.service_group_available?
2238
+ }.to raise_error(Puppet::Error, /Cannot manage group permissions, because the provider for 'Group\[foo\]' is not functional/)
2239
+ end
2199
2240
  end
2200
2241
 
2201
2242
  describe "when dealing with command-line options" do