puppet 6.21.0-x86-mingw32 → 6.24.0-x86-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 (217) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +5 -5
  3. data/Gemfile +1 -1
  4. data/Gemfile.lock +29 -23
  5. data/README.md +4 -4
  6. data/ext/osx/puppet.plist +2 -0
  7. data/ext/project_data.yaml +3 -2
  8. data/lib/puppet.rb +3 -3
  9. data/lib/puppet/application/agent.rb +12 -5
  10. data/lib/puppet/application/apply.rb +2 -1
  11. data/lib/puppet/application/device.rb +2 -1
  12. data/lib/puppet/application/filebucket.rb +1 -0
  13. data/lib/puppet/application/resource.rb +17 -3
  14. data/lib/puppet/application/script.rb +2 -1
  15. data/lib/puppet/application/ssl.rb +12 -0
  16. data/lib/puppet/configurer/downloader.rb +2 -1
  17. data/lib/puppet/defaults.rb +27 -5
  18. data/lib/puppet/environments.rb +26 -1
  19. data/lib/puppet/face/facts.rb +128 -30
  20. data/lib/puppet/face/help/action.erb +1 -0
  21. data/lib/puppet/face/help/face.erb +1 -0
  22. data/lib/puppet/face/node/clean.rb +11 -0
  23. data/lib/puppet/file_serving/fileset.rb +14 -2
  24. data/lib/puppet/file_system/file_impl.rb +1 -1
  25. data/lib/puppet/file_system/memory_file.rb +8 -1
  26. data/lib/puppet/file_system/windows.rb +4 -2
  27. data/lib/puppet/forge.rb +3 -3
  28. data/lib/puppet/functions/all.rb +1 -1
  29. data/lib/puppet/functions/camelcase.rb +1 -1
  30. data/lib/puppet/functions/capitalize.rb +2 -2
  31. data/lib/puppet/functions/downcase.rb +2 -2
  32. data/lib/puppet/functions/empty.rb +8 -0
  33. data/lib/puppet/functions/get.rb +5 -5
  34. data/lib/puppet/functions/group_by.rb +13 -5
  35. data/lib/puppet/functions/lest.rb +1 -1
  36. data/lib/puppet/functions/new.rb +100 -100
  37. data/lib/puppet/functions/partition.rb +12 -4
  38. data/lib/puppet/functions/require.rb +5 -5
  39. data/lib/puppet/functions/sort.rb +3 -3
  40. data/lib/puppet/functions/strftime.rb +1 -0
  41. data/lib/puppet/functions/tree_each.rb +7 -9
  42. data/lib/puppet/functions/type.rb +4 -4
  43. data/lib/puppet/functions/unwrap.rb +17 -2
  44. data/lib/puppet/functions/upcase.rb +2 -2
  45. data/lib/puppet/http/resolver/server_list.rb +15 -4
  46. data/lib/puppet/http/service/compiler.rb +69 -0
  47. data/lib/puppet/http/service/file_server.rb +2 -1
  48. data/lib/puppet/indirector/catalog/compiler.rb +1 -0
  49. data/lib/puppet/indirector/facts/facter.rb +24 -3
  50. data/lib/puppet/indirector/file_metadata/rest.rb +1 -0
  51. data/lib/puppet/indirector/resource/ral.rb +6 -1
  52. data/lib/puppet/interface/documentation.rb +1 -0
  53. data/lib/puppet/module_tool/applications/installer.rb +4 -0
  54. data/lib/puppet/module_tool/errors/shared.rb +17 -0
  55. data/lib/puppet/network/formats.rb +67 -0
  56. data/lib/puppet/network/http/factory.rb +4 -0
  57. data/lib/puppet/parser/functions/fqdn_rand.rb +14 -6
  58. data/lib/puppet/pops/types/p_sem_ver_type.rb +8 -2
  59. data/lib/puppet/pops/types/p_sensitive_type.rb +10 -0
  60. data/lib/puppet/pops/types/type_mismatch_describer.rb +1 -1
  61. data/lib/puppet/provider/exec/posix.rb +16 -4
  62. data/lib/puppet/provider/package/dnfmodule.rb +1 -1
  63. data/lib/puppet/provider/package/nim.rb +11 -6
  64. data/lib/puppet/provider/package/pip.rb +15 -3
  65. data/lib/puppet/provider/parsedfile.rb +3 -0
  66. data/lib/puppet/provider/service/systemd.rb +14 -4
  67. data/lib/puppet/provider/service/windows.rb +38 -0
  68. data/lib/puppet/provider/user/directoryservice.rb +25 -12
  69. data/lib/puppet/provider/user/useradd.rb +9 -2
  70. data/lib/puppet/reference/configuration.rb +1 -1
  71. data/lib/puppet/settings.rb +30 -7
  72. data/lib/puppet/settings/environment_conf.rb +1 -0
  73. data/lib/puppet/transaction/additional_resource_generator.rb +1 -1
  74. data/lib/puppet/type/exec.rb +16 -3
  75. data/lib/puppet/type/file.rb +19 -1
  76. data/lib/puppet/type/file/mode.rb +6 -0
  77. data/lib/puppet/type/file/selcontext.rb +1 -1
  78. data/lib/puppet/type/service.rb +18 -38
  79. data/lib/puppet/type/tidy.rb +22 -3
  80. data/lib/puppet/type/user.rb +38 -20
  81. data/lib/puppet/util/fact_dif.rb +36 -17
  82. data/lib/puppet/util/monkey_patches.rb +7 -0
  83. data/lib/puppet/util/selinux.rb +30 -4
  84. data/lib/puppet/util/symbolic_file_mode.rb +29 -17
  85. data/lib/puppet/util/windows/adsi.rb +46 -0
  86. data/lib/puppet/util/windows/api_types.rb +1 -1
  87. data/lib/puppet/util/windows/principal.rb +9 -2
  88. data/lib/puppet/util/windows/sid.rb +6 -2
  89. data/lib/puppet/version.rb +1 -1
  90. data/locales/puppet.pot +360 -280
  91. data/man/man5/puppet.conf.5 +279 -251
  92. data/man/man8/puppet-agent.8 +1 -1
  93. data/man/man8/puppet-apply.8 +1 -1
  94. data/man/man8/puppet-catalog.8 +9 -9
  95. data/man/man8/puppet-config.8 +1 -1
  96. data/man/man8/puppet-describe.8 +1 -1
  97. data/man/man8/puppet-device.8 +1 -1
  98. data/man/man8/puppet-doc.8 +1 -1
  99. data/man/man8/puppet-epp.8 +1 -1
  100. data/man/man8/puppet-facts.8 +65 -7
  101. data/man/man8/puppet-filebucket.8 +1 -1
  102. data/man/man8/puppet-generate.8 +1 -1
  103. data/man/man8/puppet-help.8 +1 -1
  104. data/man/man8/puppet-key.8 +7 -7
  105. data/man/man8/puppet-lookup.8 +1 -1
  106. data/man/man8/puppet-man.8 +1 -1
  107. data/man/man8/puppet-module.8 +1 -1
  108. data/man/man8/puppet-node.8 +5 -5
  109. data/man/man8/puppet-parser.8 +1 -1
  110. data/man/man8/puppet-plugin.8 +1 -1
  111. data/man/man8/puppet-report.8 +5 -5
  112. data/man/man8/puppet-resource.8 +1 -1
  113. data/man/man8/puppet-script.8 +1 -1
  114. data/man/man8/puppet-ssl.8 +5 -1
  115. data/man/man8/puppet-status.8 +4 -4
  116. data/man/man8/puppet.8 +2 -2
  117. data/spec/fixtures/ssl/127.0.0.1-key.pem +107 -57
  118. data/spec/fixtures/ssl/127.0.0.1.pem +52 -31
  119. data/spec/fixtures/ssl/bad-basic-constraints.pem +57 -35
  120. data/spec/fixtures/ssl/bad-int-basic-constraints.pem +57 -35
  121. data/spec/fixtures/ssl/ca.pem +57 -35
  122. data/spec/fixtures/ssl/crl.pem +28 -18
  123. data/spec/fixtures/ssl/ec-key.pem +11 -11
  124. data/spec/fixtures/ssl/ec.pem +33 -24
  125. data/spec/fixtures/ssl/encrypted-ec-key.pem +12 -12
  126. data/spec/fixtures/ssl/encrypted-key.pem +108 -58
  127. data/spec/fixtures/ssl/intermediate-agent-crl.pem +28 -19
  128. data/spec/fixtures/ssl/intermediate-agent.pem +57 -36
  129. data/spec/fixtures/ssl/intermediate-crl.pem +31 -21
  130. data/spec/fixtures/ssl/intermediate.pem +57 -36
  131. data/spec/fixtures/ssl/oid-key.pem +117 -0
  132. data/spec/fixtures/ssl/oid.pem +69 -0
  133. data/spec/fixtures/ssl/pluto-key.pem +107 -57
  134. data/spec/fixtures/ssl/pluto.pem +52 -30
  135. data/spec/fixtures/ssl/request-key.pem +107 -57
  136. data/spec/fixtures/ssl/request.pem +47 -26
  137. data/spec/fixtures/ssl/revoked-key.pem +107 -57
  138. data/spec/fixtures/ssl/revoked.pem +52 -30
  139. data/spec/fixtures/ssl/signed-key.pem +107 -57
  140. data/spec/fixtures/ssl/signed.pem +52 -30
  141. data/spec/fixtures/ssl/tampered-cert.pem +52 -30
  142. data/spec/fixtures/ssl/tampered-csr.pem +47 -26
  143. data/spec/fixtures/ssl/trusted_oid_mapping.yaml +5 -0
  144. data/spec/fixtures/ssl/unknown-127.0.0.1-key.pem +107 -57
  145. data/spec/fixtures/ssl/unknown-127.0.0.1.pem +50 -29
  146. data/spec/fixtures/ssl/unknown-ca-key.pem +107 -57
  147. data/spec/fixtures/ssl/unknown-ca.pem +55 -33
  148. data/spec/fixtures/unit/provider/service/systemd/list_unit_files_services_vendor_preset +9 -0
  149. data/spec/integration/application/filebucket_spec.rb +11 -0
  150. data/spec/integration/application/module_spec.rb +21 -0
  151. data/spec/integration/application/plugin_spec.rb +1 -1
  152. data/spec/integration/application/resource_spec.rb +64 -0
  153. data/spec/integration/application/ssl_spec.rb +20 -0
  154. data/spec/integration/environments/settings_interpolation_spec.rb +0 -4
  155. data/spec/integration/http/client_spec.rb +12 -0
  156. data/spec/integration/indirector/direct_file_server_spec.rb +1 -3
  157. data/spec/integration/indirector/facts/facter_spec.rb +90 -36
  158. data/spec/integration/type/exec_spec.rb +70 -45
  159. data/spec/integration/util/windows/adsi_spec.rb +18 -0
  160. data/spec/integration/util/windows/principal_spec.rb +21 -0
  161. data/spec/integration/util/windows/registry_spec.rb +6 -0
  162. data/spec/lib/puppet/test_ca.rb +7 -2
  163. data/spec/lib/puppet_spec/settings.rb +1 -0
  164. data/spec/spec_helper.rb +11 -1
  165. data/spec/unit/application/agent_spec.rb +7 -2
  166. data/spec/unit/application/facts_spec.rb +482 -3
  167. data/spec/unit/application/ssl_spec.rb +23 -0
  168. data/spec/unit/configurer/downloader_spec.rb +6 -0
  169. data/spec/unit/configurer_spec.rb +23 -0
  170. data/spec/unit/defaults_spec.rb +16 -0
  171. data/spec/unit/environments_spec.rb +199 -88
  172. data/spec/unit/face/facts_spec.rb +4 -0
  173. data/spec/unit/file_serving/fileset_spec.rb +60 -0
  174. data/spec/unit/file_system_spec.rb +15 -0
  175. data/spec/unit/functions/assert_type_spec.rb +1 -1
  176. data/spec/unit/functions/empty_spec.rb +10 -0
  177. data/spec/unit/functions/unwrap_spec.rb +8 -0
  178. data/spec/unit/functions4_spec.rb +2 -2
  179. data/spec/unit/gettext/config_spec.rb +12 -0
  180. data/spec/unit/http/service/compiler_spec.rb +123 -0
  181. data/spec/unit/indirector/catalog/compiler_spec.rb +14 -10
  182. data/spec/unit/indirector/facts/facter_spec.rb +95 -0
  183. data/spec/unit/indirector/resource/ral_spec.rb +40 -75
  184. data/spec/unit/module_tool/applications/installer_spec.rb +12 -0
  185. data/spec/unit/network/formats_spec.rb +41 -0
  186. data/spec/unit/network/http/factory_spec.rb +19 -0
  187. data/spec/unit/parser/functions/fqdn_rand_spec.rb +15 -1
  188. data/spec/unit/parser/templatewrapper_spec.rb +12 -2
  189. data/spec/unit/pops/types/p_sem_ver_type_spec.rb +18 -0
  190. data/spec/unit/pops/types/p_sensitive_type_spec.rb +18 -0
  191. data/spec/unit/provider/package/dnfmodule_spec.rb +10 -1
  192. data/spec/unit/provider/package/nim_spec.rb +42 -0
  193. data/spec/unit/provider/package/pip_spec.rb +37 -0
  194. data/spec/unit/provider/parsedfile_spec.rb +10 -0
  195. data/spec/unit/provider/service/init_spec.rb +1 -0
  196. data/spec/unit/provider/service/openwrt_spec.rb +3 -1
  197. data/spec/unit/provider/service/systemd_spec.rb +53 -8
  198. data/spec/unit/provider/service/windows_spec.rb +202 -0
  199. data/spec/unit/provider/user/directoryservice_spec.rb +67 -35
  200. data/spec/unit/provider/user/useradd_spec.rb +21 -6
  201. data/spec/unit/resource/catalog_spec.rb +1 -1
  202. data/spec/unit/settings_spec.rb +97 -56
  203. data/spec/unit/ssl/state_machine_spec.rb +19 -5
  204. data/spec/unit/transaction/additional_resource_generator_spec.rb +0 -2
  205. data/spec/unit/transaction_spec.rb +18 -20
  206. data/spec/unit/type/exec_spec.rb +76 -29
  207. data/spec/unit/type/file/selinux_spec.rb +3 -3
  208. data/spec/unit/type/file/source_spec.rb +4 -4
  209. data/spec/unit/type/service_spec.rb +59 -188
  210. data/spec/unit/type/tidy_spec.rb +24 -7
  211. data/spec/unit/type/user_spec.rb +45 -0
  212. data/spec/unit/util/selinux_spec.rb +87 -16
  213. data/spec/unit/util/windows/sid_spec.rb +41 -0
  214. data/tasks/generate_cert_fixtures.rake +12 -3
  215. metadata +24 -9
  216. data/spec/lib/matchers/include.rb +0 -27
  217. data/spec/lib/matchers/include_spec.rb +0 -32
