bolt 0.23.0 → 0.24.0

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

Potentially problematic release.


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

Files changed (192) hide show
  1. checksums.yaml +4 -4
  2. data/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb +5 -2
  3. data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_query.rb +5 -1
  4. data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +5 -8
  5. data/lib/bolt/applicator.rb +11 -8
  6. data/lib/bolt/boltdir.rb +13 -5
  7. data/lib/bolt/catalog.rb +22 -47
  8. data/lib/bolt/config.rb +1 -26
  9. data/lib/bolt/executor.rb +1 -1
  10. data/lib/bolt/outputter.rb +0 -9
  11. data/lib/bolt/outputter/human.rb +29 -14
  12. data/lib/bolt/outputter/json.rb +12 -1
  13. data/lib/bolt/pal.rb +12 -10
  14. data/lib/bolt/target.rb +0 -6
  15. data/lib/bolt/task.rb +53 -10
  16. data/lib/bolt/transport/base.rb +1 -6
  17. data/lib/bolt/transport/local.rb +11 -13
  18. data/lib/bolt/transport/local/shell.rb +2 -2
  19. data/lib/bolt/transport/ssh.rb +16 -11
  20. data/lib/bolt/transport/winrm.rb +8 -11
  21. data/lib/bolt/version.rb +1 -1
  22. data/lib/bolt_ext/schemas/task.json +12 -5
  23. data/libexec/apply_catalog.rb +3 -1
  24. data/libexec/bolt_catalog +4 -0
  25. data/vendored/puppet/lib/puppet.rb +2 -1
  26. data/vendored/puppet/lib/puppet/application/agent.rb +2 -6
  27. data/vendored/puppet/lib/puppet/application/apply.rb +100 -60
  28. data/vendored/puppet/lib/puppet/application/cert.rb +26 -291
  29. data/vendored/puppet/lib/puppet/application/device.rb +0 -5
  30. data/vendored/puppet/lib/puppet/application/lookup.rb +1 -1
  31. data/vendored/puppet/lib/puppet/application/ssl.rb +133 -0
  32. data/vendored/puppet/lib/puppet/application_support.rb +1 -2
  33. data/vendored/puppet/lib/puppet/configurer.rb +34 -50
  34. data/vendored/puppet/lib/puppet/configurer/downloader.rb +1 -1
  35. data/vendored/puppet/lib/puppet/configurer/plugin_handler.rb +1 -1
  36. data/vendored/puppet/lib/puppet/daemon.rb +1 -1
  37. data/vendored/puppet/lib/puppet/defaults.rb +40 -117
  38. data/vendored/puppet/lib/puppet/face/epp.rb +2 -2
  39. data/vendored/puppet/lib/puppet/face/help.rb +21 -7
  40. data/vendored/puppet/lib/puppet/face/node/clean.rb +14 -10
  41. data/vendored/puppet/lib/puppet/feature/base.rb +7 -23
  42. data/vendored/puppet/lib/puppet/feature/eventlog.rb +1 -1
  43. data/vendored/puppet/lib/puppet/file_serving/base.rb +2 -2
  44. data/vendored/puppet/lib/puppet/file_serving/fileset.rb +1 -1
  45. data/vendored/puppet/lib/puppet/file_serving/metadata.rb +2 -2
  46. data/vendored/puppet/lib/puppet/functions.rb +133 -0
  47. data/vendored/puppet/lib/puppet/functions/eyaml_lookup_key.rb +4 -5
  48. data/vendored/puppet/lib/puppet/functions/filter.rb +7 -6
  49. data/vendored/puppet/lib/puppet/functions/new.rb +37 -53
  50. data/vendored/puppet/lib/puppet/functions/warning.rb +1 -1
  51. data/vendored/puppet/lib/puppet/functions/yaml_data.rb +4 -5
  52. data/vendored/puppet/lib/puppet/gettext/config.rb +1 -1
  53. data/vendored/puppet/lib/puppet/graph.rb +0 -2
  54. data/vendored/puppet/lib/puppet/indirector/catalog/json.rb +14 -3
  55. data/vendored/puppet/lib/puppet/indirector/catalog/yaml.rb +0 -16
  56. data/vendored/puppet/lib/puppet/indirector/certificate/file.rb +0 -1
  57. data/vendored/puppet/lib/puppet/indirector/facts/yaml.rb +4 -2
  58. data/vendored/puppet/lib/puppet/indirector/key/file.rb +1 -6
  59. data/vendored/puppet/lib/puppet/indirector/node/exec.rb +1 -3
  60. data/vendored/puppet/lib/puppet/indirector/node/yaml.rb +0 -6
  61. data/vendored/puppet/lib/puppet/indirector/request.rb +1 -1
  62. data/vendored/puppet/lib/puppet/indirector/ssl_file.rb +3 -44
  63. data/vendored/puppet/lib/puppet/indirector/yaml.rb +4 -4
  64. data/vendored/puppet/lib/puppet/info_service/task_information_service.rb +7 -3
  65. data/vendored/puppet/lib/puppet/loaders.rb +1 -0
  66. data/vendored/puppet/lib/puppet/module/task.rb +198 -29
  67. data/vendored/puppet/lib/puppet/module_tool/applications/unpacker.rb +1 -1
  68. data/vendored/puppet/lib/puppet/network/format_support.rb +13 -8
  69. data/vendored/puppet/lib/puppet/network/formats.rb +93 -2
  70. data/vendored/puppet/lib/puppet/network/http/api/indirected_routes.rb +10 -3
  71. data/vendored/puppet/lib/puppet/node/facts.rb +11 -1
  72. data/vendored/puppet/lib/puppet/parser/catalog_compiler.rb +56 -0
  73. data/vendored/puppet/lib/puppet/parser/compiler.rb +3 -1
  74. data/vendored/puppet/lib/puppet/parser/functions.rb +3 -1
  75. data/vendored/puppet/lib/puppet/parser/functions/filter.rb +1 -1
  76. data/vendored/puppet/lib/puppet/parser/functions/generate.rb +1 -1
  77. data/vendored/puppet/lib/puppet/parser/functions/sprintf.rb +12 -1
  78. data/vendored/puppet/lib/puppet/parser/functions/tagged.rb +1 -4
  79. data/vendored/puppet/lib/puppet/parser/scope.rb +1 -1
  80. data/vendored/puppet/lib/puppet/parser/script_compiler.rb +7 -2
  81. data/vendored/puppet/lib/puppet/pops/evaluator/deferred_resolver.rb +5 -3
  82. data/vendored/puppet/lib/puppet/pops/evaluator/runtime3_converter.rb +23 -4
  83. data/vendored/puppet/lib/puppet/pops/evaluator/runtime3_support.rb +3 -4
  84. data/vendored/puppet/lib/puppet/pops/functions/dispatch.rb +4 -0
  85. data/vendored/puppet/lib/puppet/pops/issues.rb +8 -0
  86. data/vendored/puppet/lib/puppet/pops/loader/loader.rb +2 -2
  87. data/vendored/puppet/lib/puppet/pops/loader/loader_paths.rb +3 -1
  88. data/vendored/puppet/lib/puppet/pops/loader/module_loaders.rb +30 -9
  89. data/vendored/puppet/lib/puppet/pops/loader/ruby_legacy_function_instantiator.rb +62 -0
  90. data/vendored/puppet/lib/puppet/pops/loader/static_loader.rb +0 -1
  91. data/vendored/puppet/lib/puppet/pops/loader/task_instantiator.rb +13 -70
  92. data/vendored/puppet/lib/puppet/pops/loaders.rb +19 -29
  93. data/vendored/puppet/lib/puppet/pops/lookup/hiera_config.rb +1 -1
  94. data/vendored/puppet/lib/puppet/pops/model/model_label_provider.rb +4 -1
  95. data/vendored/puppet/lib/puppet/pops/pcore.rb +10 -33
  96. data/vendored/puppet/lib/puppet/pops/serialization.rb +2 -0
  97. data/vendored/puppet/lib/puppet/pops/serialization/from_data_converter.rb +2 -1
  98. data/vendored/puppet/lib/puppet/pops/serialization/to_data_converter.rb +11 -3
  99. data/vendored/puppet/lib/puppet/pops/serialization/to_stringified_converter.rb +226 -0
  100. data/vendored/puppet/lib/puppet/pops/types/p_object_type.rb +3 -0
  101. data/vendored/puppet/lib/puppet/pops/validation/checker4_0.rb +97 -47
  102. data/vendored/puppet/lib/puppet/pops/validation/validator_factory_4_0.rb +7 -8
  103. data/vendored/puppet/lib/puppet/property/keyvalue.rb +70 -8
  104. data/vendored/puppet/lib/puppet/provider/aix_object.rb +483 -0
  105. data/vendored/puppet/lib/puppet/provider/file/windows.rb +1 -1
  106. data/vendored/puppet/lib/puppet/provider/group/aix.rb +51 -112
  107. data/vendored/puppet/lib/puppet/provider/package/gem.rb +1 -1
  108. data/vendored/puppet/lib/puppet/provider/package/pip.rb +1 -1
  109. data/vendored/puppet/lib/puppet/provider/package/puppet_gem.rb +1 -1
  110. data/vendored/puppet/lib/puppet/provider/package/rpm.rb +1 -1
  111. data/vendored/puppet/lib/puppet/provider/package/windows/package.rb +1 -1
  112. data/vendored/puppet/lib/puppet/provider/package/zypper.rb +1 -1
  113. data/vendored/puppet/lib/puppet/provider/service/systemd.rb +1 -1
  114. data/vendored/puppet/lib/puppet/provider/service/windows.rb +37 -40
  115. data/vendored/puppet/lib/puppet/provider/user/aix.rb +142 -254
  116. data/vendored/puppet/lib/puppet/resource.rb +20 -3
  117. data/vendored/puppet/lib/puppet/resource/catalog.rb +2 -12
  118. data/vendored/puppet/lib/puppet/rest/routes.rb +97 -34
  119. data/vendored/puppet/lib/puppet/settings.rb +1 -1
  120. data/vendored/puppet/lib/puppet/settings/file_setting.rb +1 -1
  121. data/vendored/puppet/lib/puppet/ssl/base.rb +1 -9
  122. data/vendored/puppet/lib/puppet/ssl/certificate_request.rb +1 -13
  123. data/vendored/puppet/lib/puppet/ssl/certificate_request_attributes.rb +1 -1
  124. data/vendored/puppet/lib/puppet/ssl/host.rb +114 -232
  125. data/vendored/puppet/lib/puppet/ssl/key.rb +1 -5
  126. data/vendored/puppet/lib/puppet/ssl/oids.rb +1 -1
  127. data/vendored/puppet/lib/puppet/test/test_helper.rb +0 -4
  128. data/vendored/puppet/lib/puppet/transaction/event.rb +3 -7
  129. data/vendored/puppet/lib/puppet/transaction/persistence.rb +1 -1
  130. data/vendored/puppet/lib/puppet/type/exec.rb +18 -16
  131. data/vendored/puppet/lib/puppet/type/file.rb +3 -3
  132. data/vendored/puppet/lib/puppet/type/file/source.rb +20 -7
  133. data/vendored/puppet/lib/puppet/type/group.rb +3 -5
  134. data/vendored/puppet/lib/puppet/type/notify.rb +1 -1
  135. data/vendored/puppet/lib/puppet/type/package.rb +2 -5
  136. data/vendored/puppet/lib/puppet/type/schedule.rb +1 -1
  137. data/vendored/puppet/lib/puppet/type/service.rb +3 -6
  138. data/vendored/puppet/lib/puppet/type/tidy.rb +1 -1
  139. data/vendored/puppet/lib/puppet/type/user.rb +13 -20
  140. data/vendored/puppet/lib/puppet/util.rb +8 -9
  141. data/vendored/puppet/lib/puppet/util/execution.rb +3 -3
  142. data/vendored/puppet/lib/puppet/util/feature.rb +61 -39
  143. data/vendored/puppet/lib/puppet/util/log/destinations.rb +1 -1
  144. data/vendored/puppet/lib/puppet/util/rdoc.rb +1 -1
  145. data/vendored/puppet/lib/puppet/util/run_mode.rb +1 -1
  146. data/vendored/puppet/lib/puppet/util/storage.rb +1 -1
  147. data/vendored/puppet/lib/puppet/util/suidmanager.rb +7 -5
  148. data/vendored/puppet/lib/puppet/util/tag_set.rb +1 -1
  149. data/vendored/puppet/lib/puppet/util/tagging.rb +1 -1
  150. data/vendored/puppet/lib/puppet/util/windows.rb +18 -2
  151. data/vendored/puppet/lib/puppet/util/windows/adsi.rb +154 -205
  152. data/vendored/puppet/lib/puppet/util/windows/service.rb +770 -0
  153. data/vendored/puppet/lib/puppet/util/yaml.rb +41 -5
  154. data/vendored/puppet/lib/puppet/version.rb +1 -1
  155. data/vendored/puppet/lib/puppet_pal.rb +280 -24
  156. metadata +8 -38
  157. data/lib/bolt/catalog/compiler.rb +0 -48
  158. data/lib/bolt/catalog/loaders.rb +0 -19
  159. data/vendored/puppet/lib/puppet/application/ca.rb +0 -11
  160. data/vendored/puppet/lib/puppet/application/certificate.rb +0 -17
  161. data/vendored/puppet/lib/puppet/application/certificate_request.rb +0 -7
  162. data/vendored/puppet/lib/puppet/application/certificate_revocation_list.rb +0 -7
  163. data/vendored/puppet/lib/puppet/face/ca.rb +0 -266
  164. data/vendored/puppet/lib/puppet/face/certificate.rb +0 -167
  165. data/vendored/puppet/lib/puppet/face/certificate_request.rb +0 -56
  166. data/vendored/puppet/lib/puppet/face/certificate_revocation_list.rb +0 -56
  167. data/vendored/puppet/lib/puppet/graph/random_prioritizer.rb +0 -16
  168. data/vendored/puppet/lib/puppet/graph/title_hash_prioritizer.rb +0 -16
  169. data/vendored/puppet/lib/puppet/indirector/certificate/ca.rb +0 -9
  170. data/vendored/puppet/lib/puppet/indirector/certificate/disabled_ca.rb +0 -22
  171. data/vendored/puppet/lib/puppet/indirector/certificate_request/ca.rb +0 -22
  172. data/vendored/puppet/lib/puppet/indirector/certificate_request/disabled_ca.rb +0 -22
  173. data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/ca.rb +0 -8
  174. data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/disabled_ca.rb +0 -22
  175. data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/file.rb +0 -8
  176. data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/rest.rb +0 -11
  177. data/vendored/puppet/lib/puppet/indirector/certificate_status.rb +0 -4
  178. data/vendored/puppet/lib/puppet/indirector/certificate_status/file.rb +0 -91
  179. data/vendored/puppet/lib/puppet/indirector/certificate_status/rest.rb +0 -11
  180. data/vendored/puppet/lib/puppet/indirector/key/ca.rb +0 -16
  181. data/vendored/puppet/lib/puppet/indirector/key/disabled_ca.rb +0 -22
  182. data/vendored/puppet/lib/puppet/indirector/ldap.rb +0 -86
  183. data/vendored/puppet/lib/puppet/indirector/node/ldap.rb +0 -275
  184. data/vendored/puppet/lib/puppet/provider/aixobject.rb +0 -392
  185. data/vendored/puppet/lib/puppet/provider/cron/crontab.rb +0 -297
  186. data/vendored/puppet/lib/puppet/ssl/certificate_authority.rb +0 -475
  187. data/vendored/puppet/lib/puppet/ssl/certificate_authority/autosign_command.rb +0 -45
  188. data/vendored/puppet/lib/puppet/ssl/certificate_authority/interface.rb +0 -324
  189. data/vendored/puppet/lib/puppet/ssl/certificate_factory.rb +0 -219
  190. data/vendored/puppet/lib/puppet/ssl/certificate_revocation_list.rb +0 -111
  191. data/vendored/puppet/lib/puppet/ssl/inventory.rb +0 -55
  192. data/vendored/puppet/lib/puppet/type/cron.rb +0 -480
