puppet 7.12.1-x64-mingw32 → 7.13.1-x64-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +13 -8
  4. data/ext/project_data.yaml +1 -1
  5. data/lib/puppet/application/lookup.rb +72 -24
  6. data/lib/puppet/concurrent/thread_local_singleton.rb +5 -3
  7. data/lib/puppet/defaults.rb +3 -1
  8. data/lib/puppet/file_serving/metadata.rb +3 -0
  9. data/lib/puppet/file_system/file_impl.rb +7 -7
  10. data/lib/puppet/file_system/jruby.rb +1 -1
  11. data/lib/puppet/file_system/path_pattern.rb +10 -15
  12. data/lib/puppet/file_system/uniquefile.rb +1 -1
  13. data/lib/puppet/file_system/windows.rb +4 -4
  14. data/lib/puppet/file_system.rb +1 -1
  15. data/lib/puppet/functions/versioncmp.rb +6 -2
  16. data/lib/puppet/graph/simple_graph.rb +2 -1
  17. data/lib/puppet/pops/parser/code_merger.rb +4 -4
  18. data/lib/puppet/pops/parser/egrammar.ra +2 -0
  19. data/lib/puppet/pops/parser/eparser.rb +574 -558
  20. data/lib/puppet/pops/serialization/to_data_converter.rb +6 -18
  21. data/lib/puppet/pops/validation/checker4_0.rb +7 -2
  22. data/lib/puppet/provider/service/init.rb +5 -4
  23. data/lib/puppet/ssl/verifier.rb +3 -1
  24. data/lib/puppet/transaction/persistence.rb +22 -12
  25. data/lib/puppet/type/file/data_sync.rb +1 -1
  26. data/lib/puppet/type/file/group.rb +8 -1
  27. data/lib/puppet/type/file/owner.rb +8 -1
  28. data/lib/puppet/type/user.rb +40 -38
  29. data/lib/puppet/util/json.rb +17 -0
  30. data/lib/puppet/util/log.rb +7 -2
  31. data/lib/puppet/util/monkey_patches.rb +26 -2
  32. data/lib/puppet/util/package.rb +25 -16
  33. data/lib/puppet/util/yaml.rb +11 -0
  34. data/lib/puppet/version.rb +1 -1
  35. data/lib/puppet.rb +1 -0
  36. data/locales/puppet.pot +115 -93
  37. data/man/man5/puppet.conf.5 +10 -2
  38. data/man/man8/puppet-agent.8 +1 -1
  39. data/man/man8/puppet-apply.8 +1 -1
  40. data/man/man8/puppet-catalog.8 +1 -1
  41. data/man/man8/puppet-config.8 +1 -1
  42. data/man/man8/puppet-describe.8 +1 -1
  43. data/man/man8/puppet-device.8 +1 -1
  44. data/man/man8/puppet-doc.8 +1 -1
  45. data/man/man8/puppet-epp.8 +1 -1
  46. data/man/man8/puppet-facts.8 +1 -1
  47. data/man/man8/puppet-filebucket.8 +1 -1
  48. data/man/man8/puppet-generate.8 +1 -1
  49. data/man/man8/puppet-help.8 +1 -1
  50. data/man/man8/puppet-lookup.8 +9 -6
  51. data/man/man8/puppet-module.8 +1 -1
  52. data/man/man8/puppet-node.8 +1 -1
  53. data/man/man8/puppet-parser.8 +1 -1
  54. data/man/man8/puppet-plugin.8 +1 -1
  55. data/man/man8/puppet-report.8 +1 -1
  56. data/man/man8/puppet-resource.8 +1 -1
  57. data/man/man8/puppet-script.8 +1 -1
  58. data/man/man8/puppet-ssl.8 +1 -1
  59. data/man/man8/puppet.8 +2 -2
  60. data/spec/fixtures/unit/forge/bacula.json +1 -1
  61. data/spec/integration/application/lookup_spec.rb +29 -6
  62. data/spec/integration/parser/pcore_resource_spec.rb +10 -0
  63. data/spec/shared_contexts/l10n.rb +5 -0
  64. data/spec/unit/application/lookup_spec.rb +131 -10
  65. data/spec/unit/concurrent/thread_local_singleton_spec.rb +39 -0
  66. data/spec/unit/file_system/uniquefile_spec.rb +7 -1
  67. data/spec/unit/file_system_spec.rb +34 -4
  68. data/spec/unit/forge/module_release_spec.rb +3 -3
  69. data/spec/unit/functions/versioncmp_spec.rb +40 -4
  70. data/spec/unit/pops/parser/parse_containers_spec.rb +2 -2
  71. data/spec/unit/pops/serialization/to_from_hr_spec.rb +0 -58
  72. data/spec/unit/pops/validator/validator_spec.rb +5 -0
  73. data/spec/unit/provider/service/gentoo_spec.rb +6 -5
  74. data/spec/unit/provider/service/init_spec.rb +15 -9
  75. data/spec/unit/provider/service/openwrt_spec.rb +21 -29
  76. data/spec/unit/provider/service/redhat_spec.rb +3 -2
  77. data/spec/unit/transaction/persistence_spec.rb +51 -0
  78. data/spec/unit/type/file/group_spec.rb +7 -0
  79. data/spec/unit/type/file/owner_spec.rb +7 -0
  80. data/spec/unit/type/user_spec.rb +0 -45
  81. data/spec/unit/util/json_spec.rb +126 -0
  82. data/spec/unit/util/yaml_spec.rb +37 -13
  83. metadata +14 -4
