puppet 4.10.1 → 4.10.4

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
@@ -7,7 +7,7 @@ summary: 'Puppet, an automated configuration management tool'
7
7
  description: 'Puppet, an automated configuration management tool'
8
8
  version_file: 'lib/puppet/version.rb'
9
9
  # files and gem_files are space separated lists
10
- files: '[A-Z]* install.rb bin lib conf man examples ext tasks spec'
10
+ files: '[A-Z]* install.rb bin lib conf man examples ext tasks spec locales'
11
11
  # The gem specification bits only work on Puppet >= 3.0rc, NOT 2.7.x and earlier
12
12
  gem_files: '[A-Z]* install.rb bin lib conf man examples ext tasks spec locales'
13
13
  gem_test_files: 'spec/**/*'
@@ -1,6 +1,6 @@
1
1
  require 'puppet/version'
2
2
 
3
- if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("1.9.3")
3
+ if Gem::Version.new(RUBY_VERSION.dup) < 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
 
@@ -27,14 +27,46 @@ require 'puppet/external/pson/pure'
27
27
  begin
28
28
  require 'gettext-setup'
29
29
  require 'locale'
30
+
31
+ # e.g. ~/code/puppet/locales. Also when running as a gem.
32
+ local_locale_path = File.absolute_path('../locales', File.dirname(__FILE__))
33
+ # e.g. /opt/puppetlabs/puppet/share/locale
34
+ posix_system_locale_path = File.absolute_path('../../../share/locale', File.dirname(__FILE__))
35
+ # e.g. C:\Program Files\Puppet Labs\Puppet\puppet\share\locale
36
+ win32_system_locale_path = File.absolute_path('../../../../../puppet/share/locale', File.dirname(__FILE__))
37
+
38
+ if File.exist?(local_locale_path)
39
+ locale_path = local_locale_path
40
+ elsif Puppet::Util::Platform.windows? && File.exist?(win32_system_locale_path)
41
+ locale_path = win32_system_locale_path
42
+ elsif !Puppet::Util::Platform.windows? && File.exist?(posix_system_locale_path)
43
+ locale_path = posix_system_locale_path
44
+ else
45
+ # We couldn't load our locale data.
46
+ raise LoadError, "could not find locale data, skipping Gettext initialization"
47
+ end
48
+
49
+ Puppet::LOCALE_PATH = locale_path
30
50
  Puppet::GETTEXT_AVAILABLE = true
31
51
  rescue LoadError
32
52
  def _(msg)
33
53
  msg
34
54
  end
55
+
56
+ def n_(*args, &block)
57
+ # assume two string args (singular and plural English form) and the count
58
+ # to pluralize on
59
+ plural = args[2] == 1 ? args[0] : args[1]
60
+ # if a block is passed, prefer that over the string selection above
61
+ block ? block.call : plural
62
+ end
63
+
64
+ Puppet::LOCALE_PATH = nil
35
65
  Puppet::GETTEXT_AVAILABLE = false
36
66
  end
37
67
 
68
+
69
+
38
70
  #------------------------------------------------------------
39
71
  # the top-level module
40
72
  #
@@ -53,34 +85,14 @@ module Puppet
53
85
  require 'puppet/environments'
54
86
 
55
87
  class << self
56
- if Puppet::GETTEXT_AVAILABLE
57
- # e.g. ~/code/puppet/locales. Also when running as a gem.
58
- local_locale_path = File.absolute_path('../locales', File.dirname(__FILE__))
59
- # e.g. /opt/puppetlabs/puppet/share/locale
60
- posix_system_locale_path = File.absolute_path('../../../share/locale', File.dirname(__FILE__))
61
- # e.g. C:\Program Files\Puppet Labs\Puppet\puppet\share\locale
62
- win32_system_locale_path = File.absolute_path('../../../../../puppet/share/locale', File.dirname(__FILE__))
63
-
64
- if File.exist?(local_locale_path)
65
- locale_path = local_locale_path
66
- elsif File.exist?(win32_system_locale_path)
67
- locale_path = win32_system_locale_path
68
- elsif File.exist?(posix_system_locale_path)
69
- locale_path = posix_system_locale_path
88
+ if Puppet::GETTEXT_AVAILABLE && Puppet::LOCALE_PATH
89
+ if GettextSetup.method(:initialize).parameters.count == 1
90
+ # Will load translations from PO files only
91
+ GettextSetup.initialize(Puppet::LOCALE_PATH)
70
92
  else
