puppet 7.12.1 → 7.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/CODEOWNERS +1 -1
  3. data/Gemfile +2 -2
  4. data/Gemfile.lock +36 -31
  5. data/ext/project_data.yaml +1 -1
  6. data/lib/puppet/application/lookup.rb +74 -24
  7. data/lib/puppet/concurrent/thread_local_singleton.rb +5 -3
  8. data/lib/puppet/configurer.rb +8 -14
  9. data/lib/puppet/defaults.rb +13 -1
  10. data/lib/puppet/face/generate.rb +2 -0
  11. data/lib/puppet/file_serving/metadata.rb +3 -0
  12. data/lib/puppet/file_system/file_impl.rb +7 -7
  13. data/lib/puppet/file_system/jruby.rb +1 -1
  14. data/lib/puppet/file_system/path_pattern.rb +10 -15
  15. data/lib/puppet/file_system/uniquefile.rb +1 -1
  16. data/lib/puppet/file_system/windows.rb +4 -4
  17. data/lib/puppet/file_system.rb +1 -1
  18. data/lib/puppet/functions/next.rb +18 -1
  19. data/lib/puppet/functions/tree_each.rb +0 -1
  20. data/lib/puppet/functions/versioncmp.rb +6 -2
  21. data/lib/puppet/generate/type.rb +9 -0
  22. data/lib/puppet/graph/simple_graph.rb +2 -1
  23. data/lib/puppet/http/client.rb +1 -1
  24. data/lib/puppet/node.rb +1 -1
  25. data/lib/puppet/pops/parser/code_merger.rb +4 -4
  26. data/lib/puppet/pops/parser/egrammar.ra +2 -0
  27. data/lib/puppet/pops/parser/eparser.rb +574 -558
  28. data/lib/puppet/pops/serialization/to_data_converter.rb +6 -18
  29. data/lib/puppet/pops/validation/checker4_0.rb +7 -2
  30. data/lib/puppet/provider/service/init.rb +5 -4
  31. data/lib/puppet/resource/type_collection.rb +21 -17
  32. data/lib/puppet/ssl/verifier.rb +3 -1
  33. data/lib/puppet/transaction/persistence.rb +22 -12
  34. data/lib/puppet/type/exec.rb +1 -1
  35. data/lib/puppet/type/file/data_sync.rb +1 -1
  36. data/lib/puppet/type/file/group.rb +8 -1
  37. data/lib/puppet/type/file/owner.rb +8 -1
  38. data/lib/puppet/type/user.rb +41 -39
  39. data/lib/puppet/util/json.rb +17 -0
  40. data/lib/puppet/util/log.rb +7 -2
  41. data/lib/puppet/util/monkey_patches.rb +26 -4
  42. data/lib/puppet/util/package.rb +25 -16
  43. data/lib/puppet/util/yaml.rb +16 -1
  44. data/lib/puppet/util.rb +1 -0
  45. data/lib/puppet/version.rb +1 -1
  46. data/lib/puppet.rb +1 -0
  47. data/locales/puppet.pot +5 -9741
  48. data/man/man5/puppet.conf.5 +21 -2
  49. data/man/man8/puppet-agent.8 +1 -1
  50. data/man/man8/puppet-apply.8 +1 -1
  51. data/man/man8/puppet-catalog.8 +1 -1
  52. data/man/man8/puppet-config.8 +1 -1
  53. data/man/man8/puppet-describe.8 +1 -1
  54. data/man/man8/puppet-device.8 +1 -1
  55. data/man/man8/puppet-doc.8 +1 -1
  56. data/man/man8/puppet-epp.8 +1 -1
  57. data/man/man8/puppet-facts.8 +1 -1
  58. data/man/man8/puppet-filebucket.8 +1 -1
  59. data/man/man8/puppet-generate.8 +1 -1
  60. data/man/man8/puppet-help.8 +1 -1
  61. data/man/man8/puppet-lookup.8 +9 -6
  62. data/man/man8/puppet-module.8 +1 -1
  63. data/man/man8/puppet-node.8 +1 -1
  64. data/man/man8/puppet-parser.8 +1 -1
  65. data/man/man8/puppet-plugin.8 +1 -1
  66. data/man/man8/puppet-report.8 +1 -1
  67. data/man/man8/puppet-resource.8 +1 -1
  68. data/man/man8/puppet-script.8 +1 -1
  69. data/man/man8/puppet-ssl.8 +1 -1
  70. data/man/man8/puppet.8 +2 -2
  71. data/spec/fixtures/unit/forge/bacula.json +1 -1
  72. data/spec/integration/application/lookup_spec.rb +81 -50
  73. data/spec/integration/application/resource_spec.rb +6 -2
  74. data/spec/integration/parser/pcore_resource_spec.rb +10 -0
  75. data/spec/shared_contexts/l10n.rb +5 -0
  76. data/spec/unit/application/lookup_spec.rb +131 -10
  77. data/spec/unit/concurrent/thread_local_singleton_spec.rb +39 -0
  78. data/spec/unit/configurer_spec.rb +124 -61
  79. data/spec/unit/confiner_spec.rb +6 -6
  80. data/spec/unit/face/generate_spec.rb +64 -0
  81. data/spec/unit/file_system/uniquefile_spec.rb +7 -1
  82. data/spec/unit/file_system_spec.rb +34 -4
  83. data/spec/unit/forge/module_release_spec.rb +3 -3
  84. data/spec/unit/functions/versioncmp_spec.rb +40 -4
  85. data/spec/unit/node_spec.rb +6 -0
  86. data/spec/unit/pops/parser/parse_containers_spec.rb +2 -2
  87. data/spec/unit/pops/serialization/to_from_hr_spec.rb +0 -58
  88. data/spec/unit/pops/validator/validator_spec.rb +5 -0
  89. data/spec/unit/provider/service/gentoo_spec.rb +6 -5
  90. data/spec/unit/provider/service/init_spec.rb +15 -9
  91. data/spec/unit/provider/service/openwrt_spec.rb +21 -29
  92. data/spec/unit/provider/service/redhat_spec.rb +3 -2
  93. data/spec/unit/transaction/persistence_spec.rb +51 -0
  94. data/spec/unit/type/file/group_spec.rb +7 -0
  95. data/spec/unit/type/file/owner_spec.rb +7 -0
  96. data/spec/unit/type/user_spec.rb +67 -45
  97. data/spec/unit/util/json_spec.rb +126 -0
  98. data/spec/unit/util/windows_spec.rb +23 -0
  99. data/spec/unit/util/yaml_spec.rb +37 -13
  100. metadata +17 -5
