puppet 4.0.0 → 4.1.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 (219) hide show
  1. checksums.yaml +4 -4
  2. data/ext/build_defaults.yaml +8 -35
  3. data/ext/debian/puppet.default +0 -5
  4. data/ext/debian/puppet.init +1 -15
  5. data/lib/hiera/puppet_function.rb +15 -4
  6. data/lib/puppet/application/agent.rb +5 -0
  7. data/lib/puppet/application/apply.rb +23 -2
  8. data/lib/puppet/application/device.rb +8 -3
  9. data/lib/puppet/application/master.rb +16 -5
  10. data/lib/puppet/configurer.rb +7 -5
  11. data/lib/puppet/defaults.rb +18 -0
  12. data/lib/puppet/environments.rb +1 -1
  13. data/lib/puppet/error.rb +27 -1
  14. data/lib/puppet/file_serving/metadata.rb +13 -8
  15. data/lib/puppet/file_serving/terminus_helper.rb +7 -8
  16. data/lib/puppet/file_system.rb +13 -0
  17. data/lib/puppet/file_system/file_impl.rb +4 -0
  18. data/lib/puppet/file_system/memory_impl.rb +4 -0
  19. data/lib/puppet/file_system/windows.rb +8 -0
  20. data/lib/puppet/functions.rb +33 -3
  21. data/lib/puppet/functions/defined.rb +130 -0
  22. data/lib/puppet/functions/regsubst.rb +1 -1
  23. data/lib/puppet/functions/split.rb +1 -1
  24. data/lib/puppet/indirector/catalog/compiler.rb +1 -1
  25. data/lib/puppet/indirector/facts/facter.rb +11 -0
  26. data/lib/puppet/loaders.rb +1 -0
  27. data/lib/puppet/node.rb +17 -1
  28. data/lib/puppet/node/environment.rb +4 -0
  29. data/lib/puppet/parser/ast/pops_bridge.rb +4 -0
  30. data/lib/puppet/parser/compiler.rb +9 -0
  31. data/lib/puppet/parser/functions/defined.rb +25 -1
  32. data/lib/puppet/parser/functions/file.rb +3 -1
  33. data/lib/puppet/parser/scope.rb +11 -2
  34. data/lib/puppet/parser/templatewrapper.rb +2 -1
  35. data/lib/puppet/pops.rb +4 -0
  36. data/lib/puppet/pops/evaluator/access_operator.rb +25 -5
  37. data/lib/puppet/pops/evaluator/closure.rb +28 -2
  38. data/lib/puppet/pops/evaluator/collector_transformer.rb +1 -11
  39. data/lib/puppet/pops/evaluator/collectors/catalog_collector.rb +4 -0
  40. data/lib/puppet/pops/evaluator/collectors/exported_collector.rb +4 -0
  41. data/lib/puppet/pops/evaluator/compare_operator.rb +43 -0
  42. data/lib/puppet/pops/evaluator/epp_evaluator.rb +7 -2
  43. data/lib/puppet/pops/evaluator/evaluator_impl.rb +48 -14
  44. data/lib/puppet/pops/evaluator/runtime3_support.rb +10 -5
  45. data/lib/puppet/pops/functions/dispatch.rb +6 -1
  46. data/lib/puppet/pops/functions/dispatcher.rb +7 -1
  47. data/lib/puppet/pops/issue_reporter.rb +42 -16
  48. data/lib/puppet/pops/issues.rb +116 -2
  49. data/lib/puppet/pops/loader/loader.rb +11 -0
  50. data/lib/puppet/pops/loader/loader_paths.rb +67 -6
  51. data/lib/puppet/pops/loader/module_loaders.rb +19 -8
  52. data/lib/puppet/pops/loader/puppet_function_instantiator.rb +78 -0
  53. data/lib/puppet/pops/loaders.rb +6 -4
  54. data/lib/puppet/pops/migration/migration_checker.rb +54 -0
  55. data/lib/puppet/pops/model/factory.rb +5 -1
  56. data/lib/puppet/pops/model/model_label_provider.rb +2 -0
  57. data/lib/puppet/pops/model/model_meta.rb +5 -1
  58. data/lib/puppet/pops/parser/egrammar.ra +9 -10
  59. data/lib/puppet/pops/parser/eparser.rb +1061 -1047
  60. data/lib/puppet/pops/parser/epp_support.rb +18 -9
  61. data/lib/puppet/pops/parser/evaluating_parser.rb +7 -1
  62. data/lib/puppet/pops/parser/heredoc_support.rb +12 -11
  63. data/lib/puppet/pops/parser/interpolation_support.rb +7 -1
  64. data/lib/puppet/pops/parser/lexer2.rb +29 -12
  65. data/lib/puppet/pops/parser/lexer_support.rb +52 -23
  66. data/lib/puppet/pops/parser/parser_support.rb +11 -14
  67. data/lib/puppet/pops/parser/slurp_support.rb +22 -6
  68. data/lib/puppet/pops/types/type_calculator.rb +156 -55
  69. data/lib/puppet/pops/types/type_factory.rb +66 -13
  70. data/lib/puppet/pops/types/type_parser.rb +22 -13
  71. data/lib/puppet/pops/types/types.rb +23 -4
  72. data/lib/puppet/pops/types/types_meta.rb +13 -2
  73. data/lib/puppet/pops/validation.rb +25 -2
  74. data/lib/puppet/pops/validation/checker4_0.rb +63 -31
  75. data/lib/puppet/provider/group/windows_adsi.rb +8 -4
  76. data/lib/puppet/provider/mount/parsed.rb +145 -2
  77. data/lib/puppet/provider/package/apt.rb +1 -1
  78. data/lib/puppet/provider/package/pip.rb +11 -2
  79. data/lib/puppet/provider/package/pkgng.rb +134 -0
  80. data/lib/puppet/provider/package/portage.rb +1 -1
  81. data/lib/puppet/provider/package/ports.rb +0 -3
  82. data/lib/puppet/provider/package/windows/exe_package.rb +0 -1
  83. data/lib/puppet/provider/package/windows/msi_package.rb +0 -1
  84. data/lib/puppet/provider/package/zypper.rb +50 -15
  85. data/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +32 -7
  86. data/lib/puppet/provider/service/debian.rb +1 -1
  87. data/lib/puppet/provider/service/init.rb +7 -0
  88. data/lib/puppet/provider/user/openbsd.rb +1 -0
  89. data/lib/puppet/provider/user/windows_adsi.rb +45 -2
  90. data/lib/puppet/reference/indirection.rb +1 -1
  91. data/lib/puppet/resource.rb +1 -1
  92. data/lib/puppet/resource/catalog.rb +0 -4
  93. data/lib/puppet/settings.rb +19 -0
  94. data/lib/puppet/type/file.rb +1 -0
  95. data/lib/puppet/type/file/ensure.rb +1 -1
  96. data/lib/puppet/type/mount.rb +9 -1
  97. data/lib/puppet/type/scheduled_task.rb +13 -0
  98. data/lib/puppet/type/tidy.rb +3 -1
  99. data/lib/puppet/type/user.rb +32 -0
  100. data/lib/puppet/type/yumrepo.rb +5 -5
  101. data/lib/puppet/util/log.rb +50 -8
  102. data/lib/puppet/util/log/destinations.rb +23 -2
  103. data/lib/puppet/util/logging.rb +37 -1
  104. data/lib/puppet/util/run_mode.rb +1 -14
  105. data/lib/puppet/util/windows/adsi.rb +130 -58
  106. data/lib/puppet/version.rb +1 -1
  107. data/man/man5/puppet.conf.5 +48 -6
  108. data/man/man8/extlookup2hiera.8 +1 -1
  109. data/man/man8/puppet-agent.8 +4 -1
  110. data/man/man8/puppet-apply.8 +4 -1
  111. data/man/man8/puppet-ca.8 +1 -1
  112. data/man/man8/puppet-catalog.8 +1 -1
  113. data/man/man8/puppet-cert.8 +1 -1
  114. data/man/man8/puppet-certificate.8 +1 -1
  115. data/man/man8/puppet-certificate_request.8 +1 -1
  116. data/man/man8/puppet-certificate_revocation_list.8 +1 -1
  117. data/man/man8/puppet-config.8 +1 -1
  118. data/man/man8/puppet-describe.8 +1 -1
  119. data/man/man8/puppet-device.8 +6 -3
  120. data/man/man8/puppet-doc.8 +1 -1
  121. data/man/man8/puppet-epp.8 +1 -1
  122. data/man/man8/puppet-facts.8 +1 -1
  123. data/man/man8/puppet-file.8 +1 -1
  124. data/man/man8/puppet-filebucket.8 +1 -1
  125. data/man/man8/puppet-help.8 +1 -1
  126. data/man/man8/puppet-inspect.8 +1 -1
  127. data/man/man8/puppet-key.8 +1 -1
  128. data/man/man8/puppet-man.8 +1 -1
  129. data/man/man8/puppet-master.8 +4 -1
  130. data/man/man8/puppet-module.8 +1 -1
  131. data/man/man8/puppet-node.8 +1 -1
  132. data/man/man8/puppet-parser.8 +1 -1
  133. data/man/man8/puppet-plugin.8 +1 -1
  134. data/man/man8/puppet-report.8 +1 -1
  135. data/man/man8/puppet-resource.8 +1 -1
  136. data/man/man8/puppet-resource_type.8 +1 -1
  137. data/man/man8/puppet-status.8 +1 -1
  138. data/man/man8/puppet.8 +1 -1
  139. data/spec/fixtures/unit/data_providers/environments/production/lib/puppet/functions/environment/data.rb +3 -1
  140. data/spec/fixtures/unit/data_providers/environments/production/modules/xyz/functions/data.pp +6 -0
  141. data/spec/fixtures/unit/data_providers/environments/production/modules/xyz/lib/puppet/bindings/xyz/default.rb +9 -0
  142. data/spec/fixtures/unit/data_providers/environments/production/modules/xyz/manifests/init.pp +9 -0
  143. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/functions/puppetcalled.pp +3 -0
  144. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/functions/puppetcaller.pp +3 -0
  145. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/functions/puppetcaller4.pp +3 -0
  146. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/lib/puppet/functions/user/callingpuppet.rb +5 -0
  147. data/spec/fixtures/unit/pops/loaders/loaders/module_no_lib/modules/modulea/functions/hello.pp +3 -0
  148. data/spec/fixtures/unit/pops/loaders/loaders/module_no_lib/modules/modulea/manifests/init.pp +3 -0
  149. data/spec/fixtures/unit/pops/loaders/loaders/module_no_lib/modules/modulea/metadata.json +10 -0
  150. data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/functions/hello.pp +3 -0
  151. data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/functions/subspace/hello.pp +3 -0
  152. data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/metadata.json +1 -10
  153. data/spec/fixtures/unit/provider/mount/parsed/aix.filesystems +93 -85
  154. data/spec/fixtures/unit/provider/mount/parsed/aix.mount +11 -7
  155. data/spec/fixtures/unit/provider/package/pkgng/pkg.info +8 -0
  156. data/spec/fixtures/unit/provider/package/pkgng/pkg.query +1 -0
  157. data/spec/fixtures/unit/provider/package/pkgng/pkg.query_absent +1 -0
  158. data/spec/fixtures/unit/provider/package/pkgng/pkg.version +3 -0
  159. data/spec/fixtures/unit/provider/package/zypper/zypper-list-updates-empty.out +3 -0
  160. data/spec/integration/application/apply_spec.rb +49 -0
  161. data/spec/integration/faces/plugin_spec.rb +0 -4
  162. data/spec/integration/indirector/facts/facter_spec.rb +59 -0
  163. data/spec/integration/parser/compiler_spec.rb +850 -0
  164. data/spec/integration/parser/resource_expressions_spec.rb +3 -0
  165. data/spec/integration/parser/scope_spec.rb +26 -5
  166. data/spec/integration/transaction_spec.rb +1 -1
  167. data/spec/integration/type/file_spec.rb +318 -41
  168. data/spec/integration/util/windows/security_spec.rb +14 -5
  169. data/spec/lib/matchers/resource.rb +22 -1
  170. data/spec/lib/puppet_spec/matchers.rb +6 -4
  171. data/spec/unit/application/master_spec.rb +33 -7
  172. data/spec/unit/data_providers/function_data_provider_spec.rb +10 -1
  173. data/spec/unit/file_serving/metadata_spec.rb +1 -1
  174. data/spec/unit/file_serving/terminus_helper_spec.rb +2 -3
  175. data/spec/unit/file_system_spec.rb +38 -0
  176. data/spec/unit/functions/defined_spec.rb +289 -0
  177. data/spec/unit/functions/hiera_spec.rb +8 -6
  178. data/spec/unit/functions/regsubst_spec.rb +4 -0
  179. data/spec/unit/functions/split_spec.rb +8 -0
  180. data/spec/unit/functions4_spec.rb +97 -2
  181. data/spec/unit/indirector/facts/facter_spec.rb +7 -0
  182. data/spec/unit/node_spec.rb +6 -0
  183. data/spec/unit/parser/functions/file_spec.rb +7 -1
  184. data/spec/unit/parser/functions/template_spec.rb +1 -1
  185. data/spec/unit/parser/scope_spec.rb +2 -2
  186. data/spec/unit/parser/templatewrapper_spec.rb +1 -1
  187. data/spec/unit/pops/evaluator/access_ops_spec.rb +19 -0
  188. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +84 -18
  189. data/spec/unit/pops/evaluator/variables_spec.rb +1 -1
  190. data/spec/unit/pops/issues_spec.rb +16 -16
  191. data/spec/unit/pops/loaders/loaders_spec.rb +106 -48
  192. data/spec/unit/pops/migration_spec.rb +53 -0
  193. data/spec/unit/pops/parser/lexer2_spec.rb +142 -1
  194. data/spec/unit/pops/parser/parse_heredoc_spec.rb +26 -0
  195. data/spec/unit/pops/types/type_calculator_spec.rb +205 -12
  196. data/spec/unit/pops/validation_spec.rb +66 -0
  197. data/spec/unit/pops/validator/validator_spec.rb +1 -1
  198. data/spec/unit/provider/group/windows_adsi_spec.rb +57 -9
  199. data/spec/unit/provider/mount/parsed_spec.rb +31 -5
  200. data/spec/unit/provider/package/apt_spec.rb +5 -0
  201. data/spec/unit/provider/package/pip_spec.rb +9 -0
  202. data/spec/unit/provider/package/pkgng_spec.rb +172 -0
  203. data/spec/unit/provider/package/windows/exe_package_spec.rb +0 -1
  204. data/spec/unit/provider/package/windows/msi_package_spec.rb +0 -1
  205. data/spec/unit/provider/package/zypper_spec.rb +50 -19
  206. data/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb +312 -70
  207. data/spec/unit/provider/service/base_spec.rb +38 -27
  208. data/spec/unit/provider/service/debian_spec.rb +8 -0
  209. data/spec/unit/provider/service/freebsd_spec.rb +1 -0
  210. data/spec/unit/provider/service/gentoo_spec.rb +1 -0
  211. data/spec/unit/provider/service/init_spec.rb +18 -0
  212. data/spec/unit/provider/service/openbsd_spec.rb +1 -0
  213. data/spec/unit/provider/service/redhat_spec.rb +1 -0
  214. data/spec/unit/provider/user/windows_adsi_spec.rb +134 -5
  215. data/spec/unit/settings_spec.rb +11 -0
  216. data/spec/unit/util/log_spec.rb +113 -0
  217. data/spec/unit/util/windows/adsi_spec.rb +135 -41
  218. data/spec/unit/util/windows/sid_spec.rb +0 -10
  219. metadata +48 -2
