puppet 3.7.3 → 3.7.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 (57) hide show
  1. data/Gemfile +4 -0
  2. data/ext/build_defaults.yaml +2 -2
  3. data/ext/project_data.yaml +2 -2
  4. data/lib/puppet.rb +1 -1
  5. data/lib/puppet/configurer.rb +7 -4
  6. data/lib/puppet/environments.rb +68 -51
  7. data/lib/puppet/functions/scanf.rb +46 -0
  8. data/lib/puppet/network/http/webrick/rest.rb +3 -0
  9. data/lib/puppet/parser/ast/pops_bridge.rb +2 -1
  10. data/lib/puppet/parser/compiler.rb +11 -3
  11. data/lib/puppet/parser/functions/realize.rb +7 -2
  12. data/lib/puppet/parser/functions/scanf.rb +35 -0
  13. data/lib/puppet/parser/relationship.rb +21 -6
  14. data/lib/puppet/parser/resource.rb +11 -4
  15. data/lib/puppet/pops.rb +7 -0
  16. data/lib/puppet/pops/evaluator/access_operator.rb +1 -6
  17. data/lib/puppet/pops/evaluator/collector_transformer.rb +219 -0
  18. data/lib/puppet/pops/evaluator/collectors/abstract_collector.rb +86 -0
  19. data/lib/puppet/pops/evaluator/collectors/catalog_collector.rb +25 -0
  20. data/lib/puppet/pops/evaluator/collectors/exported_collector.rb +66 -0
  21. data/lib/puppet/pops/evaluator/collectors/fixed_set_collector.rb +37 -0
  22. data/lib/puppet/pops/evaluator/compare_operator.rb +8 -28
  23. data/lib/puppet/pops/evaluator/evaluator_impl.rb +4 -18
  24. data/lib/puppet/pops/evaluator/relationship_operator.rb +4 -0
  25. data/lib/puppet/pops/evaluator/runtime3_support.rb +2 -2
  26. data/lib/puppet/pops/parser/egrammar.ra +3 -3
  27. data/lib/puppet/pops/parser/eparser.rb +3 -3
  28. data/lib/puppet/pops/parser/evaluating_parser.rb +4 -0
  29. data/lib/puppet/pops/types/type_calculator.rb +19 -8
  30. data/lib/puppet/pops/types/type_parser.rb +1 -4
  31. data/lib/puppet/provider/service/redhat.rb +6 -3
  32. data/lib/puppet/resource/catalog.rb +12 -1
  33. data/lib/puppet/settings/environment_conf.rb +7 -8
  34. data/lib/puppet/type/cron.rb +5 -1
  35. data/lib/puppet/type/file/content.rb +1 -1
  36. data/lib/puppet/util/tagging.rb +21 -2
  37. data/lib/puppet/version.rb +1 -1
  38. data/spec/integration/indirector/catalog/compiler_spec.rb +11 -0
  39. data/spec/integration/parser/collector_spec.rb +41 -0
  40. data/spec/integration/parser/compiler_spec.rb +16 -0
  41. data/spec/integration/parser/future_compiler_spec.rb +1 -1
  42. data/spec/unit/environments_spec.rb +238 -118
  43. data/spec/unit/functions/scanf_spec.rb +36 -0
  44. data/spec/unit/network/http/rack/rest_spec.rb +11 -8
  45. data/spec/unit/network/http/webrick/rest_spec.rb +19 -0
  46. data/spec/unit/parser/compiler_spec.rb +0 -27
  47. data/spec/unit/pops/evaluator/access_ops_spec.rb +9 -9
  48. data/spec/unit/pops/evaluator/comparison_ops_spec.rb +14 -8
  49. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +20 -8
  50. data/spec/unit/pops/parser/parse_basic_expressions_spec.rb +10 -0
  51. data/spec/unit/pops/parser/parse_heredoc_spec.rb +30 -0
  52. data/spec/unit/pops/types/type_calculator_spec.rb +18 -0
  53. data/spec/unit/pops/types/type_parser_spec.rb +2 -2
  54. data/spec/unit/provider/service/redhat_spec.rb +2 -1
  55. data/spec/unit/type/cron_spec.rb +24 -24
  56. data/spec/unit/util/tagging_spec.rb +7 -0
  57. metadata +11 -2