@@ -71,4 +71,8 @@ CONF
71
71
  log.message =~ /Uploading facts for '.*' to 'puppet\.server\.test'/}
72
72
  end
73
73
  end
74
+
75
+ describe "#show" do
76
+ it { is_expected.to be_action :show }
77
+ end
74
78
  end
@@ -46,6 +46,13 @@ describe Puppet::FileServing::Fileset do
46
46
  expect(set.recurselimit).to eq(3)
47
47
  end
48
48
 
49
+ it "accepts a 'max_files' option" do
50
+ expect(Puppet::FileSystem).to receive(:lstat).with(somefile).and_return(double('stat'))
51
+ set = Puppet::FileServing::Fileset.new(somefile, :recurselimit => 3, :max_files => 100)
52
+ expect(set.recurselimit).to eq(3)
53
+ expect(set.max_files).to eq(100)
54
+ end
55
+
49
56
  it "accepts an 'ignore' option" do
50
57
  expect(Puppet::FileSystem).to receive(:lstat).with(somefile).and_return(double('stat'))
51
58
  set = Puppet::FileServing::Fileset.new(somefile, :ignore => ".svn")
@@ -160,6 +167,29 @@ describe Puppet::FileServing::Fileset do
160
167
  end
161
168
  end
162
169
 