@@ -132,7 +132,7 @@ class HieraConfig
132
132
  if config_path.exist?
133
133
  env_context = EnvironmentContext.adapt(lookup_invocation.scope.compiler.environment)
134
134
  loaded_config = env_context.cached_file_data(config_path) do |content|
135
- parsed = YAML.load(content, config_path)
135
+ parsed = Puppet::Util::Yaml.safe_load(content, [Symbol], config_path)
136
136
 
137
137
  # For backward compatibility, we must treat an empty file, or a yaml that doesn't
138
138
  # produce a Hash as Hiera version 3 default.
@@ -128,7 +128,10 @@ class ModelLabelProvider
128
128
  simple_name[1..-5] + "-Type"
129
129
  else
130
130
  n = o.name
131
- n.nil? ? 'Anonymous Class' : n
131
+ if n.nil?
132
+ n = o.respond_to?(:_pcore_type) ? o._pcore_type.name : 'Anonymous Class'
133
+ end
134
+ n
132
135
  end
133
136
  end
134
137
  end
@@ -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
@@ -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
@@ -34,6 +35,7 @@ end
34
35
  require_relative 'serialization/json_path'
35
36
  require_relative 'serialization/from_data_converter'
36
37
  require_relative 'serialization/to_data_converter'
38
+ require_relative 'serialization/to_stringified_converter'
37
39
  require_relative 'serialization/serializer'