71
- # We couldn't load our locale data.
72
- locale_path = nil
73
- end
74
-
75
- if locale_path
76
- if Gem.loaded_specs['gettext-setup'].version < Gem::Version.new('0.8')
77
- # Will load translations from PO files only
78
- GettextSetup.initialize(locale_path)
79
- else
80
- GettextSetup.initialize(locale_path, :file_format => :mo)
81
- end
82
- FastGettext.locale = GettextSetup.negotiate_locale(Locale.current.language)
93
+ GettextSetup.initialize(Puppet::LOCALE_PATH, :file_format => :mo)
83
94
  end
95
+ FastGettext.locale = GettextSetup.negotiate_locale(Locale.current.language)
84
96
  end
85
97
 
86
98
  include Puppet::Util
@@ -164,7 +176,7 @@ module Puppet
164
176
 
165
177
  # Now that settings are loaded we have the code loaded to be able to issue
166
178
  # deprecation warnings. Warn if we're on a deprecated ruby version.
167
- if Gem::Version.new(RUBY_VERSION) < Gem::Version.new(Puppet::OLDEST_RECOMMENDED_RUBY_VERSION)
179
+ if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new(Puppet::OLDEST_RECOMMENDED_RUBY_VERSION)
168
180
  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
181
  end
170
182
 
@@ -309,7 +309,7 @@ Luke Kanies
309
309
 
310
310
  COPYRIGHT
311
311
  ---------
312
- Copyright (c) 2011 Puppet Labs, LLC Licensed under the Apache 2.0 License
312
+ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
313
313
 
314
314
  HELP
315
315
  end
@@ -152,7 +152,7 @@ Luke Kanies
152
152
 
153
153
  COPYRIGHT
154
154
  ---------
155
- Copyright (c) 2011 Puppet Labs, LLC Licensed under the Apache 2.0 License
155
+ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
156
156
 
157
157
  HELP
158
158
  end
@@ -250,7 +250,7 @@ Luke Kanies
250
250
 
251
251
  COPYRIGHT
252
252
  ---------
253
- Copyright (c) 2011 Puppet Labs, LLC Licensed under the Apache 2.0 License
253
+ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
254
254
 
255
255
  HELP
256
256
  end
@@ -226,7 +226,7 @@ David Lutterkort
226
226
 
227
227
  COPYRIGHT
228
228
  ---------
229
- Copyright (c) 2011 Puppet Labs, LLC Licensed under the Apache 2.0 License
229
+ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
230
230
 
231
231
  HELP
232
232
  end
@@ -155,7 +155,7 @@ Brice Figureau
155
155
 
156
156
  COPYRIGHT
157
157
  ---------
158
- Copyright (c) 2011 Puppet Labs, LLC
158
+ Copyright (c) 2011 Puppet Inc., LLC
159
159
  Licensed under the Apache 2.0 License
160
160
  HELP
161
161
  end
@@ -57,7 +57,7 @@ puppet-doc(8) -- Generate Puppet references
57
57
  SYNOPSIS
58
58
  --------
59
59
  Generates a reference for all Puppet types. Largely meant for internal
60
- Puppet Labs use. (Deprecated)
60
+ Puppet Inc. use. (Deprecated)
61
61
 
62
62
 
63
63
  USAGE
@@ -71,7 +71,7 @@ DESCRIPTION
71
71
  This deprecated command generates a Markdown document to stdout
72
72
  describing all installed Puppet types or all allowable arguments to
73
73
  puppet executables. It is largely meant for internal use and is used to
74
- generate the reference document available on the Puppet Labs web site.
74
+ generate the reference document available on the Puppet Inc. web site.
75
75
 
76
76
  For Puppet module documentation (and all other use cases) this command
77
77
  has been superseded by the "puppet-strings"
@@ -104,7 +104,7 @@ Luke Kanies
104
104
 
105
105
  COPYRIGHT
106
106
  ---------
107
- Copyright (c) 2011 Puppet Labs, LLC Licensed under the Apache 2.0 License
107
+ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
108
108
 
109
109
  HELP
110
110
  end
@@ -146,7 +146,7 @@ Luke Kanies
146
146
 
147
147
  COPYRIGHT
148
148
  ---------
149
- Copyright (c) 2011 Puppet Labs, LLC Licensed under the Apache 2.0 License
149
+ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
150
150
 