170
+ def mock_big_dir_structure(path, stat_method = :lstat)
171
+ allow(Puppet::FileSystem).to receive(stat_method).with(path).and_return(@dirstat)
172
+
173
+ # Keep track of the files we're stubbing.
174
+ @files = %w{.}
175
+
176
+ top_names = (1..10).map {|i| "dir_#{i}" }
177
+ sub_names = (1..100).map {|i| "file__#{i}" }
178
+
179
+ allow(Dir).to receive(:entries).with(path, encoding: Encoding::UTF_8).and_return(top_names)
180
+ top_names.each do |subdir|
181
+ @files << subdir # relative path
182
+ subpath = File.join(path, subdir)
183
+ allow(Puppet::FileSystem).to receive(stat_method).with(subpath).and_return(@dirstat)
184
+ allow(Dir).to receive(:entries).with(subpath, encoding: Encoding::UTF_8).and_return(sub_names)
185
+ sub_names.each do |file|
186
+ @files << File.join(subdir, file) # relative path
187
+ subfile_path = File.join(subpath, file)
188
+ allow(Puppet::FileSystem).to receive(stat_method).with(subfile_path).and_return(@filestat)
189
+ end
190
+ end
191
+ end
192
+
163
193
  def setup_mocks_for_dir(mock_dir, base_path)
