puppet 4.10.1-universal-darwin → 4.10.4-universal-darwin

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 (120) hide show
  1. data/ext/project_data.yaml +1 -1
  2. data/lib/puppet.rb +40 -28
  3. data/lib/puppet/application/agent.rb +1 -1
  4. data/lib/puppet/application/apply.rb +1 -1
  5. data/lib/puppet/application/cert.rb +1 -1
  6. data/lib/puppet/application/describe.rb +1 -1
  7. data/lib/puppet/application/device.rb +1 -1
  8. data/lib/puppet/application/doc.rb +3 -3
  9. data/lib/puppet/application/filebucket.rb +1 -1
  10. data/lib/puppet/application/inspect.rb +2 -2
  11. data/lib/puppet/application/lookup.rb +1 -1
  12. data/lib/puppet/application/master.rb +1 -1
  13. data/lib/puppet/application/resource.rb +7 -7
  14. data/lib/puppet/defaults.rb +1 -1
  15. data/lib/puppet/etc.rb +75 -39
  16. data/lib/puppet/face/ca.rb +1 -1
  17. data/lib/puppet/face/catalog.rb +1 -1
  18. data/lib/puppet/face/certificate.rb +1 -1
  19. data/lib/puppet/face/certificate_request.rb +1 -1
  20. data/lib/puppet/face/certificate_revocation_list.rb +1 -1
  21. data/lib/puppet/face/config.rb +1 -1
  22. data/lib/puppet/face/epp.rb +1 -1
  23. data/lib/puppet/face/facts.rb +1 -1
  24. data/lib/puppet/face/file.rb +1 -1
  25. data/lib/puppet/face/help.rb +1 -1
  26. data/lib/puppet/face/key.rb +1 -1
  27. data/lib/puppet/face/man.rb +2 -2
  28. data/lib/puppet/face/module.rb +1 -1
  29. data/lib/puppet/face/node.rb +1 -1
  30. data/lib/puppet/face/parser.rb +1 -1
  31. data/lib/puppet/face/plugin.rb +1 -1
  32. data/lib/puppet/face/report.rb +1 -1
  33. data/lib/puppet/face/resource.rb +1 -1
  34. data/lib/puppet/face/resource_type.rb +1 -1
  35. data/lib/puppet/face/status.rb +1 -1
  36. data/lib/puppet/feature/base.rb +1 -1
  37. data/lib/puppet/functions/eyaml_lookup_key.rb +16 -12
  38. data/lib/puppet/functions/hiera.rb +9 -2
  39. data/lib/puppet/functions/hiera_array.rb +9 -2
  40. data/lib/puppet/functions/hiera_hash.rb +10 -2
  41. data/lib/puppet/functions/hiera_include.rb +17 -3
  42. data/lib/puppet/functions/hocon_data.rb +6 -0
  43. data/lib/puppet/functions/json_data.rb +4 -0
  44. data/lib/puppet/functions/yaml_data.rb +4 -0
  45. data/lib/puppet/generate/models/type/type.rb +6 -5
  46. data/lib/puppet/generate/templates/type/pcore.erb +1 -1
  47. data/lib/puppet/module_tool/skeleton/templates/generator/examples/init.pp.erb +1 -1
  48. data/lib/puppet/parser/functions/create_resources.rb +8 -0
  49. data/lib/puppet/parser/scope.rb +2 -2
  50. data/lib/puppet/pops/adapters.rb +10 -4
  51. data/lib/puppet/pops/evaluator/runtime3_resource_support.rb +0 -2
  52. data/lib/puppet/pops/evaluator/runtime3_support.rb +31 -0
  53. data/lib/puppet/pops/issues.rb +8 -0
  54. data/lib/puppet/pops/loader/loader.rb +4 -0
  55. data/lib/puppet/pops/loader/module_loaders.rb +0 -2
  56. data/lib/puppet/pops/loader/static_loader.rb +1 -1
  57. data/lib/puppet/pops/loader/type_definition_instantiator.rb +1 -1
  58. data/lib/puppet/pops/loader/typed_name.rb +1 -0
  59. data/lib/puppet/pops/loaders.rb +7 -15
  60. data/lib/puppet/pops/lookup/environment_data_provider.rb +1 -1
  61. data/lib/puppet/pops/lookup/hiera_config.rb +3 -1
  62. data/lib/puppet/pops/lookup/interpolation.rb +2 -1
  63. data/lib/puppet/pops/lookup/lookup_key.rb +1 -1
  64. data/lib/puppet/pops/lookup/module_data_provider.rb +10 -2
  65. data/lib/puppet/pops/lookup/sub_lookup.rb +10 -9
  66. data/lib/puppet/pops/parser/lexer2.rb +20 -3
  67. data/lib/puppet/pops/pcore.rb +2 -2
  68. data/lib/puppet/pops/resource/resource_type_impl.rb +2 -2
  69. data/lib/puppet/pops/semantic_error.rb +12 -0
  70. data/lib/puppet/pops/serialization/deserializer.rb +7 -4
  71. data/lib/puppet/pops/types/p_type_set_type.rb +2 -2
  72. data/lib/puppet/pops/types/string_converter.rb +5 -17
  73. data/lib/puppet/pops/types/type_set_reference.rb +1 -1
  74. data/lib/puppet/pops/validation/checker4_0.rb +4 -0
  75. data/lib/puppet/pops/validation/validator_factory_4_0.rb +1 -0
  76. data/lib/puppet/provider/nameservice.rb +12 -4
  77. data/lib/puppet/provider/package/yum.rb +8 -8
  78. data/lib/puppet/provider/user/useradd.rb +1 -1
  79. data/lib/puppet/reference/configuration.rb +1 -1
  80. data/lib/puppet/resource.rb +9 -11
  81. data/lib/puppet/resource/type_collection.rb +1 -0
  82. data/lib/puppet/type/exec.rb +32 -26
  83. data/lib/puppet/type/file/mode.rb +4 -0
  84. data/lib/puppet/util/character_encoding.rb +77 -74
  85. data/lib/puppet/util/monkey_patches.rb +3 -1
  86. data/lib/puppet/util/windows/api_types.rb +3 -0
  87. data/lib/puppet/util/windows/file.rb +1 -1
  88. data/lib/puppet/version.rb +1 -1
  89. data/locales/puppet.pot +31 -7
  90. data/spec/integration/faces/documentation_spec.rb +2 -2
  91. data/spec/integration/parser/pcore_resource_spec.rb +15 -0
  92. data/spec/integration/resource/type_collection_spec.rb +6 -0
  93. data/spec/lib/puppet/face/1.0.0/huzzah.rb +1 -1
  94. data/spec/lib/puppet/face/basetest.rb +1 -1
  95. data/spec/lib/puppet/face/huzzah.rb +1 -1
  96. data/spec/lib/puppet/face/version_matching.rb +1 -1
  97. data/spec/lib/puppet_spec/character_encoding.rb +12 -0
  98. data/spec/lib/puppet_spec/compiler.rb +7 -0
  99. data/spec/shared_examples/rhel_package_provider.rb +10 -11
  100. data/spec/unit/application/resource_spec.rb +22 -1
  101. data/spec/unit/configurer/fact_handler_spec.rb +2 -1
  102. data/spec/unit/etc_spec.rb +361 -153
  103. data/spec/unit/functions/lookup_spec.rb +118 -2
  104. data/spec/unit/parser/functions/create_resources_spec.rb +47 -6
  105. data/spec/unit/parser/scope_spec.rb +8 -0
  106. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +40 -0
  107. data/spec/unit/pops/loaders/loaders_spec.rb +141 -79
  108. data/spec/unit/pops/lookup/interpolation_spec.rb +49 -9
  109. data/spec/unit/pops/lookup/lookup_spec.rb +32 -0
  110. data/spec/unit/pops/parser/lexer2_spec.rb +28 -0
  111. data/spec/unit/pops/types/p_object_type_spec.rb +1 -1
  112. data/spec/unit/pops/types/p_type_set_type_spec.rb +1 -1
  113. data/spec/unit/pops/types/string_converter_spec.rb +21 -0
  114. data/spec/unit/pops/validator/validator_spec.rb +43 -0
  115. data/spec/unit/provider/nameservice/directoryservice_spec.rb +2 -0
  116. data/spec/unit/provider/nameservice_spec.rb +113 -3
  117. data/spec/unit/provider/user/useradd_spec.rb +13 -0
  118. data/spec/unit/resource/catalog_spec.rb +21 -0
  119. data/spec/unit/util/character_encoding_spec.rb +193 -52
  120. metadata +4 -2
