puppet 3.5.0.rc1 → 3.5.0.rc2

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.

@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 325fdbafac6d3a0b58e2c6ed8c297064e9b88151
4
+ data.tar.gz: d809acbac40afe5fef9f2da786f480f087e80aa3
5
+ SHA512:
6
+ metadata.gz: 22fdb5d7f73a1b55b62900873ef2c0fc53b1645ee04294f1fb26d5024a1c7948ec4d5f367088a0cac41986672f09b09b8e6aecf6c6ada2239b3333f14d5dd378
7
+ data.tar.gz: eee4ae631b6941dc5545e188211df25d8e7f21a143793eb4627bad65bff15eff854190de45e0f33798dc16d877406e88e58b96afeeddcdea5506de1e1a86fb9b
@@ -870,9 +870,10 @@ EOT
870
870
  },
871
871
  :manifest => {
872
872
  :default => "$manifestdir/site.pp",
873
- :type => :file,
873
+ :type => :file_or_directory,
874
874
  :desc => "The entry-point manifest file for puppet master or a directory of manifests
875
- to be evaluated in alphabetical order.",
875
+ to be evaluated in alphabetical order. Puppet manages this path as a directory
876
+ if it exists or if the path ends with a / or \\.",
876
877
  },
877
878
  :code => {
878
879
  :default => "",
@@ -32,7 +32,13 @@ class Puppet::Resource::Catalog::Compiler < Puppet::Indirector::Code
32
32
  end
33
33
 
34
34
  facts.add_timestamp
35
- Puppet::Node::Facts.indirection.save(facts)
35
+
36
+ options = {
37
+ :environment => request.environment,
38
+ :transaction_uuid => request.options[:transaction_uuid],
39
+ }
40
+
41
+ Puppet::Node::Facts.indirection.save(facts, nil, options)
36
42
  end
37
43
  end
38
44
 
@@ -538,6 +538,9 @@ class Puppet::Parser::Scope
538
538
  def to_hash_future(recursive)
539
539
  if recursive and has_enclosing_scope?
540
540
  target = enclosing_scope.to_hash_future(recursive)
541
+ if !(inherited = inherited_scope).nil?
542
+ target.merge!(inherited.to_hash_future(recursive))
543
+ end
541
544
  else
542
545
  target = Hash.new
543
546
  end
@@ -73,7 +73,7 @@ class Puppet::Pops::Evaluator::AccessOperator
73
73
  def access_PRegexpType(o, scope, keys)
74
74
  keys.flatten!
75
75
  unless keys.size == 1
76
- blamed = keys.size == 0 ? @semantic : @semantic.keys[2]
76
+ blamed = keys.size == 0 ? @semantic : @semantic.keys[1]
77
77
  fail(Puppet::Pops::Issues::BAD_TYPE_SLICE_ARITY, blamed, :base_type => o, :min=>1, :actual => keys.size)
78
78
  end
79
79
  assert_keys(keys, o, 1, 1, String, Regexp)
@@ -214,7 +214,7 @@ class Puppet::Pops::Evaluator::AccessOperator
214
214
  def assert_keys(keys, o, min, max, *allowed_classes)
215
215
  size = keys.size
216
216
  unless size.between?(min, max || INFINITY)
217
- fail(Puppet::Pops::Issues::BAD_TYPE_SLICE_ARITY, blamed, :base_type => o, :min=>1, :max => max, :actual => keys.size)
217
+ fail(Puppet::Pops::Issues::BAD_TYPE_SLICE_ARITY, @semantic, :base_type => o, :min=>1, :max => max, :actual => keys.size)
218
218
  end
219
219
  keys.each_with_index do |k, i|
220
220
  unless allowed_classes.any? {|clazz| k.is_a?(clazz) }
@@ -438,10 +438,12 @@ class Puppet::Pops::Evaluator::AccessOperator
438
438
  # Resource[File, 'foo']['bar'] # => Value of the 'bar' parameter in the File['foo'] resource
439
439
  #
440
440
  def access_PResourceType(o, scope, keys)
441
+ blamed = keys.size == 0 ? @semantic : @semantic.keys[0]
441
442
  keys.flatten!
442
443
  if keys.size == 0
443
- fail(Puppet::Pops::Issues::BAD_TYPE_SLICE_ARITY, o,
444
- :base_type => Puppet::Pops::Types::TypeCalculator.new().string(o), :min => 1, :actual => 0)
444
+ max = o.type_name.nil? ? 2 : 1
445
+ fail(Puppet::Pops::Issues::BAD_TYPE_SLICE_ARITY, blamed,
446
+ :base_type => Puppet::Pops::Types::TypeCalculator.new().string(o), :min => 1, :max => max, :actual => 0)
445
447
  end
446
448
  if !o.title.nil?
447
449
  # lookup resource and return one or more parameter values
@@ -500,10 +502,12 @@ class Puppet::Pops::Evaluator::AccessOperator
500
502
  end
501
503
 
502
504
  def access_PHostClassType(o, scope, keys)
505
+ blamed = keys.size == 0 ? @semantic : @semantic.keys[0]
506
+
503
507
  keys.flatten!
504
508
  if keys.size == 0
505
- fail(Puppet::Pops::Issues::BAD_TYPE_SLICE_ARITY, o,
506
- :base_type => Puppet::Pops::Types::TypeCalculator.new().string(o), :min => 1, :actual => 0)
509
+ fail(Puppet::Pops::Issues::BAD_TYPE_SLICE_ARITY, blamed,
510
+ :base_type => Puppet::Pops::Types::TypeCalculator.new().string(o), :min => 1, :max => -1, :actual => 0)
507
511
  end
508
512
  if ! o.class_name.nil?
509
513
  # lookup class resource and return one or more parameter values
@@ -531,7 +535,8 @@ class Puppet::Pops::Evaluator::AccessOperator
531
535
  result = keys.each_with_index.map do |c, i|
532
536
  ctype = Puppet::Pops::Types::PHostClassType.new()
533
537
  if c.is_a?(Puppet::Pops::Types::PResourceType) && !c.type_name.nil? && c.title.nil?
534
- c = c.type_name.downcase
538
+ # Remove leading '::' since all references are global, and 3x runtime does the wrong thing
539
+ c = c.type_name.downcase.sub(/^::/, '')
535
540
  end
536
541
  unless c.is_a?(String)
537
542
  fail(Puppet::Pops::Issues::ILLEGAL_HOSTCLASS_NAME, @semantic.keys[i], {:name => c})
@@ -539,7 +544,7 @@ class Puppet::Pops::Evaluator::AccessOperator
539
544
  if c !~ Puppet::Pops::Patterns::NAME
540
545
  fail(Issues::ILLEGAL_NAME, @semantic.keys[i], {:name=>c})
541
546
  end
542
- ctype.class_name = c
547
+ ctype.class_name = c.downcase.sub(/^::/,'')
543
548
  ctype
544
549
  end
545
550
  # returns single type as type, else an array of types
@@ -384,7 +384,7 @@ module Puppet::Pops::Issues
384
384
  base_type_label = base_type.is_a?(String) ? base_type : label.a_an_uc(base_type)
385
385
  if max == -1 || max == 1.0 / 0.0 # Infinity
386
386
  "#{base_type_label}[] accepts #{min} or more arguments. Got #{actual}"
387
- elsif max
387
+ elsif max && max != min
388
388
  "#{base_type_label}[] accepts #{min} to #{max} arguments. Got #{actual}"
389
389
  else
390
390
  "#{base_type_label}[] accepts #{min} #{label.plural_s(min, 'argument')}. Got #{actual}"
@@ -383,10 +383,8 @@ class Puppet::Pops::Types::TypeCalculator
383
383
  def instance_of_PTupleType(t, o)
384
384
  return false unless o.is_a?(Array)
385
385
  # compute the tuple's min/max size, and check if that size matches
386
- from, to = size_range(t.size_type)
387
- size_t = Types::PIntegerType.new()
388
- size_t.from = t.types.size - 1 + from
389
- size_t.to = t.types.size - 1 + to
386
+ size_t = t.size_type || Puppet::Pops::Types::TypeFactory.range(*t.size_range)
387
+
390
388
  # compute the array's size as type
391
389
  size_t2 = size_as_type(o)
392
390
  return false unless assignable?(size_t, size_t2)
@@ -915,39 +913,27 @@ class Puppet::Pops::Types::TypeCalculator
915
913
  end
916
914
  end
917
915
 
916
+ def max(a,b)
917
+ a >=b ? a : b
918
+ end
919
+
920
+ def min(a,b)
921
+ a <= b ? a : b
922
+ end
923
+
918
924
  def assignable_PTupleType(t, t2)
919
925
  return true if t == t2 || t.types.empty? && (t2.is_a?(Types::PArrayType))
920
- t_regular = t.types[0..-2]
921
- t_ranged = t.types[-1]
922
- t_from, t_to = size_range(t.size_type)
923
- t_required = t_regular.size + t_from
926
+ size_t = t.size_type || Puppet::Pops::Types::TypeFactory.range(*t.size_range)
924
927
 
925
928
  if t2.is_a?(Types::PTupleType)
926
- t2_regular = t2.types[0..-2]
927
- t2_ranged = t2.types[-1]
928
- t2_from, t2_to = size_range(t2.size_type)
929
- t2_required = t2_regular.size + t2_from
929
+ size_t2 = t2.size_type || Puppet::Pops::Types::TypeFactory.range(*t2.size_range)
930
930
 
931
- # tuples with fewer required entries can not be assigned
932
- return false if t_required > t2_required
933
- # tuples with more optionally available entries can not be assigned
934
- return false if t_regular.size + t_to < t2_regular.size + t2_to
935
-
936
- t_required.times do |index|
937
- t_entry = tuple_entry_at(t, t_from, t_to, index)
938
- t2_entry = tuple_entry_at(t2, t2_from, t2_to, index)
939
- return false if t2_entry.nil? || !assignable?(t_entry, t2_entry)
931
+ # not assignable if the number of types in t2 is outside number of types in t1
932
+ return false unless assignable?(size_t, size_t2)
933
+ max(t.types.size, t2.types.size).times do |index|
934
+ return false unless assignable?((t.types[index] || t.types[-1]), (t2.types[index] || t2.types[-1]))
940
935
  end
941
- # Handle remainder in t2's required
942
- (t2_required - t_required).times do |index|
943
- t_entry = tuple_entry_at(t, t_from, t_to, t_required + index)
944
- t2_entry = tuple_entry_at(t2, t2_from, t2_to, t_required + index)
945
- return false if t2_entry.nil? || !assignable?(t_entry, t2_entry)
946
- end
947
- # Now only a trailing optional type remains - the last type must always be compatible
948
- # irrespective of optionality and count
949
- #
950
- return assignable?(t_ranged, t2_ranged)
936
+ true
951
937
 
952
938
  elsif t2.is_a?(Types::PArrayType)
953
939
  t2_entry = t2.element_type
@@ -956,21 +942,15 @@ class Puppet::Pops::Types::TypeCalculator
956
942
  # was handled at the top of this method.
957
943
  #
958
944
  return false if t2_entry.nil?
959
-
960
- # array type may be size constrained
961
- size_t = t2.size_type || @collection_default_size_t
962
- min, max = size_t.range
963
- # Array with fewer min entries can not be assigned
964
- return false if t_required > min
965
- # Array with more optionally available entries can not be assigned
966
- return false if t_regular.size + t_to < max
967
- # each tuple type must be assignable to the element type
968
- t_required.times do |index|
969
- t_entry = tuple_entry_at(t, t_from, t_to, index)
970
- return false unless assignable?(t_entry, t2_entry)
945
+ size_t = t.size_type || Puppet::Pops::Types::TypeFactory.range(*t.size_range)
946
+ size_t2 = t2.size_type || @collection_default_size_t
947
+ return false unless assignable?(size_t, size_t2)
948
+ min(t.types.size, size_t2.range()[1]).times do |index|
949
+ return false unless assignable?((t.types[index] || t.types[-1]), t2_entry)
971
950
  end
972
- # ... and so must the last, possibly optional (ranged) type
973
- return assignable?(t_ranged, t2_entry)
951
+ true
952
+ else
953
+ false
974
954
  end
975
955
  end
976
956
 
@@ -221,7 +221,9 @@ module Puppet::Pops::Types::TypeFactory
221
221
  #
222
222
  def self.host_class(class_name = nil)
223
223
  type = Types::PHostClassType.new()
224
- type.class_name = class_name
224
+ unless class_name.nil?
225
+ type.class_name = class_name.sub(/^::/, '')
226
+ end
225
227
  type
226
228
  end
227
229
 
@@ -307,10 +307,33 @@ module Puppet::Pops::Types
307
307
  # @api public
308
308
  class PTupleType < PObjectType
309
309
  contains_many_uni 'types', PAbstractType, :lowerBound => 1
310
- # If set, describes repetition of the last type in types
310
+ # If set, describes min and max required of the given types - if max > size of
311
+ # types, the last type entry repeats
312
+ #
311
313
  contains_one_uni 'size_type', PIntegerType, :lowerBound => 0
312
314
 
313
315
  module ClassModule
316
+ # Returns the number of elements accepted [min, max] in the tuple
317
+ def size_range
318
+ types_size = types.size
319
+ size_type.nil? ? [types_size, types_size] : size_type.range
320
+ end
321
+
322
+ # Returns the number of accepted occurrences [min, max] of the last type in the tuple
323
+ # The defaults is [1,1]
324
+ #
325
+ def repeat_last_range
326
+ types_size = types.size
327
+ if size_type.nil?
328
+ return [1, 1]
329
+ end
330
+ from, to = size_type.range()
331
+ min = from - (types_size-1)
332
+ min = min <= 0 ? 0 : min
333
+ max = to - (types_size-1)
334
+ [min, max]
335
+ end
336
+
314
337
  def hash
315
338
  [self.class, size_type, Set.new(types)].hash
316
339
  end
@@ -379,7 +402,7 @@ module Puppet::Pops::Types
379
402
  # contains_one_uni 'super_type', PHostClassType
380
403
  module ClassModule
381
404
  def hash
382
- [self.class, host_class].hash
405
+ [self.class, class_name].hash
383
406
  end
384
407
  def ==(o)
385
408
  self.class == o.class && class_name == o.class_name
@@ -370,6 +370,8 @@ Puppet::Type.type(:user).provide :directoryservice do
370
370
  if value.length != 256
371
371
  raise Puppet::Error, "OS X versions > 10.7 require a Salted SHA512 PBKDF2 password hash of 256 characters. Please check your password and try again."
372
372
  end
373
+
374
+ assert_full_pbkdf2_password
373
375
  end
374
376
 
375
377
  # Methods around setting the password on OS X are the ONLY methods that
@@ -405,6 +407,8 @@ Puppet::Type.type(:user).provide :directoryservice do
405
407
  # method.
406
408
  def iterations=(value)
407
409
  if (Puppet::Util::Package.versioncmp(self.class.get_os_version, '10.7') > 0)
410
+ assert_full_pbkdf2_password
411
+
408
412
  sleep 2
409
413
  flush_dscl_cache
410
414
  users_plist = get_users_plist(@resource.name)
@@ -420,6 +424,8 @@ Puppet::Type.type(:user).provide :directoryservice do
420
424
  # method.
421
425
  def salt=(value)
422
426
  if (Puppet::Util::Package.versioncmp(self.class.get_os_version, '10.7') > 0)
427
+ assert_full_pbkdf2_password
428
+
423
429
  sleep 2
424
430
  flush_dscl_cache
425
431
  users_plist = get_users_plist(@resource.name)
@@ -473,6 +479,14 @@ Puppet::Type.type(:user).provide :directoryservice do
473
479
  ## Helper Methods ##
474
480
  ## ##
475
481
 
482
+ def assert_full_pbkdf2_password
483
+ missing = [:password, :salt, :iterations].select { |parameter| @resource[parameter].nil? }
484
+
485
+ if !missing.empty?
486
+ raise Puppet::Error, "OS X versions > 10\.7 use PBKDF2 password hashes, which requires all three of salt, iterations, and password hash. This resource is missing: #{missing.join(', ')}."
487
+ end
488
+ end
489
+
476
490
  def users_plist_dir
477
491
  '/var/db/dslocal/nodes/Default/users'
478
492
  end
@@ -13,6 +13,7 @@ class Puppet::Settings
13
13
  require 'puppet/settings/enum_setting'
14
14
  require 'puppet/settings/file_setting'
15
15
  require 'puppet/settings/directory_setting'
16
+ require 'puppet/settings/file_or_directory_setting'
16
17
  require 'puppet/settings/path_setting'
17
18
  require 'puppet/settings/boolean_setting'
18
19
  require 'puppet/settings/terminus_setting'
@@ -639,6 +640,7 @@ class Puppet::Settings
639
640
  :string => StringSetting,
640
641
  :file => FileSetting,
641
642
  :directory => DirectorySetting,
643
+ :file_or_directory => FileOrDirectorySetting,
642
644
  :path => PathSetting,
643
645
  :boolean => BooleanSetting,
644
646
  :terminus => TerminusSetting,
@@ -1214,7 +1216,7 @@ Generated on #{Time.now}.
1214
1216
  return value unless value.is_a? String
1215
1217
  value.gsub(/\$(\w+)|\$\{(\w+)\}/) do |value|
1216
1218
  varname = $2 || $1
1217
- if varname == "environment"
1219
+ if varname == "environment" && @environment
1218
1220
  @environment
1219
1221
  elsif varname == "run_mode"
1220
1222
  @mode
@@ -0,0 +1,34 @@
1
+ class Puppet::Settings::FileOrDirectorySetting < Puppet::Settings::FileSetting
2
+
3
+ def initialize(args)
4
+ super
5
+ end
6
+
7
+ def type
8
+ if Puppet::FileSystem.directory?(self.value) || @path_ends_with_slash
9
+ :directory
10
+ else
11
+ :file
12
+ end
13
+ end
14
+
15
+ # Overrides munge to be able to read the un-munged value (the FileSetting.munch removes trailing slash)
16
+ #
17
+ def munge(value)
18
+ if value.is_a?(String) && value =~ /[\\\/]$/
19
+ @path_ends_with_slash = true
20
+ end
21
+ super
22
+ end
23
+
24
+ # @api private
25
+ def open_file(filename, option = 'r', &block)
26
+ if type == :file
27
+ super
28
+ else
29
+ controlled_access do |mode|
30
+ Puppet::FileSystem.open(filename, mode, option, &block)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -189,6 +189,9 @@ module Puppet
189
189
  * Mac OS X 10.7 (Lion) uses salted SHA512 hashes. The Puppet Labs [stdlib][]
190
190
  module contains a `str2saltedsha512` function which can generate password
191
191
  hashes for Lion.
192
+ * Mac OS X 10.8 and higher use salted SHA512 PBKDF2 hashes. When
193
+ managing passwords on these systems the salt and iterations properties
194
+ need to be specified as well as the password.
192
195
  * Windows passwords can only be managed in cleartext, as there is no Windows API
193
196
  for setting the password hash.
194
197
 
@@ -544,13 +547,13 @@ module Puppet
544
547
 
545
548
  newproperty(:salt, :required_features => :manages_password_salt) do
546
549
  desc "This is the 32 byte salt used to generate the PBKDF2 password used in
547
- OS X"
550
+ OS X. This field is required for managing passwords on OS X >= 10.8."
548
551
  end
549
552
 
550
553
  newproperty(:iterations, :required_features => :manages_password_salt) do
551
554
  desc "This is the number of iterations of a chained computation of the
552
555
  password hash (http://en.wikipedia.org/wiki/PBKDF2). This parameter
553
- is used in OS X"
556
+ is used in OS X. This field is required for managing passwords on OS X >= 10.8."
554
557
 
555
558
  munge do |value|
556
559
  if value.is_a?(String) and value =~/^[-0-9]+$/
@@ -7,7 +7,7 @@
7
7
 
8
8
 
9
9
  module Puppet
10
- PUPPETVERSION = '3.5.0-rc1'
10
+ PUPPETVERSION = '3.5.0-rc2'
11
11
 
12
12
  ##
13
13
  # version is a public API method intended to always provide a fast and
@@ -1,5 +1,5 @@
1
- #! /usr/bin/env ruby
2
1
  require 'spec_helper'
2
+ require 'matchers/include'
3
3
 
4
4
  require 'puppet/indirector/file_content/file'
5
5
 
@@ -34,34 +34,31 @@ end
34
34
 
35
35
  describe Puppet::Indirector::DirectFileServer, " when interacting with FileServing::Fileset and the model" do
36
36
  include PuppetSpec::Files
37
+ include Matchers::Include
37
38
 
38
- let(:path) { tmpdir('direct_file_server_testing') }
39
+ matcher :file_with_content do |name, content|
40
+ match do |actual|
41
+ actual.full_path == name && actual.content == content
42
+ end
43
+ end
39
44
 
40
- before do
41
- @terminus = Puppet::Indirector::FileContent::File.new
45
+ matcher :directory_named do |name|
46
+ match do |actual|
47
+ actual.full_path == name
48
+ end
49
+ end
42
50
 
51
+ it "should return an instance for every file in the fileset" do
52
+ path = tmpdir('direct_file_server_testing')
43
53
  File.open(File.join(path, "one"), "w") { |f| f.print "one content" }
44
54
  File.open(File.join(path, "two"), "w") { |f| f.print "two content" }
45
55
 
46
- @request = @terminus.indirection.request(:search, "file:///#{path}", nil, :recurse => true)
47
- end
48
-
49
- it "should return an instance for every file in the fileset" do
50
- result = @terminus.search(@request)
51
- result.should be_instance_of(Array)
52
- result.length.should == 3
53
- result.each { |r| r.should be_instance_of(Puppet::FileServing::Content) }
54
- end
56
+ terminus = Puppet::Indirector::FileContent::File.new
57
+ request = terminus.indirection.request(:search, "file:///#{path}", nil, :recurse => true)
55
58
 
56
- it "should return instances capable of returning their content" do
57
- @terminus.search(@request).each do |instance|
58
- case instance.full_path
59
- when /one/; instance.content.should == "one content"
60
- when /two/; instance.content.should == "two content"
61
- when path
62
- else
63
- raise "No valid key for #{instance.path.inspect}"
64
- end
65
- end
59
+ expect(terminus.search(request)).to include_in_any_order(
60
+ file_with_content(File.join(path, "one"), "one content"),
61
+ file_with_content(File.join(path, "two"), "two content"),
62
+ directory_named(path))
66
63
  end
67
64
  end