151
151
  HELP
152
152
  end
@@ -64,12 +64,12 @@ the full list of acceptable settings.
64
64
  AUTHOR
65
65
  ------
66
66
 
67
- Puppet Labs
67
+ Puppet Inc.
68
68
 
69
69
 
70
70
  COPYRIGHT
71
71
  ---------
72
- Copyright (c) 2011 Puppet Labs, LLC Licensed under the Apache 2.0 License
72
+ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
73
73
 
74
74
  HELP
75
75
  end
@@ -230,7 +230,7 @@ EXAMPLE
230
230
 
231
231
  COPYRIGHT
232
232
  ---------
233
- Copyright (c) 2015 Puppet Labs, LLC Licensed under the Apache 2.0 License
233
+ Copyright (c) 2015 Puppet Inc., LLC Licensed under the Apache 2.0 License
234
234
 
235
235
 
236
236
  HELP
@@ -130,7 +130,7 @@ Luke Kanies
130
130
 
131
131
  COPYRIGHT
132
132
  ---------
133
- Copyright (c) 2012 Puppet Labs, LLC Licensed under the Apache 2.0 License
133
+ Copyright (c) 2012 Puppet Inc., LLC Licensed under the Apache 2.0 License
134
134
 
135
135
  HELP
136
136
  end
@@ -123,7 +123,7 @@ Luke Kanies
123
123
 
124
124
  COPYRIGHT
125
125
  ---------
126
- Copyright (c) 2011 Puppet Labs, LLC Licensed under the Apache 2.0 License
126
+ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
127
127
 
128
128
  HELP
129
129
  end
@@ -136,14 +136,14 @@ Copyright (c) 2011 Puppet Labs, LLC Licensed under the Apache 2.0 License
136
136
  resources = find_or_save_resources(type, name, params)
137
137
 
138
138
  if options[:to_yaml]
139
- text = resources.
140
- map { |resource| resource.prune_parameters(:parameters_to_include => @extra_params).to_hierayaml }.
141
- join("\n")
139
+ text = resources.map do |resource|
140
+ resource.prune_parameters(:parameters_to_include => @extra_params).to_hierayaml.force_encoding(Encoding.default_external)
141
+ end.join("\n")
142
142
  text.prepend("#{type.downcase}:\n")
143
143
  else
144
- text = resources.
145
- map { |resource| resource.prune_parameters(:parameters_to_include => @extra_params).to_manifest }.
146
- join("\n")
144
+ text = resources.map do |resource|
145
+ resource.prune_parameters(:parameters_to_include => @extra_params).to_manifest.force_encoding(Encoding.default_external)
146
+ end.join("\n")
147
147
  end
148
148
 
149
149
  options[:edit] ?
@@ -1976,7 +1976,7 @@ EOT
1976
1976
  :default => false,
1977
1977
  :type => :boolean,
1978
1978
  :desc => <<-'EOT'
1979
- Makes the parser raise errors when referencing unknown variables. (This does not affect
1979
+ Causes an evaluation error when referencing unknown variables. (This does not affect
1980
1980
  referencing variables that are explicitly set to undef).
1981
1981
  EOT
1982
1982
  }
@@ -2,11 +2,36 @@ require 'puppet/util/character_encoding'
2
2
  # Wrapper around Ruby Etc module allowing us to manage encoding in a single
3
3
  # place.
4
4
  # This represents a subset of Ruby's Etc module, only the methods required by Puppet.
