puppet 6.0.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (259) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -2
  3. data/Gemfile.lock +20 -20
  4. data/Guardfile.example +76 -0
  5. data/LICENSE +189 -4
  6. data/README.md +3 -3
  7. data/Rakefile +5 -2
  8. data/ext/solaris/smf/svc-puppetd +8 -1
  9. data/ext/solaris/smf/svc-puppetmasterd +8 -1
  10. data/lib/puppet/application/apply.rb +100 -59
  11. data/lib/puppet/application/cert.rb +4 -114
  12. data/lib/puppet/application/device.rb +48 -32
  13. data/lib/puppet/application/script.rb +1 -1
  14. data/lib/puppet/application/ssl.rb +135 -51
  15. data/lib/puppet/application.rb +5 -0
  16. data/lib/puppet/configurer.rb +2 -3
  17. data/lib/puppet/defaults.rb +33 -49
  18. data/lib/puppet/etc.rb +20 -0
  19. data/lib/puppet/face/config.rb +3 -3
  20. data/lib/puppet/face/key.rb +1 -1
  21. data/lib/puppet/face/node/clean.rb +0 -1
  22. data/lib/puppet/feature/base.rb +1 -1
  23. data/lib/puppet/file_bucket/dipper.rb +1 -1
  24. data/lib/puppet/file_serving/fileset.rb +1 -1
  25. data/lib/puppet/functions/abs.rb +1 -1
  26. data/lib/puppet/functions/new.rb +1 -1
  27. data/lib/puppet/module/task.rb +29 -38
  28. data/lib/puppet/pal/catalog_compiler.rb +96 -0
  29. data/lib/puppet/pal/compiler.rb +221 -0
  30. data/lib/puppet/pal/function_signature.rb +52 -0
  31. data/lib/puppet/pal/json_catalog_encoder.rb +67 -0
  32. data/lib/puppet/pal/pal_api.rb +15 -0
  33. data/lib/puppet/pal/pal_impl.rb +523 -0
  34. data/lib/puppet/pal/plan_signature.rb +71 -0
  35. data/lib/puppet/pal/script_compiler.rb +71 -0
  36. data/lib/puppet/pal/task_signature.rb +58 -0
  37. data/lib/puppet/parser/catalog_compiler.rb +24 -0
  38. data/lib/puppet/parser/compiler.rb +3 -1
  39. data/lib/puppet/parser/functions/generate.rb +7 -6
  40. data/lib/puppet/plugins/configuration.rb +5 -1
  41. data/lib/puppet/pops/evaluator/collectors/abstract_collector.rb +3 -1
  42. data/lib/puppet/pops/evaluator/deferred_resolver.rb +3 -0
  43. data/lib/puppet/pops/evaluator/evaluator_impl.rb +5 -1
  44. data/lib/puppet/pops/evaluator/external_syntax_support.rb +3 -3
  45. data/lib/puppet/pops/evaluator/runtime3_converter.rb +2 -2
  46. data/lib/puppet/pops/loader/ruby_legacy_function_instantiator.rb +19 -10
  47. data/lib/puppet/pops/loader/task_instantiator.rb +13 -70
  48. data/lib/puppet/pops/parser/heredoc_support.rb +1 -2
  49. data/lib/puppet/pops/parser/lexer2.rb +1 -1
  50. data/lib/puppet/pops/pcore.rb +10 -33
  51. data/lib/puppet/pops/serialization/to_data_converter.rb +9 -1
  52. data/lib/puppet/pops/serialization.rb +1 -0
  53. data/lib/puppet/pops/types/p_timespan_type.rb +2 -2
  54. data/lib/puppet/pops/types/string_converter.rb +18 -4
  55. data/lib/puppet/pops/validation/checker4_0.rb +17 -2
  56. data/lib/puppet/provider/exec.rb +59 -57
  57. data/lib/puppet/provider/group/aix.rb +18 -2
  58. data/lib/puppet/provider/group/windows_adsi.rb +7 -3
  59. data/lib/puppet/provider/nameservice.rb +1 -25
  60. data/lib/puppet/provider/package/dnf.rb +2 -0
  61. data/lib/puppet/provider/package/pkgng.rb +37 -21
  62. data/lib/puppet/provider/package/portage.rb +2 -2
  63. data/lib/puppet/provider/package/windows/exe_package.rb +16 -10
  64. data/lib/puppet/provider/package/windows/msi_package.rb +8 -0
  65. data/lib/puppet/provider/package/windows/package.rb +9 -1
  66. data/lib/puppet/provider/package/windows.rb +2 -2
  67. data/lib/puppet/provider/package/yum.rb +1 -1
  68. data/lib/puppet/provider/parsedfile.rb +25 -4
  69. data/lib/puppet/provider/service/launchd.rb +19 -3
  70. data/lib/puppet/provider/service/smf.rb +54 -0
  71. data/lib/puppet/provider/service/systemd.rb +19 -0
  72. data/lib/puppet/provider/service/upstart.rb +1 -0
  73. data/lib/puppet/provider/service/windows.rb +22 -5
  74. data/lib/puppet/provider/user/aix.rb +48 -2
  75. data/lib/puppet/provider/user/useradd.rb +2 -10
  76. data/lib/puppet/provider/user/windows_adsi.rb +9 -1
  77. data/lib/puppet/resource/catalog.rb +1 -5
  78. data/lib/puppet/resource.rb +3 -1
  79. data/lib/puppet/ssl/host.rb +26 -16
  80. data/lib/puppet/syntax_checkers/epp.rb +34 -0
  81. data/lib/puppet/syntax_checkers/pp.rb +34 -0
  82. data/lib/puppet/transaction/event_manager.rb +13 -1
  83. data/lib/puppet/transaction/persistence.rb +1 -1
  84. data/lib/puppet/transaction/resource_harness.rb +3 -1
  85. data/lib/puppet/type/group.rb +29 -1
  86. data/lib/puppet/type/package.rb +5 -1
  87. data/lib/puppet/type/resources.rb +12 -2
  88. data/lib/puppet/type/schedule.rb +7 -0
  89. data/lib/puppet/type/service.rb +12 -0
  90. data/lib/puppet/type/user.rb +5 -2
  91. data/lib/puppet/type.rb +6 -0
  92. data/lib/puppet/util/command_line.rb +2 -3
  93. data/lib/puppet/util/execution.rb +15 -1
  94. data/lib/puppet/util/filetype.rb +56 -8
  95. data/lib/puppet/util/log/destinations.rb +3 -2
  96. data/lib/puppet/util/logging.rb +3 -2
  97. data/lib/puppet/util/posix.rb +15 -0
  98. data/lib/puppet/util/selinux.rb +1 -1
  99. data/lib/puppet/util/storage.rb +12 -0
  100. data/lib/puppet/util/windows/adsi.rb +79 -2
  101. data/lib/puppet/util/windows/api_types.rb +1 -1
  102. data/lib/puppet/util/windows/process.rb +23 -3
  103. data/lib/puppet/util/windows/registry.rb +29 -5
  104. data/lib/puppet/util/windows/security.rb +14 -0
  105. data/lib/puppet/util/windows/service.rb +294 -74
  106. data/lib/puppet/util/windows/user.rb +3 -5
  107. data/lib/puppet/util.rb +7 -3
  108. data/lib/puppet/version.rb +1 -1
  109. data/lib/puppet.rb +1 -0
  110. data/lib/puppet_pal.rb +5 -1099
  111. data/locales/ja/puppet.po +952 -986
  112. data/locales/puppet.pot +592 -347
  113. data/man/man5/puppet.conf.5 +26 -31
  114. data/man/man8/puppet-agent.8 +1 -1
  115. data/man/man8/puppet-apply.8 +1 -1
  116. data/man/man8/puppet-catalog.8 +1 -1
  117. data/man/man8/puppet-config.8 +4 -4
  118. data/man/man8/puppet-describe.8 +1 -1
  119. data/man/man8/puppet-device.8 +23 -19
  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-filebucket.8 +1 -1
  124. data/man/man8/puppet-generate.8 +1 -1
  125. data/man/man8/puppet-help.8 +1 -1
  126. data/man/man8/puppet-key.8 +2 -2
  127. data/man/man8/puppet-lookup.8 +1 -1
  128. data/man/man8/puppet-man.8 +1 -1
  129. data/man/man8/puppet-module.8 +1 -1
  130. data/man/man8/puppet-node.8 +1 -1
  131. data/man/man8/puppet-parser.8 +1 -1
  132. data/man/man8/puppet-plugin.8 +1 -1
  133. data/man/man8/puppet-report.8 +1 -1
  134. data/man/man8/puppet-resource.8 +1 -1
  135. data/man/man8/puppet-script.8 +1 -1
  136. data/man/man8/puppet-ssl.8 +26 -3
  137. data/man/man8/puppet-status.8 +1 -1
  138. data/man/man8/puppet.8 +2 -2
  139. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/usee/lib/puppet/parser/functions/bad_func_load.rb +11 -0
  140. data/spec/fixtures/unit/provider/package/pkgng/pkg.query +7 -1
  141. data/spec/fixtures/unit/provider/package/pkgng/pkg.query.zsh +1 -0
  142. data/spec/fixtures/unit/provider/service/smf/svcs_fmri.out +6 -0
  143. data/spec/fixtures/unit/provider/service/smf/svcs_multiple_fmris.out +13 -0
  144. data/spec/integration/application/apply_spec.rb +4 -1
  145. data/spec/integration/parser/collection_spec.rb +4 -8
  146. data/spec/integration/provider/service/windows_spec.rb +5 -5
  147. data/spec/integration/ssl/key_spec.rb +0 -4
  148. data/spec/integration/transaction_spec.rb +559 -0
  149. data/spec/integration/type/file_spec.rb +6 -6
  150. data/spec/integration/util/windows/registry_spec.rb +39 -0
  151. data/spec/integration/util/windows/security_spec.rb +10 -7
  152. data/spec/integration/util/windows/user_spec.rb +37 -17
  153. data/spec/lib/puppet/test_ca.rb +1 -1
  154. data/spec/spec_helper.rb +1 -1
  155. data/spec/unit/agent_spec.rb +2 -2
  156. data/spec/unit/application/apply_spec.rb +55 -2
  157. data/spec/unit/application/device_spec.rb +10 -7
  158. data/spec/unit/application/face_base_spec.rb +1 -1
  159. data/spec/unit/application/lookup_spec.rb +2 -1
  160. data/spec/unit/application/ssl_spec.rb +178 -109
  161. data/spec/unit/application_spec.rb +29 -11
  162. data/spec/unit/configurer/downloader_spec.rb +1 -1
  163. data/spec/unit/configurer_spec.rb +16 -5
  164. data/spec/unit/etc_spec.rb +25 -0
  165. data/spec/unit/face/node_spec.rb +1 -3
  166. data/spec/unit/face/parser_spec.rb +15 -0
  167. data/spec/unit/file_serving/fileset_spec.rb +11 -11
  168. data/spec/unit/functions/logging_spec.rb +10 -3
  169. data/spec/unit/indirector/catalog/json_spec.rb +9 -3
  170. data/spec/unit/indirector/yaml_spec.rb +1 -1
  171. data/spec/unit/network/http/connection_spec.rb +2 -2
  172. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +36 -0
  173. data/spec/unit/pops/evaluator/runtime3_converter_spec.rb +22 -4
  174. data/spec/unit/pops/loaders/loader_spec.rb +9 -17
  175. data/spec/unit/pops/loaders/loaders_spec.rb +48 -0
  176. data/spec/unit/pops/loaders/module_loaders_spec.rb +7 -7
  177. data/spec/unit/pops/parser/parse_heredoc_spec.rb +16 -0
  178. data/spec/unit/pops/serialization/to_from_hr_spec.rb +9 -0
  179. data/spec/unit/pops/types/p_timespan_type_spec.rb +22 -0
  180. data/spec/unit/pops/types/p_timestamp_type_spec.rb +19 -0
  181. data/spec/unit/pops/types/string_converter_spec.rb +25 -1
  182. data/spec/unit/pops/types/task_spec.rb +42 -116
  183. data/spec/unit/pops/validator/validator_spec.rb +24 -10
  184. data/spec/unit/provider/exec/posix_spec.rb +24 -0
  185. data/spec/unit/provider/group/aix_spec.rb +20 -6
  186. data/spec/unit/provider/group/ldap_spec.rb +22 -25
  187. data/spec/unit/provider/group/pw_spec.rb +7 -10
  188. data/spec/unit/provider/group/windows_adsi_spec.rb +42 -33
  189. data/spec/unit/provider/nameservice/directoryservice_spec.rb +97 -103
  190. data/spec/unit/provider/package/aix_spec.rb +5 -8
  191. data/spec/unit/provider/package/apt_spec.rb +3 -6
  192. data/spec/unit/provider/package/dnf_spec.rb +38 -25
  193. data/spec/unit/provider/package/dpkg_spec.rb +18 -21
  194. data/spec/unit/provider/package/freebsd_spec.rb +4 -7
  195. data/spec/unit/provider/package/gem_spec.rb +41 -41
  196. data/spec/unit/provider/package/hpux_spec.rb +7 -10
  197. data/spec/unit/provider/package/macports_spec.rb +13 -15
  198. data/spec/unit/provider/package/nim_spec.rb +3 -10
  199. data/spec/unit/provider/package/openbsd_spec.rb +14 -17
  200. data/spec/unit/provider/package/pip3_spec.rb +3 -6
  201. data/spec/unit/provider/package/pip_spec.rb +45 -49
  202. data/spec/unit/provider/package/pkgin_spec.rb +13 -18
  203. data/spec/unit/provider/package/pkgng_spec.rb +32 -27
  204. data/spec/unit/provider/package/puppet_gem_spec.rb +6 -9
  205. data/spec/unit/provider/package/tdnf_spec.rb +9 -12
  206. data/spec/unit/provider/package/windows/exe_package_spec.rb +3 -3
  207. data/spec/unit/provider/package/windows_spec.rb +4 -4
  208. data/spec/unit/provider/package/yum_spec.rb +30 -16
  209. data/spec/unit/provider/package/zypper_spec.rb +17 -19
  210. data/spec/unit/provider/service/bsd_spec.rb +7 -9
  211. data/spec/unit/provider/service/daemontools_spec.rb +12 -16
  212. data/spec/unit/provider/service/debian_spec.rb +6 -10
  213. data/spec/unit/provider/service/freebsd_spec.rb +2 -2
  214. data/spec/unit/provider/service/launchd_spec.rb +19 -0
  215. data/spec/unit/provider/service/openbsd_spec.rb +13 -17
  216. data/spec/unit/provider/service/rcng_spec.rb +2 -4
  217. data/spec/unit/provider/service/redhat_spec.rb +12 -11
  218. data/spec/unit/provider/service/runit_spec.rb +7 -14
  219. data/spec/unit/provider/service/smf_spec.rb +77 -13
  220. data/spec/unit/provider/service/src_spec.rb +11 -16
  221. data/spec/unit/provider/service/systemd_spec.rb +39 -1
  222. data/spec/unit/provider/service/windows_spec.rb +39 -7
  223. data/spec/unit/provider/user/aix_spec.rb +43 -2
  224. data/spec/unit/provider/user/hpux_spec.rb +3 -5
  225. data/spec/unit/provider/user/ldap_spec.rb +29 -32
  226. data/spec/unit/provider/user/pw_spec.rb +10 -13
  227. data/spec/unit/provider/user/useradd_spec.rb +2 -2
  228. data/spec/unit/provider/user/windows_adsi_spec.rb +4 -4
  229. data/spec/unit/puppet_pal_2pec.rb +6 -6
  230. data/spec/unit/puppet_pal_catalog_spec.rb +58 -0
  231. data/spec/unit/resource/catalog_spec.rb +2 -2
  232. data/spec/unit/resource_spec.rb +31 -0
  233. data/spec/unit/ssl/host_spec.rb +22 -1
  234. data/spec/unit/ssl/key_spec.rb +2 -4
  235. data/spec/unit/task_spec.rb +50 -5
  236. data/spec/unit/transaction/event_manager_spec.rb +12 -1
  237. data/spec/unit/transaction/persistence_spec.rb +4 -4
  238. data/spec/unit/transaction/resource_harness_spec.rb +18 -0
  239. data/spec/unit/type/group_spec.rb +11 -3
  240. data/spec/unit/type/resources_spec.rb +18 -0
  241. data/spec/unit/type/service_spec.rb +27 -1
  242. data/spec/unit/util/execution_spec.rb +77 -0
  243. data/spec/unit/util/filetype_spec.rb +13 -5
  244. data/spec/unit/util/log/destinations_spec.rb +10 -0
  245. data/spec/unit/util/logging_spec.rb +58 -41
  246. data/spec/unit/util/monkey_patches_spec.rb +18 -5
  247. data/spec/unit/util/posix_spec.rb +28 -0
  248. data/spec/unit/util/selinux_spec.rb +4 -0
  249. data/spec/unit/util/storage_spec.rb +107 -0
  250. data/spec/unit/util/suidmanager_spec.rb +1 -3
  251. data/spec/unit/util/windows/adsi_spec.rb +95 -0
  252. data/spec/unit/util/windows/service_spec.rb +377 -131
  253. metadata +24 -11
  254. data/ext/autotest/Rakefile +0 -8
  255. data/ext/autotest/config +0 -43
  256. data/ext/autotest/readme.rst +0 -16
  257. data/spec/fixtures/unit/provider/package/pkgng/pkg.info +0 -7
  258. data/spec/fixtures/unit/provider/package/pkgng/pkg.query_absent +0 -1
  259. data/spec/watchr.rb +0 -137