164
194
  path = File.join(base_path, mock_dir.name)
165
195
  allow(Puppet::FileSystem).to receive(:lstat).with(path).and_return(MockStat.new(path, true))
@@ -258,6 +288,36 @@ describe Puppet::FileServing::Fileset do
258
288
  expect(@fileset.files.find { |file| file.include?("0") }).to be_nil
259
289
  end
260
290
 
291
+ it "raises exception if number of files is greater than :max_files" do
292
+ mock_dir_structure(@path)
293
+ @fileset.recurse = true
294
+ @fileset.max_files = 22
295
+ expect { @fileset.files }.to raise_error(Puppet::Error, "The directory '#{@path}' contains 28 entries, which exceeds the limit of 22 specified by the max_files parameter for this resource. The limit may be increased, but be aware that large number of file resources can result in excessive resource consumption and degraded performance. Consider using an alternate method to manage large directory trees")
296
+ end
297
+
298
+ it "logs a warning if number of files is greater than soft max_files limit of 1000" do
299
+ mock_big_dir_structure(@path)
300
+ @fileset.recurse = true
301
+ expect(Puppet).to receive(:warning).with("The directory '#{@path}' contains 1010 entries, which exceeds the default soft limit 1000 and may cause excessive resource consumption and degraded performance. To remove this warning set a value for `max_files` parameter or consider using an alternate method to manage large directory trees")
302
+ expect { @fileset.files }.to_not raise_error
303
+ end
304
+
305
+ it "does not emit a warning if max_files is -1" do
306
+ mock_big_dir_structure(@path)
307
+ @fileset.recurse = true
308
+ @fileset.max_files = -1
309
+ expect(Puppet).to receive(:warning).never
310
+ @fileset.files
311
+ end
312
+
313
+ it "does not emit a warning if max_files is `-1`(string)" do
314
+ mock_big_dir_structure(@path)
315
+ @fileset.recurse = true
316
+ @fileset.max_files = '-1'
317
+ expect(Puppet).to receive(:warning).never
318
+ @fileset.files
319
+ end
320
+
261
321
  it "ignores files that match a pattern given as a boolean" do