@@ -1,7 +1,11 @@
1
- node mounted mounted over vfs date options
2
- ---- ------- ------------ --- ------------ -------------------
3
- /dev/hd0 / jfs Dec 17 08:04 rw, log =/dev/hd8
4
- /dev/hd3 /tmp jfs Dec 17 08:04 rw, log =/dev/hd8
5
- /dev/hd1 /home jfs Dec 17 08:06 rw, log =/dev/hd8
6
- /dev/hd2 /usr jfs Dec 17 08:06 rw, log =/dev/hd8
7
- sue /home/local/src /usr/code nfs Dec 17 08:06 ro, log =/dev/hd8
1
+ node mounted mounted over vfs date options
2
+ -------- --------------- --------------- ------ ------------ ---------------
3
+ /dev/hd4 / jfs2 Feb 05 10:27 rw,log=NULL
4
+ /dev/hd2 /usr jfs2 Feb 05 10:28 rw,log=NULL
5
+ /dev/hd9var /var jfs2 Feb 05 10:28 rw,log=NULL
6
+ /dev/hd3 /tmp jfs2 Feb 05 10:28 rw,log=NULL
7
+ /dev/hd1 /home jfs2 Feb 05 10:28 rw,log=NULL
8
+ /dev/hd11admin /admin jfs2 Feb 05 10:28 rw,log=NULL
9
+ /proc /proc procfs Feb 05 10:28 rw
10
+ /dev/hd10opt /opt jfs2 Feb 05 10:28 rw,log=NULL
11
+ mynode /srv/aix /srv/aix nfs Mar 19 14:33 vers=2,rw
@@ -0,0 +1,8 @@
1
+ ca_root_nss 3.15.3.1 security/ca_root_nss
2
+ curl 7.33.0 ftp/curl
3
+ gnupg 2.0.22 security/gnupg
4
+ mcollective 2.2.4 sysutils/mcollective
5
+ nmap 6.40 security/nmap
6
+ pkg 1.2.4_1 ports-mgmt/pkg
7
+ zsh 5.0.2_1 shells/zsh
8
+ tac_plus F4.0.4.27a net/tac_plus4
@@ -0,0 +1 @@
1
+ zsh-5.0.2 The Z shell
@@ -0,0 +1 @@
1
+ pkg: No package(s) matching bash
@@ -0,0 +1,3 @@
1
+ shells/bash-completion < needs updating (index has 2.1_3)
2
+ ftp/curl < needs updating (index has 7.33.0_2)
3
+ shells/zsh < needs updating (index has 5.0.4)
@@ -0,0 +1,3 @@
1
+ Loading repository data...
2
+ Reading installed packages...
3
+ No updates found.
@@ -41,6 +41,18 @@ describe "apply" do
41
41
  expect(@logs.map(&:to_s)).to include('it was applied')