@@ -0,0 +1,58 @@
1
+ module Puppet
2
+ module Pal
3
+ # A TaskSignature is returned from `task_signature`. Its purpose is to answer questions about the task's parameters
4
+ # and if it can be run/called with a hash of named parameters.
5
+ #
6
+ class TaskSignature
7
+ def initialize(task)
8
+ @task = task
9
+ end
10
+
11
+ # Returns whether or not the given arguments are acceptable when running the task.
12
+ # In addition to returning the boolean outcome, if a block is given, it is called with a string of formatted
13
+ # error messages that describes the difference between what was given and what is expected. The error message may
14
+ # have multiple lines of text, and each line is indented one space.
15
+ #
16
+ # @param args_hash [Hash] a hash mapping parameter names to argument values
17
+ # @yieldparam [String] a formatted error message if a type mismatch occurs that explains the mismatch
18
+ # @return [Boolean] if the given arguments are acceptable when running the task
19
+ #
20
+ def runnable_with?(args_hash)
21
+ params = @task.parameters
22
+ params_type = if params.nil?
23
+ T_GENERIC_TASK_HASH
24
+ else
25
+ Puppet::Pops::Types::TypeFactory.struct(params)
26
+ end
27
+ return true if params_type.instance?(args_hash)
28
+
29
+ if block_given?
30
+ tm = Puppet::Pops::Types::TypeMismatchDescriber.singleton
31
+ error = if params.nil?
32
+ tm.describe_mismatch('', params_type, Puppet::Pops::Types::TypeCalculator.infer_set(args_hash))
33
+ else
34
+ tm.describe_struct_signature(params_type, args_hash).flatten.map {|e| e.format }.join("\n")
35
+ end
36
+ yield "Task #{@task.name}:\n#{error}"
37
+ end
38
+ false
39
+ end
40
+
41
+ # Returns the Task instance as a hash
42
+ #
43
+ # @return [Hash{String=>Object}] the hash representation of the task
44
+ def task_hash
45
+ @task._pcore_init_hash
46
+ end
47
+
48
+ # Returns the Task instance which can be further explored. It contains all meta-data defined for
49
+ # the task such as the description, parameters, output, etc.
50
+ #
51
+ # @return [Puppet::Pops::Types::PuppetObject] An instance of a dynamically created Task class
52
+ def task
53
+ @task
54
+ end
55
+ end
56
+
57
+ end
58
+ end
@@ -29,4 +29,28 @@ class Puppet::Parser::CatalogCompiler < Puppet::Parser::Compiler
29
29
  raise Puppet::Error, message, detail.backtrace