262
322
  mock_dir_structure(@path)
263
323
  @fileset.recurse = true
@@ -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
@@ -999,6 +1005,15 @@ describe "Puppet::FileSystem" do
999
1005
  Puppet::FileSystem.replace_file(dest, 0755) { |_| }
1000
1006
  }.to raise_error(ArgumentError, /Only modes 0644, 0640, 0660, and 0440 are allowed/)
1001
1007
  end
1008
+
1009
+ it 'falls back to fully qualified user name when sid retrieval fails' do
1010
+ current_user_sid = Puppet::Util::Windows::SID.name_to_sid(Puppet::Util::Windows::ADSI::User.current_user_name)
1011
+ allow(Puppet::Util::Windows::SID).to receive(:name_to_sid).with(Puppet::Util::Windows::ADSI::User.current_user_name).and_return(nil, current_user_sid)
1012
+ allow(Puppet::Util::Windows::SID).to receive(:name_to_sid).with(Puppet::Util::Windows::ADSI::User.current_sam_compatible_user_name).and_call_original
1013
+
1014
+ Puppet::FileSystem.replace_file(dest, 0644) { |f| f.write(content) }
1015
+ expects_public_file(dest)
1016
+ end
1002
1017
  end
1003
1018
  end
1004
1019
 
@@ -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)
@@ -27,6 +27,18 @@ describe Puppet::GettextConfig do
27
27
  Puppet::GettextConfig.delete_all_text_domains
28
28
  end
29
29
 
30
+ # These tests assume gettext is enabled, but it will be disabled when the
31
+ # first time the `Puppet[:disable_i18n]` setting is resolved
32
+ around(:each) do |example|
33
+ disabled = Puppet::GettextConfig.instance_variable_get(:@gettext_disabled)
34
+ Puppet::GettextConfig.instance_variable_set(:@gettext_disabled, false)
35
+ begin
36
+ example.run
37
+ ensure
38
+ Puppet::GettextConfig.instance_variable_set(:@gettext_disabled, disabled)
39
+ end
40
+ end
41
+
30
42
  describe 'setting and getting the locale' do
31
43
  it 'should return "en" when gettext is unavailable' do
32
44
  allow(Puppet::GettextConfig).to receive(:gettext_loaded?).and_return(false)
@@ -1,3 +1,4 @@
1
+
1
2
  # coding: utf-8
2
3
  require 'spec_helper'
3
4
  require 'puppet/http'
@@ -258,6 +259,128 @@ describe Puppet::HTTP::Service::Compiler do
258
259
  end
259
260
  end
260
261
 