38
40
  require_relative 'serialization/deserializer'
39
41
  require_relative 'serialization/json'
@@ -135,6 +135,7 @@ module Serialization
135
135
  end
136
136
  hash
137
137
  else
138
+ # not a string
138
139
  pcore_type_hash_to_value(type, value)
139
140
  end
140
141
  end
@@ -150,7 +151,7 @@ module Serialization
150
151
  def convert(value)
151
152
  if value.is_a?(Hash)
152
153
  pcore_type = value[PCORE_TYPE_KEY]
153
- if pcore_type
154
+ if pcore_type && (pcore_type.is_a?(String) || pcore_type.is_a?(Hash))
154
155
  @pcore_type_procs[pcore_type].call(value, pcore_type)
155
156
  else
156
157
  build({}) { value.each_pair { |key, elem| with(key) { convert(elem) }}}
@@ -11,10 +11,10 @@ module Serialization
11
11
  # @param value [Object] the value to convert
12
12
  # @param options {Symbol => <Boolean,String>} options hash
13
13
  # @option options [Boolean] :rich_data `true` if rich data is enabled
14
- # @option options [Boolean] :local_references use local references instead of duplicating complex entries
14
+ # @option options [Boolean] :local_reference use local references instead of duplicating complex entries
15
15
  # @option options [Boolean] :type_by_reference `true` if Object types are converted to references rather than embedded.