30
30
  end
31
31
 
32
+ # Evaluates all added constructs, and validates the resulting catalog.
33
+ # This can be called whenever a series of evaluation of puppet code strings
34
+ # have reached a stable state (essentially that there are no relationships to
35
+ # non-existing resources).
36
+ #
37
+ # Raises an error if validation fails.
38
+ #
39
+ def compile_additions
40
+ evaluate_additions
41
+ validate
42
+ end
43
+
44
+ # Evaluates added constructs that are lazily evaluated until all of them have been evaluated.
45
+ #
46
+ def evaluate_additions
47
+ evaluate_generators
48
+ finish
49
+ end
50
+
51
+ # Validates the current state of the catalog.
52
+ # Does not cause evaluation of lazy constructs.
53
+ def validate
54
+ validate_catalog(CatalogValidator::FINAL)
55
+ end
32
56
  end
@@ -577,6 +577,7 @@ class Puppet::Parser::Compiler
577
577
  end
578
578
  end
579
579
  end
580
+ protected :evaluate_generators
580
581
 
581
582
  # Find and evaluate our main object, if possible.
582
583
  def evaluate_main
@@ -641,6 +642,7 @@ class Puppet::Parser::Compiler
641
642
 
642
643
  add_resource_metaparams
643
644
  end