@@ -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)
@@ -0,0 +1,126 @@
1
+ # coding: utf-8
2
+ require 'spec_helper'
3
+ require 'puppet/util/json'
4
+
5
+ describe Puppet::Util::Json do
6
+ include PuppetSpec::Files
7
+
8
+ shared_examples_for 'json file loader' do |load_method|
9
+ it 'reads a JSON file from disk' do
10
+ file_path = file_containing('input', JSON.dump({ "my" => "data" }))
11
+
12
+ expect(load_method.call(file_path)).to eq({ "my" => "data" })
13
+ end
14
+
15
+ it 'reads JSON as UTF-8' do
16
+ file_path = file_containing('input', JSON.dump({ "my" => "𠜎" }))
17
+
18
+ expect(load_method.call(file_path)).to eq({ "my" => "𠜎" })
19
+ end
20
+ end
21
+
22
+ context "#load" do
23
+ it 'raises an error if JSON is invalid' do
24
+ expect {
25
+ Puppet::Util::Json.load('{ invalid')
26
+ }.to raise_error(Puppet::Util::Json::ParseError, /unexpected token at '{ invalid'/)
27
+ end
28
+
29
+ it 'raises an error if the content is empty' do
30
+ expect {
31
+ Puppet::Util::Json.load('')
32
+ }.to raise_error(Puppet::Util::Json::ParseError)
33
+ end
34
+
35
+ it 'loads true' do
36
+ expect(Puppet::Util::Json.load('true')).to eq(true)
37
+ end
38
+
39
+ it 'loads false' do
40
+ expect(Puppet::Util::Json.load('false')).to eq(false)
41
+ end
42
+
43
+ it 'loads a numeric' do
44
+ expect(Puppet::Util::Json.load('42')).to eq(42)
45
+ end
46
+
47
+ it 'loads a string' do
48
+ expect(Puppet::Util::Json.load('"puppet"')).to eq('puppet')
49
+ end
50
+
51
+ it 'loads an array' do
52
+ expect(Puppet::Util::Json.load(<<~JSON)).to eq([1, 2])
53
+ [1, 2]
54
+ JSON
55
+ end
56
+
57
+ it 'loads a hash' do
58
+ expect(Puppet::Util::Json.load(<<~JSON)).to eq('a' => 1, 'b' => 2)
59
+ {
60
+ "a": 1,
61
+ "b": 2
62
+ }
63
+ JSON
64
+ end
65
+ end
66
+
67
+ context "load_file_if_valid" do
68
+ before do
69
+ Puppet[:log_level] = 'debug'
70
+ end
71
+
72
+ it_should_behave_like 'json file loader', Puppet::Util::Json.method(:load_file_if_valid)
73
+
74
+ it 'returns nil when the file is invalid JSON and debug logs about it' do
75
+ file_path = file_containing('input', '{ invalid')
76
+ expect(Puppet).to receive(:debug)
77
+ .with(/Could not retrieve JSON content .+: unexpected token at '{ invalid'/).and_call_original
78
+
79
+ expect(Puppet::Util::Json.load_file_if_valid(file_path)).to eql(nil)
80
+ end
81
+
82
+ it 'returns nil when the filename is illegal and debug logs about it' do
83
+ expect(Puppet).to receive(:debug)
84
+ .with(/Could not retrieve JSON content .+: pathname contains null byte/).and_call_original
85
+
86
+ expect(Puppet::Util::Json.load_file_if_valid("not\0allowed")).to eql(nil)
87
+ end
88
+
89
+ it 'returns nil when the file does not exist and debug logs about it' do
90
+ expect(Puppet).to receive(:debug)
91
+ .with(/Could not retrieve JSON content .+: No such file or directory/).and_call_original
92
+
93
+ expect(Puppet::Util::Json.load_file_if_valid('does/not/exist.json')).to eql(nil)
94
+ end
95
+ end
96
+
97
+ context '#load_file' do
98
+ it_should_behave_like 'json file loader', Puppet::Util::Json.method(:load_file)
99
+
100
+ it 'raises an error when the file is invalid JSON' do
101
+ file_path = file_containing('input', '{ invalid')
102
+
103
+ expect {
104
+ Puppet::Util::Json.load_file(file_path)
105
+ }.to raise_error(Puppet::Util::Json::ParseError, /unexpected token at '{ invalid'/)
106
+ end
107
+
108
+ it 'raises an error when the filename is illegal' do
109
+ expect {
110
+ Puppet::Util::Json.load_file("not\0allowed")
111
+ }.to raise_error(ArgumentError, /null byte/)
112
+ end
113
+
114
+ it 'raises an error when the file does not exist' do
115
+ expect {
116
+ Puppet::Util::Json.load_file('does/not/exist.json')
117
+ }.to raise_error(Errno::ENOENT, /No such file or directory/)
118
+ end
119
+
120
+ it 'writes data formatted as JSON to disk' do
121
+ file_path = file_containing('input', Puppet::Util::Json.dump({ "my" => "data" }))
122
+
123
+ expect(Puppet::Util::Json.load_file(file_path)).to eq({ "my" => "data" })
124
+ end
125
+ end
126
+ end