@@ -19,16 +19,52 @@ describe "the versioncmp function" do
19
19
  let(:type_parser) { Puppet::Pops::Types::TypeParser.singleton }
20
20
 
21
21
  it 'should raise an Error if there is less than 2 arguments' do
22
- expect { versioncmp('a,b') }.to raise_error(/expects 2 arguments, got 1/)
22
+ expect { versioncmp('a,b') }.to raise_error(/expects between 2 and 3 arguments, got 1/)
23
23
  end
24
24
 
25
- it 'should raise an Error if there is more than 2 arguments' do
26
- expect { versioncmp('a,b','foo', 'bar') }.to raise_error(/expects 2 arguments, got 3/)
25
+ it 'should raise an Error if there is more than 3 arguments' do
26
+ expect { versioncmp('a,b','foo', false, 'bar') }.to raise_error(/expects between 2 and 3 arguments, got 4/)
27
27
  end
28
28
 
29
29
  it "should call Puppet::Util::Package.versioncmp (included in scope)" do
30
- expect(Puppet::Util::Package).to receive(:versioncmp).with('1.2', '1.3').and_return(-1)
30
+ expect(Puppet::Util::Package).to receive(:versioncmp).with('1.2', '1.3', false).and_return(-1)
31
31
 
32
32
  expect(versioncmp('1.2', '1.3')).to eq(-1)
33
33
  end
34
+
35
+ context "when ignore_trailing_zeroes is true" do
36
+ it "should equate versions with 2 elements and dots but with unnecessary zero" do
37
+ expect(versioncmp("10.1.0", "10.1", true)).to eq(0)
38
+ end
39
+
40
+ it "should equate versions with 1 element and dot but with unnecessary zero" do
41
+ expect(versioncmp("11.0", "11", true)).to eq(0)
42
+ end
43
+
44
+ it "should equate versions with 1 element and dot but with unnecessary zeros" do
45
+ expect(versioncmp("11.00", "11", true)).to eq(0)
46
+ end
47
+
48
+ it "should equate versions with dots and iregular zeroes" do
49
+ expect(versioncmp("11.0.00", "11", true)).to eq(0)
50
+ end
51
+
52
+ it "should equate versions with dashes" do
53
+ expect(versioncmp("10.1-0", "10.1.0-0", true)).to eq(0)
54
+ end
55
+
56
+ it "should compare versions with dashes after normalization" do
57
+ expect(versioncmp("10.1-1", "10.1.0-0", true)).to eq(1)
58
+ end
59
+
60
+ it "should not normalize versions if zeros are not trailing" do
61
+ expect(versioncmp("1.1", "1.0.1", true)).to eq(1)
62
+ end
63
+ end
64
+
65
+ context "when ignore_trailing_zeroes is false" do
66
+ it "should not equate versions if zeros are not trailing" do
67
+ expect(versioncmp("1.1", "1.0.1")).to eq(1)
68
+ end
69
+ end
34
70
  end