data/Gemfile CHANGED
@@ -60,6 +60,10 @@ end
60
60
  group(:extra) do
61
61
  gem "rack", "~> 1.4", :require => false
62
62
  gem "activerecord", '~> 3.2', :require => false
63
+ # this pin for i18n should *not* be in the puppet-4+ branches
64
+ # it's solely here because activerecord pulls in i18n and i18n
65
+ # was recently updated to require 1.9.3 which breaks 1.8.7 specs
66
+ gem "i18n", '~> 0.6.11', :require => false
63
67
  gem "couchrest", '~> 1.0', :require => false
64
68
  gem "net-ssh", '~> 2.1', :require => false
65
69
  gem "puppetlabs_spec_helper", :require => false
@@ -26,8 +26,8 @@ build_msi:
26
26
  repo: 'git://github.com/puppetlabs/hiera.git'
27
27
  sys:
28
28
  ref:
29
- x86: 'cbe94f4cafb0f78d587e8addcf723bc671af7cca'
30
- x64: '417378f607340d211fbfef89a96e6639bef1bfb1'
29
+ x86: '57068e7b7c87288c51ff39d96c80cfb509a42091'
30
+ x64: '531319f5c121e98990772e018eb9781bf7dc6316'
31
31
  repo: 'git://github.com/puppetlabs/puppet-win32-ruby.git'
32
32
  apt_host: 'apt.puppetlabs.com'
33
33
  apt_repo_url: 'http://apt.puppetlabs.com'
@@ -28,7 +28,7 @@ gem_platform_dependencies:
28
28
  x86-mingw32:
29
29
  gem_runtime_dependencies:
30
30
  # Pinning versions that require native extensions
31
- ffi: '1.9.3'
31
+ ffi: '~> 1.9.5'
32
32
  win32-dir: '~> 0.4.9'
33
33
  win32-eventlog: '~> 0.6.1'
34
34
  win32-process: '~> 0.7.4'
@@ -38,7 +38,7 @@ gem_platform_dependencies:
38
38
  minitar: '~> 0.5.4'
39
39
  x64-mingw32:
40
40
  gem_runtime_dependencies:
41
- ffi: '1.9.3'
41
+ ffi: '~> 1.9.5'
42
42
  win32-dir: '~> 0.4.9'
43
43
  win32-eventlog: '~> 0.6.1'
44
44
  win32-process: '~> 0.7.4'
@@ -197,7 +197,7 @@ module Puppet
197
197
  end
198
198
 