16
16
  # @option options [Boolean] :symbol_as_string `true` if Symbols should be converted to strings (with type loss)
17
- # @option options [String] :path_prefix String to prepend to path in warnings and errors
17
+ # @option options [String] :message_prefix String to prepend to in warnings and errors
18
18
  # @return [Data] the processed result. An object assignable to `Data`.
19
19
  #
20
20
  # @api public
@@ -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 }
@@ -0,0 +1,226 @@
1
+ module Puppet::Pops
2
+ module Serialization
3
+
4
+ # Class that can process an arbitrary object into a value that is assignable to `Data`
5
+ # and where contents is converted from rich data to one of:
6
+ # * Numeric (Integer, Float)
7
+ # * Boolean
8
+ # * Undef (nil)
9
+ # * String
10
+ # * Array
11
+ # * Hash
12
+ #
13
+ # The conversion is lossy - the result cannot be deserialized to produce the original data types.
14
+ # All rich values are transformed to strings..
15
+ # Hashes with rich keys are transformed to use string representation of such keys.
16
+ #
17
+ # @api public
18
+ class ToStringifiedConverter
19
+ include Evaluator::Runtime3Support
20
+
21
+ # Converts the given _value_ according to the given _options_ and return the result of the conversion
22
+ #
23
+ # @param value [Object] the value to convert
24
+ # @param options {Symbol => <Boolean,String>} options hash
25
+ # @option options [String] :message_prefix String to prepend to in warnings and errors
26
+ # @option options [String] :semantic object (AST) to pass to the issue reporter
27
+ # @return [Data] the processed result. An object assignable to `Data` with rich data stringified.
28
+ #
29
+ # @api public
30
+ def self.convert(value, options = EMPTY_HASH)
31
+ new(options).convert(value)
32
+ end
33
+
34
+ # Creates a new instance of the processor
35
+ #
36
+ # @param options {Symbol => Object} options hash
37
+ # @option options [String] :message_prefix String to prepend to path in warnings and errors
38
+ # @option semantic [Object] :semantic object to pass to the issue reporter
39
+ def initialize(options = EMPTY_HASH)
40
+ @message_prefix = options[:message_prefix]
41
+ @semantic = options[:semantic]
42
+ end
43
+
44
+ # Converts the given _value_
45
+ #
46
+ # @param value [Object] the value to convert
47
+ # @return [Data] the processed result. An object assignable to `Data` with rich data stringified.
48
+ #
49
+ # @api public
50
+ def convert(value)
51
+ @path = []
52
+ @values = {}
53
+ to_data(value)
54
+ end
55
+
56
+ private
57
+
58
+ def path_to_s
59
+ s = @message_prefix || ''
60
+ s << JsonPath.to_json_path(@path)[1..-1]
61
+ s
62
+ end
63
+
64
+ def to_data(value)
65
+ if value.is_a?(String)
66
+ to_string_or_binary(value)
67
+ elsif value.nil? || Types::PScalarDataType::DEFAULT.instance?(value)
68
+ value
69
+ elsif :default == value
70
+ 'default'
71
+ elsif value.is_a?(Symbol)
72
+ value.to_s
73
+ elsif value.instance_of?(Array)
74
+ process(value) do
75
+ result = []
76
+ value.each_with_index do |elem, index|
77
+ with(index) { result << to_data(elem) }
78
+ end
79
+ result
80
+ end
81
+ elsif value.instance_of?(Hash)
82
+ process(value) do
83
+ if value.keys.all? { |key| key.is_a?(String) && key != PCORE_TYPE_KEY && key != PCORE_VALUE_KEY }
84
+ result = {}
85
+ value.each_pair { |key, elem| with(key) { result[key] = to_data(elem) } }
86
+ result
87
+ else
88
+ non_string_keyed_hash_to_data(value)
89
+ end
90
+ end
91
+ else
92
+ unknown_to_string(value)
93
+ end
94
+ end
95
+
96
+ # Turns an ASCII-8BIT encoded string into a Binary, returns US_ASCII encoded and transforms all other strings to UTF-8
97
+ # with replacements for non Unicode characters.
98
+ # If String cannot be represented as UTF-8
99
+ def to_string_or_binary(value)
100
+ encoding = value.encoding
101
+ if encoding == Encoding::ASCII_8BIT
102
+ Puppet::Pops::Types::PBinaryType::Binary.from_binary_string(value).to_s
103
+ else
104
+ # Transform to UTF-8 (do not assume UTF-8 is correct) with source invalid byte
105
+ # sequences and UTF-8 undefined characters replaced by the default unicode uFFFD character
106
+ # (black diamond with question mark).
107
+ value.encode(Encoding::UTF_8, encoding, :invalid => :replace, :undef => :replace)
108
+ end
109
+ end
110
+
111
+ # Performs a check for endless recursion before
112
+ # it yields to the given block. The result of yielding is returned.
113
+ #
114
+ # @param value [Object] the value
115
+ # @yield The block that will produce the data for the value
116
+ # @return [Data] the result of yielding to the given block, or a hash denoting a reference
117
+ #
118
+ # @api private
119
+ def process(value, &block)
120
+ with_recursive_guard(value, &block)
121
+ end
122
+
123
+ # Pushes `key` to the end of the path and yields to the given block. The
124
+ # `key` is popped when the yield returns.
125
+ # @param key [Object] the key to push on the current path
126
+ # @yield The block that will produce the returned value
127
+ # @return [Object] the result of yielding to the given block
128
+ #
129
+ # @api private
130
+ def with(key)
131
+ @path.push(key)
132
+ value = yield
133
+ @path.pop
134
+ value
135
+ end
136
+
137
+ # @param value [Object] the value to use when checking endless recursion
138
+ # @yield The block that will produce the data
139
+ # @return [Data] the result of yielding to the given block
140
+ def with_recursive_guard(value)
141
+ id = value.object_id
142
+ if @recursive_lock
143
+ if @recursive_lock.include?(id)
144
+ serialization_issue(Issues::SERIALIZATION_ENDLESS_RECURSION, :type_name => value.class.name)
145
+ end
146
+ @recursive_lock[id] = true
147
+ else
148
+ @recursive_lock = { id => true }
149
+ end
150
+ v = yield
151
+ @recursive_lock.delete(id)
152
+ v
153
+ end
154
+
155
+ # A hash key that is non conforming
156
+ def unknown_key_to_string(value)
157
+ unknown_to_string(value)
158
+ end
159
+
160
+ def unknown_to_string(value)
161
+ if value.is_a?(Regexp)
162
+ return Puppet::Pops::Types::PRegexpType.regexp_to_s_with_delimiters(value)
163
+
164
+ elsif value.instance_of?(Types::PSensitiveType::Sensitive)
165
+ # to_s does not differentiate between instances - if they were used as keys in a hash
166
+ # the stringified result would override all Sensitive keys with the last such key's value
167
+ # this adds object_id.
168
+ #
169
+ return "#<#{value}:#{value.object_id}>"
170
+
171
+ elsif value.is_a?(Puppet::Pops::Types::PObjectType)
172
+ # regular to_s on an ObjectType gives the entire definition
173
+ return value.name
174
+
175
+ end
176
+
177
+ # Do a to_s on anything else
178
+ result = value.to_s
179
+
180
+ # The result may be ascii-8bit encoded without being a binary (low level object.inspect returns ascii-8bit string)
181
+ # This can be the case if runtime objects have very simple implementation (no to_s or inspect method).
182
+ # They are most likely not of Binary nature. Therefore the encoding is forced and only if it errors
183
+ # will the result be taken as binary and encoded as base64 string.
184
+ if result.encoding == Encoding::ASCII_8BIT
185
+ begin
186
+ result.force_encoding(Encoding::UTF_8)
187
+ rescue
188
+ # The result cannot be represented in UTF-8, make it a binary Base64 encoded string
189
+ Puppet::Pops::Types::PBinaryType::Binary.from_binary_string(result).to_s
190
+ end
191
+ end
192
+ result
193
+ end
194
+
195
+ def non_string_keyed_hash_to_data(hash)
196
+ result = {}
197
+ hash.each_pair do |key, value|
198
+ if key.is_a?(Symbol)
199
+ key = key.to_s
200
+ elsif !key.is_a?(String)
201
+ key = unknown_key_to_string(key)
202
+ end
203
+ if key == "__ptype" || key =="__pvalue"
204
+ key = "reserved key: #{key}"
205
+ end
206
+ with(key) { result[key] = to_data(value) }
207
+ end
208
+ result
209
+ end
210
+
211
+ def serialization_issue(issue, options = EMPTY_HASH)
212
+ semantic = @semantic
213
+ if semantic.nil?
214
+ tos = Puppet::Pops::PuppetStack.top_of_stack
215
+ if tos.empty?
216
+ semantic = Puppet::Pops::SemanticError.new(issue, nil, EMPTY_HASH)
217
+ else
218
+ file, line = stacktrace
219
+ semantic = Puppet::Pops::SemanticError.new(issue, nil, {:file => file, :line => line})
220
+ end
221
+ end
222
+ optionally_fail(issue, semantic, options)
223
+ end
224
+ end
225
+ end
226
+ end
@@ -284,6 +284,9 @@ class PObjectType < PMetaType
284
284
  # @api public