@@ -40,6 +40,12 @@ describe Puppet::Node do
40
40
  expect(node.environment.name).to eq(:bar)
41
41
  end
42
42
 
43
+ it "sets environment_name with the correct environment name" do
44
+ node = Puppet::Node.new("foo")
45
+ node.environment = Puppet::Node::Environment.remote('www123')
46
+ expect(node.environment_name).to eq(:www123)
47
+ end
48
+
43
49
  it "allows its environment to be set by parameters after initialization" do
44
50
  node = Puppet::Node.new("foo")
45
51
  node.parameters["environment"] = :bar
@@ -106,7 +106,7 @@ describe "egrammar parsing containers" do
106
106
 
107
107
  context 'it should allow keywords as attribute names' do
108
108
  ['and', 'case', 'class', 'default', 'define', 'else', 'elsif', 'if', 'in', 'inherits', 'node', 'or',
109
- 'undef', 'unless', 'type', 'attr', 'function', 'private'].each do |keyword|
109
+ 'undef', 'unless', 'type', 'attr', 'function', 'private', 'plan', 'apply'].each do |keyword|
110
110
  it "such as #{keyword}" do
111
111
  expect { parse("class x ($#{keyword}){} class { x: #{keyword} => 1 }") }.to_not raise_error
112
112
  end
@@ -178,7 +178,7 @@ describe "egrammar parsing containers" do
178
178
 
179
179
  context 'it should allow keywords as attribute names' do
180
180
  ['and', 'case', 'class', 'default', 'define', 'else', 'elsif', 'if', 'in', 'inherits', 'node', 'or',
181
- 'undef', 'unless', 'type', 'attr', 'function', 'private'].each do |keyword|
181
+ 'undef', 'unless', 'type', 'attr', 'function', 'private', 'plan', 'apply'].each do |keyword|
182
182
  it "such as #{keyword}" do
183
183
  expect {parse("define x ($#{keyword}){} x { y: #{keyword} => 1 }")}.to_not raise_error
184
184
  end
@@ -559,29 +559,6 @@ module Serialization
559
559
  expect(warnings).to eql(["['key'] contains the special value default. It will be converted to the String 'default'"])
560
560
  end
561
561
  end
562
- context 'and force_symbol set to true' do
563
- let(:to_converter) { ToDataConverter.new(:rich_data => false, :force_symbol => true) }
564
-
565
- it 'A Hash with Symbol values is converted to hash with Symbol values' do
566
- val = { 'one' => :one, 'two' => :two }
567
- Puppet::Util::Log.with_destination(Puppet::Test::LogCollector.new(logs)) do
568
-
569
- # write and read methods does not work here as we cannot force Symbols in Json.
570
- # and a hash with symbol values cannot be an instance of Types::TypeFactory.data.
571
- # Using YAML for this instead
572
- io.reopen
573
- value = to_converter.convert(val)
574
- io << [value].to_yaml
575
- io.rewind
576
-
577
- val2 = from_converter.convert(YAML::load(io.read)[0])
578
-
579
- expect(val2).to be_a(Hash)
580
- expect(val2).to eql({ 'one' => :one, 'two' => :two })
581
- end
582
- expect(warnings).to be_empty
583
- end
584
- end
585
562
  end
586
563
 
587
564
  context 'with rich_data is set to true' do
@@ -655,41 +632,6 @@ module Serialization
655
632
  end.to raise_error(/Cannot create a Pcore::TimestampType from a Integer/)
656
633
  end
657
634
  end
658
-
659
- context 'when data is unknown' do
660
- let(:to_converter) { ToDataConverter.new(:message_prefix => 'Test Hash') }
661
- let(:logs) { [] }
662
- let(:warnings) { logs.select { |log| log.level == :warning }.map { |log| log.message } }
663
- let(:val) { Class.new }
664
-
665
- context 'and :silence_warnings undefined or set to false' do
666
- it 'convert the unknown data to string with warnings' do
667
- Puppet::Util::Log.with_destination(Puppet::Test::LogCollector.new(logs)) do
668
- write(val)
669
- val2 = read
670
- expect(val2).to be_a(String)
671
- expect(val2).to match(/Class/)
672
- end
673
- expect(warnings).to eql([
674
- "Test Hash contains a #{val.class} value. It will be converted to the String '#{val.to_s}'"])
675
- end
676
- end
677
-
678
- context 'and :silence_warnings undefined or set to true' do
679
- let(:to_converter) { ToDataConverter.new(:message_prefix => 'Test Hash', :silence_warnings => true) }
680
-
681
- it 'convert the unknown data to string without warnings if silence_warnings set to true' do
682
- val = Class.new
683
- Puppet::Util::Log.with_destination(Puppet::Test::LogCollector.new(logs)) do
684
- write(val)
685
- val2 = read
686
- expect(val2).to be_a(String)
687
- expect(val2).to match(/Class/)
688
- end
689
- expect(warnings).to be_empty
690
- end
691
- end
692
- end
693
635
  end