262
+ context 'when posting for a v4 catalog' do
263
+ let(:uri) {"https://compiler.example.com:8140/puppet/v4/catalog"}
264
+ let(:persistence) {{ facts: true, catalog: true }}
265
+ let(:facts) {{ 'foo' => 'bar' }}
266
+ let(:trusted_facts) {{}}
267
+ let(:uuid) { "ec3d2844-b236-4287-b0ad-632fbb4d1ff0" }
268
+ let(:job_id) { "1" }
269
+ let(:payload) {{
270
+ environment: environment,
271
+ persistence: persistence,
272
+ facts: facts,
273
+ trusted_facts: trusted_facts,
274
+ transaction_uuid: uuid,
275
+ job_id: job_id,
276
+ options: {
277
+ prefer_requested_environment: false,
278
+ capture_logs: false
279
+ }
280
+ }}
281
+ let(:serialized_catalog) {{ 'catalog' => catalog.to_data_hash }.to_json}
282
+ let(:catalog_response) {{ body: serialized_catalog, headers: {'Content-Type' => formatter.mime }}}
283
+
284
+ it 'includes default HTTP headers' do
285
+ stub_request(:post, uri).with do |request|
286
+ expect(request.headers).to include({'X-Puppet-Version' => /./, 'User-Agent' => /./})
287
+ expect(request.headers).to_not include('X-Puppet-Profiling')
288
+ end.to_return(**catalog_response)
289
+
290
+ subject.post_catalog4(certname, **payload)
291
+ end
292
+
293
+ it 'defaults the server and port based on settings' do
294
+ Puppet[:server] = 'compiler2.example.com'
295
+ Puppet[:serverport] = 8141
296
+
297
+ stub_request(:post, "https://compiler2.example.com:8141/puppet/v4/catalog")
298
+ .to_return(**catalog_response)
299
+
300
+ subject.post_catalog4(certname, **payload)
301
+ end
302
+
303
+ it 'includes puppet headers set via the :http_extra_headers and :profile settings' do
304
+ stub_request(:post, uri).with(headers: {'Example-Header' => 'real-thing', 'another' => 'thing', 'X-Puppet-Profiling' => 'true'}).
305
+ to_return(**catalog_response)
306
+
307
+ Puppet[:http_extra_headers] = 'Example-Header:real-thing,another:thing'
308
+ Puppet[:profile] = true
309
+
310
+ subject.post_catalog4(certname, **payload)
311
+ end
312
+
313
+ it 'returns a deserialized catalog' do
314
+ stub_request(:post, uri)
315
+ .to_return(**catalog_response)
316
+
317
+ _, cat, _ = subject.post_catalog4(certname, **payload)
318
+ expect(cat).to be_a(Puppet::Resource::Catalog)
319
+ expect(cat.name).to eq(certname)
320
+ end
321
+
322
+ it 'returns the request response' do
323
+ stub_request(:post, uri)
324
+ .to_return(**catalog_response)
325
+
326
+ resp, _, _ = subject.post_catalog4(certname, **payload)
327
+ expect(resp).to be_a(Puppet::HTTP::Response)
328
+ end
329
+
330
+ it 'raises a response error if unsuccessful' do
331
+ stub_request(:post, uri)
332
+ .to_return(status: [500, "Server Error"])
333
+
334
+ expect {
335
+ subject.post_catalog4(certname, **payload)
336
+ }.to raise_error do |err|
337
+ expect(err).to be_an_instance_of(Puppet::HTTP::ResponseError)
338
+ expect(err.message).to eq('Server Error')
339
+ expect(err.response.code).to eq(500)
340
+ end
341
+ end
342
+
343
+ it 'raises a response error when server response is not JSON' do
344
+ stub_request(:post, uri)
345
+ .to_return(body: "this isn't valid JSON", headers: {'Content-Type' => 'application/json'})
346
+
347
+ expect {
348
+ subject.post_catalog4(certname, **payload)
349
+ }.to raise_error do |err|
350
+ expect(err).to be_an_instance_of(Puppet::HTTP::SerializationError)
351
+ expect(err.message).to match(/Failed to deserialize catalog from puppetserver response/)
352
+ end
353
+ end
354
+
355
+ it 'raises a response error when server response a JSON serialized catalog' do
356
+ stub_request(:post, uri)
357
+ .to_return(body: {oops: 'bad response data'}.to_json, headers: {'Content-Type' => 'application/json'})
358
+
359
+ expect {
360
+ subject.post_catalog4(certname, **payload)
361
+ }.to raise_error do |err|
362
+ expect(err).to be_an_instance_of(Puppet::HTTP::SerializationError)
363
+ expect(err.message).to match(/Failed to deserialize catalog from puppetserver response/)
364
+ end
365
+ end
366
+
367
+ it 'raises ArgumentError when the `persistence` hash does not contain required keys' do
368
+ payload[:persistence].delete(:facts)
369
+ expect { subject.post_catalog4(certname, **payload) }.to raise_error do |err|
370
+ expect(err).to be_an_instance_of(ArgumentError)
371
+ expect(err.message).to match(/The 'persistence' hash is missing the keys: facts/)
372
+ end
373
+ end
374
+
375
+ it 'raises ArgumentError when `facts` are not a Hash' do
376
+ payload[:facts] = Puppet::Node::Facts.new(certname)
377
+ expect { subject.post_catalog4(certname, **payload) }.to raise_error do |err|
378
+ expect(err).to be_an_instance_of(ArgumentError)
379
+ expect(err.message).to match(/Facts must be a Hash not a Puppet::Node::Facts/)
380
+ end
381
+ end
382
+ end
383
+
261
384
  context 'when getting a node' do
