puppet 6.19.1 → 6.20.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

Files changed (171) hide show
  1. checksums.yaml +4 -4
  2. data/CODEOWNERS +2 -16
  3. data/Gemfile +2 -0
  4. data/Gemfile.lock +30 -25
  5. data/lib/puppet/application.rb +10 -6
  6. data/lib/puppet/application/agent.rb +1 -0
  7. data/lib/puppet/application/apply.rb +3 -2
  8. data/lib/puppet/application/device.rb +1 -0
  9. data/lib/puppet/application/filebucket.rb +2 -2
  10. data/lib/puppet/application/script.rb +1 -0
  11. data/lib/puppet/application_support.rb +7 -0
  12. data/lib/puppet/configurer.rb +28 -18
  13. data/lib/puppet/defaults.rb +24 -18
  14. data/lib/puppet/environments.rb +38 -54
  15. data/lib/puppet/face/config.rb +10 -0
  16. data/lib/puppet/face/epp.rb +12 -2
  17. data/lib/puppet/face/facts.rb +60 -0
  18. data/lib/puppet/ffi/posix.rb +10 -0
  19. data/lib/puppet/ffi/posix/constants.rb +14 -0
  20. data/lib/puppet/ffi/posix/functions.rb +24 -0
  21. data/lib/puppet/functions/epp.rb +1 -0
  22. data/lib/puppet/functions/inline_epp.rb +1 -0
  23. data/lib/puppet/indirector/fact_search.rb +60 -0
  24. data/lib/puppet/indirector/facts/json.rb +27 -0
  25. data/lib/puppet/indirector/facts/yaml.rb +3 -58
  26. data/lib/puppet/indirector/json.rb +5 -1
  27. data/lib/puppet/indirector/node/json.rb +8 -0
  28. data/lib/puppet/indirector/report/json.rb +34 -0
  29. data/lib/puppet/module_tool/applications/installer.rb +48 -2
  30. data/lib/puppet/module_tool/errors/shared.rb +17 -2
  31. data/lib/puppet/network/formats.rb +2 -1
  32. data/lib/puppet/pal/pal_impl.rb +70 -17
  33. data/lib/puppet/parser/ast/leaf.rb +3 -2
  34. data/lib/puppet/parser/templatewrapper.rb +1 -1
  35. data/lib/puppet/pops/evaluator/deferred_resolver.rb +5 -3
  36. data/lib/puppet/pops/evaluator/evaluator_impl.rb +22 -3
  37. data/lib/puppet/pops/model/ast_transformer.rb +1 -1
  38. data/lib/puppet/provider/package/apt.rb +4 -0
  39. data/lib/puppet/provider/user/aix.rb +2 -2
  40. data/lib/puppet/reference/configuration.rb +6 -5
  41. data/lib/puppet/settings.rb +33 -28
  42. data/lib/puppet/settings/alias_setting.rb +37 -0
  43. data/lib/puppet/settings/base_setting.rb +26 -2
  44. data/lib/puppet/util/autoload.rb +1 -8
  45. data/lib/puppet/util/fact_dif.rb +62 -0
  46. data/lib/puppet/util/posix.rb +54 -5
  47. data/lib/puppet/util/rubygems.rb +5 -1
  48. data/lib/puppet/version.rb +1 -1
  49. data/locales/puppet.pot +188 -164
  50. data/man/man5/puppet.conf.5 +6 -6
  51. data/man/man8/puppet-agent.8 +2 -2
  52. data/man/man8/puppet-apply.8 +2 -2
  53. data/man/man8/puppet-catalog.8 +1 -1
  54. data/man/man8/puppet-config.8 +1 -1
  55. data/man/man8/puppet-describe.8 +1 -1
  56. data/man/man8/puppet-device.8 +2 -2
  57. data/man/man8/puppet-doc.8 +1 -1
  58. data/man/man8/puppet-epp.8 +1 -1
  59. data/man/man8/puppet-facts.8 +32 -1
  60. data/man/man8/puppet-filebucket.8 +3 -3
  61. data/man/man8/puppet-generate.8 +1 -1
  62. data/man/man8/puppet-help.8 +1 -1
  63. data/man/man8/puppet-key.8 +1 -1
  64. data/man/man8/puppet-lookup.8 +1 -1
  65. data/man/man8/puppet-man.8 +1 -1
  66. data/man/man8/puppet-module.8 +1 -1
  67. data/man/man8/puppet-node.8 +4 -1
  68. data/man/man8/puppet-parser.8 +1 -1
  69. data/man/man8/puppet-plugin.8 +1 -1
  70. data/man/man8/puppet-report.8 +4 -1
  71. data/man/man8/puppet-resource.8 +1 -1
  72. data/man/man8/puppet-script.8 +2 -2
  73. data/man/man8/puppet-ssl.8 +1 -1
  74. data/man/man8/puppet-status.8 +1 -1
  75. data/man/man8/puppet.8 +2 -2
  76. data/spec/fixtures/integration/application/agent/cached_deferred_catalog.json +91 -0
  77. data/spec/fixtures/unit/provider/user/aix/aix_passwd_file.out +4 -0
  78. data/spec/integration/application/agent_spec.rb +127 -3
  79. data/spec/integration/application/apply_spec.rb +19 -0
  80. data/spec/integration/defaults_spec.rb +0 -7
  81. data/spec/integration/environments/setting_hooks_spec.rb +1 -1
  82. data/spec/integration/resource/type_collection_spec.rb +2 -6
  83. data/spec/integration/transaction_spec.rb +4 -9
  84. data/spec/integration/util/windows/adsi_spec.rb +3 -1
  85. data/spec/integration/util/windows/registry_spec.rb +0 -10
  86. data/spec/lib/puppet_spec/settings.rb +6 -1
  87. data/spec/spec_helper.rb +1 -4
  88. data/spec/unit/agent_spec.rb +8 -6
  89. data/spec/unit/application/agent_spec.rb +0 -1
  90. data/spec/unit/application/config_spec.rb +224 -4
  91. data/spec/unit/application/filebucket_spec.rb +0 -2
  92. data/spec/unit/application_spec.rb +51 -9
  93. data/spec/unit/confine/feature_spec.rb +1 -1
  94. data/spec/unit/confine_spec.rb +8 -2
  95. data/spec/unit/defaults_spec.rb +20 -1
  96. data/spec/unit/environments_spec.rb +96 -19
  97. data/spec/unit/face/config_spec.rb +27 -32
  98. data/spec/unit/face/node_spec.rb +0 -11
  99. data/spec/unit/file_serving/configuration/parser_spec.rb +0 -1
  100. data/spec/unit/file_serving/metadata_spec.rb +3 -3
  101. data/spec/unit/file_serving/terminus_helper_spec.rb +11 -4
  102. data/spec/unit/forge/module_release_spec.rb +2 -7
  103. data/spec/unit/functions/inline_epp_spec.rb +26 -1
  104. data/spec/unit/http/service/compiler_spec.rb +49 -0
  105. data/spec/unit/http/service_spec.rb +1 -1
  106. data/spec/unit/indirector/face_spec.rb +0 -1
  107. data/spec/unit/indirector/facts/facter_spec.rb +0 -1
  108. data/spec/unit/indirector/facts/json_spec.rb +255 -0
  109. data/spec/unit/indirector/file_bucket_file/selector_spec.rb +26 -8
  110. data/spec/unit/indirector/indirection_spec.rb +8 -12
  111. data/spec/unit/indirector/key/file_spec.rb +0 -1
  112. data/spec/unit/indirector/node/json_spec.rb +33 -0
  113. data/spec/{integration/indirector/report/yaml.rb → unit/indirector/report/json_spec.rb} +13 -24
  114. data/spec/unit/indirector/report/yaml_spec.rb +72 -8
  115. data/spec/unit/indirector_spec.rb +2 -2
  116. data/spec/unit/module_tool/applications/installer_spec.rb +66 -0
  117. data/spec/unit/network/authconfig_spec.rb +0 -3
  118. data/spec/unit/network/http/api/indirected_routes_spec.rb +0 -9
  119. data/spec/unit/network/http/handler_spec.rb +0 -5
  120. data/spec/unit/parser/compiler_spec.rb +3 -19
  121. data/spec/unit/parser/resource_spec.rb +14 -8
  122. data/spec/unit/parser/templatewrapper_spec.rb +4 -3
  123. data/spec/unit/pops/evaluator/deferred_resolver_spec.rb +20 -0
  124. data/spec/unit/property_spec.rb +1 -0
  125. data/spec/unit/provider/nameservice_spec.rb +66 -65
  126. data/spec/unit/provider/package/apt_spec.rb +4 -8
  127. data/spec/unit/provider/package/base_spec.rb +6 -5
  128. data/spec/unit/provider/package/pacman_spec.rb +18 -12
  129. data/spec/unit/provider/package/pip_spec.rb +6 -11
  130. data/spec/unit/provider/package/pkgdmg_spec.rb +0 -4
  131. data/spec/unit/provider/user/aix_spec.rb +5 -0
  132. data/spec/unit/provider/user/hpux_spec.rb +1 -1
  133. data/spec/unit/provider/user/pw_spec.rb +2 -0
  134. data/spec/unit/provider/user/useradd_spec.rb +1 -0
  135. data/spec/unit/provider_spec.rb +8 -10
  136. data/spec/unit/puppet_pal_catalog_spec.rb +45 -0
  137. data/spec/unit/resource/capability_finder_spec.rb +6 -1
  138. data/spec/unit/resource/type_spec.rb +1 -1
  139. data/spec/unit/resource_spec.rb +11 -10
  140. data/spec/unit/settings_spec.rb +419 -242
  141. data/spec/unit/ssl/base_spec.rb +0 -1
  142. data/spec/unit/ssl/host_spec.rb +0 -5
  143. data/spec/unit/ssl/ssl_provider_spec.rb +14 -8
  144. data/spec/unit/transaction/additional_resource_generator_spec.rb +3 -7
  145. data/spec/unit/transaction/event_manager_spec.rb +14 -11
  146. data/spec/unit/transaction_spec.rb +13 -4
  147. data/spec/unit/type/file/content_spec.rb +0 -1
  148. data/spec/unit/type/file/selinux_spec.rb +0 -2
  149. data/spec/unit/type/file_spec.rb +0 -6
  150. data/spec/unit/type/group_spec.rb +13 -6
  151. data/spec/unit/type/resources_spec.rb +7 -7
  152. data/spec/unit/type/service_spec.rb +1 -1
  153. data/spec/unit/type/tidy_spec.rb +0 -1
  154. data/spec/unit/type_spec.rb +2 -2
  155. data/spec/unit/util/at_fork_spec.rb +2 -2
  156. data/spec/unit/util/autoload_spec.rb +5 -1
  157. data/spec/unit/util/backups_spec.rb +1 -2
  158. data/spec/unit/util/execution_spec.rb +15 -11
  159. data/spec/unit/util/inifile_spec.rb +6 -14
  160. data/spec/unit/util/log_spec.rb +8 -7
  161. data/spec/unit/util/logging_spec.rb +3 -3
  162. data/spec/unit/util/posix_spec.rb +363 -15
  163. data/spec/unit/util/rubygems_spec.rb +2 -2
  164. data/spec/unit/util/selinux_spec.rb +76 -52
  165. data/spec/unit/util/storage_spec.rb +3 -1
  166. data/spec/unit/util/suidmanager_spec.rb +44 -41
  167. data/spec/unit/util_spec.rb +13 -6
  168. metadata +21 -10
  169. data/spec/integration/application/config_spec.rb +0 -74
  170. data/spec/unit/face/catalog_spec.rb +0 -6
  171. data/spec/unit/face/module_spec.rb +0 -3