694
636
  end
695
637
  end
@@ -414,6 +414,11 @@ describe "validating 4x" do
414
414
  expect(acceptor.error_count).to eql(0)
415
415
  end
416
416
 
417
+ it 'allows apply to be used as a resource attribute name' do
418
+ acceptor = validate(parse('apply("foo.example.com") { sometype { "resourcetitle": apply => "applyvalue" } }'))
419
+ expect(acceptor.error_count).to eql(0)
420
+ end
421
+
417
422
  it 'accepts multiple arguments' do
418
423
  acceptor = validate(parse('apply(["foo.example.com"], { "other" => "args" }) { }'))
419
424
  expect(acceptor.error_count).to eql(0)
@@ -6,8 +6,8 @@ describe 'Puppet::Type::Service::Provider::Gentoo',
6
6
 
7
7
  before :each do
8
8
  allow(Puppet::Type.type(:service)).to receive(:defaultprovider).and_return(provider_class)
9
- allow(FileTest).to receive(:file?).with('/sbin/rc-update').and_return(true)
10
- allow(FileTest).to receive(:executable?).with('/sbin/rc-update').and_return(true)
9
+ allow(Puppet::FileSystem).to receive(:file?).with('/sbin/rc-update').and_return(true)
10
+ allow(Puppet::FileSystem).to receive(:executable?).with('/sbin/rc-update').and_return(true)
11
11
  allow(Facter).to receive(:value).with(:operatingsystem).and_return('Gentoo')
12
12
  allow(Facter).to receive(:value).with(:osfamily).and_return('Gentoo')
13
13
 
@@ -52,13 +52,14 @@ describe 'Puppet::Type::Service::Provider::Gentoo',
52
52
  end
53
53
 
54
54
  it "should get a list of services from /etc/init.d but exclude helper scripts" do
55
- expect(FileTest).to receive(:directory?).with('/etc/init.d').and_return(true)
55
+ allow(Puppet::FileSystem).to receive(:directory?).and_call_original
56
+ allow(Puppet::FileSystem).to receive(:directory?).with('/etc/init.d').and_return(true)
56
57
  expect(Dir).to receive(:entries).with('/etc/init.d').and_return(initscripts)
57
58
  (initscripts - helperscripts).each do |script|
58
- expect(FileTest).to receive(:executable?).with("/etc/init.d/#{script}").and_return(true)
59
+ expect(Puppet::FileSystem).to receive(:executable?).with("/etc/init.d/#{script}").and_return(true)
59
60
  end
60
61
  helperscripts.each do |script|
61
- expect(FileTest).not_to receive(:executable?).with("/etc/init.d/#{script}")
62
+ expect(Puppet::FileSystem).not_to receive(:executable?).with("/etc/init.d/#{script}")
62
63
  end
63
64
 
64
65
  allow(Puppet::FileSystem).to receive(:symlink?).and_return(false)
@@ -85,14 +85,20 @@ describe 'Puppet::Type::Service::Provider::Init',
85
85
  @services = ['one', 'two', 'three', 'four', 'umountfs']
86
86
  allow(Dir).to receive(:entries).and_call_original
87
87
  allow(Dir).to receive(:entries).with('tmp').and_return(@services)
88
- expect(FileTest).to receive(:directory?).with('tmp').and_return(true)
89
- allow(FileTest).to receive(:executable?).and_return(true)
88
+ allow(Puppet::FileSystem).to receive(:directory?).and_call_original
89
+ allow(Puppet::FileSystem).to receive(:directory?).with('tmp').and_return(true)
90
+ allow(Puppet::FileSystem).to receive(:executable?).and_return(true)
90
91
  end
91
92
 
92
93
  it "should return instances for all services" do
93
94
  expect(provider_class.instances.map(&:name)).to eq(@services)
94
95
  end
95
96
 
97
+ it "should omit directories from the service list" do
98
+ expect(Puppet::FileSystem).to receive(:directory?).with('tmp/four').and_return(true)
99
+ expect(provider_class.instances.map(&:name)).to eq(@services - ['four'])
100
+ end
101
+
96
102
  it "should omit an array of services from exclude list" do
97
103
  exclude = ['two', 'four']
98
104
  expect(provider_class.get_services(provider_class.defpath, exclude).map(&:name)).to eq(@services - exclude)
@@ -140,9 +146,9 @@ describe 'Puppet::Type::Service::Provider::Init',
140
146
 
141
147
  describe "when checking valid paths" do