285
285
  def initialize(name, container, init_hash)
286
286
  super(name, container, TypeAsserter.assert_instance_of(nil, TYPE_ATTRIBUTE, init_hash) { "initializer for #{self.class.label(container, name)}" })
287
+ if name == Serialization::PCORE_TYPE_KEY || name == Serialization::PCORE_VALUE_KEY
288
+ raise Puppet::ParseError, _("The attribute '%{name}' is reserved and cannot be used") % { name: name}
289
+ end
287
290
  @kind = init_hash[KEY_KIND]
288
291
  if @kind == ATTRIBUTE_KIND_CONSTANT # final is implied
289
292
  if init_hash.include?(KEY_FINAL) && !@final
@@ -35,7 +35,6 @@ class Checker4_0 < Evaluator::LiteralEvaluator
35
35
 
36
36
  @check_visitor = self.class.check_visitor
37
37
  @acceptor = diagnostics_producer
38
- @file_to_namespace = {}
39
38
 
40
39
  # Use null migration checker unless given in context
41
40
  @migration_checker = (Puppet.lookup(:migration_checker) { Migration::MigrationChecker.new() })
@@ -49,6 +48,7 @@ class Checker4_0 < Evaluator::LiteralEvaluator
49
48
  # tree iterate the model, and call check for each element