@@ -6,6 +6,10 @@ test_aix_user:
6
6
  no_password_user:
7
7
  lastupdate = another_last_update
8
8
 
9
+ tab_password_user:
10
+ password = some_password
11
+ lastupdate = another_last_update
12
+
9
13
  daemon:
10
14
  password = *
11
15
 
@@ -100,10 +100,10 @@ describe "puppet agent", unless: Puppet::Util::Platform.jruby? do
100
100
  end
101
101
 
102
102
  context 'rich data' do
103
- it "applies deferred values" do
103
+ it "calls a deferred 4x function" do
104
104
  catalog_handler = -> (req, res) {
105
105
  catalog = compile_to_catalog(<<-MANIFEST, node)
106
- notify { 'deferred':
106
+ notify { 'deferred4x':
107
107
  message => Deferred('join', [[1,2,3], ':'])
108
108
  }
109
109
  MANIFEST
@@ -118,7 +118,66 @@ describe "puppet agent", unless: Puppet::Util::Platform.jruby? do
118
118
  agent.command_line.args << '--test'
119
119
  agent.run
120
120
  }.to exit_with(2)
121
- .and output(%r{Notice: /Stage\[main\]/Main/Notify\[deferred\]/message: defined 'message' as '1:2:3'}).to_stdout
121
+ .and output(%r{Notice: /Stage\[main\]/Main/Notify\[deferred4x\]/message: defined 'message' as '1:2:3'}).to_stdout
122
+ end
123
+ end
124
+
125
+ it "calls a deferred 3x function" do
126
+ catalog_handler = -> (req, res) {
127
+ catalog = compile_to_catalog(<<-MANIFEST, node)
128
+ notify { 'deferred3x':
129
+ message => Deferred('sprintf', ['%s', 'I am deferred'])
130
+ }
131
+ MANIFEST
132
+
133
+ res.body = formatter.render(catalog)
134
+ res['Content-Type'] = formatter.mime
135
+ }
136
+
137
+ server.start_server(mounts: {catalog: catalog_handler}) do |port|
138
+ Puppet[:serverport] = port
139
+ expect {
140
+ agent.command_line.args << '--test'
141
+ agent.run
142
+ }.to exit_with(2)
143
+ .and output(%r{Notice: /Stage\[main\]/Main/Notify\[deferred3x\]/message: defined 'message' as 'I am deferred'}).to_stdout
144
+ end
145
+ end
146
+
147
+ it "re-evaluates a deferred function in a cached catalog" do
148
+ Puppet[:report] = false
149
+ Puppet[:use_cached_catalog] = true
150
+ Puppet[:usecacheonfailure] = false
151
+
152
+ catalog_dir = File.join(Puppet[:client_datadir], 'catalog')
153
+ Puppet::FileSystem.mkpath(catalog_dir)
154
+ cached_catalog_path = "#{File.join(catalog_dir, Puppet[:certname])}.json"
155
+
156
+ # our catalog contains a deferred function that calls `binary_file`
157
+ # to read `source`. The function returns a Binary object, whose
158
+ # base64 value is printed to stdout
159
+ source = tmpfile('deferred_source')
160
+ catalog = File.read(my_fixture('cached_deferred_catalog.json'))
161
+ catalog.gsub!('__SOURCE_PATH__', source)
162
+ File.write(cached_catalog_path, catalog)
163
+
164
+ # verify we get a different result each time the deferred function
165
+ # is evaluated, and reads `source`.
166
+ {
167
+ '1234' => 'MTIzNA==',
168
+ '5678' => 'NTY3OA=='
169
+ }.each_pair do |content, base64|
170
+ File.write(source, content)
171
+
172
+ expect {
173
+ agent.command_line.args << '-t'
174
+ agent.run
175
+
176
+ }.to exit_with(2)
177
+ .and output(/Notice: #{base64}/).to_stdout
178
+
179
+ # reset state so we can run again
180
+ Puppet::Application.clear!
122
181
  end
123
182
  end
124
183
 
@@ -476,4 +535,69 @@ describe "puppet agent", unless: Puppet::Util::Platform.jruby? do
476
535
  th.kill # kill thread so we don't wait too much
477
536
  end
478
537
  end
538
+
539
+ context 'cached catalogs' do
540
+ it 'falls back to a cached catalog' do
541
+ catalog_handler = -> (req, res) {
542
+ catalog = compile_to_catalog(<<-MANIFEST, node)
543
+ notify { 'a message': }
544
+ MANIFEST
545
+
546
+ res.body = formatter.render(catalog)
547
+ res['Content-Type'] = formatter.mime
548
+ }
549
+
550
+ server.start_server(mounts: {catalog: catalog_handler}) do |port|
551
+ Puppet[:serverport] = port
552
+ expect {
553
+ agent.command_line.args << '--test'
554
+ agent.run
555
+ }.to exit_with(2)
556
+ .and output(%r{Caching catalog for #{Puppet[:certname]}}).to_stdout
557
+ end
558
+
559
+ # reset state so we can run again
560
+ Puppet::Application.clear!
561
+
562
+ # --test above turns off `usecacheonfailure` so re-enable here
563
+ Puppet[:usecacheonfailure] = true
564
+
565
+ # run agent without server
566
+ expect {
567
+ agent.command_line.args << '--no-daemonize' << '--onetime' << '--server' << '127.0.0.1'
568
+ agent.run
569
+ }.to exit_with(2)
570
+ .and output(a_string_matching(
571
+ /Using cached catalog from environment 'production'/
572
+ ).and matching(
573
+ /Notify\[a message\]\/message:/
574
+ )).to_stdout
575
+ .and output(/the agent run will continue/).to_stderr
576
+ end
577
+
578
+ it 'preserves the old cached catalog if validation fails with the old one' do
579
+ catalog_handler = -> (req, res) {
580
+ catalog = compile_to_catalog(<<-MANIFEST, node)
581
+ exec { 'unqualified_command': }
582
+ MANIFEST
583
+
584
+ res.body = formatter.render(catalog)
585
+ res['Content-Type'] = formatter.mime
586
+ }
587
+
588
+ server.start_server(mounts: {catalog: catalog_handler}) do |port|
589
+ Puppet[:serverport] = port
590
+ expect {
591
+ agent.command_line.args << '--test'
592
+ agent.run
593
+ }.to exit_with(1)
594
+ .and output(/Using configured environment/).to_stdout
595
+ .and output(%r{Validation of Exec\[unqualified_command\] failed: 'unqualified_command' is not qualified and no path was specified}).to_stderr
596
+ end
597
+
598
+ # cached catalog should not be updated
599
+ cached_catalog = "#{File.join(Puppet[:client_datadir], 'catalog', Puppet[:certname])}.json"
600
+ expect(File).to_not be_exist(cached_catalog)
601
+ end
602
+ end
479
603
  end
@@ -663,4 +663,23 @@ class amod::bad_type {
663
663
  end
664
664
  end
665
665
  end
666
+
667
+ context 'rich data' do
668
+ it "calls a deferred 4x function" do
669
+ apply.command_line.args = ['-e', 'notify { "deferred3x": message => Deferred("join", [[1,2,3], ":"]) }']
670
+
671
+ expect {
672
+ apply.run
673
+ }.to exit_with(0) # for some reason apply returns 0 instead of 2
674
+ .and output(%r{Notice: /Stage\[main\]/Main/Notify\[deferred3x\]/message: defined 'message' as '1:2:3'}).to_stdout
675
+ end
676
+
677
+ it "calls a deferred 3x function" do
678
+ apply.command_line.args = ['-e', 'notify { "deferred4x": message => Deferred("sprintf", ["%s", "I am deferred"]) }']
679
+ expect {
680
+ apply.run
681
+ }.to exit_with(0) # for some reason apply returns 0 instead of 2
682
+ .and output(%r{Notice: /Stage\[main\]/Main/Notify\[deferred4x\]/message: defined 'message' as 'I am deferred'}).to_stdout
683
+ end
684
+ end
666
685
  end
@@ -36,13 +36,6 @@ describe "Puppet defaults" do
36
36
  end
37
37
  end
38
38
 
39
- describe "when setting the :serverport" do
40
- it "should also set the :masterport to the same value" do
41
- Puppet.settings[:serverport] = 9000
42
- expect(Puppet.settings[:masterport]).to eq(9000)
43
- end
44
- end
45
-
46
39
  describe "when setting the :factpath" do
47
40
  it "should add the :factpath to Facter's search paths" do
48
41
  expect(Facter).to receive(:search).with("/my/fact/path")
@@ -12,7 +12,7 @@ describe "setting hooks" do
12
12
  end
13
13
 
14
14
  it "accesses correct directory environment settings after initializing a setting with an on_write hook" do
15
- expect(Puppet.settings.setting(:certname).call_hook).to eq(:on_write_only)
15
+ expect(Puppet.settings.setting(:strict).call_hook).to eq(:on_write_only)
16
16
 
17
17
  File.open(File.join(confdir, "puppet.conf"), "w:UTF-8") do |f|
18
18
  f.puts("environmentpath=#{environmentpath}")
@@ -11,12 +11,8 @@ describe Puppet::Resource::TypeCollection do
11
11
  @dir = tmpfile("autoload_testing")
12
12
  FileUtils.mkdir_p @dir
13
13
 
14
- loader = Object.new
15
- allow(loader).to receive(:load).and_return(nil)
16
- allow(loader).to receive(:set_entry)
17
-
18
- loaders = Object.new
19
- expect(loaders).to receive(:runtime3_type_loader).at_most(:once).and_return(loader)
14
+ loader = double('loader', load: nil, set_entry: nil)
15
+ loaders = double('loaders', runtime3_type_loader: loader)
20
16
  expect(Puppet::Pops::Loaders).to receive(:loaders).at_most(:once).and_return(loaders)
21
17
 
22
18
  environment = Puppet::Node::Environment.create(:env, [@dir])
@@ -61,7 +61,7 @@ describe Puppet::Transaction do
61
61
 
62
62
  transaction = Puppet::Transaction.new(catalog, nil, Puppet::Graph::SequentialPrioritizer.new)
63
63
 
64
- expect(resource).not_to receive(:evaluate)
64
+ expect(resource).not_to receive(:retrieve)
65
65
 
66
66
  transaction.evaluate
67
67
  end
@@ -86,7 +86,7 @@ describe Puppet::Transaction do
86
86
 
87
87
  transaction = Puppet::Transaction.new(catalog, nil, Puppet::Graph::SequentialPrioritizer.new)
88
88
 
89
- expect(resource).not_to receive(:evaluate)
89
+ expect(resource).not_to receive(:retrieve)
90
90
 
91
91
  transaction.evaluate
92
92
  end
@@ -315,16 +315,14 @@ describe Puppet::Transaction do
315
315
  file1 = tmpfile("file1")
316
316
  file2 = tmpfile("file2")
317
317
 
318
+ expect(Puppet::FileSystem).to_not be_exist(file2)
319
+
318
320
  exec1 = Puppet::Type.type(:exec).new(
319
321
  :name => "exec1",
320
322
  :path => ENV["PATH"],
321
323
  :command => touch(file1),
322
324
  )
323
325
 
324
- allow(exec1).to receive(:eval_generate).and_return(
325
- [ Puppet::Type.type(:notify).new(:name => "eval1_notify") ]
326
- )
327
-
328
326
  exec2 = Puppet::Type.type(:exec).new(
329
327
  :name => "exec2",
330
328
  :path => ENV["PATH"],
@@ -332,9 +330,6 @@ describe Puppet::Transaction do
332
330
  :refreshonly => true,
333
331
  :subscribe => exec1,
334
332
  )
335
- allow(exec2).to receive(:eval_generate).and_return(
336
- [ Puppet::Type.type(:notify).new(:name => "eval2_notify") ]
337
- )
338
333
 
339
334
  Puppet[:tags] = "exec"
340
335
  catalog = mk_catalog(exec1, exec2)
@@ -157,7 +157,9 @@ describe Puppet::Util::Windows::ADSI::Group,
157
157
 
158
158
  # touch the native_object member to have it lazily loaded, so COM objects can be stubbed
159
159
  admins.native_object
160
- allow(admins.native_object).to receive(:Members).and_return(members)
160
+ without_partial_double_verification do
161
+ allow(admins.native_object).to receive(:Members).and_return(members)
162
+ end
161
163
 
162
164
  # well-known NULL SID
163
165
  expect(admins.members[0].sid).to eq('S-1-0-0')
@@ -146,16 +146,6 @@ describe Puppet::Util::Windows::Registry do
146
146
  utf_8_bytes = ENDASH_UTF_8 + TM_UTF_8
147
147
  utf_8_str = utf_8_bytes.pack('c*').force_encoding(Encoding::UTF_8)
148
148
 
149
- # this problematic Ruby codepath triggers a conversion of UTF-16LE to
150
- # a local codepage which can totally break when that codepage has no
151
- # conversion from the given UTF-16LE characters to local codepage
152
- # a prime example is that IBM437 has no conversion from a Unicode en-dash
153
- expect(Win32::Registry).not_to receive(:export_string)
154
-
155
- # also, expect that we're using our variants of keys / values, not Rubys
156
- expect(Win32::Registry).not_to receive(:each_key)
157
- expect(Win32::Registry).not_to receive(:each_value)
158
-
159
149
  hklm.create("#{puppet_key}\\#{subkey_name}", Win32::Registry::KEY_ALL_ACCESS | regsam) do |reg|
160
150
  reg.write("#{guid}", Win32::Registry::REG_SZ, utf_16_str)
161
151
 
@@ -12,7 +12,12 @@ module PuppetSpec::Settings
12
12
  :codedir => { :type => :directory, :default => "test", :desc => "codedir" },
13
13
  :vardir => { :type => :directory, :default => "test", :desc => "vardir" },
14
14
  :rundir => { :type => :directory, :default => "test", :desc => "rundir" },
15
- }
15
+ }.freeze
16
+
17
+ TEST_APP_DEFAULT_VALUES = TEST_APP_DEFAULT_DEFINITIONS.inject({}) do |memo, (key, value)|
18
+ memo[key] = value[:default]
19
+ memo
20
+ end.freeze
16
21
 
17
22
  def set_puppet_conf(confdir, settings)
18
23
  write_file(File.join(confdir, "puppet.conf"), settings)
@@ -84,10 +84,7 @@ RSpec.configure do |config|
84
84
  config.filter_run_when_matching :focus
85
85
 
86
86
  config.mock_with :rspec do |mocks|
87
- # We really should have this on, but it breaks a _lot_ of tests. We'll
88
- # need to go through and fix those tests first before it can be enabled
89
- # for real.
90
- mocks.verify_partial_doubles = false
87
+ mocks.verify_partial_doubles = true
91
88
  end
92
89
 
93
90
  tmpdir = Puppet::FileSystem.expand_path(Dir.mktmpdir("rspecrun"))
@@ -3,9 +3,13 @@ require 'puppet/agent'
3
3
  require 'puppet/configurer'
4
4
 
5
5
  class AgentTestClient
6
- def run
6
+ def initialize(transaction_uuid = nil, job_id = nil)
7
+ end
8
+
9
+ def run(client_args)
7
10
  # no-op
8
11
  end
12
+
9
13
  def stop
10
14
  # no-op
11
15
  end
@@ -51,11 +55,10 @@ describe Puppet::Agent do
51
55
 
52
56
  it "should create an instance of its client class and run it when asked to run" do
53
57
  client = double('client')
54
- expect(AgentTestClient).to receive(:new).and_return(client)
55
-
56
- expect(client).to receive(:run)
58
+ allow(AgentTestClient).to receive(:new).with(nil, nil).and_return(client)
57
59
 
58
60
  allow(@agent).to receive(:disabled?).and_return(false)
61
+ expect(client).to receive(:run)
59
62
  @agent.run
60
63
  end
61
64
 
@@ -92,7 +95,6 @@ describe Puppet::Agent do
92
95
 
93
96
  describe "when being run" do
94
97
  before do
95
- allow(AgentTestClient).to receive(:lockfile_path).and_return("/my/lock")
96
98
  allow(@agent).to receive(:disabled?).and_return(false)
97
99
  end
98
100
 
@@ -188,7 +190,7 @@ describe Puppet::Agent do
188
190
  allow(lockfile).to receive(:lock).and_return(false)
189
191
  end
190
192
 
191
- it "should notify that a run is already in progres" do
193
+ it "should notify that a run is already in progress" do
192
194
  client = AgentTestClient.new
193
195
  expect(AgentTestClient).to receive(:new).and_return(client)
194
196
  expect(Puppet).to receive(:notice).with(/Run of .* already in progress; skipping .* exists/)
@@ -202,7 +202,6 @@ describe Puppet::Application::Agent do
202
202
  allow(Puppet::Resource::Catalog.indirection).to receive(:terminus_class=)
203
203
  allow(Puppet::Resource::Catalog.indirection).to receive(:cache_class=)
204
204
  allow(Puppet::Node::Facts.indirection).to receive(:terminus_class=)
205
- allow(Puppet).to receive(:settraps)
206
205
  end
207
206
 
208
207
  it "should not run with extra arguments" do
@@ -1,12 +1,232 @@
1
+ # coding: utf-8
1
2
  require 'spec_helper'
2
3
  require 'puppet/application/config'
3
4
 
4
5
  describe Puppet::Application::Config do
5
- it "should be a subclass of Puppet::Application::FaceBase" do
6
- expect(Puppet::Application::Config.superclass).to equal(Puppet::Application::FaceBase)
6
+ include PuppetSpec::Files
7
+
8
+ # different UTF-8 widths
9
+ # 1-byte A
10
+ # 2-byte ۿ - http://www.fileformat.info/info/unicode/char/06ff/index.htm - 0xDB 0xBF / 219 191
11
+ # 3-byte ᚠ - http://www.fileformat.info/info/unicode/char/16A0/index.htm - 0xE1 0x9A 0xA0 / 225 154 160
12
+ # 4-byte 𠜎 - http://www.fileformat.info/info/unicode/char/2070E/index.htm - 0xF0 0xA0 0x9C 0x8E / 240 160 156 142
13
+ MIXED_UTF8 = "A\u06FF\u16A0\u{2070E}" # Aۿᚠ𠜎
14
+
15
+ let(:app) { Puppet::Application[:config] }
16
+
17
+ before :each do
18
+ Puppet[:config] = tmpfile('config')
19
+ end
20
+
21
+ def initialize_app(args)
22
+ app.command_line.args = args
23
+ # ensure global defaults are initialized prior to app defaults
24
+ Puppet.initialize_settings(args)
25
+ end
26
+
27
+ def read_utf8(path)
28
+ File.read(path, :encoding => 'UTF-8')
29
+ end
30
+
31
+ def write_utf8(path, content)
32
+ File.write(path, content, 0, :encoding => 'UTF-8')
33
+ end
34
+
35
+ context "when printing" do
36
+ it "prints a value" do
37
+ initialize_app(%w[print certname])
38
+
39
+ expect {
40
+ app.run
41
+ }.to exit_with(0)
42
+ .and output(a_string_matching(Puppet[:certname])).to_stdout
43
+ end
44
+
45
+ it "prints a value from a section" do
46
+ File.write(Puppet[:config], <<~END)
47
+ [main]
48
+ external_nodes=none
49
+ [server]
50
+ external_nodes=exec
51
+ END
52
+
53
+ initialize_app(%w[print external_nodes --section server])
54
+
55
+ expect {
56
+ app.run
57
+ }.to exit_with(0)
58
+ .and output(a_string_matching('exec')).to_stdout
59
+ end
60
+
61
+ it "doesn't require the environment to exist" do
62
+ initialize_app(%w[print certname --environment doesntexist])
63
+
64
+ expect {
65
+ app.run
66
+ }.to exit_with(0)
67
+ .and output(a_string_matching(Puppet[:certname])).to_stdout
68
+ end
7
69
  end
8
70
 
9
- it "should set `environment_mode` to :not_required" do
10
- expect(Puppet::Application::Config.get_environment_mode).to equal(:not_required)
71
+ context "when setting" do
72
+ it "sets a value in its config file" do
73
+ initialize_app(%w[set certname www.example.com])
74
+
75
+ expect {
76
+ app.run
77
+ }.to exit_with(0)
78
+
79
+ expect(File.read(Puppet[:config])).to eq("[main]\ncertname = www.example.com\n")
80
+ end
81
+
82
+ it "sets a value in the server section" do
83
+ initialize_app(%w[set external_nodes exec --section server])
84
+
85
+ expect {
86
+ app.run
87
+ }.to exit_with(0)
88
+
89
+ expect(File.read(Puppet[:config])).to eq("[server]\nexternal_nodes = exec\n")
90
+ end
91
+
92
+ {
93
+ %w[certname WWW.EXAMPLE.COM] => /Certificate names must be lower case/,
94
+ %w[log_level all] => /Invalid loglevel all/,
95
+ %w[disable_warnings true] => /Cannot disable unrecognized warning types 'true'/,
96
+ %w[strict on] => /Invalid value 'on' for parameter strict/,
97
+ %w[digest_algorithm rot13] => /Invalid value 'rot13' for parameter digest_algorithm/,
98
+ %w[http_proxy_password a#b] => /Passwords set in the http_proxy_password setting must be valid as part of a URL/,
99
+ }.each_pair do |args, message|
100
+ it "rejects #{args.join(' ')}" do
101
+ initialize_app(['set', *args])
102
+
103
+ expect {
104
+ app.run
105
+ }.to exit_with(1)
106
+ .and output(message).to_stderr
107
+ end
108
+ end
109
+
110
+ it 'sets unknown settings' do
111
+ initialize_app(['set', 'notarealsetting', 'true'])
112
+
113
+ expect {
114
+ app.run
115
+ }.to exit_with(0)
116
+
117
+ expect(File.read(Puppet[:config])).to eq("[main]\nnotarealsetting = true\n")
118
+ end
119
+ end
120
+
121
+ context "when deleting" do
122
+ it "deletes a value" do
123
+ initialize_app(%w[delete external_nodes])
124
+
125
+ File.write(Puppet[:config], <<~END)
126
+ [main]
127
+ external_nodes=none
128
+ END
129
+
130
+ expect {
131
+ app.run
132
+ }.to exit_with(0)
133
+ .and output(/Deleted setting from 'main': 'external_nodes=none'/).to_stdout
134
+
135
+ expect(File.read(Puppet[:config])).to eq("[main]\n")
136
+ end
137
+
138
+ it "warns when deleting a value that isn't set" do
139
+ initialize_app(%w[delete external_nodes])
140
+
141
+ File.write(Puppet[:config], "")
142
+
143
+ expect {
144
+ app.run
145
+ }.to exit_with(0)
146
+ .and output(a_string_matching("Warning: No setting found in configuration file for section 'main' setting name 'external_nodes'")).to_stderr
147
+
148
+ expect(File.read(Puppet[:config])).to eq("")
149
+ end
150
+
151
+ it "deletes a value from main" do
152
+ initialize_app(%w[delete external_nodes])
153
+
154
+ File.write(Puppet[:config], <<~END)
155
+ [main]
156
+ external_nodes=none
157
+ END
158
+
159
+ expect {
160
+ app.run
161
+ }.to exit_with(0)
162
+ .and output(/Deleted setting from 'main': 'external_nodes=none'/).to_stdout
163
+
164
+ expect(File.read(Puppet[:config])).to eq("[main]\n")
165
+ end
166
+
167
+ it "deletes a value from main a section" do
168
+ initialize_app(%w[delete external_nodes --section server])
169
+
170
+ File.write(Puppet[:config], <<~END)
171
+ [main]
172
+ external_nodes=none
173
+ [server]
174
+ external_nodes=exec
175
+ END
176
+
177
+ expect {
178
+ app.run
179
+ }.to exit_with(0)
180
+ .and output(/Deleted setting from 'server': 'external_nodes'/).to_stdout
181
+
182
+ expect(File.read(Puppet[:config])).to eq("[main]\nexternal_nodes=none\n[server]\n")
183
+ end
184
+ end
185
+
186
+ context "when managing UTF-8 values" do
187
+ it "reads a UTF-8 value" do
188
+ write_utf8(Puppet[:config], <<~EOF)
189
+ [main]
190
+ tags=#{MIXED_UTF8}
191
+ EOF
192
+
193
+ initialize_app(%w[print tags])
194
+
195
+ expect {
196
+ app.run
197
+ }.to exit_with(0)
198
+ .and output("#{MIXED_UTF8}\n").to_stdout
199
+ end
200
+
201
+ it "sets a UTF-8 value" do
202
+ initialize_app(['set', 'tags', MIXED_UTF8])
203
+
204
+ expect {
205
+ app.run
206
+ }.to exit_with(0)
207
+
208
+ expect(read_utf8(Puppet[:config])).to eq(<<~EOF)
209
+ [main]
210
+ tags = #{MIXED_UTF8}
211
+ EOF
212
+ end
213
+
214
+ it "deletes a UTF-8 value" do
215
+ initialize_app(%w[delete tags])
216
+
217
+ write_utf8(Puppet[:config], <<~EOF)
218
+ [main]
219
+ tags=#{MIXED_UTF8}
220
+ EOF
221
+
222
+ expect {
223
+ app.run
224
+ }.to exit_with(0)
225
+ .and output(/Deleted setting from 'main': 'tags=#{MIXED_UTF8}'/).to_stdout
226
+
227
+ expect(read_utf8(Puppet[:config])).to eq(<<~EOF)
228
+ [main]
229
+ EOF
230
+ end
11
231
  end
12
232
  end