142
148
  it "should discard paths that do not exist" do
143
- expect(File).to receive(:directory?).with(paths[0]).and_return(false)
149
+ expect(Puppet::FileSystem).to receive(:directory?).with(paths[0]).and_return(false)
144
150
  expect(Puppet::FileSystem).to receive(:exist?).with(paths[0]).and_return(false)
145
- expect(File).to receive(:directory?).with(paths[1]).and_return(true)
151
+ expect(Puppet::FileSystem).to receive(:directory?).with(paths[1]).and_return(true)
146
152
 
147
153
  expect(provider.paths).to eq([paths[1]])
148
154
  end
@@ -150,7 +156,7 @@ describe 'Puppet::Type::Service::Provider::Init',
150
156
  it "should discard paths that are not directories" do
151
157
  paths.each do |path|
152
158
  expect(Puppet::FileSystem).to receive(:exist?).with(path).and_return(true)
153
- expect(File).to receive(:directory?).with(path).and_return(false)
159
+ expect(Puppet::FileSystem).to receive(:directory?).with(path).and_return(false)
154
160
  end
155
161
  expect(provider.paths).to be_empty
156
162
  end
@@ -158,7 +164,7 @@ describe 'Puppet::Type::Service::Provider::Init',
158
164
 
159
165
  describe "when searching for the init script" do
160
166
  before :each do
161
- paths.each {|path| expect(File).to receive(:directory?).with(path).and_return(true) }
167
+ paths.each {|path| expect(Puppet::FileSystem).to receive(:directory?).with(path).and_return(true) }
162
168
  end
163
169
 
164
170
  it "should be able to find the init script in the service path" do
@@ -191,9 +197,9 @@ describe 'Puppet::Type::Service::Provider::Init',
191
197
 
192
198
  describe "if the init script is present" do
193
199
  before :each do
194
- allow(File).to receive(:directory?).and_call_original
195
- allow(File).to receive(:directory?).with("/service/path").and_return(true)
196
- allow(File).to receive(:directory?).with("/alt/service/path").and_return(true)
200
+ allow(Puppet::FileSystem).to receive(:directory?).and_call_original
201
+ allow(Puppet::FileSystem).to receive(:directory?).with("/service/path").and_return(true)
202
+ allow(Puppet::FileSystem).to receive(:directory?).with("/alt/service/path").and_return(true)
197
203
  allow(Puppet::FileSystem).to receive(:exist?).with("/service/path/myservice").and_return(true)
198
204
  end
199
205
 
@@ -2,63 +2,56 @@ require 'spec_helper'
2
2
 
3
3
  describe 'Puppet::Type::Service::Provider::Openwrt',
4
4
  unless: Puppet::Util::Platform.windows? || Puppet::Util::Platform.jruby? do
5
+
5
6
  let(:provider_class) { Puppet::Type.type(:service).provider(:openwrt) }
6
7
 
7
8
  let(:resource) do
8
- resource = double('resource')
9
- allow(resource).to receive(:[]).and_return(nil)
10
- allow(resource).to receive(:[]).with(:name).and_return("myservice")
11
- allow(resource).to receive(:[]).with(:path).and_return(["/etc/init.d"])
12
-
13
- resource
9
+ Puppet::Type.type(:service).new(
10
+ :name => 'myservice',
11
+ :path => '/etc/init.d',
12
+ :hasrestart => true,
13
+ )
14
14
  end
15
15
 
16
16
  let(:provider) do
17
17
  provider = provider_class.new
18
- allow(provider).to receive(:get).with(:hasstatus).and_return(false)
19
-
18
+ provider.resource = resource
20
19
  provider
21
20
  end
22
21
 
23
22
  before :each do
24
- allow(resource).to receive(:provider).and_return(provider)
25
- provider.resource = resource
26
-
27
- allow(FileTest).to receive(:file?).with('/etc/rc.common').and_return(true)
28
- allow(FileTest).to receive(:executable?).with('/etc/rc.common').and_return(true)
23
+ resource.provider = provider
29
24
 
30
25
  # All OpenWrt tests operate on the init script directly. It must exist.
31
- allow(File).to receive(:directory?).and_call_original
32
- allow(File).to receive(:directory?).with('/etc/init.d').and_return(true)
26
+ allow(Puppet::FileSystem).to receive(:directory?).and_call_original
27
+ allow(Puppet::FileSystem).to receive(:directory?).with('/etc/init.d').and_return(true)
33
28
 
34
29
  allow(Puppet::FileSystem).to receive(:exist?).with('/etc/init.d/myservice').and_return(true)
