puppet 0.25.4 → 0.25.5

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 (169) hide show
  1. data/CHANGELOG +679 -23
  2. data/LICENSE +2 -2
  3. data/README +2 -2
  4. data/README.queueing +1 -1
  5. data/README.rst +2 -2
  6. data/Rakefile +4 -2
  7. data/bin/filebucket +2 -2
  8. data/bin/pi +1 -1
  9. data/bin/puppet +2 -2
  10. data/bin/puppetca +2 -2
  11. data/bin/puppetd +5 -4
  12. data/bin/puppetdoc +4 -4
  13. data/bin/puppetmasterd +2 -2
  14. data/bin/puppetqd +2 -2
  15. data/bin/puppetrun +2 -2
  16. data/bin/ralsh +2 -2
  17. data/conf/epm.list +2 -2
  18. data/conf/gentoo/puppet/puppet.conf +0 -4
  19. data/conf/osx/PackageInfo.plist +1 -1
  20. data/conf/redhat/logrotate +1 -0
  21. data/conf/redhat/puppet.conf +0 -4
  22. data/conf/redhat/puppet.spec +16 -10
  23. data/conf/solaris/pkginfo +2 -2
  24. data/conf/solaris/smf/puppetd.xml +3 -3
  25. data/conf/solaris/smf/puppetmasterd.xml +3 -3
  26. data/conf/solaris/smf/svc-puppetd +1 -1
  27. data/conf/solaris/smf/svc-puppetmasterd +1 -1
  28. data/conf/suse/puppet.spec +16 -14
  29. data/conf/suse/puppet.suse.patch +16 -0
  30. data/examples/etc/puppet/fileserver.conf +5 -5
  31. data/examples/modules/sample-module/README.txt +3 -3
  32. data/examples/modules/sample-module/lib/puppet/parser/functions/hostname_to_dn.rb +1 -1
  33. data/ext/extlookup.rb +1 -1
  34. data/ext/nagios/check_puppet.rb +1 -1
  35. data/ext/nagios/naggen +2 -2
  36. data/ext/puppet-test +2 -2
  37. data/ext/puppetlast +1 -1
  38. data/ext/puppetstoredconfigclean.rb +1 -1
  39. data/ext/regexp_nodes/regexp_nodes.rb +4 -4
  40. data/ext/vim/syntax/puppet.vim +5 -3
  41. data/install.rb +11 -9
  42. data/lib/puppet.rb +1 -1
  43. data/lib/puppet/application/puppetd.rb +5 -4
  44. data/lib/puppet/configurer.rb +38 -31
  45. data/lib/puppet/defaults.rb +18 -13
  46. data/lib/puppet/file_serving/fileset.rb +2 -2
  47. data/lib/puppet/file_serving/terminus_helper.rb +1 -0
  48. data/lib/puppet/indirector/indirection.rb +20 -13
  49. data/lib/puppet/network/authstore.rb +3 -3
  50. data/lib/puppet/network/format_handler.rb +1 -1
  51. data/lib/puppet/network/handler/fileserver.rb +2 -2
  52. data/lib/puppet/network/handler/master.rb +1 -1
  53. data/lib/puppet/network/http_pool.rb +0 -2
  54. data/lib/puppet/network/http_server/webrick.rb +1 -1
  55. data/lib/puppet/parser/ast/casestatement.rb +4 -4
  56. data/lib/puppet/parser/ast/ifstatement.rb +2 -1
  57. data/lib/puppet/parser/ast/leaf.rb +1 -0
  58. data/lib/puppet/parser/ast/selector.rb +2 -3
  59. data/lib/puppet/parser/functions/generate.rb +3 -5
  60. data/lib/puppet/parser/functions/require.rb +8 -1
  61. data/lib/puppet/parser/functions/template.rb +1 -1
  62. data/lib/puppet/parser/lexer.rb +1 -7
  63. data/lib/puppet/parser/resource.rb +10 -4
  64. data/lib/puppet/parser/scope.rb +61 -9
  65. data/lib/puppet/provider/augeas/augeas.rb +23 -7
  66. data/lib/puppet/provider/macauthorization/macauthorization.rb +1 -1
  67. data/lib/puppet/provider/maillist/mailman.rb +2 -2
  68. data/lib/puppet/provider/package/portage.rb +2 -2
  69. data/lib/puppet/provider/service/debian.rb +2 -2
  70. data/lib/puppet/provider/service/redhat.rb +1 -1
  71. data/lib/puppet/provider/service/smf.rb +4 -1
  72. data/lib/puppet/provider/ssh_authorized_key/parsed.rb +9 -29
  73. data/lib/puppet/provider/user/user_role_add.rb +1 -1
  74. data/lib/puppet/reference/configuration.rb +1 -1
  75. data/lib/puppet/reference/providers.rb +1 -1
  76. data/lib/puppet/reports/tagmail.rb +1 -0
  77. data/lib/puppet/resource/catalog.rb +1 -8
  78. data/lib/puppet/simple_graph.rb +37 -12
  79. data/lib/puppet/ssl/certificate.rb +2 -3
  80. data/lib/puppet/ssl/certificate_authority.rb +1 -1
  81. data/lib/puppet/ssl/host.rb +19 -12
  82. data/lib/puppet/sslcertificates/ca.rb +5 -6
  83. data/lib/puppet/transaction.rb +11 -15
  84. data/lib/puppet/type/augeas.rb +2 -1
  85. data/lib/puppet/type/exec.rb +1 -1
  86. data/lib/puppet/type/file.rb +9 -2
  87. data/lib/puppet/type/file/checksum.rb +2 -1
  88. data/lib/puppet/type/file/source.rb +4 -4
  89. data/lib/puppet/type/maillist.rb +10 -0
  90. data/lib/puppet/type/mount.rb +5 -3
  91. data/lib/puppet/type/tidy.rb +36 -30
  92. data/lib/puppet/util/autoload.rb +2 -2
  93. data/lib/puppet/util/checksums.rb +5 -0
  94. data/lib/puppet/util/monkey_patches.rb +38 -0
  95. data/lib/puppet/util/nagios_maker.rb +1 -1
  96. data/lib/puppet/util/settings.rb +14 -4
  97. data/lib/puppet/util/suidmanager.rb +26 -2
  98. data/lib/puppet/util/zaml.rb +318 -0
  99. data/man/{man8/puppet.conf.8 → man5/puppet.conf.5} +594 -899
  100. data/man/man8/filebucket.8 +31 -45
  101. data/man/man8/pi.8 +16 -22
  102. data/man/man8/puppet.8 +26 -36
  103. data/man/man8/puppetca.8 +38 -51
  104. data/man/man8/puppetd.8 +48 -64
  105. data/man/man8/puppetdoc.8 +37 -48
  106. data/man/man8/puppetmasterd.8 +24 -32
  107. data/man/man8/puppetqd.8 +22 -27
  108. data/man/man8/puppetrun.8 +46 -58
  109. data/man/man8/ralsh.8 +43 -48
  110. data/spec/integration/bin/puppetmasterd.rb +20 -9
  111. data/spec/integration/defaults.rb +4 -0
  112. data/spec/integration/indirector/certificate/rest.rb +0 -1
  113. data/spec/integration/indirector/certificate_request/rest.rb +0 -1
  114. data/spec/integration/indirector/certificate_revocation_list/rest.rb +0 -1
  115. data/spec/integration/indirector/report/rest.rb +0 -1
  116. data/spec/integration/indirector/rest.rb +0 -1
  117. data/spec/integration/parser/functions/require.rb +18 -1
  118. data/spec/unit/application/filebucket.rb +2 -2
  119. data/spec/unit/application/puppetd.rb +4 -5
  120. data/spec/unit/configurer.rb +46 -8
  121. data/spec/unit/file_serving/fileset.rb +6 -0
  122. data/spec/unit/file_serving/terminus_helper.rb +10 -0
  123. data/spec/unit/indirector/indirection.rb +17 -28
  124. data/spec/unit/network/format_handler.rb +3 -2
  125. data/spec/unit/network/http_pool.rb +9 -17
  126. data/spec/unit/parser/ast/casestatement.rb +4 -12
  127. data/spec/unit/parser/ast/ifstatement.rb +2 -1
  128. data/spec/unit/parser/ast/leaf.rb +15 -2
  129. data/spec/unit/parser/ast/selector.rb +4 -12
  130. data/spec/unit/parser/functions/generate.rb +41 -0
  131. data/spec/unit/parser/functions/require.rb +23 -2
  132. data/spec/unit/parser/resource.rb +18 -0
  133. data/spec/unit/parser/scope.rb +94 -3
  134. data/spec/unit/provider/augeas/augeas.rb +27 -3
  135. data/spec/unit/provider/ssh_authorized_key/parsed.rb +30 -19
  136. data/spec/unit/resource/catalog.rb +16 -39
  137. data/spec/unit/simple_graph.rb +14 -0
  138. data/spec/unit/ssl/host.rb +55 -17
  139. data/spec/unit/type/file.rb +43 -11
  140. data/spec/unit/type/file/checksum.rb +28 -0
  141. data/spec/unit/type/tidy.rb +30 -1
  142. data/spec/unit/util/autoload.rb +2 -1
  143. data/spec/unit/util/checksums.rb +7 -1
  144. data/spec/unit/util/settings.rb +39 -2
  145. data/spec/unit/util/zaml.rb +38 -0
  146. data/tasks/rake/changelog.rake +1 -1
  147. data/tasks/rake/gem.rake +3 -3
  148. data/tasks/rake/git_workflow.rake +1 -1
  149. data/tasks/rake/sign.rake +1 -1
  150. data/tasks/rake/yard.rake +11 -0
  151. data/test/certmgr/certmgr.rb +1 -1
  152. data/test/data/providers/ssh_authorized_key/parsed/authorized_keys +1 -1
  153. data/test/lib/puppettest/support/utils.rb +2 -1
  154. data/test/network/handler/ca.rb +4 -4
  155. data/test/network/handler/fileserver.rb +15 -9
  156. data/test/other/transactions.rb +1 -6
  157. data/test/puppet/tc_suidmanager.rb +7 -2
  158. data/test/ral/providers/host/parsed.rb +6 -6
  159. data/test/ral/providers/package.rb +4 -0
  160. data/test/ral/providers/sshkey/parsed.rb +5 -5
  161. data/test/ral/type/file.rb +0 -21
  162. data/test/ral/type/host.rb +4 -4
  163. data/test/ral/type/resources.rb +0 -78
  164. data/test/ral/type/sshkey.rb +2 -2
  165. data/test/test +1 -1
  166. data/test/util/settings.rb +6 -6
  167. metadata +1065 -1050
  168. data/test/executables/puppetmodule.rb +0 -55
  169. data/test/ral/providers/service/debian.rb +0 -58