262
385
  let(:uri) { %r{/puppet/v3/node/ziggy} }
263
386
  let(:node_response) { { body: formatter.render(node), headers: {'Content-Type' => formatter.mime } } }
@@ -909,9 +909,10 @@ describe Puppet::Resource::Catalog::Compiler do
909
909
  it "inlines child metadata" do
910
910
  catalog = compile_to_catalog(<<-MANIFEST, node)
911
911
  file { '#{path}':
912
- ensure => directory,
913
- recurse => true,
914
- source => '#{source_dir}'
912
+ ensure => directory,
913
+ recurse => true,
914
+ source => '#{source_dir}',
915
+ max_files => 1234,
915
916
  }
916
917
  MANIFEST
917
918
 
@@ -925,6 +926,7 @@ describe Puppet::Resource::Catalog::Compiler do
925
926
  :source_permissions => :ignore,
926
927
  :recurse => true,
927
928
  :recurselimit => nil,
929
+ :max_files => 1234,
928
930
  :ignore => nil,
929
931
  }
930
932
  expect(Puppet::FileServing::Metadata.indirection).to receive(:search).with(source_dir, options).and_return([metadata, child_metadata])
@@ -938,14 +940,15 @@ describe Puppet::Resource::Catalog::Compiler do
938
940
  it "uses resource parameters when inlining metadata" do
939
941
  catalog = compile_to_catalog(<<-MANIFEST, node)
940
942
  file { '#{path}':
941
- ensure => directory,
942
- recurse => true,
943
- source => '#{source_dir}',
944
- checksum => sha256,
943
+ ensure => directory,
944
+ recurse => true,
945
+ source => '#{source_dir}',
946
+ checksum => sha256,
945
947
  source_permissions => use_when_creating,
946
- recurselimit => 2,
947
- ignore => 'foo.+',
948
- links => follow,
948
+ recurselimit => 2,
949
+ max_files => 4321,
950
+ ignore => 'foo.+',
951
+ links => follow,
949
952
  }
950
953
  MANIFEST
951
954
 
@@ -956,6 +959,7 @@ describe Puppet::Resource::Catalog::Compiler do
956
959
  :source_permissions => :use_when_creating,
957
960
  :recurse => true,
958
961
  :recurselimit => 2,
962
+ :max_files => 4321,
959
963
  :ignore => 'foo.+',
960
964
  }
961
965
  expect(Puppet::FileServing::Metadata.indirection).to receive(:search).with(source_dir, options).and_return([metadata, child_metadata])
@@ -28,6 +28,7 @@ describe Puppet::Node::Facts::Facter do
28
28
  @request = double('request', :key => @name)
29
29
  @environment = double('environment')
30
30
  allow(@request).to receive(:environment).and_return(@environment)
31
+ allow(@request).to receive(:options).and_return({})
31
32
  allow(@request.environment).to receive(:modules).and_return([])
32
33
  allow(@request.environment).to receive(:modulepath).and_return([])
33
34
  end
@@ -104,6 +105,7 @@ describe Puppet::Node::Facts::Facter do
104
105
  expect(FileTest).to receive(:directory?).with(factpath1).and_return(true)
105
106
  expect(FileTest).to receive(:directory?).with(factpath2).and_return(true)
106
107
  allow(@request.environment).to receive(:modulepath).and_return([modulepath])
108
+ allow(@request).to receive(:options).and_return({})
107
109
  expect(Dir).to receive(:glob).with("#{modulepath}/*/lib/facter").and_return([modulelibfacter])
108
110
  expect(Dir).to receive(:glob).with("#{modulepath}/*/plugins/facter").and_return([modulepluginsfacter])
109
111
 
@@ -149,4 +151,97 @@ describe Puppet::Node::Facts::Facter do
149
151
  Puppet::Node::Facts::Facter.setup_external_search_paths @request
150
152
  end
151
153
  end