35
- allow(FileTest).to receive(:file?).and_call_original
36
- allow(FileTest).to receive(:file?).with('/etc/init.d/myservice').and_return(true)
37
- allow(FileTest).to receive(:executable?).with('/etc/init.d/myservice').and_return(true)
30
+ allow(Puppet::FileSystem).to receive(:file?).and_call_original
31
+ allow(Puppet::FileSystem).to receive(:file?).with('/etc/init.d/myservice').and_return(true)
32
+ allow(Puppet::FileSystem).to receive(:executable?).with('/etc/init.d/myservice').and_return(true)
38
33
  end
39
34
 
40
- operatingsystem = 'openwrt'
41
- it "should be the default provider on #{operatingsystem}" do
42
- expect(Facter).to receive(:value).with(:operatingsystem).and_return(operatingsystem)
35
+ it "should be the default provider on 'openwrt'" do
36
+ expect(Facter).to receive(:value).with(:operatingsystem).and_return('openwrt')
43
37
  expect(provider_class.default?).to be_truthy
44
38
  end
45
39
 
46
40
  # test self.instances
47
41
  describe "when getting all service instances" do
48
- let(:services) {['dnsmasq', 'dropbear', 'firewall', 'led', 'puppet', 'uhttpd' ]}
42
+ let(:services) { ['dnsmasq', 'dropbear', 'firewall', 'led', 'puppet', 'uhttpd' ] }
49
43
 
50
44
  before :each do
51
45
  allow(Dir).to receive(:entries).and_call_original
52
46
  allow(Dir).to receive(:entries).with('/etc/init.d').and_return(services)
53
- allow(FileTest).to receive(:directory?).and_return(true)
54
- allow(FileTest).to receive(:executable?).and_return(true)
47
+ allow(Puppet::FileSystem).to receive(:executable?).and_return(true)
55
48
  end
56
49
 
57
50
  it "should return instances for all services" do
58
51
  services.each do |inst|
59
52
  expect(provider_class).to receive(:new).with(hash_including(:name => inst, :path => '/etc/init.d')).and_return("#{inst}_instance")
60
53
  end
61
- results = services.collect {|x| "#{x}_instance"}
54
+ results = services.collect { |x| "#{x}_instance"}
62
55
  expect(provider_class.instances).to eq(results)
63
56
  end
64
57
  end
@@ -82,14 +75,13 @@ describe 'Puppet::Type::Service::Provider::Openwrt',
82
75
 
83
76
  describe "when running #{method}" do
84
77
  it "should use any provided explicit command" do
85
- allow(resource).to receive(:[]).with(method).and_return("/user/specified/command")
86
- expect(provider).to receive(:execute).with(["/user/specified/command"], any_args)
78
+ resource[method] = '/user/specified/command'
79
+ expect(provider).to receive(:execute).with(['/user/specified/command'], any_args)
87
80
  provider.send(method)
88
81
  end
89
82
 
90
83
  it "should execute the init script with #{method} when no explicit command is provided" do
91
- allow(resource).to receive(:[]).with("has#{method}".intern).and_return(:true)
92
- expect(provider).to receive(:execute).with(['/etc/init.d/myservice', method ], any_args)
84
+ expect(provider).to receive(:execute).with(['/etc/init.d/myservice', method], any_args)
93
85
  provider.send(method)
94
86
  end
95
87
  end
@@ -41,8 +41,9 @@ describe 'Puppet::Type::Service::Provider::Redhat',
41
41
  @services = ['one', 'two', 'three', 'four', 'kudzu', 'functions', 'halt', 'killall', 'single', 'linuxconf', 'boot', 'reboot']
42
42
  @not_services = ['functions', 'halt', 'killall', 'single', 'linuxconf', 'reboot', 'boot']
43
43
  allow(Dir).to receive(:entries).and_return(@services)
44
- allow(FileTest).to receive(:directory?).and_return(true)
45
- allow(FileTest).to receive(:executable?).and_return(true)
44
+ allow(Puppet::FileSystem).to receive(:directory?).and_call_original
45
+ allow(Puppet::FileSystem).to receive(:directory?).with('/etc/init.d').and_return(true)
46
+ allow(Puppet::FileSystem).to receive(:executable?).and_return(true)
46
47
  end
47
48
 
48
49
  it "should return instances for all services" do
@@ -138,6 +138,57 @@ describe Puppet::Transaction::Persistence do
138
138
  persistence = Puppet::Transaction::Persistence.new
139
139
  expect(persistence.load.dig("File[/tmp/audit]", "parameters", "mtime", "system_value")).to contain_exactly(be_a(Time))
140
140
  end