5
- # Etc returns strings in variable encoding depending on
6
- # environment. For Puppet we specifically want UTF-8 as our input from the Etc
7
- # module - which is our input for many resource instance 'is' values. The
8
- # associated 'should' value will basically always be coming from Puppet in
9
- # UTF-8. Etc is defined for Windows but calls to it return nil.
5
+
6
+ # On Ruby 2.1.0 and later, Etc returns strings in variable encoding depending on
7
+ # environment. The string returned will be labeled with the environment's
8
+ # encoding (Encoding.default_external), with one exception: If the environment
9
+ # encoding is 7-bit ASCII, and any individual character bit representation is
10
+ # equal to or greater than 128 - \x80 - 0b10000000 - signifying the smallest
11
+ # 8-bit big-endian value, the returned string will be in BINARY encoding instead
12
+ # of environment encoding.
13
+ #
14
+ # Barring that exception, the returned string will be labeled as encoding
15
+ # Encoding.default_external, regardless of validity or byte-width. For example,
16
+ # ruby will label a string containing a four-byte characters such as "\u{2070E}"
17
+ # as EUC_KR even though EUC_KR is a two-byte width encoding.
18
+ #
19
+ # On Ruby 2.0.x and earlier, Etc will always return string values in BINARY,
20
+ # ignoring encoding altogether.
21
+ #
22
+ # For Puppet we specifically want UTF-8 as our input from the Etc module - which
23
+ # is our input for many resource instance 'is' values. The associated 'should'
24
+ # value will basically always be coming from Puppet in UTF-8 - and written to
25
+ # disk as UTF-8. Etc is defined for Windows but the majority calls to it return
26
+ # nil and Puppet does not use it.
27
+ #
28
+ # That being said, we have cause to retain the original, pre-override string
29
+ # values. `puppet resource user`
30
+ # (Puppet::Resource::User.indirection.search('User', {})) uses self.instances to
31
+ # query for user(s) and then iterates over the results of that query again to
32
+ # obtain state for each user. If we've overridden the original user name and not
33
+ # retained the original, we've lost the ability to query the system for it
34
+ # later. Hence the Puppet::Etc::Passwd and Puppet::Etc::Group structs.
10
35
  #
11
36
  # We only use Etc for retrieving existing property values from the system. For
12
37
  # setting property values, providers leverage system tools (i.e., `useradd`)
@@ -14,11 +39,12 @@ require 'puppet/util/character_encoding'
14
39
  # @api private
15
40
  module Puppet::Etc
16
41
  class << self
42
+
17
43
  # Etc::getgrent returns an Etc::Group struct object
18
44
  # On first call opens /etc/group and returns parse of first entry. Each subsquent call
19
45
  # returns new struct the next entry or nil if EOF. Call ::endgrent to close file.
20
46
  def getgrent
21
- convert_field_values_to_utf8!(::Etc.getgrent)
47
+ override_field_values_to_utf8(::Etc.getgrent)
22
48
  end
23
49
 
24
50
  # closes handle to /etc/group file
@@ -35,7 +61,7 @@ module Puppet::Etc
35
61
  # On first call opens /etc/passwd and returns parse of first entry. Each subsquent call
36
62
  # returns new struct for the next entry or nil if EOF. Call ::endgrent to close file.
37
63
  def getpwent
38
- convert_field_values_to_utf8!(::Etc.getpwent)
64
+ override_field_values_to_utf8(::Etc.getpwent)
39
65
  end
40
66
 
41
67
  # closes handle to /etc/passwd file
@@ -53,70 +79,80 @@ module Puppet::Etc
53
79
  # returns an Etc::Passwd struct corresponding to the entry or raises
54
80
  # ArgumentError if none
55
81
  def getpwnam(username)
56
- convert_field_values_to_utf8!(::Etc.getpwnam(username))
82
+ override_field_values_to_utf8(::Etc.getpwnam(username))
57
83
  end
58
84
 
59
85
  # Etc::getgrnam searches /etc/group file for an entry corresponding to groupname.
60
86
  # returns an Etc::Group struct corresponding to the entry or raises
61
87
  # ArgumentError if none
62
88
  def getgrnam(groupname)
63
- convert_field_values_to_utf8!(::Etc.getgrnam(groupname))
89
+ override_field_values_to_utf8(::Etc.getgrnam(groupname))
64
90
  end
65
91
 
66
92
  # Etc::getgrid searches /etc/group file for an entry corresponding to id.
67
93
  # returns an Etc::Group struct corresponding to the entry or raises
68
94
  # ArgumentError if none
69
95
  def getgrgid(id)
70
- convert_field_values_to_utf8!(::Etc.getgrgid(id))
96
+ override_field_values_to_utf8(::Etc.getgrgid(id))
71
97
  end
72
98
 
73
99
  # Etc::getpwuid searches /etc/passwd file for an entry corresponding to id.
74
100
  # returns an Etc::Passwd struct corresponding to the entry or raises
75
101
  # ArgumentError if none
76
102
  def getpwuid(id)
77
- convert_field_values_to_utf8!(::Etc.getpwuid(id))
103
+ override_field_values_to_utf8(::Etc.getpwuid(id))
78
104
  end
79
105
 
80
106
  private