645
+ protected :finish
644
646
 
645
647
  def add_resource_metaparams
646
648
  unless main = catalog.resource(:class, :main)
@@ -780,8 +782,8 @@ class Puppet::Parser::Compiler
780
782
  settings_resource = Puppet::Parser::Resource.new('class', SETTINGS, :scope => @topscope)
781
783
 
782
784
  @catalog.add_resource(settings_resource)
783
-
784
785
  settings_type.evaluate_code(settings_resource)
786
+ settings_resource.instance_variable_set(:@evaluated, true) # Prevents settings from being reevaluated
785
787
 
786
788
  scope = @topscope.class_scope(settings_type)
787
789
  scope.merge_settings(environment.name)
@@ -1,15 +1,16 @@
1
1
  # Runs an external command and returns the results
2
2
  Puppet::Parser::Functions::newfunction(:generate, :arity => -2, :type => :rvalue,
3
3
  :doc => "Calls an external command on the Puppet master and returns
4
- the results of the command. Any arguments are passed to the external command as
5
- arguments. If the generator does not exit with return code of 0,
4
+ the results of the command. Any arguments are passed to the external command as
5
+ arguments. If the generator does not exit with return code of 0,
6
6
  the generator is considered to have failed and a parse error is
7
- thrown. Generators can only have file separators, alphanumerics, dashes,
8
- and periods in them. This function will attempt to protect you from
7
+ thrown. Generators can only have file separators, alphanumerics, dashes,
8
+ and periods in them. This function will attempt to protect you from
9
9
  malicious generator calls (e.g., those with '..' in them), but it can
10
- never be entirely safe. No subshell is used to execute
10
+ never be entirely safe. No subshell is used to execute
11
11
  generators, so all shell metacharacters are passed directly to
12
- the generator.") do |args|
12
+ the generator, and all metacharacters are returned by the function.
13
+ Consider cleaning white space from any string generated.") do |args|
13
14
 
14
15
  #TRANSLATORS "fully qualified" refers to a fully qualified file system path
15
16
  raise Puppet::ParseError, _("Generators must be fully qualified") unless Puppet::Util.absolute_path?(args[0])
@@ -10,6 +10,8 @@ module Puppet::Plugins
10
10
  require 'puppet/plugins/syntax_checkers'
11
11
  require 'puppet/syntax_checkers/base64'
12
12
  require 'puppet/syntax_checkers/json'
13
+ require 'puppet/syntax_checkers/pp'
14
+ require 'puppet/syntax_checkers/epp'
13
15
 
14
16
  def self.load_plugins
15
17
  # Register extensions
@@ -17,7 +19,9 @@ module Puppet::Plugins
17
19
  {
18
20
  SyntaxCheckers::SYNTAX_CHECKERS_KEY => {
19
21
  'json' => Puppet::SyntaxCheckers::Json.new,
20
- 'base64' => Puppet::SyntaxCheckers::Base64.new
22
+ 'base64' => Puppet::SyntaxCheckers::Base64.new,
23
+ 'pp' => Puppet::SyntaxCheckers::PP.new,
24
+ 'epp' => Puppet::SyntaxCheckers::EPP.new
21
25
  }
22
26
  }
23
27
  end
@@ -51,7 +51,9 @@ class Puppet::Pops::Evaluator::Collectors::AbstractCollector
51
51
 
52
52
  objects.each do |res|
53
53
  unless @collected.include?(res.ref)
54
- newres = Puppet::Parser::Resource.new(res.type, res.title, @overrides)
54
+ t = res.type
55
+ t = Puppet::Pops::Evaluator::Runtime3ResourceSupport.find_resource_type(scope, t)
56
+ newres = Puppet::Parser::Resource.new(t, res.title, @overrides)
55
57
  scope.compiler.add_override(newres)
56
58
  end
57
59
  end
@@ -96,6 +96,9 @@ class DeferredResolver
96
96
  elsif x.is_a?(Puppet::Pops::Types::PSensitiveType::Sensitive)
97
97
  # rewrap in a new Sensitive after resolving any nested deferred values
98
98
  Puppet::Pops::Types::PSensitiveType::Sensitive.new(resolve(x.unwrap))
99
+ elsif x.is_a?(Puppet::Pops::Types::PBinaryType::Binary)
100
+ # use the ASCII-8BIT string that it wraps
101
+ x.binary_buffer
99
102
  else
100
103
  x
101
104
  end
@@ -1028,8 +1028,12 @@ class EvaluatorImpl
1028
1028
 
1029
1029
  # Evaluates Puppet DSL Heredoc
1030
1030
  def eval_HeredocExpression o, scope
1031
+ expr = o.text_expr.expr # Always a SublocatedExpression with an expression
1031
1032
  result = evaluate(o.text_expr, scope)
1032
- assert_external_syntax(scope, result, o.syntax, o.text_expr)
1033
+ unless expr.is_a?(Model::LiteralString)
1034
+ # When expr is a LiteralString, validation has already validated this
1035
+ assert_external_syntax(scope, result, o.syntax, o.text_expr)
1036
+ end
1033
1037
  result
1034
1038
  end
1035
1039
 
@@ -3,11 +3,11 @@
3
3
  #
4
4
  require 'puppet/plugins/syntax_checkers'
5
5
  module Puppet::Pops::Evaluator::ExternalSyntaxSupport
6
- def assert_external_syntax(scope, result, syntax, reference_expr)
6
+ def assert_external_syntax(_, result, syntax, reference_expr)
7
7
  # ignore 'unspecified syntax'
8
8
  return if syntax.nil? || syntax == ''
9
9
 
10
- checker = checker_for_syntax(scope, syntax)
10
+ checker = checker_for_syntax(nil, syntax)
11
11
  # ignore syntax with no matching checker
12
12
  return unless checker
13
13
 
@@ -26,7 +26,7 @@ module Puppet::Pops::Evaluator::ExternalSyntaxSupport
26
26
  # Finds the most significant checker for the given syntax (most significant is to the right).
27
27
  # Returns nil if there is no registered checker.
28
28
  #
29
- def checker_for_syntax(scope, syntax)
29
+ def checker_for_syntax(_, syntax)
30
30
  checkers_hash = Puppet.lookup(:plugins)[Puppet::Plugins::SyntaxCheckers::SYNTAX_CHECKERS_KEY]
31
31
  checkers_hash[lookup_keys_for_syntax(syntax).find {|x| checkers_hash[x] }]
32
32
  end
@@ -105,8 +105,8 @@ class Runtime3Converter
105
105
  end
106
106
 
107
107
  def convert_Symbol(o, scope, undef_value)
108
- o == :undef ? undef_value : o
109
- #o == :undef && !@inner ? undef_value : o
108
+ return o unless o == :undef
109
+ !@inner ? undef_value : nil
110
110
  end
111
111
 
112
112
  def convert_PAnyType(o, scope, undef_value)
@@ -20,17 +20,26 @@ class Puppet::Pops::Loader::RubyLegacyFunctionInstantiator
20
20
  loader_for_function = loader.private_loader
21
21
  here = get_binding(loader_for_function)
22
22
 
23
- # This will to do the 3x loading and define the "function_<name>" and "real_function_<name>" methods
24
- # in the anonymous module used to hold function definitions.
25
- #
26
- func_info = eval(ruby_code_string, here, source_ref, 1)
23
+ # Avoid reloading the function if already loaded via one of the APIs that trigger 3x function loading
24
+ # Check if function is already loaded the 3x way (and obviously not the 4x way since we would not be here in the
25
+ # first place.
26
+ environment = Puppet.lookup(:current_environment)
27
+ func_info = Puppet::Parser::Functions.environment_module(environment).get_function_info(typed_name.name.to_sym)
28
+ if func_info.nil?
29
+ # This will to do the 3x loading and define the "function_<name>" and "real_function_<name>" methods
30
+ # in the anonymous module used to hold function definitions.
31
+ #
32
+ func_info = eval(ruby_code_string, here, source_ref, 1)
27
33
 
28
- unless func_info.is_a?(Hash)
29
- raise ArgumentError, _("The code loaded from %{source_ref} did not produce the expected 3x function info Hash when evaluated. Got '%{klass}'") % { source_ref: source_ref, klass: created.class }
30
- end
31
- unless func_info[:name] == "function_#{typed_name.name()}"
32
- raise ArgumentError, _("The code loaded from %{source_ref} produced mis-matched name, expected 'function_%{type_name}', got %{created_name}") % {
33
- source_ref: source_ref, type_name: typed_name.name, created_name: func_info[:name] }
34
+ # Validate what was loaded
35
+ unless func_info.is_a?(Hash)
36
+ # TRANSLATORS - the word 'newfunction' shoud not be translated as it is a method name.
37
+ raise ArgumentError, _("Illegal legacy function definition! The code loaded from %{source_ref} did not return the result of calling 'newfunction'. Got '%{klass}'") % { source_ref: source_ref, klass: func_info.class }
38
+ end
39
+ unless func_info[:name] == "function_#{typed_name.name()}"
40
+ raise ArgumentError, _("The code loaded from %{source_ref} produced mis-matched name, expected 'function_%{type_name}', got '%{created_name}'") % {
41
+ source_ref: source_ref, type_name: typed_name.name, created_name: func_info[:name] }
42
+ end
34
43
  end
35
44
 
36
45
  created = Puppet::Functions::Function3x.create_function(typed_name.name(), func_info, loader_for_function)
@@ -1,58 +1,9 @@
1
1
  # The TypeDefinitionInstantiator instantiates a type alias or a type definition
2
2
  #
3
+ require 'puppet/module/task'
3
4
  module Puppet::Pops
4
5
  module Loader
5
6
  class TaskInstantiator
6
- def self.load_metadata(loader, metadata)
7
- if metadata.nil?
8
- EMPTY_HASH
9
- else
10
- json_text = loader.get_contents(metadata)
11
- begin
12
- Puppet::Util::Json.load(json_text).freeze || EMPTY_HASH
13
- rescue Puppet::Util::Json::ParseError => ex
14
- raise Puppet::ParseError.new(ex.message, metadata)
15
- end
16
- end
17
- end
18
-
19
- def self.validate_implementations(typed_name, directory, metadata, executables)
20
- name = typed_name.name
21
- basename = typed_name.name_parts[1] || 'init'
22
- # If 'implementations' is defined, it needs to mention at least one
23
- # implementation, and everything it mentions must exist.
24
- if metadata.key?('implementations')
25
- if metadata['implementations'].is_a?(Array)
26
- metadata['implementations'].map do |impl|
27
- path = executables.find { |real_impl| File.basename(real_impl) == impl['name'] }
28
- if path
29
- { "name" => impl['name'], "requirements" => impl.fetch('requirements', []), "path" => path }
30
- else
31
- raise ArgumentError, _("Task metadata for task %{name} specifies missing implementation %{implementation}") %
32
- { name: name, implementation: impl['name'] }
33
- end
34
- end
35
- else
36
- # If 'implementations' is the wrong type, we just pass it through and
37
- # let the task type definition reject it.
38
- metadata['implementations']
39
- end
40
- # If implementations isn't defined, then we use executables matching the
41
- # task name, and only one may exist.
42
- else
43
- implementations = executables.select { |impl| File.basename(impl, '.*') == basename }
44
- if implementations.empty?
45
- raise ArgumentError, _('No source besides task metadata was found in directory %{directory} for task %{name}') %
46
- { name: name, directory: directory }
47
- elsif implementations.length > 1
48
- raise ArgumentError, _("Multiple executables were found in directory %{directory} for task %{name}; define 'implementations' in metadata to differentiate between them") %
49
- { name: name, directory: implementations[0] }
50
- end
51
-
52
- [{ "name" => File.basename(implementations.first), "path" => implementations.first, "requirements" => [] }]
53
- end
54
- end
55
-
56
7
  def self.create(loader, typed_name, source_refs)
57
8
  name = typed_name.name
58
9
  basename = typed_name.name_parts[1] || 'init'
@@ -60,31 +11,16 @@ class TaskInstantiator
60
11
  metadata_files, executables = source_refs.partition { |source_ref| source_ref.end_with?('.json') }
61
12
  metadata_file = metadata_files.find { |source_ref| File.basename(source_ref, '.json') == basename }
62
13
 
63
- metadata = load_metadata(loader, metadata_file)
14
+ metadata = Puppet::Module::Task.read_metadata(metadata_file) || {}
64
15
 
65
- implementation_metadata = validate_implementations(typed_name, dirname, metadata, executables)
16
+ files = Puppet::Module::Task.find_files(name, dirname, metadata, executables)
66
17
 
67
- arguments = {
68
- 'name' => name,
69
- 'implementations' => implementation_metadata
70
- }
18
+ task = { 'name' => name, 'metadata' => metadata, 'files' => files }
71
19
 
72
20
  begin
73
- metadata.each_pair do |key, value|
74
- if %w[parameters output].include?(key)
75
- ps = {}
76
- value.each_pair do |k, v|
77
- pd = v.dup
78
- t = v['type']
79
- pd['type'] = t.nil? ? Types::TypeFactory.data : Types::TypeParser.singleton.parse(t)
80
- ps[k] = pd
81
- end
82
- value = ps
83
- end
84
- arguments[key] = value unless arguments.key?(key)
85
- end
21
+ task['parameters'] = convert_types(metadata['parameters'])
86
22
 
87
- Types::TypeFactory.task.from_hash(arguments)
23
+ Types::TypeFactory.task.from_hash(task)
88
24
  rescue Types::TypeAssertionError => ex
89
25
  # Not strictly a parser error but from the users perspective, the file content didn't parse properly. The
90
26
  # ParserError also conveys file info (even though line is unknown)
@@ -92,6 +28,13 @@ class TaskInstantiator
92
28
  raise Puppet::ParseError.new(msg, metadata_file)
93
29
  end
94
30
  end
31
+
32
+ def self.convert_types(args)
33
+ args.each_with_object({}) do |(k, v), hsh|
34
+ hsh[k] = v['type'].nil? ? Types::TypeFactory.data : Types::TypeParser.singleton.parse(v['type'])
35
+ end if args
36
+ end
37
+ private_class_method :convert_types
95
38
  end
96
39
  end
97
40
  end
@@ -98,8 +98,7 @@ module HeredocSupport
98
98
 
99
99
  # Use a new lexer instance configured with a sub-locator to enable correct positioning
100
100
  sublexer = self.class.new()
101
- locator = Locator::SubLocator.sub_locator(str,
102
- locator.file, heredoc_line, heredoc_offset, leading.length())
101
+ locator = Locator::SubLocator.new(locator, heredoc_line, heredoc_offset, leading.length())
103
102
 
104
103
  # Emit a token that provides the grammar with location information about the lines on which the heredoc
105
104
  # content is based.
@@ -189,7 +189,7 @@ class Lexer2
189
189
  ',' => lambda { emit(TOKEN_COMMA, @scanner.pos) },
190
190
  '[' => lambda do
191
191
  before = @scanner.pos
192
- if (before == 0 || @scanner.string[locator.char_offset(before)-1,1] =~ /[[:blank:]\r\n]+/)
192
+ if (before == 0 || locator.string[locator.char_offset(before)-1,1] =~ /[[:blank:]\r\n]+/)
193
193
  emit(TOKEN_LISTSTART, before)
194
194
  else
195
195
  emit(TOKEN_LBRACK, before)
@@ -39,39 +39,16 @@ module Pcore
39
39
  # Fully qualified name of the task
40
40
  name => { type => Pattern[/\\A[a-z][a-z0-9_]*(?:::[a-z][a-z0-9_]*)*\\z/] },
41
41
 
42
- # List of implementations with requirements
43
- implementations => { type => Array[Struct[name => String, path => String, Optional[requirements] => Array[String]], 1] },
44
-
45
- # Task description
46
- description => { type => Optional[String], value => undef },
47
-
48
- # Puppet Task version
49
- puppet_task_version => { type => Integer, value => 1 },
50
-
51
- # Type, description, and sensitive property of each parameter
52
- parameters => {
53
- type => Optional[Hash[
54
- Pattern[/\\A[a-z][a-z0-9_]*\\z/],
55
- Struct[
56
- Optional[description] => String,
57
- Optional[sensitive] => Boolean,
58
- type => Type]]],
59
- value => undef
60
- },
61
-
62
- # Type, description, and sensitive property of each output
63
- output => {
64
- type => Optional[Hash[
65
- Pattern[/\\A[a-z][a-z0-9_]*\\z/],
66
- Struct[
67
- Optional[description] => String,
68
- Optional[sensitive] => Boolean,
69
- type => Type]]],
70
- value => undef
71
- },
72
-
73
- supports_noop => { type => Boolean, value => false },
74
- input_method => { type => Optional[String] },
42
+ # List of file references referenced by metadata and their paths on disk.
43
+ # If there are no implementations listed in metadata, the first file is always
44
+ # the task executable.
45
+ files => { type => Array[Struct[name => String, path => String]] },
46
+
47
+ # Task metadata
48
+ metadata => { type => Hash[String, Any] },
49
+
50
+ # Map parameter names to their parsed data type
51
+ parameters => { type => Optional[Hash[Pattern[/\\A[a-z][a-z0-9_]*\\z/], Type]], value => undef },
75
52
  }