154
+
155
+ describe 'when :resolve_options is true' do
156
+ let(:options) { { resolve_options: true, user_query: ["os", "timezone"], show_legacy: true } }
157
+ let(:facts) { Puppet::Node::Facts.new("foo") }
158
+
159
+ before :each do
160
+ allow(@request).to receive(:options).and_return(options)
161
+ allow(Puppet::Node::Facts).to receive(:new).and_return(facts)
162
+ allow(facts).to receive(:add_local_facts)
163
+ end
164
+
165
+ it 'should call Facter.resolve method' do
166
+ expect(Facter).to receive(:resolve).with("os timezone --show-legacy")
167
+ @facter.find(@request)
168
+ end
169
+
170
+ it 'should NOT add local facts' do
171
+ expect(facts).not_to receive(:add_local_facts)
172
+
173
+ @facter.find(@request)
174
+ end
175
+
176
+ describe 'when Facter version is lower than 4.0.40' do
177
+ before :each do
178
+ allow(Facter).to receive(:respond_to?).and_return(false)
179
+ allow(Facter).to receive(:respond_to?).with(:resolve).and_return(false)
180
+ end
181
+
182
+ it 'raises an error' do
183
+ expect { @facter.find(@request) }.to raise_error(Puppet::Error, "puppet facts show requires version 4.0.40 or greater of Facter.")
184
+ end
185
+ end
186
+
187
+ describe 'when setting up external search paths' do
188
+ let(:options) { { resolve_options: true, user_query: ["os", "timezone"], external_dir: 'some/dir' } }
189
+ let(:pluginfactdest) { File.expand_path 'plugin/dest' }
190
+ let(:modulepath) { File.expand_path 'module/foo' }
191
+ let(:modulefactsd) { File.expand_path 'module/foo/facts.d' }
192
+
193
+ before :each do
194
+ expect(FileTest).to receive(:directory?).with(pluginfactdest).and_return(true)
195
+ mod = Puppet::Module.new('foo', modulepath, @request.environment)
196
+ allow(@request.environment).to receive(:modules).and_return([mod])
197
+ Puppet[:pluginfactdest] = pluginfactdest
198
+ end
199
+
200
+ it 'should skip files' do
201
+ expect(File).to receive(:directory?).with(modulefactsd).and_return(false)
202
+ expect(Facter).to receive(:search_external).with([pluginfactdest, options[:external_dir]])
203
+ Puppet::Node::Facts::Facter.setup_external_search_paths @request
204
+ end
205
+
206
+ it 'should add directories' do
207
+ expect(File).to receive(:directory?).with(modulefactsd).and_return(true)
208
+ expect(Facter).to receive(:search_external).with([modulefactsd, pluginfactdest, options[:external_dir]])
209
+ Puppet::Node::Facts::Facter.setup_external_search_paths @request
210
+ end
211
+ end
212
+
213
+ describe 'when setting up search paths' do
214
+ let(:factpath1) { File.expand_path 'one' }
215
+ let(:factpath2) { File.expand_path 'two' }
216
+ let(:factpath) { [factpath1, factpath2].join(File::PATH_SEPARATOR) }
217
+ let(:modulepath) { File.expand_path 'module/foo' }
218
+ let(:modulelibfacter) { File.expand_path 'module/foo/lib/facter' }
219
+ let(:modulepluginsfacter) { File.expand_path 'module/foo/plugins/facter' }
220
+ let(:options) { { resolve_options: true, custom_dir: 'some/dir' } }
221
+
222
+ before :each do
223
+ expect(FileTest).to receive(:directory?).with(factpath1).and_return(true)
224
+ expect(FileTest).to receive(:directory?).with(factpath2).and_return(true)
225
+ allow(@request.environment).to receive(:modulepath).and_return([modulepath])
226
+ expect(Dir).to receive(:glob).with("#{modulepath}/*/lib/facter").and_return([modulelibfacter])
227
+ expect(Dir).to receive(:glob).with("#{modulepath}/*/plugins/facter").and_return([modulepluginsfacter])
228
+
229
+ Puppet[:factpath] = factpath
230
+ end
231
+
232
+ it 'should skip files' do
233
+ expect(FileTest).to receive(:directory?).with(modulelibfacter).and_return(false)
234
+ expect(FileTest).to receive(:directory?).with(modulepluginsfacter).and_return(false)
235
+ expect(Facter).to receive(:search).with(factpath1, factpath2, options[:custom_dir])
236
+ Puppet::Node::Facts::Facter.setup_search_paths @request
237
+ end
238
+
239
+ it 'should add directories' do
240
+ expect(FileTest).to receive(:directory?).with(modulelibfacter).and_return(true)
241
+ expect(FileTest).to receive(:directory?).with(modulepluginsfacter).and_return(false)
242
+ expect(Facter).to receive(:search).with(modulelibfacter, factpath1, factpath2, options[:custom_dir])
243
+ Puppet::Node::Facts::Facter.setup_search_paths @request
244
+ end
245
+ end
246
+ end
152
247
  end