81
- # Utility method for converting the String values of a struct returned by
107
+
108
+ # @api private
109
+ # Defines Puppet::Etc::Passwd struct class. Contains all of the original
110
+ # member fields of Etc::Passwd, and additional "canonical_" versions of
111
+ # these fields as well. API compatible with Etc::Passwd. Because Struct.new
112
+ # defines a new Class object, we memozie to avoid superfluous extra Class
113
+ # instantiations.
114
+ def puppet_etc_passwd_class
115
+ @password_class ||= Struct.new(*Etc::Passwd.members, *Etc::Passwd.members.map { |member| "canonical_#{member}".to_sym })
116
+ end
117
+
118
+ # @api private
119
+ # Defines Puppet::Etc::Group struct class. Contains all of the original
120
+ # member fields of Etc::Group, and additional "canonical_" versions of these
121
+ # fields as well. API compatible with Etc::Group. Because Struct.new
122
+ # defines a new Class object, we memoize to avoid superfluous extra Class
123
+ # instantiations.
124
+ def puppet_etc_group_class
125
+ @group_class ||= Struct.new(*Etc::Group.members, *Etc::Group.members.map { |member| "canonical_#{member}".to_sym })
126
+ end
127
+
128
+ # Utility method for overriding the String values of a struct returned by
82
129
  # the Etc module to UTF-8. Structs returned by the ruby Etc module contain
83
130
  # members with fields of type String, Integer, or Array of Strings, so we
84
131
  # handle these types. Otherwise ignore fields.
85
132
  #
86
- # NOTE: If a string cannot be converted to UTF-8, this leaves the original
87
- # string string intact in the Struct.
88
- #
89
- # Warning! This is a destructive method - the struct passed is modified!
90
- #
91
133
  # @api private
92
134
  # @param [Etc::Passwd or Etc::Group struct]
93
- # @return [Etc::Passwd or Etc::Group struct] the original struct with values
94
- # converted to UTF-8 if possible, or the original value intact if not
95
- def convert_field_values_to_utf8!(struct)
135
+ # @return [Puppet::Etc::Passwd or Puppet::Etc::Group struct] a new struct
136
+ # object with the original struct values overidden to UTF-8, if valid. For
137
+ # invalid values originating in UTF-8, invalid characters are replaced with
138
+ # '?'. For each member the struct also contains a corresponding
139
+ # :canonical_<member name> struct member.
140
+ def override_field_values_to_utf8(struct)
96
141
  return nil if struct.nil?
97
- struct.each_with_index do |value, index|
142
+ new_struct = struct.is_a?(Etc::Passwd) ? puppet_etc_passwd_class.new : puppet_etc_group_class.new
143
+ struct.each_pair do |member, value|
98
144
  if value.is_a?(String)
99
- converted = Puppet::Util::CharacterEncoding.convert_to_utf_8!(value)
100
- struct[index] = converted if !converted.nil?
145
+ new_struct["canonical_#{member}".to_sym] = value.dup
146
+ new_struct[member] = Puppet::Util::CharacterEncoding.scrub(Puppet::Util::CharacterEncoding.override_encoding_to_utf_8(value))
101
147
  elsif value.is_a?(Array)
102
- struct[index] = convert_array_values_to_utf8!(value)
148
+ new_struct["canonical_#{member}".to_sym] = value.inject([]) { |acc, elem| acc << elem.dup }
149
+ new_struct[member] = value.inject([]) { |acc, elem| acc << Puppet::Util::CharacterEncoding.scrub(Puppet::Util::CharacterEncoding.override_encoding_to_utf_8(elem)) }
150
+ else
151
+ new_struct["canonical_#{member}".to_sym] = value
152
+ new_struct[member] = value
103
153
  end
104
154
  end
105
- end
106
-
107
- # Helper method for ::convert_field_values_to_utf8!
108
- #
109
- # Warning! This is a destructive method - the array passed is modified!
110
- #
111
- # @api private
112
- # @param [Array] object containing String values to convert to UTF-8
113
- # @return [Array] original Array with String values converted to UTF-8 if
114
- # convertible, or original, unmodified values if not.
115
- def convert_array_values_to_utf8!(string_array)
116
- string_array.map! do |elem|
117
- converted = Puppet::Util::CharacterEncoding.convert_to_utf_8!(elem)
118
- converted.nil? ? elem : converted
119
- end
155
+ new_struct
120
156
  end
121
157
  end
122
158
  end