76
53
  }
77
54
  PUPPET
@@ -70,7 +70,15 @@ module Serialization
70
70
 
71
71
  def to_data(value)
72
72
  if value.nil? || Types::PScalarDataType::DEFAULT.instance?(value)
73
- value
73
+ if @rich_data && value.is_a?(String) && value.encoding == Encoding::ASCII_8BIT
74
+ # Transform the binary string to rich Binary
75
+ {
76
+ PCORE_TYPE_KEY => PCORE_TYPE_BINARY,
77
+ PCORE_VALUE_KEY => Puppet::Pops::Types::PBinaryType::Binary.from_binary_string(value).to_s
78
+ }
79
+ else
80
+ value
81
+ end
74
82
  elsif :default == value
75
83
  if @rich_data
76
84
  { PCORE_TYPE_KEY => PCORE_TYPE_DEFAULT }
@@ -19,6 +19,7 @@ module Serialization
19
19
 
20
20
  # Type key used for symbols
21
21
  PCORE_TYPE_SENSITIVE = 'Sensitive'.freeze
22
+ PCORE_TYPE_BINARY = 'Binary'.freeze
22
23
 
23
24
  # Type key used for symbols
24
25
  PCORE_TYPE_SYMBOL = 'Symbol'.freeze
@@ -65,9 +65,9 @@ module Types
65
65
  when String