50
49
  @path = []
51
50
  check(model)
51
+ internal_check_top_construct_in_module(model)
52
52
  model._pcore_all_contents(@path) { |element| check(element) }
53
53
  end
54
54
 
@@ -397,7 +397,7 @@ class Checker4_0 < Evaluator::LiteralEvaluator
397
397
  acceptor.accept(Issues::ILLEGAL_DEFINITION_NAME, o, {:name=>o.name})
398
398
  end
399
399
 
400
- internal_check_file_namespace(o, o.name, o.locator.file)
400
+ internal_check_file_namespace(o)
401
401
  internal_check_reserved_type_name(o, o.name)
402
402
  internal_check_future_reserved_word(o, o.name)
403
403
  end
@@ -533,75 +533,125 @@ class Checker4_0 < Evaluator::LiteralEvaluator
533
533
  end
534
534
  end
535
535
 
536
- def internal_check_file_namespace(o, name, file)
537
- return if file.nil?
536
+ NO_NAMESPACE = :no_namespace
537
+ NO_PATH = :no_path
538
+ BAD_MODULE_FILE = :bad_module_file
539
+
540
+ def internal_check_file_namespace(o)
541
+ file = o.locator.file
542
+ return if file.nil? || file == '' #e.g. puppet apply -e '...'
538
543
 