42
42
  end
43
43
 
44
+ it "adds environment to the $server_facts variable if trusted_server_facts is true" do
45
+ manifest = file_containing("manifest.pp", "notice(\"$server_facts\")")
46
+ Puppet[:trusted_server_facts] = true
47
+
48
+ puppet = Puppet::Application[:apply]
49
+ puppet.stubs(:command_line).returns(stub('command_line', :args => [manifest]))
50
+
51
+ expect { puppet.run_command }.to exit_with(0)
52
+
53
+ expect(@logs.map(&:to_s)).to include(/{environment =>.*/)
54
+ end
55
+
44
56
  it "applies a given file even when an ENC is configured", :if => !Puppet.features.microsoft_windows? do
45
57
  manifest = file_containing("manifest.pp", "notice('specific manifest applied')")
46
58
  site_manifest = file_containing("site_manifest.pp", "notice('the site manifest was applied instead')")
@@ -61,6 +73,43 @@ describe "apply" do
61
73
  expect(@logs.map(&:to_s)).to include('specific manifest applied')
62
74
  end
63
75
 
76
+ context "handles errors" do
77
+ it "logs compile errors once" do
78
+ Puppet.initialize_settings([])
79
+ apply = Puppet::Application.find(:apply).new(stub('command_line', :subcommand_name => :apply, :args => []))
80
+ apply.options[:code] = '08'
81
+
82
+ msg = 'valid octal'
83
+ callback = Proc.new do |actual|
84
+ expect(actual.scan(Regexp.new(msg))).to eq([msg])
85
+ end
86
+
87
+ expect do
88
+ apply.run
89
+ end.to have_printed(callback).and_exit_with(1)
90
+ end
91
+
92
+ it "logs compile post processing errors once" do
93
+ Puppet.initialize_settings([])
94
+ apply = Puppet::Application.find(:apply).new(stub('command_line', :subcommand_name => :apply, :args => []))
95
+ path = File.expand_path('/tmp/content_file_test.Q634Dlmtime')
96
+ apply.options[:code] = "file { '#{path}':
97
+ content => 'This is the test file content',
98
+ ensure => present,
99
+ checksum => mtime
100
+ }"
101
+
102
+ msg = 'You cannot specify content when using checksum'
103
+ callback = Proc.new do |actual|
104
+ expect(actual.scan(Regexp.new(msg))).to eq([msg])
105
+ end
106
+
107
+ expect do
108
+ apply.run
109
+ end.to have_printed(callback).and_exit_with(1)
110
+ end
111
+ end
112
+
64
113
  context "with a module" do
65
114
  let(:modulepath) { tmpdir('modulepath') }
66
115
  let(:execute) { 'include amod' }
@@ -26,7 +26,6 @@ describe "Puppet plugin face" do
26
26
  end
27
27
 
28
28
  before do
29
- FileUtils.mkdir(Puppet[:vardir])
30
29
  FileUtils.mkdir(File.join(Puppet[:vardir], 'lib'))
31
30
  FileUtils.mkdir(File.join(Puppet[:vardir], 'facts.d'))
32
31
  @termini_classes = {}
@@ -37,9 +36,6 @@ describe "Puppet plugin face" do
37
36
  end
38
37
 
39
38
  after do
40
- FileUtils.rmdir(File.join(Puppet[:vardir],'lib'))
41
- FileUtils.rmdir(File.join(Puppet[:vardir],'facts.d'))
42
- FileUtils.rmdir(Puppet[:vardir])
43
39
  INDIRECTED_CLASSES.each do |indirected|
44
40
  indirected.indirection.terminus_class = @termini_classes[indirected]
45
41
  indirected.indirection.termini.clear
@@ -1,9 +1,11 @@
1
1
  #! /usr/bin/env ruby
2
2
  require 'spec_helper'
3
3
 
4
+ require 'puppet_spec/files'
4
5
  require 'puppet_spec/compiler'
5
6
 
6
7
  describe Puppet::Node::Facts::Facter do
8
+ include PuppetSpec::Files
7
9
  include PuppetSpec::Compiler
8
10
 
9
11
  it "preserves case in fact values" do
@@ -19,4 +21,61 @@ describe Puppet::Node::Facts::Facter do
19
21
  Puppet::Node.indirection.find('foo'))
20
22
  expect(cat.resource("Notify[AaBbCc]")).to be
21
23
  end