66
66
  impl_class.parse(arg)
67
67
  when Integer
68
- arg == impl_class.new(arg * Time::NSECS_PER_SEC)
68
+ impl_class.new(arg * Time::NSECS_PER_SEC)
69
69
  when Float
70
- arg == (min ? -Float::INFINITY : Float::INFINITY) ? arg : impl_class.new(arg * Time::NSECS_PER_SEC)
70
+ impl_class.new(arg * Time::NSECS_PER_SEC)
71
71
  else
72
72
  raise ArgumentError, "Unable to create a #{impl_class.name} from a #{arg.class.name}" unless arg.nil? || arg == :default
73
73
  nil
@@ -484,8 +484,17 @@ class StringConverter
484
484
 
485
485
  value_type = TypeCalculator.infer_set(value)
486
486
  if string_formats.is_a?(String)
487
- # add the format given for the exact type
488
- string_formats = { value_type => string_formats }
487
+ # For Array and Hash, the format is given as a Hash where 'format' key is the format for the collection itself
488
+ if Puppet::Pops::Types::PArrayType::DEFAULT.assignable?(value_type)
489
+ # add the format given for the exact type
490
+ string_formats = { Puppet::Pops::Types::PArrayType::DEFAULT => {'format' => string_formats }}
491
+ elsif Puppet::Pops::Types::PHashType::DEFAULT.assignable?(value_type)
492
+ # add the format given for the exact type
493
+ string_formats = { Puppet::Pops::Types::PHashType::DEFAULT => {'format' => string_formats }}
494
+ else
495
+ # add the format given for the exact type
496
+ string_formats = { value_type => string_formats }
497
+ end
489
498
  end