539
- lc_file = file.downcase
544
+ file_namespace = namespace_for_file(file)
545
+ return if file_namespace == NO_NAMESPACE
540
546
 
541
- file_namespace = @file_to_namespace[lc_file]
542
- if file_namespace.nil?
543
- return if @file_to_namespace.key?(lc_file)
544
- file_namespace = @file_to_namespace[lc_file] = namespace_for_file(lc_file)
545
- return if file_namespace.nil?
547
+ # Downcasing here because check is case-insensitive
548
+ if file_namespace == BAD_MODULE_FILE || !o.name.downcase.start_with?(file_namespace)
549
+ acceptor.accept(Issues::ILLEGAL_DEFINITION_LOCATION, o, {:name => o.name, :file => file})
546
550
  end
551
+ end
552
+
553
+ def internal_check_top_construct_in_module(prog)
554
+ return unless prog.is_a?(Model::Program) && !prog.body.nil?
555
+
556
+ #Check that this is a module autoloaded file
557
+ file = prog.locator.file
558
+ return if file.nil?
559
+ return if namespace_for_file(file) == NO_NAMESPACE
547
560
 
548
- if !name.downcase.start_with?(file_namespace)
549
- acceptor.accept(Issues::ILLEGAL_DEFINITION_LOCATION, o, {:name => name, :file => file})
561
+ body = prog.body
562
+ if(body.is_a?(Model::BlockExpression))
563
+ body.statements.each { |s| acceptor.accept(Issues::ILLEGAL_TOP_CONSTRUCT_LOCATION, s) unless valid_top_construct?(s) }
564
+ else
565
+ acceptor.accept(Issues::ILLEGAL_TOP_CONSTRUCT_LOCATION, body) unless valid_top_construct?(body)
550
566
  end
551
567
  end
552
568
 
553
- NEVER_MATCH = '\b'.freeze
569
+ def valid_top_construct?(o)
570
+ o.is_a?(Model::Definition) && !o.is_a?(Model::NodeDefinition)
571
+ end
572
+
573
+ # @api private
574
+ class Puppet::Util::FileNamespaceAdapter < Puppet::Pops::Adaptable::Adapter
575
+ attr_accessor :file_to_namespace
576
+ end
554
577
 
555
578
  def namespace_for_file(file)
556
- path = Pathname.new(file)
579
+ env = Puppet.lookup(:current_environment)
580
+ return NO_NAMESPACE if env.nil?
557
581
 
558
- return nil if path.extname != ".pp"
582
+ Puppet::Util::FileNamespaceAdapter.adapt(env) do |adapter|
583
+ adapter.file_to_namespace ||= {}
559
584
 
560
- return nil if initial_manifest?(path)
585
+ file_namespace = adapter.file_to_namespace[file]
586
+ return file_namespace unless file_namespace.nil? # No cache entry, so we do the calculation
561
587
 
562
- path = path.each_filename.to_a
588
+ path = Pathname.new(file)
563
589
 
