puppet 4.10.0 → 4.10.1

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 (34) hide show
  1. data/Gemfile +11 -35
  2. data/lib/puppet.rb +2 -2
  3. data/lib/puppet/defaults.rb +44 -12
  4. data/lib/puppet/indirector/catalog/compiler.rb +4 -2
  5. data/lib/puppet/module_tool/tar.rb +3 -3
  6. data/lib/puppet/parser/functions/new.rb +14 -1
  7. data/lib/puppet/pops/lookup.rb +3 -3
  8. data/lib/puppet/pops/lookup/global_data_provider.rb +6 -9
  9. data/lib/puppet/pops/lookup/interpolation.rb +6 -7
  10. data/lib/puppet/pops/lookup/invocation.rb +12 -2
  11. data/lib/puppet/pops/lookup/lookup_adapter.rb +11 -7
  12. data/lib/puppet/pops/serialization/object.rb +1 -1
  13. data/lib/puppet/pops/serialization/serializer.rb +9 -2
  14. data/lib/puppet/pops/types/string_converter.rb +24 -21
  15. data/lib/puppet/pops/types/types.rb +16 -0
  16. data/lib/puppet/resource.rb +58 -20
  17. data/lib/puppet/resource/catalog.rb +3 -10
  18. data/lib/puppet/version.rb +1 -1
  19. data/locales/puppet.pot +58 -3
  20. data/spec/integration/application/apply_spec.rb +1 -0
  21. data/spec/shared_contexts/types_setup.rb +28 -10
  22. data/spec/unit/functions/lookup_spec.rb +71 -0
  23. data/spec/unit/indirector/catalog/compiler_spec.rb +32 -4
  24. data/spec/unit/module_tool/tar_spec.rb +16 -10
  25. data/spec/unit/pops/lookup/interpolation_spec.rb +2 -2
  26. data/spec/unit/pops/serialization/serialization_spec.rb +30 -4
  27. data/spec/unit/pops/types/p_sem_ver_type_spec.rb +12 -17
  28. data/spec/unit/pops/types/p_type_set_type_spec.rb +2 -2
  29. data/spec/unit/pops/types/string_converter_spec.rb +21 -9
  30. data/spec/unit/pops/types/type_calculator_spec.rb +2 -2
  31. data/spec/unit/pops/types/types_spec.rb +11 -0
  32. data/spec/unit/resource/catalog_spec.rb +14 -15
  33. metadata +25 -13
  34. checksums.yaml +0 -7
data/Gemfile CHANGED
@@ -1,5 +1,7 @@
1
1
  source ENV['GEM_SOURCE'] || "https://rubygems.org"
2
2
 
3
+ gemspec
4
+
3
5
  def location_for(place, fake_version = nil)