490
499
 
491
500
  case string_formats
@@ -804,7 +813,7 @@ class StringConverter
804
813
  Kernel.format(f.orig_fmt, val)
805
814
 
806
815
  when :p
807
- apply_string_flags(f, puppet_quote(val))
816
+ apply_string_flags(f, puppet_quote(val, f.alt?))
808
817
 
809
818
  when :c
810
819
  c_val = val.capitalize
@@ -836,10 +845,15 @@ class StringConverter
836
845
  # strings will be quoted using double quotes.
837
846
  #
838
847
  # @param [String] str the string that should be formatted
848
+ # @param [Boolean] enforce_double_quotes if true the result will be double quoted (even if single quotes would be possible)
839
849
  # @return [String] the formatted string
840
850
  #
841
851
  # @api public
842
- def puppet_quote(str)
852
+ def puppet_quote(str, enforce_double_quotes = false)
853
+ if enforce_double_quotes
854
+ return puppet_double_quote(str)
855
+ end
856
+
843
857
  # Assume that the string can be single quoted
844
858
  bld = '\''
845
859
  bld.force_encoding(str.encoding)
@@ -1,5 +1,8 @@
1
+ require 'puppet/pops/evaluator/external_syntax_support'
2
+
1
3
  module Puppet::Pops
2
4
  module Validation
