summaryrefslogtreecommitdiffstats
path: root/lib/puppet/parser
diff options
context:
space:
mode:
authorJesse Wolfe <jes5199@gmail.com>2010-10-01 11:35:35 -0700
committerJesse Wolfe <jes5199@gmail.com>2010-10-01 11:35:35 -0700
commitda84c03a7d1fe33c660c3e4c3a069ef1aed23bae (patch)
treea75697d977d90b7754e0a14dcfc13b33aff893d1 /lib/puppet/parser
parent0077379e528037d875a92575a994d01ca5233cc0 (diff)
parent917c520f1abc0c72d7065531cffcef88259e32e0 (diff)
downloadpuppet-da84c03a7d1fe33c660c3e4c3a069ef1aed23bae.tar.gz
puppet-da84c03a7d1fe33c660c3e4c3a069ef1aed23bae.tar.xz
puppet-da84c03a7d1fe33c660c3e4c3a069ef1aed23bae.zip
Merge commit '2.6.2rc1'
Diffstat (limited to 'lib/puppet/parser')
-rw-r--r--lib/puppet/parser/ast/function.rb2
-rw-r--r--lib/puppet/parser/ast/resource.rb6
-rw-r--r--lib/puppet/parser/functions/extlookup.rb2
-rw-r--r--lib/puppet/parser/functions/versioncmp.rb6
-rw-r--r--lib/puppet/parser/lexer.rb2
-rw-r--r--lib/puppet/parser/parser_support.rb6
-rw-r--r--lib/puppet/parser/resource.rb8
-rw-r--r--lib/puppet/parser/type_loader.rb98
8 files changed, 69 insertions, 61 deletions
diff --git a/lib/puppet/parser/ast/function.rb b/lib/puppet/parser/ast/function.rb
index 74023f631..80e6e6512 100644
--- a/lib/puppet/parser/ast/function.rb
+++ b/lib/puppet/parser/ast/function.rb
@@ -28,7 +28,7 @@ class Puppet::Parser::AST
end
# We don't need to evaluate the name, because it's plaintext
- args = @arguments.safeevaluate(scope)
+ args = @arguments.safeevaluate(scope).map { |x| x == :undef ? '' : x }
scope.send("function_#{@name}", args)
end
diff --git a/lib/puppet/parser/ast/resource.rb b/lib/puppet/parser/ast/resource.rb
index 0c58538d5..6909c85c2 100644
--- a/lib/puppet/parser/ast/resource.rb
+++ b/lib/puppet/parser/ast/resource.rb
@@ -46,7 +46,6 @@ class Resource < AST::ResourceReference
:virtual => virt,
:source => scope.source,
:scope => scope,
-
:strict => true
)
@@ -64,12 +63,9 @@ class Resource < AST::ResourceReference
if params.is_a?(AST::ASTArray)
@parameters = params
else
-
- @parameters = AST::ASTArray.new(
-
+ @parameters = AST::ASTArray.new(
:line => params.line,
:file => params.file,
-
:children => [params]
)
end
diff --git a/lib/puppet/parser/functions/extlookup.rb b/lib/puppet/parser/functions/extlookup.rb
index 63d49e563..bc55410b9 100644
--- a/lib/puppet/parser/functions/extlookup.rb
+++ b/lib/puppet/parser/functions/extlookup.rb
@@ -52,7 +52,7 @@ the exact same outcome:
$snmp_contact = extlookup(\"snmp_contact\")
-The obove code shows some other features, you can use any fact or variable that
+The above code shows some other features, you can use any fact or variable that
is in scope by simply using %{varname} in your data files, you can return arrays
by just having multiple values in the csv after the initial variable name.
diff --git a/lib/puppet/parser/functions/versioncmp.rb b/lib/puppet/parser/functions/versioncmp.rb
index 94ba3886f..6091e0923 100644
--- a/lib/puppet/parser/functions/versioncmp.rb
+++ b/lib/puppet/parser/functions/versioncmp.rb
@@ -14,9 +14,9 @@ Where a and b are arbitrary version strings
This functions returns a number:
-* > 0 if version a is greater than version b
-* == 0 if both version are equals
-* < 0 if version a is less than version b
+* Greater than 0 if version a is greater than version b
+* Equal to 0 if both version are equals
+* Less than 0 if version a is less than version b
Example:
diff --git a/lib/puppet/parser/lexer.rb b/lib/puppet/parser/lexer.rb
index a25a17e3f..9036d652e 100644
--- a/lib/puppet/parser/lexer.rb
+++ b/lib/puppet/parser/lexer.rb
@@ -520,7 +520,7 @@ class Puppet::Parser::Lexer
def slurpstring(terminators,escapes=%w{ \\ $ ' " n t s }+["\n"],ignore_invalid_escapes=false)
# we search for the next quote that isn't preceded by a
# backslash; the caret is there to match empty strings
- str = @scanner.scan_until(/([^\\]|^)[#{terminators}]/) or lex_error "Unclosed quote after '#{last}' in '#{rest}'"
+ str = @scanner.scan_until(/([^\\]|^|[^\\])([\\]{2})*[#{terminators}]/) or lex_error "Unclosed quote after '#{last}' in '#{rest}'"
@line += str.count("\n") # literal carriage returns add to the line count.
str.gsub!(/\\(.)/) {
ch = $1
diff --git a/lib/puppet/parser/parser_support.rb b/lib/puppet/parser/parser_support.rb
index c0fd37178..c90c1978f 100644
--- a/lib/puppet/parser/parser_support.rb
+++ b/lib/puppet/parser/parser_support.rb
@@ -111,7 +111,7 @@ class Puppet::Parser::Parser
end
def import(file)
- known_resource_types.loader.import_if_possible(file, @lexer.file)
+ known_resource_types.loader.import(file, @lexer.file)
end
def initialize(env)
@@ -215,7 +215,9 @@ class Puppet::Parser::Parser
end
def parse_ruby_file
- require self.file
+ # Execute the contents of the file inside its own "main" object so
+ # that it can call methods in the resource type API.
+ Puppet::DSL::ResourceTypeAPI.new.instance_eval(File.read(self.file))
end
def string=(string)
diff --git a/lib/puppet/parser/resource.rb b/lib/puppet/parser/resource.rb
index 8a5ae886c..c007d4dbe 100644
--- a/lib/puppet/parser/resource.rb
+++ b/lib/puppet/parser/resource.rb
@@ -64,6 +64,7 @@ class Puppet::Parser::Resource < Puppet::Resource
# Retrieve the associated definition and evaluate it.
def evaluate
+ return if evaluated?
@evaluated = true
if klass = resource_type and ! builtin_type?
finish
@@ -93,6 +94,7 @@ class Puppet::Parser::Resource < Puppet::Resource
@finished = true
add_defaults
add_metaparams
+ add_scope_tags
validate
end
@@ -259,6 +261,12 @@ class Puppet::Parser::Resource < Puppet::Resource
end
end
+ def add_scope_tags
+ if scope_resource = scope.resource
+ tag(*scope_resource.tags)
+ end
+ end
+
# Accept a parameter from an override.
def override_parameter(param)
# This can happen if the override is defining a new parameter, rather
diff --git a/lib/puppet/parser/type_loader.rb b/lib/puppet/parser/type_loader.rb
index 09aa636e1..bae560381 100644
--- a/lib/puppet/parser/type_loader.rb
+++ b/lib/puppet/parser/type_loader.rb
@@ -3,25 +3,56 @@ require 'puppet/node/environment'
class Puppet::Parser::TypeLoader
include Puppet::Node::Environment::Helper
- class Helper < Hash
+ # Helper class that makes sure we don't try to import the same file
+ # more than once from either the same thread or different threads.
+ class Helper
include MonitorMixin
- def done_with(item)
- synchronize do
- delete(item)[:busy].signal if self.has_key?(item) and self[item][:loader] == Thread.current
- end
+ def initialize
+ super
+ # These hashes are indexed by filename
+ @state = {} # :doing or :done
+ @thread = {} # if :doing, thread that's doing the parsing
+ @cond_var = {} # if :doing, condition var that will be signaled when done.
end
- def owner_of(item)
- synchronize do
- if !self.has_key? item
- self[item] = { :loader => Thread.current, :busy => self.new_cond}
- :nobody
- elsif self[item][:loader] == Thread.current
- :this_thread
+
+ # Execute the supplied block exactly once per file, no matter how
+ # many threads have asked for it to run. If another thread is
+ # already executing it, wait for it to finish. If this thread is
+ # already executing it, return immediately without executing the
+ # block.
+ #
+ # Note: the reason for returning immediately if this thread is
+ # already executing the block is to handle the case of a circular
+ # import--when this happens, we attempt to recursively re-parse a
+ # file that we are already in the process of parsing. To prevent
+ # an infinite regress we need to simply do nothing when the
+ # recursive import is attempted.
+ def do_once(file)
+ need_to_execute = synchronize do
+ case @state[file]
+ when :doing
+ if @thread[file] != Thread.current
+ @cond_var[file].wait
+ end
+ false
+ when :done
+ false
else
- flag = self[item][:busy]
- flag.wait
- flag.signal
- :another_thread
+ @state[file] = :doing
+ @thread[file] = Thread.current
+ @cond_var[file] = new_cond
+ true
+ end
+ end
+ if need_to_execute
+ begin
+ yield
+ ensure
+ synchronize do
+ @state[file] = :done
+ @thread.delete(file)
+ @cond_var.delete(file).broadcast
+ end
end
end
end
@@ -51,8 +82,7 @@ class Puppet::Parser::TypeLoader
unless file =~ /^#{File::SEPARATOR}/
file = File.join(dir, file)
end
- unless imported? file
- @imported[file] = true
+ @loading_helper.do_once(file) do
parse_file(file)
end
end
@@ -60,27 +90,20 @@ class Puppet::Parser::TypeLoader
modname
end
- def imported?(file)
- @imported.has_key?(file)
- end
-
def known_resource_types
environment.known_resource_types
end
def initialize(env)
self.environment = env
- @loaded = {}
- @loading = Helper.new
-
- @imported = {}
+ @loading_helper = Helper.new
end
def load_until(namespaces, name)
return nil if name == "" # special-case main.
name2files(namespaces, name).each do |filename|
modname = begin
- import_if_possible(filename)
+ import(filename)
rescue Puppet::ImportError => detail
# We couldn't load the item
# I'm not convienced we should just drop these errors, but this
@@ -96,10 +119,6 @@ class Puppet::Parser::TypeLoader
nil
end
- def loaded?(name)
- @loaded.include?(name)
- end
-
def name2files(namespaces, name)
return [name.sub(/^::/, '').gsub("::", File::SEPARATOR)] if name =~ /^::/
@@ -126,21 +145,4 @@ class Puppet::Parser::TypeLoader
parser.file = file
parser.parse
end
-
- # Utility method factored out of load for handling thread-safety.
- # This isn't tested in the specs, because that's basically impossible.
- def import_if_possible(file, current_file = nil)
- @loaded[file] || begin
- case @loading.owner_of(file)
- when :this_thread
- nil
- when :another_thread
- import_if_possible(file,current_file)
- when :nobody
- @loaded[file] = import(file,current_file)
- end
- ensure
- @loading.done_with(file)
- end
- end
end