4
6
  if place =~ /^(git[:@][^#]*)#(.*)/
5
7
  [fake_version, { :git => $1, :branch => $2, :require => false }].compact
@@ -13,7 +15,6 @@ end
13
15
  # C Ruby (MRI) or Rubinius, but NOT Windows
14
16
  platforms :ruby do
15
17
  gem 'pry', :group => :development
16
- gem 'yard', :group => :development
17
18
  gem 'redcarpet', '~> 2.0', :group => :development
18
19
  gem "racc", "1.4.9", :group => :development
19
20
 
@@ -23,20 +24,18 @@ platforms :ruby do
23
24
  #gem 'ruby-augeas', :group => :development
24
25
  end
25
26
 
26
- gem "puppet", :path => File.dirname(__FILE__), :require => false
27
- gem "facter", *location_for(ENV['FACTER_LOCATION'] || ['> 2.0', '< 4'])
28
- gem "hiera", *location_for(ENV['HIERA_LOCATION'] || ['>= 2.0', '< 4'])
27
+ # override .gemspec deps - may issue warning depending on Bundler version
28
+ gem "facter", *location_for(ENV['FACTER_LOCATION']) if ENV.has_key?('FACTER_LOCATION')
29
+ gem "hiera", *location_for(ENV['HIERA_LOCATION']) if ENV.has_key?('HIERA_LOCATION')
29
30
  # PUP-7115 - return to a gem dependency in Puppet 5
30
31
  # gem "semantic_puppet", *location_for(ENV['SEMANTIC_PUPPET_LOCATION'] || ['>= 0.1.3', '< 2'])
31
- gem "rake", "10.1.1", :require => false
32
- # Hiera has an unbound dependency on json_pure
33
- # json_pure 2.0.2+ officially requires Ruby >= 2.0, but should have specified that in 2.0
34
- gem 'json_pure', '~> 1.8', :require => false
35
- # i18n support (gettext-setup and dependencies)
36
- gem 'gettext-setup', '>= 0.10', '< 1.0', :require => false
37
- gem 'locale', '~> 2.1', :require => false
38
32
 
39
33
  group(:development, :test) do
34
+ # rake is in .gemspec as a development dependency but cannot
35
+ # be removed here *yet* due to TravisCI / AppVeyor which call:
36
+ # bundle install --without development
37
+ # PUP-7433 describes work necessary to restructure this
38
+ gem "rake", "10.1.1", :require => false
40
39
  gem "rspec", "~> 3.1", :require => false
41
40
  gem "rspec-its", "~> 1.1", :require => false
42
41
  gem "rspec-collection_matchers", "~> 1.1", :require => false
@@ -57,6 +56,7 @@ group(:development, :test) do
57
56
  gem "rubocop", "~> 0.39.0", :platforms => [:ruby]
58
57
 
59
58
  gem 'rdoc', "~> 4.1", :platforms => [:ruby]
59
+ gem 'yard'
60
60
 
61
61
  # webmock requires addressable as as of 2.5.0 addressable started
62
62
  # requiring the public_suffix gem which requires Ruby 2
@@ -75,34 +75,10 @@ end
75
75
 
76
76
  group(:extra) do
77
77
  gem "rack", "~> 1.4", :require => false
78
- gem "net-ssh", '~> 2.1', :require => false
79
78
  gem "puppetlabs_spec_helper", :require => false
80
- gem "tzinfo", :require => false
81
79
  gem "msgpack", :require => false
82
80
  end
83
81
 
84
- require 'yaml'
85
- data = YAML.load_file(File.join(File.dirname(__FILE__), 'ext', 'project_data.yaml'))
86
- bundle_platforms = data['bundle_platforms']
87
- x64_platform = Gem::Platform.local.cpu == 'x64'
88
- data['gem_platform_dependencies'].each_pair do |gem_platform, info|
89
- next if gem_platform == 'x86-mingw32' && x64_platform
90
- next if gem_platform == 'x64-mingw32' && !x64_platform
91
- if bundle_deps = info['gem_runtime_dependencies']
92
- bundle_platform = bundle_platforms[gem_platform] or raise "Missing bundle_platform"
93
- if bundle_platform == "all"
94
- bundle_deps.each_pair do |name, version|
95
- gem(name, version, :require => false)
96
- end
97
- else
98
- platform(bundle_platform.intern) do
99
- bundle_deps.each_pair do |name, version|
100
- gem(name, version, :require => false)
101
- end
102
- end
103
- end
104
- end
105
- end
106
82
 
107
83
  if File.exists? "#{__FILE__}.local"
108
84
  eval(File.read("#{__FILE__}.local"), binding)
@@ -1,6 +1,6 @@
1
1
  require 'puppet/version'
2
2
 
3
- if RUBY_VERSION < "1.9.3"
3
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("1.9.3")
4
4
  raise LoadError, "Puppet #{Puppet.version} requires ruby 1.9.3 or greater."
5
5
  end
6
6
 
@@ -164,7 +164,7 @@ module Puppet
164
164
 
165
165
  # Now that settings are loaded we have the code loaded to be able to issue
166
166
  # deprecation warnings. Warn if we're on a deprecated ruby version.
167
- if RUBY_VERSION < Puppet::OLDEST_RECOMMENDED_RUBY_VERSION
167
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new(Puppet::OLDEST_RECOMMENDED_RUBY_VERSION)
168
168
  Puppet.deprecation_warning("Support for ruby version #{RUBY_VERSION} is deprecated and will be removed in a future release. See https://docs.puppet.com/puppet/latest/system_requirements.html#ruby for a list of supported ruby versions.")
169
169
  end
170
170
 
@@ -407,7 +407,29 @@ deprecated and has been replaced by 'always_retry_plugins'."
407
407
  :node_terminus => {
408
408
  :type => :terminus,
409
409
  :default => "plain",
410
- :desc => "Where to find information about nodes.",
410
+ :desc => <<-'EOT',
411
+ Which node data plugin to use when compiling node catalogs.
412
+
413
+ When Puppet compiles a catalog, it combines two primary sources of info: the main manifest,
414
+ and a node data plugin (often called a "node terminus," for historical reasons). Node data
415
+ plugins provide three things for a given node name:
416
+
417
+ 1. A list of classes to add to that node's catalog (and, optionally, values for their
418
+ parameters).
419
+ 2. Which Puppet environment the node should use.
420
+ 3. A list of additional top-scope variables to set.
421
+
422
+ The three main node data plugins are:
423
+
424
+ * `plain` --- Returns no data, so that the main manifest controls all node configuration.
425
+ * `exec` --- Uses an
426
+ [external node classifier (ENC)](https://docs.puppet.com/puppet/latest/nodes_external.html),
427
+ configured by the `external_nodes` setting. This lets you pull a list of Puppet classes
428
+ from any external system, using a small glue script to perform the request and format the
429
+ result as YAML.
430
+ * `classifier` (formerly `console`) --- Specific to Puppet Enterprise. Uses the PE console
431
+ for node data."
432
+ EOT
411
433
  },
412
434
  :node_cache_terminus => {
413
435
  :type => :terminus,
@@ -1802,14 +1824,24 @@ EOT
1802
1824
  :main,
1803
1825
  :external_nodes => {
1804
1826
  :default => "none",
1805
- :desc => "An external command that can produce node information. The command's output
1806
- must be a YAML dump of a hash, and that hash must have a `classes` key and/or
1807
- a `parameters` key, where `classes` is an array or hash and
1808
- `parameters` is a hash. For unknown nodes, the command should
1809
- exit with a non-zero exit code.
1810
-
1811
- This command makes it straightforward to store your node mapping
1812
- information in other data sources like databases.",
1827
+ :desc => "The external node classifier (ENC) script to use for node data.
1828
+ Puppet combines this data with the main manifest to produce node catalogs.
1829
+
1830
+ To enable this setting, set the `node_terminus` setting to `exec`.
1831
+
1832
+ This setting's value must be the path to an executable command that
1833
+ can produce node information. The command must:
1834
+
1835
+ * Take the name of a node as a command-line argument.
1836
+ * Return a YAML hash with up to three keys:
1837
+ * `classes` --- A list of classes, as an array or hash.
1838
+ * `environment` --- A string.
1839
+ * `parameters` --- A list of top-scope variables to set, as a hash.
1840
+ * For unknown nodes, exit with a non-zero exit code.
1841
+
1842
+ Generally, an ENC script makes requests to an external data source.
1843
+
1844
+ For more info, see [the ENC documentation](https://docs.puppet.com/puppet/latest/nodes_external.html).",
1813
1845
  }
1814
1846
  )
1815
1847
 
@@ -1968,10 +2000,10 @@ EOT
1968
2000
  envs.clear_all unless envs.nil?
1969
2001
  end,
1970
2002
  :desc => <<-'EOT'
1971
- Enables having extended data in the catalog by adding the key `ext_parameters` to serialized
1972
- resources. When enabled, resource containing values of the data types `Binary`, `Regexp`,
2003
+ Enables having extended data in the catalog by storing them as a hash with the special key
2004
+ `__pcore_type__`. When enabled, resource containing values of the data types `Binary`, `Regexp`,
1973
2005
  `SemVer`, `SemVerRange`, `Timespan` and `Timestamp`, as well as instances of types derived
1974
- from `Object` retain their data type and are serialized using Pcore in `ext_parameters`.
2006
+ from `Object` retain their data type.
1975
2007
  EOT
1976
2008
  }
1977
2009
  )
@@ -25,9 +25,11 @@ class Puppet::Resource::Catalog::Compiler < Puppet::Indirector::Code
25
25
  # in Network::HTTP::Handler will automagically deserialize the value.
26
26
  if text_facts.is_a?(Puppet::Node::Facts)
27
27
  facts = text_facts
28
- else
28
+ elsif format == 'pson'
29
29
  # We unescape here because the corresponding code in Puppet::Configurer::FactHandler escapes
30
- facts = Puppet::Node::Facts.convert_from(format, CGI.unescape(text_facts))
30
+ facts = Puppet::Node::Facts.convert_from('pson', CGI.unescape(text_facts))
31
+ else
32
+ raise ArgumentError, "Unsupported facts format"
31
33
  end
32
34
 
33
35
  unless facts.name == request.key
@@ -6,10 +6,10 @@ module Puppet::ModuleTool::Tar
6
6
  require 'puppet/module_tool/tar/mini'
7
7
 
8
8
  def self.instance
9
- if Puppet::Util.which('tar') && ! Puppet::Util::Platform.windows?
10
- Gnu.new
11
- elsif Puppet.features.minitar? && Puppet.features.zlib?
9
+ if Puppet.features.minitar? && Puppet.features.zlib?
12
10
  Mini.new
11
+ elsif Puppet::Util.which('tar') && ! Puppet::Util::Platform.windows?
12
+ Gnu.new
13
13
  else
14
14
  raise RuntimeError, 'No suitable tar implementation found'
15
15
  end
@@ -635,7 +635,7 @@ Defaults to `s` at top level and `p` inside array or hash.
635
635
 
636
636
  | Format | Regexp Formats
637
637
  | ---- | --------------
638
- | s | Delimiters `/ /`, alternate flag `#` replaces `/` delimiters with quotes.
638
+ | s | No delimiters, quoted if alternative flag `#` is used.
639
639
  | p | Delimiters `/ /`.
640
640
 
641
641
  ### Undef to String
@@ -775,6 +775,19 @@ Accepts a single value as argument:
775
775
  Conversion to a `Struct` works exactly as conversion to a `Hash`, only that the constructed hash is
776
776
  asserted against the given struct type.
777
777
 
778
+ Conversion to a Regexp
779
+ ---
780
+ A `String` can be converted into a `Regexp`
781
+
782
+ **Example**: Converting a String into a Regexp
783
+ ```puppet
784
+ $s = '[a-z]+\.com'
785
+ $r = Regexp($s)
786
+ if('foo.com' =~ $r) {
787
+ ...
788
+ }
789
+ ```
790
+
778
791
  Creating a SemVer
779
792
  ---
780
793
 
@@ -28,7 +28,7 @@ module Lookup
28
28
  override_values = lookup_invocation.override_values
29
29
  result_with_name = names.reduce([nil, not_found]) do |memo, key|
30
30
  value = override_values.include?(key) ? assert_type(["Value found for key '%s' in override hash", key], value_type, override_values[key]) : not_found
31
- catch(:no_such_key) { value = search_and_merge(key, lookup_invocation, merge) } if value.equal?(not_found)
31
+ catch(:no_such_key) { value = search_and_merge(key, lookup_invocation, merge, false) } if value.equal?(not_found)
32
32
  break [key, assert_type('Found value', value_type, value)] unless value.equal?(not_found)
33
33
  memo
34
34
  end
@@ -72,9 +72,9 @@ module Lookup
72
72
  end
73
73
 
74
74
  # @api private
75
- def self.search_and_merge(name, lookup_invocation, merge)
75
+ def self.search_and_merge(name, lookup_invocation, merge, apl = true)
76
76
  answer = lookup_invocation.lookup_adapter.lookup(name, lookup_invocation, merge)
77
- lookup_invocation.emit_debug_info("Automatic Parameter Lookup of '#{name}") if Puppet[:debug]
77
+ lookup_invocation.emit_debug_info("Automatic Parameter Lookup of '#{name}'") if apl && Puppet[:debug]
78
78
  answer
79
79
  end
80
80
 
@@ -15,16 +15,13 @@ class GlobalDataProvider < ConfiguredDataProvider
15
15
  # Hiera version 3 needs access to special scope variables
16
16
  scope = lookup_invocation.scope
17
17
  unless scope.is_a?(Hiera::Scope)
18
- hiera_invocation = Invocation.new(
19
- Hiera::Scope.new(scope),
20
- lookup_invocation.override_values,
21
- lookup_invocation.default_values,
22
- lookup_invocation.explainer)
18
+ return lookup_invocation.with_scope(Hiera::Scope.new(scope)) do |hiera_invocation|
23
19
 
24
- # Confine to global scope unless an environment data provider has been defined (same as for hiera_xxx functions)
25
- adapter = lookup_invocation.lookup_adapter
26
- hiera_invocation.set_global_only unless adapter.global_only? || adapter.has_environment_data_provider?(lookup_invocation)
27
- lookup_invocation = hiera_invocation
20
+ # Confine to global scope unless an environment data provider has been defined (same as for hiera_xxx functions)
21
+ adapter = lookup_invocation.lookup_adapter
22
+ hiera_invocation.set_global_only unless adapter.global_only? || adapter.has_environment_data_provider?(lookup_invocation)
23
+ hiera_invocation.lookup(key, lookup_invocation.module_name) { unchecked_key_lookup(key , hiera_invocation, merge) }
24
+ end
28
25
  end
29
26
 
30
27
  merge = MergeStrategy.strategy(merge)
@@ -70,15 +70,14 @@ module Interpolation
70
70
  def interpolate_method(method_key)
71
71
  @@interpolate_methods ||= begin
72
72
  global_lookup = lambda do |key, lookup_invocation, _|
73
- if lookup_invocation.scope.is_a?(Hiera::Scope) && !lookup_invocation.global_only?
73
+ scope = lookup_invocation.scope
74
+ if scope.is_a?(Hiera::Scope) && !lookup_invocation.global_only?
74
75
  # "unwrap" the Hiera::Scope
75
- lookup_invocation = Invocation.new(
76
- lookup_invocation.scope.real,
77
- lookup_invocation.override_values,
78
- lookup_invocation.default_values,
79
- lookup_invocation.explainer)
76
+ scope = scope.real
77
+ end
78
+ lookup_invocation.with_scope(scope) do |sub_invocation|
79
+ sub_invocation.lookup(key) { Lookup.lookup(key, nil, '', true, nil, sub_invocation) }
80
80
  end
81
- Lookup.lookup(key, nil, '', true, nil, lookup_invocation)
82
81
  end
83
82
  scope_lookup = lambda do |key, lookup_invocation, subject|
84
83
  segments = split_key(key) { |problem| Puppet::DataBinding::LookupError.new("#{problem} in string: #{subject}") }
@@ -10,6 +10,15 @@ class Invocation
10
10
  @current
11
11
  end
12
12
 
13
+ # Creates a new instance with same settings as this instance but with a new given scope
14
+ # and yields with that scope.
15
+ #
16
+ # @param scope [Puppet::Parser::Scope] The new scope
17
+ # @return [Invocation] the new instance
18
+ def with_scope(scope)
19
+ yield(Invocation.new(scope, override_values, default_values, explainer))
20
+ end
21
+
13
22
  # Creates a context object for a lookup invocation. The object contains the current scope, overrides, and default
14
23
  # values and may optionally contain an {ExplanationAcceptor} instance that will receive book-keeping information
15
24
  # about the progress of the lookup.
@@ -53,9 +62,10 @@ class Invocation
53
62
  @explainer = explainer
54
63
  end
55
64
 
56
- def lookup(key, module_name)
65
+ def lookup(key, module_name = nil)
66
+ key = LookupKey.new(key) unless key.is_a?(LookupKey)
57
67
  @top_key = key
58
- @module_name = module_name
68
+ @module_name = module_name.nil? ? key.module_name : module_name
59
69
  save_current = self.class.current
60
70
  if save_current.equal?(self)
61
71
  yield
@@ -289,13 +289,17 @@ class LookupAdapter < DataAdapter
289
289
  compile_patterns(global_lookup_options(meta_invocation, merge_strategy))
290
290
  else
291
291
  opts = env_lookup_options(meta_invocation, merge_strategy)
292
- catch(:no_such_key) do
293
- module_opts = validate_lookup_options(lookup_in_module(LookupKey::LOOKUP_OPTIONS, meta_invocation, merge_strategy), module_name)
294
- opts = if opts.nil?
295
- module_opts
296
- else
297
- merge_strategy.lookup([GLOBAL_ENV_MERGE, "Module #{lookup_invocation.module_name}"], meta_invocation) do |n|
298
- meta_invocation.with(:scope, n) { meta_invocation.report_found(LOOKUP_OPTIONS, n == GLOBAL_ENV_MERGE ? opts : module_opts) }
292
+ unless module_name.nil?
293
+ # Store environment options at key nil. This removes the need for an additional lookup for keys that are not prefixed.
294
+ @lookup_options[nil] = compile_patterns(opts) unless @lookup_options.include?(nil)
295
+ catch(:no_such_key) do
296
+ module_opts = validate_lookup_options(lookup_in_module(LookupKey::LOOKUP_OPTIONS, meta_invocation, merge_strategy), module_name)
297
+ opts = if opts.nil?
298
+ module_opts
299
+ else
300
+ merge_strategy.lookup([GLOBAL_ENV_MERGE, "Module #{lookup_invocation.module_name}"], meta_invocation) do |n|
301
+ meta_invocation.with(:scope, n) { meta_invocation.report_found(LOOKUP_OPTIONS, n == GLOBAL_ENV_MERGE ? opts : module_opts) }
302
+ end
299
303
  end
300
304
  end
301
305
  end
@@ -52,7 +52,7 @@ class ObjectWriter
52
52
  args.pop
53
53
  end
54
54
 
55
- if type.name.start_with?('Pcore::')
55
+ if type.name.start_with?('Pcore::') || serializer.type_by_reference?
56
56
  serializer.push_written(value)
57
57
  serializer.start_pcore_object(type.name, args.size)
58
58
  else
@@ -10,11 +10,14 @@ module Serialization
10
10
  # @api private
11
11
  attr_reader :writer
12
12
 
13
- # @param [AbstractWriter] writer the writer that is used for writing primitive values
13
+ # @param writer [AbstractWriter] the writer that is used for writing primitive values
14
+ # @param options [{String, Object}] serialization options
15
+ # @option options [Boolean] :type_by_reference `true` if Object types are serialized by name only.
14
16
  # @api public
15
- def initialize(writer)
17
+ def initialize(writer, options = EMPTY_HASH)
16
18
  @written = {}
17
19
  @writer = writer
20
+ @options = options
18
21
  end
19
22
 
20
23
  # Tell the underlying writer to finish
@@ -81,6 +84,10 @@ module Serialization
81
84
  @writer.write(Extension::SensitiveStart::INSTANCE)
82
85
  end
83
86
 
87
+ def type_by_reference?
88
+ @options[:type_by_reference] == true
89
+ end
90
+
84
91
  # First time write of a tabulated object. This means that the object is written and then remembered. Subsequent writes
85
92
  # of the same object will yield a write of a tabulation index instead.
86
93
  # @param [Object] value the value to write
@@ -51,7 +51,7 @@ class StringConverter
51
51
 
52
52
  # Format represents one format specification that is textually represented by %<flags><width>.<precision><format>
53
53
  # Format parses and makes the individual parts available when an instance is created.
54
- #
54
+ #
55
55
  # @api private
56
56
  #
57
57
  class Format
@@ -172,7 +172,7 @@ class StringConverter
172
172
  # Sorts format based on generality of types - most specific types before general
173
173
  #
174
174
  def self.sort_formats(format_map)
175
- format_map = format_map.sort do |(a,_),(b,_)|
175
+ format_map = format_map.sort do |(a,_),(b,_)|
176
176
  ab = b.assignable?(a)
177
177
  ba = a.assignable?(b)
178
178
  if a == b
@@ -219,7 +219,7 @@ class StringConverter
219
219
  end
220
220
  # Returns an array with a delimiter pair derived from the format.
221
221
  # If format does not contain a delimiter specification the given default is returned
222
- #
222
+ #
223
223
  # @param [Array<String>] the default delimiters
224
224
  # @returns [Array<String>] a tuple with left, right delimiters
225
225
  #
@@ -289,7 +289,7 @@ class StringConverter
289
289
  # When converting to string it is possible to use a set of built in conversion rules.
290
290
  #
291
291
  # A format is specified on the form:
292
- #
292
+ #
293
293
  # ´´´
294
294
  # %[Flags][Width][.Precision]Format
295
295
  # ´´´
@@ -348,9 +348,9 @@ class StringConverter
348
348
  # Defaults to `s` at top level and `p` inside array or hash.
349
349
  #
350
350
  # ### Boolean
351
- #
351
+ #
352
352
  # | Format | Boolean Formats
353
- # | ---- | -------------------
353
+ # | ---- | -------------------
354
354
  # | t T | 'true'/'false' or 'True'/'False' , first char if alternate form is used (i.e. 't'/'f' or 'T'/'F').
355
355
  # | y Y | 'yes'/'no', 'Yes'/'No', 'y'/'n' or 'Y'/'N' if alternative flag # is used
356
356
  # | dxXobB | numeric value 0/1 in accordance with the given format which must be valid integer format
@@ -379,7 +379,7 @@ class StringConverter
379
379
  # | u | 'undef', or 'undefined' if alternative # flag is used
380
380
  #
381
381
  # ### Default (value)
382
- #
382
+ #
383
383
  # | Format | Default formats
384
384
  # | ------ | ---------------
385
385
  # | d D | 'default' or 'Default', alternative form # causes value to be quoted
@@ -420,18 +420,18 @@ class StringConverter
420
420
  #
421
421
  # | Format | Hash/Struct Formats
422
422
  # | ------ | -------------
423
- # | h | formats with `{ }` delimiters, `,` element separator and ` => ` inner element separator unless overridden by flags
423
+ # | h | formats with `{ }` delimiters, `,` element separator and ` => ` inner element separator unless overridden by flags
424
424
  # | s | same as h
425
425
  # | p | same as h
426
426
  # | a | converts the hash to an array of [k,v] tuples and formats it using array rule(s)
427
- #
427
+ #
428
428
  # See "Flags" `<[({\|` for formatting of delimiters, and "Additional parameters for containers; Array and Hash" for
429
429
  # more information about options.
430
430
  #
431
431
  # The alternate form flag `#` will format each hash key/value entry indented on a separate line.
432
432
  #
433
433
  # ### Type
434
- #
434
+ #
435
435
  # | Format | Array/Tuple Formats
436
436
  # | ------ | -------------
437
437
  # | s | The same as p, quoted if alternative flag # is used
@@ -439,7 +439,7 @@ class StringConverter
439
439
  #
440
440
  # ### Flags
441
441
  #
442
- # | Flag | Effect
442
+ # | Flag | Effect
443
443
  # | ------ | ------
444
444
  # | (space) | space instead of + for numeric output (- is shown), for containers skips delimiters
445
445
  # | # | alternate format; prefix 0x/0x, 0 (octal) and 0b/0B for binary, Floats force decimal '.'. For g/G keep trailing 0.
@@ -448,7 +448,7 @@ class StringConverter
448
448
  # | 0 | pad with 0 instead of space for widths larger than value
449
449
  # | <[({\| | defines an enclosing pair <> [] () {} or \| \| when used with a container type
450
450
  #
451
- #
451
+ #
452
452
  # ### Additional parameters for containers; Array and Hash
453
453
  #
454
454
  # For containers (Array and Hash), the format is specified by a hash where the following keys can be set:
@@ -456,7 +456,7 @@ class StringConverter
456
456
  # * `'separator'` - the separator string to use between elements, should not contain padding space at the end
457
457
  # * `'separator2'` - the separator string to use between association of hash entries key/value
458
458
  # * `'string_formats'´ - a map of type to format for elements contained in the container
459
- #
459
+ #
460
460
  # Note that the top level format applies to Array and Hash objects contained/nested in an Array or a Hash.
461
461
  #
462
462
  # Given format mappings are merged with (default) formats and a format specified for a narrower type
@@ -538,8 +538,9 @@ class StringConverter
538
538
  end
539
539
  private :validate_container_input
540
540
 
541
- def string_PRuntimeType(val_type, val, format_map)
542
- case (f = get_format(val_type, format_map))
541
+ def string_PRuntimeType(val_type, val, format_map, _)
542
+ f = get_format(val_type, format_map)
543
+ case f.format
543
544
  when :s
544
545
  val.to_s
545
546
  when :q
@@ -550,7 +551,7 @@ class StringConverter
550
551
  converted = convert(o, PNumericType) # rest is default
551
552
  "%#{f}" % converted
552
553
  else
553
- throw(:failed_conversion, [o, PStringType::DEFAULT, f])
554
+ raise FormatError.new('Runtime', f.format, 'sqidxof')
554
555
  end
555
556
  end
556
557
 
@@ -838,13 +839,15 @@ class StringConverter
838
839
  f = get_format(val_type, format_map)
839
840
  case f.format
840
841
  when :p
841
- Kernel.format(f.orig_fmt, val)
842
+ str_regexp = '/'
843
+ str_regexp << (val.options == 0 ? val.source : val.to_s) << '/'
844
+ f.orig_fmt == '%p' ? str_regexp : Kernel.format(f.orig_fmt.gsub('p', 's'), str_regexp)
842
845
  when :s
843
- str_regexp = val.inspect
844
- str_regexp = f.alt? ? "\"#{str_regexp[1..-2]}\"" : str_regexp
845
- Kernel.format(f.orig_fmt, str_regexp)
846
+ str_regexp = val.options == 0 ? val.source : val.to_s
847
+ str_regexp = puppet_quote(str_regexp) if f.alt?
848
+ f.orig_fmt == '%s' ? str_regexp : Kernel.format(f.orig_fmt, str_regexp)
846
849
  else
847
- raise FormatError.new('Regexp', f.format, 'rsp')
850
+ raise FormatError.new('Regexp', f.format, 'sp')
848
851
  end
849
852
  end
850
853