24
+
25
+ context "resolving file based facts" do
26
+ let(:factdir) { tmpdir('factdir') }
27
+
28
+ it "should resolve custom facts" do
29
+ test_module = File.join(factdir, 'module', 'lib', 'facter')
30
+ FileUtils.mkdir_p(test_module)
31
+
32
+ File.open(File.join(test_module, 'custom.rb'), 'wb') { |file| file.write(<<-EOF)}
33
+ Facter.add(:custom) do
34
+ setcode do
35
+ Facter.value('puppetversion')
36
+ end
37
+ end
38
+ EOF
39
+
40
+ Puppet.initialize_settings(['--modulepath', factdir])
41
+ apply = Puppet::Application.find(:apply).new(stub('command_line', :subcommand_name => :apply, :args => ['--modulepath', factdir, '-e', 'notify { $custom: }']))
42
+
43
+ expect do
44
+ expect { apply.run }.to exit_with(0)
45
+ end.to have_printed(Puppet.version)
46
+ end
47
+
48
+ it "should resolve external facts" do
49
+ external_fact = File.join(factdir, 'external')
50
+
51
+ if Puppet.features.microsoft_windows?
52
+ external_fact += '.bat'
53
+ File.open(external_fact, 'wb') { |file| file.write(<<-EOF)}
54
+ @echo foo=bar
55
+ EOF
56
+ else
57
+ File.open(external_fact, 'wb') { |file| file.write(<<-EOF)}
58
+ #!/bin/sh
59
+ echo "foo=bar"
60
+ EOF
61
+
62
+ Puppet::FileSystem.chmod(0755, external_fact)
63
+ end
64
+
65
+ Puppet.initialize_settings(['--pluginfactdest', factdir])
66
+ apply = Puppet::Application.find(:apply).new(stub('command_line', :subcommand_name => :apply, :args => ['--pluginfactdest', factdir, '-e', 'notify { $foo: }']))
67
+
68
+ expect do
69
+ expect { apply.run }.to exit_with(0)
70
+ end.to have_printed('bar')
71
+ end
72
+ end
73
+
74
+ it "adds the puppetversion fact" do
75
+ Facter.stubs(:reset)
76
+
77
+ cat = compile_to_catalog('notify { $::puppetversion: }',
78
+ Puppet::Node.indirection.find('foo'))
79
+ expect(cat.resource("Notify[#{Puppet.version.to_s}]")).to be
80
+ end
22
81
  end
@@ -507,6 +507,32 @@ describe Puppet::Parser::Compiler do
507
507
 
508
508
  expect { @compiler.compile }.to raise_error(Puppet::ParseError, 'Failed to realize virtual resources one, two')
509
509
  end
510
+
511
+ it 'matches on container inherited tags' do
512
+ Puppet[:code] = <<-MANIFEST
513
+ class xport_test {
514
+ tag('foo_bar')
515
+ @notify { 'nbr1':
516
+ message => 'explicitly tagged',
517
+ tag => 'foo_bar'
518
+ }
519
+
520
+ @notify { 'nbr2':
521
+ message => 'implicitly tagged'
522
+ }
523
+
524
+ Notify <| tag == 'foo_bar' |> {
525
+ message => 'overridden'
526
+ }
527
+ }
528
+ include xport_test
529
+ MANIFEST
530
+
531
+ catalog = Puppet::Parser::Compiler.compile(Puppet::Node.new("mynode"))
532
+
533
+ expect(catalog).to have_resource("Notify[nbr1]").with_parameter(:message, 'overridden')
534
+ expect(catalog).to have_resource("Notify[nbr2]").with_parameter(:message, 'overridden')
535
+ end
510
536
  end
511
537
 
512
538
  describe "when evaluating relationships" do
@@ -866,6 +892,25 @@ describe Puppet::Parser::Compiler do
866
892
  expect(catalog).to have_resource("Notify[expected]").with_parameter(:message, "8080")
867
893
  end
868
894
  end
895
+
896
+ it 'looks up default parameter values from inherited class (PUP-2532)' do
897
+ catalog = compile_to_catalog(<<-CODE)
898
+ class a {
899
+ Notify { message => "defaulted" }
900
+ include c
901
+ notify { bye: }
902
+ }
903
+ class b { Notify { message => "inherited" } }
904
+ class c inherits b { notify { hi: } }
905
+
906
+ include a
907
+ notify {hi_test: message => Notify[hi][message] }
908
+ notify {bye_test: message => Notify[bye][message] }
909
+ CODE
910
+
911
+ expect(catalog).to have_resource("Notify[hi_test]").with_parameter(:message, "inherited")
912
+ expect(catalog).to have_resource("Notify[bye_test]").with_parameter(:message, "defaulted")
913
+ end
869
914
  end
870
915
  end
871
916
 
@@ -924,4 +969,809 @@ describe Puppet::Parser::Compiler do
924
969
  Puppet::Parser::Compiler.compile(Puppet::Node.new("mynode"))
925
970
  end
926
971
  end