5
+
3
6
  # A Validator validates a model.
4
7
  #
5
8
  # Validation is performed on each model element in isolation. Each method should validate the model element's state
@@ -12,6 +15,8 @@ module Validation
12
15
  # This is however mostly valuable when validating model to model transformations, and is therefore T.B.D
13
16
  #
14
17
  class Checker4_0 < Evaluator::LiteralEvaluator
18
+ include Puppet::Pops::Evaluator::ExternalSyntaxSupport
19
+
15
20
  attr_reader :acceptor
16
21
  attr_reader :migration_checker
17
22
 
@@ -324,6 +329,14 @@ class Checker4_0 < Evaluator::LiteralEvaluator
324
329
  end
325
330
  end
326
331
 
332
+ def check_HeredocExpression(o)
333
+ # Only check static text in heredoc
334
+ expr = o.text_expr.expr # Always a SublocatedExpression with an expression
335
+ if expr.is_a?(Model::LiteralString)
336
+ assert_external_syntax(nil, expr.value, o.syntax, o.text_expr)
337
+ end
338
+ end
339
+
327
340
  def check_MethodCallExpression(o)
328
341
  unless o.functor_expr.is_a? Model::QualifiedName
329
342
  acceptor.accept(Issues::ILLEGAL_EXPRESSION, o.functor_expr, :feature => 'function name', :container => o)
@@ -559,6 +572,8 @@ class Checker4_0 < Evaluator::LiteralEvaluator
559
572
  return if namespace_for_file(file) == NO_NAMESPACE
560
573
 
561
574
  body = prog.body
575
+ return if prog.body.is_a?(Model::Nop) #Ignore empty or comment-only files
576
+
562
577
  if(body.is_a?(Model::BlockExpression))
563
578
  body.statements.each { |s| acceptor.accept(Issues::ILLEGAL_TOP_CONSTRUCT_LOCATION, s) unless valid_top_construct?(s) }
564
579
  else
@@ -623,9 +638,9 @@ class Checker4_0 < Evaluator::LiteralEvaluator
623
638
 
624
639
  def is_parent_dir_of(parent_dir, child_dir)
625
640
  parent_dir_path = Pathname.new(parent_dir)
626
- clean_parent = parent_dir_path.cleanpath
641
+ clean_parent = parent_dir_path.cleanpath.to_s + File::SEPARATOR
627
642
 
628
- return child_dir.to_s.start_with?(clean_parent.to_s)
643
+ return child_dir.to_s.start_with?(clean_parent)
629
644
  end
630
645
 
631
646
  def dir_to_names(relative_path)