564
- # Example definition dir: manifests in this path:
565
- # <modules dir>/<module name>/manifests/<module subdir>/<classfile>.pp
566
- definition_dir_index = find_module_definition_dir(path)
590
+ return adapter.file_to_namespace[file] = NO_NAMESPACE if path.extname != ".pp"
567
591
 
568
- # How can we get this result?
569
- # If it is not an initial manifest, it must come from a module,
570
- # and from the manifests dir there. This may never get used...
571
- return NEVER_MATCH if definition_dir_index.nil? || definition_dir_index == 0
592
+ path = path.expand_path
572
593
 
573
- before_definition_dir = definition_dir_index - 1
574
- after_definition_dir = definition_dir_index + 1
575
- names = path[after_definition_dir .. -2] # Directories inside module
576
- names.unshift(path[before_definition_dir]) # Name of the module itself
577
- # Do not include name of module init file at top level of module
578
- filename = path[-1]
579
- if !(path.length == (after_definition_dir+1) && filename == 'init.pp')
580
- names.push(filename[0 .. -4]) # Remove .pp from filename
594
+ return adapter.file_to_namespace[file] = NO_NAMESPACE if initial_manifest?(path, env.manifest)
595
+
596
+ #All auto-loaded files from modules come from a module search path dir
597
+ relative_path = get_module_relative_path(path, env.full_modulepath)
598
+
599
+ return adapter.file_to_namespace[file] = NO_NAMESPACE if relative_path == NO_PATH
600
+
601
+ #If a file comes from a module, but isn't in the right place, always error
602
+ names = dir_to_names(relative_path)
603
+
604
+ return adapter.file_to_namespace[file] = (names == BAD_MODULE_FILE ? BAD_MODULE_FILE : names.join("::").freeze)
581
605
  end
606
+ end
607
+
608
+ def initial_manifest?(path, manifest_setting)
609
+ return false if manifest_setting.nil? || manifest_setting == :no_manifest
582
610
 
583
- names.join("::").freeze
611
+ string_path = path.to_s
612
+
613
+ string_path == manifest_setting || string_path.start_with?(manifest_setting)
584
614
  end
585
615
 
586
- def initial_manifest?(path)
587
- manifest_setting = Puppet[:manifest]
616
+ def get_module_relative_path(file_path, modulepath_directories)
617
+ clean_file = file_path.cleanpath
618
+ parent_path = modulepath_directories.find { |path_dir| is_parent_dir_of(path_dir, clean_file) }
619
+ return NO_PATH if parent_path.nil?
588
620
 
589
- # Does this ever happen outside of tests?
590
- if manifest_setting.nil?
591
- return path.basename.to_s == 'site.pp'
592
- end
621
+ file_path.relative_path_from(Pathname.new(parent_path))
622
+ end
623
+
624
+ def is_parent_dir_of(parent_dir, child_dir)
625
+ parent_dir_path = Pathname.new(parent_dir)
626
+ clean_parent = parent_dir_path.cleanpath
593
627
 
594
- full_path = path.expand_path.to_s
595
- full_path == manifest_setting || full_path.start_with?(manifest_setting)
628
+ return child_dir.to_s.start_with?(clean_parent.to_s)
596
629
  end
597
630
 
598
- # Returns module root directory index in path for files under 'manifests',
599
- # 'functions', 'types' and 'plans'
600
- def find_module_definition_dir(path)
601
- reverse_index = path.reverse_each.find_index do |dir|
602
- dir == 'manifests' || dir == 'functions' || dir == 'types' || dir == 'plans'
631
+ def dir_to_names(relative_path)
632
+ # Downcasing here because check is case-insensitive
633
+ path_components = relative_path.to_s.downcase.split(File::SEPARATOR)
634
+
635
+ # Example definition dir: manifests in this path:
636
+ # <module name>/manifests/<module subdir>/<classfile>.pp
637
+ dir = path_components[1]
638
+
639
+ # How can we get this result?
640
+ # If it is not an initial manifest, it must come from a module,
641
+ # and from the manifests dir there. This may never get used...
642
+ return BAD_MODULE_FILE unless dir == 'manifests' || dir == 'functions' || dir == 'types' || dir == 'plans'
643
+
644
+ names = path_components[2 .. -2] # Directories inside module
645
+ names.unshift(path_components[0]) # Name of the module itself
646
+
647
+ # Do not include name of module init file at top level of module
648
+ # e.g. <module name>/manifests/init.pp
649
+ filename = path_components[-1]
650
+ if !(path_components.length == 3 && filename == 'init.pp')
651
+ names.push(filename[0 .. -4]) # Remove .pp from filename
603
652
  end
604
- return reverse_index.nil? ? nil : (path.length - 1) - reverse_index
653
+
654
+ names
605
655
  end
606
656
 
607
657
  RESERVED_PARAMETERS = {