141
+
142
+ it 'should load Regexp' do
143
+ write_state_file(<<~END)
144
+ system_value:
145
+ - !ruby/regexp /regexp/
146
+ END
147
+
148
+ persistence = Puppet::Transaction::Persistence.new
149
+ expect(persistence.load.dig("system_value")).to contain_exactly(be_a(Regexp))
150
+ end
151
+
152
+ it 'should load semantic puppet version' do
153
+ write_state_file(<<~END)
154
+ system_value:
155
+ - !ruby/object:SemanticPuppet::Version
156
+ major: 1
157
+ minor: 0
158
+ patch: 0
159
+ prerelease:
160
+ build:
161
+ END
162
+
163
+ persistence = Puppet::Transaction::Persistence.new
164
+ expect(persistence.load.dig("system_value")).to contain_exactly(be_a(SemanticPuppet::Version))
165
+ end
166
+
167
+ it 'should load puppet time related objects' do
168
+ write_state_file(<<~END)
169
+ system_value:
170
+ - !ruby/object:Puppet::Pops::Time::Timestamp
171
+ nsecs: 1638316135955087259
172
+ - !ruby/object:Puppet::Pops::Time::TimeData
173
+ nsecs: 1495789430910161286
174
+ - !ruby/object:Puppet::Pops::Time::Timespan
175
+ nsecs: 1495789430910161286
176
+ END
177
+
178
+ persistence = Puppet::Transaction::Persistence.new
179
+ expect(persistence.load.dig("system_value")).to contain_exactly(be_a(Puppet::Pops::Time::Timestamp), be_a(Puppet::Pops::Time::TimeData), be_a(Puppet::Pops::Time::Timespan))
180
+ end
181
+
182
+ it 'should load binary objects' do
183
+ write_state_file(<<~END)
184
+ system_value:
185
+ - !ruby/object:Puppet::Pops::Types::PBinaryType::Binary
186
+ binary_buffer: ''
187
+ END
188
+
189
+ persistence = Puppet::Transaction::Persistence.new
190
+ expect(persistence.load.dig("system_value")).to contain_exactly(be_a(Puppet::Pops::Types::PBinaryType::Binary))
191
+ end
141
192
  end
142
193
  end
143
194
 
@@ -27,6 +27,13 @@ describe Puppet::Type.type(:file).attrclass(:group) do
27
27
  expect { group.insync?(5) }.to raise_error(/Could not find group foos/)
28
28
  end
29
29
 
30
+ it "should return false if a group's id can't be found by name in noop" do
31
+ Puppet[:noop] = true
32
+ allow(resource.provider).to receive(:name2gid).and_return(nil)
33
+
34
+ expect(group.insync?('notcreatedyet')).to eq(false)
35
+ end
36
+
30
37
  it "should use the id for comparisons, not the name" do
31
38
  expect(group.insync?('foos')).to be_falsey
32
39
  end
@@ -25,6 +25,13 @@ describe Puppet::Type.type(:file).attrclass(:owner) do
25
25
  expect { owner.insync?(5) }.to raise_error(/Could not find user foo/)
26
26
  end
27
27
 
28
+ it "should return false if an owner's id can't be found by name in noop" do
29
+ Puppet[:noop] = true
30
+ allow(resource.provider).to receive(:name2uid).and_return(nil)
31
+
32
+ expect(owner.insync?('notcreatedyet')).to eq(false)
33
+ end
34
+
28
35
  it "should use the id for comparisons, not the name" do
29
36
  expect(owner.insync?('foo')).to be_falsey
30
37
  end
@@ -174,51 +174,6 @@ describe Puppet::Type.type(:user) do
174
174
  end
175
175
  end
176
176
 
177
- describe "when managing the purge_ssh_keys property" do
178
- context "with valid input" do
179
- it "should support a :true value" do
180
- expect { described_class.new(:name => 'foo', :purge_ssh_keys => :true) }.to_not raise_error
181
- end
182
-
183
- it "should support a :false value" do
184
- expect { described_class.new(:name => 'foo', :purge_ssh_keys => :false) }.to_not raise_error
185
- end
186
-
187
- it "should support a String value" do
188
- expect { described_class.new(:name => 'foo', :purge_ssh_keys => File.expand_path('home/foo/.ssh/authorized_keys')) }.to_not raise_error
189
- end
190
-
191
- it "should support an Array value" do
192
- expect { described_class.new(:name => 'foo', :purge_ssh_keys => [File.expand_path('home/foo/.ssh/authorized_keys'),
193
- File.expand_path('custom/authorized_keys')]) }.to_not raise_error
194
- end
195
- end
196
-
197
- context "with faulty input" do
198
- it "should raise error for relative path" do
199
- expect { described_class.new(:name => 'foo', :purge_ssh_keys => 'home/foo/.ssh/authorized_keys') }.to raise_error(Puppet::ResourceError,
200
- /Paths to keyfiles must be absolute/ )
201
- end
202
-
203
- it "should raise error for invalid type" do
204
- expect { described_class.new(:name => 'foo', :purge_ssh_keys => :invalid) }.to raise_error(Puppet::ResourceError,
205
- /purge_ssh_keys must be true, false, or an array of file names/ )
206
- end
207
-
208
- it "should raise error for array with relative path" do
209
- expect { described_class.new(:name => 'foo', :purge_ssh_keys => ['home/foo/.ssh/authorized_keys',
210
- File.expand_path('custom/authorized_keys')]) }.to raise_error(Puppet::ResourceError,
211
- /Paths to keyfiles must be absolute/ )
212
- end
213
-
214
- it "should raise error for array with invalid type" do
215
- expect { described_class.new(:name => 'foo', :purge_ssh_keys => [:invalid,
216
- File.expand_path('custom/authorized_keys')]) }.to raise_error(Puppet::ResourceError,
217
- /Each entry for purge_ssh_keys must be a string/ )
218
- end
219
- end
220
- end
221
-
222
177
  describe "when managing the uid property" do