@@ -34,7 +34,7 @@ Puppet::Resource::ResourceType3.new(
34
34
  ],
35
35
  {
36
36
  <%- title_patterns.each_with_index do |mapping, index| -%>
37
- <%= mapping[0] %> => [<%= mapping[1].join(', ')%>]<%= "," if index + 1 < title_patterns.size %>
37
+ <%= mapping[0] %> => <%= mapping[1] %><%= "," if index + 1 < title_patterns.size %>
38
38
  <%- end -%>
39
39
  },
40
40
  <%= isomorphic -%>,
@@ -1,4 +1,4 @@
1
- # The baseline for module testing used by Puppet Labs is that each manifest
1
+ # The baseline for module testing used by Puppet Inc. is that each manifest
2
2
  # should have a corresponding test manifest that declares that class or defined
3
3
  # type.
4
4
  #
@@ -71,10 +71,18 @@ Puppet::Parser::Functions::newfunction(:create_resources, :arity => -3, :doc =>
71
71
 
72
72
  if type.start_with? '@@'
73
73
  exported = true
74
+ virtual = true
74
75
  elsif type.start_with? '@'
75
76
  virtual = true
76
77
  end
77
78
 
79
+ if type_name == 'class' && (exported || virtual)
80
+ # cannot find current evaluator, so use another
81
+ evaluator = Puppet::Pops::Parser::EvaluatingParser.new.evaluator
82
+ # optionally fails depending on configured severity of issue
83
+ evaluator.runtime_issue(Puppet::Pops::Issues::CLASS_NOT_VIRTUALIZABLE)
84
+ end
85
+
78
86
  instances.map do |title, params|
79
87
  # Add support for iteration if title is an array
80
88
  resource_titles = title.is_a?(Array) ? title : [title]
@@ -85,7 +85,7 @@ class Puppet::Parser::Scope
85
85
 
86
86
  def [](name)
87
87
  val = @symbols[name]
88
- val.nil? && !@symbols.include?(val) ? super : val
88
+ val.nil? && !@symbols.include?(name) ? super : val
89
89
  end
90
90
 
91
91
  def is_local_scope?
@@ -481,7 +481,7 @@ class Puppet::Parser::Scope
481
481
  #
482
482
  # @param [String] name the variable name to lookup
483
483
  #
484
- # @return Object the value of the variable, or nil if it's not found
484
+ # @return Object the value of the variable, or if not found; nil if `strict_variables` is false, and thrown :undefined_variable otherwise
485
485
  #
486
486
  # @api public
487
487
  def lookupvar(name, options = EMPTY_HASH)
@@ -129,7 +129,11 @@ module Adapters
129
129
  default_loader
130
130
  else
131
131
  loader_name = loader_name_by_source(loaders.environment, model, file)
132
- loader_name.nil? ? default_loader || loaders.find_loader(nil) : loaders[loader_name]
132
+ if loader_name.nil?
133
+ default_loader || loaders[Loader::ENVIRONMENT_PRIVATE]
134
+ else
135
+ loaders[loader_name]
136
+ end
133
137
  end
134
138
  end
135
139
 
@@ -145,12 +149,14 @@ module Adapters
145
149
  #
146
150
  # The method returns `nil` when no module could be found.
147
151
  #
148
- # @param scope
149
- # @param instance
152
+ # @param environment [Puppet::Node::Environment] the current environment
153
+ # @param instance [Model::PopsObject] the AST for the code
154
+ # @param file [String] the path to the file for the code or `nil`
155
+ # @return [String] the name of the loader associated with the source
150
156
  # @api private
151
157
  def self.loader_name_by_source(environment, instance, file)
152
158
  file = find_file(instance) if file.nil?
153
- return nil if file.nil?
159
+ return nil if file.nil? || EMPTY_STRING == file
154
160
  pn_adapter = PathsAndNameCacheAdapter.adapt(environment) do |a|
155
161
  a.paths ||= environment.modulepath.map { |p| Pathname.new(p) }
156
162
  a.cache ||= {}
@@ -67,12 +67,10 @@ module Runtime3ResourceSupport
67
67
  end
68
68
 
69
69
  def self.find_resource_type(scope, type_name)
70
- type_name = type_name.to_s.downcase
71
70
  find_builtin_resource_type(scope, type_name) || find_defined_resource_type(scope, type_name)
72
71
  end
73
72
 
74
73
  def self.find_resource_type_or_class(scope, name)
75
- type_name = type_name.to_s.downcase
76
74
  find_builtin_resource_type(scope, name) || find_defined_resource_type(scope, name) || find_hostclass(scope, name)
77
75
  end
78
76
 
@@ -44,6 +44,30 @@ module Runtime3Support
44
44
  diagnostic_producer.accept(issue, semantic, options, except)
45
45
  end
46
46
 
47
+ # Optionally (based on severity) Fails the evaluation with a given issue
48
+ # If the given issue is configured to be of severity < :error it is only reported, and the function returns.
49
+ # The location the issue is reported against is found is based on the top file/line in the puppet call stack
50
+ #
51
+ # @param issue [Issue] the issue to report
52
+ # @param options [Hash] hash of optional named data elements for the given issue
53
+ # @return [!] this method may not return, nil if it does
54
+ # @raise [Puppet::ParseError] an evaluation error initialized from the arguments
55
+ #
56
+ def runtime_issue(issue, options={})
57
+ # Get position from puppet runtime stack
58
+ stacktrace = Puppet::Pops::PuppetStack.stacktrace()
59
+ if stacktrace.size > 0
60
+ file, line = stacktrace[0]
61
+ else
62
+ file = nil
63
+ line = nil
64
+ end
65
+ # Use a SemanticError as the sourcepos
66
+ semantic = Puppet::Pops::SemanticError.new(issue, nil, options.merge({:file => file, :line => line}))
67
+ optionally_fail(issue, semantic)
68
+ nil
69
+ end
70
+
47
71
  # Binds the given variable name to the given value in the given scope.
48
72
  # The reference object `o` is intended to be used for origin information - the 3x scope implementation
49
73
  # only makes use of location when there is an error. This is now handled by other mechanisms; first a check
@@ -236,9 +260,14 @@ module Runtime3Support
236
260
  # @return [Numeric] value `v` converted to Numeric.
237
261
  #
238
262
  def coerce_numeric(v, o, scope)
263
+ if v.is_a?(Numeric)
264
+ return v
265
+ end
239
266
  unless n = Utils.to_n(v)
240
267
  fail(Issues::NOT_NUMERIC, o, {:value => v})
241
268
  end
269
+ # this point is reached if there was a conversion
270
+ optionally_fail(Issues::NUMERIC_COERCION, o, {:before => v, :after => n})
242
271
  n
243
272
  end
244
273
 
@@ -498,6 +527,8 @@ module Runtime3Support
498
527
  # Store config issues, ignore or warning
499
528
  p[Issues::RT_NO_STORECONFIGS_EXPORT] = Puppet[:storeconfigs] ? :ignore : :warning
500
529
  p[Issues::RT_NO_STORECONFIGS] = Puppet[:storeconfigs] ? :ignore : :warning
530
+ p[Issues::CLASS_NOT_VIRTUALIZABLE] = Puppet[:strict] == :off ? :warning : Puppet[:strict]
531
+ p[Issues::NUMERIC_COERCION] = Puppet[:strict] == :off ? :ignore : Puppet[:strict]
501
532
  end
502
533
  end
503
534
 
@@ -368,6 +368,10 @@ module Issues
368
368
  "Resource Defaults are not virtualizable"
369
369
  end
370
370
 
371
+ CLASS_NOT_VIRTUALIZABLE = issue :CLASS_NOT_VIRTUALIZABLE do
372
+ "Classes are not virtualizable"
373
+ end
374
+
371
375
  # When an attempt is made to use multiple keys (to produce a range in Ruby - e.g. $arr[2,-1]).
372
376
  # This is not supported in 3x, but it allowed in 4x.
373
377
  #
@@ -502,6 +506,10 @@ module Issues
502
506
  "The value '#{value}' cannot be converted to Numeric."
503
507
  end
504
508
 
509
+ NUMERIC_COERCION = issue :NUMERIC_COERCION, :before, :after do
510
+ "The string '#{before}' was automatically coerced to the numerical value #{after}"
511
+ end
512
+
505
513
  UNKNOWN_FUNCTION = issue :UNKNOWN_FUNCTION, :name do
506
514
  "Unknown function: '#{name}'."
507
515
  end
@@ -21,6 +21,10 @@
21
21
  #
22
22
  module Puppet::Pops
23
23
  module Loader
24
+
25
+ ENVIRONMENT = 'environment'.freeze
26
+ ENVIRONMENT_PRIVATE = 'environment private'.freeze
27
+
24
28
  class Loader
25
29
  attr_reader :loader_name
26
30
 
@@ -21,8 +21,6 @@ module Loader
21
21
  # @api private
22
22
  #
23
23
  module ModuleLoaders
24
- ENVIRONMENT = 'environment'.freeze
25
-
26
24
  def self.system_loader_from(parent_loader, loaders)
27
25
  # Puppet system may be installed in a fixed location via RPM, installed as a Gem, via source etc.
28
26
  # The only way to find this across the different ways puppet can be installed is
@@ -171,7 +171,7 @@ class StaticLoader < Loader
171
171
  end
172
172
 
173
173
  def create_resource_type_reference(name)
174
- typed_name = TypedName.new(:type, name.downcase)
174
+ typed_name = TypedName.new(:type, name)
175
175
  type = Puppet::Pops::Types::TypeFactory.resource(name)
176
176
  @loaded[ typed_name ] = NamedEntry.new(typed_name, type, __FILE__)
177
177
  end
@@ -46,7 +46,7 @@ class TypeDefinitionInstantiator
46
46
  end
47
47
 
48
48
  def self.create_from_model(type_definition, loader)
49
- typed_name = TypedName.new(:type, type_definition.name.downcase)
49
+ typed_name = TypedName.new(:type, type_definition.name)
50
50
  type = create_runtime_type(type_definition)
51
51
  loader.set_entry(
52
52
  typed_name,
@@ -12,6 +12,7 @@ class TypedName
12
12
  attr_reader :compound_name
13
13
 
14
14
  def initialize(type, name, name_authority = Pcore::RUNTIME_NAME_AUTHORITY)
15
+ name = name.downcase
15
16
  @type = type
16
17
  @name_authority = name_authority
17
18
  # relativize the name (get rid of leading ::), and make the split string available
@@ -94,7 +94,7 @@ class Loaders
94
94
  loader = @private_environment_loader
95
95
  types = obj_classes.map do |obj_class|
96
96
  type = obj_class._ptype
97
- typed_name = Loader::TypedName.new(:type, type.name.downcase, name_authority)
97
+ typed_name = Loader::TypedName.new(:type, type.name, name_authority)
98
98
  entry = loader.loaded_entry(typed_name)
99
99
  loader.set_entry(typed_name, type, obj_class._plocation) if entry.nil? || entry.value.nil?
100
100
  type
@@ -119,7 +119,7 @@ class Loaders
119
119
 
120
120
  name = name.to_s
121
121
  caps_name = Types::TypeFormatter.singleton.capitalize_segments(name)
122
- typed_name = Loader::TypedName.new(:type, name.downcase)
122
+ typed_name = Loader::TypedName.new(:type, name)
123
123
  rt3_loader.set_entry(typed_name, Types::PResourceType.new(caps_name), origin)
124
124
  nil
125
125
  end
@@ -170,15 +170,9 @@ class Loaders
170
170
  # @raise [Puppet::ParseError] if no loader can be found
171
171
  # @api private
172
172
  def find_loader(module_name)
173
- if module_name.nil? || module_name == ''
174
- # TODO : Later when fdefinition can be private, a decision is needed regarding what that means.
175
- # A private environment loader could be used for logic outside of modules, then only that logic
176
- # would see the definition.
177
- #
178
- # Use the private loader, this definition may see the environment's dependencies (currently, all modules)
179
- loader = private_environment_loader()
180
- raise Puppet::ParseError, 'Internal Error: did not find public loader' if loader.nil?
181
- loader
173
+ if module_name.nil? || EMPTY_STRING == module_name
174
+ # Use the public environment loader
175
+ public_environment_loader
182
176
  else
183
177
  # TODO : Later check if definition is private, and then add it to private_loader_for_module
184
178
  #
@@ -248,8 +242,6 @@ class Loaders
248
242
  # available modules. (3x is everyone sees everything).
249
243
  # Puppet binder currently reads confdir/bindings - that is bad, it should be using the new environment support.
250
244
 
251
- # The environment is not a namespace, so give it a nil "module_name"
252
- loader_name = "environment:#{environment.name}"
253
245
  # env_conf is setup from the environment_dir value passed into Puppet::Environments::Directories.new
254
246
  env_conf = Puppet.lookup(:environments).get_conf(environment.name)
255
247
  env_path = env_conf.nil? || !env_conf.is_a?(Puppet::Settings::EnvironmentConf) ? nil : env_conf.path_to_env
@@ -259,7 +251,7 @@ class Loaders
259
251
 
260
252
  if env_path.nil?
261
253
  # Not a real directory environment, cannot work as a module TODO: Drop when legacy env are dropped?
262
- loader = add_loader_by_name(Loader::SimpleEnvironmentLoader.new(@runtime3_type_loader, loader_name))
254
+ loader = add_loader_by_name(Loader::SimpleEnvironmentLoader.new(@runtime3_type_loader, Loader::ENVIRONMENT))
263
255
  else
264
256
  # View the environment as a module to allow loading from it - this module is always called 'environment'
265
257
  loader = Loader::ModuleLoaders.environment_loader_from(@runtime3_type_loader, self, env_path)
@@ -273,7 +265,7 @@ class Loaders
273
265
  # Code in the environment gets to see all modules (since there is no metadata for the environment)
274
266
  # but since this is not given to the module loaders, they can not load global code (since they can not
275
267
  # have prior knowledge about this
276
- loader = add_loader_by_name(Loader::DependencyLoader.new(loader, 'environment private', @module_resolver.all_module_loaders()))
268
+ loader = add_loader_by_name(Loader::DependencyLoader.new(loader, Loader::ENVIRONMENT_PRIVATE, @module_resolver.all_module_loaders()))
277
269
 
278
270
  # The module loader gets the private loader via a lazy operation to look up the module's private loader.
279
271
  # This does not work for an environment since it is not resolved the same way.
@@ -17,7 +17,7 @@ class EnvironmentDataProvider < ConfiguredDataProvider
17
17
  if Puppet[:strict] == :error
18
18
  config.fail(Issues::HIERA_VERSION_3_NOT_GLOBAL, :where => 'environment')
19
19
  else
20
- Puppet.warn_once(:hiera_v3_at_env_root, config.config_path, 'hiera.yaml version 3 found at the environment root was ignored')
20
+ Puppet.warn_once(:hiera_v3_at_env_root, config.config_path, _('hiera.yaml version 3 found at the environment root was ignored'), config.config_path)
21
21
  end
22
22
  nil
23
23
  end
@@ -106,7 +106,9 @@ class HieraConfig
106
106
  def self.symkeys_to_string(struct)
107
107
  case(struct)
108
108
  when Hash
109
- Hash[struct.map { |k,v| [k.to_s, symkeys_to_string(v)] }]
109
+ map = {}
110
+ struct.each_pair {|k,v| map[ k.is_a?(Symbol) ? k.to_s : k] = symkeys_to_string(v) }
111
+ map
110
112
  when Array
111
113
  struct.map { |v| symkeys_to_string(v) }
112
114
  else
@@ -57,10 +57,11 @@ module Interpolation
57
57
  # Alias is only permitted if the entire string is equal to the interpolate expression
58
58
  fail(Issues::HIERA_INTERPOLATION_ALIAS_NOT_ENTIRE_STRING) if is_alias && subject != match
59
59
  value = interpolate_method(method_key).call(key, lookup_invocation, subject)
60
- value = lookup_invocation.check(method_key == :scope ? "scope:#{key}" : key) { interpolate(value, lookup_invocation, allow_methods) }
61
60
 
62
61
  # break gsub and return value immediately if this was an alias substitution. The value might be something other than a String
63
62
  return value if is_alias
63
+
64
+ value = lookup_invocation.check(method_key == :scope ? "scope:#{key}" : key) { interpolate(value, lookup_invocation, allow_methods) }
64
65
  end
65
66
  value.nil? ? '' : value
66
67
  end
@@ -16,7 +16,7 @@ class LookupKey
16
16
  @key = key
17
17
  @module_name = qual_index.nil? ? nil : root_key[0..qual_index-1].freeze
18
18
  @root_key = root_key
19
- @segments = segments.empty? ? nil : segments.map { |segment| segment =~ /^[0-9]+$/ ? segment.to_i : segment }.freeze
19
+ @segments = segments.empty? ? nil : segments.freeze
20
20
  end
21
21
 
22
22
  def dig(lookup_invocation, value)
@@ -60,8 +60,16 @@ class ModuleDataProvider < ConfiguredDataProvider
60
60
  protected
61
61
 
62
62
  def assert_config_version(config)
63
- config.fail(Issues::HIERA_VERSION_3_NOT_GLOBAL, :where => 'module') unless config.version > 3
64
- config
63
+ if config.version > 3
64
+ config
65
+ else
66
+ if Puppet[:strict] == :error
67
+ config.fail(Issues::HIERA_VERSION_3_NOT_GLOBAL, :where => 'module')
68
+ else
69
+ Puppet.warn_once(:hiera_v3_at_module_root, config.config_path, _('hiera.yaml version 3 found at module root was ignored'), config.config_path)
70
+ end
71
+ nil
72
+ end
65
73
  end
66
74
 
67
75
  # Return the root of the module with the name equal to the configured module name
@@ -30,7 +30,13 @@ module SubLookup
30
30
  raise yield('Syntax error') unless segments.size * 2 == count + 1
31
31
  segments.map! do |segment|
32
32
  segment.strip!
33
- segment.start_with?('"') || segment.start_with?("'") ? segment[1..-2] : segment
33
+ if segment.start_with?('"') || segment.start_with?("'")
34
+ segment[1..-2]
35
+ elsif segment =~ /^(:?[+-]?[0-9]+)$/
36
+ segment.to_i
37
+ else
38
+ segment
39
+ end
34
40
  end
35
41
  else
36
42
  raise yield('Syntax error')
@@ -58,18 +64,13 @@ module SubLookup
58
64
  lookup_invocation.report_not_found(segment)
59
65
  throw :no_such_key
60
66
  end
61
- if segment.is_a?(Integer) || segment =~ /^[0-9]+$/
62
- segment = segment.to_i
63
- unless value.instance_of?(Array)
64
- raise Puppet::DataBinding::LookupError,
65
- "Data Provider type mismatch: Got #{value.class.name} when Array was expected to access value using '#{segment}' from key '#{key}'"
66
- end
67
- unless segment < value.size
67
+ if segment.is_a?(Integer) && value.instance_of?(Array)
68
+ unless segment >= 0 && segment < value.size
68
69
  lookup_invocation.report_not_found(segment)
69
70
  throw :no_such_key
70
71
  end
71
72
  else
72
- unless value.respond_to?(:'[]') && !(value.instance_of?(Array) || value.instance_of?(String))
73
+ unless value.respond_to?(:'[]') && !(value.is_a?(Array) || value.instance_of?(String))
73
74
  raise Puppet::DataBinding::LookupError,
74
75
  "Data Provider type mismatch: Got #{value.class.name} when a hash-like object was expected to access value using '#{segment}' from key '#{key}'"
75
76
  end
@@ -203,7 +203,7 @@ class Lexer2
203
203
  # PERFORMANCE NOTE:
204
204
  # Comparison against a frozen string is faster (than unfrozen).
205
205
  #
206
- STRING_BSLASH_BSLASH = '\\'.freeze
206
+ STRING_BSLASH_SLASH = '\/'.freeze
207
207
 
208
208
  attr_reader :locator
209
209
 
@@ -376,8 +376,10 @@ class Lexer2
376
376
  # regexp position is a regexp, else a div
377
377
  if regexp_acceptable? && value = scn.scan(PATTERN_REGEX)
378
378
  # Ensure an escaped / was not matched
379
- while value[-2..-2] == STRING_BSLASH_BSLASH # i.e. \\
380
- value += scn.scan_until(PATTERN_REGEX_END)
379
+ while escaped_end(value)
380
+ more = scn.scan_until(PATTERN_REGEX_END)
381
+ return emit(TOKEN_DIV, before) unless more
382
+ value << more
381
383
  end
382
384
  regex = value.sub(PATTERN_REGEX_A, '').sub(PATTERN_REGEX_Z, '').gsub(PATTERN_REGEX_ESC, '/')
383
385
  emit_completed([:REGEX, Regexp.new(regex), scn.pos-before], before)
@@ -597,6 +599,21 @@ class Lexer2
597
599
  @selector.freeze
598
600
  end
599
601
 
602
+ # Determine if last char of value is escaped by a backslash
603
+ def escaped_end(value)
604
+ escaped = false
605
+ if value.end_with?(STRING_BSLASH_SLASH)
606
+ value[1...-1].each_codepoint do |cp|
607
+ if cp == 0x5c # backslash
608
+ escaped = !escaped
609
+ else
610
+ escaped = false
611
+ end
612
+ end
613
+ end
614
+ escaped
615
+ end
616
+
600
617
  # Clears the lexer state (it is not required to call this as it will be garbage collected
601
618
  # and the next lex call (lex_string, lex_file) will reset the internal state.
602
619
  #
@@ -77,7 +77,7 @@ module Pcore
77
77
  end
78
78
 
79
79
  def self.add_type(type, loader, name_authority = RUNTIME_NAME_AUTHORITY)
80
- loader.set_entry(Loader::TypedName.new(:type, type.name.downcase, name_authority), type)
80
+ loader.set_entry(Loader::TypedName.new(:type, type.name, name_authority), type)
81
81
  type
82
82
  end
83
83
 
@@ -90,7 +90,7 @@ module Pcore
90
90
  add_type(Types::PTypeAliasType.new(name, Types::TypeFactory.type_reference(type_string), nil), loader, name_authority)
91
91
  end
92
92
  parser = Types::TypeParser.singleton
93
- aliases.each_key.map { |name| loader.load(:type, name.downcase).resolve(parser, loader) }
93
+ aliases.each_key.map { |name| loader.load(:type, name).resolve(parser, loader) }
94
94
  end
95
95
  end
96
96
  end