199
199
  {
200
- :environments => Puppet::Environments::Cached.new(*loaders),
200
+ :environments => Puppet::Environments::Cached.new(Puppet::Environments::Combined.new(*loaders)),
201
201
  :http_pool => proc {
202
202
  require 'puppet/network/http'
203
203
  Puppet::Network::HTTP::NoCachePool.new
@@ -87,14 +87,16 @@ class Puppet::Configurer
87
87
  download_plugins(remote_environment_for_plugins)
88
88
  end
89
89
 
90
+ facts_hash = {}
90
91
  if Puppet::Resource::Catalog.indirection.terminus_class == :rest
91
92
  # This is a bit complicated. We need the serialized and escaped facts,
92
93
  # and we need to know which format they're encoded in. Thus, we
93
94
  # get a hash with both of these pieces of information.
94
95
  #
95
96
  # facts_for_uploading may set Puppet[:node_name_value] as a side effect
96
- return facts_for_uploading
97
+ facts_hash = facts_for_uploading
97
98
  end
99
+ facts_hash
98
100
  end
99
101
 
100
102
  def prepare_and_retrieve_catalog(options, query_options)
@@ -195,9 +197,6 @@ class Puppet::Configurer
195
197
  Puppet.push_context({:current_environment => local_node_environment}, "Local node environment for configurer transaction")
196
198
 
197
199
  query_options = get_facts(options) unless query_options
198
-
199
- # get_facts returns nil during puppet apply
200
- query_options ||= {}
201
200
  query_options[:transaction_uuid] = @transaction_uuid
202
201
 
203
202
  unless catalog = prepare_and_retrieve_catalog(options, query_options)
@@ -216,6 +215,10 @@ class Puppet::Configurer
216
215
  Puppet.warning "Local environment: \"#{@environment}\" doesn't match server specified environment \"#{catalog.environment}\", restarting agent run with environment \"#{catalog.environment}\""
217
216
  @environment = catalog.environment
218
217
  report.environment = @environment
218
+
219
+ query_options = get_facts(options)
220
+ query_options[:transaction_uuid] = @transaction_uuid
221
+
219
222
  return nil unless catalog = prepare_and_retrieve_catalog(options, query_options)
220
223
  tries += 1
221
224
  end
@@ -25,6 +25,21 @@ module Puppet::Environments
25
25
  end
26
26
  end
27
27
 
28
+ # Provide any common methods that loaders should have. It requires that any
29
+ # classes that include this module implement get
30
+ # @api private
31
+ module EnvironmentLoader
32
+ # @!macro loader_get_or_fail
33
+ def get!(name)
34
+ environment = get(name)
35
+ if environment
36
+ environment
37
+ else
38
+ raise EnvironmentNotFound, name
39
+ end
40
+ end
41
+ end
42
+
28
43
  # @!macro [new] loader_search_paths
29
44
  # A list of indicators of where the loader is getting its environments from.
30
45
  # @return [Array<String>] The URIs of the load locations
@@ -62,6 +77,7 @@ module Puppet::Environments
62
77
  # @api private
63
78
  class Static
64
79
  include EnvironmentCreator
80
+ include EnvironmentLoader
65
81
 
66
82
  def initialize(*environments)
67
83
  @environments = environments
@@ -84,14 +100,6 @@ module Puppet::Environments
84
100
  end
85
101
  end
86
102
 
87
- # @!macro loader_get_or_fail
88
- def get!(name)
89
- if !environment = get(name)
90
- raise EnvironmentNotFound, name
91
- end
92
- environment
93
- end
94
-
95
103
  # Returns a basic environment configuration object tied to the environment's
96
104
  # implementation values. Will not interpolate.
97
105
  #
@@ -186,6 +194,8 @@ module Puppet::Environments
186
194
  #
187
195
  # @api private
188
196
  class Directories
197
+ include EnvironmentLoader
198
+
189
199
  def initialize(environment_dir, global_module_path)
190
200
  @environment_dir = environment_dir
191
201
  @global_module_path = global_module_path
@@ -212,51 +222,49 @@ module Puppet::Environments
212
222
  def list
213
223
  valid_directories.collect do |envdir|
214
224
  name = Puppet::FileSystem.basename_string(envdir).intern
215
-
216
- setting_values = Puppet.settings.values(name, Puppet.settings.preferred_run_mode)
217
- env = Puppet::Node::Environment.create(
218
- name,
219
- Puppet::Node::Environment.split_path(setting_values.interpolate(:modulepath)),
220
- setting_values.interpolate(:manifest),
221
- setting_values.interpolate(:config_version)
222
- )
223
- env.watching = false
224
- env
225
+ create_environment(name)
225
226
  end
226
227
  end
227
228
 
228
229
  # @!macro loader_get
229
230
  def get(name)
230
- list.find { |env| env.name == name.intern }
231
- end
232
-
233
- # @!macro loader_get_or_fail
234
- def get!(name)
235
- if !environment = get(name)
236
- raise EnvironmentNotFound, name
231
+ if valid_directory?(File.join(@environment_dir, name.to_s))
232
+ create_environment(name)
237
233
  end
238
- environment
239
234
  end
240
235
 
241
236
  # @!macro loader_get_conf
242
237
  def get_conf(name)
243
- valid_directories.each do |envdir|
244
- envname = Puppet::FileSystem.basename_string(envdir)
245
- if envname == name.to_s
246
- return Puppet::Settings::EnvironmentConf.load_from(envdir, @global_module_path)
247
- end
238
+ envdir = File.join(@environment_dir, name.to_s)
239
+ if valid_directory?(envdir)
240
+ return Puppet::Settings::EnvironmentConf.load_from(envdir, @global_module_path)
248
241
  end
249
242
  nil
250
243
  end
251
244
 
252
245
  private
253
246
 
247
+ def create_environment(name, setting_values = nil)
248
+ env_symbol = name.intern
249
+ setting_values = Puppet.settings.values(env_symbol, Puppet.settings.preferred_run_mode)
250
+ Puppet::Node::Environment.create(
251
+ env_symbol,
252
+ Puppet::Node::Environment.split_path(setting_values.interpolate(:modulepath)),
253
+ setting_values.interpolate(:manifest),
254
+ setting_values.interpolate(:config_version)
255
+ )
256
+ end
257
+
258
+ def valid_directory?(envdir)
259
+ name = Puppet::FileSystem.basename_string(envdir)
260
+ Puppet::FileSystem.directory?(envdir) &&
261
+ Puppet::Node::Environment.valid_name?(name)
262
+ end
263
+
254
264
  def valid_directories
255
265
  if Puppet::FileSystem.directory?(@environment_dir)
256
266
  Puppet::FileSystem.children(@environment_dir).select do |child|
257
- name = Puppet::FileSystem.basename_string(child)
258
- Puppet::FileSystem.directory?(child) &&
259
- Puppet::Node::Environment.valid_name?(name)
267
+ valid_directory?(child)
260
268
  end
261
269
  else
262
270
  []
@@ -267,6 +275,8 @@ module Puppet::Environments
267
275
  # Combine together multiple loaders to act as one.
268
276
  # @api private
269
277
  class Combined
278
+ include EnvironmentLoader
279
+
270
280
  def initialize(*loaders)
271
281
  @loaders = loaders
272
282
  end
@@ -291,16 +301,6 @@ module Puppet::Environments
291
301
  nil
292
302
  end
293
303
 
294
- # @!macro loader_get_or_fail
295
- def get!(name)
296
- @loaders.each do |loader|
297
- if env = loader.get(name)
298
- return env
299
- end
300
- end
301
- raise EnvironmentNotFound, name
302
- end
303
-
304
304
  # @!macro loader_get_conf
305
305
  def get_conf(name)
306
306
  @loaders.each do |loader|
@@ -313,7 +313,9 @@ module Puppet::Environments
313
313
 
314
314
  end
315
315
 
316
- class Cached < Combined
316
+ class Cached
317
+ include EnvironmentLoader
318
+
317
319
  INFINITY = 1.0 / 0.0
318
320
 
319
321
  class DefaultCacheExpirationService
@@ -336,17 +338,28 @@ module Puppet::Environments
336
338
  @cache_expiration_service || DefaultCacheExpirationService.new
337
339
  end
338
340
 
339
- def initialize(*loaders)
340
- super
341
+ def initialize(loader)
342
+ @loader = loader
341
343
  @cache = {}
342
344
  @cache_expiration_service = Puppet::Environments::Cached.cache_expiration_service
343
345
  end
344
346
 
347
+ # @!macro loader_list
348
+ def list
349
+ @loader.list
350
+ end
351
+
352
+ # @!macro loader_search_paths
353
+ def search_paths
354
+ @loader.search_paths
355
+ end
356
+
357
+ # @!macro loader_get
345
358
  def get(name)
346
359
  evict_if_expired(name)
347
360
  if result = @cache[name]
348
361
  return result.value
349
- elsif (result = super(name))
362
+ elsif (result = @loader.get(name))
350
363
  @cache[name] = entry(result)
351
364
  result
352
365
  end
@@ -364,13 +377,17 @@ module Puppet::Environments
364
377
  @cache = {}
365
378
  end
366
379
 
367
- # This implementation evicts the cache, and always gets the current configuration of the environment
368
- # TODO: While this is wasteful since it needs to go on a search for the conf, it is too disruptive to optimize
380
+ # This implementation evicts the cache, and always gets the current
381
+ # configuration of the environment
382
+ #
383
+ # TODO: While this is wasteful since it
384
+ # needs to go on a search for the conf, it is too disruptive to optimize
369
385
  # this.
370
386
  #
387
+ # @!macro loader_get_conf
371
388
  def get_conf(name)
372
389
  evict_if_expired(name)
373
- super name
390
+ @loader.get_conf(name)
374
391
  end
375
392
 
376
393
  # Creates a suitable cache entry given the time to live for one environment
@@ -0,0 +1,46 @@
1
+ # Scans a string and returns an array of one or more converted values as directed by a given format string.args
2
+ # See the documenation of Ruby's String::scanf method for details about the supported formats (which
3
+ # are similar but not identical to the formats used in Puppet's `sprintf` function.
4
+ #
5
+ # This function takes two mandatory arguments: the first is the String to convert, and the second
6
+ # the format String. A parameterized block may optionally be given, which is called with the result
7
+ # that is produced by scanf if no block is present, the result of the block is then returned by
8
+ # the function.
9
+ #
10
+ # The result of the scan is an Array, with each sucessfully scanned and transformed value.args The scanning
11
+ # stops if a scan is unsuccesful and the scanned result up to that point is returned. If there was no
12
+ # succesful scan at all, the result is an empty Array. The optional code block is typically used to
13
+ # assert that the scan was succesful, and either produce the same input, or perform unwrapping of
14
+ # the result
15
+ #
16
+ # @example scanning an integer in string form (result is an array with
17
+ # integer, or empty if unsuccessful)
18
+ # "42".scanf("%i")
19
+ #
20
+ # @example scanning and processing resulting array to assert result and unwrap
21
+ #
22
+ # "42".scanf("%i") |$x| {
23
+ # unless $x[0] =~ Integer {
24
+ # fail "Expected a well formed integer value, got '$x[0]'"
25
+ # }
26
+ # $x[0]
27
+ # }
28
+ #
29
+ # @since 3.7.4
30
+ Puppet::Functions.create_function(:scanf) do
31
+ require 'scanf'
32
+
33
+ dispatch :scanf do
34
+ param 'String', 'data'
35
+ param 'String', 'format'
36
+ optional_block_param
37
+ end
38
+
39
+ def scanf(data, format, block=nil)
40
+ result = data.scanf(format)
41
+ if !block.nil?
42
+ result = block.call({}, result)
43
+ end
44
+ result
45
+ end
46
+ end
@@ -79,6 +79,9 @@ class Puppet::Network::HTTP::WEBrickREST < WEBrick::HTTPServlet::AbstractServlet
79
79
  response.body = result
80
80
  response["content-length"] = result.stat.size if result.is_a?(File)
81
81
  end
82
+ if RUBY_VERSION[0,3] == "1.8"
83
+ response["connection"] = 'close'
84
+ end
82
85
  end
83
86
 
84
87
  # Retrieve node/cert/ip information from the request object.
@@ -24,7 +24,8 @@ class Puppet::Parser::AST::PopsBridge
24
24
  end
25
25
 
26
26
  def evaluate(scope)
27
- @@evaluator.evaluate(scope, @value)
27
+ object = @@evaluator.evaluate(scope, @value)
28
+ @@evaluator.convert_to_3x(object, scope)
28
29
  end
29
30
 
30
31
  # Adapts to 3x where top level constructs needs to have each to iterate over children. Short circuit this
@@ -31,7 +31,7 @@ class Puppet::Parser::Compiler
31
31
  raise(Puppet::Error, errmsg.join(' '))
32
32
  end
33
33
 
34
- new(node).compile.to_resource
34
+ new(node).compile {|resulting_catalog| resulting_catalog.to_resource }
35
35
  rescue => detail
36
36
  message = "#{detail} on node #{node.name}"
37
37
  Puppet.log_exception(detail, message)
@@ -140,7 +140,11 @@ class Puppet::Parser::Compiler
140
140
 
141
141
  fail_on_unevaluated
142
142
 
143
- @catalog
143
+ if block_given?
144
+ yield @catalog
145
+ else
146
+ @catalog
147
+ end
144
148
  end
145
149
  end
146
150
 
@@ -443,7 +447,11 @@ class Puppet::Parser::Compiler
443
447
  # look for resources, because we want to consider those to be
444
448
  # parse errors.
445
449
  def fail_on_unevaluated_resource_collections
446
- remaining = @collections.collect(&:resources).flatten.compact
450
+ if Puppet[:parser] == 'future'
451
+ remaining = @collections.collect(&:unresolved_resources).flatten.compact
452
+ else
453
+ remaining = @collections.collect(&:resources).flatten.compact
454
+ end
447
455
 
448
456
  if !remaining.empty?
449
457
  raise Puppet::ParseError, "Failed to realize virtual resources #{remaining.join(', ')}"
@@ -6,9 +6,14 @@ Puppet::Parser::Functions::newfunction(:realize, :arity => -2, :doc => "Make a v
6
6
  bother with a full collection. It is slightly faster than a collection,
7
7
  and, of course, is a bit shorter. You must pass the object using a
8
8
  reference; e.g.: `realize User[luke]`." ) do |vals|
9
- coll = Puppet::Parser::Collector.new(self, :nomatter, nil, nil, :virtual)
9
+
10
10
  vals = [vals] unless vals.is_a?(Array)
11
- coll.resources = vals.flatten
11
+ if Puppet[:parser] == 'future'
12
+ coll = Puppet::Pops::Evaluator::Collectors::FixedSetCollector.new(self, vals.flatten)
13
+ else
14
+ coll = Puppet::Parser::Collector.new(self, :nomatter, nil, nil, :virtual)
15
+ coll.resources = vals.flatten
16
+ end
12
17
 
13
18
  compiler.add_collection(coll)
14
19
  end
@@ -0,0 +1,35 @@
1
+ Puppet::Parser::Functions::newfunction(
2
+ :scanf,
3
+ :type => :rvalue,
4
+ :arity => 2,
5
+ :doc => <<-DOC
6
+ Scans a string and returns an array of one or more converted values as directed by a given format string.args
7
+ See the documenation of Ruby's String::scanf method for details about the supported formats (which
8
+ are similar but not identical to the formats used in Puppet's `sprintf` function.
9
+
10
+ This function takes two mandatory arguments: the first is the String to convert, and the second
11
+ the format String. A parameterized block may optionally be given, which is called with the result
12
+ that is produced by scanf if no block is present, the result of the block is then returned by
13
+ the function.
14
+
15
+ The result of the scan is an Array, with each sucessfully scanned and transformed value.args The scanning
16
+ stops if a scan is unsuccesful and the scanned result up to that point is returned. If there was no
17
+ succesful scan at all, the result is an empty Array. The optional code block is typically used to
18
+ assert that the scan was succesful, and either produce the same input, or perform unwrapping of
19
+ the result
20
+
21
+
22
+ "42".scanf("%i")
23
+ "42".scanf("%i") |$x| {
24
+ unless $x[0] =~ Integer {
25
+ fail "Expected a well formed integer value, got '$x[0]'"
26
+ }
27
+ $x[0]
28
+ }
29
+
30
+ - since 3.7.4
31
+ - note requires `parser = future`
32
+ DOC
33
+ ) do |args|
34
+ function_fail(["scanf() is only available when parser/evaluator future is in effect"])
35
+ end