223
178
  it "should convert number-looking strings into actual numbers" do
224
179
  expect(described_class.new(:name => 'foo', :uid => '50')[:uid]).to eq(50)
@@ -334,6 +289,73 @@ describe Puppet::Type.type(:user) do
334
289
  end
335
290
  end
336
291
 
292
+ describe "when managing the purge_ssh_keys property" do
293
+ context "with valid input" do
294
+ ['true', :true, true].each do |input|
295
+ it "should support #{input} as value" do
296
+ expect { described_class.new(:name => 'foo', :purge_ssh_keys => input) }.to_not raise_error
297
+ end
298
+ end
299
+
300
+ ['false', :false, false].each do |input|
301
+ it "should support #{input} as value" do
302
+ expect { described_class.new(:name => 'foo', :purge_ssh_keys => input) }.to_not raise_error
303
+ end
304
+ end
305
+
306
+ it "should support a String value" do
307
+ expect { described_class.new(:name => 'foo', :purge_ssh_keys => File.expand_path('home/foo/.ssh/authorized_keys')) }.to_not raise_error
308
+ end
309
+
310
+ it "should support an Array value" do
311
+ expect { described_class.new(:name => 'foo', :purge_ssh_keys => [File.expand_path('home/foo/.ssh/authorized_keys'),
312
+ File.expand_path('custom/authorized_keys')]) }.to_not raise_error
313
+ end
314
+ end
315
+
316
+ context "with faulty input" do
317
+ it "should raise error for relative path" do
318
+ expect { described_class.new(:name => 'foo', :purge_ssh_keys => 'home/foo/.ssh/authorized_keys') }.to raise_error(Puppet::ResourceError,
319
+ /Paths to keyfiles must be absolute/ )
320
+ end
321
+
322
+ it "should raise error for invalid type" do
323
+ expect { described_class.new(:name => 'foo', :purge_ssh_keys => :invalid) }.to raise_error(Puppet::ResourceError,
324
+ /purge_ssh_keys must be true, false, or an array of file names/ )
325
+ end
326
+
327
+ it "should raise error for array with relative path" do
328
+ expect { described_class.new(:name => 'foo', :purge_ssh_keys => ['home/foo/.ssh/authorized_keys',
329
+ File.expand_path('custom/authorized_keys')]) }.to raise_error(Puppet::ResourceError,
330
+ /Paths to keyfiles must be absolute/ )
331
+ end
332
+
333
+ it "should raise error for array with invalid type" do
334
+ expect { described_class.new(:name => 'foo', :purge_ssh_keys => [:invalid,
335
+ File.expand_path('custom/authorized_keys')]) }.to raise_error(Puppet::ResourceError,
336
+ /Each entry for purge_ssh_keys must be a string/ )
337
+ end
338
+ end
339
+
340
+ context "homedir retrieval" do
341
+ it "should accept the home provided" do
342
+ expect(Puppet).not_to receive(:debug).with("User 'foo' does not exist")
343
+ described_class.new(:name => 'foo', :purge_ssh_keys => true, :home => '/my_home')
344
+ end
345
+
346
+ it "should accept the home provided" do
347
+ expect(Dir).to receive(:home).with('foo').and_return('/my_home')
348
+ expect(Puppet).not_to receive(:debug).with("User 'foo' does not exist")
349
+ described_class.new(:name => 'foo', :purge_ssh_keys => true)
350
+ end
351
+
352
+ it "should output debug message when home directory cannot be retrieved" do
353
+ allow(Dir).to receive(:home).with('foo').and_raise(ArgumentError)
354
+ expect(Puppet).to receive(:debug).with("User 'foo' does not exist")
355
+ described_class.new(:name => 'foo', :purge_ssh_keys => true)
356
+ end
357
+ end
358
+ end
337
359
 
338
360
  describe "when managing expiry" do
339
361
  it "should fail if given an invalid date" do