972
+
973
+ context 'when working with $server_facts' do
974
+ include PuppetSpec::Compiler
975
+ context 'and have opted in to trusted_server_facts' do
976
+ before :each do
977
+ Puppet[:trusted_server_facts] = true
978
+ end
979
+
980
+ it 'should make $trusted available' do
981
+ node = Puppet::Node.new("testing")
982
+ node.add_server_facts({ "server_fact" => "foo" })
983
+
984
+ catalog = compile_to_catalog(<<-MANIFEST, node)
985
+ notify { 'test': message => $server_facts[server_fact] }
986
+ MANIFEST
987
+
988
+ expect(catalog).to have_resource("Notify[test]").with_parameter(:message, "foo")
989
+ end
990
+
991
+ it 'should not allow assignment to $server_facts' do
992
+ node = Puppet::Node.new("testing")
993
+ node.add_server_facts({ "server_fact" => "foo" })
994
+
995
+ expect do
996
+ compile_to_catalog(<<-MANIFEST, node)
997
+ $server_facts = 'changed'
998
+ notify { 'test': message => $server_facts == 'changed' }
999
+ MANIFEST
1000
+ end.to raise_error(Puppet::PreformattedError, /Attempt to assign to a reserved variable name: '\$server_facts'.*/)
1001
+ end
1002
+ end
1003
+
1004
+ context 'and have not opted in to hashed_node_data' do
1005
+ before :each do
1006
+ Puppet[:trusted_server_facts] = false
1007
+ end
1008
+
1009
+ it 'should not make $server_facts available' do
1010
+ node = Puppet::Node.new("testing")
1011
+ node.add_server_facts({ "server_fact" => "foo" })
1012
+
1013
+ catalog = compile_to_catalog(<<-MANIFEST, node)
1014
+ notify { 'test': message => ($server_facts == undef) }
1015
+ MANIFEST
1016
+
1017
+ expect(catalog).to have_resource("Notify[test]").with_parameter(:message, true)
1018
+ end
1019
+
1020
+ it 'should allow assignment to $server_facts' do
1021
+ catalog = compile_to_catalog(<<-MANIFEST)
1022
+ $server_facts = 'changed'
1023
+ notify { 'test': message => $server_facts == 'changed' }
1024
+ MANIFEST
1025
+
1026
+ expect(catalog).to have_resource("Notify[test]").with_parameter(:message, true)
1027
+ end
1028
+ end
1029
+ end
1030
+ describe "the compiler when using future parser and evaluator" do
1031
+ include PuppetSpec::Compiler
1032
+
1033
+ if Puppet.features.microsoft_windows?
1034
+ it "should be able to determine the configuration version from a local version control repository" do
1035
+ pending("Bug #14071 about semantics of Puppet::Util::Execute on Windows")
1036
+ # This should always work, because we should always be
1037
+ # in the puppet repo when we run this.
1038
+ version = %x{git rev-parse HEAD}.chomp
1039
+
1040
+ Puppet.settings[:config_version] = 'git rev-parse HEAD'
1041
+
1042
+ compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("testnode"))
1043
+ compiler.catalog.version.should == version
1044
+ end
1045
+ end
1046
+
1047
+ it "should not create duplicate resources when a class is referenced both directly and indirectly by the node classifier (4792)" do
1048
+ node = Puppet::Node.new("testnodex")
1049
+ node.classes = ['foo', 'bar']
1050
+ catalog = compile_to_catalog(<<-PP, node)
1051
+ class foo
1052
+ {
1053
+ notify { foo_notify: }
1054
+ include bar
1055
+ }
1056
+ class bar
1057
+ {
1058
+ notify { bar_notify: }
1059
+ }
1060
+ PP
1061
+
1062
+ catalog = Puppet::Parser::Compiler.compile(node)
1063
+
1064
+ expect(catalog).to have_resource("Notify[foo_notify]")
1065
+ expect(catalog).to have_resource("Notify[bar_notify]")
1066
+ end
1067
+
1068
+ it 'applies defaults for defines with qualified names (PUP-2302)' do
1069
+ catalog = compile_to_catalog(<<-CODE)
1070
+ define my::thing($msg = 'foo') { notify {'check_me': message => $msg } }
1071
+ My::Thing { msg => 'evoe' }
1072
+ my::thing { 'name': }
1073
+ CODE
1074
+
1075
+ expect(catalog).to have_resource("Notify[check_me]").with_parameter(:message, "evoe")
1076
+ end
1077
+
1078
+ it 'Applies defaults from dynamic scopes (3x and future with reverted PUP-867)' do
1079
+ catalog = compile_to_catalog(<<-CODE)
1080
+ class a {
1081
+ Notify { message => "defaulted" }
1082
+ include b
1083
+ notify { bye: }
1084
+ }
1085
+ class b { notify { hi: } }
1086
+
1087
+ include a
1088
+ CODE
1089
+ expect(catalog).to have_resource("Notify[hi]").with_parameter(:message, "defaulted")
1090
+ expect(catalog).to have_resource("Notify[bye]").with_parameter(:message, "defaulted")
1091
+ end
1092
+
1093
+ it 'gets default from inherited class (PUP-867)' do
1094
+ catalog = compile_to_catalog(<<-CODE)
1095
+ class a {
1096
+ Notify { message => "defaulted" }
1097
+ include c
1098
+ notify { bye: }
1099
+ }
1100
+ class b { Notify { message => "inherited" } }
1101
+ class c inherits b { notify { hi: } }
1102
+
1103
+ include a
1104
+ CODE
1105
+
1106
+ expect(catalog).to have_resource("Notify[hi]").with_parameter(:message, "inherited")
1107
+ expect(catalog).to have_resource("Notify[bye]").with_parameter(:message, "defaulted")
1108
+ end
1109
+
1110
+ it 'looks up default parameter values from inherited class (PUP-2532)' do
1111
+ catalog = compile_to_catalog(<<-CODE)
1112
+ class a {
1113
+ Notify { message => "defaulted" }
1114
+ include c
1115
+ notify { bye: }
1116
+ }
1117
+ class b { Notify { message => "inherited" } }
1118
+ class c inherits b { notify { hi: } }
1119
+
1120
+ include a
1121
+ notify {hi_test: message => Notify[hi][message] }
1122
+ notify {bye_test: message => Notify[bye][message] }
1123
+ CODE
1124
+
1125
+ expect(catalog).to have_resource("Notify[hi_test]").with_parameter(:message, "inherited")
1126
+ expect(catalog).to have_resource("Notify[bye_test]").with_parameter(:message, "defaulted")
1127
+ end
1128
+
1129
+ it 'does not allow override of class parameters using a resource override expression' do
1130
+ expect do
1131
+ compile_to_catalog(<<-CODE)
1132
+ Class[a] { x => 2}
1133
+ CODE
1134
+ end.to raise_error(/Resource Override can only.*got: Class\[a\].*/)
1135
+ end
1136
+
1137
+ describe "when resolving class references" do
1138
+ include Matchers::Resource
1139
+ it "should not favor local scope (with class included in topscope)" do
1140
+ catalog = compile_to_catalog(<<-PP)
1141
+ class experiment {
1142
+ class baz {
1143
+ }
1144
+ notify {"x" : require => Class[Baz] }
1145
+ notify {"y" : require => Class[Experiment::Baz] }
1146
+ }
1147
+ class baz {
1148
+ }
1149
+ include baz
1150
+ include experiment
1151
+ include experiment::baz
1152
+ PP
1153
+
1154
+ expect(catalog).to have_resource("Notify[x]").with_parameter(:require, be_resource("Class[Baz]"))
1155
+ expect(catalog).to have_resource("Notify[y]").with_parameter(:require, be_resource("Class[Experiment::Baz]"))
1156
+ end
1157
+
1158
+ it "should not favor local scope, (with class not included in topscope)" do
1159
+ catalog = compile_to_catalog(<<-PP)
1160
+ class experiment {
1161
+ class baz {
1162
+ }
1163
+ notify {"x" : require => Class[Baz] }
1164
+ notify {"y" : require => Class[Experiment::Baz] }
1165
+ }
1166
+ class baz {
1167
+ }
1168
+ include experiment
1169
+ include experiment::baz
1170
+ PP
1171
+
1172
+ expect(catalog).to have_resource("Notify[x]").with_parameter(:require, be_resource("Class[Baz]"))
1173
+ expect(catalog).to have_resource("Notify[y]").with_parameter(:require, be_resource("Class[Experiment::Baz]"))
1174
+ end
1175
+ end
1176
+
1177
+ describe "(ticket #13349) when explicitly specifying top scope" do
1178
+ ["class {'::bar::baz':}", "include ::bar::baz"].each do |include|
1179
+ describe "with #{include}" do
1180
+ it "should find the top level class" do
1181
+ catalog = compile_to_catalog(<<-MANIFEST)
1182
+ class { 'foo::test': }
1183
+ class foo::test {
1184
+ #{include}
1185
+ }
1186
+ class bar::baz {
1187
+ notify { 'good!': }
1188
+ }
1189
+ class foo::bar::baz {
1190
+ notify { 'bad!': }
1191
+ }
1192
+ MANIFEST
1193
+
1194
+ expect(catalog).to have_resource("Class[Bar::Baz]")
1195
+ expect(catalog).to have_resource("Notify[good!]")
1196
+ expect(catalog).not_to have_resource("Class[Foo::Bar::Baz]")
1197
+ expect(catalog).not_to have_resource("Notify[bad!]")
1198
+ end
1199
+ end
1200
+ end
1201
+ end
1202
+
1203
+ it 'should recompute the version after input files are re-parsed' do
1204
+ Puppet[:code] = 'class foo { }'
1205
+ Time.stubs(:now).returns(1)
1206
+ node = Puppet::Node.new('mynode')
1207
+ expect(Puppet::Parser::Compiler.compile(node).version).to eq(1)
1208
+ Time.stubs(:now).returns(2)
1209
+ expect(Puppet::Parser::Compiler.compile(node).version).to eq(1) # no change because files didn't change
1210
+ Puppet[:code] = nil
1211
+ expect(Puppet::Parser::Compiler.compile(node).version).to eq(2)
1212
+ end
1213
+
1214
+ ['define', 'class', 'node'].each do |thing|
1215
+ it "'#{thing}' is not allowed inside evaluated conditional constructs" do
1216
+ expect do
1217
+ compile_to_catalog(<<-PP)
1218
+ if true {
1219
+ #{thing} foo {
1220
+ }
1221
+ notify { decoy: }
1222
+ }
1223
+ PP
1224
+ end.to raise_error(Puppet::Error, /Classes, definitions, and nodes may only appear at toplevel/)
1225
+ end
1226
+
1227
+ it "'#{thing}' is not allowed inside un-evaluated conditional constructs" do
1228
+ expect do
1229
+ compile_to_catalog(<<-PP)
1230
+ if false {
1231
+ #{thing} foo {
1232
+ }
1233
+ notify { decoy: }
1234
+ }
1235
+ PP
1236
+ end.to raise_error(Puppet::Error, /Classes, definitions, and nodes may only appear at toplevel/)
1237
+ end
1238
+ end
1239
+
1240
+ describe "relationships can be formed" do
1241
+ def extract_name(ref)
1242
+ ref.sub(/File\[(\w+)\]/, '\1')
1243
+ end
1244
+
1245
+ def assert_creates_relationships(relationship_code, expectations)
1246
+ base_manifest = <<-MANIFEST
1247
+ file { [a,b,c]:
1248
+ mode => '0644',
1249
+ }
1250
+ file { [d,e]:
1251
+ mode => '0755',
1252
+ }
1253
+ MANIFEST
1254
+ catalog = compile_to_catalog(base_manifest + relationship_code)
1255
+
1256
+ resources = catalog.resources.select { |res| res.type == 'File' }
1257
+
1258
+ actual_relationships, actual_subscriptions = [:before, :notify].map do |relation|
1259
+ resources.map do |res|
1260
+ dependents = Array(res[relation])
1261
+ dependents.map { |ref| [res.title, extract_name(ref)] }
1262
+ end.inject(&:concat)
1263
+ end
1264
+
1265
+ expect(actual_relationships).to match_array(expectations[:relationships] || [])
1266
+ expect(actual_subscriptions).to match_array(expectations[:subscriptions] || [])
1267
+ end
1268
+
1269
+ it "of regular type" do
1270
+ assert_creates_relationships("File[a] -> File[b]",
1271
+ :relationships => [['a','b']])
1272
+ end
1273
+
1274
+ it "of subscription type" do
1275
+ assert_creates_relationships("File[a] ~> File[b]",
1276
+ :subscriptions => [['a', 'b']])
1277
+ end
1278
+
1279
+ it "between multiple resources expressed as resource with multiple titles" do
1280
+ assert_creates_relationships("File[a,b] -> File[c,d]",
1281
+ :relationships => [['a', 'c'],
1282
+ ['b', 'c'],
1283
+ ['a', 'd'],
1284
+ ['b', 'd']])
1285
+ end
1286
+
1287
+ it "between collection expressions" do
1288
+ assert_creates_relationships("File <| mode == '0644' |> -> File <| mode == '0755' |>",
1289
+ :relationships => [['a', 'd'],
1290
+ ['b', 'd'],
1291
+ ['c', 'd'],
1292
+ ['a', 'e'],
1293
+ ['b', 'e'],
1294
+ ['c', 'e']])
1295
+ end
1296
+
1297
+ it "between resources expressed as Strings" do
1298
+ assert_creates_relationships("'File[a]' -> 'File[b]'",
1299
+ :relationships => [['a', 'b']])
1300
+ end
1301
+
1302
+ it "between resources expressed as variables" do
1303
+ assert_creates_relationships(<<-MANIFEST, :relationships => [['a', 'b']])
1304
+ $var = File[a]
1305
+ $var -> File[b]
1306
+ MANIFEST
1307
+
1308
+ end
1309
+
1310
+ it "between resources expressed as case statements" do
1311
+ assert_creates_relationships(<<-MANIFEST, :relationships => [['s1', 't2']])
1312
+ $var = 10
1313
+ case $var {
1314
+ 10: {
1315
+ file { s1: }
1316
+ }
1317
+ 12: {
1318
+ file { s2: }
1319
+ }
1320
+ }
1321
+ ->
1322
+ case $var + 2 {
1323
+ 10: {
1324
+ file { t1: }
1325
+ }
1326
+ 12: {
1327
+ file { t2: }
1328
+ }
1329
+ }
1330
+ MANIFEST
1331
+ end
1332
+
1333
+ it "using deep access in array" do
1334
+ assert_creates_relationships(<<-MANIFEST, :relationships => [['a', 'b']])
1335
+ $var = [ [ [ File[a], File[b] ] ] ]
1336
+ $var[0][0][0] -> $var[0][0][1]
1337
+ MANIFEST
1338
+
1339
+ end
1340
+
1341
+ it "using deep access in hash" do
1342
+ assert_creates_relationships(<<-MANIFEST, :relationships => [['a', 'b']])
1343
+ $var = {'foo' => {'bar' => {'source' => File[a], 'target' => File[b]}}}
1344
+ $var[foo][bar][source] -> $var[foo][bar][target]
1345
+ MANIFEST
1346
+
1347
+ end
1348
+
1349
+ it "using resource declarations" do
1350
+ assert_creates_relationships("file { l: } -> file { r: }", :relationships => [['l', 'r']])
1351
+ end
1352
+
1353
+ it "between entries in a chain of relationships" do
1354
+ assert_creates_relationships("File[a] -> File[b] ~> File[c] <- File[d] <~ File[e]",
1355
+ :relationships => [['a', 'b'], ['d', 'c']],
1356
+ :subscriptions => [['b', 'c'], ['e', 'd']])
1357
+ end
1358
+ end
1359
+
1360
+ context "when dealing with variable references" do
1361
+ it 'an initial underscore in a variable name is ok' do
1362
+ catalog = compile_to_catalog(<<-MANIFEST)
1363
+ class a { $_a = 10}
1364
+ include a
1365
+ notify { 'test': message => $a::_a }
1366
+ MANIFEST
1367
+
1368
+ expect(catalog).to have_resource("Notify[test]").with_parameter(:message, 10)
1369
+ end
1370
+
1371
+ it 'an initial underscore in not ok if elsewhere than last segment' do
1372
+ expect do
1373
+ catalog = compile_to_catalog(<<-MANIFEST)
1374
+ class a { $_a = 10}
1375
+ include a
1376
+ notify { 'test': message => $_a::_a }
1377
+ MANIFEST
1378
+ end.to raise_error(/Illegal variable name/)
1379
+ end
1380
+
1381
+ it 'a missing variable as default value becomes undef' do
1382
+ # strict variables not on
1383
+ catalog = compile_to_catalog(<<-MANIFEST)
1384
+ class a ($b=$x) { notify {test: message=>"yes ${undef == $b}" } }
1385
+ include a
1386
+ MANIFEST
1387
+
1388
+ expect(catalog).to have_resource("Notify[test]").with_parameter(:message, "yes true")
1389
+ end
1390
+ end
1391
+
1392
+ context 'when working with the trusted data hash' do
1393
+ context 'and have opted in to hashed_node_data' do
1394
+ it 'should make $trusted available' do
1395
+ node = Puppet::Node.new("testing")
1396
+ node.trusted_data = { "data" => "value" }
1397
+
1398
+ catalog = compile_to_catalog(<<-MANIFEST, node)
1399
+ notify { 'test': message => $trusted[data] }
1400
+ MANIFEST
1401
+
1402
+ expect(catalog).to have_resource("Notify[test]").with_parameter(:message, "value")
1403
+ end
1404
+
1405
+ it 'should not allow assignment to $trusted' do
1406
+ node = Puppet::Node.new("testing")
1407
+ node.trusted_data = { "data" => "value" }
1408
+
1409
+ expect do
1410
+ compile_to_catalog(<<-MANIFEST, node)
1411
+ $trusted = 'changed'
1412
+ notify { 'test': message => $trusted == 'changed' }
1413
+ MANIFEST
1414
+ end.to raise_error(Puppet::PreformattedError, /Attempt to assign to a reserved variable name: '\$trusted'/)
1415
+ end
1416
+ end
1417
+ end
1418
+
1419
+ context 'when using typed parameters in definition' do
1420
+ it 'accepts type compliant arguments' do
1421
+ catalog = compile_to_catalog(<<-MANIFEST)
1422
+ define foo(String $x) { }
1423
+ foo { 'test': x =>'say friend' }
1424
+ MANIFEST
1425
+ expect(catalog).to have_resource("Foo[test]").with_parameter(:x, 'say friend')
1426
+ end
1427
+
1428
+ it 'accepts undef as the default for an Optional argument' do
1429
+ catalog = compile_to_catalog(<<-MANIFEST)
1430
+ define foo(Optional[String] $x = undef) {
1431
+ notify { "expected": message => $x == undef }
1432
+ }
1433
+ foo { 'test': }
1434
+ MANIFEST
1435
+ expect(catalog).to have_resource("Notify[expected]").with_parameter(:message, true)
1436
+ end
1437
+
1438
+ it 'accepts anything when parameters are untyped' do
1439
+ expect do
1440
+ catalog = compile_to_catalog(<<-MANIFEST)
1441
+ define foo($a, $b, $c) { }
1442
+ foo { 'test': a => String, b=>10, c=>undef }
1443
+ MANIFEST
1444
+ end.to_not raise_error()
1445
+ end
1446
+
1447
+ it 'denies non type compliant arguments' do
1448
+ expect do
1449
+ catalog = compile_to_catalog(<<-MANIFEST)
1450
+ define foo(Integer $x) { }
1451
+ foo { 'test': x =>'say friend' }
1452
+ MANIFEST
1453
+ end.to raise_error(/type Integer, got String/)
1454
+ end
1455
+
1456
+ it 'denies undef for a non-optional type' do
1457
+ expect do
1458
+ catalog = compile_to_catalog(<<-MANIFEST)
1459
+ define foo(Integer $x) { }
1460
+ foo { 'test': x => undef }
1461
+ MANIFEST
1462
+ end.to raise_error(/type Integer, got Undef/)
1463
+ end
1464
+
1465
+ it 'denies non type compliant default argument' do
1466
+ expect do
1467
+ catalog = compile_to_catalog(<<-MANIFEST)
1468
+ define foo(Integer $x = 'pow') { }
1469
+ foo { 'test': }
1470
+ MANIFEST
1471
+ end.to raise_error(/type Integer, got String/)
1472
+ end
1473
+
1474
+ it 'denies undef as the default for a non-optional type' do
1475
+ expect do
1476
+ catalog = compile_to_catalog(<<-MANIFEST)
1477
+ define foo(Integer $x = undef) { }
1478
+ foo { 'test': }
1479
+ MANIFEST
1480
+ end.to raise_error(/type Integer, got Undef/)
1481
+ end
1482
+
1483
+ it 'accepts a Resource as a Type' do
1484
+ catalog = compile_to_catalog(<<-MANIFEST)
1485
+ define foo(Type[Bar] $x) {
1486
+ notify { 'test': message => $x[text] }
1487
+ }
1488
+ define bar($text) { }
1489
+ bar { 'joke': text => 'knock knock' }
1490
+ foo { 'test': x => Bar[joke] }
1491
+ MANIFEST
1492
+ expect(catalog).to have_resource("Notify[test]").with_parameter(:message, 'knock knock')
1493
+ end
1494
+
1495
+ it 'uses infer_set when reporting type mismatch' do
1496
+ expect do
1497
+ catalog = compile_to_catalog(<<-MANIFEST)
1498
+ define foo(Struct[{b => Integer, d=>String}] $a) { }
1499
+ foo{ bar: a => {b => 5, c => 'stuff'}}
1500
+ MANIFEST
1501
+ end.to raise_error(/got Struct\[\{'b'=>Integer, 'c'=>String\}\]/)
1502
+ end
1503
+ end
1504
+
1505
+ context 'when using typed parameters in class' do
1506
+ it 'accepts type compliant arguments' do
1507
+ catalog = compile_to_catalog(<<-MANIFEST)
1508
+ class foo(String $x) { }
1509
+ class { 'foo': x =>'say friend' }
1510
+ MANIFEST
1511
+ expect(catalog).to have_resource("Class[Foo]").with_parameter(:x, 'say friend')
1512
+ end
1513
+
1514
+ it 'accepts undef as the default for an Optional argument' do
1515
+ catalog = compile_to_catalog(<<-MANIFEST)
1516
+ class foo(Optional[String] $x = undef) {
1517
+ notify { "expected": message => $x == undef }
1518
+ }
1519
+ class { 'foo': }
1520
+ MANIFEST
1521
+ expect(catalog).to have_resource("Notify[expected]").with_parameter(:message, true)
1522
+ end
1523
+
1524
+ it 'accepts anything when parameters are untyped' do
1525
+ expect do
1526
+ catalog = compile_to_catalog(<<-MANIFEST)
1527
+ class foo($a, $b, $c) { }
1528
+ class { 'foo': a => String, b=>10, c=>undef }
1529
+ MANIFEST
1530
+ end.to_not raise_error()
1531
+ end
1532
+
1533
+ it 'denies non type compliant arguments' do
1534
+ expect do
1535
+ catalog = compile_to_catalog(<<-MANIFEST)
1536
+ class foo(Integer $x) { }
1537
+ class { 'foo': x =>'say friend' }
1538
+ MANIFEST
1539
+ end.to raise_error(/type Integer, got String/)
1540
+ end
1541
+
1542
+ it 'denies undef for a non-optional type' do
1543
+ expect do
1544
+ catalog = compile_to_catalog(<<-MANIFEST)
1545
+ class foo(Integer $x) { }
1546
+ class { 'foo': x => undef }
1547
+ MANIFEST
1548
+ end.to raise_error(/type Integer, got Undef/)
1549
+ end
1550
+
1551
+ it 'denies non type compliant default argument' do
1552
+ expect do
1553
+ catalog = compile_to_catalog(<<-MANIFEST)
1554
+ class foo(Integer $x = 'pow') { }
1555
+ class { 'foo': }
1556
+ MANIFEST
1557
+ end.to raise_error(/type Integer, got String/)
1558
+ end
1559
+
1560
+ it 'denies undef as the default for a non-optional type' do
1561
+ expect do
1562
+ catalog = compile_to_catalog(<<-MANIFEST)
1563
+ class foo(Integer $x = undef) { }
1564
+ class { 'foo': }
1565
+ MANIFEST
1566
+ end.to raise_error(/type Integer, got Undef/)
1567
+ end
1568
+
1569
+ it 'accepts a Resource as a Type' do
1570
+ catalog = compile_to_catalog(<<-MANIFEST)
1571
+ class foo(Type[Bar] $x) {
1572
+ notify { 'test': message => $x[text] }
1573
+ }
1574
+ define bar($text) { }
1575
+ bar { 'joke': text => 'knock knock' }
1576
+ class { 'foo': x => Bar[joke] }
1577
+ MANIFEST
1578
+ expect(catalog).to have_resource("Notify[test]").with_parameter(:message, 'knock knock')
1579
+ end
1580
+ end
1581
+
1582
+ context 'when using typed parameters in lambdas' do
1583
+ it 'accepts type compliant arguments' do
1584
+ catalog = compile_to_catalog(<<-MANIFEST)
1585
+ with('value') |String $x| { notify { "$x": } }
1586
+ MANIFEST
1587
+ expect(catalog).to have_resource("Notify[value]")
1588
+ end
1589
+
1590
+ it 'handles an array as a single argument' do
1591
+ catalog = compile_to_catalog(<<-MANIFEST)
1592
+ with(['value', 'second']) |$x| { notify { "${x[0]} ${x[1]}": } }
1593
+ MANIFEST
1594
+ expect(catalog).to have_resource("Notify[value second]")
1595
+ end
1596
+
1597
+ # Conditinoally left out for Ruby 1.8.x since the Proc created for the expected number of arguments will accept
1598
+ # a call with fewer arguments and then pass all arguments to the closure. The closure then receives an argument
1599
+ # array of correct size with nil values instead of an array with too few arguments
1600
+ unless RUBY_VERSION[0,3] == '1.8'
1601
+ it 'denies when missing required arguments' do
1602
+ expect do
1603
+ compile_to_catalog(<<-MANIFEST)
1604
+ with(1) |$x, $y| { }
1605
+ MANIFEST
1606
+ end.to raise_error(/Parameter \$y is required but no value was given/m)
1607
+ end
1608
+ end
1609
+
1610
+ it 'accepts anything when parameters are untyped' do
1611
+ catalog = compile_to_catalog(<<-MANIFEST)
1612
+ ['value', 1, true, undef].each |$x| { notify { "value: $x": } }
1613
+ MANIFEST
1614
+
1615
+ expect(catalog).to have_resource("Notify[value: value]")
1616
+ expect(catalog).to have_resource("Notify[value: 1]")
1617
+ expect(catalog).to have_resource("Notify[value: true]")
1618
+ expect(catalog).to have_resource("Notify[value: ]")
1619
+ end
1620
+
1621
+ it 'accepts type-compliant, slurped arguments' do
1622
+ catalog = compile_to_catalog(<<-MANIFEST)
1623
+ with(1, 2) |Integer *$x| { notify { "${$x[0] + $x[1]}": } }
1624
+ MANIFEST
1625
+ expect(catalog).to have_resource("Notify[3]")
1626
+ end
1627
+
1628
+ it 'denies non-type-compliant arguments' do
1629
+ expect do
1630
+ compile_to_catalog(<<-MANIFEST)
1631
+ with(1) |String $x| { }
1632
+ MANIFEST
1633
+ end.to raise_error(/expected.*String.*actual.*Integer/m)
1634
+ end
1635
+
1636
+ it 'denies non-type-compliant, slurped arguments' do
1637
+ expect do
1638
+ compile_to_catalog(<<-MANIFEST)
1639
+ with(1, "hello") |Integer *$x| { }
1640
+ MANIFEST
1641
+ end.to raise_error(/called with mis-matched arguments.*expected.*Integer.*actual.*Integer, String/m)
1642
+ end
1643
+
1644
+ it 'denies non-type-compliant default argument' do
1645
+ expect do
1646
+ compile_to_catalog(<<-MANIFEST)
1647
+ with(1) |$x, String $defaulted = 1| { notify { "${$x + $defaulted}": }}
1648
+ MANIFEST
1649
+ end.to raise_error(/expected.*Any.*String.*actual.*Integer.*Integer/m)
1650
+ end
1651
+
1652
+ it 'raises an error when a default argument value is an incorrect type and there are no arguments passed' do
1653
+ expect do
1654
+ compile_to_catalog(<<-MANIFEST)
1655
+ with() |String $defaulted = 1| {}
1656
+ MANIFEST
1657
+ end.to raise_error(/expected.*String.*actual.*Integer/m)
1658
+ end
1659
+
1660
+ it 'raises an error when the default argument for a slurped parameter is an incorrect type' do
1661
+ expect do
1662
+ compile_to_catalog(<<-MANIFEST)
1663
+ with() |String *$defaulted = 1| {}
1664
+ MANIFEST
1665
+ end.to raise_error(/expected.*String.*actual.*Integer/m)
1666
+ end
1667
+
1668
+ it 'allows using an array as the default slurped value' do
1669
+ catalog = compile_to_catalog(<<-MANIFEST)
1670
+ with() |String *$defaulted = [hi]| { notify { $defaulted[0]: } }
1671
+ MANIFEST
1672
+
1673
+ expect(catalog).to have_resource('Notify[hi]')
1674
+ end
1675
+
1676
+ it 'allows using a value of the type as the default slurped value' do
1677
+ catalog = compile_to_catalog(<<-MANIFEST)
1678
+ with() |String *$defaulted = hi| { notify { $defaulted[0]: } }
1679
+ MANIFEST
1680
+
1681
+ expect(catalog).to have_resource('Notify[hi]')
1682
+ end
1683
+
1684
+ it 'allows specifying the type of a slurped parameter as an array' do
1685
+ catalog = compile_to_catalog(<<-MANIFEST)
1686
+ with() |Array[String] *$defaulted = hi| { notify { $defaulted[0]: } }
1687
+ MANIFEST
1688
+
1689
+ expect(catalog).to have_resource('Notify[hi]')
1690
+ end
1691
+
1692
+ it 'raises an error when the number of default values does not match the parameter\'s size specification' do
1693
+ expect do
1694
+ compile_to_catalog(<<-MANIFEST)
1695
+ with() |Array[String, 2] *$defaulted = hi| { }
1696
+ MANIFEST
1697
+ end.to raise_error(/expected.*arg count \{2,\}.*actual.*arg count \{1\}/m)
1698
+ end
1699
+
1700
+ it 'raises an error when the number of passed values does not match the parameter\'s size specification' do
1701
+ expect do
1702
+ compile_to_catalog(<<-MANIFEST)
1703
+ with(hi) |Array[String, 2] *$passed| { }
1704
+ MANIFEST
1705
+ end.to raise_error(/expected.*arg count \{2,\}.*actual.*arg count \{1\}/m)
1706
+ end
1707
+
1708
+ it 'matches when the number of arguments passed for a slurp parameter match the size specification' do
1709
+ catalog = compile_to_catalog(<<-MANIFEST)
1710
+ with(hi, bye) |Array[String, 2] *$passed| {
1711
+ $passed.each |$n| { notify { $n: } }
1712
+ }
1713
+ MANIFEST
1714
+
1715
+ expect(catalog).to have_resource('Notify[hi]')
1716
+ expect(catalog).to have_resource('Notify[bye]')
1717
+ end
1718
+
1719
+ it 'raises an error when the number of allowed slurp parameters exceeds the size constraint' do
1720
+ expect do
1721
+ compile_to_catalog(<<-MANIFEST)
1722
+ with(hi, bye) |Array[String, 1, 1] *$passed| { }
1723
+ MANIFEST
1724
+ end.to raise_error(/expected.*arg count \{1\}.*actual.*arg count \{2\}/m)
1725
+ end
1726
+
1727
+ it 'allows passing slurped arrays by specifying an array of arrays' do
1728
+ catalog = compile_to_catalog(<<-MANIFEST)
1729
+ with([hi], [bye]) |Array[Array[String, 1, 1]] *$passed| {
1730
+ notify { $passed[0][0]: }
1731
+ notify { $passed[1][0]: }
1732
+ }
1733
+ MANIFEST
1734
+
1735
+ expect(catalog).to have_resource('Notify[hi]')
1736
+ expect(catalog).to have_resource('Notify[bye]')
1737
+ end
1738
+
1739
+ it 'raises an error when a required argument follows an optional one' do
1740
+ expect do
1741
+ compile_to_catalog(<<-MANIFEST)
1742
+ with() |$y = first, $x, Array[String, 1] *$passed = bye| {}
1743
+ MANIFEST
1744
+ end.to raise_error(/Parameter \$x is required/)
1745
+ end
1746
+
1747
+ it 'raises an error when the minimum size of a slurped argument makes it required and it follows an optional argument' do
1748
+ expect do
1749
+ compile_to_catalog(<<-MANIFEST)
1750
+ with() |$x = first, Array[String, 1] *$passed| {}
1751
+ MANIFEST
1752
+ end.to raise_error(/Parameter \$passed is required/)
1753
+ end
1754
+
1755
+ it 'allows slurped arguments with a minimum size of 0 after an optional argument' do
1756
+ catalog = compile_to_catalog(<<-MANIFEST)
1757
+ with() |$x = first, Array[String, 0] *$passed| {
1758
+ notify { $x: }
1759
+ }
1760
+ MANIFEST
1761
+
1762
+ expect(catalog).to have_resource('Notify[first]')
1763
+ end
1764
+
1765
+ it 'accepts a Resource as a Type' do
1766
+ catalog = compile_to_catalog(<<-MANIFEST)
1767
+ define bar($text) { }
1768
+ bar { 'joke': text => 'knock knock' }
1769
+
1770
+ with(Bar[joke]) |Type[Bar] $joke| { notify { "${joke[text]}": } }
1771
+ MANIFEST
1772
+ expect(catalog).to have_resource("Notify[knock knock]")
1773
+ end
1774
+ end
1775
+ end
1776
+
927
1777
  end