@@ -16,7 +16,7 @@ module Puppet
16
16
  else
17
17
  # Else, use system-wide directories.
18
18
  conf = "/etc/puppet"
19
- var = "/var/puppet"
19
+ var = "/var/lib/puppet"
20
20
  end
21
21
 
22
22
  self.setdefaults(:main,
@@ -149,6 +149,8 @@ module Puppet
149
149
  huge numbers that can then not be fed back into the system. This is a hackish way to fail in a
150
150
  slightly more useful way when that happens."],
151
151
  :node_terminus => ["plain", "Where to find information about nodes."],
152
+ :catalog_terminus => ["compiler", "Where to get node catalogs. This is useful to change if, for instance,
153
+ you'd like to pre-compile catalogs and store them in memcached or some other easily-accessed store."],
152
154
  :httplog => { :default => "$logdir/http.log",
153
155
  :owner => "root",
154
156
  :mode => 0640,
@@ -159,9 +161,6 @@ module Puppet
159
161
  may need to use a FQDN for the server hostname when using a proxy."],
160
162
  :http_proxy_port => [3128,
161
163
  "The HTTP proxy port to use for outgoing connections"],
162
- :http_enable_post_connection_check => [true,
163
- "Boolean; whether or not puppetd should validate the server
164
- SSL certificate against the request hostname."],
165
164
  :filetimeout => [ 15,
166
165
  "The minimum time to wait (in seconds) between checking for updates in
167
166
  configuration files. This timeout determines how quickly Puppet checks whether
@@ -292,7 +291,9 @@ module Puppet
292
291
  :owner => "service",
293
292
  :desc => "Where the host's certificate revocation list can be found.
294
293
  This is distinct from the certificate authority's CRL."
295
- }
294
+ },
295
+ :certificate_revocation => [true, "Whether certificate revocation should be supported by downloading a Certificate Revocation List (CRL)
296
+ to all clients. If enabled, CA chaining will almost definitely not work."]
296
297
  )
297
298
 
298
299
  setdefaults(:ca,
@@ -451,12 +452,12 @@ module Puppet
451
452
  directories.", :type => :setting }, # We don't want this to be considered a file, since it's multiple files.
452
453
  :ssl_client_header => ["HTTP_X_CLIENT_DN", "The header containing an authenticated
453
454
  client's SSL DN. Only used with Mongrel. This header must be set by the proxy
454
- to the authenticated client's SSL DN (e.g., ``/CN=puppet.reductivelabs.com``).
455
- See http://reductivelabs.com/puppet/trac/wiki/UsingMongrel for more information."],
455
+ to the authenticated client's SSL DN (e.g., ``/CN=puppet.puppetlabs.com``).
456
+ See http://puppetlabs.com/puppet/trac/wiki/UsingMongrel for more information."],
456
457
  :ssl_client_verify_header => ["HTTP_X_CLIENT_VERIFY", "The header containing the status
457
458
  message of the client verification. Only used with Mongrel. This header must be set by the proxy
458
459
  to 'SUCCESS' if the client successfully authenticated, and anything else otherwise.
459
- See http://reductivelabs.com/puppet/trac/wiki/UsingMongrel for more information."],
460
+ See http://puppetlabs.com/puppet/trac/wiki/UsingMongrel for more information."],
460
461
  # To make sure this directory is created before we try to use it on the server, we need
461
462
  # it to be in the server section (#1138).
462
463
  :yamldir => {:default => "$vardir/yaml", :owner => "service", :group => "service", :mode => "750",
@@ -559,6 +560,10 @@ module Puppet
559
560
  new configurations, where you want to fix the broken configuration
560
561
  rather than reverting to a known-good one."
561
562
  ],
563
+ :use_cached_catalog => [false,
564
+ "Whether to only use the cached catalog rather than compiling a new catalog
565
+ on every run. Puppet can be run with this enabled by default and then selectively
566
+ disabled when a recompile is desired."],
562
567
  :ignorecache => [false,
563
568
  "Ignore cache and always recompile the configuration. This is
564
569
  useful for testing new configurations, where the local cache may in
@@ -629,7 +634,7 @@ module Puppet
629
634
 
630
635
  # Central fact information.
631
636
  self.setdefaults(:main,
632
- :factpath => {:default => "$vardir/facts/",
637
+ :factpath => {:default => "$vardir/lib/facter/:$vardir/facts",
633
638
  :desc => "Where Puppet should look for facts. Multiple directories should
634
639
  be colon-separated, like normal PATH variables.",
635
640
  :call_on_define => true, # Call our hook with the default value, so we always get the value added to facter.
@@ -670,11 +675,11 @@ module Puppet
670
675
  :dbadapter => [ "sqlite3", "The type of database to use." ],
671
676
  :dbmigrate => [ false, "Whether to automatically migrate the database." ],
672
677
  :dbname => [ "puppet", "The name of the database to use." ],
673
- :dbserver => [ "localhost", "The database server for Client caching. Only
678
+ :dbserver => [ "localhost", "The database server for caching. Only
674
679
  used when networked databases are used."],
675
- :dbuser => [ "puppet", "The database user for Client caching. Only
680
+ :dbuser => [ "puppet", "The database user for caching. Only
676
681
  used when networked databases are used."],
677
- :dbpassword => [ "puppet", "The database password for Client caching. Only
682
+ :dbpassword => [ "puppet", "The database password for caching. Only
678
683
  used when networked databases are used."],
679
684
  :dbsocket => [ "", "The database socket location. Only used when networked
680
685
  databases are used. Will be ignored if the value is an empty string."],
@@ -724,7 +729,7 @@ module Puppet
724
729
  setdefaults(:ldap,
725
730
  :ldapnodes => [false,
726
731
  "Whether to search for node configurations in LDAP. See
727
- http://reductivelabs.com/trac/puppet/wiki/LDAPNodes for more information."],
732
+ http://puppetlabs.com/trac/puppet/wiki/LDAPNodes for more information."],
728
733
  :ldapssl => [false,
729
734
  "Whether SSL should be used when searching for nodes.
730
735
  Defaults to false because SSL usually requires certificates
@@ -9,7 +9,7 @@ require 'puppet/file_serving/metadata'
9
9
  # Operate recursively on a path, returning a set of file paths.
10
10
  class Puppet::FileServing::Fileset
11
11
  attr_reader :path, :ignore, :links
12
- attr_accessor :recurse, :recurselimit
12
+ attr_accessor :recurse, :recurselimit, :checksum_type
13
13
 
14
14
  # Produce a hash of files, with merged so that earlier files
15
15
  # with the same postfix win. E.g., /dir1/subfile beats /dir2/subfile.
@@ -105,7 +105,7 @@ class Puppet::FileServing::Fileset
105
105
  end
106
106
 
107
107
  def initialize_from_request(request)
108
- [:links, :ignore, :recurse, :recurselimit].each do |param|
108
+ [:links, :ignore, :recurse, :recurselimit, :checksum_type].each do |param|
109
109
  if request.options.include?(param) # use 'include?' so the values can be false
110
110
  value = request.options[param]
111
111
  elsif request.options.include?(param.to_s)
@@ -16,6 +16,7 @@ module Puppet::FileServing::TerminusHelper
16
16
 
17
17
  Puppet::FileServing::Fileset.merge(*filesets).collect do |file, base_path|
18
18
  inst = model.new(base_path, :relative_path => file)
19
+ inst.checksum_type = request.options[:checksum_type] if request.options[:checksum_type]
19
20
  inst.links = request.options[:links] if request.options[:links]
20
21
  inst.collect
21
22
  inst
@@ -145,6 +145,10 @@ class Puppet::Indirector::Indirection
145
145
  @terminus_class
146
146
  end
147
147
 
148
+ def reset_terminus_class
149
+ @terminus_class = nil
150
+ end
151
+
148
152
  # Specify the terminus class to use.
149
153
  def terminus_class=(klass)
150
154
  validate_terminus_class(klass)
@@ -161,19 +165,22 @@ class Puppet::Indirector::Indirection
161
165
  end
162
166
  end
163
167
 
164
- # Expire a cached object, if one is cached. Note that we now actually
165
- # remove it if possible, and only mark it as expired if destroy isn't
166
- # supported.
168
+ # Expire a cached object, if one is cached. Note that we don't actually
169
+ # remove it, we expire it and write it back out to disk. This way people
170
+ # can still use the expired object if they want.
167
171
  def expire(key, *args)
168
- if cache? and instance = cache.find(request(:find, key, *args))
169
- Puppet.info "Expiring the #{name} cache of #{instance.name}"
170
- if cache.respond_to? :destroy
171
- cache.destroy(request(:destroy, instance, *args))
172
- else
173
- instance.expiration = Time.now - 1
174
- cache.save(request(:save,instance,*args))
175
- end
176
- end
172
+ request = request(:expire, key, *args)
173
+
174
+ return nil unless cache?
175
+
176
+ return nil unless instance = cache.find(request(:find, key, *args))
177
+
178
+ Puppet.info "Expiring the %s cache of %s" % [self.name, instance.name]
179
+
180
+ # Set an expiration date in the past
181
+ instance.expiration = Time.now - 60
182
+
183
+ cache.save(request(:save, instance, *args))
177
184
  end
178
185
 
179
186
  # Search for an instance in the appropriate terminus, caching the
@@ -213,7 +220,7 @@ class Puppet::Indirector::Indirection
213
220
  return nil
214
221
  end
215
222
 
216
- Puppet.debug "Using cached #{name} for #{request.key}, good until #{cached.expiration}"
223
+ Puppet.debug "Using cached %s for %s" % [self.name, request.key]
217
224
  return cached
218
225
  end
219
226
 
@@ -183,9 +183,9 @@ module Puppet
183
183
 
184
184
  # interpolate a pattern to replace any
185
185
  # backreferences by the given match
186
- # for instance if our pattern is $1.reductivelabs.com
186
+ # for instance if our pattern is $1.puppetlabs.com
187
187
  # and we're called with a MatchData whose capture 1 is puppet
188
- # we'll return a pattern of puppet.reductivelabs.com
188
+ # we'll return a pattern of puppet.puppetlabs.com
189
189
  def interpolate(match)
190
190
  clone = dup
191
191
  clone.pattern = clone.pattern.reverse.collect do |p|
@@ -242,7 +242,7 @@ module Puppet
242
242
  when /^\*(\.(\w[-\w]*)){1,}$/ # *.domain.com
243
243
  host_sans_star = munge_name(value)[0..-2]
244
244
  [:domain,:inexact,host_sans_star.length,host_sans_star]
245
- when /\$\d+/ # a backreference pattern ala $1.reductivelabs.com or 192.168.0.$1 or $1.$2
245
+ when /\$\d+/ # a backreference pattern ala $1.puppetlabs.com or 192.168.0.$1 or $1.$2
246
246
  [:dynamic,:exact,nil,munge_name(value)]
247
247
  when /^\w[-.@\w]*$/ # ? Just like a host name but allow '@'s and ending '.'s
248
248
  [:opaque,:exact,nil,[value]]
@@ -142,7 +142,7 @@ module Puppet::Network::FormatHandler
142
142
  list.delete(preferred_format)
143
143
  list.unshift(preferred_format)
144
144
  else
145
- Puppet.warning "Value of 'preferred_serialization_format' (#{preferred_format}) is invalid for #{friendly_name}, using default (#{list.first})"
145
+ Puppet.debug "Value of 'preferred_serialization_format' (#{preferred_format}) is invalid for #{friendly_name}, using default (#{list.first})"
146
146
  end
147
147
  list
148
148
  end
@@ -283,8 +283,8 @@ class Puppet::Network::Handler
283
283
  when /\[([-\w]+)\]/
284
284
  name = $1
285
285
  if newmounts.include?(name)
286
- raise FileServerError, "%s is already mounted at %s" %
287
- [newmounts[name], name], count, @configuration.file
286
+ raise FileServerError, "%s is already mounted as %s in %s" %
287
+ [newmounts[name], name, @configuration.file]
288
288
  end
289
289
  mount = Mount.new(name)
290
290
  newmounts[name] = mount
@@ -66,7 +66,7 @@ class Puppet::Network::Handler
66
66
 
67
67
  case format
68
68
  when "yaml"
69
- return CGI.escape(catalog.extract.to_yaml(:UseBlock => true))
69
+ return CGI.escape(catalog.extract.to_yaml)
70
70
  when "marshal"
71
71
  return CGI.escape(Marshal.dump(catalog.extract))
72
72
  else
@@ -94,8 +94,6 @@ module Puppet::Network::HttpPool
94
94
  # Use configured timeout (#1176)
95
95
  http.read_timeout = Puppet[:configtimeout]
96
96
  http.open_timeout = Puppet[:configtimeout]
97
- # JJM Configurable fix for #896.
98
- http.enable_post_connection_check = Puppet[:http_enable_post_connection_check]
99
97
 
100
98
  cert_setup(http)
101
99
 
@@ -28,7 +28,7 @@ module Puppet
28
28
  crl = OpenSSL::X509::CRL.new(File.read(Puppet[:cacrl]))
29
29
  store = OpenSSL::X509::Store.new
30
30
  store.purpose = OpenSSL::X509::PURPOSE_ANY
31
- store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL|OpenSSL::X509::V_FLAG_CRL_CHECK
31
+ store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL|OpenSSL::X509::V_FLAG_CRL_CHECK if Puppet.settings[:certificate_revocation]
32
32
  unless self.ca_cert
33
33
  raise Puppet::Error, "Could not find CA certificate"
34
34
  end
@@ -11,9 +11,9 @@ class Puppet::Parser::AST
11
11
  # Short-curcuit evaluation. Return the value of the statements for
12
12
  # the first option that matches.
13
13
  def evaluate(scope)
14
+ level = scope.ephemeral_level
15
+
14
16
  value = @test.safeevaluate(scope)
15
- sensitive = Puppet[:casesensitive]
16
- value = value.downcase if ! sensitive and value.respond_to?(:downcase)
17
17
 
18
18
  retvalue = nil
19
19
  found = false
@@ -22,7 +22,7 @@ class Puppet::Parser::AST
22
22
  default = nil
23
23
  @options.each do |option|
24
24
  option.eachopt do |opt|
25
- return option.safeevaluate(scope) if opt.evaluate_match(value, scope, :file => file, :line => line, :sensitive => sensitive)
25
+ return option.safeevaluate(scope) if opt.evaluate_match(value, scope, :file => file, :line => line, :sensitive => Puppet[:casesensitive])
26
26
  end
27
27
 
28
28
  default = option if option.default?
@@ -34,7 +34,7 @@ class Puppet::Parser::AST
34
34
  Puppet.debug "No true answers and no default"
35
35
  return nil
36
36
  ensure
37
- scope.unset_ephemeral_var
37
+ scope.unset_ephemeral_var(level)
38
38
  end
39
39
 
40
40
  def each
@@ -16,6 +16,7 @@ class Puppet::Parser::AST
16
16
  # else if there's an 'else' setting, evaluate it.
17
17
  # the first option that matches.
18
18
  def evaluate(scope)
19
+ level = scope.ephemeral_level
19
20
  value = @test.safeevaluate(scope)
20
21
 
21
22
  # let's emulate a new scope for each branches
@@ -30,7 +31,7 @@ class Puppet::Parser::AST
30
31
  end
31
32
  end
32
33
  ensure
33
- scope.unset_ephemeral_var
34
+ scope.unset_ephemeral_var(level)
34
35
  end
35
36
  end
36
37
  end
@@ -16,6 +16,7 @@ class Puppet::Parser::AST
16
16
  if ! options[:sensitive] && obj.respond_to?(:downcase)
17
17
  obj = obj.downcase
18
18
  end
19
+ value = value.downcase if not options[:sensitive] and value.respond_to?(:downcase)
19
20
  obj == value
20
21
  end
21
22
 
@@ -12,13 +12,12 @@ class Puppet::Parser::AST
12
12
 
13
13
  # Find the value that corresponds with the test.
14
14
  def evaluate(scope)
15
+ level = scope.ephemeral_level
15
16
  # Get our parameter.
16
17
  paramvalue = @param.safeevaluate(scope)
17
18
 
18
19
  sensitive = Puppet[:casesensitive]
19
20
 
20
- paramvalue = paramvalue.downcase if not sensitive and paramvalue.respond_to?(:downcase)
21
-
22
21
  default = nil
23
22
 
24
23
  unless @values.instance_of? AST::ASTArray or @values.instance_of? Array
@@ -39,7 +38,7 @@ class Puppet::Parser::AST
39
38
 
40
39
  self.fail Puppet::ParseError, "No matching value for selector param '%s'" % paramvalue
41
40
  ensure
42
- scope.unset_ephemeral_var
41
+ scope.unset_ephemeral_var(level)
43
42
  end
44
43
 
45
44
  def to_s
@@ -1,6 +1,6 @@
1
1
  # Runs an external command and returns the results
2
2
  Puppet::Parser::Functions::newfunction(:generate, :type => :rvalue,
3
- :doc => "Calls an external command on the Puppet master and returns
3
+ :doc => "Calls an external command on the Puppet master and returns
4
4
  the results of the command. Any arguments are passed to the external command as
5
5
  arguments. If the generator does not exit with return code of 0,
6
6
  the generator is considered to have failed and a parse error is
@@ -26,10 +26,8 @@ Puppet::Parser::Functions::newfunction(:generate, :type => :rvalue,
26
26
  end
27
27
 
28
28
  begin
29
- output = Puppet::Util.execute(args)
29
+ Dir.chdir(File.dirname(args[0])) { Puppet::Util.execute(args) }
30
30
  rescue Puppet::ExecutionFailure => detail
31
- raise Puppet::ParseError, "Failed to execute generator %s: %s" %
32
- [args[0], detail]
31
+ raise Puppet::ParseError, "Failed to execute generator #{args[0]}: #{detail}"
33
32
  end
34
- output
35
33
  end
@@ -37,13 +37,20 @@ fail if used with earlier clients.
37
37
  vals = [vals] unless vals.is_a?(Array)
38
38
 
39
39
  vals.each do |klass|
40
+ # lookup the class in the scopes
41
+ if classobj = find_hostclass(klass)
42
+ klass = classobj.classname
43
+ else
44
+ raise Puppet::ParseError, "Could not find class %s" % klass
45
+ end
46
+
40
47
  # This is a bit hackish, in some ways, but it's the only way
41
48
  # to configure a dependency that will make it to the client.
42
49
  # The 'obvious' way is just to add an edge in the catalog,
43
50
  # but that is considered a containment edge, not a dependency
44
51
  # edge, so it usually gets lost on the client.
45
52
  ref = Puppet::Parser::Resource::Reference.new(:type => :class, :title => klass)
46
- resource.set_parameter(:require, ref)
53
+ resource.set_parameter(:require, [resource[:require]].flatten.compact << ref)
47
54
  end
48
55
  end
49
56
  end
@@ -1,6 +1,6 @@
1
1
  Puppet::Parser::Functions::newfunction(:template, :type => :rvalue, :doc =>
2
2
  "Evaluate a template and return its value. See `the templating docs
3
- </trac/puppet/wiki/PuppetTemplating>`_ for more information. Note that
3
+ <http://docs.puppetlabs.com/guides/templating.html>`_ for more information. Note that
4
4
  if multiple templates are specified, their output is all concatenated
5
5
  and returned as the output of the function.") do |vals|
6
6
  require 'erb'
@@ -262,16 +262,10 @@ class Puppet::Parser::Lexer
262
262
  return array
263
263
  end
264
264
 
265
- # this is probably pretty damned inefficient...
266
- # it'd be nice not to have to load the whole file first...
267
265
  def file=(file)
268
266
  @file = file
269
267
  @line = 1
270
- File.open(file) { |of|
271
- str = ""
272
- of.each { |line| str += line }
273
- @scanner = StringScanner.new(str)
274
- }
268
+ @scanner = StringScanner.new(File.read(file))
275
269
  end
276
270
 
277
271
  def find_string_token
@@ -377,10 +377,16 @@ class Puppet::Parser::Resource
377
377
 
378
378
  # If we've gotten this far, we're allowed to override.
379
379
 
380
- # Merge with previous value, if the parameter was generated with the +> syntax.
381
- # It's important that we use the new param instance here, not the old one,
382
- # so that the source is registered correctly for later overrides.
383
- param.value = [current.value, param.value].flatten if param.add
380
+ # Merge with previous value, if the parameter was generated with the +>
381
+ # syntax. It's important that we use a copy of the new param instance
382
+ # here, not the old one, and not the original new one, so that the source
383
+ # is registered correctly for later overrides but the values aren't
384
+ # implcitly shared when multiple resources are overrriden at once (see
385
+ # ticket #3556).
386
+ if param.add
387
+ param = param.dup
388
+ param.value = [current.value, param.value].flatten
389
+ end
384
390
 
385
391
  set_parameter(param)
386
392
  end
@@ -20,6 +20,30 @@ class Puppet::Parser::Scope
20
20
  attr_accessor :top, :translated, :compiler
21
21
  attr_writer :parent
22
22
 
23
+ # thin wrapper around an ephemeral
24
+ # symbol table.
25
+ # when a symbol
26
+ class Ephemeral
27
+ def initialize(parent=nil)
28
+ @symbols = {}
29
+ @parent = parent
30
+ end
31
+
32
+ [:include?, :delete, :[]=].each do |m|
33
+ define_method(m) do |*args|
34
+ @symbols.send(m, *args)
35
+ end
36
+ end
37
+
38
+ def [](name)
39
+ unless @symbols.include?(name) or @parent.nil?
40
+ @parent[name]
41
+ else
42
+ @symbols[name]
43
+ end
44
+ end
45
+ end
46
+
23
47
  # A demeterific shortcut to the catalog.
24
48
  def catalog
25
49
  compiler.catalog
@@ -131,7 +155,9 @@ class Puppet::Parser::Scope
131
155
  # the ephemeral symbol tables
132
156
  # those should not persist long, and are used for the moment only
133
157
  # for $0..$xy capture variables of regexes
134
- @ephemeral = {}
158
+ # this is actually implemented as a stack, with each ephemeral scope
159
+ # shadowing the previous one
160
+ @ephemeral = [ Ephemeral.new ]
135
161
 
136
162
  # All of the defaults set for types. It's a hash of hashes,
137
163
  # with the first key being the type, then the second key being
@@ -194,13 +220,13 @@ class Puppet::Parser::Scope
194
220
  # Look up a variable. The simplest value search we do. Default to returning
195
221
  # an empty string for missing values, but support returning a constant.
196
222
  def lookupvar(name, usestring = true)
197
- table = ephemeral?(name) ? @ephemeral : @symtable
223
+ table = ephemeral?(name) ? @ephemeral.last : @symtable
198
224
  # If the variable is qualified, then find the specified scope and look the variable up there instead.
199
225
  if name =~ /::/
200
226
  return lookup_qualified_var(name, usestring)
201
227
  end
202
228
  # We can't use "if table[name]" here because the value might be false
203
- if table.include?(name)
229
+ if ephemeral_include?(name) or table.include?(name)
204
230
  if usestring and table[name] == :undef
205
231
  return ""
206
232
  else
@@ -293,7 +319,7 @@ class Puppet::Parser::Scope
293
319
  # in scopes above, but will not allow variables in the current scope
294
320
  # to be reassigned.
295
321
  def setvar(name,value, options = {})
296
- table = options[:ephemeral] ? @ephemeral : @symtable
322
+ table = options[:ephemeral] ? @ephemeral.last : @symtable
297
323
  #Puppet.debug "Setting %s to '%s' at level %s mode append %s" %
298
324
  # [name.inspect,value,self.level, append]
299
325
  if table.include?(name)
@@ -338,7 +364,7 @@ class Puppet::Parser::Scope
338
364
  else # look the variable up
339
365
  # make sure $0-$9 are lookupable only if ephemeral
340
366
  var = ss[1] || ss[3] || ss[4]
341
- if var and var =~ /^[0-9]+$/ and not ephemeral?(var)
367
+ if var and var =~ /^[0-9]+$/ and not ephemeral_include?(var)
342
368
  next
343
369
  end
344
370
  out << lookupvar(var).to_s || ""
@@ -403,23 +429,49 @@ class Puppet::Parser::Scope
403
429
 
404
430
  # Undefine a variable; only used for testing.
405
431
  def unsetvar(var)
406
- table = ephemeral?(var) ? @ephemeral : @symtable
432
+ table = ephemeral?(var) ? @ephemeral.last : @symtable
407
433
  if table.include?(var)
408
434
  table.delete(var)
409
435
  end
410
436
  end
411
437
 
412
- def unset_ephemeral_var
413
- @ephemeral = {}
438
+ # remove ephemeral scope up to level
439
+ def unset_ephemeral_var(level=:all)
440
+ if level == :all
441
+ @ephemeral = [ Ephemeral.new ]
442
+ else
443
+ (@ephemeral.size - level).times do
444
+ @ephemeral.pop
445
+ end
446
+ end
447
+ end
448
+
449
+ # check if name exists in one of the ephemeral scope.
450
+ def ephemeral_include?(name)
451
+ @ephemeral.reverse.each do |eph|
452
+ return true if eph.include?(name)
453
+ end
454
+ false
414
455
  end
415
456
 
457
+ # is name an ephemeral variable?
416
458
  def ephemeral?(name)
417
- @ephemeral.include?(name)
459
+ name =~ /^\d+$/
460
+ end
461
+
462
+ def ephemeral_level
463
+ @ephemeral.size
464
+ end
465
+
466
+ def new_ephemeral
467
+ @ephemeral.push(Ephemeral.new(@ephemeral.last))
418
468
  end
419
469
 
420
470
  def ephemeral_from(match, file = nil, line = nil)
421
471
  raise(ArgumentError,"Invalid regex match data") unless match.is_a?(MatchData)
422
472
 
473
+ new_ephemeral
474
+
423
475
  setvar("0", match[0], :file => file, :line => line, :ephemeral => true)
424
476
  match.captures.each_with_index do |m,i|
425
477
  setvar("#{i+1}", m, :file => file, :line => line, :ephemeral => true)