summaryrefslogtreecommitdiffstats
path: root/lib/puppet/parser
diff options
context:
space:
mode:
authorMarkus Roberts <Markus@reality.com>2010-07-09 18:12:17 -0700
committerMarkus Roberts <Markus@reality.com>2010-07-09 18:12:17 -0700
commit3180b9d9b2c844dade1d361326600f7001ec66dd (patch)
tree98fe7c5ac7eb942aac9c39f019a17b0b3f5a57f4 /lib/puppet/parser
parent543225970225de5697734bfaf0a6eee996802c04 (diff)
downloadpuppet-3180b9d9b2c844dade1d361326600f7001ec66dd.tar.gz
puppet-3180b9d9b2c844dade1d361326600f7001ec66dd.tar.xz
puppet-3180b9d9b2c844dade1d361326600f7001ec66dd.zip
Code smell: Two space indentation
Replaced 106806 occurances of ^( +)(.*$) with The ruby community almost universally (i.e. everyone but Luke, Markus, and the other eleven people who learned ruby in the 1900s) uses two-space indentation. 3 Examples: The code: end # Tell getopt which arguments are valid def test_get_getopt_args element = Setting.new :name => "foo", :desc => "anything", :settings => Puppet::Util::Settings.new assert_equal([["--foo", GetoptLong::REQUIRED_ARGUMENT]], element.getopt_args, "Did not produce appropriate getopt args") becomes: end # Tell getopt which arguments are valid def test_get_getopt_args element = Setting.new :name => "foo", :desc => "anything", :settings => Puppet::Util::Settings.new assert_equal([["--foo", GetoptLong::REQUIRED_ARGUMENT]], element.getopt_args, "Did not produce appropriate getopt args") The code: assert_equal(str, val) assert_instance_of(Float, result) end # Now test it with a passed object becomes: assert_equal(str, val) assert_instance_of(Float, result) end # Now test it with a passed object The code: end assert_nothing_raised do klass[:Yay] = "boo" klass["Cool"] = :yayness end becomes: end assert_nothing_raised do klass[:Yay] = "boo" klass["Cool"] = :yayness end
Diffstat (limited to 'lib/puppet/parser')
-rw-r--r--lib/puppet/parser/ast.rb128
-rw-r--r--lib/puppet/parser/ast/arithmetic_operator.rb54
-rw-r--r--lib/puppet/parser/ast/astarray.rb100
-rw-r--r--lib/puppet/parser/ast/asthash.rb52
-rw-r--r--lib/puppet/parser/ast/boolean_operator.rb66
-rw-r--r--lib/puppet/parser/ast/branch.rb58
-rw-r--r--lib/puppet/parser/ast/caseopt.rb100
-rw-r--r--lib/puppet/parser/ast/casestatement.rb60
-rw-r--r--lib/puppet/parser/ast/collection.rb78
-rw-r--r--lib/puppet/parser/ast/collexpr.rb132
-rw-r--r--lib/puppet/parser/ast/comparison_operator.rb66
-rw-r--r--lib/puppet/parser/ast/else.rb26
-rw-r--r--lib/puppet/parser/ast/function.rb68
-rw-r--r--lib/puppet/parser/ast/ifstatement.rb46
-rw-r--r--lib/puppet/parser/ast/in_operator.rb28
-rw-r--r--lib/puppet/parser/ast/leaf.rb342
-rw-r--r--lib/puppet/parser/ast/match_operator.rb32
-rw-r--r--lib/puppet/parser/ast/minus.rb26
-rw-r--r--lib/puppet/parser/ast/nop.rb12
-rw-r--r--lib/puppet/parser/ast/not.rb18
-rw-r--r--lib/puppet/parser/ast/relationship.rb84
-rw-r--r--lib/puppet/parser/ast/resource.rb108
-rw-r--r--lib/puppet/parser/ast/resource_defaults.rb32
-rw-r--r--lib/puppet/parser/ast/resource_override.rb98
-rw-r--r--lib/puppet/parser/ast/resource_reference.rb26
-rw-r--r--lib/puppet/parser/ast/resourceparam.rb36
-rw-r--r--lib/puppet/parser/ast/selector.rb60
-rw-r--r--lib/puppet/parser/ast/tag.rb32
-rw-r--r--lib/puppet/parser/ast/vardef.rb40
-rw-r--r--lib/puppet/parser/collector.rb360
-rw-r--r--lib/puppet/parser/compiler.rb822
-rw-r--r--lib/puppet/parser/files.rb130
-rw-r--r--lib/puppet/parser/functions.rb158
-rw-r--r--lib/puppet/parser/functions/defined.rb46
-rw-r--r--lib/puppet/parser/functions/fail.rb4
-rw-r--r--lib/puppet/parser/functions/file.rb38
-rw-r--r--lib/puppet/parser/functions/fqdn_rand.rb14
-rw-r--r--lib/puppet/parser/functions/generate.rb48
-rw-r--r--lib/puppet/parser/functions/include.rb32
-rw-r--r--lib/puppet/parser/functions/inline_template.rb32
-rw-r--r--lib/puppet/parser/functions/realize.rb16
-rw-r--r--lib/puppet/parser/functions/regsubst.rb144
-rw-r--r--lib/puppet/parser/functions/require.rb76
-rw-r--r--lib/puppet/parser/functions/search.rb10
-rw-r--r--lib/puppet/parser/functions/sha1.rb4
-rw-r--r--lib/puppet/parser/functions/shellquote.rb62
-rw-r--r--lib/puppet/parser/functions/split.rb22
-rw-r--r--lib/puppet/parser/functions/sprintf.rb16
-rw-r--r--lib/puppet/parser/functions/tag.rb6
-rw-r--r--lib/puppet/parser/functions/tagged.rb26
-rw-r--r--lib/puppet/parser/functions/template.rb36
-rw-r--r--lib/puppet/parser/functions/versioncmp.rb30
-rw-r--r--lib/puppet/parser/grammar.ra996
-rw-r--r--lib/puppet/parser/lexer.rb1004
-rw-r--r--lib/puppet/parser/parser_support.rb454
-rw-r--r--lib/puppet/parser/relationship.rb68
-rw-r--r--lib/puppet/parser/resource.rb552
-rw-r--r--lib/puppet/parser/resource/param.rb34
-rw-r--r--lib/puppet/parser/scope.rb898
-rw-r--r--lib/puppet/parser/templatewrapper.rb184
-rw-r--r--lib/puppet/parser/type_loader.rb242
-rw-r--r--lib/puppet/parser/yaml_trimmer.rb12
62 files changed, 4292 insertions, 4292 deletions
diff --git a/lib/puppet/parser/ast.rb b/lib/puppet/parser/ast.rb
index dffc30a8a..2773a240e 100644
--- a/lib/puppet/parser/ast.rb
+++ b/lib/puppet/parser/ast.rb
@@ -8,85 +8,85 @@ require 'puppet/file_collection/lookup'
# Handles things like file name, line #, and also does the initialization
# for all of the parameters of all of the child objects.
class Puppet::Parser::AST
- # Do this so I don't have to type the full path in all of the subclasses
- AST = Puppet::Parser::AST
+ # Do this so I don't have to type the full path in all of the subclasses
+ AST = Puppet::Parser::AST
- include Puppet::FileCollection::Lookup
+ include Puppet::FileCollection::Lookup
- include Puppet::Util::Errors
- include Puppet::Util::MethodHelper
- include Puppet::Util::Docs
+ include Puppet::Util::Errors
+ include Puppet::Util::MethodHelper
+ include Puppet::Util::Docs
- attr_accessor :parent, :scope
+ attr_accessor :parent, :scope
- # don't fetch lexer comment by default
- def use_docs
- self.class.use_docs
- end
+ # don't fetch lexer comment by default
+ def use_docs
+ self.class.use_docs
+ end
- # allow our subclass to specify they want documentation
- class << self
- attr_accessor :use_docs
- def associates_doc
- self.use_docs = true
- end
+ # allow our subclass to specify they want documentation
+ class << self
+ attr_accessor :use_docs
+ def associates_doc
+ self.use_docs = true
end
+ end
- # Does this ast object set something? If so, it gets evaluated first.
- def self.settor?
- if defined?(@settor)
- @settor
- else
- false
- end
+ # Does this ast object set something? If so, it gets evaluated first.
+ def self.settor?
+ if defined?(@settor)
+ @settor
+ else
+ false
end
+ end
- # Evaluate the current object. Just a stub method, since the subclass
- # should override this method.
- # of the contained children and evaluates them in turn, returning a
- # list of all of the collected values, rejecting nil values
- def evaluate(*options)
- raise Puppet::DevError, "Did not override #evaluate in #{self.class}"
- end
+ # Evaluate the current object. Just a stub method, since the subclass
+ # should override this method.
+ # of the contained children and evaluates them in turn, returning a
+ # list of all of the collected values, rejecting nil values
+ def evaluate(*options)
+ raise Puppet::DevError, "Did not override #evaluate in #{self.class}"
+ end
- # Throw a parse error.
- def parsefail(message)
- self.fail(Puppet::ParseError, message)
- end
+ # Throw a parse error.
+ def parsefail(message)
+ self.fail(Puppet::ParseError, message)
+ end
- # Wrap a statemp in a reusable way so we always throw a parse error.
- def parsewrap
- exceptwrap :type => Puppet::ParseError do
- yield
- end
+ # Wrap a statemp in a reusable way so we always throw a parse error.
+ def parsewrap
+ exceptwrap :type => Puppet::ParseError do
+ yield
end
+ end
- # The version of the evaluate method that should be called, because it
- # correctly handles errors. It is critical to use this method because
- # it can enable you to catch the error where it happens, rather than
- # much higher up the stack.
- def safeevaluate(*options)
- # We duplicate code here, rather than using exceptwrap, because this
- # is called so many times during parsing.
- begin
- return self.evaluate(*options)
- rescue Puppet::Error => detail
- raise adderrorcontext(detail)
- rescue => detail
- error = Puppet::Error.new(detail.to_s)
- # We can't use self.fail here because it always expects strings,
- # not exceptions.
- raise adderrorcontext(error, detail)
- end
+ # The version of the evaluate method that should be called, because it
+ # correctly handles errors. It is critical to use this method because
+ # it can enable you to catch the error where it happens, rather than
+ # much higher up the stack.
+ def safeevaluate(*options)
+ # We duplicate code here, rather than using exceptwrap, because this
+ # is called so many times during parsing.
+ begin
+ return self.evaluate(*options)
+ rescue Puppet::Error => detail
+ raise adderrorcontext(detail)
+ rescue => detail
+ error = Puppet::Error.new(detail.to_s)
+ # We can't use self.fail here because it always expects strings,
+ # not exceptions.
+ raise adderrorcontext(error, detail)
end
+ end
- # Initialize the object. Requires a hash as the argument, and
- # takes each of the parameters of the hash and calls the settor
- # method for them. This is probably pretty inefficient and should
- # likely be changed at some point.
- def initialize(args)
- set_options(args)
- end
+ # Initialize the object. Requires a hash as the argument, and
+ # takes each of the parameters of the hash and calls the settor
+ # method for them. This is probably pretty inefficient and should
+ # likely be changed at some point.
+ def initialize(args)
+ set_options(args)
+ end
end
# And include all of the AST subclasses.
diff --git a/lib/puppet/parser/ast/arithmetic_operator.rb b/lib/puppet/parser/ast/arithmetic_operator.rb
index 6b9a6018c..33352d727 100644
--- a/lib/puppet/parser/ast/arithmetic_operator.rb
+++ b/lib/puppet/parser/ast/arithmetic_operator.rb
@@ -2,38 +2,38 @@ require 'puppet'
require 'puppet/parser/ast/branch'
class Puppet::Parser::AST
- class ArithmeticOperator < AST::Branch
+ class ArithmeticOperator < AST::Branch
- attr_accessor :operator, :lval, :rval
+ attr_accessor :operator, :lval, :rval
- # Iterate across all of our children.
- def each
- [@lval,@rval,@operator].each { |child| yield child }
- end
+ # Iterate across all of our children.
+ def each
+ [@lval,@rval,@operator].each { |child| yield child }
+ end
- # Returns a boolean which is the result of the boolean operation
- # of lval and rval operands
- def evaluate(scope)
- # evaluate the operands, should return a boolean value
- lval = @lval.safeevaluate(scope)
- lval = Puppet::Parser::Scope.number?(lval)
- if lval == nil
- raise ArgumentError, "left operand of #{@operator} is not a number"
- end
- rval = @rval.safeevaluate(scope)
- rval = Puppet::Parser::Scope.number?(rval)
- if rval == nil
- raise ArgumentError, "right operand of #{@operator} is not a number"
- end
+ # Returns a boolean which is the result of the boolean operation
+ # of lval and rval operands
+ def evaluate(scope)
+ # evaluate the operands, should return a boolean value
+ lval = @lval.safeevaluate(scope)
+ lval = Puppet::Parser::Scope.number?(lval)
+ if lval == nil
+ raise ArgumentError, "left operand of #{@operator} is not a number"
+ end
+ rval = @rval.safeevaluate(scope)
+ rval = Puppet::Parser::Scope.number?(rval)
+ if rval == nil
+ raise ArgumentError, "right operand of #{@operator} is not a number"
+ end
- # compute result
- lval.send(@operator, rval)
- end
+ # compute result
+ lval.send(@operator, rval)
+ end
- def initialize(hash)
- super
+ def initialize(hash)
+ super
- raise ArgumentError, "Invalid arithmetic operator #{@operator}" unless %w{+ - * / << >>}.include?(@operator)
- end
+ raise ArgumentError, "Invalid arithmetic operator #{@operator}" unless %w{+ - * / << >>}.include?(@operator)
end
+ end
end
diff --git a/lib/puppet/parser/ast/astarray.rb b/lib/puppet/parser/ast/astarray.rb
index f0a0c5602..529998e3c 100644
--- a/lib/puppet/parser/ast/astarray.rb
+++ b/lib/puppet/parser/ast/astarray.rb
@@ -1,61 +1,61 @@
require 'puppet/parser/ast/branch'
class Puppet::Parser::AST
- # The basic container class. This object behaves almost identically
- # to a normal array except at initialization time. Note that its name
- # is 'AST::ASTArray', rather than plain 'AST::Array'; I had too many
- # bugs when it was just 'AST::Array', because things like
- # 'object.is_a?(Array)' never behaved as I expected.
- class ASTArray < Branch
- include Enumerable
-
- # Return a child by index. Probably never used.
- def [](index)
- @children[index]
- end
+ # The basic container class. This object behaves almost identically
+ # to a normal array except at initialization time. Note that its name
+ # is 'AST::ASTArray', rather than plain 'AST::Array'; I had too many
+ # bugs when it was just 'AST::Array', because things like
+ # 'object.is_a?(Array)' never behaved as I expected.
+ class ASTArray < Branch
+ include Enumerable
+
+ # Return a child by index. Probably never used.
+ def [](index)
+ @children[index]
+ end
- # Evaluate our children.
- def evaluate(scope)
- # Make a new array, so we don't have to deal with the details of
- # flattening and such
- items = []
-
- # First clean out any AST::ASTArrays
- @children.each { |child|
- if child.instance_of?(AST::ASTArray)
- child.each do |ac|
- items << ac
- end
- else
- items << child
- end
- }
-
- rets = items.flatten.collect { |child|
- child.safeevaluate(scope)
- }
- rets.reject { |o| o.nil? }
+ # Evaluate our children.
+ def evaluate(scope)
+ # Make a new array, so we don't have to deal with the details of
+ # flattening and such
+ items = []
+
+ # First clean out any AST::ASTArrays
+ @children.each { |child|
+ if child.instance_of?(AST::ASTArray)
+ child.each do |ac|
+ items << ac
+ end
+ else
+ items << child
end
+ }
- def push(*ary)
- ary.each { |child|
- #Puppet.debug "adding %s(%s) of type %s to %s" %
- # [child, child.object_id, child.class.to_s.sub(/.+::/,''),
- # self.object_id]
- @children.push(child)
- }
+ rets = items.flatten.collect { |child|
+ child.safeevaluate(scope)
+ }
+ rets.reject { |o| o.nil? }
+ end
- self
- end
+ def push(*ary)
+ ary.each { |child|
+ #Puppet.debug "adding %s(%s) of type %s to %s" %
+ # [child, child.object_id, child.class.to_s.sub(/.+::/,''),
+ # self.object_id]
+ @children.push(child)
+ }
- def to_s
- "[" + @children.collect { |c| c.to_s }.join(', ') + "]"
- end
+ self
+ end
+
+ def to_s
+ "[" + @children.collect { |c| c.to_s }.join(', ') + "]"
end
+ end
- # A simple container class, containing the parameters for an object.
- # Used for abstracting the grammar declarations. Basically unnecessary
- # except that I kept finding bugs because I had too many arrays that
- # meant completely different things.
- class ResourceInstance < ASTArray; end
+ # A simple container class, containing the parameters for an object.
+ # Used for abstracting the grammar declarations. Basically unnecessary
+ # except that I kept finding bugs because I had too many arrays that
+ # meant completely different things.
+ class ResourceInstance < ASTArray; end
end
diff --git a/lib/puppet/parser/ast/asthash.rb b/lib/puppet/parser/ast/asthash.rb
index d16b7459f..ae81d35dd 100644
--- a/lib/puppet/parser/ast/asthash.rb
+++ b/lib/puppet/parser/ast/asthash.rb
@@ -1,37 +1,37 @@
require 'puppet/parser/ast/leaf'
class Puppet::Parser::AST
- class ASTHash < Leaf
- include Enumerable
+ class ASTHash < Leaf
+ include Enumerable
- # Evaluate our children.
- def evaluate(scope)
- items = {}
+ # Evaluate our children.
+ def evaluate(scope)
+ items = {}
- @value.each_pair do |k,v|
- key = k.respond_to?(:safeevaluate) ? k.safeevaluate(scope) : k
- items.merge!({ key => v.safeevaluate(scope) })
- end
+ @value.each_pair do |k,v|
+ key = k.respond_to?(:safeevaluate) ? k.safeevaluate(scope) : k
+ items.merge!({ key => v.safeevaluate(scope) })
+ end
- items
- end
+ items
+ end
- def merge(hash)
- case hash
- when ASTHash
- @value = @value.merge(hash.value)
- when Hash
- @value = @value.merge(hash)
- end
- end
+ def merge(hash)
+ case hash
+ when ASTHash
+ @value = @value.merge(hash.value)
+ when Hash
+ @value = @value.merge(hash)
+ end
+ end
- def to_s
- "{" + @value.collect { |v| v.collect { |a| a.to_s }.join(' => ') }.join(', ') + "}"
- end
+ def to_s
+ "{" + @value.collect { |v| v.collect { |a| a.to_s }.join(' => ') }.join(', ') + "}"
+ end
- def initialize(args)
- super(args)
- @value ||= {}
- end
+ def initialize(args)
+ super(args)
+ @value ||= {}
end
+ end
end
diff --git a/lib/puppet/parser/ast/boolean_operator.rb b/lib/puppet/parser/ast/boolean_operator.rb
index 0f7e21d2c..8481e4f8d 100644
--- a/lib/puppet/parser/ast/boolean_operator.rb
+++ b/lib/puppet/parser/ast/boolean_operator.rb
@@ -2,45 +2,45 @@ require 'puppet'
require 'puppet/parser/ast/branch'
class Puppet::Parser::AST
- class BooleanOperator < AST::Branch
+ class BooleanOperator < AST::Branch
- attr_accessor :operator, :lval, :rval
+ attr_accessor :operator, :lval, :rval
- # Iterate across all of our children.
- def each
- [@lval,@rval,@operator].each { |child| yield child }
- end
+ # Iterate across all of our children.
+ def each
+ [@lval,@rval,@operator].each { |child| yield child }
+ end
- # Returns a boolean which is the result of the boolean operation
- # of lval and rval operands
- def evaluate(scope)
- # evaluate the first operand, should return a boolean value
- lval = @lval.safeevaluate(scope)
+ # Returns a boolean which is the result of the boolean operation
+ # of lval and rval operands
+ def evaluate(scope)
+ # evaluate the first operand, should return a boolean value
+ lval = @lval.safeevaluate(scope)
- # return result
- # lazy evaluate right operand
- case @operator
- when "and"
- if Puppet::Parser::Scope.true?(lval)
- rval = @rval.safeevaluate(scope)
- Puppet::Parser::Scope.true?(rval)
- else # false and false == false
- false
- end
- when "or"
- if Puppet::Parser::Scope.true?(lval)
- true
- else
- rval = @rval.safeevaluate(scope)
- Puppet::Parser::Scope.true?(rval)
- end
- end
+ # return result
+ # lazy evaluate right operand
+ case @operator
+ when "and"
+ if Puppet::Parser::Scope.true?(lval)
+ rval = @rval.safeevaluate(scope)
+ Puppet::Parser::Scope.true?(rval)
+ else # false and false == false
+ false
+ end
+ when "or"
+ if Puppet::Parser::Scope.true?(lval)
+ true
+ else
+ rval = @rval.safeevaluate(scope)
+ Puppet::Parser::Scope.true?(rval)
end
+ end
+ end
- def initialize(hash)
- super
+ def initialize(hash)
+ super
- raise ArgumentError, "Invalid boolean operator #{@operator}" unless %w{and or}.include?(@operator)
- end
+ raise ArgumentError, "Invalid boolean operator #{@operator}" unless %w{and or}.include?(@operator)
end
+ end
end
diff --git a/lib/puppet/parser/ast/branch.rb b/lib/puppet/parser/ast/branch.rb
index 96d065e4c..73a2f674b 100644
--- a/lib/puppet/parser/ast/branch.rb
+++ b/lib/puppet/parser/ast/branch.rb
@@ -1,37 +1,37 @@
class Puppet::Parser::AST
- # The parent class of all AST objects that contain other AST objects.
- # Everything but the really simple objects descend from this. It is
- # important to note that Branch objects contain other AST objects only --
- # if you want to contain values, use a descendent of the AST::Leaf class.
- class Branch < AST
- include Enumerable
- attr_accessor :pin, :children
+ # The parent class of all AST objects that contain other AST objects.
+ # Everything but the really simple objects descend from this. It is
+ # important to note that Branch objects contain other AST objects only --
+ # if you want to contain values, use a descendent of the AST::Leaf class.
+ class Branch < AST
+ include Enumerable
+ attr_accessor :pin, :children
- # Yield each contained AST node in turn. Used mostly by 'evaluate'.
- # This definition means that I don't have to override 'evaluate'
- # every time, but each child of Branch will likely need to override
- # this method.
- def each
- @children.each { |child|
- yield child
- }
- end
+ # Yield each contained AST node in turn. Used mostly by 'evaluate'.
+ # This definition means that I don't have to override 'evaluate'
+ # every time, but each child of Branch will likely need to override
+ # this method.
+ def each
+ @children.each { |child|
+ yield child
+ }
+ end
- # Initialize our object. Largely relies on the method from the base
- # class, but also does some verification.
- def initialize(arghash)
- super(arghash)
+ # Initialize our object. Largely relies on the method from the base
+ # class, but also does some verification.
+ def initialize(arghash)
+ super(arghash)
- # Create the hash, if it was not set at initialization time.
- @children ||= []
+ # Create the hash, if it was not set at initialization time.
+ @children ||= []
- # Verify that we only got valid AST nodes.
- @children.each { |child|
- unless child.is_a?(AST)
- raise Puppet::DevError,
- "child #{child} is a #{child.class} instead of ast"
- end
- }
+ # Verify that we only got valid AST nodes.
+ @children.each { |child|
+ unless child.is_a?(AST)
+ raise Puppet::DevError,
+ "child #{child} is a #{child.class} instead of ast"
end
+ }
end
+ end
end
diff --git a/lib/puppet/parser/ast/caseopt.rb b/lib/puppet/parser/ast/caseopt.rb
index 6cf36f94c..4e296e82f 100644
--- a/lib/puppet/parser/ast/caseopt.rb
+++ b/lib/puppet/parser/ast/caseopt.rb
@@ -1,64 +1,64 @@
require 'puppet/parser/ast/branch'
class Puppet::Parser::AST
- # Each individual option in a case statement.
- class CaseOpt < AST::Branch
- attr_accessor :value, :statements
+ # Each individual option in a case statement.
+ class CaseOpt < AST::Branch
+ attr_accessor :value, :statements
- # CaseOpt is a bit special -- we just want the value first,
- # so that CaseStatement can compare, and then it will selectively
- # decide whether to fully evaluate this option
+ # CaseOpt is a bit special -- we just want the value first,
+ # so that CaseStatement can compare, and then it will selectively
+ # decide whether to fully evaluate this option
- def each
- [@value,@statements].each { |child| yield child }
- end
+ def each
+ [@value,@statements].each { |child| yield child }
+ end
- # Are we the default option?
- def default?
- # Cache the @default value.
- return @default if defined?(@default)
+ # Are we the default option?
+ def default?
+ # Cache the @default value.
+ return @default if defined?(@default)
- if @value.is_a?(AST::ASTArray)
- @value.each { |subval|
- if subval.is_a?(AST::Default)
- @default = true
- break
- end
- }
- else
- @default = true if @value.is_a?(AST::Default)
- end
+ if @value.is_a?(AST::ASTArray)
+ @value.each { |subval|
+ if subval.is_a?(AST::Default)
+ @default = true
+ break
+ end
+ }
+ else
+ @default = true if @value.is_a?(AST::Default)
+ end
- @default ||= false
+ @default ||= false
- @default
- end
+ @default
+ end
- # You can specify a list of values; return each in turn.
- def eachvalue(scope)
- if @value.is_a?(AST::ASTArray)
- @value.each { |subval|
- yield subval.safeevaluate(scope)
- }
- else
- yield @value.safeevaluate(scope)
- end
- end
+ # You can specify a list of values; return each in turn.
+ def eachvalue(scope)
+ if @value.is_a?(AST::ASTArray)
+ @value.each { |subval|
+ yield subval.safeevaluate(scope)
+ }
+ else
+ yield @value.safeevaluate(scope)
+ end
+ end
- def eachopt
- if @value.is_a?(AST::ASTArray)
- @value.each { |subval|
- yield subval
- }
- else
- yield @value
- end
- end
+ def eachopt
+ if @value.is_a?(AST::ASTArray)
+ @value.each { |subval|
+ yield subval
+ }
+ else
+ yield @value
+ end
+ end
- # Evaluate the actual statements; this only gets called if
- # our option matched.
- def evaluate(scope)
- @statements.safeevaluate(scope)
- end
+ # Evaluate the actual statements; this only gets called if
+ # our option matched.
+ def evaluate(scope)
+ @statements.safeevaluate(scope)
end
+ end
end
diff --git a/lib/puppet/parser/ast/casestatement.rb b/lib/puppet/parser/ast/casestatement.rb
index 0cddef0f0..8370d11f3 100644
--- a/lib/puppet/parser/ast/casestatement.rb
+++ b/lib/puppet/parser/ast/casestatement.rb
@@ -1,44 +1,44 @@
require 'puppet/parser/ast/branch'
class Puppet::Parser::AST
- # The basic logical structure in Puppet. Supports a list of
- # tests and statement arrays.
- class CaseStatement < AST::Branch
- attr_accessor :test, :options, :default
+ # The basic logical structure in Puppet. Supports a list of
+ # tests and statement arrays.
+ class CaseStatement < AST::Branch
+ attr_accessor :test, :options, :default
- associates_doc
+ associates_doc
- # Short-curcuit evaluation. Return the value of the statements for
- # the first option that matches.
- def evaluate(scope)
- level = scope.ephemeral_level
+ # Short-curcuit evaluation. Return the value of the statements for
+ # the first option that matches.
+ def evaluate(scope)
+ level = scope.ephemeral_level
- value = @test.safeevaluate(scope)
+ value = @test.safeevaluate(scope)
- retvalue = nil
- found = false
+ retvalue = nil
+ found = false
- # Iterate across the options looking for a match.
- default = nil
- @options.each do |option|
- option.eachopt do |opt|
- return option.safeevaluate(scope) if opt.evaluate_match(value, scope)
- end
+ # Iterate across the options looking for a match.
+ default = nil
+ @options.each do |option|
+ option.eachopt do |opt|
+ return option.safeevaluate(scope) if opt.evaluate_match(value, scope)
+ end
- default = option if option.default?
- end
+ default = option if option.default?
+ end
- # Unless we found something, look for the default.
- return default.safeevaluate(scope) if default
+ # Unless we found something, look for the default.
+ return default.safeevaluate(scope) if default
- Puppet.debug "No true answers and no default"
- return nil
- ensure
- scope.unset_ephemeral_var(level)
- end
+ Puppet.debug "No true answers and no default"
+ return nil
+ ensure
+ scope.unset_ephemeral_var(level)
+ end
- def each
- [@test,@options].each { |child| yield child }
- end
+ def each
+ [@test,@options].each { |child| yield child }
end
+ end
end
diff --git a/lib/puppet/parser/ast/collection.rb b/lib/puppet/parser/ast/collection.rb
index 44f3b330c..09d5b4eb3 100644
--- a/lib/puppet/parser/ast/collection.rb
+++ b/lib/puppet/parser/ast/collection.rb
@@ -6,60 +6,60 @@ require 'puppet/parser/collector'
# them to the current host, yo.
class Puppet::Parser::AST
class Collection < AST::Branch
- attr_accessor :type, :query, :form
- attr_reader :override
+ attr_accessor :type, :query, :form
+ attr_reader :override
- associates_doc
+ associates_doc
- # We return an object that does a late-binding evaluation.
- def evaluate(scope)
- if self.query
- str, code = self.query.safeevaluate scope
- else
- str = code = nil
- end
+ # We return an object that does a late-binding evaluation.
+ def evaluate(scope)
+ if self.query
+ str, code = self.query.safeevaluate scope
+ else
+ str = code = nil
+ end
- newcoll = Puppet::Parser::Collector.new(scope, @type, str, code, self.form)
+ newcoll = Puppet::Parser::Collector.new(scope, @type, str, code, self.form)
- scope.compiler.add_collection(newcoll)
+ scope.compiler.add_collection(newcoll)
- # overrides if any
- # Evaluate all of the specified params.
- if @override
- params = @override.collect do |param|
- param.safeevaluate(scope)
- end
+ # overrides if any
+ # Evaluate all of the specified params.
+ if @override
+ params = @override.collect do |param|
+ param.safeevaluate(scope)
+ end
- newcoll.add_override(
+ newcoll.add_override(
- :parameters => params,
- :file => @file,
- :line => @line,
- :source => scope.source,
+ :parameters => params,
+ :file => @file,
+ :line => @line,
+ :source => scope.source,
- :scope => scope
- )
- end
-
- newcoll
+ :scope => scope
+ )
end
- # Handle our parameter ourselves
- def override=(override)
- if override.is_a?(AST::ASTArray)
- @override = override
- else
+ newcoll
+ end
+
+ # Handle our parameter ourselves
+ def override=(override)
+ if override.is_a?(AST::ASTArray)
+ @override = override
+ else
- @override = AST::ASTArray.new(
+ @override = AST::ASTArray.new(
- :line => override.line,
- :file => override.file,
+ :line => override.line,
+ :file => override.file,
- :children => [override]
- )
- end
+ :children => [override]
+ )
end
+ end
end
end
diff --git a/lib/puppet/parser/ast/collexpr.rb b/lib/puppet/parser/ast/collexpr.rb
index f71b53d46..f912b4b33 100644
--- a/lib/puppet/parser/ast/collexpr.rb
+++ b/lib/puppet/parser/ast/collexpr.rb
@@ -6,81 +6,81 @@ require 'puppet/parser/collector'
# them to the current host, yo.
class Puppet::Parser::AST
class CollExpr < AST::Branch
- attr_accessor :test1, :test2, :oper, :form, :type, :parens
+ attr_accessor :test1, :test2, :oper, :form, :type, :parens
- # We return an object that does a late-binding evaluation.
- def evaluate(scope)
- # Make sure our contained expressions have all the info they need.
- [@test1, @test2].each do |t|
- if t.is_a?(self.class)
- t.form ||= self.form
- t.type ||= self.type
- end
- end
-
- # The code is only used for virtual lookups
- str1, code1 = @test1.safeevaluate scope
- str2, code2 = @test2.safeevaluate scope
-
- # First build up the virtual code.
- # If we're a conjunction operator, then we're calling code. I did
- # some speed comparisons, and it's at least twice as fast doing these
- # case statements as doing an eval here.
- code = proc do |resource|
- case @oper
- when "and"; code1.call(resource) and code2.call(resource)
- when "or"; code1.call(resource) or code2.call(resource)
- when "=="
- if str1 == "tag"
- resource.tagged?(str2)
- else
- if resource[str1].is_a?(Array)
- resource[str1].include?(str2)
- else
- resource[str1] == str2
- end
- end
- when "!="; resource[str1] != str2
- end
- end
-
- # Now build up the rails conditions code
- if self.parens and self.form == :exported
- Puppet.warning "Parentheses are ignored in Rails searches"
- end
+ # We return an object that does a late-binding evaluation.
+ def evaluate(scope)
+ # Make sure our contained expressions have all the info they need.
+ [@test1, @test2].each do |t|
+ if t.is_a?(self.class)
+ t.form ||= self.form
+ t.type ||= self.type
+ end
+ end
- case @oper
- when "and", "or"
- if form == :exported
- raise Puppet::ParseError, "Puppet does not currently support collecting exported resources with more than one condition"
- end
- oper = @oper.upcase
- when "=="; oper = "="
- else
- oper = @oper
- end
+ # The code is only used for virtual lookups
+ str1, code1 = @test1.safeevaluate scope
+ str2, code2 = @test2.safeevaluate scope
- if oper == "=" or oper == "!="
- # Add the rails association info where necessary
- case str1
- when "title"
- str = "title #{oper} '#{str2}'"
- when "tag"
- str = "puppet_tags.name #{oper} '#{str2}'"
- else
- str = "param_values.value #{oper} '#{str2}' and param_names.name = '#{str1}'"
- end
+ # First build up the virtual code.
+ # If we're a conjunction operator, then we're calling code. I did
+ # some speed comparisons, and it's at least twice as fast doing these
+ # case statements as doing an eval here.
+ code = proc do |resource|
+ case @oper
+ when "and"; code1.call(resource) and code2.call(resource)
+ when "or"; code1.call(resource) or code2.call(resource)
+ when "=="
+ if str1 == "tag"
+ resource.tagged?(str2)
else
- str = "(#{str1}) #{oper} (#{str2})"
+ if resource[str1].is_a?(Array)
+ resource[str1].include?(str2)
+ else
+ resource[str1] == str2
+ end
end
+ when "!="; resource[str1] != str2
+ end
+ end
- return str, code
+ # Now build up the rails conditions code
+ if self.parens and self.form == :exported
+ Puppet.warning "Parentheses are ignored in Rails searches"
end
- def initialize(hash = {})
- super
+ case @oper
+ when "and", "or"
+ if form == :exported
+ raise Puppet::ParseError, "Puppet does not currently support collecting exported resources with more than one condition"
+ end
+ oper = @oper.upcase
+ when "=="; oper = "="
+ else
+ oper = @oper
+ end
- raise ArgumentError, "Invalid operator #{@oper}" unless %w{== != and or}.include?(@oper)
+ if oper == "=" or oper == "!="
+ # Add the rails association info where necessary
+ case str1
+ when "title"
+ str = "title #{oper} '#{str2}'"
+ when "tag"
+ str = "puppet_tags.name #{oper} '#{str2}'"
+ else
+ str = "param_values.value #{oper} '#{str2}' and param_names.name = '#{str1}'"
+ end
+ else
+ str = "(#{str1}) #{oper} (#{str2})"
end
+
+ return str, code
+ end
+
+ def initialize(hash = {})
+ super
+
+ raise ArgumentError, "Invalid operator #{@oper}" unless %w{== != and or}.include?(@oper)
+ end
end
end
diff --git a/lib/puppet/parser/ast/comparison_operator.rb b/lib/puppet/parser/ast/comparison_operator.rb
index e8b21d45f..c8694bbff 100644
--- a/lib/puppet/parser/ast/comparison_operator.rb
+++ b/lib/puppet/parser/ast/comparison_operator.rb
@@ -2,38 +2,38 @@ require 'puppet'
require 'puppet/parser/ast/branch'
class Puppet::Parser::AST
- class ComparisonOperator < AST::Branch
-
- attr_accessor :operator, :lval, :rval
-
- # Iterate across all of our children.
- def each
- [@lval,@rval,@operator].each { |child| yield child }
- end
-
- # Returns a boolean which is the result of the boolean operation
- # of lval and rval operands
- def evaluate(scope)
- # evaluate the operands, should return a boolean value
- lval = @lval.safeevaluate(scope)
- rval = @rval.safeevaluate(scope)
-
- # convert to number if operands are number
- lval = Puppet::Parser::Scope.number?(lval) || lval
- rval = Puppet::Parser::Scope.number?(rval) || rval
-
- # return result
- unless @operator == '!='
- lval.send(@operator,rval)
- else
- lval != rval
- end
- end
-
- def initialize(hash)
- super
-
- raise ArgumentError, "Invalid comparison operator #{@operator}" unless %w{== != < > <= >=}.include?(@operator)
- end
+ class ComparisonOperator < AST::Branch
+
+ attr_accessor :operator, :lval, :rval
+
+ # Iterate across all of our children.
+ def each
+ [@lval,@rval,@operator].each { |child| yield child }
+ end
+
+ # Returns a boolean which is the result of the boolean operation
+ # of lval and rval operands
+ def evaluate(scope)
+ # evaluate the operands, should return a boolean value
+ lval = @lval.safeevaluate(scope)
+ rval = @rval.safeevaluate(scope)
+
+ # convert to number if operands are number
+ lval = Puppet::Parser::Scope.number?(lval) || lval
+ rval = Puppet::Parser::Scope.number?(rval) || rval
+
+ # return result
+ unless @operator == '!='
+ lval.send(@operator,rval)
+ else
+ lval != rval
+ end
+ end
+
+ def initialize(hash)
+ super
+
+ raise ArgumentError, "Invalid comparison operator #{@operator}" unless %w{== != < > <= >=}.include?(@operator)
end
+ end
end
diff --git a/lib/puppet/parser/ast/else.rb b/lib/puppet/parser/ast/else.rb
index 2da9191c8..172149116 100644
--- a/lib/puppet/parser/ast/else.rb
+++ b/lib/puppet/parser/ast/else.rb
@@ -1,22 +1,22 @@
require 'puppet/parser/ast/branch'
class Puppet::Parser::AST
- # A separate ElseIf statement; can function as an 'else' if there's no
- # test.
- class Else < AST::Branch
+ # A separate ElseIf statement; can function as an 'else' if there's no
+ # test.
+ class Else < AST::Branch
- associates_doc
+ associates_doc
- attr_accessor :statements
+ attr_accessor :statements
- def each
- yield @statements
- end
+ def each
+ yield @statements
+ end
- # Evaluate the actual statements; this only gets called if
- # our test was true matched.
- def evaluate(scope)
- @statements.safeevaluate(scope)
- end
+ # Evaluate the actual statements; this only gets called if
+ # our test was true matched.
+ def evaluate(scope)
+ @statements.safeevaluate(scope)
end
+ end
end
diff --git a/lib/puppet/parser/ast/function.rb b/lib/puppet/parser/ast/function.rb
index 6f6c869f5..602016c75 100644
--- a/lib/puppet/parser/ast/function.rb
+++ b/lib/puppet/parser/ast/function.rb
@@ -1,51 +1,51 @@
require 'puppet/parser/ast/branch'
class Puppet::Parser::AST
- # An AST object to call a function.
- class Function < AST::Branch
+ # An AST object to call a function.
+ class Function < AST::Branch
- associates_doc
+ associates_doc
- attr_accessor :name, :arguments
+ attr_accessor :name, :arguments
- @settor = true
+ @settor = true
- def evaluate(scope)
+ def evaluate(scope)
- # Make sure it's a defined function
- raise Puppet::ParseError, "Unknown function #{@name}" unless Puppet::Parser::Functions.function(@name)
+ # Make sure it's a defined function
+ raise Puppet::ParseError, "Unknown function #{@name}" unless Puppet::Parser::Functions.function(@name)
- # Now check that it's been used correctly
- case @ftype
- when :rvalue
- raise Puppet::ParseError, "Function '#{@name}' does not return a value" unless Puppet::Parser::Functions.rvalue?(@name)
- when :statement
- if Puppet::Parser::Functions.rvalue?(@name)
- raise Puppet::ParseError,
- "Function '#{@name}' must be the value of a statement"
- end
- else
- raise Puppet::DevError, "Invalid function type #{@ftype.inspect}"
- end
+ # Now check that it's been used correctly
+ case @ftype
+ when :rvalue
+ raise Puppet::ParseError, "Function '#{@name}' does not return a value" unless Puppet::Parser::Functions.rvalue?(@name)
+ when :statement
+ if Puppet::Parser::Functions.rvalue?(@name)
+ raise Puppet::ParseError,
+ "Function '#{@name}' must be the value of a statement"
+ end
+ else
+ raise Puppet::DevError, "Invalid function type #{@ftype.inspect}"
+ end
- # We don't need to evaluate the name, because it's plaintext
- args = @arguments.safeevaluate(scope)
+ # We don't need to evaluate the name, because it's plaintext
+ args = @arguments.safeevaluate(scope)
- scope.send("function_#{@name}", args)
- end
+ scope.send("function_#{@name}", args)
+ end
- def initialize(hash)
- @ftype = hash[:ftype] || :rvalue
- hash.delete(:ftype) if hash.include? :ftype
+ def initialize(hash)
+ @ftype = hash[:ftype] || :rvalue
+ hash.delete(:ftype) if hash.include? :ftype
- super(hash)
+ super(hash)
- # Lastly, check the parity
- end
+ # Lastly, check the parity
+ end
- def to_s
- args = arguments.is_a?(ASTArray) ? arguments.to_s.gsub(/\[(.*)\]/,'\1') : arguments
- "#{name}(#{args})"
- end
+ def to_s
+ args = arguments.is_a?(ASTArray) ? arguments.to_s.gsub(/\[(.*)\]/,'\1') : arguments
+ "#{name}(#{args})"
end
+ end
end
diff --git a/lib/puppet/parser/ast/ifstatement.rb b/lib/puppet/parser/ast/ifstatement.rb
index cbb61bf9c..7fd8a576a 100644
--- a/lib/puppet/parser/ast/ifstatement.rb
+++ b/lib/puppet/parser/ast/ifstatement.rb
@@ -1,34 +1,34 @@
require 'puppet/parser/ast/branch'
class Puppet::Parser::AST
- # A basic 'if/elsif/else' statement.
- class IfStatement < AST::Branch
+ # A basic 'if/elsif/else' statement.
+ class IfStatement < AST::Branch
- associates_doc
+ associates_doc
- attr_accessor :test, :else, :statements
+ attr_accessor :test, :else, :statements
- def each
- [@test,@else,@statements].each { |child| yield child }
- end
+ def each
+ [@test,@else,@statements].each { |child| yield child }
+ end
- # Short-curcuit evaluation. If we're true, evaluate our statements,
- # else if there's an 'else' setting, evaluate it.
- # the first option that matches.
- def evaluate(scope)
- level = scope.ephemeral_level
- value = @test.safeevaluate(scope)
+ # Short-curcuit evaluation. If we're true, evaluate our statements,
+ # else if there's an 'else' setting, evaluate it.
+ # the first option that matches.
+ def evaluate(scope)
+ level = scope.ephemeral_level
+ value = @test.safeevaluate(scope)
- # let's emulate a new scope for each branches
- begin
- if Puppet::Parser::Scope.true?(value)
- return @statements.safeevaluate(scope)
- else
- return defined?(@else) ? @else.safeevaluate(scope) : nil
- end
- ensure
- scope.unset_ephemeral_var(level)
- end
+ # let's emulate a new scope for each branches
+ begin
+ if Puppet::Parser::Scope.true?(value)
+ return @statements.safeevaluate(scope)
+ else
+ return defined?(@else) ? @else.safeevaluate(scope) : nil
end
+ ensure
+ scope.unset_ephemeral_var(level)
+ end
end
+ end
end
diff --git a/lib/puppet/parser/ast/in_operator.rb b/lib/puppet/parser/ast/in_operator.rb
index 1b17b1006..2a163e726 100644
--- a/lib/puppet/parser/ast/in_operator.rb
+++ b/lib/puppet/parser/ast/in_operator.rb
@@ -2,23 +2,23 @@ require 'puppet'
require 'puppet/parser/ast/branch'
class Puppet::Parser::AST
- class InOperator < AST::Branch
+ class InOperator < AST::Branch
- attr_accessor :lval, :rval
+ attr_accessor :lval, :rval
- # Returns a boolean which is the result of the 'in' operation
- # of lval and rval operands
- def evaluate(scope)
+ # Returns a boolean which is the result of the 'in' operation
+ # of lval and rval operands
+ def evaluate(scope)
- # evaluate the operands, should return a boolean value
- lval = @lval.safeevaluate(scope)
- raise ArgumentError, "'#{lval}' from left operand of 'in' expression is not a string" unless lval.is_a?(::String)
+ # evaluate the operands, should return a boolean value
+ lval = @lval.safeevaluate(scope)
+ raise ArgumentError, "'#{lval}' from left operand of 'in' expression is not a string" unless lval.is_a?(::String)
- rval = @rval.safeevaluate(scope)
- unless rval.respond_to?(:include?)
- raise ArgumentError, "'#{rval}' from right operand of 'in' expression is not of a supported type (string, array or hash)"
- end
- rval.include?(lval)
- end
+ rval = @rval.safeevaluate(scope)
+ unless rval.respond_to?(:include?)
+ raise ArgumentError, "'#{rval}' from right operand of 'in' expression is not of a supported type (string, array or hash)"
+ end
+ rval.include?(lval)
end
+ end
end
diff --git a/lib/puppet/parser/ast/leaf.rb b/lib/puppet/parser/ast/leaf.rb
index a62edc61e..3b9163d9c 100644
--- a/lib/puppet/parser/ast/leaf.rb
+++ b/lib/puppet/parser/ast/leaf.rb
@@ -1,224 +1,224 @@
class Puppet::Parser::AST
- # The base class for all of the leaves of the parse trees. These
- # basically just have types and values. Both of these parameters
- # are simple values, not AST objects.
- class Leaf < AST
- attr_accessor :value, :type
-
- # Return our value.
- def evaluate(scope)
- @value
- end
-
- # evaluate ourselves, and match
- def evaluate_match(value, scope)
- obj = self.safeevaluate(scope)
+ # The base class for all of the leaves of the parse trees. These
+ # basically just have types and values. Both of these parameters
+ # are simple values, not AST objects.
+ class Leaf < AST
+ attr_accessor :value, :type
+
+ # Return our value.
+ def evaluate(scope)
+ @value
+ end
- obj = obj.downcase if obj.respond_to?(:downcase)
- value = value.downcase if value.respond_to?(:downcase)
+ # evaluate ourselves, and match
+ def evaluate_match(value, scope)
+ obj = self.safeevaluate(scope)
- # "" == undef for case/selector/if
- obj == value or (obj == "" and value == :undef)
- end
+ obj = obj.downcase if obj.respond_to?(:downcase)
+ value = value.downcase if value.respond_to?(:downcase)
- def match(value)
- @value == value
- end
+ # "" == undef for case/selector/if
+ obj == value or (obj == "" and value == :undef)
+ end
- def to_s
- @value.to_s unless @value.nil?
- end
+ def match(value)
+ @value == value
end
- # The boolean class. True or false. Converts the string it receives
- # to a Ruby boolean.
- class Boolean < AST::Leaf
+ def to_s
+ @value.to_s unless @value.nil?
+ end
+ end
- # Use the parent method, but then convert to a real boolean.
- def initialize(hash)
- super
+ # The boolean class. True or false. Converts the string it receives
+ # to a Ruby boolean.
+ class Boolean < AST::Leaf
- unless @value == true or @value == false
- raise Puppet::DevError,
- "'#{@value}' is not a boolean"
- end
- @value
- end
+ # Use the parent method, but then convert to a real boolean.
+ def initialize(hash)
+ super
- def to_s
- @value ? "true" : "false"
- end
+ unless @value == true or @value == false
+ raise Puppet::DevError,
+ "'#{@value}' is not a boolean"
+ end
+ @value
end
- # The base string class.
- class String < AST::Leaf
- def evaluate(scope)
- @value
- end
+ def to_s
+ @value ? "true" : "false"
+ end
+ end
- def to_s
- "\"#{@value}\""
- end
+ # The base string class.
+ class String < AST::Leaf
+ def evaluate(scope)
+ @value
end
- # An uninterpreted string.
- class FlatString < AST::Leaf
- def evaluate(scope)
- @value
- end
+ def to_s
+ "\"#{@value}\""
+ end
+ end
- def to_s
- "\"#{@value}\""
- end
+ # An uninterpreted string.
+ class FlatString < AST::Leaf
+ def evaluate(scope)
+ @value
end
- class Concat < AST::Leaf
- def evaluate(scope)
- @value.collect { |x| x.evaluate(scope) }.join
- end
+ def to_s
+ "\"#{@value}\""
+ end
+ end
- def to_s
- "concat(#{@value.join(',')})"
- end
+ class Concat < AST::Leaf
+ def evaluate(scope)
+ @value.collect { |x| x.evaluate(scope) }.join
end
- # The 'default' option on case statements and selectors.
- class Default < AST::Leaf; end
+ def to_s
+ "concat(#{@value.join(',')})"
+ end
+ end
- # Capitalized words; used mostly for type-defaults, but also
- # get returned by the lexer any other time an unquoted capitalized
- # word is found.
- class Type < AST::Leaf; end
+ # The 'default' option on case statements and selectors.
+ class Default < AST::Leaf; end
- # Lower-case words.
- class Name < AST::Leaf; end
+ # Capitalized words; used mostly for type-defaults, but also
+ # get returned by the lexer any other time an unquoted capitalized
+ # word is found.
+ class Type < AST::Leaf; end
- # double-colon separated class names
- class ClassName < AST::Leaf; end
+ # Lower-case words.
+ class Name < AST::Leaf; end
- # undef values; equiv to nil
- class Undef < AST::Leaf; end
+ # double-colon separated class names
+ class ClassName < AST::Leaf; end
- # Host names, either fully qualified or just the short name, or even a regex
- class HostName < AST::Leaf
- def initialize(hash)
- super
+ # undef values; equiv to nil
+ class Undef < AST::Leaf; end
- # Note that this is an AST::Regex, not a Regexp
- @value = @value.to_s.downcase unless @value.is_a?(Regex)
- if @value =~ /[^-\w.]/
- raise Puppet::DevError,
- "'#{@value}' is not a valid hostname"
- end
- end
+ # Host names, either fully qualified or just the short name, or even a regex
+ class HostName < AST::Leaf
+ def initialize(hash)
+ super
- # implementing eql? and hash so that when an HostName is stored
- # in a hash it has the same hashing properties as the underlying value
- def eql?(value)
- value = value.value if value.is_a?(HostName)
- @value.eql?(value)
- end
+ # Note that this is an AST::Regex, not a Regexp
+ @value = @value.to_s.downcase unless @value.is_a?(Regex)
+ if @value =~ /[^-\w.]/
+ raise Puppet::DevError,
+ "'#{@value}' is not a valid hostname"
+ end
+ end
- def hash
- @value.hash
- end
+ # implementing eql? and hash so that when an HostName is stored
+ # in a hash it has the same hashing properties as the underlying value
+ def eql?(value)
+ value = value.value if value.is_a?(HostName)
+ @value.eql?(value)
+ end
- def to_s
- @value.to_s
- end
+ def hash
+ @value.hash
end
- # A simple variable. This object is only used during interpolation;
- # the VarDef class is used for assignment.
- class Variable < Name
- # Looks up the value of the object in the scope tree (does
- # not include syntactical constructs, like '$' and '{}').
- def evaluate(scope)
- parsewrap do
- if (var = scope.lookupvar(@value, false)) == :undefined
- var = :undef
- end
- var
- end
- end
+ def to_s
+ @value.to_s
+ end
+ end
+
+ # A simple variable. This object is only used during interpolation;
+ # the VarDef class is used for assignment.
+ class Variable < Name
+ # Looks up the value of the object in the scope tree (does
+ # not include syntactical constructs, like '$' and '{}').
+ def evaluate(scope)
+ parsewrap do
+ if (var = scope.lookupvar(@value, false)) == :undefined
+ var = :undef
+ end
+ var
+ end
+ end
- def to_s
- "\$#{value}"
- end
+ def to_s
+ "\$#{value}"
end
+ end
- class HashOrArrayAccess < AST::Leaf
- attr_accessor :variable, :key
+ class HashOrArrayAccess < AST::Leaf
+ attr_accessor :variable, :key
- def evaluate_container(scope)
- container = variable.respond_to?(:evaluate) ? variable.safeevaluate(scope) : variable
- (container.is_a?(Hash) or container.is_a?(Array)) ? container : scope.lookupvar(container)
- end
+ def evaluate_container(scope)
+ container = variable.respond_to?(:evaluate) ? variable.safeevaluate(scope) : variable
+ (container.is_a?(Hash) or container.is_a?(Array)) ? container : scope.lookupvar(container)
+ end
- def evaluate_key(scope)
- key.respond_to?(:evaluate) ? key.safeevaluate(scope) : key
- end
+ def evaluate_key(scope)
+ key.respond_to?(:evaluate) ? key.safeevaluate(scope) : key
+ end
- def evaluate(scope)
- object = evaluate_container(scope)
+ def evaluate(scope)
+ object = evaluate_container(scope)
- raise Puppet::ParseError, "#{variable} is not an hash or array when accessing it with #{accesskey}" unless object.is_a?(Hash) or object.is_a?(Array)
+ raise Puppet::ParseError, "#{variable} is not an hash or array when accessing it with #{accesskey}" unless object.is_a?(Hash) or object.is_a?(Array)
- object[evaluate_key(scope)]
- end
+ object[evaluate_key(scope)]
+ end
- # Assign value to this hashkey or array index
- def assign(scope, value)
- object = evaluate_container(scope)
- accesskey = evaluate_key(scope)
+ # Assign value to this hashkey or array index
+ def assign(scope, value)
+ object = evaluate_container(scope)
+ accesskey = evaluate_key(scope)
- if object.is_a?(Hash) and object.include?(accesskey)
- raise Puppet::ParseError, "Assigning to the hash '#{variable}' with an existing key '#{accesskey}' is forbidden"
- end
+ if object.is_a?(Hash) and object.include?(accesskey)
+ raise Puppet::ParseError, "Assigning to the hash '#{variable}' with an existing key '#{accesskey}' is forbidden"
+ end
- # assign to hash or array
- object[accesskey] = value
- end
+ # assign to hash or array
+ object[accesskey] = value
+ end
- def to_s
- "\$#{variable.to_s}[#{key.to_s}]"
- end
+ def to_s
+ "\$#{variable.to_s}[#{key.to_s}]"
end
+ end
- class Regex < AST::Leaf
- def initialize(hash)
- super
- @value = Regexp.new(@value) unless @value.is_a?(Regexp)
- end
+ class Regex < AST::Leaf
+ def initialize(hash)
+ super
+ @value = Regexp.new(@value) unless @value.is_a?(Regexp)
+ end
- # we're returning self here to wrap the regexp and to be used in places
- # where a string would have been used, without modifying any client code.
- # For instance, in many places we have the following code snippet:
- # val = @val.safeevaluate(@scope)
- # if val.match(otherval)
- # ...
- # end
- # this way, we don't have to modify this test specifically for handling
- # regexes.
- def evaluate(scope)
- self
- end
+ # we're returning self here to wrap the regexp and to be used in places
+ # where a string would have been used, without modifying any client code.
+ # For instance, in many places we have the following code snippet:
+ # val = @val.safeevaluate(@scope)
+ # if val.match(otherval)
+ # ...
+ # end
+ # this way, we don't have to modify this test specifically for handling
+ # regexes.
+ def evaluate(scope)
+ self
+ end
- def evaluate_match(value, scope, options = {})
- value = value.is_a?(String) ? value : value.to_s
+ def evaluate_match(value, scope, options = {})
+ value = value.is_a?(String) ? value : value.to_s
- if matched = @value.match(value)
- scope.ephemeral_from(matched, options[:file], options[:line])
- end
- matched
- end
+ if matched = @value.match(value)
+ scope.ephemeral_from(matched, options[:file], options[:line])
+ end
+ matched
+ end
- def match(value)
- @value.match(value)
- end
+ def match(value)
+ @value.match(value)
+ end
- def to_s
- "/#{@value.source}/"
- end
+ def to_s
+ "/#{@value.source}/"
end
+ end
end
diff --git a/lib/puppet/parser/ast/match_operator.rb b/lib/puppet/parser/ast/match_operator.rb
index 2ab2befd4..6207a8c2c 100644
--- a/lib/puppet/parser/ast/match_operator.rb
+++ b/lib/puppet/parser/ast/match_operator.rb
@@ -2,27 +2,27 @@ require 'puppet'
require 'puppet/parser/ast/branch'
class Puppet::Parser::AST
- class MatchOperator < AST::Branch
+ class MatchOperator < AST::Branch
- attr_accessor :lval, :rval, :operator
+ attr_accessor :lval, :rval, :operator
- # Iterate across all of our children.
- def each
- [@lval,@rval].each { |child| yield child }
- end
+ # Iterate across all of our children.
+ def each
+ [@lval,@rval].each { |child| yield child }
+ end
- # Returns a boolean which is the result of the boolean operation
- # of lval and rval operands
- def evaluate(scope)
- lval = @lval.safeevaluate(scope)
+ # Returns a boolean which is the result of the boolean operation
+ # of lval and rval operands
+ def evaluate(scope)
+ lval = @lval.safeevaluate(scope)
- return(rval.evaluate_match(lval, scope) ? @operator == "=~" : @operator == "!~")
- end
+ return(rval.evaluate_match(lval, scope) ? @operator == "=~" : @operator == "!~")
+ end
- def initialize(hash)
- super
+ def initialize(hash)
+ super
- raise ArgumentError, "Invalid regexp operator #{@operator}" unless %w{!~ =~}.include?(@operator)
- end
+ raise ArgumentError, "Invalid regexp operator #{@operator}" unless %w{!~ =~}.include?(@operator)
end
+ end
end
diff --git a/lib/puppet/parser/ast/minus.rb b/lib/puppet/parser/ast/minus.rb
index 40f64336c..d7a362aa1 100644
--- a/lib/puppet/parser/ast/minus.rb
+++ b/lib/puppet/parser/ast/minus.rb
@@ -4,20 +4,20 @@ require 'puppet/parser/ast/branch'
# An object that returns a boolean which is the boolean not
# of the given value.
class Puppet::Parser::AST
- class Minus < AST::Branch
- attr_accessor :value
+ class Minus < AST::Branch
+ attr_accessor :value
- def each
- yield @value
- end
+ def each
+ yield @value
+ end
- def evaluate(scope)
- val = @value.safeevaluate(scope)
- val = Puppet::Parser::Scope.number?(val)
- if val == nil
- raise ArgumentError, "minus operand #{val} is not a number"
- end
- -val
- end
+ def evaluate(scope)
+ val = @value.safeevaluate(scope)
+ val = Puppet::Parser::Scope.number?(val)
+ if val == nil
+ raise ArgumentError, "minus operand #{val} is not a number"
+ end
+ -val
end
+ end
end
diff --git a/lib/puppet/parser/ast/nop.rb b/lib/puppet/parser/ast/nop.rb
index ea5232043..bf35c6a5c 100644
--- a/lib/puppet/parser/ast/nop.rb
+++ b/lib/puppet/parser/ast/nop.rb
@@ -1,11 +1,11 @@
require 'puppet/parser/ast/branch'
class Puppet::Parser::AST
- # This class is a no-op, it doesn't produce anything
- # when evaluated, hence it's name :-)
- class Nop < AST::Leaf
- def evaluate(scope)
- # nothing to do
- end
+ # This class is a no-op, it doesn't produce anything
+ # when evaluated, hence it's name :-)
+ class Nop < AST::Leaf
+ def evaluate(scope)
+ # nothing to do
end
+ end
end
diff --git a/lib/puppet/parser/ast/not.rb b/lib/puppet/parser/ast/not.rb
index 24d5e838b..30fa6d503 100644
--- a/lib/puppet/parser/ast/not.rb
+++ b/lib/puppet/parser/ast/not.rb
@@ -4,16 +4,16 @@ require 'puppet/parser/ast/branch'
# An object that returns a boolean which is the boolean not
# of the given value.
class Puppet::Parser::AST
- class Not < AST::Branch
- attr_accessor :value
+ class Not < AST::Branch
+ attr_accessor :value
- def each
- yield @value
- end
+ def each
+ yield @value
+ end
- def evaluate(scope)
- val = @value.safeevaluate(scope)
- ! Puppet::Parser::Scope.true?(val)
- end
+ def evaluate(scope)
+ val = @value.safeevaluate(scope)
+ ! Puppet::Parser::Scope.true?(val)
end
+ end
end
diff --git a/lib/puppet/parser/ast/relationship.rb b/lib/puppet/parser/ast/relationship.rb
index 9f9f6fc1d..a7134a04f 100644
--- a/lib/puppet/parser/ast/relationship.rb
+++ b/lib/puppet/parser/ast/relationship.rb
@@ -3,58 +3,58 @@ require 'puppet/parser/ast/branch'
require 'puppet/parser/relationship'
class Puppet::Parser::AST::Relationship < Puppet::Parser::AST::Branch
- RELATIONSHIP_TYPES = %w{-> <- ~> <~}
+ RELATIONSHIP_TYPES = %w{-> <- ~> <~}
- attr_accessor :left, :right, :arrow, :type
+ attr_accessor :left, :right, :arrow, :type
- def actual_left
- chained? ? left.right : left
- end
+ def actual_left
+ chained? ? left.right : left
+ end
- # Evaluate our object, but just return a simple array of the type
- # and name.
- def evaluate(scope)
- if chained?
- real_left = left.safeevaluate(scope)
- left_dep = left_dep.shift if left_dep.is_a?(Array)
- else
- real_left = left.safeevaluate(scope)
- end
- real_right = right.safeevaluate(scope)
-
- source, target = sides2edge(real_left, real_right)
- result = Puppet::Parser::Relationship.new(source, target, type)
- scope.compiler.add_relationship(result)
- real_right
+ # Evaluate our object, but just return a simple array of the type
+ # and name.
+ def evaluate(scope)
+ if chained?
+ real_left = left.safeevaluate(scope)
+ left_dep = left_dep.shift if left_dep.is_a?(Array)
+ else
+ real_left = left.safeevaluate(scope)
end
+ real_right = right.safeevaluate(scope)
- def initialize(left, right, arrow, args = {})
- super(args)
- unless RELATIONSHIP_TYPES.include?(arrow)
- raise ArgumentError, "Invalid relationship type #{arrow.inspect}; valid types are #{RELATIONSHIP_TYPES.collect { |r| r.to_s }.join(", ")}"
- end
- @left, @right, @arrow = left, right, arrow
- end
+ source, target = sides2edge(real_left, real_right)
+ result = Puppet::Parser::Relationship.new(source, target, type)
+ scope.compiler.add_relationship(result)
+ real_right
+ end
- def type
- subscription? ? :subscription : :relationship
+ def initialize(left, right, arrow, args = {})
+ super(args)
+ unless RELATIONSHIP_TYPES.include?(arrow)
+ raise ArgumentError, "Invalid relationship type #{arrow.inspect}; valid types are #{RELATIONSHIP_TYPES.collect { |r| r.to_s }.join(", ")}"
end
+ @left, @right, @arrow = left, right, arrow
+ end
- def sides2edge(left, right)
- out_edge? ? [left, right] : [right, left]
- end
+ def type
+ subscription? ? :subscription : :relationship
+ end
- private
+ def sides2edge(left, right)
+ out_edge? ? [left, right] : [right, left]
+ end
- def chained?
- left.is_a?(self.class)
- end
+ private
- def out_edge?
- ["->", "~>"].include?(arrow)
- end
+ def chained?
+ left.is_a?(self.class)
+ end
- def subscription?
- ["~>", "<~"].include?(arrow)
- end
+ def out_edge?
+ ["->", "~>"].include?(arrow)
+ end
+
+ def subscription?
+ ["~>", "<~"].include?(arrow)
+ end
end
diff --git a/lib/puppet/parser/ast/resource.rb b/lib/puppet/parser/ast/resource.rb
index 01b9370ff..1b063c984 100644
--- a/lib/puppet/parser/ast/resource.rb
+++ b/lib/puppet/parser/ast/resource.rb
@@ -5,73 +5,73 @@ require 'puppet/parser/ast/resource_reference'
class Puppet::Parser::AST
class Resource < AST::ResourceReference
- associates_doc
+ associates_doc
- attr_accessor :title, :type, :exported, :virtual
- attr_reader :parameters
+ attr_accessor :title, :type, :exported, :virtual
+ attr_reader :parameters
- # Does not actually return an object; instead sets an object
- # in the current scope.
- def evaluate(scope)
- # Evaluate all of the specified params.
- paramobjects = parameters.collect { |param|
- param.safeevaluate(scope)
- }
+ # Does not actually return an object; instead sets an object
+ # in the current scope.
+ def evaluate(scope)
+ # Evaluate all of the specified params.
+ paramobjects = parameters.collect { |param|
+ param.safeevaluate(scope)
+ }
- resource_titles = @title.safeevaluate(scope)
+ resource_titles = @title.safeevaluate(scope)
- # it's easier to always use an array, even for only one name
- resource_titles = [resource_titles] unless resource_titles.is_a?(Array)
+ # it's easier to always use an array, even for only one name
+ resource_titles = [resource_titles] unless resource_titles.is_a?(Array)
- # We want virtual to be true if exported is true. We can't
- # just set :virtual => self.virtual in the initialization,
- # because sometimes the :virtual attribute is set *after*
- # :exported, in which case it clobbers :exported if :exported
- # is true. Argh, this was a very tough one to track down.
- virt = self.virtual || self.exported
+ # We want virtual to be true if exported is true. We can't
+ # just set :virtual => self.virtual in the initialization,
+ # because sometimes the :virtual attribute is set *after*
+ # :exported, in which case it clobbers :exported if :exported
+ # is true. Argh, this was a very tough one to track down.
+ virt = self.virtual || self.exported
- # This is where our implicit iteration takes place; if someone
- # passed an array as the name, then we act just like the called us
- # many times.
- resource_titles.flatten.collect { |resource_title|
- exceptwrap :type => Puppet::ParseError do
+ # This is where our implicit iteration takes place; if someone
+ # passed an array as the name, then we act just like the called us
+ # many times.
+ resource_titles.flatten.collect { |resource_title|
+ exceptwrap :type => Puppet::ParseError do
- resource = Puppet::Parser::Resource.new(
- type, resource_title,
- :parameters => paramobjects,
- :file => self.file,
- :line => self.line,
- :exported => self.exported,
- :virtual => virt,
- :source => scope.source,
- :scope => scope,
+ resource = Puppet::Parser::Resource.new(
+ type, resource_title,
+ :parameters => paramobjects,
+ :file => self.file,
+ :line => self.line,
+ :exported => self.exported,
+ :virtual => virt,
+ :source => scope.source,
+ :scope => scope,
- :strict => true
- )
+ :strict => true
+ )
- # And then store the resource in the compiler.
- # At some point, we need to switch all of this to return
- # resources instead of storing them like this.
- scope.compiler.add_resource(scope, resource)
- resource
- end
- }.reject { |resource| resource.nil? }
- end
+ # And then store the resource in the compiler.
+ # At some point, we need to switch all of this to return
+ # resources instead of storing them like this.
+ scope.compiler.add_resource(scope, resource)
+ resource
+ end
+ }.reject { |resource| resource.nil? }
+ end
- # Set the parameters for our object.
- def parameters=(params)
- if params.is_a?(AST::ASTArray)
- @parameters = params
- else
+ # Set the parameters for our object.
+ def parameters=(params)
+ if params.is_a?(AST::ASTArray)
+ @parameters = params
+ else
- @parameters = AST::ASTArray.new(
+ @parameters = AST::ASTArray.new(
- :line => params.line,
- :file => params.file,
+ :line => params.line,
+ :file => params.file,
- :children => [params]
- )
- end
+ :children => [params]
+ )
end
+ end
end
end
diff --git a/lib/puppet/parser/ast/resource_defaults.rb b/lib/puppet/parser/ast/resource_defaults.rb
index aec86d02d..812b979e9 100644
--- a/lib/puppet/parser/ast/resource_defaults.rb
+++ b/lib/puppet/parser/ast/resource_defaults.rb
@@ -1,24 +1,24 @@
require 'puppet/parser/ast/branch'
class Puppet::Parser::AST
- # A statement syntactically similar to an ResourceDef, but uses a
- # capitalized object type and cannot have a name.
- class ResourceDefaults < AST::Branch
- attr_accessor :type, :parameters
+ # A statement syntactically similar to an ResourceDef, but uses a
+ # capitalized object type and cannot have a name.
+ class ResourceDefaults < AST::Branch
+ attr_accessor :type, :parameters
- associates_doc
+ associates_doc
- # As opposed to ResourceDef, this stores each default for the given
- # object type.
- def evaluate(scope)
- # Use a resource reference to canonize the type
- ref = Puppet::Resource.new(@type, "whatever")
- type = ref.type
- params = @parameters.safeevaluate(scope)
+ # As opposed to ResourceDef, this stores each default for the given
+ # object type.
+ def evaluate(scope)
+ # Use a resource reference to canonize the type
+ ref = Puppet::Resource.new(@type, "whatever")
+ type = ref.type
+ params = @parameters.safeevaluate(scope)
- parsewrap do
- scope.setdefaults(type, params)
- end
- end
+ parsewrap do
+ scope.setdefaults(type, params)
+ end
end
+ end
end
diff --git a/lib/puppet/parser/ast/resource_override.rb b/lib/puppet/parser/ast/resource_override.rb
index 7f7047dd9..e0be889ff 100644
--- a/lib/puppet/parser/ast/resource_override.rb
+++ b/lib/puppet/parser/ast/resource_override.rb
@@ -1,68 +1,68 @@
require 'puppet/parser/ast/resource'
class Puppet::Parser::AST
- # Set a parameter on a resource specification created somewhere else in the
- # configuration. The object is responsible for verifying that this is allowed.
- class ResourceOverride < Resource
+ # Set a parameter on a resource specification created somewhere else in the
+ # configuration. The object is responsible for verifying that this is allowed.
+ class ResourceOverride < Resource
- associates_doc
+ associates_doc
- attr_accessor :object
- attr_reader :parameters
+ attr_accessor :object
+ attr_reader :parameters
- # Iterate across all of our children.
- def each
- [@object,@parameters].flatten.each { |param|
- #Puppet.debug("yielding param #{param}")
- yield param
- }
- end
+ # Iterate across all of our children.
+ def each
+ [@object,@parameters].flatten.each { |param|
+ #Puppet.debug("yielding param #{param}")
+ yield param
+ }
+ end
- # Does not actually return an object; instead sets an object
- # in the current scope.
- def evaluate(scope)
- # Get our object reference.
- resource = @object.safeevaluate(scope)
+ # Does not actually return an object; instead sets an object
+ # in the current scope.
+ def evaluate(scope)
+ # Get our object reference.
+ resource = @object.safeevaluate(scope)
- hash = {}
+ hash = {}
- # Evaluate all of the specified params.
- params = @parameters.collect { |param|
- param.safeevaluate(scope)
- }
+ # Evaluate all of the specified params.
+ params = @parameters.collect { |param|
+ param.safeevaluate(scope)
+ }
- # Now we just create a normal resource, but we call a very different
- # method on the scope.
- resource = [resource] unless resource.is_a?(Array)
+ # Now we just create a normal resource, but we call a very different
+ # method on the scope.
+ resource = [resource] unless resource.is_a?(Array)
- resource = resource.collect do |r|
+ resource = resource.collect do |r|
- res = Puppet::Parser::Resource.new(
- r.type, r.title,
- :parameters => params,
- :file => file,
- :line => line,
- :source => scope.source,
+ res = Puppet::Parser::Resource.new(
+ r.type, r.title,
+ :parameters => params,
+ :file => file,
+ :line => line,
+ :source => scope.source,
- :scope => scope
- )
+ :scope => scope
+ )
- # Now we tell the scope that it's an override, and it behaves as
- # necessary.
- scope.compiler.add_override(res)
+ # Now we tell the scope that it's an override, and it behaves as
+ # necessary.
+ scope.compiler.add_override(res)
- res
- end
- # decapsulate array in case of only one item
- return(resource.length == 1 ? resource.pop : resource)
- end
+ res
+ end
+ # decapsulate array in case of only one item
+ return(resource.length == 1 ? resource.pop : resource)
+ end
- # Create our ResourceDef. Handles type checking for us.
- def initialize(hash)
- @checked = false
- super
+ # Create our ResourceDef. Handles type checking for us.
+ def initialize(hash)
+ @checked = false
+ super
- #self.typecheck(@type.value)
- end
+ #self.typecheck(@type.value)
end
+ end
end
diff --git a/lib/puppet/parser/ast/resource_reference.rb b/lib/puppet/parser/ast/resource_reference.rb
index 37e82d568..5d8334335 100644
--- a/lib/puppet/parser/ast/resource_reference.rb
+++ b/lib/puppet/parser/ast/resource_reference.rb
@@ -2,20 +2,20 @@ require 'puppet/parser/ast'
require 'puppet/parser/ast/branch'
class Puppet::Parser::AST::ResourceReference < Puppet::Parser::AST::Branch
- attr_accessor :title, :type
+ attr_accessor :title, :type
- # Evaluate our object, but just return a simple array of the type
- # and name.
- def evaluate(scope)
- titles = Array(title.safeevaluate(scope)).collect { |t| Puppet::Resource.new(type, t, :namespaces => scope.namespaces) }
- return(titles.length == 1 ? titles.pop : titles)
- end
+ # Evaluate our object, but just return a simple array of the type
+ # and name.
+ def evaluate(scope)
+ titles = Array(title.safeevaluate(scope)).collect { |t| Puppet::Resource.new(type, t, :namespaces => scope.namespaces) }
+ return(titles.length == 1 ? titles.pop : titles)
+ end
- def to_s
- if title.is_a?(Puppet::Parser::AST::ASTArray)
- "#{type.to_s.capitalize}#{title}"
- else
- "#{type.to_s.capitalize}[#{title}]"
- end
+ def to_s
+ if title.is_a?(Puppet::Parser::AST::ASTArray)
+ "#{type.to_s.capitalize}#{title}"
+ else
+ "#{type.to_s.capitalize}[#{title}]"
end
+ end
end
diff --git a/lib/puppet/parser/ast/resourceparam.rb b/lib/puppet/parser/ast/resourceparam.rb
index bf0a2258b..4073a197b 100644
--- a/lib/puppet/parser/ast/resourceparam.rb
+++ b/lib/puppet/parser/ast/resourceparam.rb
@@ -1,29 +1,29 @@
require 'puppet/parser/ast/branch'
class Puppet::Parser::AST
- # The AST object for the parameters inside ResourceDefs and Selectors.
- class ResourceParam < AST::Branch
- attr_accessor :value, :param, :add
+ # The AST object for the parameters inside ResourceDefs and Selectors.
+ class ResourceParam < AST::Branch
+ attr_accessor :value, :param, :add
- def each
- [@param,@value].each { |child| yield child }
- end
+ def each
+ [@param,@value].each { |child| yield child }
+ end
- # Return the parameter and the value.
- def evaluate(scope)
+ # Return the parameter and the value.
+ def evaluate(scope)
- return Puppet::Parser::Resource::Param.new(
+ return Puppet::Parser::Resource::Param.new(
- :name => @param,
- :value => @value.safeevaluate(scope),
+ :name => @param,
+ :value => @value.safeevaluate(scope),
- :source => scope.source, :line => self.line, :file => self.file,
- :add => self.add
- )
- end
+ :source => scope.source, :line => self.line, :file => self.file,
+ :add => self.add
+ )
+ end
- def to_s
- "#{@param} => #{@value.to_s}"
- end
+ def to_s
+ "#{@param} => #{@value.to_s}"
end
+ end
end
diff --git a/lib/puppet/parser/ast/selector.rb b/lib/puppet/parser/ast/selector.rb
index cf6b8ac19..d6a4ea436 100644
--- a/lib/puppet/parser/ast/selector.rb
+++ b/lib/puppet/parser/ast/selector.rb
@@ -1,44 +1,44 @@
require 'puppet/parser/ast/branch'
class Puppet::Parser::AST
- # The inline conditional operator. Unlike CaseStatement, which executes
- # code, we just return a value.
- class Selector < AST::Branch
- attr_accessor :param, :values
+ # The inline conditional operator. Unlike CaseStatement, which executes
+ # code, we just return a value.
+ class Selector < AST::Branch
+ attr_accessor :param, :values
- def each
- [@param,@values].each { |child| yield child }
- end
+ def each
+ [@param,@values].each { |child| yield child }
+ end
- # Find the value that corresponds with the test.
- def evaluate(scope)
- level = scope.ephemeral_level
- # Get our parameter.
- paramvalue = @param.safeevaluate(scope)
+ # Find the value that corresponds with the test.
+ def evaluate(scope)
+ level = scope.ephemeral_level
+ # Get our parameter.
+ paramvalue = @param.safeevaluate(scope)
- default = nil
+ default = nil
- @values = [@values] unless @values.instance_of? AST::ASTArray or @values.instance_of? Array
+ @values = [@values] unless @values.instance_of? AST::ASTArray or @values.instance_of? Array
- # Then look for a match in the options.
- @values.each do |obj|
- # short circuit asap if we have a match
- return obj.value.safeevaluate(scope) if obj.param.evaluate_match(paramvalue, scope)
+ # Then look for a match in the options.
+ @values.each do |obj|
+ # short circuit asap if we have a match
+ return obj.value.safeevaluate(scope) if obj.param.evaluate_match(paramvalue, scope)
- # Store the default, in case it's necessary.
- default = obj if obj.param.is_a?(Default)
- end
+ # Store the default, in case it's necessary.
+ default = obj if obj.param.is_a?(Default)
+ end
- # Unless we found something, look for the default.
- return default.value.safeevaluate(scope) if default
+ # Unless we found something, look for the default.
+ return default.value.safeevaluate(scope) if default
- self.fail Puppet::ParseError, "No matching value for selector param '#{paramvalue}'"
- ensure
- scope.unset_ephemeral_var(level)
- end
+ self.fail Puppet::ParseError, "No matching value for selector param '#{paramvalue}'"
+ ensure
+ scope.unset_ephemeral_var(level)
+ end
- def to_s
- param.to_s + " ? { " + values.collect { |v| v.to_s }.join(', ') + " }"
- end
+ def to_s
+ param.to_s + " ? { " + values.collect { |v| v.to_s }.join(', ') + " }"
end
+ end
end
diff --git a/lib/puppet/parser/ast/tag.rb b/lib/puppet/parser/ast/tag.rb
index 2909504a7..6f906a1c6 100644
--- a/lib/puppet/parser/ast/tag.rb
+++ b/lib/puppet/parser/ast/tag.rb
@@ -1,24 +1,24 @@
require 'puppet/parser/ast/branch'
class Puppet::Parser::AST
- # The code associated with a class. This is different from components
- # in that each class is a singleton -- only one will exist for a given
- # node.
- class Tag < AST::Branch
- @name = :class
- attr_accessor :type
+ # The code associated with a class. This is different from components
+ # in that each class is a singleton -- only one will exist for a given
+ # node.
+ class Tag < AST::Branch
+ @name = :class
+ attr_accessor :type
- def evaluate(scope)
- types = @type.safeevaluate(scope)
+ def evaluate(scope)
+ types = @type.safeevaluate(scope)
- types = [types] unless types.is_a? Array
+ types = [types] unless types.is_a? Array
- types.each do |type|
- # Now set our class. We don't have to worry about checking
- # whether we've been evaluated because we're not evaluating
- # any code.
- scope.setclass(self.object_id, type)
- end
- end
+ types.each do |type|
+ # Now set our class. We don't have to worry about checking
+ # whether we've been evaluated because we're not evaluating
+ # any code.
+ scope.setclass(self.object_id, type)
+ end
end
+ end
end
diff --git a/lib/puppet/parser/ast/vardef.rb b/lib/puppet/parser/ast/vardef.rb
index f103d49c3..6de1860c8 100644
--- a/lib/puppet/parser/ast/vardef.rb
+++ b/lib/puppet/parser/ast/vardef.rb
@@ -1,33 +1,33 @@
require 'puppet/parser/ast/branch'
class Puppet::Parser::AST
- # Define a variable. Stores the value in the current scope.
- class VarDef < AST::Branch
+ # Define a variable. Stores the value in the current scope.
+ class VarDef < AST::Branch
- associates_doc
+ associates_doc
- attr_accessor :name, :value, :append
+ attr_accessor :name, :value, :append
- @settor = true
+ @settor = true
- # Look up our name and value, and store them appropriately. The
- # lexer strips off the syntax stuff like '$'.
- def evaluate(scope)
- value = @value.safeevaluate(scope)
- if name.is_a?(HashOrArrayAccess)
- name.assign(scope, value)
- else
- name = @name.safeevaluate(scope)
+ # Look up our name and value, and store them appropriately. The
+ # lexer strips off the syntax stuff like '$'.
+ def evaluate(scope)
+ value = @value.safeevaluate(scope)
+ if name.is_a?(HashOrArrayAccess)
+ name.assign(scope, value)
+ else
+ name = @name.safeevaluate(scope)
- parsewrap do
- scope.setvar(name,value, :file => @file, :line => @line, :append => @append)
- end
- end
+ parsewrap do
+ scope.setvar(name,value, :file => @file, :line => @line, :append => @append)
end
+ end
+ end
- def each
- [@name,@value].each { |child| yield child }
- end
+ def each
+ [@name,@value].each { |child| yield child }
end
+ end
end
diff --git a/lib/puppet/parser/collector.rb b/lib/puppet/parser/collector.rb
index c03add304..de60cb170 100644
--- a/lib/puppet/parser/collector.rb
+++ b/lib/puppet/parser/collector.rb
@@ -1,223 +1,223 @@
# An object that collects stored objects from the central cache and returns
# them to the current host, yo.
class Puppet::Parser::Collector
- attr_accessor :type, :scope, :vquery, :equery, :form, :resources, :overrides, :collected
-
- # Call the collection method, mark all of the returned objects as non-virtual,
- # optionally applying parameter overrides. The collector can also delete himself
- # from the compiler if there is no more resources to collect (valid only for resource fixed-set collector
- # which get their resources from +collect_resources+ and not from the catalog)
- def evaluate
- # Shortcut if we're not using storeconfigs and they're trying to collect
- # exported resources.
- if form == :exported and Puppet[:storeconfigs] != true
- Puppet.warning "Not collecting exported resources without storeconfigs"
- return false
- end
+ attr_accessor :type, :scope, :vquery, :equery, :form, :resources, :overrides, :collected
+
+ # Call the collection method, mark all of the returned objects as non-virtual,
+ # optionally applying parameter overrides. The collector can also delete himself
+ # from the compiler if there is no more resources to collect (valid only for resource fixed-set collector
+ # which get their resources from +collect_resources+ and not from the catalog)
+ def evaluate
+ # Shortcut if we're not using storeconfigs and they're trying to collect
+ # exported resources.
+ if form == :exported and Puppet[:storeconfigs] != true
+ Puppet.warning "Not collecting exported resources without storeconfigs"
+ return false
+ end
- if self.resources
- unless objects = collect_resources and ! objects.empty?
- return false
- end
- else
- method = "collect_#{@form.to_s}"
- objects = send(method).each do |obj|
- obj.virtual = false
- end
- return false if objects.empty?
- end
+ if self.resources
+ unless objects = collect_resources and ! objects.empty?
+ return false
+ end
+ else
+ method = "collect_#{@form.to_s}"
+ objects = send(method).each do |obj|
+ obj.virtual = false
+ end
+ return false if objects.empty?
+ end
- # we have an override for the collected resources
- if @overrides and !objects.empty?
-
- # force the resource to be always child of any other resource
- overrides[:source].meta_def(:child_of?) do
- true
- end
-
- # tell the compiler we have some override for him unless we already
- # overrided those resources
- objects.each do |res|
- unless @collected.include?(res.ref)
-
- newres = Puppet::Parser::Resource.new(
- res.type, res.title,
- :parameters => overrides[:parameters],
- :file => overrides[:file],
- :line => overrides[:line],
- :source => overrides[:source],
+ # we have an override for the collected resources
+ if @overrides and !objects.empty?
+
+ # force the resource to be always child of any other resource
+ overrides[:source].meta_def(:child_of?) do
+ true
+ end
+
+ # tell the compiler we have some override for him unless we already
+ # overrided those resources
+ objects.each do |res|
+ unless @collected.include?(res.ref)
+
+ newres = Puppet::Parser::Resource.new(
+ res.type, res.title,
+ :parameters => overrides[:parameters],
+ :file => overrides[:file],
+ :line => overrides[:line],
+ :source => overrides[:source],
- :scope => overrides[:scope]
- )
+ :scope => overrides[:scope]
+ )
- scope.compiler.add_override(newres)
- end
- end
+ scope.compiler.add_override(newres)
end
+ end
+ end
- # filter out object that already have been collected by ourself
- objects.reject! { |o| @collected.include?(o.ref) }
+ # filter out object that already have been collected by ourself
+ objects.reject! { |o| @collected.include?(o.ref) }
- return false if objects.empty?
+ return false if objects.empty?
- # keep an eye on the resources we have collected
- objects.inject(@collected) { |c,o| c[o.ref]=o; c }
+ # keep an eye on the resources we have collected
+ objects.inject(@collected) { |c,o| c[o.ref]=o; c }
- # return our newly collected resources
- objects
- end
+ # return our newly collected resources
+ objects
+ end
- def initialize(scope, type, equery, vquery, form)
- @scope = scope
+ def initialize(scope, type, equery, vquery, form)
+ @scope = scope
- # initialisation
- @collected = {}
+ # initialisation
+ @collected = {}
- # Canonize the type
- @type = Puppet::Resource.new(type, "whatever").type
- @equery = equery
- @vquery = vquery
+ # Canonize the type
+ @type = Puppet::Resource.new(type, "whatever").type
+ @equery = equery
+ @vquery = vquery
- raise(ArgumentError, "Invalid query form #{form}") unless [:exported, :virtual].include?(form)
- @form = form
- end
+ raise(ArgumentError, "Invalid query form #{form}") unless [:exported, :virtual].include?(form)
+ @form = form
+ end
- # add a resource override to the soon to be exported/realized resources
- def add_override(hash)
- raise ArgumentError, "Exported resource try to override without parameters" unless hash[:parameters]
+ # add a resource override to the soon to be exported/realized resources
+ def add_override(hash)
+ raise ArgumentError, "Exported resource try to override without parameters" unless hash[:parameters]
- # schedule an override for an upcoming collection
- @overrides = hash
- end
-
- private
-
- # Create our active record query.
- def build_active_record_query
- Puppet::Rails.init unless ActiveRecord::Base.connected?
-
- raise Puppet::DevError, "Cannot collect resources for a nil host" unless @scope.host
- host = Puppet::Rails::Host.find_by_name(@scope.host)
-
- search = "(exported=? AND restype=?)"
- values = [true, @type]
-
- search += " AND (#{@equery})" if @equery
-
- # note:
- # we're not eagerly including any relations here because
- # it can creates so much objects we'll throw out later.
- # We used to eagerly include param_names/values but the way
- # the search filter is built ruined those efforts and we
- # were eagerly loading only the searched parameter and not
- # the other ones.
- query = {}
- case search
- when /puppet_tags/
- query = {:joins => {:resource_tags => :puppet_tag}}
- when /param_name/
- query = {:joins => {:param_values => :param_name}}
- end
+ # schedule an override for an upcoming collection
+ @overrides = hash
+ end
- # We're going to collect objects from rails, but we don't want any
- # objects from this host.
- search = ("host_id != ? AND #{search}") and values.unshift(host.id) if host
+ private
- query[:conditions] = [search, *values]
+ # Create our active record query.
+ def build_active_record_query
+ Puppet::Rails.init unless ActiveRecord::Base.connected?
- query
- end
+ raise Puppet::DevError, "Cannot collect resources for a nil host" unless @scope.host
+ host = Puppet::Rails::Host.find_by_name(@scope.host)
- # Collect exported objects.
- def collect_exported
- # First get everything from the export table. Just reuse our
- # collect_virtual method but tell it to use 'exported? for the test.
- resources = collect_virtual(true).reject { |r| ! r.virtual? }
-
- count = resources.length
-
- query = build_active_record_query
-
- # Now look them up in the rails db. When we support attribute comparison
- # and such, we'll need to vary the conditions, but this works with no
- # attributes, anyway.
- time = Puppet::Util.thinmark do
- Puppet::Rails::Resource.find(:all, query).each do |obj|
- if resource = exported_resource(obj)
- count += 1
- resources << resource
- end
- end
- end
+ search = "(exported=? AND restype=?)"
+ values = [true, @type]
- scope.debug("Collected %s %s resource%s in %.2f seconds" % [count, @type, count == 1 ? "" : "s", time])
+ search += " AND (#{@equery})" if @equery
- resources
+ # note:
+ # we're not eagerly including any relations here because
+ # it can creates so much objects we'll throw out later.
+ # We used to eagerly include param_names/values but the way
+ # the search filter is built ruined those efforts and we
+ # were eagerly loading only the searched parameter and not
+ # the other ones.
+ query = {}
+ case search
+ when /puppet_tags/
+ query = {:joins => {:resource_tags => :puppet_tag}}
+ when /param_name/
+ query = {:joins => {:param_values => :param_name}}
end
- def collect_resources
- @resources = [@resources] unless @resources.is_a?(Array)
- method = "collect_#{form.to_s}_resources"
- send(method)
- end
+ # We're going to collect objects from rails, but we don't want any
+ # objects from this host.
+ search = ("host_id != ? AND #{search}") and values.unshift(host.id) if host
- def collect_exported_resources
- raise Puppet::ParseError, "realize() is not yet implemented for exported resources"
- end
+ query[:conditions] = [search, *values]
- # Collect resources directly; this is the result of using 'realize',
- # which specifies resources, rather than using a normal collection.
- def collect_virtual_resources
- return [] unless defined?(@resources) and ! @resources.empty?
- result = @resources.dup.collect do |ref|
- if res = @scope.findresource(ref.to_s)
- @resources.delete(ref)
- res
- end
- end.reject { |r| r.nil? }.each do |res|
- res.virtual = false
- end
+ query
+ end
- # If there are no more resources to find, delete this from the list
- # of collections.
- @scope.compiler.delete_collection(self) if @resources.empty?
+ # Collect exported objects.
+ def collect_exported
+ # First get everything from the export table. Just reuse our
+ # collect_virtual method but tell it to use 'exported? for the test.
+ resources = collect_virtual(true).reject { |r| ! r.virtual? }
- result
- end
+ count = resources.length
- # Collect just virtual objects, from our local compiler.
- def collect_virtual(exported = false)
- scope.compiler.resources.find_all do |resource|
- resource.type == @type and (exported ? resource.exported? : true) and match?(resource)
+ query = build_active_record_query
+
+ # Now look them up in the rails db. When we support attribute comparison
+ # and such, we'll need to vary the conditions, but this works with no
+ # attributes, anyway.
+ time = Puppet::Util.thinmark do
+ Puppet::Rails::Resource.find(:all, query).each do |obj|
+ if resource = exported_resource(obj)
+ count += 1
+ resources << resource
end
+ end
end
- # Seek a specific exported resource.
- def exported_resource(obj)
- if existing = @scope.findresource(obj.restype, obj.title)
- # Next see if we've already collected this resource
- return nil if existing.rails_id == obj.id
+ scope.debug("Collected %s %s resource%s in %.2f seconds" % [count, @type, count == 1 ? "" : "s", time])
+
+ resources
+ end
+
+ def collect_resources
+ @resources = [@resources] unless @resources.is_a?(Array)
+ method = "collect_#{form.to_s}_resources"
+ send(method)
+ end
+
+ def collect_exported_resources
+ raise Puppet::ParseError, "realize() is not yet implemented for exported resources"
+ end
+
+ # Collect resources directly; this is the result of using 'realize',
+ # which specifies resources, rather than using a normal collection.
+ def collect_virtual_resources
+ return [] unless defined?(@resources) and ! @resources.empty?
+ result = @resources.dup.collect do |ref|
+ if res = @scope.findresource(ref.to_s)
+ @resources.delete(ref)
+ res
+ end
+ end.reject { |r| r.nil? }.each do |res|
+ res.virtual = false
+ end
- # This is the one we've already collected
- raise Puppet::ParseError, "Exported resource #{obj.ref} cannot override local resource"
- end
+ # If there are no more resources to find, delete this from the list
+ # of collections.
+ @scope.compiler.delete_collection(self) if @resources.empty?
- resource = obj.to_resource(self.scope)
+ result
+ end
- resource.exported = false
+ # Collect just virtual objects, from our local compiler.
+ def collect_virtual(exported = false)
+ scope.compiler.resources.find_all do |resource|
+ resource.type == @type and (exported ? resource.exported? : true) and match?(resource)
+ end
+ end
- scope.compiler.add_resource(scope, resource)
+ # Seek a specific exported resource.
+ def exported_resource(obj)
+ if existing = @scope.findresource(obj.restype, obj.title)
+ # Next see if we've already collected this resource
+ return nil if existing.rails_id == obj.id
- resource
+ # This is the one we've already collected
+ raise Puppet::ParseError, "Exported resource #{obj.ref} cannot override local resource"
end
- # Does the resource match our tests? We don't yet support tests,
- # so it's always true at the moment.
- def match?(resource)
- if self.vquery
- return self.vquery.call(resource)
- else
- return true
- end
+ resource = obj.to_resource(self.scope)
+
+ resource.exported = false
+
+ scope.compiler.add_resource(scope, resource)
+
+ resource
+ end
+
+ # Does the resource match our tests? We don't yet support tests,
+ # so it's always true at the moment.
+ def match?(resource)
+ if self.vquery
+ return self.vquery.call(resource)
+ else
+ return true
end
+ end
end
diff --git a/lib/puppet/parser/compiler.rb b/lib/puppet/parser/compiler.rb
index 17b05baab..85980722c 100644
--- a/lib/puppet/parser/compiler.rb
+++ b/lib/puppet/parser/compiler.rb
@@ -10,484 +10,484 @@ require 'puppet/resource/type_collection_helper'
# Maintain a graph of scopes, along with a bunch of data
# about the individual catalog we're compiling.
class Puppet::Parser::Compiler
- include Puppet::Util
- include Puppet::Util::Errors
- include Puppet::Resource::TypeCollectionHelper
-
- def self.compile(node)
- new(node).compile.to_resource
- rescue => detail
- puts detail.backtrace if Puppet[:trace]
- raise Puppet::Error, "#{detail} on node #{node.name}"
- end
-
- attr_reader :node, :facts, :collections, :catalog, :node_scope, :resources, :relationships
+ include Puppet::Util
+ include Puppet::Util::Errors
+ include Puppet::Resource::TypeCollectionHelper
- # Add a collection to the global list.
- def add_collection(coll)
- @collections << coll
- end
-
- def add_relationship(dep)
- @relationships << dep
- end
+ def self.compile(node)
+ new(node).compile.to_resource
+ rescue => detail
+ puts detail.backtrace if Puppet[:trace]
+ raise Puppet::Error, "#{detail} on node #{node.name}"
+ end
- # Store a resource override.
- def add_override(override)
- # If possible, merge the override in immediately.
- if resource = @catalog.resource(override.ref)
- resource.merge(override)
- else
- # Otherwise, store the override for later; these
- # get evaluated in Resource#finish.
- @resource_overrides[override.ref] << override
- end
- end
+ attr_reader :node, :facts, :collections, :catalog, :node_scope, :resources, :relationships
- # Store a resource in our resource table.
- def add_resource(scope, resource)
- @resources << resource
+ # Add a collection to the global list.
+ def add_collection(coll)
+ @collections << coll
+ end
- # Note that this will fail if the resource is not unique.
- @catalog.add_resource(resource)
+ def add_relationship(dep)
+ @relationships << dep
+ end
- set_container_resource(scope, resource)
+ # Store a resource override.
+ def add_override(override)
+ # If possible, merge the override in immediately.
+ if resource = @catalog.resource(override.ref)
+ resource.merge(override)
+ else
+ # Otherwise, store the override for later; these
+ # get evaluated in Resource#finish.
+ @resource_overrides[override.ref] << override
end
+ end
- # Add our container edge. If we're a class, then we get treated specially - we can
- # control the stage that the class is applied in. Otherwise, we just
- # get added to our parent container.
- def set_container_resource(scope, resource)
- return if resource.type.to_s.downcase == "stage"
-
- if resource.type.to_s.downcase != "class"
- raise ArgumentError, "Only classes can set 'stage'; normal resources like #{resource} cannot change run stage" if resource[:stage]
- return @catalog.add_edge(scope.resource, resource)
- end
-
- unless stage = @catalog.resource(:stage, resource[:stage] || :main)
- raise ArgumentError, "Could not find stage #{resource[:stage] || :main} specified by #{resource}"
- end
+ # Store a resource in our resource table.
+ def add_resource(scope, resource)
+ @resources << resource
- @catalog.add_edge(stage, resource)
- end
+ # Note that this will fail if the resource is not unique.
+ @catalog.add_resource(resource)
- private :set_container_resource
+ set_container_resource(scope, resource)
+ end
- # Do we use nodes found in the code, vs. the external node sources?
- def ast_nodes?
- known_resource_types.nodes?
- end
+ # Add our container edge. If we're a class, then we get treated specially - we can
+ # control the stage that the class is applied in. Otherwise, we just
+ # get added to our parent container.
+ def set_container_resource(scope, resource)
+ return if resource.type.to_s.downcase == "stage"
- # Store the fact that we've evaluated a class
- def add_class(name)
- @catalog.add_class(name) unless name == ""
+ if resource.type.to_s.downcase != "class"
+ raise ArgumentError, "Only classes can set 'stage'; normal resources like #{resource} cannot change run stage" if resource[:stage]
+ return @catalog.add_edge(scope.resource, resource)
end
-
- # Return a list of all of the defined classes.
- def classlist
- @catalog.classes
+ unless stage = @catalog.resource(:stage, resource[:stage] || :main)
+ raise ArgumentError, "Could not find stage #{resource[:stage] || :main} specified by #{resource}"
end
- # Compiler our catalog. This mostly revolves around finding and evaluating classes.
- # This is the main entry into our catalog.
- def compile
- # Set the client's parameters into the top scope.
- set_node_parameters
- create_settings_scope
+ @catalog.add_edge(stage, resource)
+ end
- evaluate_main
+ private :set_container_resource
+
+ # Do we use nodes found in the code, vs. the external node sources?
+ def ast_nodes?
+ known_resource_types.nodes?
+ end
- evaluate_ast_node
+ # Store the fact that we've evaluated a class
+ def add_class(name)
+ @catalog.add_class(name) unless name == ""
+ end
- evaluate_node_classes
- evaluate_generators
+ # Return a list of all of the defined classes.
+ def classlist
+ @catalog.classes
+ end
+
+ # Compiler our catalog. This mostly revolves around finding and evaluating classes.
+ # This is the main entry into our catalog.
+ def compile
+ # Set the client's parameters into the top scope.
+ set_node_parameters
+ create_settings_scope
+
+ evaluate_main
+
+ evaluate_ast_node
+
+ evaluate_node_classes
+
+ evaluate_generators
+
+ finish
+
+ fail_on_unevaluated
+
+ @catalog
+ end
+
+ # LAK:FIXME There are no tests for this.
+ def delete_collection(coll)
+ @collections.delete(coll) if @collections.include?(coll)
+ end
- finish
-
- fail_on_unevaluated
-
- @catalog
+ # Return the node's environment.
+ def environment
+ unless defined?(@environment)
+ @environment = (node.environment and node.environment != "") ? node.environment : nil
end
+ Puppet::Node::Environment.current = @environment
+ @environment
+ end
- # LAK:FIXME There are no tests for this.
- def delete_collection(coll)
- @collections.delete(coll) if @collections.include?(coll)
- end
+ # Evaluate all of the classes specified by the node.
+ def evaluate_node_classes
+ evaluate_classes(@node.classes, topscope)
+ end
- # Return the node's environment.
- def environment
- unless defined?(@environment)
- @environment = (node.environment and node.environment != "") ? node.environment : nil
- end
- Puppet::Node::Environment.current = @environment
- @environment
- end
+ # Evaluate each specified class in turn. If there are any classes we can't
+ # find, just tag the catalog and move on. This method really just
+ # creates resource objects that point back to the classes, and then the
+ # resources are themselves evaluated later in the process.
+ def evaluate_classes(classes, scope, lazy_evaluate = true)
+ raise Puppet::DevError, "No source for scope passed to evaluate_classes" unless scope.source
+ found = []
+ classes.each do |name|
+ # If we can find the class, then make a resource that will evaluate it.
+ if klass = scope.find_hostclass(name)
+ found << name and next if scope.class_scope(klass)
- # Evaluate all of the classes specified by the node.
- def evaluate_node_classes
- evaluate_classes(@node.classes, topscope)
- end
-
- # Evaluate each specified class in turn. If there are any classes we can't
- # find, just tag the catalog and move on. This method really just
- # creates resource objects that point back to the classes, and then the
- # resources are themselves evaluated later in the process.
- def evaluate_classes(classes, scope, lazy_evaluate = true)
- raise Puppet::DevError, "No source for scope passed to evaluate_classes" unless scope.source
- found = []
- classes.each do |name|
- # If we can find the class, then make a resource that will evaluate it.
- if klass = scope.find_hostclass(name)
- found << name and next if scope.class_scope(klass)
-
- resource = klass.mk_plain_resource(scope)
-
- # If they've disabled lazy evaluation (which the :include function does),
- # then evaluate our resource immediately.
- resource.evaluate unless lazy_evaluate
- found << name
- else
- Puppet.info "Could not find class #{name} for #{node.name}"
- @catalog.tag(name)
- end
- end
- found
- end
-
- def evaluate_relationships
- @relationships.each { |rel| rel.evaluate(catalog) }
- end
+ resource = klass.mk_plain_resource(scope)
- # Return a resource by either its ref or its type and title.
- def findresource(*args)
- @catalog.resource(*args)
+ # If they've disabled lazy evaluation (which the :include function does),
+ # then evaluate our resource immediately.
+ resource.evaluate unless lazy_evaluate
+ found << name
+ else
+ Puppet.info "Could not find class #{name} for #{node.name}"
+ @catalog.tag(name)
+ end
end
-
- def initialize(node, options = {})
- @node = node
-
- options.each do |param, value|
- begin
- send(param.to_s + "=", value)
- rescue NoMethodError
- raise ArgumentError, "Compiler objects do not accept #{param}"
- end
+ found
+ end
+
+ def evaluate_relationships
+ @relationships.each { |rel| rel.evaluate(catalog) }
+ end
+
+ # Return a resource by either its ref or its type and title.
+ def findresource(*args)
+ @catalog.resource(*args)
+ end
+
+ def initialize(node, options = {})
+ @node = node
+
+ options.each do |param, value|
+ begin
+ send(param.to_s + "=", value)
+ rescue NoMethodError
+ raise ArgumentError, "Compiler objects do not accept #{param}"
+ end
+ end
+
+ initvars
+ end
+
+ # Create a new scope, with either a specified parent scope or
+ # using the top scope.
+ def newscope(parent, options = {})
+ parent ||= topscope
+ options[:compiler] = self
+ scope = Puppet::Parser::Scope.new(options)
+ scope.parent = parent
+ scope
+ end
+
+ # Return any overrides for the given resource.
+ def resource_overrides(resource)
+ @resource_overrides[resource.ref]
+ end
+
+ # The top scope is usually the top-level scope, but if we're using AST nodes,
+ # then it is instead the node's scope.
+ def topscope
+ node_scope || @topscope
+ end
+
+ private
+
+ # If ast nodes are enabled, then see if we can find and evaluate one.
+ def evaluate_ast_node
+ return unless ast_nodes?
+
+ # Now see if we can find the node.
+ astnode = nil
+ @node.names.each do |name|
+ break if astnode = known_resource_types.node(name.to_s.downcase)
+ end
+
+ unless (astnode ||= known_resource_types.node("default"))
+ raise Puppet::ParseError, "Could not find default node or by name with '#{node.names.join(", ")}'"
+ end
+
+ # Create a resource to model this node, and then add it to the list
+ # of resources.
+ resource = astnode.mk_plain_resource(topscope)
+
+ resource.evaluate
+
+ # Now set the node scope appropriately, so that :topscope can
+ # behave differently.
+ @node_scope = topscope.class_scope(astnode)
+ end
+
+ # Evaluate our collections and return true if anything returned an object.
+ # The 'true' is used to continue a loop, so it's important.
+ def evaluate_collections
+ return false if @collections.empty?
+
+ found_something = false
+ exceptwrap do
+ # We have to iterate over a dup of the array because
+ # collections can delete themselves from the list, which
+ # changes its length and causes some collections to get missed.
+ @collections.dup.each do |collection|
+ found_something = true if collection.evaluate
+ end
+ end
+
+ found_something
+ end
+
+ # Make sure all of our resources have been evaluated into native resources.
+ # We return true if any resources have, so that we know to continue the
+ # evaluate_generators loop.
+ def evaluate_definitions
+ exceptwrap do
+ if ary = unevaluated_resources
+ evaluated = false
+ ary.each do |resource|
+ if not resource.virtual?
+ resource.evaluate
+ evaluated = true
+ end
end
-
- initvars
- end
-
- # Create a new scope, with either a specified parent scope or
- # using the top scope.
- def newscope(parent, options = {})
- parent ||= topscope
- options[:compiler] = self
- scope = Puppet::Parser::Scope.new(options)
- scope.parent = parent
- scope
- end
-
- # Return any overrides for the given resource.
- def resource_overrides(resource)
- @resource_overrides[resource.ref]
- end
-
- # The top scope is usually the top-level scope, but if we're using AST nodes,
- # then it is instead the node's scope.
- def topscope
- node_scope || @topscope
- end
-
- private
-
- # If ast nodes are enabled, then see if we can find and evaluate one.
- def evaluate_ast_node
- return unless ast_nodes?
-
- # Now see if we can find the node.
- astnode = nil
- @node.names.each do |name|
- break if astnode = known_resource_types.node(name.to_s.downcase)
- end
-
- unless (astnode ||= known_resource_types.node("default"))
- raise Puppet::ParseError, "Could not find default node or by name with '#{node.names.join(", ")}'"
+ # If we evaluated, let the loop know.
+ return evaluated
+ else
+ return false
+ end
+ end
+ end
+
+ # Iterate over collections and resources until we're sure that the whole
+ # compile is evaluated. This is necessary because both collections
+ # and defined resources can generate new resources, which themselves could
+ # be defined resources.
+ def evaluate_generators
+ count = 0
+ loop do
+ done = true
+
+ # Call collections first, then definitions.
+ done = false if evaluate_collections
+ done = false if evaluate_definitions
+ break if done
+
+ count += 1
+
+ if count > 1000
+ raise Puppet::ParseError, "Somehow looped more than 1000 times while evaluating host catalog"
+ end
+ end
+ end
+
+ # Find and evaluate our main object, if possible.
+ def evaluate_main
+ @main = known_resource_types.find_hostclass([""], "") || known_resource_types.add(Puppet::Resource::Type.new(:hostclass, ""))
+ @topscope.source = @main
+ @main_resource = Puppet::Parser::Resource.new("class", :main, :scope => @topscope, :source => @main)
+ @topscope.resource = @main_resource
+
+ @resources << @main_resource
+ @catalog.add_resource(@main_resource)
+
+ set_container_resource(@topscope, @main_resource)
+
+ @main_resource.evaluate
+ end
+
+ # Make sure the entire catalog is evaluated.
+ def fail_on_unevaluated
+ fail_on_unevaluated_overrides
+ fail_on_unevaluated_resource_collections
+ end
+
+ # If there are any resource overrides remaining, then we could
+ # not find the resource they were supposed to override, so we
+ # want to throw an exception.
+ def fail_on_unevaluated_overrides
+ remaining = []
+ @resource_overrides.each do |name, overrides|
+ remaining += overrides
+ end
+
+ unless remaining.empty?
+ fail Puppet::ParseError,
+ "Could not find resource(s) %s for overriding" % remaining.collect { |o|
+ o.ref
+ }.join(", ")
+ end
+ end
+
+ # Make sure we don't have any remaining collections that specifically
+ # look for resources, because we want to consider those to be
+ # parse errors.
+ def fail_on_unevaluated_resource_collections
+ remaining = []
+ @collections.each do |coll|
+ # We're only interested in the 'resource' collections,
+ # which result from direct calls of 'realize'. Anything
+ # else is allowed not to return resources.
+ # Collect all of them, so we have a useful error.
+ if r = coll.resources
+ if r.is_a?(Array)
+ remaining += r
+ else
+ remaining << r
end
-
- # Create a resource to model this node, and then add it to the list
- # of resources.
- resource = astnode.mk_plain_resource(topscope)
-
- resource.evaluate
-
- # Now set the node scope appropriately, so that :topscope can
- # behave differently.
- @node_scope = topscope.class_scope(astnode)
+ end
end
- # Evaluate our collections and return true if anything returned an object.
- # The 'true' is used to continue a loop, so it's important.
- def evaluate_collections
- return false if @collections.empty?
-
- found_something = false
- exceptwrap do
- # We have to iterate over a dup of the array because
- # collections can delete themselves from the list, which
- # changes its length and causes some collections to get missed.
- @collections.dup.each do |collection|
- found_something = true if collection.evaluate
- end
- end
+ raise Puppet::ParseError, "Failed to realize virtual resources #{remaining.join(', ')}" unless remaining.empty?
+ end
- found_something
- end
+ # Make sure all of our resources and such have done any last work
+ # necessary.
+ def finish
+ evaluate_relationships
- # Make sure all of our resources have been evaluated into native resources.
- # We return true if any resources have, so that we know to continue the
- # evaluate_generators loop.
- def evaluate_definitions
- exceptwrap do
- if ary = unevaluated_resources
- evaluated = false
- ary.each do |resource|
- if not resource.virtual?
- resource.evaluate
- evaluated = true
- end
- end
- # If we evaluated, let the loop know.
- return evaluated
- else
- return false
- end
+ resources.each do |resource|
+ # Add in any resource overrides.
+ if overrides = resource_overrides(resource)
+ overrides.each do |over|
+ resource.merge(over)
end
- end
- # Iterate over collections and resources until we're sure that the whole
- # compile is evaluated. This is necessary because both collections
- # and defined resources can generate new resources, which themselves could
- # be defined resources.
- def evaluate_generators
- count = 0
- loop do
- done = true
-
- # Call collections first, then definitions.
- done = false if evaluate_collections
- done = false if evaluate_definitions
- break if done
-
- count += 1
-
- if count > 1000
- raise Puppet::ParseError, "Somehow looped more than 1000 times while evaluating host catalog"
- end
- end
- end
-
- # Find and evaluate our main object, if possible.
- def evaluate_main
- @main = known_resource_types.find_hostclass([""], "") || known_resource_types.add(Puppet::Resource::Type.new(:hostclass, ""))
- @topscope.source = @main
- @main_resource = Puppet::Parser::Resource.new("class", :main, :scope => @topscope, :source => @main)
- @topscope.resource = @main_resource
-
- @resources << @main_resource
- @catalog.add_resource(@main_resource)
+ # Remove the overrides, so that the configuration knows there
+ # are none left.
+ overrides.clear
+ end
- set_container_resource(@topscope, @main_resource)
-
- @main_resource.evaluate
+ resource.finish if resource.respond_to?(:finish)
end
- # Make sure the entire catalog is evaluated.
- def fail_on_unevaluated
- fail_on_unevaluated_overrides
- fail_on_unevaluated_resource_collections
- end
+ add_resource_metaparams
+ end
- # If there are any resource overrides remaining, then we could
- # not find the resource they were supposed to override, so we
- # want to throw an exception.
- def fail_on_unevaluated_overrides
- remaining = []
- @resource_overrides.each do |name, overrides|
- remaining += overrides
- end
-
- unless remaining.empty?
- fail Puppet::ParseError,
- "Could not find resource(s) %s for overriding" % remaining.collect { |o|
- o.ref
- }.join(", ")
- end
+ def add_resource_metaparams
+ unless main = catalog.resource(:class, :main)
+ raise "Couldn't find main"
end
- # Make sure we don't have any remaining collections that specifically
- # look for resources, because we want to consider those to be
- # parse errors.
- def fail_on_unevaluated_resource_collections
- remaining = []
- @collections.each do |coll|
- # We're only interested in the 'resource' collections,
- # which result from direct calls of 'realize'. Anything
- # else is allowed not to return resources.
- # Collect all of them, so we have a useful error.
- if r = coll.resources
- if r.is_a?(Array)
- remaining += r
- else
- remaining << r
- end
- end
- end
-
- raise Puppet::ParseError, "Failed to realize virtual resources #{remaining.join(', ')}" unless remaining.empty?
+ names = []
+ Puppet::Type.eachmetaparam do |name|
+ next if Puppet::Parser::Resource.relationship_parameter?(name)
+ names << name
end
- # Make sure all of our resources and such have done any last work
- # necessary.
- def finish
- evaluate_relationships
-
- resources.each do |resource|
- # Add in any resource overrides.
- if overrides = resource_overrides(resource)
- overrides.each do |over|
- resource.merge(over)
- end
-
- # Remove the overrides, so that the configuration knows there
- # are none left.
- overrides.clear
- end
-
- resource.finish if resource.respond_to?(:finish)
+ data = {}
+ catalog.walk(main, :out) do |source, target|
+ if source_data = data[source] || metaparams_as_data(source, names)
+ # only store anything in the data hash if we've actually got
+ # data
+ data[source] ||= source_data
+ source_data.each do |param, value|
+ target[param] = value if target[param].nil?
end
+ data[target] = source_data.merge(metaparams_as_data(target, names))
+ end
- add_resource_metaparams
+ target.tag(*(source.tags))
end
+ end
- def add_resource_metaparams
- unless main = catalog.resource(:class, :main)
- raise "Couldn't find main"
- end
-
- names = []
- Puppet::Type.eachmetaparam do |name|
- next if Puppet::Parser::Resource.relationship_parameter?(name)
- names << name
- end
-
- data = {}
- catalog.walk(main, :out) do |source, target|
- if source_data = data[source] || metaparams_as_data(source, names)
- # only store anything in the data hash if we've actually got
- # data
- data[source] ||= source_data
- source_data.each do |param, value|
- target[param] = value if target[param].nil?
- end
- data[target] = source_data.merge(metaparams_as_data(target, names))
- end
-
- target.tag(*(source.tags))
- end
+ def metaparams_as_data(resource, params)
+ data = nil
+ params.each do |param|
+ unless resource[param].nil?
+ # Because we could be creating a hash for every resource,
+ # and we actually probably don't often have any data here at all,
+ # we're optimizing a bit by only creating a hash if there's
+ # any data to put in it.
+ data ||= {}
+ data[param] = resource[param]
+ end
end
+ data
+ end
- def metaparams_as_data(resource, params)
- data = nil
- params.each do |param|
- unless resource[param].nil?
- # Because we could be creating a hash for every resource,
- # and we actually probably don't often have any data here at all,
- # we're optimizing a bit by only creating a hash if there's
- # any data to put in it.
- data ||= {}
- data[param] = resource[param]
- end
- end
- data
- end
+ # Set up all of our internal variables.
+ def initvars
+ # The list of objects that will available for export.
+ @exported_resources = {}
- # Set up all of our internal variables.
- def initvars
- # The list of objects that will available for export.
- @exported_resources = {}
+ # The list of overrides. This is used to cache overrides on objects
+ # that don't exist yet. We store an array of each override.
+ @resource_overrides = Hash.new do |overs, ref|
+ overs[ref] = []
+ end
- # The list of overrides. This is used to cache overrides on objects
- # that don't exist yet. We store an array of each override.
- @resource_overrides = Hash.new do |overs, ref|
- overs[ref] = []
- end
+ # The list of collections that have been created. This is a global list,
+ # but they each refer back to the scope that created them.
+ @collections = []
- # The list of collections that have been created. This is a global list,
- # but they each refer back to the scope that created them.
- @collections = []
+ # The list of relationships to evaluate.
+ @relationships = []
- # The list of relationships to evaluate.
- @relationships = []
+ # For maintaining the relationship between scopes and their resources.
+ @catalog = Puppet::Resource::Catalog.new(@node.name)
+ @catalog.version = known_resource_types.version
- # For maintaining the relationship between scopes and their resources.
- @catalog = Puppet::Resource::Catalog.new(@node.name)
- @catalog.version = known_resource_types.version
+ # Create our initial scope and a resource that will evaluate main.
+ @topscope = Puppet::Parser::Scope.new(:compiler => self)
- # Create our initial scope and a resource that will evaluate main.
- @topscope = Puppet::Parser::Scope.new(:compiler => self)
+ @main_stage_resource = Puppet::Parser::Resource.new("stage", :main, :scope => @topscope)
+ @catalog.add_resource(@main_stage_resource)
- @main_stage_resource = Puppet::Parser::Resource.new("stage", :main, :scope => @topscope)
- @catalog.add_resource(@main_stage_resource)
+ # local resource array to maintain resource ordering
+ @resources = []
- # local resource array to maintain resource ordering
- @resources = []
+ # Make sure any external node classes are in our class list
+ @catalog.add_class(*@node.classes)
+ end
- # Make sure any external node classes are in our class list
- @catalog.add_class(*@node.classes)
+ # Set the node's parameters into the top-scope as variables.
+ def set_node_parameters
+ node.parameters.each do |param, value|
+ @topscope.setvar(param, value)
end
- # Set the node's parameters into the top-scope as variables.
- def set_node_parameters
- node.parameters.each do |param, value|
- @topscope.setvar(param, value)
- end
+ # These might be nil.
+ catalog.client_version = node.parameters["clientversion"]
+ catalog.server_version = node.parameters["serverversion"]
+ end
- # These might be nil.
- catalog.client_version = node.parameters["clientversion"]
- catalog.server_version = node.parameters["serverversion"]
+ def create_settings_scope
+ unless settings_type = environment.known_resource_types.hostclass("settings")
+ settings_type = Puppet::Resource::Type.new :hostclass, "settings"
+ environment.known_resource_types.add(settings_type)
end
- def create_settings_scope
- unless settings_type = environment.known_resource_types.hostclass("settings")
- settings_type = Puppet::Resource::Type.new :hostclass, "settings"
- environment.known_resource_types.add(settings_type)
- end
+ settings_resource = Puppet::Parser::Resource.new("class", "settings", :scope => @topscope)
+ settings_type.evaluate_code(settings_resource)
- settings_resource = Puppet::Parser::Resource.new("class", "settings", :scope => @topscope)
- settings_type.evaluate_code(settings_resource)
+ @catalog.add_resource(settings_resource)
- @catalog.add_resource(settings_resource)
+ scope = @topscope.class_scope(settings_type)
- scope = @topscope.class_scope(settings_type)
-
- Puppet.settings.each do |name, setting|
- next if name.to_s == "name"
- scope.setvar name.to_s, environment[name]
- end
+ Puppet.settings.each do |name, setting|
+ next if name.to_s == "name"
+ scope.setvar name.to_s, environment[name]
end
+ end
- # Return an array of all of the unevaluated resources. These will be definitions,
- # which need to get evaluated into native resources.
- def unevaluated_resources
- ary = resources.reject { |resource| resource.builtin? or resource.evaluated? }
+ # Return an array of all of the unevaluated resources. These will be definitions,
+ # which need to get evaluated into native resources.
+ def unevaluated_resources
+ ary = resources.reject { |resource| resource.builtin? or resource.evaluated? }
- if ary.empty?
- return nil
- else
- return ary
- end
+ if ary.empty?
+ return nil
+ else
+ return ary
end
+ end
end
diff --git a/lib/puppet/parser/files.rb b/lib/puppet/parser/files.rb
index 875a87826..749743493 100644
--- a/lib/puppet/parser/files.rb
+++ b/lib/puppet/parser/files.rb
@@ -6,83 +6,83 @@ require 'puppet/parser/parser'
# doesn't really belong in the Puppet::Module class,
# but it doesn't really belong anywhere else, either.
module Puppet::Parser::Files
- module_function
+ module_function
- # Return a list of manifests (as absolute filenames) that match +pat+
- # with the current directory set to +cwd+. If the first component of
- # +pat+ does not contain any wildcards and is an existing module, return
- # a list of manifests in that module matching the rest of +pat+
- # Otherwise, try to find manifests matching +pat+ relative to +cwd+
- def find_manifests(start, options = {})
- cwd = options[:cwd] || Dir.getwd
- module_name, pattern = split_file_path(start)
- begin
- if mod = Puppet::Module.find(module_name, options[:environment])
- return [mod.name, mod.match_manifests(pattern)]
- end
- rescue Puppet::Module::InvalidName
- # Than that would be a "no."
- end
- abspat = File::expand_path(start, cwd)
- [nil, Dir.glob(abspat + (File.extname(abspat).empty? ? '{,.pp,.rb}' : '' )).reject { |f| FileTest.directory?(f) }]
+ # Return a list of manifests (as absolute filenames) that match +pat+
+ # with the current directory set to +cwd+. If the first component of
+ # +pat+ does not contain any wildcards and is an existing module, return
+ # a list of manifests in that module matching the rest of +pat+
+ # Otherwise, try to find manifests matching +pat+ relative to +cwd+
+ def find_manifests(start, options = {})
+ cwd = options[:cwd] || Dir.getwd
+ module_name, pattern = split_file_path(start)
+ begin
+ if mod = Puppet::Module.find(module_name, options[:environment])
+ return [mod.name, mod.match_manifests(pattern)]
+ end
+ rescue Puppet::Module::InvalidName
+ # Than that would be a "no."
end
+ abspat = File::expand_path(start, cwd)
+ [nil, Dir.glob(abspat + (File.extname(abspat).empty? ? '{,.pp,.rb}' : '' )).reject { |f| FileTest.directory?(f) }]
+ end
- # Find the concrete file denoted by +file+. If +file+ is absolute,
- # return it directly. Otherwise try to find it as a template in a
- # module. If that fails, return it relative to the +templatedir+ config
- # param.
- # In all cases, an absolute path is returned, which does not
- # necessarily refer to an existing file
- def find_template(template, environment = nil)
- if template == File.expand_path(template)
- return template
- end
-
- if template_paths = templatepath(environment)
- # If we can find the template in :templatedir, we return that.
- template_paths.collect { |path|
- File::join(path, template)
- }.each do |f|
- return f if FileTest.exist?(f)
- end
- end
+ # Find the concrete file denoted by +file+. If +file+ is absolute,
+ # return it directly. Otherwise try to find it as a template in a
+ # module. If that fails, return it relative to the +templatedir+ config
+ # param.
+ # In all cases, an absolute path is returned, which does not
+ # necessarily refer to an existing file
+ def find_template(template, environment = nil)
+ if template == File.expand_path(template)
+ return template
+ end
- # check in the default template dir, if there is one
- if td_file = find_template_in_module(template, environment)
- return td_file
- end
+ if template_paths = templatepath(environment)
+ # If we can find the template in :templatedir, we return that.
+ template_paths.collect { |path|
+ File::join(path, template)
+ }.each do |f|
+ return f if FileTest.exist?(f)
+ end
+ end
- nil
+ # check in the default template dir, if there is one
+ if td_file = find_template_in_module(template, environment)
+ return td_file
end
- def find_template_in_module(template, environment = nil)
- path, file = split_file_path(template)
+ nil
+ end
- # Because templates don't have an assumed template name, like manifests do,
- # we treat templates with no name as being templates in the main template
- # directory.
- return nil unless file
+ def find_template_in_module(template, environment = nil)
+ path, file = split_file_path(template)
- if mod = Puppet::Module.find(path, environment) and t = mod.template(file)
- return t
- end
- nil
- end
+ # Because templates don't have an assumed template name, like manifests do,
+ # we treat templates with no name as being templates in the main template
+ # directory.
+ return nil unless file
- # Return an array of paths by splitting the +templatedir+ config
- # parameter.
- def templatepath(environment = nil)
- dirs = Puppet.settings.value(:templatedir, environment).split(File::PATH_SEPARATOR)
- dirs.select do |p|
- File::directory?(p)
- end
+ if mod = Puppet::Module.find(path, environment) and t = mod.template(file)
+ return t
end
+ nil
+ end
- # Split the path into the module and the rest of the path, or return
- # nil if the path is empty or absolute (starts with a /).
- # This method can return nil & anyone calling it needs to handle that.
- def split_file_path(path)
- path.split(File::SEPARATOR, 2) unless path == "" or path == File.expand_path(path)
+ # Return an array of paths by splitting the +templatedir+ config
+ # parameter.
+ def templatepath(environment = nil)
+ dirs = Puppet.settings.value(:templatedir, environment).split(File::PATH_SEPARATOR)
+ dirs.select do |p|
+ File::directory?(p)
end
+ end
+
+ # Split the path into the module and the rest of the path, or return
+ # nil if the path is empty or absolute (starts with a /).
+ # This method can return nil & anyone calling it needs to handle that.
+ def split_file_path(path)
+ path.split(File::SEPARATOR, 2) unless path == "" or path == File.expand_path(path)
+ end
end
diff --git a/lib/puppet/parser/functions.rb b/lib/puppet/parser/functions.rb
index 3e56f2a95..c238da5d4 100644
--- a/lib/puppet/parser/functions.rb
+++ b/lib/puppet/parser/functions.rb
@@ -7,116 +7,116 @@ require 'monitor'
# class.
module Puppet::Parser::Functions
- (@functions = Hash.new { |h,k| h[k] = {} }).extend(MonitorMixin)
- (@modules = {} ).extend(MonitorMixin)
+ (@functions = Hash.new { |h,k| h[k] = {} }).extend(MonitorMixin)
+ (@modules = {} ).extend(MonitorMixin)
- class << self
- include Puppet::Util
- end
+ class << self
+ include Puppet::Util
+ end
- def self.autoloader
- unless defined?(@autoloader)
+ def self.autoloader
+ unless defined?(@autoloader)
- @autoloader = Puppet::Util::Autoload.new(
- self,
- "puppet/parser/functions",
+ @autoloader = Puppet::Util::Autoload.new(
+ self,
+ "puppet/parser/functions",
- :wrap => false
- )
- end
-
- @autoloader
+ :wrap => false
+ )
end
- Environment = Puppet::Node::Environment
+ @autoloader
+ end
- def self.environment_module(env = nil)
- @modules.synchronize {
- @modules[ env || Environment.current || Environment.root ] ||= Module.new
- }
- end
+ Environment = Puppet::Node::Environment
- # Create a new function type.
- def self.newfunction(name, options = {}, &block)
- name = symbolize(name)
+ def self.environment_module(env = nil)
+ @modules.synchronize {
+ @modules[ env || Environment.current || Environment.root ] ||= Module.new
+ }
+ end
- raise Puppet::DevError, "Function #{name} already defined" if functions.include?(name)
+ # Create a new function type.
+ def self.newfunction(name, options = {}, &block)
+ name = symbolize(name)
- ftype = options[:type] || :statement
+ raise Puppet::DevError, "Function #{name} already defined" if functions.include?(name)
- unless ftype == :statement or ftype == :rvalue
- raise Puppet::DevError, "Invalid statement type #{ftype.inspect}"
- end
+ ftype = options[:type] || :statement
- fname = "function_#{name}"
- environment_module.send(:define_method, fname, &block)
-
- # Someday we'll support specifying an arity, but for now, nope
- #functions[name] = {:arity => arity, :type => ftype}
- functions[name] = {:type => ftype, :name => fname}
- functions[name][:doc] = options[:doc] if options[:doc]
+ unless ftype == :statement or ftype == :rvalue
+ raise Puppet::DevError, "Invalid statement type #{ftype.inspect}"
end
- # Remove a function added by newfunction
- def self.rmfunction(name)
- name = symbolize(name)
+ fname = "function_#{name}"
+ environment_module.send(:define_method, fname, &block)
- raise Puppet::DevError, "Function #{name} is not defined" unless functions.include? name
+ # Someday we'll support specifying an arity, but for now, nope
+ #functions[name] = {:arity => arity, :type => ftype}
+ functions[name] = {:type => ftype, :name => fname}
+ functions[name][:doc] = options[:doc] if options[:doc]
+ end
- functions.delete name
+ # Remove a function added by newfunction
+ def self.rmfunction(name)
+ name = symbolize(name)
- fname = "function_#{name}"
- environment_module.send(:remove_method, fname)
- end
+ raise Puppet::DevError, "Function #{name} is not defined" unless functions.include? name
- # Determine if a given name is a function
- def self.function(name)
- name = symbolize(name)
+ functions.delete name
- unless functions.include?(name) or functions(Puppet::Node::Environment.root).include?(name)
- autoloader.load(name,Environment.current || Environment.root)
- end
+ fname = "function_#{name}"
+ environment_module.send(:remove_method, fname)
+ end
- ( functions(Environment.root)[name] || functions[name] || {:name => false} )[:name]
+ # Determine if a given name is a function
+ def self.function(name)
+ name = symbolize(name)
+
+ unless functions.include?(name) or functions(Puppet::Node::Environment.root).include?(name)
+ autoloader.load(name,Environment.current || Environment.root)
end
- def self.functiondocs
- autoloader.loadall
+ ( functions(Environment.root)[name] || functions[name] || {:name => false} )[:name]
+ end
- ret = ""
+ def self.functiondocs
+ autoloader.loadall
- functions.sort { |a,b| a[0].to_s <=> b[0].to_s }.each do |name, hash|
- #ret += "#{name}\n#{hash[:type]}\n"
- ret += "#{name}\n#{"-" * name.to_s.length}\n"
- if hash[:doc]
- ret += Puppet::Util::Docs.scrub(hash[:doc])
- else
- ret += "Undocumented.\n"
- end
+ ret = ""
- ret += "\n\n- **Type**: #{hash[:type]}\n\n"
- end
+ functions.sort { |a,b| a[0].to_s <=> b[0].to_s }.each do |name, hash|
+ #ret += "#{name}\n#{hash[:type]}\n"
+ ret += "#{name}\n#{"-" * name.to_s.length}\n"
+ if hash[:doc]
+ ret += Puppet::Util::Docs.scrub(hash[:doc])
+ else
+ ret += "Undocumented.\n"
+ end
- ret
+ ret += "\n\n- **Type**: #{hash[:type]}\n\n"
end
- def self.functions(env = nil)
- @functions.synchronize {
- @functions[ env || Environment.current || Environment.root ]
- }
- end
+ ret
+ end
- # Determine if a given function returns a value or not.
- def self.rvalue?(name)
- (functions[symbolize(name)] || {})[:type] == :rvalue
- end
+ def self.functions(env = nil)
+ @functions.synchronize {
+ @functions[ env || Environment.current || Environment.root ]
+ }
+ end
+
+ # Determine if a given function returns a value or not.
+ def self.rvalue?(name)
+ (functions[symbolize(name)] || {})[:type] == :rvalue
+ end
- # Runs a newfunction to create a function for each of the log levels
+ # Runs a newfunction to create a function for each of the log levels
- Puppet::Util::Log.levels.each do |level|
- newfunction(level, :doc => "Log a message on the server at level #{level.to_s}.") do |vals|
- send(level, vals.join(" "))
- end
+ Puppet::Util::Log.levels.each do |level|
+ newfunction(level, :doc => "Log a message on the server at level #{level.to_s}.") do |vals|
+ send(level, vals.join(" "))
end
+ end
end
diff --git a/lib/puppet/parser/functions/defined.rb b/lib/puppet/parser/functions/defined.rb
index 4d1d8c6fd..2930a65cc 100644
--- a/lib/puppet/parser/functions/defined.rb
+++ b/lib/puppet/parser/functions/defined.rb
@@ -1,27 +1,27 @@
# Test whether a given class or definition is defined
Puppet::Parser::Functions::newfunction(:defined, :type => :rvalue, :doc => "Determine whether a given
- type is defined, either as a native type or a defined type, or whether a class is defined.
- This is useful for checking whether a class is defined and only including it if it is.
- This function can also test whether a resource has been defined, using resource references
- (e.g., ``if defined(File['/tmp/myfile']) { ... }``). This function is unfortunately
- dependent on the parse order of the configuration when testing whether a resource is defined.") do |vals|
- result = false
- vals = [vals] unless vals.is_a?(Array)
- vals.each do |val|
- case val
- when String
- if Puppet::Type.type(val) or find_definition(val) or find_hostclass(val)
- result = true
- break
- end
- when Puppet::Resource
- if findresource(val.to_s)
- result = true
- break
- end
- else
- raise ArgumentError, "Invalid argument of type '#{val.class}' to 'defined'"
- end
+ type is defined, either as a native type or a defined type, or whether a class is defined.
+ This is useful for checking whether a class is defined and only including it if it is.
+ This function can also test whether a resource has been defined, using resource references
+ (e.g., ``if defined(File['/tmp/myfile']) { ... }``). This function is unfortunately
+ dependent on the parse order of the configuration when testing whether a resource is defined.") do |vals|
+ result = false
+ vals = [vals] unless vals.is_a?(Array)
+ vals.each do |val|
+ case val
+ when String
+ if Puppet::Type.type(val) or find_definition(val) or find_hostclass(val)
+ result = true
+ break
end
- result
+ when Puppet::Resource
+ if findresource(val.to_s)
+ result = true
+ break
+ end
+ else
+ raise ArgumentError, "Invalid argument of type '#{val.class}' to 'defined'"
+ end
+ end
+ result
end
diff --git a/lib/puppet/parser/functions/fail.rb b/lib/puppet/parser/functions/fail.rb
index 35b20ee92..5bef6c7e3 100644
--- a/lib/puppet/parser/functions/fail.rb
+++ b/lib/puppet/parser/functions/fail.rb
@@ -1,4 +1,4 @@
Puppet::Parser::Functions::newfunction(:fail, :doc => "Fail with a parse error.") do |vals|
- vals = vals.collect { |s| s.to_s }.join(" ") if vals.is_a? Array
- raise Puppet::ParseError, vals.to_s
+ vals = vals.collect { |s| s.to_s }.join(" ") if vals.is_a? Array
+ raise Puppet::ParseError, vals.to_s
end
diff --git a/lib/puppet/parser/functions/file.rb b/lib/puppet/parser/functions/file.rb
index d13b01ede..963111260 100644
--- a/lib/puppet/parser/functions/file.rb
+++ b/lib/puppet/parser/functions/file.rb
@@ -1,23 +1,23 @@
# Returns the contents of a file
- Puppet::Parser::Functions::newfunction(
- :file, :type => :rvalue,
+ Puppet::Parser::Functions::newfunction(
+ :file, :type => :rvalue,
- :doc => "Return the contents of a file. Multiple files
- can be passed, and the first file that exists will be read in.") do |vals|
- ret = nil
- vals.each do |file|
- unless file =~ /^#{File::SEPARATOR}/
- raise Puppet::ParseError, "Files must be fully qualified"
- end
- if FileTest.exists?(file)
- ret = File.read(file)
- break
- end
- end
- if ret
- ret
- else
- raise Puppet::ParseError, "Could not find any files from #{vals.join(", ")}"
- end
+ :doc => "Return the contents of a file. Multiple files
+ can be passed, and the first file that exists will be read in.") do |vals|
+ ret = nil
+ vals.each do |file|
+ unless file =~ /^#{File::SEPARATOR}/
+ raise Puppet::ParseError, "Files must be fully qualified"
+ end
+ if FileTest.exists?(file)
+ ret = File.read(file)
+ break
+ end
+ end
+ if ret
+ ret
+ else
+ raise Puppet::ParseError, "Could not find any files from #{vals.join(", ")}"
+ end
end
diff --git a/lib/puppet/parser/functions/fqdn_rand.rb b/lib/puppet/parser/functions/fqdn_rand.rb
index 27af2d7ca..3e7018ac4 100644
--- a/lib/puppet/parser/functions/fqdn_rand.rb
+++ b/lib/puppet/parser/functions/fqdn_rand.rb
@@ -1,9 +1,9 @@
Puppet::Parser::Functions::newfunction(:fqdn_rand, :type => :rvalue, :doc =>
- "Generates random numbers based on the node's fqdn. The first argument
- sets the range. Additional (optional) arguments may be used to further
- distinguish the seed.") do |args|
- require 'md5'
- max = args.shift
- srand MD5.new([lookupvar('fqdn'),args].join(':')).to_s.hex
- rand(max).to_s
+ "Generates random numbers based on the node's fqdn. The first argument
+ sets the range. Additional (optional) arguments may be used to further
+ distinguish the seed.") do |args|
+ require 'md5'
+ max = args.shift
+ srand MD5.new([lookupvar('fqdn'),args].join(':')).to_s.hex
+ rand(max).to_s
end
diff --git a/lib/puppet/parser/functions/generate.rb b/lib/puppet/parser/functions/generate.rb
index 8430f03a6..91f7b2240 100644
--- a/lib/puppet/parser/functions/generate.rb
+++ b/lib/puppet/parser/functions/generate.rb
@@ -1,31 +1,31 @@
# Runs an external command and returns the results
Puppet::Parser::Functions::newfunction(:generate, :type => :rvalue,
- :doc => "Calls an external command on the Puppet master and returns
- the results of the command. Any arguments are passed to the external command as
- arguments. If the generator does not exit with return code of 0,
- the generator is considered to have failed and a parse error is
- thrown. Generators can only have file separators, alphanumerics, dashes,
- and periods in them. This function will attempt to protect you from
- malicious generator calls (e.g., those with '..' in them), but it can
- never be entirely safe. No subshell is used to execute
- generators, so all shell metacharacters are passed directly to
- the generator.") do |args|
+ :doc => "Calls an external command on the Puppet master and returns
+ the results of the command. Any arguments are passed to the external command as
+ arguments. If the generator does not exit with return code of 0,
+ the generator is considered to have failed and a parse error is
+ thrown. Generators can only have file separators, alphanumerics, dashes,
+ and periods in them. This function will attempt to protect you from
+ malicious generator calls (e.g., those with '..' in them), but it can
+ never be entirely safe. No subshell is used to execute
+ generators, so all shell metacharacters are passed directly to
+ the generator.") do |args|
- raise Puppet::ParseError, "Generators must be fully qualified" unless args[0] =~ /^#{File::SEPARATOR}/
+ raise Puppet::ParseError, "Generators must be fully qualified" unless args[0] =~ /^#{File::SEPARATOR}/
- unless args[0] =~ /^[-#{File::SEPARATOR}\w.]+$/
- raise Puppet::ParseError,
- "Generators can only contain alphanumerics, file separators, and dashes"
- end
+ unless args[0] =~ /^[-#{File::SEPARATOR}\w.]+$/
+ raise Puppet::ParseError,
+ "Generators can only contain alphanumerics, file separators, and dashes"
+ end
- if args[0] =~ /\.\./
- raise Puppet::ParseError,
- "Can not use generators with '..' in them."
- end
+ if args[0] =~ /\.\./
+ raise Puppet::ParseError,
+ "Can not use generators with '..' in them."
+ end
- begin
- Dir.chdir(File.dirname(args[0])) { Puppet::Util.execute(args) }
- rescue Puppet::ExecutionFailure => detail
- raise Puppet::ParseError, "Failed to execute generator #{args[0]}: #{detail}"
- end
+ begin
+ Dir.chdir(File.dirname(args[0])) { Puppet::Util.execute(args) }
+ rescue Puppet::ExecutionFailure => detail
+ raise Puppet::ParseError, "Failed to execute generator #{args[0]}: #{detail}"
+ end
end
diff --git a/lib/puppet/parser/functions/include.rb b/lib/puppet/parser/functions/include.rb
index d1bafa54a..1e12a6a88 100644
--- a/lib/puppet/parser/functions/include.rb
+++ b/lib/puppet/parser/functions/include.rb
@@ -1,24 +1,24 @@
# Include the specified classes
Puppet::Parser::Functions::newfunction(:include, :doc => "Evaluate one or more classes.") do |vals|
- vals = [vals] unless vals.is_a?(Array)
+ vals = [vals] unless vals.is_a?(Array)
- # The 'false' disables lazy evaluation.
- klasses = compiler.evaluate_classes(vals, self, false)
+ # The 'false' disables lazy evaluation.
+ klasses = compiler.evaluate_classes(vals, self, false)
- missing = vals.find_all do |klass|
- ! klasses.include?(klass)
- end
+ missing = vals.find_all do |klass|
+ ! klasses.include?(klass)
+ end
- unless missing.empty?
- # Throw an error if we didn't evaluate all of the classes.
- str = "Could not find class"
- str += "es" if missing.length > 1
+ unless missing.empty?
+ # Throw an error if we didn't evaluate all of the classes.
+ str = "Could not find class"
+ str += "es" if missing.length > 1
- str += " " + missing.join(", ")
+ str += " " + missing.join(", ")
- if n = namespaces and ! n.empty? and n != [""]
- str += " in namespaces #{@namespaces.join(", ")}"
- end
- self.fail Puppet::ParseError, str
- end
+ if n = namespaces and ! n.empty? and n != [""]
+ str += " in namespaces #{@namespaces.join(", ")}"
+ end
+ self.fail Puppet::ParseError, str
+ end
end
diff --git a/lib/puppet/parser/functions/inline_template.rb b/lib/puppet/parser/functions/inline_template.rb
index 6c0485d1e..11d980fab 100644
--- a/lib/puppet/parser/functions/inline_template.rb
+++ b/lib/puppet/parser/functions/inline_template.rb
@@ -1,20 +1,20 @@
Puppet::Parser::Functions::newfunction(:inline_template, :type => :rvalue, :doc =>
- "Evaluate a template string and return its value. See `the templating docs
- </trac/puppet/wiki/PuppetTemplating>`_ for more information. Note that
- if multiple template strings are specified, their output is all concatenated
- and returned as the output of the function.") do |vals|
- require 'erb'
+ "Evaluate a template string and return its value. See `the templating docs
+ </trac/puppet/wiki/PuppetTemplating>`_ for more information. Note that
+ if multiple template strings are specified, their output is all concatenated
+ and returned as the output of the function.") do |vals|
+ require 'erb'
- vals.collect do |string|
- # Use a wrapper, so the template can't get access to the full
- # Scope object.
+ vals.collect do |string|
+ # Use a wrapper, so the template can't get access to the full
+ # Scope object.
- wrapper = Puppet::Parser::TemplateWrapper.new(self)
- begin
- wrapper.result(string)
- rescue => detail
- raise Puppet::ParseError,
- "Failed to parse inline template: #{detail}"
- end
- end.join("")
+ wrapper = Puppet::Parser::TemplateWrapper.new(self)
+ begin
+ wrapper.result(string)
+ rescue => detail
+ raise Puppet::ParseError,
+ "Failed to parse inline template: #{detail}"
+ end
+ end.join("")
end
diff --git a/lib/puppet/parser/functions/realize.rb b/lib/puppet/parser/functions/realize.rb
index 6aff19d29..4247b8af8 100644
--- a/lib/puppet/parser/functions/realize.rb
+++ b/lib/puppet/parser/functions/realize.rb
@@ -2,13 +2,13 @@
# be a good bit faster.
Puppet::Parser::Functions::newfunction(:realize, :doc => "Make a virtual object real. This is useful
- when you want to know the name of the virtual object and don't want to
- bother with a full collection. It is slightly faster than a collection,
- and, of course, is a bit shorter. You must pass the object using a
- reference; e.g.: ``realize User[luke]``." ) do |vals|
- coll = Puppet::Parser::Collector.new(self, :nomatter, nil, nil, :virtual)
- vals = [vals] unless vals.is_a?(Array)
- coll.resources = vals.flatten
+ when you want to know the name of the virtual object and don't want to
+ bother with a full collection. It is slightly faster than a collection,
+ and, of course, is a bit shorter. You must pass the object using a
+ reference; e.g.: ``realize User[luke]``." ) do |vals|
+ coll = Puppet::Parser::Collector.new(self, :nomatter, nil, nil, :virtual)
+ vals = [vals] unless vals.is_a?(Array)
+ coll.resources = vals.flatten
- compiler.add_collection(coll)
+ compiler.add_collection(coll)
end
diff --git a/lib/puppet/parser/functions/regsubst.rb b/lib/puppet/parser/functions/regsubst.rb
index c47c1654e..c0aeef222 100644
--- a/lib/puppet/parser/functions/regsubst.rb
+++ b/lib/puppet/parser/functions/regsubst.rb
@@ -1,10 +1,10 @@
module Puppet::Parser::Functions
- newfunction(
- :regsubst, :type => :rvalue,
+ newfunction(
+ :regsubst, :type => :rvalue,
- :doc => "
- Perform regexp replacement on a string or array of strings.
+ :doc => "
+ Perform regexp replacement on a string or array of strings.
- **Parameters** (in order):
@@ -16,85 +16,85 @@ module Puppet::Parser::Functions
:flags: Optional. String of single letter flags for how the regexp is interpreted:
- - **E** Extended regexps
- - **I** Ignore case in regexps
- - **M** Multiline regexps
- - **G** Global replacement; all occurrences of the regexp in each target string will be replaced. Without this, only the first occurrence will be replaced.
+ - **E** Extended regexps
+ - **I** Ignore case in regexps
+ - **M** Multiline regexps
+ - **G** Global replacement; all occurrences of the regexp in each target string will be replaced. Without this, only the first occurrence will be replaced.
:lang: Optional. How to handle multibyte characters. A single-character string with the following values:
- - **N** None
- - **E** EUC
- - **S** SJIS
- - **U** UTF-8
+ - **N** None
+ - **E** EUC
+ - **S** SJIS
+ - **U** UTF-8
- **Examples**
Get the third octet from the node's IP address::
- $i3 = regsubst($ipaddress,'^([0-9]+)[.]([0-9]+)[.]([0-9]+)[.]([0-9]+)$','\\3')
+ $i3 = regsubst($ipaddress,'^([0-9]+)[.]([0-9]+)[.]([0-9]+)[.]([0-9]+)$','\\3')
Put angle brackets around each octet in the node's IP address::
- $x = regsubst($ipaddress, '([0-9]+)', '<\\1>', 'G')
+ $x = regsubst($ipaddress, '([0-9]+)', '<\\1>', 'G')
") \
- do |args|
- unless args.length.between?(3, 5)
-
- raise(
- Puppet::ParseError,
-
- "regsubst(): got #{args.length} arguments, expected 3 to 5")
- end
- target, regexp, replacement, flags, lang = args
- reflags = 0
- operation = :sub
- if flags == nil
- flags = []
- elsif flags.respond_to?(:split)
- flags = flags.split('')
- else
-
- raise(
- Puppet::ParseError,
-
- "regsubst(): bad flags parameter #{flags.class}:`#{flags}'")
- end
- flags.each do |f|
- case f
- when 'G' then operation = :gsub
- when 'E' then reflags |= Regexp::EXTENDED
- when 'I' then reflags |= Regexp::IGNORECASE
- when 'M' then reflags |= Regexp::MULTILINE
- else raise(Puppet::ParseError, "regsubst(): bad flag `#{f}'")
- end
- end
- begin
- re = Regexp.compile(regexp, reflags, lang)
- rescue RegexpError, TypeError
-
- raise(
- Puppet::ParseError,
-
- "regsubst(): Bad regular expression `#{regexp}'")
- end
- if target.respond_to?(operation)
- # String parameter -> string result
- result = target.send(operation, re, replacement)
- elsif target.respond_to?(:collect) and
- target.respond_to?(:all?) and
- target.all? { |e| e.respond_to?(operation) }
- # Array parameter -> array result
- result = target.collect { |e|
- e.send(operation, re, replacement)
- }
- else
-
- raise(
- Puppet::ParseError,
-
- "regsubst(): bad target #{target.class}:`#{target}'")
- end
- return result
+ do |args|
+ unless args.length.between?(3, 5)
+
+ raise(
+ Puppet::ParseError,
+
+ "regsubst(): got #{args.length} arguments, expected 3 to 5")
+ end
+ target, regexp, replacement, flags, lang = args
+ reflags = 0
+ operation = :sub
+ if flags == nil
+ flags = []
+ elsif flags.respond_to?(:split)
+ flags = flags.split('')
+ else
+
+ raise(
+ Puppet::ParseError,
+
+ "regsubst(): bad flags parameter #{flags.class}:`#{flags}'")
+ end
+ flags.each do |f|
+ case f
+ when 'G' then operation = :gsub
+ when 'E' then reflags |= Regexp::EXTENDED
+ when 'I' then reflags |= Regexp::IGNORECASE
+ when 'M' then reflags |= Regexp::MULTILINE
+ else raise(Puppet::ParseError, "regsubst(): bad flag `#{f}'")
+ end
+ end
+ begin
+ re = Regexp.compile(regexp, reflags, lang)
+ rescue RegexpError, TypeError
+
+ raise(
+ Puppet::ParseError,
+
+ "regsubst(): Bad regular expression `#{regexp}'")
+ end
+ if target.respond_to?(operation)
+ # String parameter -> string result
+ result = target.send(operation, re, replacement)
+ elsif target.respond_to?(:collect) and
+ target.respond_to?(:all?) and
+ target.all? { |e| e.respond_to?(operation) }
+ # Array parameter -> array result
+ result = target.collect { |e|
+ e.send(operation, re, replacement)
+ }
+ else
+
+ raise(
+ Puppet::ParseError,
+
+ "regsubst(): bad target #{target.class}:`#{target}'")
end
+ return result
+ end
end
diff --git a/lib/puppet/parser/functions/require.rb b/lib/puppet/parser/functions/require.rb
index c5c4c851f..3f98c9523 100644
--- a/lib/puppet/parser/functions/require.rb
+++ b/lib/puppet/parser/functions/require.rb
@@ -1,9 +1,9 @@
# Requires the specified classes
- Puppet::Parser::Functions::newfunction(
- :require,
+ Puppet::Parser::Functions::newfunction(
+ :require,
- :doc =>"Evaluate one or more classes, adding the required class as a dependency.
+ :doc =>"Evaluate one or more classes, adding the required class as a dependency.
The relationship metaparameters work well for specifying relationships
between individual resources, but they can be clumsy for specifying
@@ -12,47 +12,47 @@ relationships between classes. This function is a superset of the
class depends on the required class.
Warning: using require in place of include can lead to unwanted dependency cycles.
- For instance the following manifest, with 'require' instead of 'include'
- would produce a nasty dependence cycle, because notify imposes a before
- between File[/foo] and Service[foo]::
+ For instance the following manifest, with 'require' instead of 'include'
+ would produce a nasty dependence cycle, because notify imposes a before
+ between File[/foo] and Service[foo]::
- class myservice {
- service { foo: ensure => running }
- }
+ class myservice {
+ service { foo: ensure => running }
+ }
- class otherstuff {
- include myservice
- file { '/foo': notify => Service[foo] }
- }
+ class otherstuff {
+ include myservice
+ file { '/foo': notify => Service[foo] }
+ }
Note that this function only works with clients 0.25 and later, and it will
fail if used with earlier clients.
") do |vals|
- # Verify that the 'include' function is loaded
- method = Puppet::Parser::Functions.function(:include)
-
- send(method, vals)
- if resource.metaparam_compatibility_mode?
- warning "The 'require' function is only compatible with clients at 0.25 and above; including class but not adding dependency"
- else
- vals = [vals] unless vals.is_a?(Array)
-
- vals.each do |klass|
- # lookup the class in the scopes
- if classobj = find_hostclass(klass)
- klass = classobj.name
- else
- raise Puppet::ParseError, "Could not find class #{klass}"
- end
-
- # This is a bit hackish, in some ways, but it's the only way
- # to configure a dependency that will make it to the client.
- # The 'obvious' way is just to add an edge in the catalog,
- # but that is considered a containment edge, not a dependency
- # edge, so it usually gets lost on the client.
- ref = Puppet::Resource.new(:class, klass)
- resource.set_parameter(:require, [resource[:require]].flatten.compact << ref)
- end
+ # Verify that the 'include' function is loaded
+ method = Puppet::Parser::Functions.function(:include)
+
+ send(method, vals)
+ if resource.metaparam_compatibility_mode?
+ warning "The 'require' function is only compatible with clients at 0.25 and above; including class but not adding dependency"
+ else
+ vals = [vals] unless vals.is_a?(Array)
+
+ vals.each do |klass|
+ # lookup the class in the scopes
+ if classobj = find_hostclass(klass)
+ klass = classobj.name
+ else
+ raise Puppet::ParseError, "Could not find class #{klass}"
+ end
+
+ # This is a bit hackish, in some ways, but it's the only way
+ # to configure a dependency that will make it to the client.
+ # The 'obvious' way is just to add an edge in the catalog,
+ # but that is considered a containment edge, not a dependency
+ # edge, so it usually gets lost on the client.
+ ref = Puppet::Resource.new(:class, klass)
+ resource.set_parameter(:require, [resource[:require]].flatten.compact << ref)
end
+ end
end
diff --git a/lib/puppet/parser/functions/search.rb b/lib/puppet/parser/functions/search.rb
index 87dd02d67..8a9c7c8be 100644
--- a/lib/puppet/parser/functions/search.rb
+++ b/lib/puppet/parser/functions/search.rb
@@ -1,7 +1,7 @@
Puppet::Parser::Functions::newfunction(:search, :doc => "Add another namespace for this class to search.
- This allows you to create classes with sets of definitions and add
- those classes to another class's search path.") do |vals|
- vals.each do |val|
- add_namespace(val)
- end
+ This allows you to create classes with sets of definitions and add
+ those classes to another class's search path.") do |vals|
+ vals.each do |val|
+ add_namespace(val)
+ end
end
diff --git a/lib/puppet/parser/functions/sha1.rb b/lib/puppet/parser/functions/sha1.rb
index 432825ee9..10cc55cfe 100644
--- a/lib/puppet/parser/functions/sha1.rb
+++ b/lib/puppet/parser/functions/sha1.rb
@@ -1,5 +1,5 @@
Puppet::Parser::Functions::newfunction(:sha1, :type => :rvalue, :doc => "Returns a SHA1 hash value from a provided string.") do |args|
- require 'sha1'
+ require 'sha1'
- Digest::SHA1.hexdigest(args[0])
+ Digest::SHA1.hexdigest(args[0])
end
diff --git a/lib/puppet/parser/functions/shellquote.rb b/lib/puppet/parser/functions/shellquote.rb
index 888b9769d..3ddb988f2 100644
--- a/lib/puppet/parser/functions/shellquote.rb
+++ b/lib/puppet/parser/functions/shellquote.rb
@@ -1,39 +1,39 @@
module Puppet::Parser::Functions
- Safe = 'a-zA-Z0-9@%_+=:,./-' # Safe unquoted
- Dangerous = '!"`$\\' # Unsafe inside double quotes
+ Safe = 'a-zA-Z0-9@%_+=:,./-' # Safe unquoted
+ Dangerous = '!"`$\\' # Unsafe inside double quotes
- newfunction(:shellquote, :type => :rvalue, :doc => "\
- Quote and concatenate arguments for use in Bourne shell.
+ newfunction(:shellquote, :type => :rvalue, :doc => "\
+ Quote and concatenate arguments for use in Bourne shell.
- Each argument is quoted separately, and then all are concatenated
- with spaces. If an argument is an array, the elements of that
- array is interpolated within the rest of the arguments; this makes
- it possible to have an array of arguments and pass that array to
- shellquote instead of having to specify each argument
- individually in the call.
- ") \
- do |args|
+ Each argument is quoted separately, and then all are concatenated
+ with spaces. If an argument is an array, the elements of that
+ array is interpolated within the rest of the arguments; this makes
+ it possible to have an array of arguments and pass that array to
+ shellquote instead of having to specify each argument
+ individually in the call.
+ ") \
+ do |args|
- result = []
- args.flatten.each do |word|
- if word.length != 0 and word.count(Safe) == word.length
- result << word
- elsif word.count(Dangerous) == 0
- result << ('"' + word + '"')
- elsif word.count("'") == 0
- result << ("'" + word + "'")
- else
- r = '"'
- word.each_byte do |c|
- r += "\\" if Dangerous.include?(c)
- r += c.chr
- end
- r += '"'
- result << r
- end
+ result = []
+ args.flatten.each do |word|
+ if word.length != 0 and word.count(Safe) == word.length
+ result << word
+ elsif word.count(Dangerous) == 0
+ result << ('"' + word + '"')
+ elsif word.count("'") == 0
+ result << ("'" + word + "'")
+ else
+ r = '"'
+ word.each_byte do |c|
+ r += "\\" if Dangerous.include?(c)
+ r += c.chr
end
-
- return result.join(" ")
+ r += '"'
+ result << r
+ end
end
+
+ return result.join(" ")
+ end
end
diff --git a/lib/puppet/parser/functions/split.rb b/lib/puppet/parser/functions/split.rb
index 09caa18aa..5d0a9dabc 100644
--- a/lib/puppet/parser/functions/split.rb
+++ b/lib/puppet/parser/functions/split.rb
@@ -1,17 +1,17 @@
module Puppet::Parser::Functions
- newfunction(
- :split, :type => :rvalue,
+ newfunction(
+ :split, :type => :rvalue,
- :doc => "\
+ :doc => "\
Split a string variable into an array using the specified split regexp.
- Usage::
+ Usage::
- $string = 'v1.v2:v3.v4'
- $array_var1 = split($string, ':')
- $array_var2 = split($string, '[.]')
- $array_var3 = split($string, '[.:]')
+ $string = 'v1.v2:v3.v4'
+ $array_var1 = split($string, ':')
+ $array_var2 = split($string, '[.]')
+ $array_var3 = split($string, '[.:]')
$array_var1 now holds the result ['v1.v2', 'v3.v4'],
while $array_var2 holds ['v1', 'v2:v3', 'v4'], and
@@ -22,8 +22,8 @@ a regexp meta-character (.), and that needs protection. A simple
way to do that for a single character is to enclose it in square
brackets.") do |args|
- raise Puppet::ParseError, ("split(): wrong number of arguments (#{args.length}; must be 2)") if args.length != 2
+ raise Puppet::ParseError, ("split(): wrong number of arguments (#{args.length}; must be 2)") if args.length != 2
- return args[0].split(Regexp.compile(args[1]))
- end
+ return args[0].split(Regexp.compile(args[1]))
+ end
end
diff --git a/lib/puppet/parser/functions/sprintf.rb b/lib/puppet/parser/functions/sprintf.rb
index af0a7213e..5ada0fed7 100644
--- a/lib/puppet/parser/functions/sprintf.rb
+++ b/lib/puppet/parser/functions/sprintf.rb
@@ -1,13 +1,13 @@
module Puppet::Parser::Functions
- newfunction(
- :sprintf, :type => :rvalue,
+ newfunction(
+ :sprintf, :type => :rvalue,
- :doc => "Perform printf-style formatting of text.
+ :doc => "Perform printf-style formatting of text.
- The first parameter is format string describing how the rest of the parameters should be formatted. See the documentation for the ``Kernel::sprintf`` function in Ruby for all the details.") do |args|
- raise Puppet::ParseError, 'sprintf() needs at least one argument' if args.length < 1
- fmt = args.shift
- return sprintf(fmt, *args)
- end
+ The first parameter is format string describing how the rest of the parameters should be formatted. See the documentation for the ``Kernel::sprintf`` function in Ruby for all the details.") do |args|
+ raise Puppet::ParseError, 'sprintf() needs at least one argument' if args.length < 1
+ fmt = args.shift
+ return sprintf(fmt, *args)
+ end
end
diff --git a/lib/puppet/parser/functions/tag.rb b/lib/puppet/parser/functions/tag.rb
index 3e487feaf..84df175eb 100644
--- a/lib/puppet/parser/functions/tag.rb
+++ b/lib/puppet/parser/functions/tag.rb
@@ -1,6 +1,6 @@
# Tag the current scope with each passed name
Puppet::Parser::Functions::newfunction(:tag, :doc => "Add the specified tags to the containing class
- or definition. All contained objects will then acquire that tag, also.
- ") do |vals|
- self.resource.tag(*vals)
+ or definition. All contained objects will then acquire that tag, also.
+ ") do |vals|
+ self.resource.tag(*vals)
end
diff --git a/lib/puppet/parser/functions/tagged.rb b/lib/puppet/parser/functions/tagged.rb
index fccb13205..aaa2adfad 100644
--- a/lib/puppet/parser/functions/tagged.rb
+++ b/lib/puppet/parser/functions/tagged.rb
@@ -1,18 +1,18 @@
# Test whether a given tag is set. This functions as a big OR -- if any of the specified tags are unset, we return false.
Puppet::Parser::Functions::newfunction(:tagged, :type => :rvalue, :doc => "A boolean function that
- tells you whether the current container is tagged with the specified tags.
- The tags are ANDed, so that all of the specified tags must be included for
- the function to return true.") do |vals|
- configtags = compiler.catalog.tags
- resourcetags = resource.tags
+ tells you whether the current container is tagged with the specified tags.
+ The tags are ANDed, so that all of the specified tags must be included for
+ the function to return true.") do |vals|
+ configtags = compiler.catalog.tags
+ resourcetags = resource.tags
- retval = true
- vals.each do |val|
- unless configtags.include?(val) or resourcetags.include?(val)
- retval = false
- break
- end
- end
+ retval = true
+ vals.each do |val|
+ unless configtags.include?(val) or resourcetags.include?(val)
+ retval = false
+ break
+ end
+ end
- return retval
+ return retval
end
diff --git a/lib/puppet/parser/functions/template.rb b/lib/puppet/parser/functions/template.rb
index 6c4873efe..f51bcc1e2 100644
--- a/lib/puppet/parser/functions/template.rb
+++ b/lib/puppet/parser/functions/template.rb
@@ -1,22 +1,22 @@
Puppet::Parser::Functions::newfunction(:template, :type => :rvalue, :doc =>
- "Evaluate a template and return its value. See `the templating docs
- <http://docs.puppetlabs.com/guides/templating.html>`_ for more information.
- Note that if multiple templates are specified, their output is all
- concatenated and returned as the output of the function.") do |vals|
- require 'erb'
+ "Evaluate a template and return its value. See `the templating docs
+ <http://docs.puppetlabs.com/guides/templating.html>`_ for more information.
+ Note that if multiple templates are specified, their output is all
+ concatenated and returned as the output of the function.") do |vals|
+ require 'erb'
- vals.collect do |file|
- # Use a wrapper, so the template can't get access to the full
- # Scope object.
- debug "Retrieving template #{file}"
+ vals.collect do |file|
+ # Use a wrapper, so the template can't get access to the full
+ # Scope object.
+ debug "Retrieving template #{file}"
- wrapper = Puppet::Parser::TemplateWrapper.new(self)
- wrapper.file = file
- begin
- wrapper.result
- rescue => detail
- raise Puppet::ParseError,
- "Failed to parse template #{file}: #{detail}"
- end
- end.join("")
+ wrapper = Puppet::Parser::TemplateWrapper.new(self)
+ wrapper.file = file
+ begin
+ wrapper.result
+ rescue => detail
+ raise Puppet::ParseError,
+ "Failed to parse template #{file}: #{detail}"
+ end
+ end.join("")
end
diff --git a/lib/puppet/parser/functions/versioncmp.rb b/lib/puppet/parser/functions/versioncmp.rb
index b8d39af96..b38406532 100644
--- a/lib/puppet/parser/functions/versioncmp.rb
+++ b/lib/puppet/parser/functions/versioncmp.rb
@@ -1,34 +1,34 @@
require 'puppet/util/package'
- Puppet::Parser::Functions::newfunction(
- :versioncmp, :type => :rvalue,
+ Puppet::Parser::Functions::newfunction(
+ :versioncmp, :type => :rvalue,
- :doc => "Compares two versions
+ :doc => "Compares two versions
Prototype::
- \$result = versioncmp(a, b)
+ \$result = versioncmp(a, b)
- where a and b are arbitrary version strings
+ 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
+ * > 0 if version a is greater than version b
+ * == 0 if both version are equals
+ * < 0 if version a is less than version b
Example::
- if versioncmp('2.6-1', '2.4.5') > 0 {
- notice('2.6-1 is > than 2.4.5')
- }
+ if versioncmp('2.6-1', '2.4.5') > 0 {
+ notice('2.6-1 is > than 2.4.5')
+ }
") do |args|
- unless args.length == 2
- raise Puppet::ParseError, "versioncmp should have 2 arguments"
- end
+ unless args.length == 2
+ raise Puppet::ParseError, "versioncmp should have 2 arguments"
+ end
- return Puppet::Util::Package.versioncmp(args[0], args[1])
+ return Puppet::Util::Package.versioncmp(args[0], args[1])
end
diff --git a/lib/puppet/parser/grammar.ra b/lib/puppet/parser/grammar.ra
index 9fa8f5069..7a316d4d7 100644
--- a/lib/puppet/parser/grammar.ra
+++ b/lib/puppet/parser/grammar.ra
@@ -15,73 +15,73 @@ token MATCH NOMATCH REGEX IN_EDGE OUT_EDGE IN_EDGE_SUB OUT_EDGE_SUB
token IN
prechigh
- right NOT
- nonassoc UMINUS
- left IN MATCH NOMATCH
- left TIMES DIV
- left MINUS PLUS
- left LSHIFT RSHIFT
- left NOTEQUAL ISEQUAL
- left GREATEREQUAL GREATERTHAN LESSTHAN LESSEQUAL
- left AND
- left OR
+ right NOT
+ nonassoc UMINUS
+ left IN MATCH NOMATCH
+ left TIMES DIV
+ left MINUS PLUS
+ left LSHIFT RSHIFT
+ left NOTEQUAL ISEQUAL
+ left GREATEREQUAL GREATERTHAN LESSTHAN LESSEQUAL
+ left AND
+ left OR
preclow
rule
program: statements {
- if val[0]
- # Make sure we always return an array.
- if val[0].is_a?(AST::ASTArray)
- if val[0].children.empty?
- result = nil
- else
- result = val[0]
- end
- else
- result = aryfy(val[0])
- end
- else
+ if val[0]
+ # Make sure we always return an array.
+ if val[0].is_a?(AST::ASTArray)
+ if val[0].children.empty?
result = nil
+ else
+ result = val[0]
+ end
+ else
+ result = aryfy(val[0])
end
+ else
+ result = nil
+ end
}
- | nil
+ | nil
statements: statement
- | statements statement {
- if val[0] and val[1]
- if val[0].instance_of?(AST::ASTArray)
- val[0].push(val[1])
- result = val[0]
- else
- result = ast AST::ASTArray, :children => [val[0],val[1]]
- end
- elsif obj = (val[0] || val[1])
- result = obj
- else result = nil
+ | statements statement {
+ if val[0] and val[1]
+ if val[0].instance_of?(AST::ASTArray)
+ val[0].push(val[1])
+ result = val[0]
+ else
+ result = ast AST::ASTArray, :children => [val[0],val[1]]
end
+ elsif obj = (val[0] || val[1])
+ result = obj
+ else result = nil
+ end
}
# The main list of valid statements
statement: resource
- | virtualresource
- | collection
- | assignment
- | casestatement
- | ifstatement_begin
- | import
- | fstatement
- | definition
- | hostclass
- | nodedef
- | resourceoverride
- | append
- | relationship
+ | virtualresource
+ | collection
+ | assignment
+ | casestatement
+ | ifstatement_begin
+ | import
+ | fstatement
+ | definition
+ | hostclass
+ | nodedef
+ | resourceoverride
+ | append
+ | relationship
relationship: relationship_side edge relationship_side {
- result = AST::Relationship.new(val[0], val[2], val[1][:value], ast_context)
+ result = AST::Relationship.new(val[0], val[2], val[1][:value], ast_context)
}
- | relationship edge relationship_side {
- result = AST::Relationship.new(val[0], val[2], val[1][:value], ast_context)
+ | relationship edge relationship_side {
+ result = AST::Relationship.new(val[0], val[2], val[1][:value], ast_context)
}
relationship_side: resource | resourceref | collection
@@ -89,411 +89,411 @@ relationship_side: resource | resourceref | collection
edge: IN_EDGE | OUT_EDGE | IN_EDGE_SUB | OUT_EDGE_SUB
fstatement: NAME LPAREN funcvalues RPAREN {
- args = aryfy(val[2])
- result = ast AST::Function,
- :name => val[0][:value],
- :line => val[0][:line],
- :arguments => args,
- :ftype => :statement
+ args = aryfy(val[2])
+ result = ast AST::Function,
+ :name => val[0][:value],
+ :line => val[0][:line],
+ :arguments => args,
+ :ftype => :statement
}
| NAME LPAREN funcvalues COMMA RPAREN {
- args = aryfy(val[2])
- result = ast AST::Function,
- :name => val[0][:value],
- :line => val[0][:line],
- :arguments => args,
- :ftype => :statement
+ args = aryfy(val[2])
+ result = ast AST::Function,
+ :name => val[0][:value],
+ :line => val[0][:line],
+ :arguments => args,
+ :ftype => :statement
} | NAME LPAREN RPAREN {
+ result = ast AST::Function,
+ :name => val[0][:value],
+ :line => val[0][:line],
+ :arguments => AST::ASTArray.new({}),
+ :ftype => :statement
+}
+ | NAME funcvalues {
+ args = aryfy(val[1])
result = ast AST::Function,
- :name => val[0][:value],
- :line => val[0][:line],
- :arguments => AST::ASTArray.new({}),
- :ftype => :statement
-}
- | NAME funcvalues {
- args = aryfy(val[1])
- result = ast AST::Function,
- :name => val[0][:value],
- :line => val[0][:line],
- :arguments => args,
- :ftype => :statement
+ :name => val[0][:value],
+ :line => val[0][:line],
+ :arguments => args,
+ :ftype => :statement
}
funcvalues: namestring
- | resourceref
- | funcvalues COMMA namestring {
- result = aryfy(val[0], val[2])
- result.line = @lexer.line
- result.file = @lexer.file
-}
- | funcvalues COMMA resourceref {
- unless val[0].is_a?(AST::ASTArray)
- val[0] = aryfy(val[0])
- end
+ | resourceref
+ | funcvalues COMMA namestring {
+ result = aryfy(val[0], val[2])
+ result.line = @lexer.line
+ result.file = @lexer.file
+}
+ | funcvalues COMMA resourceref {
+ unless val[0].is_a?(AST::ASTArray)
+ val[0] = aryfy(val[0])
+ end
- val[0].push(val[2])
+ val[0].push(val[2])
- result = val[0]
+ result = val[0]
}
# This is *almost* an rvalue, but I couldn't get a full
# rvalue to work without scads of shift/reduce conflicts.
namestring: name
- | variable
- | type
- | boolean
- | funcrvalue
- | selector
- | quotedtext
- | hasharrayaccesses
- | CLASSNAME {
- result = ast AST::Name, :value => val[0][:value]
- }
+ | variable
+ | type
+ | boolean
+ | funcrvalue
+ | selector
+ | quotedtext
+ | hasharrayaccesses
+ | CLASSNAME {
+ result = ast AST::Name, :value => val[0][:value]
+ }
resource: classname LBRACE resourceinstances endsemi RBRACE {
- @lexer.commentpop
- array = val[2]
- array = [array] if array.instance_of?(AST::ResourceInstance)
- result = ast AST::ASTArray
-
- # this iterates across each specified resourceinstance
- array.each { |instance|
- raise Puppet::Dev, "Got something that isn't an instance" unless instance.instance_of?(AST::ResourceInstance)
- # now, i need to somehow differentiate between those things with
- # arrays in their names, and normal things
-
- result.push ast(
- AST::Resource,
- :type => val[0],
- :title => instance[0],
-
- :parameters => instance[1])
- }
+ @lexer.commentpop
+ array = val[2]
+ array = [array] if array.instance_of?(AST::ResourceInstance)
+ result = ast AST::ASTArray
+
+ # this iterates across each specified resourceinstance
+ array.each { |instance|
+ raise Puppet::Dev, "Got something that isn't an instance" unless instance.instance_of?(AST::ResourceInstance)
+ # now, i need to somehow differentiate between those things with
+ # arrays in their names, and normal things
+
+ result.push ast(
+ AST::Resource,
+ :type => val[0],
+ :title => instance[0],
+
+ :parameters => instance[1])
+ }
} | classname LBRACE params endcomma RBRACE {
- # This is a deprecated syntax.
- error "All resource specifications require names"
+ # This is a deprecated syntax.
+ error "All resource specifications require names"
} | classref LBRACE params endcomma RBRACE {
- # a defaults setting for a type
- @lexer.commentpop
- result = ast(AST::ResourceDefaults, :type => val[0], :parameters => val[2])
+ # a defaults setting for a type
+ @lexer.commentpop
+ result = ast(AST::ResourceDefaults, :type => val[0], :parameters => val[2])
}
# Override a value set elsewhere in the configuration.
resourceoverride: resourceref LBRACE anyparams endcomma RBRACE {
- @lexer.commentpop
- result = ast AST::ResourceOverride, :object => val[0], :parameters => val[2]
+ @lexer.commentpop
+ result = ast AST::ResourceOverride, :object => val[0], :parameters => val[2]
}
# Exported and virtual resources; these don't get sent to the client
# unless they get collected elsewhere in the db.
virtualresource: at resource {
- type = val[0]
+ type = val[0]
- if (type == :exported and ! Puppet[:storeconfigs]) and ! Puppet[:parseonly]
- Puppet.warning addcontext("You cannot collect without storeconfigs being set")
- end
+ if (type == :exported and ! Puppet[:storeconfigs]) and ! Puppet[:parseonly]
+ Puppet.warning addcontext("You cannot collect without storeconfigs being set")
+ end
- error "Defaults are not virtualizable" if val[1].is_a? AST::ResourceDefaults
+ error "Defaults are not virtualizable" if val[1].is_a? AST::ResourceDefaults
- method = type.to_s + "="
+ method = type.to_s + "="
- # Just mark our resources as exported and pass them through.
- if val[1].instance_of?(AST::ASTArray)
- val[1].each do |obj|
- obj.send(method, true)
- end
- else
- val[1].send(method, true)
+ # Just mark our resources as exported and pass them through.
+ if val[1].instance_of?(AST::ASTArray)
+ val[1].each do |obj|
+ obj.send(method, true)
end
+ else
+ val[1].send(method, true)
+ end
- result = val[1]
+ result = val[1]
}
at: AT { result = :virtual }
- | AT AT { result = :exported }
+ | AT AT { result = :exported }
# A collection statement. Currently supports no arguments at all, but eventually
# will, I assume.
collection: classref collectrhand LBRACE anyparams endcomma RBRACE {
- @lexer.commentpop
- Puppet.warning addcontext("Collection names must now be capitalized") if val[0] =~ /^[a-z]/
- type = val[0].downcase
- args = {:type => type}
-
- if val[1].is_a?(AST::CollExpr)
- args[:query] = val[1]
- args[:query].type = type
- args[:form] = args[:query].form
- else
- args[:form] = val[1]
- end
- if args[:form] == :exported and ! Puppet[:storeconfigs] and ! Puppet[:parseonly]
- Puppet.warning addcontext("You cannot collect exported resources without storeconfigs being set; the collection will be ignored")
- end
- args[:override] = val[3]
- result = ast AST::Collection, args
-}
- | classref collectrhand {
- if val[0] =~ /^[a-z]/
- Puppet.warning addcontext("Collection names must now be capitalized")
- end
- type = val[0].downcase
- args = {:type => type }
-
- if val[1].is_a?(AST::CollExpr)
- args[:query] = val[1]
- args[:query].type = type
- args[:form] = args[:query].form
- else
- args[:form] = val[1]
- end
- if args[:form] == :exported and ! Puppet[:storeconfigs] and ! Puppet[:parseonly]
- Puppet.warning addcontext("You cannot collect exported resources without storeconfigs being set; the collection will be ignored")
- end
- result = ast AST::Collection, args
+ @lexer.commentpop
+ Puppet.warning addcontext("Collection names must now be capitalized") if val[0] =~ /^[a-z]/
+ type = val[0].downcase
+ args = {:type => type}
+
+ if val[1].is_a?(AST::CollExpr)
+ args[:query] = val[1]
+ args[:query].type = type
+ args[:form] = args[:query].form
+ else
+ args[:form] = val[1]
+ end
+ if args[:form] == :exported and ! Puppet[:storeconfigs] and ! Puppet[:parseonly]
+ Puppet.warning addcontext("You cannot collect exported resources without storeconfigs being set; the collection will be ignored")
+ end
+ args[:override] = val[3]
+ result = ast AST::Collection, args
+}
+ | classref collectrhand {
+ if val[0] =~ /^[a-z]/
+ Puppet.warning addcontext("Collection names must now be capitalized")
+ end
+ type = val[0].downcase
+ args = {:type => type }
+
+ if val[1].is_a?(AST::CollExpr)
+ args[:query] = val[1]
+ args[:query].type = type
+ args[:form] = args[:query].form
+ else
+ args[:form] = val[1]
+ end
+ if args[:form] == :exported and ! Puppet[:storeconfigs] and ! Puppet[:parseonly]
+ Puppet.warning addcontext("You cannot collect exported resources without storeconfigs being set; the collection will be ignored")
+ end
+ result = ast AST::Collection, args
}
collectrhand: LCOLLECT collstatements RCOLLECT {
- if val[1]
- result = val[1]
- result.form = :virtual
- else
- result = :virtual
- end
+ if val[1]
+ result = val[1]
+ result.form = :virtual
+ else
+ result = :virtual
+ end
}
- | LLCOLLECT collstatements RRCOLLECT {
- if val[1]
- result = val[1]
- result.form = :exported
- else
- result = :exported
- end
+ | LLCOLLECT collstatements RRCOLLECT {
+ if val[1]
+ result = val[1]
+ result.form = :exported
+ else
+ result = :exported
+ end
}
# A mini-language for handling collection comparisons. This is organized
# to avoid the need for precedence indications.
collstatements: nil
- | collstatement
- | collstatements colljoin collstatement {
- result = ast AST::CollExpr, :test1 => val[0], :oper => val[1], :test2 => val[2]
+ | collstatement
+ | collstatements colljoin collstatement {
+ result = ast AST::CollExpr, :test1 => val[0], :oper => val[1], :test2 => val[2]
}
collstatement: collexpr
- | LPAREN collstatements RPAREN {
- result = val[1]
- result.parens = true
+ | LPAREN collstatements RPAREN {
+ result = val[1]
+ result.parens = true
}
colljoin: AND { result=val[0][:value] }
- | OR { result=val[0][:value] }
+ | OR { result=val[0][:value] }
collexpr: colllval ISEQUAL simplervalue {
+ result = ast AST::CollExpr, :test1 => val[0], :oper => val[1][:value], :test2 => val[2]
+ #result = ast AST::CollExpr
+ #result.push *val
+}
+ | colllval NOTEQUAL simplervalue {
result = ast AST::CollExpr, :test1 => val[0], :oper => val[1][:value], :test2 => val[2]
#result = ast AST::CollExpr
#result.push *val
}
- | colllval NOTEQUAL simplervalue {
- result = ast AST::CollExpr, :test1 => val[0], :oper => val[1][:value], :test2 => val[2]
- #result = ast AST::CollExpr
- #result.push *val
-}
colllval: variable
- | name
+ | name
resourceinst: resourcename COLON params endcomma {
- result = ast AST::ResourceInstance, :children => [val[0],val[2]]
+ result = ast AST::ResourceInstance, :children => [val[0],val[2]]
}
resourceinstances: resourceinst
- | resourceinstances SEMIC resourceinst {
- if val[0].instance_of?(AST::ResourceInstance)
- result = ast AST::ASTArray, :children => [val[0],val[2]]
- else
- val[0].push val[2]
- result = val[0]
- end
+ | resourceinstances SEMIC resourceinst {
+ if val[0].instance_of?(AST::ResourceInstance)
+ result = ast AST::ASTArray, :children => [val[0],val[2]]
+ else
+ val[0].push val[2]
+ result = val[0]
+ end
}
endsemi: # nothing
- | SEMIC
+ | SEMIC
undef: UNDEF {
- result = ast AST::Undef, :value => :undef
+ result = ast AST::Undef, :value => :undef
}
name: NAME {
- result = ast AST::Name, :value => val[0][:value], :line => val[0][:line]
+ result = ast AST::Name, :value => val[0][:value], :line => val[0][:line]
}
type: CLASSREF {
- result = ast AST::Type, :value => val[0][:value], :line => val[0][:line]
+ result = ast AST::Type, :value => val[0][:value], :line => val[0][:line]
}
resourcename: quotedtext
- | name
- | type
- | selector
- | variable
- | array
- | hasharrayaccesses
+ | name
+ | type
+ | selector
+ | variable
+ | array
+ | hasharrayaccesses
assignment: VARIABLE EQUALS expression {
- raise Puppet::ParseError, "Cannot assign to variables in other namespaces" if val[0][:value] =~ /::/
- # this is distinct from referencing a variable
- variable = ast AST::Name, :value => val[0][:value], :line => val[0][:line]
- result = ast AST::VarDef, :name => variable, :value => val[2], :line => val[0][:line]
+ raise Puppet::ParseError, "Cannot assign to variables in other namespaces" if val[0][:value] =~ /::/
+ # this is distinct from referencing a variable
+ variable = ast AST::Name, :value => val[0][:value], :line => val[0][:line]
+ result = ast AST::VarDef, :name => variable, :value => val[2], :line => val[0][:line]
}
- | hasharrayaccess EQUALS expression {
- result = ast AST::VarDef, :name => val[0], :value => val[2]
+ | hasharrayaccess EQUALS expression {
+ result = ast AST::VarDef, :name => val[0], :value => val[2]
}
append: VARIABLE APPENDS expression {
- variable = ast AST::Name, :value => val[0][:value], :line => val[0][:line]
- result = ast AST::VarDef, :name => variable, :value => val[2], :append => true, :line => val[0][:line]
+ variable = ast AST::Name, :value => val[0][:value], :line => val[0][:line]
+ result = ast AST::VarDef, :name => variable, :value => val[2], :append => true, :line => val[0][:line]
}
params: # nothing
{
- result = ast AST::ASTArray
+ result = ast AST::ASTArray
}
- | param { result = val[0] }
- | params COMMA param {
- if val[0].instance_of?(AST::ASTArray)
- val[0].push(val[2])
- result = val[0]
- else
- result = ast AST::ASTArray, :children => [val[0],val[2]]
- end
+ | param { result = val[0] }
+ | params COMMA param {
+ if val[0].instance_of?(AST::ASTArray)
+ val[0].push(val[2])
+ result = val[0]
+ else
+ result = ast AST::ASTArray, :children => [val[0],val[2]]
+ end
}
param: NAME FARROW rvalue {
- result = ast AST::ResourceParam, :param => val[0][:value], :line => val[0][:line], :value => val[2]
+ result = ast AST::ResourceParam, :param => val[0][:value], :line => val[0][:line], :value => val[2]
}
addparam: NAME PARROW rvalue {
- result = ast AST::ResourceParam, :param => val[0][:value], :line => val[0][:line], :value => val[2],
- :add => true
+ result = ast AST::ResourceParam, :param => val[0][:value], :line => val[0][:line], :value => val[2],
+ :add => true
}
anyparam: param
- | addparam
+ | addparam
anyparams: # nothing
{
- result = ast AST::ASTArray
+ result = ast AST::ASTArray
}
- | anyparam { result = val[0] }
- | anyparams COMMA anyparam {
- if val[0].instance_of?(AST::ASTArray)
- val[0].push(val[2])
- result = val[0]
- else
- result = ast AST::ASTArray, :children => [val[0],val[2]]
- end
+ | anyparam { result = val[0] }
+ | anyparams COMMA anyparam {
+ if val[0].instance_of?(AST::ASTArray)
+ val[0].push(val[2])
+ result = val[0]
+ else
+ result = ast AST::ASTArray, :children => [val[0],val[2]]
+ end
}
rvalues: rvalue
- | rvalues comma rvalue {
- if val[0].instance_of?(AST::ASTArray)
- result = val[0].push(val[2])
- else
- result = ast AST::ASTArray, :children => [val[0],val[2]]
- end
+ | rvalues comma rvalue {
+ if val[0].instance_of?(AST::ASTArray)
+ result = val[0].push(val[2])
+ else
+ result = ast AST::ASTArray, :children => [val[0],val[2]]
+ end
}
simplervalue: quotedtext
- | name
- | type
- | boolean
- | selector
- | variable
+ | name
+ | type
+ | boolean
+ | selector
+ | variable
rvalue: quotedtext
- | name
- | type
- | boolean
- | selector
- | variable
- | array
- | hash
- | hasharrayaccesses
- | resourceref
- | funcrvalue
- | undef
+ | name
+ | type
+ | boolean
+ | selector
+ | variable
+ | array
+ | hash
+ | hasharrayaccesses
+ | resourceref
+ | funcrvalue
+ | undef
# We currently require arguments in these functions.
funcrvalue: NAME LPAREN funcvalues RPAREN {
- args = aryfy(val[2])
- result = ast AST::Function,
- :name => val[0][:value], :line => val[0][:line],
- :arguments => args,
- :ftype => :rvalue
+ args = aryfy(val[2])
+ result = ast AST::Function,
+ :name => val[0][:value], :line => val[0][:line],
+ :arguments => args,
+ :ftype => :rvalue
} | NAME LPAREN RPAREN {
- result = ast AST::Function,
- :name => val[0][:value], :line => val[0][:line],
- :arguments => AST::ASTArray.new({}),
- :ftype => :rvalue
+ result = ast AST::Function,
+ :name => val[0][:value], :line => val[0][:line],
+ :arguments => AST::ASTArray.new({}),
+ :ftype => :rvalue
}
quotedtext: STRING { result = ast AST::String, :value => val[0][:value], :line => val[0][:line] }
- | DQPRE dqrval { result = ast AST::Concat, :value => [ast(AST::String,val[0])]+val[1], :line => val[0][:line] }
+ | DQPRE dqrval { result = ast AST::Concat, :value => [ast(AST::String,val[0])]+val[1], :line => val[0][:line] }
dqrval: expression dqtail { result = [val[0]] + val[1] }
dqtail: DQPOST { result = [ast(AST::String,val[0])] }
- | DQMID dqrval { result = [ast(AST::String,val[0])] + val[1] }
+ | DQMID dqrval { result = [ast(AST::String,val[0])] + val[1] }
boolean: BOOLEAN {
- result = ast AST::Boolean, :value => val[0][:value], :line => val[0][:line]
+ result = ast AST::Boolean, :value => val[0][:value], :line => val[0][:line]
}
resourceref: NAME LBRACK rvalues RBRACK {
- Puppet.warning addcontext("Deprecation notice: Resource references should now be capitalized")
- result = ast AST::ResourceReference, :type => val[0][:value], :line => val[0][:line], :title => val[2]
+ Puppet.warning addcontext("Deprecation notice: Resource references should now be capitalized")
+ result = ast AST::ResourceReference, :type => val[0][:value], :line => val[0][:line], :title => val[2]
} | classref LBRACK rvalues RBRACK {
- result = ast AST::ResourceReference, :type => val[0], :title => val[2]
+ result = ast AST::ResourceReference, :type => val[0], :title => val[2]
}
ifstatement_begin: IF ifstatement {
- result = val[1]
+ result = val[1]
}
ifstatement: expression LBRACE statements RBRACE else {
- @lexer.commentpop
- args = {
- :test => val[0],
- :statements => val[2]
- }
+ @lexer.commentpop
+ args = {
+ :test => val[0],
+ :statements => val[2]
+ }
- args[:else] = val[4] if val[4]
+ args[:else] = val[4] if val[4]
- result = ast AST::IfStatement, args
+ result = ast AST::IfStatement, args
}
- | expression LBRACE RBRACE else {
- @lexer.commentpop
- args = {
- :test => val[0],
- :statements => ast(AST::Nop)
- }
+ | expression LBRACE RBRACE else {
+ @lexer.commentpop
+ args = {
+ :test => val[0],
+ :statements => ast(AST::Nop)
+ }
- args[:else] = val[3] if val[3]
+ args[:else] = val[3] if val[3]
- result = ast AST::IfStatement, args
+ result = ast AST::IfStatement, args
}
else: # nothing
- | ELSIF ifstatement {
- result = ast AST::Else, :statements => val[1]
+ | ELSIF ifstatement {
+ result = ast AST::Else, :statements => val[1]
}
- | ELSE LBRACE statements RBRACE {
- @lexer.commentpop
- result = ast AST::Else, :statements => val[2]
+ | ELSE LBRACE statements RBRACE {
+ @lexer.commentpop
+ result = ast AST::Else, :statements => val[2]
}
- | ELSE LBRACE RBRACE {
- @lexer.commentpop
- result = ast AST::Else, :statements => ast(AST::Nop)
+ | ELSE LBRACE RBRACE {
+ @lexer.commentpop
+ result = ast AST::Else, :statements => ast(AST::Nop)
}
# Unlike yacc/bison, it seems racc
@@ -509,343 +509,343 @@ else: # nothing
# per operator :-(
expression: rvalue
- | expression IN rvalue {
- result = ast AST::InOperator, :lval => val[0], :rval => val[2]
+ | expression IN rvalue {
+ result = ast AST::InOperator, :lval => val[0], :rval => val[2]
}
- | expression MATCH regex {
- result = ast AST::MatchOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
+ | expression MATCH regex {
+ result = ast AST::MatchOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
}
- | expression NOMATCH regex {
- result = ast AST::MatchOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
+ | expression NOMATCH regex {
+ result = ast AST::MatchOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
}
- | expression PLUS expression {
- result = ast AST::ArithmeticOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
+ | expression PLUS expression {
+ result = ast AST::ArithmeticOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
}
- | expression MINUS expression {
- result = ast AST::ArithmeticOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
+ | expression MINUS expression {
+ result = ast AST::ArithmeticOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
}
- | expression DIV expression {
- result = ast AST::ArithmeticOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
+ | expression DIV expression {
+ result = ast AST::ArithmeticOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
}
- | expression TIMES expression {
- result = ast AST::ArithmeticOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
+ | expression TIMES expression {
+ result = ast AST::ArithmeticOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
}
- | expression LSHIFT expression {
- result = ast AST::ArithmeticOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
+ | expression LSHIFT expression {
+ result = ast AST::ArithmeticOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
}
- | expression RSHIFT expression {
- result = ast AST::ArithmeticOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
+ | expression RSHIFT expression {
+ result = ast AST::ArithmeticOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
}
- | MINUS expression =UMINUS {
- result = ast AST::Minus, :value => val[1]
+ | MINUS expression =UMINUS {
+ result = ast AST::Minus, :value => val[1]
}
- | expression NOTEQUAL expression {
- result = ast AST::ComparisonOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
+ | expression NOTEQUAL expression {
+ result = ast AST::ComparisonOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
}
- | expression ISEQUAL expression {
- result = ast AST::ComparisonOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
+ | expression ISEQUAL expression {
+ result = ast AST::ComparisonOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
}
- | expression GREATERTHAN expression {
- result = ast AST::ComparisonOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
+ | expression GREATERTHAN expression {
+ result = ast AST::ComparisonOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
}
- | expression GREATEREQUAL expression {
- result = ast AST::ComparisonOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
+ | expression GREATEREQUAL expression {
+ result = ast AST::ComparisonOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
}
- | expression LESSTHAN expression {
- result = ast AST::ComparisonOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
+ | expression LESSTHAN expression {
+ result = ast AST::ComparisonOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
}
- | expression LESSEQUAL expression {
- result = ast AST::ComparisonOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
+ | expression LESSEQUAL expression {
+ result = ast AST::ComparisonOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
}
- | NOT expression {
- result = ast AST::Not, :value => val[1]
+ | NOT expression {
+ result = ast AST::Not, :value => val[1]
}
- | expression AND expression {
- result = ast AST::BooleanOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
+ | expression AND expression {
+ result = ast AST::BooleanOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
}
- | expression OR expression {
- result = ast AST::BooleanOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
+ | expression OR expression {
+ result = ast AST::BooleanOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
}
- | LPAREN expression RPAREN {
- result = val[1]
+ | LPAREN expression RPAREN {
+ result = val[1]
}
casestatement: CASE rvalue LBRACE caseopts RBRACE {
- @lexer.commentpop
- options = val[3]
- options = ast AST::ASTArray, :children => [val[3]] unless options.instance_of?(AST::ASTArray)
- result = ast AST::CaseStatement, :test => val[1], :options => options
+ @lexer.commentpop
+ options = val[3]
+ options = ast AST::ASTArray, :children => [val[3]] unless options.instance_of?(AST::ASTArray)
+ result = ast AST::CaseStatement, :test => val[1], :options => options
}
caseopts: caseopt
- | caseopts caseopt {
- if val[0].instance_of?(AST::ASTArray)
- val[0].push val[1]
- result = val[0]
- else
- result = ast AST::ASTArray, :children => [val[0], val[1]]
- end
+ | caseopts caseopt {
+ if val[0].instance_of?(AST::ASTArray)
+ val[0].push val[1]
+ result = val[0]
+ else
+ result = ast AST::ASTArray, :children => [val[0], val[1]]
+ end
}
caseopt: casevalues COLON LBRACE statements RBRACE {
- @lexer.commentpop
- result = ast AST::CaseOpt, :value => val[0], :statements => val[3]
+ @lexer.commentpop
+ result = ast AST::CaseOpt, :value => val[0], :statements => val[3]
} | casevalues COLON LBRACE RBRACE {
- @lexer.commentpop
+ @lexer.commentpop
- result = ast(
- AST::CaseOpt,
- :value => val[0],
+ result = ast(
+ AST::CaseOpt,
+ :value => val[0],
- :statements => ast(AST::ASTArray)
- )
+ :statements => ast(AST::ASTArray)
+ )
}
casevalues: selectlhand
- | casevalues COMMA selectlhand {
- if val[0].instance_of?(AST::ASTArray)
- val[0].push(val[2])
- result = val[0]
- else
- result = ast AST::ASTArray, :children => [val[0],val[2]]
- end
+ | casevalues COMMA selectlhand {
+ if val[0].instance_of?(AST::ASTArray)
+ val[0].push(val[2])
+ result = val[0]
+ else
+ result = ast AST::ASTArray, :children => [val[0],val[2]]
+ end
}
selector: selectlhand QMARK svalues {
- result = ast AST::Selector, :param => val[0], :values => val[2]
+ result = ast AST::Selector, :param => val[0], :values => val[2]
}
svalues: selectval
- | LBRACE sintvalues endcomma RBRACE {
- @lexer.commentpop
- result = val[1]
+ | LBRACE sintvalues endcomma RBRACE {
+ @lexer.commentpop
+ result = val[1]
}
sintvalues: selectval
- | sintvalues comma selectval {
- if val[0].instance_of?(AST::ASTArray)
- val[0].push(val[2])
- result = val[0]
- else
- result = ast AST::ASTArray, :children => [val[0],val[2]]
- end
+ | sintvalues comma selectval {
+ if val[0].instance_of?(AST::ASTArray)
+ val[0].push(val[2])
+ result = val[0]
+ else
+ result = ast AST::ASTArray, :children => [val[0],val[2]]
+ end
}
selectval: selectlhand FARROW rvalue {
- result = ast AST::ResourceParam, :param => val[0], :value => val[2]
+ result = ast AST::ResourceParam, :param => val[0], :value => val[2]
}
selectlhand: name
- | type
- | quotedtext
- | variable
- | funcrvalue
- | boolean
- | undef
- | DEFAULT {
- result = ast AST::Default, :value => val[0][:value], :line => val[0][:line]
+ | type
+ | quotedtext
+ | variable
+ | funcrvalue
+ | boolean
+ | undef
+ | DEFAULT {
+ result = ast AST::Default, :value => val[0][:value], :line => val[0][:line]
}
- | regex
+ | regex
# These are only used for importing, and we don't interpolate there.
string: STRING { result = [val[0][:value]] }
strings: string
- | strings COMMA string { result = val[0] += val[2] }
+ | strings COMMA string { result = val[0] += val[2] }
import: IMPORT strings {
- val[1].each do |file|
- import(file)
- end
+ val[1].each do |file|
+ import(file)
+ end
- result = AST::ASTArray.new(:children => [])
+ result = AST::ASTArray.new(:children => [])
}
# Disable definition inheritance for now. 8/27/06, luke
#definition: DEFINE NAME argumentlist parent LBRACE statements RBRACE {
definition: DEFINE classname argumentlist LBRACE statements RBRACE {
- @lexer.commentpop
- newdefine classname(val[1]), :arguments => val[2], :code => val[4], :line => val[0][:line]
- @lexer.indefine = false
- result = nil
+ @lexer.commentpop
+ newdefine classname(val[1]), :arguments => val[2], :code => val[4], :line => val[0][:line]
+ @lexer.indefine = false
+ result = nil
#} | DEFINE NAME argumentlist parent LBRACE RBRACE {
} | DEFINE classname argumentlist LBRACE RBRACE {
- @lexer.commentpop
- newdefine classname(val[1]), :arguments => val[2], :line => val[0][:line]
- @lexer.indefine = false
- result = nil
+ @lexer.commentpop
+ newdefine classname(val[1]), :arguments => val[2], :line => val[0][:line]
+ @lexer.indefine = false
+ result = nil
}
#hostclass: CLASS NAME argumentlist parent LBRACE statements RBRACE {
hostclass: CLASS classname argumentlist classparent LBRACE statements RBRACE {
- @lexer.commentpop
- # Our class gets defined in the parent namespace, not our own.
- @lexer.namepop
- newclass classname(val[1]), :arguments => val[2], :parent => val[3], :code => val[5], :line => val[0][:line]
- result = nil
+ @lexer.commentpop
+ # Our class gets defined in the parent namespace, not our own.
+ @lexer.namepop
+ newclass classname(val[1]), :arguments => val[2], :parent => val[3], :code => val[5], :line => val[0][:line]
+ result = nil
} | CLASS classname argumentlist classparent LBRACE RBRACE {
- @lexer.commentpop
- # Our class gets defined in the parent namespace, not our own.
- @lexer.namepop
- newclass classname(val[1]), :arguments => val[2], :parent => val[3], :line => val[0][:line]
- result = nil
+ @lexer.commentpop
+ # Our class gets defined in the parent namespace, not our own.
+ @lexer.namepop
+ newclass classname(val[1]), :arguments => val[2], :parent => val[3], :line => val[0][:line]
+ result = nil
}
nodedef: NODE hostnames nodeparent LBRACE statements RBRACE {
- @lexer.commentpop
- newnode val[1], :parent => val[2], :code => val[4], :line => val[0][:line]
- result = nil
+ @lexer.commentpop
+ newnode val[1], :parent => val[2], :code => val[4], :line => val[0][:line]
+ result = nil
} | NODE hostnames nodeparent LBRACE RBRACE {
- @lexer.commentpop
- newnode val[1], :parent => val[2], :line => val[0][:line]
- result = nil
+ @lexer.commentpop
+ newnode val[1], :parent => val[2], :line => val[0][:line]
+ result = nil
}
classref: CLASSREF { result = val[0][:value] }
classname: NAME { result = val[0][:value] }
- | CLASSNAME { result = val[0][:value] }
- | CLASS { result = "class" }
+ | CLASSNAME { result = val[0][:value] }
+ | CLASS { result = "class" }
# Multiple hostnames, as used for node names. These are all literal
# strings, not AST objects.
hostnames: nodename
- | hostnames COMMA nodename {
- result = val[0]
- result = [result] unless result.is_a?(Array)
- result << val[2]
+ | hostnames COMMA nodename {
+ result = val[0]
+ result = [result] unless result.is_a?(Array)
+ result << val[2]
}
nodename: hostname {
- result = ast AST::HostName, :value => val[0]
+ result = ast AST::HostName, :value => val[0]
}
hostname: NAME { result = val[0][:value] }
- | STRING { result = val[0][:value] }
- | DEFAULT { result = val[0][:value] }
- | regex
+ | STRING { result = val[0][:value] }
+ | DEFAULT { result = val[0][:value] }
+ | regex
nil: {
- result = nil
+ result = nil
}
nothing: {
- result = ast AST::ASTArray, :children => []
+ result = ast AST::ASTArray, :children => []
}
argumentlist: nil
- | LPAREN nothing RPAREN {
- result = nil
+ | LPAREN nothing RPAREN {
+ result = nil
}
- | LPAREN arguments RPAREN {
- result = val[1]
- result = [result] unless result[0].is_a?(Array)
+ | LPAREN arguments RPAREN {
+ result = val[1]
+ result = [result] unless result[0].is_a?(Array)
}
arguments: argument
- | arguments COMMA argument {
- result = val[0]
- result = [result] unless result[0].is_a?(Array)
- result << val[2]
+ | arguments COMMA argument {
+ result = val[0]
+ result = [result] unless result[0].is_a?(Array)
+ result << val[2]
}
argument: NAME EQUALS rvalue {
- Puppet.warning addcontext("Deprecation notice: must now include '$' in prototype")
- result = [val[0][:value], val[2]]
+ Puppet.warning addcontext("Deprecation notice: must now include '$' in prototype")
+ result = [val[0][:value], val[2]]
}
- | NAME {
- Puppet.warning addcontext("Deprecation notice: must now include '$' in prototype")
- result = [val[0][:value]]
+ | NAME {
+ Puppet.warning addcontext("Deprecation notice: must now include '$' in prototype")
+ result = [val[0][:value]]
} | VARIABLE EQUALS rvalue {
- result = [val[0][:value], val[2]]
+ result = [val[0][:value], val[2]]
} | VARIABLE {
- result = [val[0][:value]]
+ result = [val[0][:value]]
}
nodeparent: nil
- | INHERITS hostname {
- result = val[1]
+ | INHERITS hostname {
+ result = val[1]
}
classparent: nil
- | INHERITS classnameordefault {
- result = val[1]
+ | INHERITS classnameordefault {
+ result = val[1]
}
classnameordefault: classname | DEFAULT
variable: VARIABLE {
- result = ast AST::Variable, :value => val[0][:value], :line => val[0][:line]
+ result = ast AST::Variable, :value => val[0][:value], :line => val[0][:line]
}
array: LBRACK rvalues RBRACK {
- if val[1].instance_of?(AST::ASTArray)
- result = val[1]
- else
- result = ast AST::ASTArray, :children => [val[1]]
- end
+ if val[1].instance_of?(AST::ASTArray)
+ result = val[1]
+ else
+ result = ast AST::ASTArray, :children => [val[1]]
+ end
}
- | LBRACK rvalues COMMA RBRACK {
- if val[1].instance_of?(AST::ASTArray)
- result = val[1]
- else
- result = ast AST::ASTArray, :children => [val[1]]
- end
+ | LBRACK rvalues COMMA RBRACK {
+ if val[1].instance_of?(AST::ASTArray)
+ result = val[1]
+ else
+ result = ast AST::ASTArray, :children => [val[1]]
+ end
} | LBRACK RBRACK {
- result = ast AST::ASTArray
+ result = ast AST::ASTArray
}
comma: FARROW
- | COMMA
+ | COMMA
endcomma: # nothing
- | COMMA { result = nil }
+ | COMMA { result = nil }
regex: REGEX {
- result = ast AST::Regex, :value => val[0][:value]
+ result = ast AST::Regex, :value => val[0][:value]
}
hash: LBRACE hashpairs RBRACE {
- if val[1].instance_of?(AST::ASTHash)
- result = val[1]
- else
- result = ast AST::ASTHash, { :value => val[1] }
- end
+ if val[1].instance_of?(AST::ASTHash)
+ result = val[1]
+ else
+ result = ast AST::ASTHash, { :value => val[1] }
+ end
}
- | LBRACE hashpairs COMMA RBRACE {
- if val[1].instance_of?(AST::ASTHash)
- result = val[1]
- else
- result = ast AST::ASTHash, { :value => val[1] }
- end
+ | LBRACE hashpairs COMMA RBRACE {
+ if val[1].instance_of?(AST::ASTHash)
+ result = val[1]
+ else
+ result = ast AST::ASTHash, { :value => val[1] }
+ end
} | LBRACE RBRACE {
- result = ast AST::ASTHash
+ result = ast AST::ASTHash
}
hashpairs: hashpair
- | hashpairs COMMA hashpair {
- if val[0].instance_of?(AST::ASTHash)
- result = val[0].merge(val[2])
- else
- result = ast AST::ASTHash, :value => val[0]
- result.merge(val[2])
- end
+ | hashpairs COMMA hashpair {
+ if val[0].instance_of?(AST::ASTHash)
+ result = val[0].merge(val[2])
+ else
+ result = ast AST::ASTHash, :value => val[0]
+ result.merge(val[2])
+ end
}
hashpair: key FARROW rvalue {
- result = ast AST::ASTHash, { :value => { val[0] => val[2] } }
+ result = ast AST::ASTHash, { :value => { val[0] => val[2] } }
}
key: NAME { result = val[0][:value] }
- | quotedtext { result = val[0] }
+ | quotedtext { result = val[0] }
hasharrayaccess: VARIABLE LBRACK rvalue RBRACK {
- result = ast AST::HashOrArrayAccess, :variable => val[0][:value], :key => val[2]
+ result = ast AST::HashOrArrayAccess, :variable => val[0][:value], :key => val[2]
}
hasharrayaccesses: hasharrayaccess
- | hasharrayaccess LBRACK rvalue RBRACK {
- result = ast AST::HashOrArrayAccess, :variable => val[0], :key => val[2]
+ | hasharrayaccess LBRACK rvalue RBRACK {
+ result = ast AST::HashOrArrayAccess, :variable => val[0], :key => val[2]
}
end
@@ -856,9 +856,9 @@ require 'puppet/parser/lexer'
require 'puppet/parser/ast'
module Puppet
- class ParseError < Puppet::Error; end
- class ImportError < Racc::ParseError; end
- class AlreadyImportedError < ImportError; end
+ class ParseError < Puppet::Error; end
+ class ImportError < Racc::ParseError; end
+ class AlreadyImportedError < ImportError; end
end
---- inner ----
diff --git a/lib/puppet/parser/lexer.rb b/lib/puppet/parser/lexer.rb
index 0c95142f9..6a9f1cfc4 100644
--- a/lib/puppet/parser/lexer.rb
+++ b/lib/puppet/parser/lexer.rb
@@ -5,573 +5,573 @@ require 'puppet'
module Puppet
- class LexError < RuntimeError; end
+ class LexError < RuntimeError; end
end
module Puppet::Parser; end
class Puppet::Parser::Lexer
- attr_reader :last, :file, :lexing_context, :token_queue
+ attr_reader :last, :file, :lexing_context, :token_queue
- attr_accessor :line, :indefine
+ attr_accessor :line, :indefine
- def lex_error msg
- raise Puppet::LexError.new(msg)
- end
-
- class Token
- attr_accessor :regex, :name, :string, :skip, :incr_line, :skip_text, :accumulate
-
- def initialize(regex, name)
- if regex.is_a?(String)
- @name, @string = name, regex
- @regex = Regexp.new(Regexp.escape(@string))
- else
- @name, @regex = name, regex
- end
- end
-
- # MQR: Why not just alias?
- %w{skip accumulate}.each do |method|
- define_method(method+"?") do
- self.send(method)
- end
- end
-
- def to_s
- if self.string
- @string
- else
- @name.to_s
- end
- end
-
- def acceptable?(context={})
- # By default tokens are aceeptable in any context
- true
- end
- end
-
- # Maintain a list of tokens.
- class TokenList
- attr_reader :regex_tokens, :string_tokens
-
- def [](name)
- @tokens[name]
- end
-
- # Create a new token.
- def add_token(name, regex, options = {}, &block)
- token = Token.new(regex, name)
- raise(ArgumentError, "Token #{name} already exists") if @tokens.include?(name)
- @tokens[token.name] = token
- if token.string
- @string_tokens << token
- @tokens_by_string[token.string] = token
- else
- @regex_tokens << token
- end
-
- options.each do |name, option|
- token.send(name.to_s + "=", option)
- end
-
- token.meta_def(:convert, &block) if block_given?
-
- token
- end
-
- def initialize
- @tokens = {}
- @regex_tokens = []
- @string_tokens = []
- @tokens_by_string = {}
- end
-
- # Look up a token by its value, rather than name.
- def lookup(string)
- @tokens_by_string[string]
- end
-
- # Define more tokens.
- def add_tokens(hash)
- hash.each do |regex, name|
- add_token(name, regex)
- end
- end
-
- # Sort our tokens by length, so we know once we match, we're done.
- # This helps us avoid the O(n^2) nature of token matching.
- def sort_tokens
- @string_tokens.sort! { |a, b| b.string.length <=> a.string.length }
- end
- end
+ def lex_error msg
+ raise Puppet::LexError.new(msg)
+ end
- TOKENS = TokenList.new
-
- TOKENS.add_tokens(
-
- '[' => :LBRACK,
- ']' => :RBRACK,
- '{' => :LBRACE,
- '}' => :RBRACE,
- '(' => :LPAREN,
-
- ')' => :RPAREN,
- '=' => :EQUALS,
- '+=' => :APPENDS,
- '==' => :ISEQUAL,
- '>=' => :GREATEREQUAL,
- '>' => :GREATERTHAN,
- '<' => :LESSTHAN,
- '<=' => :LESSEQUAL,
- '!=' => :NOTEQUAL,
- '!' => :NOT,
- ',' => :COMMA,
- '.' => :DOT,
- ':' => :COLON,
- '@' => :AT,
- '<<|' => :LLCOLLECT,
- '->' => :IN_EDGE,
- '<-' => :OUT_EDGE,
- '~>' => :IN_EDGE_SUB,
- '<~' => :OUT_EDGE_SUB,
- '|>>' => :RRCOLLECT,
- '<|' => :LCOLLECT,
- '|>' => :RCOLLECT,
- ';' => :SEMIC,
- '?' => :QMARK,
- '\\' => :BACKSLASH,
- '=>' => :FARROW,
- '+>' => :PARROW,
- '+' => :PLUS,
- '-' => :MINUS,
- '/' => :DIV,
- '*' => :TIMES,
- '<<' => :LSHIFT,
- '>>' => :RSHIFT,
- '=~' => :MATCH,
- '!~' => :NOMATCH,
- %r{([a-z][-\w]*)?(::[a-z][-\w]*)+} => :CLASSNAME, # Require '::' in the class name, else we'd compete with NAME
- %r{((::){0,1}[A-Z][-\w]*)+} => :CLASSREF,
- "<string>" => :STRING,
- "<dqstring up to first interpolation>" => :DQPRE,
- "<dqstring between two interpolations>" => :DQMID,
- "<dqstring after final interpolation>" => :DQPOST,
- "<boolean>" => :BOOLEAN
- )
-
- TOKENS.add_token :NUMBER, %r{\b(?:0[xX][0-9A-Fa-f]+|0?\d+(?:\.\d+)?(?:[eE]-?\d+)?)\b} do |lexer, value|
- [TOKENS[:NAME], value]
- end
- #:stopdoc: # Issue #4161
- def (TOKENS[:NUMBER]).acceptable?(context={})
- ![:DQPRE,:DQMID].include? context[:after]
- end
- #:startdoc:
+ class Token
+ attr_accessor :regex, :name, :string, :skip, :incr_line, :skip_text, :accumulate
- TOKENS.add_token :NAME, %r{[a-z0-9][-\w]*} do |lexer, value|
- string_token = self
- # we're looking for keywords here
- if tmp = KEYWORDS.lookup(value)
- string_token = tmp
- if [:TRUE, :FALSE].include?(string_token.name)
- value = eval(value)
- string_token = TOKENS[:BOOLEAN]
- end
- end
- [string_token, value]
+ def initialize(regex, name)
+ if regex.is_a?(String)
+ @name, @string = name, regex
+ @regex = Regexp.new(Regexp.escape(@string))
+ else
+ @name, @regex = name, regex
+ end
end
- [:NAME,:CLASSNAME,:CLASSREF].each { |name_token|
- #:stopdoc: # Issue #4161
- def (TOKENS[name_token]).acceptable?(context={})
- ![:DQPRE,:DQMID].include? context[:after]
- end
- #:startdoc:
- }
- TOKENS.add_token :COMMENT, %r{#.*}, :accumulate => true, :skip => true do |lexer,value|
- value.sub!(/# ?/,'')
- [self, value]
+ # MQR: Why not just alias?
+ %w{skip accumulate}.each do |method|
+ define_method(method+"?") do
+ self.send(method)
+ end
end
- TOKENS.add_token :MLCOMMENT, %r{/\*(.*?)\*/}m, :accumulate => true, :skip => true do |lexer, value|
- lexer.line += value.count("\n")
- value.sub!(/^\/\* ?/,'')
- value.sub!(/ ?\*\/$/,'')
- [self,value]
+ def to_s
+ if self.string
+ @string
+ else
+ @name.to_s
+ end
end
- TOKENS.add_token :REGEX, %r{/[^/\n]*/} do |lexer, value|
- # Make sure we haven't matched an escaped /
- while value[-2..-2] == '\\'
- other = lexer.scan_until(%r{/})
- value += other
- end
- regex = value.sub(%r{\A/}, "").sub(%r{/\Z}, '').gsub("\\/", "/")
- [self, Regexp.new(regex)]
- end
-
- #:stopdoc: # Issue #4161
- def (TOKENS[:REGEX]).acceptable?(context={})
- [:NODE,:LBRACE,:RBRACE,:MATCH,:NOMATCH,:COMMA].include? context[:after]
+ def acceptable?(context={})
+ # By default tokens are aceeptable in any context
+ true
end
- #:startdoc:
+ end
- TOKENS.add_token :RETURN, "\n", :skip => true, :incr_line => true, :skip_text => true
+ # Maintain a list of tokens.
+ class TokenList
+ attr_reader :regex_tokens, :string_tokens
- TOKENS.add_token :SQUOTE, "'" do |lexer, value|
- [TOKENS[:STRING], lexer.slurpstring(value).first ]
+ def [](name)
+ @tokens[name]
end
- DQ_initial_token_types = {'$' => :DQPRE,'"' => :STRING}
- DQ_continuation_token_types = {'$' => :DQMID,'"' => :DQPOST}
+ # Create a new token.
+ def add_token(name, regex, options = {}, &block)
+ token = Token.new(regex, name)
+ raise(ArgumentError, "Token #{name} already exists") if @tokens.include?(name)
+ @tokens[token.name] = token
+ if token.string
+ @string_tokens << token
+ @tokens_by_string[token.string] = token
+ else
+ @regex_tokens << token
+ end
- TOKENS.add_token :DQUOTE, /"/ do |lexer, value|
- lexer.tokenize_interpolated_string(DQ_initial_token_types)
- end
+ options.each do |name, option|
+ token.send(name.to_s + "=", option)
+ end
- TOKENS.add_token :DQCONT, /\}/ do |lexer, value|
- lexer.tokenize_interpolated_string(DQ_continuation_token_types)
- end
- #:stopdoc: # Issue #4161
- def (TOKENS[:DQCONT]).acceptable?(context={})
- context[:string_interpolation_depth] > 0
- end
- #:startdoc:
+ token.meta_def(:convert, &block) if block_given?
- TOKENS.add_token :DOLLAR_VAR, %r{\$(\w*::)*\w+} do |lexer, value|
- [TOKENS[:VARIABLE],value[1..-1]]
+ token
end
- TOKENS.add_token :VARIABLE, %r{(\w*::)*\w+}
+ def initialize
+ @tokens = {}
+ @regex_tokens = []
+ @string_tokens = []
+ @tokens_by_string = {}
+ end
+
+ # Look up a token by its value, rather than name.
+ def lookup(string)
+ @tokens_by_string[string]
+ end
+
+ # Define more tokens.
+ def add_tokens(hash)
+ hash.each do |regex, name|
+ add_token(name, regex)
+ end
+ end
+
+ # Sort our tokens by length, so we know once we match, we're done.
+ # This helps us avoid the O(n^2) nature of token matching.
+ def sort_tokens
+ @string_tokens.sort! { |a, b| b.string.length <=> a.string.length }
+ end
+ end
+
+ TOKENS = TokenList.new
+
+ TOKENS.add_tokens(
+
+ '[' => :LBRACK,
+ ']' => :RBRACK,
+ '{' => :LBRACE,
+ '}' => :RBRACE,
+ '(' => :LPAREN,
+
+ ')' => :RPAREN,
+ '=' => :EQUALS,
+ '+=' => :APPENDS,
+ '==' => :ISEQUAL,
+ '>=' => :GREATEREQUAL,
+ '>' => :GREATERTHAN,
+ '<' => :LESSTHAN,
+ '<=' => :LESSEQUAL,
+ '!=' => :NOTEQUAL,
+ '!' => :NOT,
+ ',' => :COMMA,
+ '.' => :DOT,
+ ':' => :COLON,
+ '@' => :AT,
+ '<<|' => :LLCOLLECT,
+ '->' => :IN_EDGE,
+ '<-' => :OUT_EDGE,
+ '~>' => :IN_EDGE_SUB,
+ '<~' => :OUT_EDGE_SUB,
+ '|>>' => :RRCOLLECT,
+ '<|' => :LCOLLECT,
+ '|>' => :RCOLLECT,
+ ';' => :SEMIC,
+ '?' => :QMARK,
+ '\\' => :BACKSLASH,
+ '=>' => :FARROW,
+ '+>' => :PARROW,
+ '+' => :PLUS,
+ '-' => :MINUS,
+ '/' => :DIV,
+ '*' => :TIMES,
+ '<<' => :LSHIFT,
+ '>>' => :RSHIFT,
+ '=~' => :MATCH,
+ '!~' => :NOMATCH,
+ %r{([a-z][-\w]*)?(::[a-z][-\w]*)+} => :CLASSNAME, # Require '::' in the class name, else we'd compete with NAME
+ %r{((::){0,1}[A-Z][-\w]*)+} => :CLASSREF,
+ "<string>" => :STRING,
+ "<dqstring up to first interpolation>" => :DQPRE,
+ "<dqstring between two interpolations>" => :DQMID,
+ "<dqstring after final interpolation>" => :DQPOST,
+ "<boolean>" => :BOOLEAN
+ )
+
+ TOKENS.add_token :NUMBER, %r{\b(?:0[xX][0-9A-Fa-f]+|0?\d+(?:\.\d+)?(?:[eE]-?\d+)?)\b} do |lexer, value|
+ [TOKENS[:NAME], value]
+ end
+ #:stopdoc: # Issue #4161
+ def (TOKENS[:NUMBER]).acceptable?(context={})
+ ![:DQPRE,:DQMID].include? context[:after]
+ end
+ #:startdoc:
+
+ TOKENS.add_token :NAME, %r{[a-z0-9][-\w]*} do |lexer, value|
+ string_token = self
+ # we're looking for keywords here
+ if tmp = KEYWORDS.lookup(value)
+ string_token = tmp
+ if [:TRUE, :FALSE].include?(string_token.name)
+ value = eval(value)
+ string_token = TOKENS[:BOOLEAN]
+ end
+ end
+ [string_token, value]
+ end
+ [:NAME,:CLASSNAME,:CLASSREF].each { |name_token|
#:stopdoc: # Issue #4161
- def (TOKENS[:VARIABLE]).acceptable?(context={})
- [:DQPRE,:DQMID].include? context[:after]
+ def (TOKENS[name_token]).acceptable?(context={})
+ ![:DQPRE,:DQMID].include? context[:after]
end
#:startdoc:
-
-
- TOKENS.sort_tokens
-
- @@pairs = {
- "{" => "}",
- "(" => ")",
- "[" => "]",
- "<|" => "|>",
- "<<|" => "|>>"
+ }
+
+ TOKENS.add_token :COMMENT, %r{#.*}, :accumulate => true, :skip => true do |lexer,value|
+ value.sub!(/# ?/,'')
+ [self, value]
+ end
+
+ TOKENS.add_token :MLCOMMENT, %r{/\*(.*?)\*/}m, :accumulate => true, :skip => true do |lexer, value|
+ lexer.line += value.count("\n")
+ value.sub!(/^\/\* ?/,'')
+ value.sub!(/ ?\*\/$/,'')
+ [self,value]
+ end
+
+ TOKENS.add_token :REGEX, %r{/[^/\n]*/} do |lexer, value|
+ # Make sure we haven't matched an escaped /
+ while value[-2..-2] == '\\'
+ other = lexer.scan_until(%r{/})
+ value += other
+ end
+ regex = value.sub(%r{\A/}, "").sub(%r{/\Z}, '').gsub("\\/", "/")
+ [self, Regexp.new(regex)]
+ end
+
+ #:stopdoc: # Issue #4161
+ def (TOKENS[:REGEX]).acceptable?(context={})
+ [:NODE,:LBRACE,:RBRACE,:MATCH,:NOMATCH,:COMMA].include? context[:after]
+ end
+ #:startdoc:
+
+ TOKENS.add_token :RETURN, "\n", :skip => true, :incr_line => true, :skip_text => true
+
+ TOKENS.add_token :SQUOTE, "'" do |lexer, value|
+ [TOKENS[:STRING], lexer.slurpstring(value).first ]
+ end
+
+ DQ_initial_token_types = {'$' => :DQPRE,'"' => :STRING}
+ DQ_continuation_token_types = {'$' => :DQMID,'"' => :DQPOST}
+
+ TOKENS.add_token :DQUOTE, /"/ do |lexer, value|
+ lexer.tokenize_interpolated_string(DQ_initial_token_types)
+ end
+
+ TOKENS.add_token :DQCONT, /\}/ do |lexer, value|
+ lexer.tokenize_interpolated_string(DQ_continuation_token_types)
+ end
+ #:stopdoc: # Issue #4161
+ def (TOKENS[:DQCONT]).acceptable?(context={})
+ context[:string_interpolation_depth] > 0
+ end
+ #:startdoc:
+
+ TOKENS.add_token :DOLLAR_VAR, %r{\$(\w*::)*\w+} do |lexer, value|
+ [TOKENS[:VARIABLE],value[1..-1]]
+ end
+
+ TOKENS.add_token :VARIABLE, %r{(\w*::)*\w+}
+ #:stopdoc: # Issue #4161
+ def (TOKENS[:VARIABLE]).acceptable?(context={})
+ [:DQPRE,:DQMID].include? context[:after]
+ end
+ #:startdoc:
+
+
+ TOKENS.sort_tokens
+
+ @@pairs = {
+ "{" => "}",
+ "(" => ")",
+ "[" => "]",
+ "<|" => "|>",
+ "<<|" => "|>>"
+ }
+
+ KEYWORDS = TokenList.new
+
+
+ KEYWORDS.add_tokens(
+
+ "case" => :CASE,
+ "class" => :CLASS,
+ "default" => :DEFAULT,
+ "define" => :DEFINE,
+ "import" => :IMPORT,
+ "if" => :IF,
+ "elsif" => :ELSIF,
+ "else" => :ELSE,
+ "inherits" => :INHERITS,
+ "node" => :NODE,
+ "and" => :AND,
+ "or" => :OR,
+ "undef" => :UNDEF,
+ "false" => :FALSE,
+ "true" => :TRUE,
+
+ "in" => :IN
+ )
+
+ def clear
+ initvars
+ end
+
+ def expected
+ return nil if @expected.empty?
+ name = @expected[-1]
+ TOKENS.lookup(name) or lex_error "Could not find expected token #{name}"
+ end
+
+ # scan the whole file
+ # basically just used for testing
+ def fullscan
+ array = []
+
+ self.scan { |token, str|
+ # Ignore any definition nesting problems
+ @indefine = false
+ array.push([token,str])
}
-
- KEYWORDS = TokenList.new
-
-
- KEYWORDS.add_tokens(
-
- "case" => :CASE,
- "class" => :CLASS,
- "default" => :DEFAULT,
- "define" => :DEFINE,
- "import" => :IMPORT,
- "if" => :IF,
- "elsif" => :ELSIF,
- "else" => :ELSE,
- "inherits" => :INHERITS,
- "node" => :NODE,
- "and" => :AND,
- "or" => :OR,
- "undef" => :UNDEF,
- "false" => :FALSE,
- "true" => :TRUE,
-
- "in" => :IN
- )
-
- def clear
- initvars
- end
-
- def expected
- return nil if @expected.empty?
- name = @expected[-1]
- TOKENS.lookup(name) or lex_error "Could not find expected token #{name}"
- end
-
- # scan the whole file
- # basically just used for testing
- def fullscan
- array = []
-
- self.scan { |token, str|
- # Ignore any definition nesting problems
- @indefine = false
- array.push([token,str])
- }
- array
- end
-
- def file=(file)
- @file = file
- @line = 1
- @scanner = StringScanner.new(File.read(file))
- end
-
- def shift_token
- @token_queue.shift
- end
-
- def find_string_token
- # We know our longest string token is three chars, so try each size in turn
- # until we either match or run out of chars. This way our worst-case is three
- # tries, where it is otherwise the number of string token we have. Also,
- # the lookups are optimized hash lookups, instead of regex scans.
- #
- s = @scanner.peek(3)
- token = TOKENS.lookup(s[0,3]) || TOKENS.lookup(s[0,2]) || TOKENS.lookup(s[0,1])
- [ token, token && @scanner.scan(token.regex) ]
- end
-
- # Find the next token that matches a regex. We look for these first.
- def find_regex_token
- @regex += 1
- best_token = nil
- best_length = 0
-
- # I tried optimizing based on the first char, but it had
- # a slightly negative affect and was a good bit more complicated.
- TOKENS.regex_tokens.each do |token|
- if length = @scanner.match?(token.regex) and token.acceptable?(lexing_context)
- # We've found a longer match
- if length > best_length
- best_length = length
- best_token = token
- end
- end
+ array
+ end
+
+ def file=(file)
+ @file = file
+ @line = 1
+ @scanner = StringScanner.new(File.read(file))
+ end
+
+ def shift_token
+ @token_queue.shift
+ end
+
+ def find_string_token
+ # We know our longest string token is three chars, so try each size in turn
+ # until we either match or run out of chars. This way our worst-case is three
+ # tries, where it is otherwise the number of string token we have. Also,
+ # the lookups are optimized hash lookups, instead of regex scans.
+ #
+ s = @scanner.peek(3)
+ token = TOKENS.lookup(s[0,3]) || TOKENS.lookup(s[0,2]) || TOKENS.lookup(s[0,1])
+ [ token, token && @scanner.scan(token.regex) ]
+ end
+
+ # Find the next token that matches a regex. We look for these first.
+ def find_regex_token
+ @regex += 1
+ best_token = nil
+ best_length = 0
+
+ # I tried optimizing based on the first char, but it had
+ # a slightly negative affect and was a good bit more complicated.
+ TOKENS.regex_tokens.each do |token|
+ if length = @scanner.match?(token.regex) and token.acceptable?(lexing_context)
+ # We've found a longer match
+ if length > best_length
+ best_length = length
+ best_token = token
end
+ end
+ end
- return best_token, @scanner.scan(best_token.regex) if best_token
- end
-
- # Find the next token, returning the string and the token.
- def find_token
- @find += 1
- shift_token || find_regex_token || find_string_token
- end
+ return best_token, @scanner.scan(best_token.regex) if best_token
+ end
- def indefine?
- if defined?(@indefine)
- @indefine
- else
- false
- end
- end
+ # Find the next token, returning the string and the token.
+ def find_token
+ @find += 1
+ shift_token || find_regex_token || find_string_token
+ end
- def initialize
- @find = 0
- @regex = 0
- initvars
+ def indefine?
+ if defined?(@indefine)
+ @indefine
+ else
+ false
end
+ end
- def initvars
- @line = 1
- @previous_token = nil
- @scanner = nil
- @file = nil
- # AAARRGGGG! okay, regexes in ruby are bloody annoying
- # no one else has "\n" =~ /\s/
- @skip = %r{[ \t\r]+}
-
- @namestack = []
- @token_queue = []
- @indefine = false
- @expected = []
- @commentstack = [ ['', @line] ]
- @lexing_context = {
- :after => nil,
- :start_of_line => true,
- :string_interpolation_depth => 0
- }
- end
+ def initialize
+ @find = 0
+ @regex = 0
+ initvars
+ end
- # Make any necessary changes to the token and/or value.
- def munge_token(token, value)
- @line += 1 if token.incr_line
+ def initvars
+ @line = 1
+ @previous_token = nil
+ @scanner = nil
+ @file = nil
+ # AAARRGGGG! okay, regexes in ruby are bloody annoying
+ # no one else has "\n" =~ /\s/
+ @skip = %r{[ \t\r]+}
- skip if token.skip_text
+ @namestack = []
+ @token_queue = []
+ @indefine = false
+ @expected = []
+ @commentstack = [ ['', @line] ]
+ @lexing_context = {
+ :after => nil,
+ :start_of_line => true,
+ :string_interpolation_depth => 0
+ }
+ end
- return if token.skip and not token.accumulate?
+ # Make any necessary changes to the token and/or value.
+ def munge_token(token, value)
+ @line += 1 if token.incr_line
- token, value = token.convert(self, value) if token.respond_to?(:convert)
+ skip if token.skip_text
- return unless token
+ return if token.skip and not token.accumulate?
- if token.accumulate?
- comment = @commentstack.pop
- comment[0] << value + "\n"
- @commentstack.push(comment)
- end
+ token, value = token.convert(self, value) if token.respond_to?(:convert)
- return if token.skip
+ return unless token
- return token, { :value => value, :line => @line }
+ if token.accumulate?
+ comment = @commentstack.pop
+ comment[0] << value + "\n"
+ @commentstack.push(comment)
end
- # Go up one in the namespace.
- def namepop
- @namestack.pop
- end
+ return if token.skip
- # Collect the current namespace.
- def namespace
- @namestack.join("::")
- end
+ return token, { :value => value, :line => @line }
+ end
- # This value might have :: in it, but we don't care -- it'll be
- # handled normally when joining, and when popping we want to pop
- # this full value, however long the namespace is.
- def namestack(value)
- @namestack << value
- end
-
- def rest
- @scanner.rest
- end
-
- # this is the heart of the lexer
- def scan
- #Puppet.debug("entering scan")
- lex_error "Invalid or empty string" unless @scanner
-
- # Skip any initial whitespace.
- skip
+ # Go up one in the namespace.
+ def namepop
+ @namestack.pop
+ end
- until token_queue.empty? and @scanner.eos? do
- yielded = false
- matched_token, value = find_token
+ # Collect the current namespace.
+ def namespace
+ @namestack.join("::")
+ end
- # error out if we didn't match anything at all
- lex_error "Could not match #{@scanner.rest[/^(\S+|\s+|.*)/]}" unless matched_token
+ # This value might have :: in it, but we don't care -- it'll be
+ # handled normally when joining, and when popping we want to pop
+ # this full value, however long the namespace is.
+ def namestack(value)
+ @namestack << value
+ end
- newline = matched_token.name == :RETURN
+ def rest
+ @scanner.rest
+ end
- # this matches a blank line; eat the previously accumulated comments
- getcomment if lexing_context[:start_of_line] and newline
- lexing_context[:start_of_line] = newline
+ # this is the heart of the lexer
+ def scan
+ #Puppet.debug("entering scan")
+ lex_error "Invalid or empty string" unless @scanner
- final_token, token_value = munge_token(matched_token, value)
+ # Skip any initial whitespace.
+ skip
- unless final_token
- skip
- next
- end
+ until token_queue.empty? and @scanner.eos? do
+ yielded = false
+ matched_token, value = find_token
- lexing_context[:after] = final_token.name unless newline
- lexing_context[:string_interpolation_depth] += 1 if final_token.name == :DQPRE
- lexing_context[:string_interpolation_depth] -= 1 if final_token.name == :DQPOST
+ # error out if we didn't match anything at all
+ lex_error "Could not match #{@scanner.rest[/^(\S+|\s+|.*)/]}" unless matched_token
- value = token_value[:value]
+ newline = matched_token.name == :RETURN
+
+ # this matches a blank line; eat the previously accumulated comments
+ getcomment if lexing_context[:start_of_line] and newline
+ lexing_context[:start_of_line] = newline
- if match = @@pairs[value] and final_token.name != :DQUOTE and final_token.name != :SQUOTE
- @expected << match
- elsif exp = @expected[-1] and exp == value and final_token.name != :DQUOTE and final_token.name != :SQUOTE
- @expected.pop
- end
+ final_token, token_value = munge_token(matched_token, value)
- if final_token.name == :LBRACE
- commentpush
- end
-
- yield [final_token.name, token_value]
+ unless final_token
+ skip
+ next
+ end
- if @previous_token
- namestack(value) if @previous_token.name == :CLASS
+ lexing_context[:after] = final_token.name unless newline
+ lexing_context[:string_interpolation_depth] += 1 if final_token.name == :DQPRE
+ lexing_context[:string_interpolation_depth] -= 1 if final_token.name == :DQPOST
- if @previous_token.name == :DEFINE
- if indefine?
- msg = "Cannot nest definition #{value} inside #{@indefine}"
- self.indefine = false
- raise Puppet::ParseError, msg
- end
+ value = token_value[:value]
- @indefine = value
- end
- end
- @previous_token = final_token
- skip
- end
- @scanner = nil
+ if match = @@pairs[value] and final_token.name != :DQUOTE and final_token.name != :SQUOTE
+ @expected << match
+ elsif exp = @expected[-1] and exp == value and final_token.name != :DQUOTE and final_token.name != :SQUOTE
+ @expected.pop
+ end
- # This indicates that we're done parsing.
- yield [false,false]
- end
+ if final_token.name == :LBRACE
+ commentpush
+ end
- # Skip any skipchars in our remaining string.
- def skip
- @scanner.skip(@skip)
- end
+ yield [final_token.name, token_value]
- # Provide some limited access to the scanner, for those
- # tokens that need it.
- def scan_until(regex)
- @scanner.scan_until(regex)
- end
+ if @previous_token
+ namestack(value) if @previous_token.name == :CLASS
- # we've encountered the start of a string...
- # slurp in the rest of the string and return it
- Valid_escapes_in_strings = %w{ \\ $ ' " n t s }+["\n"]
- def slurpstring(terminators)
- # 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}'"
- @line += str.count("\n") # literal carriage returns add to the line count.
- str.gsub!(/\\(.)/) {
- case ch=$1
- when 'n'; "\n"
- when 't'; "\t"
- when 's'; " "
- else
- if Valid_escapes_in_strings.include? ch and not (ch == '"' and terminators == "'")
- ch
- else
- Puppet.warning "Unrecognised escape sequence '\\#{ch}'#{file && " in file #{file}"}#{line && " at line #{line}"}"
- "\\#{ch}"
- end
- end
- }
- [ str[0..-2],str[-1,1] ]
- end
+ if @previous_token.name == :DEFINE
+ if indefine?
+ msg = "Cannot nest definition #{value} inside #{@indefine}"
+ self.indefine = false
+ raise Puppet::ParseError, msg
+ end
- def tokenize_interpolated_string(token_type)
- value,terminator = slurpstring('"$')
- token_queue << [TOKENS[token_type[terminator]],value]
- while terminator == '$' and not @scanner.scan(/\{/)
- token_queue << [TOKENS[:VARIABLE],@scanner.scan(%r{(\w*::)*\w+|[0-9]})]
- value,terminator = slurpstring('"$')
- token_queue << [TOKENS[DQ_continuation_token_types[terminator]],value]
+ @indefine = value
end
- token_queue.shift
- end
-
- # just parse a string, not a whole file
- def string=(string)
- @scanner = StringScanner.new(string)
- end
-
- # returns the content of the currently accumulated content cache
- def commentpop
- @commentstack.pop[0]
- end
-
- def getcomment(line = nil)
- comment = @commentstack.last
- if line.nil? or comment[1] <= line
- @commentstack.pop
- @commentstack.push(['', @line])
- return comment[0]
+ end
+ @previous_token = final_token
+ skip
+ end
+ @scanner = nil
+
+ # This indicates that we're done parsing.
+ yield [false,false]
+ end
+
+ # Skip any skipchars in our remaining string.
+ def skip
+ @scanner.skip(@skip)
+ end
+
+ # Provide some limited access to the scanner, for those
+ # tokens that need it.
+ def scan_until(regex)
+ @scanner.scan_until(regex)
+ end
+
+ # we've encountered the start of a string...
+ # slurp in the rest of the string and return it
+ Valid_escapes_in_strings = %w{ \\ $ ' " n t s }+["\n"]
+ def slurpstring(terminators)
+ # 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}'"
+ @line += str.count("\n") # literal carriage returns add to the line count.
+ str.gsub!(/\\(.)/) {
+ case ch=$1
+ when 'n'; "\n"
+ when 't'; "\t"
+ when 's'; " "
+ else
+ if Valid_escapes_in_strings.include? ch and not (ch == '"' and terminators == "'")
+ ch
+ else
+ Puppet.warning "Unrecognised escape sequence '\\#{ch}'#{file && " in file #{file}"}#{line && " at line #{line}"}"
+ "\\#{ch}"
end
- ''
- end
-
- def commentpush
- @commentstack.push(['', @line])
- end
+ end
+ }
+ [ str[0..-2],str[-1,1] ]
+ end
+
+ def tokenize_interpolated_string(token_type)
+ value,terminator = slurpstring('"$')
+ token_queue << [TOKENS[token_type[terminator]],value]
+ while terminator == '$' and not @scanner.scan(/\{/)
+ token_queue << [TOKENS[:VARIABLE],@scanner.scan(%r{(\w*::)*\w+|[0-9]})]
+ value,terminator = slurpstring('"$')
+ token_queue << [TOKENS[DQ_continuation_token_types[terminator]],value]
+ end
+ token_queue.shift
+ end
+
+ # just parse a string, not a whole file
+ def string=(string)
+ @scanner = StringScanner.new(string)
+ end
+
+ # returns the content of the currently accumulated content cache
+ def commentpop
+ @commentstack.pop[0]
+ end
+
+ def getcomment(line = nil)
+ comment = @commentstack.last
+ if line.nil? or comment[1] <= line
+ @commentstack.pop
+ @commentstack.push(['', @line])
+ return comment[0]
+ end
+ ''
+ end
+
+ def commentpush
+ @commentstack.push(['', @line])
+ end
end
diff --git a/lib/puppet/parser/parser_support.rb b/lib/puppet/parser/parser_support.rb
index 8dd986bd5..4f3a4ddff 100644
--- a/lib/puppet/parser/parser_support.rb
+++ b/lib/puppet/parser/parser_support.rb
@@ -1,235 +1,235 @@
# I pulled this into a separate file, because I got
# tired of rebuilding the parser.rb file all the time.
class Puppet::Parser::Parser
- require 'puppet/parser/functions'
- require 'puppet/parser/files'
- require 'puppet/resource/type_collection'
- require 'puppet/resource/type_collection_helper'
- require 'puppet/resource/type'
- require 'monitor'
+ require 'puppet/parser/functions'
+ require 'puppet/parser/files'
+ require 'puppet/resource/type_collection'
+ require 'puppet/resource/type_collection_helper'
+ require 'puppet/resource/type'
+ require 'monitor'
- AST = Puppet::Parser::AST
+ AST = Puppet::Parser::AST
- include Puppet::Resource::TypeCollectionHelper
+ include Puppet::Resource::TypeCollectionHelper
- attr_reader :version, :environment
- attr_accessor :files
+ attr_reader :version, :environment
+ attr_accessor :files
- attr_accessor :lexer
-
- # Add context to a message; useful for error messages and such.
- def addcontext(message, obj = nil)
- obj ||= @lexer
-
- message += " on line #{obj.line}"
- if file = obj.file
- message += " in file #{file}"
- end
-
- message
- end
-
- # Create an AST array out of all of the args
- def aryfy(*args)
- if args[0].instance_of?(AST::ASTArray)
- result = args.shift
- args.each { |arg|
- result.push arg
- }
- else
- result = ast AST::ASTArray, :children => args
- end
-
- result
- end
-
- # Create an AST object, and automatically add the file and line information if
- # available.
- def ast(klass, hash = {})
- klass.new ast_context(klass.use_docs).merge(hash)
- end
-
- def ast_context(include_docs = false)
- result = {
- :line => lexer.line,
- :file => lexer.file
- }
- result[:doc] = lexer.getcomment(result[:line]) if include_docs
- result
- end
-
- # The fully qualifed name, with the full namespace.
- def classname(name)
- [@lexer.namespace, name].join("::").sub(/^::/, '')
- end
-
- def clear
- initvars
- end
-
- # Raise a Parse error.
- def error(message)
- if brace = @lexer.expected
- message += "; expected '%s'"
- end
- except = Puppet::ParseError.new(message)
- except.line = @lexer.line
- except.file = @lexer.file if @lexer.file
-
- raise except
- end
-
- def file
- @lexer.file
- end
-
- def file=(file)
- unless FileTest.exist?(file)
- unless file =~ /\.pp$/
- file = file + ".pp"
- end
- raise Puppet::Error, "Could not find file #{file}" unless FileTest.exist?(file)
- end
- raise Puppet::AlreadyImportedError, "Import loop detected" if known_resource_types.watching_file?(file)
-
- watch_file(file)
- @lexer.file = file
- end
-
- [:hostclass, :definition, :node, :nodes?].each do |method|
- define_method(method) do |*args|
- known_resource_types.send(method, *args)
- end
- end
-
- def find_hostclass(namespace, name)
- known_resource_types.find_or_load(namespace, name, :hostclass)
- end
-
- def find_definition(namespace, name)
- known_resource_types.find_or_load(namespace, name, :definition)
- end
-
- def import(file)
- known_resource_types.loader.import(file, @lexer.file)
- end
-
- def initialize(env)
- # The environment is needed to know how to find the resource type collection.
- @environment = env.is_a?(String) ? Puppet::Node::Environment.new(env) : env
- initvars
- end
-
- # Initialize or reset all of our variables.
- def initvars
- @lexer = Puppet::Parser::Lexer.new
- end
-
- # Split an fq name into a namespace and name
- def namesplit(fullname)
- ary = fullname.split("::")
- n = ary.pop || ""
- ns = ary.join("::")
- return ns, n
- end
-
- # Create a new class, or merge with an existing class.
- def newclass(name, options = {})
- known_resource_types.add Puppet::Resource::Type.new(:hostclass, name, ast_context(true).merge(options))
- end
-
- # Create a new definition.
- def newdefine(name, options = {})
- known_resource_types.add Puppet::Resource::Type.new(:definition, name, ast_context(true).merge(options))
- end
-
- # Create a new node. Nodes are special, because they're stored in a global
- # table, not according to namespaces.
- def newnode(names, options = {})
- names = [names] unless names.instance_of?(Array)
- context = ast_context(true)
- names.collect do |name|
- known_resource_types.add(Puppet::Resource::Type.new(:node, name, context.merge(options)))
- end
- end
-
- def on_error(token,value,stack)
- if token == 0 # denotes end of file
- value = 'end of file'
- else
- value = "'#{value[:value]}'"
- end
- error = "Syntax error at #{value}"
-
- if brace = @lexer.expected
- error += "; expected '#{brace}'"
- end
-
- except = Puppet::ParseError.new(error)
- except.line = @lexer.line
- except.file = @lexer.file if @lexer.file
-
- raise except
- end
-
- # how should I do error handling here?
- def parse(string = nil)
- return parse_ruby_file if self.file =~ /\.rb$/
- self.string = string if string
- begin
- @yydebug = false
- main = yyparse(@lexer,:scan)
- rescue Racc::ParseError => except
- error = Puppet::ParseError.new(except)
- error.line = @lexer.line
- error.file = @lexer.file
- error.set_backtrace except.backtrace
- raise error
- rescue Puppet::ParseError => except
- except.line ||= @lexer.line
- except.file ||= @lexer.file
- raise except
- rescue Puppet::Error => except
- # and this is a framework error
- except.line ||= @lexer.line
- except.file ||= @lexer.file
- raise except
- rescue Puppet::DevError => except
- except.line ||= @lexer.line
- except.file ||= @lexer.file
- raise except
- rescue => except
- error = Puppet::DevError.new(except.message)
- error.line = @lexer.line
- error.file = @lexer.file
- error.set_backtrace except.backtrace
- raise error
- end
- if main
- # Store the results as the top-level class.
- newclass("", :code => main)
- end
- return known_resource_types
- ensure
- @lexer.clear
- end
-
- def parse_ruby_file
- require self.file
- end
-
- def string=(string)
- @lexer.string = string
- end
-
- def version
- known_resource_types.version
- end
-
- # Add a new file to be checked when we're checking to see if we should be
- # reparsed. This is basically only used by the TemplateWrapper to let the
- # parser know about templates that should be parsed.
- def watch_file(filename)
- known_resource_types.watch_file(filename)
- end
+ attr_accessor :lexer
+
+ # Add context to a message; useful for error messages and such.
+ def addcontext(message, obj = nil)
+ obj ||= @lexer
+
+ message += " on line #{obj.line}"
+ if file = obj.file
+ message += " in file #{file}"
+ end
+
+ message
+ end
+
+ # Create an AST array out of all of the args
+ def aryfy(*args)
+ if args[0].instance_of?(AST::ASTArray)
+ result = args.shift
+ args.each { |arg|
+ result.push arg
+ }
+ else
+ result = ast AST::ASTArray, :children => args
+ end
+
+ result
+ end
+
+ # Create an AST object, and automatically add the file and line information if
+ # available.
+ def ast(klass, hash = {})
+ klass.new ast_context(klass.use_docs).merge(hash)
+ end
+
+ def ast_context(include_docs = false)
+ result = {
+ :line => lexer.line,
+ :file => lexer.file
+ }
+ result[:doc] = lexer.getcomment(result[:line]) if include_docs
+ result
+ end
+
+ # The fully qualifed name, with the full namespace.
+ def classname(name)
+ [@lexer.namespace, name].join("::").sub(/^::/, '')
+ end
+
+ def clear
+ initvars
+ end
+
+ # Raise a Parse error.
+ def error(message)
+ if brace = @lexer.expected
+ message += "; expected '%s'"
+ end
+ except = Puppet::ParseError.new(message)
+ except.line = @lexer.line
+ except.file = @lexer.file if @lexer.file
+
+ raise except
+ end
+
+ def file
+ @lexer.file
+ end
+
+ def file=(file)
+ unless FileTest.exist?(file)
+ unless file =~ /\.pp$/
+ file = file + ".pp"
+ end
+ raise Puppet::Error, "Could not find file #{file}" unless FileTest.exist?(file)
+ end
+ raise Puppet::AlreadyImportedError, "Import loop detected" if known_resource_types.watching_file?(file)
+
+ watch_file(file)
+ @lexer.file = file
+ end
+
+ [:hostclass, :definition, :node, :nodes?].each do |method|
+ define_method(method) do |*args|
+ known_resource_types.send(method, *args)
+ end
+ end
+
+ def find_hostclass(namespace, name)
+ known_resource_types.find_or_load(namespace, name, :hostclass)
+ end
+
+ def find_definition(namespace, name)
+ known_resource_types.find_or_load(namespace, name, :definition)
+ end
+
+ def import(file)
+ known_resource_types.loader.import(file, @lexer.file)
+ end
+
+ def initialize(env)
+ # The environment is needed to know how to find the resource type collection.
+ @environment = env.is_a?(String) ? Puppet::Node::Environment.new(env) : env
+ initvars
+ end
+
+ # Initialize or reset all of our variables.
+ def initvars
+ @lexer = Puppet::Parser::Lexer.new
+ end
+
+ # Split an fq name into a namespace and name
+ def namesplit(fullname)
+ ary = fullname.split("::")
+ n = ary.pop || ""
+ ns = ary.join("::")
+ return ns, n
+ end
+
+ # Create a new class, or merge with an existing class.
+ def newclass(name, options = {})
+ known_resource_types.add Puppet::Resource::Type.new(:hostclass, name, ast_context(true).merge(options))
+ end
+
+ # Create a new definition.
+ def newdefine(name, options = {})
+ known_resource_types.add Puppet::Resource::Type.new(:definition, name, ast_context(true).merge(options))
+ end
+
+ # Create a new node. Nodes are special, because they're stored in a global
+ # table, not according to namespaces.
+ def newnode(names, options = {})
+ names = [names] unless names.instance_of?(Array)
+ context = ast_context(true)
+ names.collect do |name|
+ known_resource_types.add(Puppet::Resource::Type.new(:node, name, context.merge(options)))
+ end
+ end
+
+ def on_error(token,value,stack)
+ if token == 0 # denotes end of file
+ value = 'end of file'
+ else
+ value = "'#{value[:value]}'"
+ end
+ error = "Syntax error at #{value}"
+
+ if brace = @lexer.expected
+ error += "; expected '#{brace}'"
+ end
+
+ except = Puppet::ParseError.new(error)
+ except.line = @lexer.line
+ except.file = @lexer.file if @lexer.file
+
+ raise except
+ end
+
+ # how should I do error handling here?
+ def parse(string = nil)
+ return parse_ruby_file if self.file =~ /\.rb$/
+ self.string = string if string
+ begin
+ @yydebug = false
+ main = yyparse(@lexer,:scan)
+ rescue Racc::ParseError => except
+ error = Puppet::ParseError.new(except)
+ error.line = @lexer.line
+ error.file = @lexer.file
+ error.set_backtrace except.backtrace
+ raise error
+ rescue Puppet::ParseError => except
+ except.line ||= @lexer.line
+ except.file ||= @lexer.file
+ raise except
+ rescue Puppet::Error => except
+ # and this is a framework error
+ except.line ||= @lexer.line
+ except.file ||= @lexer.file
+ raise except
+ rescue Puppet::DevError => except
+ except.line ||= @lexer.line
+ except.file ||= @lexer.file
+ raise except
+ rescue => except
+ error = Puppet::DevError.new(except.message)
+ error.line = @lexer.line
+ error.file = @lexer.file
+ error.set_backtrace except.backtrace
+ raise error
+ end
+ if main
+ # Store the results as the top-level class.
+ newclass("", :code => main)
+ end
+ return known_resource_types
+ ensure
+ @lexer.clear
+ end
+
+ def parse_ruby_file
+ require self.file
+ end
+
+ def string=(string)
+ @lexer.string = string
+ end
+
+ def version
+ known_resource_types.version
+ end
+
+ # Add a new file to be checked when we're checking to see if we should be
+ # reparsed. This is basically only used by the TemplateWrapper to let the
+ # parser know about templates that should be parsed.
+ def watch_file(filename)
+ known_resource_types.watch_file(filename)
+ end
end
diff --git a/lib/puppet/parser/relationship.rb b/lib/puppet/parser/relationship.rb
index 1d1bad76c..6190df52c 100644
--- a/lib/puppet/parser/relationship.rb
+++ b/lib/puppet/parser/relationship.rb
@@ -1,43 +1,43 @@
class Puppet::Parser::Relationship
- attr_accessor :source, :target, :type
+ attr_accessor :source, :target, :type
- PARAM_MAP = {:relationship => :before, :subscription => :notify}
+ PARAM_MAP = {:relationship => :before, :subscription => :notify}
- def evaluate(catalog)
- if source.is_a?(Puppet::Parser::Collector)
- sources = source.collected.values
- else
- sources = [source]
- end
- if target.is_a?(Puppet::Parser::Collector)
- targets = target.collected.values
- else
- targets = [target]
- end
- sources.each do |s|
- targets.each do |t|
- mk_relationship(s, t, catalog)
- end
- end
+ def evaluate(catalog)
+ if source.is_a?(Puppet::Parser::Collector)
+ sources = source.collected.values
+ else
+ sources = [source]
end
-
- def initialize(source, target, type)
- @source, @target, @type = source, target, type
+ if target.is_a?(Puppet::Parser::Collector)
+ targets = target.collected.values
+ else
+ targets = [target]
end
-
- def param_name
- PARAM_MAP[type] || raise(ArgumentError, "Invalid relationship type #{type}")
+ sources.each do |s|
+ targets.each do |t|
+ mk_relationship(s, t, catalog)
+ end
end
+ end
+
+ def initialize(source, target, type)
+ @source, @target, @type = source, target, type
+ end
- def mk_relationship(source, target, catalog)
- unless source_resource = catalog.resource(source.to_s)
- raise ArgumentError, "Could not find resource '#{source}' for relationship on '#{target}'"
- end
- unless target_resource = catalog.resource(target.to_s)
- raise ArgumentError, "Could not find resource '#{target}' for relationship from '#{source}'"
- end
- Puppet.debug "Adding relationship from #{source.to_s} to #{target.to_s} with '#{param_name}'"
- source_resource[param_name] ||= []
- source_resource[param_name] << target.to_s
+ def param_name
+ PARAM_MAP[type] || raise(ArgumentError, "Invalid relationship type #{type}")
+ end
+
+ def mk_relationship(source, target, catalog)
+ unless source_resource = catalog.resource(source.to_s)
+ raise ArgumentError, "Could not find resource '#{source}' for relationship on '#{target}'"
+ end
+ unless target_resource = catalog.resource(target.to_s)
+ raise ArgumentError, "Could not find resource '#{target}' for relationship from '#{source}'"
end
+ Puppet.debug "Adding relationship from #{source.to_s} to #{target.to_s} with '#{param_name}'"
+ source_resource[param_name] ||= []
+ source_resource[param_name] << target.to_s
+ end
end
diff --git a/lib/puppet/parser/resource.rb b/lib/puppet/parser/resource.rb
index 2d31b40e7..3cccf4f3e 100644
--- a/lib/puppet/parser/resource.rb
+++ b/lib/puppet/parser/resource.rb
@@ -4,323 +4,323 @@ require 'puppet/resource'
# parent is that this class has rules on who can set
# parameters
class Puppet::Parser::Resource < Puppet::Resource
- require 'puppet/parser/resource/param'
- require 'puppet/util/tagging'
- require 'puppet/file_collection/lookup'
- require 'puppet/parser/yaml_trimmer'
- require 'puppet/resource/type_collection_helper'
-
- include Puppet::FileCollection::Lookup
- include Puppet::Resource::TypeCollectionHelper
-
- include Puppet::Util
- include Puppet::Util::MethodHelper
- include Puppet::Util::Errors
- include Puppet::Util::Logging
- include Puppet::Util::Tagging
- include Puppet::Parser::YamlTrimmer
-
- attr_accessor :source, :scope, :rails_id
- attr_accessor :virtual, :override, :translated, :catalog, :evaluated
-
- attr_reader :exported, :parameters
-
- # Determine whether the provided parameter name is a relationship parameter.
- def self.relationship_parameter?(name)
- @relationship_names ||= Puppet::Type.relationship_params.collect { |p| p.name }
- @relationship_names.include?(name)
+ require 'puppet/parser/resource/param'
+ require 'puppet/util/tagging'
+ require 'puppet/file_collection/lookup'
+ require 'puppet/parser/yaml_trimmer'
+ require 'puppet/resource/type_collection_helper'
+
+ include Puppet::FileCollection::Lookup
+ include Puppet::Resource::TypeCollectionHelper
+
+ include Puppet::Util
+ include Puppet::Util::MethodHelper
+ include Puppet::Util::Errors
+ include Puppet::Util::Logging
+ include Puppet::Util::Tagging
+ include Puppet::Parser::YamlTrimmer
+
+ attr_accessor :source, :scope, :rails_id
+ attr_accessor :virtual, :override, :translated, :catalog, :evaluated
+
+ attr_reader :exported, :parameters
+
+ # Determine whether the provided parameter name is a relationship parameter.
+ def self.relationship_parameter?(name)
+ @relationship_names ||= Puppet::Type.relationship_params.collect { |p| p.name }
+ @relationship_names.include?(name)
+ end
+
+ # Set up some boolean test methods
+ [:translated, :override, :evaluated].each do |method|
+ newmeth = (method.to_s + "?").intern
+ define_method(newmeth) do
+ self.send(method)
end
+ end
- # Set up some boolean test methods
- [:translated, :override, :evaluated].each do |method|
- newmeth = (method.to_s + "?").intern
- define_method(newmeth) do
- self.send(method)
- end
- end
-
- def [](param)
- param = symbolize(param)
- if param == :title
- return self.title
- end
- if @parameters.has_key?(param)
- @parameters[param].value
- else
- nil
- end
- end
-
- def []=(param, value)
- set_parameter(param, value)
+ def [](param)
+ param = symbolize(param)
+ if param == :title
+ return self.title
end
-
- def eachparam
- @parameters.each do |name, param|
- yield param
- end
+ if @parameters.has_key?(param)
+ @parameters[param].value
+ else
+ nil
end
+ end
- def environment
- scope.environment
- end
+ def []=(param, value)
+ set_parameter(param, value)
+ end
- # Retrieve the associated definition and evaluate it.
- def evaluate
- if klass = resource_type and ! builtin_type?
- finish
- return klass.evaluate_code(self)
- elsif builtin?
- devfail "Cannot evaluate a builtin type (#{type})"
- else
- self.fail "Cannot find definition #{type}"
- end
- ensure
- @evaluated = true
+ def eachparam
+ @parameters.each do |name, param|
+ yield param
end
-
- # Mark this resource as both exported and virtual,
- # or remove the exported mark.
- def exported=(value)
- if value
- @virtual = true
- @exported = value
- else
- @exported = value
- end
+ end
+
+ def environment
+ scope.environment
+ end
+
+ # Retrieve the associated definition and evaluate it.
+ def evaluate
+ if klass = resource_type and ! builtin_type?
+ finish
+ return klass.evaluate_code(self)
+ elsif builtin?
+ devfail "Cannot evaluate a builtin type (#{type})"
+ else
+ self.fail "Cannot find definition #{type}"
end
-
- # Do any finishing work on this object, called before evaluation or
- # before storage/translation.
- def finish
- return if finished?
- @finished = true
- add_defaults
- add_metaparams
- validate
+ ensure
+ @evaluated = true
+ end
+
+ # Mark this resource as both exported and virtual,
+ # or remove the exported mark.
+ def exported=(value)
+ if value
+ @virtual = true
+ @exported = value
+ else
+ @exported = value
end
-
- # Has this resource already been finished?
- def finished?
- @finished
+ end
+
+ # Do any finishing work on this object, called before evaluation or
+ # before storage/translation.
+ def finish
+ return if finished?
+ @finished = true
+ add_defaults
+ add_metaparams
+ validate
+ end
+
+ # Has this resource already been finished?
+ def finished?
+ @finished
+ end
+
+ def initialize(*args)
+ super
+
+ raise ArgumentError, "Resources require a scope" unless scope
+ @source ||= scope.source
+ end
+
+ # Is this resource modeling an isomorphic resource type?
+ def isomorphic?
+ if builtin_type?
+ return resource_type.isomorphic?
+ else
+ return true
end
-
- def initialize(*args)
- super
-
- raise ArgumentError, "Resources require a scope" unless scope
- @source ||= scope.source
+ end
+
+ # Merge an override resource in. This will throw exceptions if
+ # any overrides aren't allowed.
+ def merge(resource)
+ # Test the resource scope, to make sure the resource is even allowed
+ # to override.
+ unless self.source.object_id == resource.source.object_id || resource.source.child_of?(self.source)
+ raise Puppet::ParseError.new("Only subclasses can override parameters", resource.line, resource.file)
end
-
- # Is this resource modeling an isomorphic resource type?
- def isomorphic?
- if builtin_type?
- return resource_type.isomorphic?
- else
- return true
- end
+ # Some of these might fail, but they'll fail in the way we want.
+ resource.parameters.each do |name, param|
+ override_parameter(param)
end
-
- # Merge an override resource in. This will throw exceptions if
- # any overrides aren't allowed.
- def merge(resource)
- # Test the resource scope, to make sure the resource is even allowed
- # to override.
- unless self.source.object_id == resource.source.object_id || resource.source.child_of?(self.source)
- raise Puppet::ParseError.new("Only subclasses can override parameters", resource.line, resource.file)
- end
- # Some of these might fail, but they'll fail in the way we want.
- resource.parameters.each do |name, param|
- override_parameter(param)
- end
+ end
+
+ # Unless we're running >= 0.25, we're in compat mode.
+ def metaparam_compatibility_mode?
+ ! (catalog and ver = (catalog.client_version||'0.0.0').split(".") and (ver[0] > "0" or ver[1].to_i >= 25))
+ end
+
+ def name
+ self[:name] || self.title
+ end
+
+ def namespaces
+ scope.namespaces
+ end
+
+ # A temporary occasion, until I get paths in the scopes figured out.
+ def path
+ to_s
+ end
+
+ # Define a parameter in our resource.
+ # if we ever receive a parameter named 'tag', set
+ # the resource tags with its value.
+ def set_parameter(param, value = nil)
+ if ! value.nil?
+ param = Puppet::Parser::Resource::Param.new(
+ :name => param, :value => value, :source => self.source
+ )
+ elsif ! param.is_a?(Puppet::Parser::Resource::Param)
+ raise ArgumentError, "Must pass a parameter or all necessary values"
end
- # Unless we're running >= 0.25, we're in compat mode.
- def metaparam_compatibility_mode?
- ! (catalog and ver = (catalog.client_version||'0.0.0').split(".") and (ver[0] > "0" or ver[1].to_i >= 25))
- end
+ tag(*param.value) if param.name == :tag
- def name
- self[:name] || self.title
- end
+ # And store it in our parameter hash.
+ @parameters[param.name] = param
+ end
- def namespaces
- scope.namespaces
+ def to_hash
+ @parameters.inject({}) do |hash, ary|
+ param = ary[1]
+ # Skip "undef" values.
+ hash[param.name] = param.value if param.value != :undef
+ hash
end
-
- # A temporary occasion, until I get paths in the scopes figured out.
- def path
- to_s
- end
-
- # Define a parameter in our resource.
- # if we ever receive a parameter named 'tag', set
- # the resource tags with its value.
- def set_parameter(param, value = nil)
- if ! value.nil?
- param = Puppet::Parser::Resource::Param.new(
- :name => param, :value => value, :source => self.source
- )
- elsif ! param.is_a?(Puppet::Parser::Resource::Param)
- raise ArgumentError, "Must pass a parameter or all necessary values"
+ end
+
+
+ # Create a Puppet::Resource instance from this parser resource.
+ # We plan, at some point, on not needing to do this conversion, but
+ # it's sufficient for now.
+ def to_resource
+ result = Puppet::Resource.new(type, title)
+
+ to_hash.each do |p, v|
+ if v.is_a?(Puppet::Resource)
+ v = Puppet::Resource.new(v.type, v.title)
+ elsif v.is_a?(Array)
+ # flatten resource references arrays
+ v = v.flatten if v.flatten.find { |av| av.is_a?(Puppet::Resource) }
+ v = v.collect do |av|
+ av = Puppet::Resource.new(av.type, av.title) if av.is_a?(Puppet::Resource)
+ av
end
-
- tag(*param.value) if param.name == :tag
-
- # And store it in our parameter hash.
- @parameters[param.name] = param
+ end
+
+ # If the value is an array with only one value, then
+ # convert it to a single value. This is largely so that
+ # the database interaction doesn't have to worry about
+ # whether it returns an array or a string.
+ result[p] = if v.is_a?(Array) and v.length == 1
+ v[0]
+ else
+ v
+ end
end
- def to_hash
- @parameters.inject({}) do |hash, ary|
- param = ary[1]
- # Skip "undef" values.
- hash[param.name] = param.value if param.value != :undef
- hash
- end
- end
+ result.file = self.file
+ result.line = self.line
+ result.exported = self.exported
+ result.virtual = self.virtual
+ result.tag(*self.tags)
+ result
+ end
- # Create a Puppet::Resource instance from this parser resource.
- # We plan, at some point, on not needing to do this conversion, but
- # it's sufficient for now.
- def to_resource
- result = Puppet::Resource.new(type, title)
-
- to_hash.each do |p, v|
- if v.is_a?(Puppet::Resource)
- v = Puppet::Resource.new(v.type, v.title)
- elsif v.is_a?(Array)
- # flatten resource references arrays
- v = v.flatten if v.flatten.find { |av| av.is_a?(Puppet::Resource) }
- v = v.collect do |av|
- av = Puppet::Resource.new(av.type, av.title) if av.is_a?(Puppet::Resource)
- av
- end
- end
-
- # If the value is an array with only one value, then
- # convert it to a single value. This is largely so that
- # the database interaction doesn't have to worry about
- # whether it returns an array or a string.
- result[p] = if v.is_a?(Array) and v.length == 1
- v[0]
- else
- v
- end
- end
+ # Translate our object to a transportable object.
+ def to_trans
+ return nil if virtual?
- result.file = self.file
- result.line = self.line
- result.exported = self.exported
- result.virtual = self.virtual
- result.tag(*self.tags)
+ to_resource.to_trans
+ end
- result
- end
+ # Convert this resource to a RAL resource. We hackishly go via the
+ # transportable stuff.
+ def to_ral
+ to_resource.to_ral
+ end
- # Translate our object to a transportable object.
- def to_trans
- return nil if virtual?
+ private
- to_resource.to_trans
- end
+ # Add default values from our definition.
+ def add_defaults
+ scope.lookupdefaults(self.type).each do |name, param|
+ unless @parameters.include?(name)
+ self.debug "Adding default for #{name}"
- # Convert this resource to a RAL resource. We hackishly go via the
- # transportable stuff.
- def to_ral
- to_resource.to_ral
+ @parameters[name] = param.dup
+ end
end
+ end
- private
+ def add_backward_compatible_relationship_param(name)
+ # Skip metaparams for which we get no value.
+ return unless val = scope.lookupvar(name.to_s, false) and val != :undefined
- # Add default values from our definition.
- def add_defaults
- scope.lookupdefaults(self.type).each do |name, param|
- unless @parameters.include?(name)
- self.debug "Adding default for #{name}"
+ # The default case: just set the value
+ set_parameter(name, val) and return unless @parameters[name]
- @parameters[name] = param.dup
- end
- end
- end
+ # For relationship params, though, join the values (a la #446).
+ @parameters[name].value = [@parameters[name].value, val].flatten
+ end
- def add_backward_compatible_relationship_param(name)
- # Skip metaparams for which we get no value.
- return unless val = scope.lookupvar(name.to_s, false) and val != :undefined
+ # Add any metaparams defined in our scope. This actually adds any metaparams
+ # from any parent scope, and there's currently no way to turn that off.
+ def add_metaparams
+ compat_mode = metaparam_compatibility_mode?
- # The default case: just set the value
- set_parameter(name, val) and return unless @parameters[name]
-
- # For relationship params, though, join the values (a la #446).
- @parameters[name].value = [@parameters[name].value, val].flatten
+ Puppet::Type.eachmetaparam do |name|
+ next unless self.class.relationship_parameter?(name)
+ add_backward_compatible_relationship_param(name) if compat_mode
end
-
- # Add any metaparams defined in our scope. This actually adds any metaparams
- # from any parent scope, and there's currently no way to turn that off.
- def add_metaparams
- compat_mode = metaparam_compatibility_mode?
-
- Puppet::Type.eachmetaparam do |name|
- next unless self.class.relationship_parameter?(name)
- add_backward_compatible_relationship_param(name) if compat_mode
- end
+ end
+
+ # Accept a parameter from an override.
+ def override_parameter(param)
+ # This can happen if the override is defining a new parameter, rather
+ # than replacing an existing one.
+ (set_parameter(param) and return) unless current = @parameters[param.name]
+
+ # The parameter is already set. Fail if they're not allowed to override it.
+ unless param.source.child_of?(current.source)
+ puts caller if Puppet[:trace]
+ msg = "Parameter '#{param.name}' is already set on #{self}"
+ msg += " by #{current.source}" if current.source.to_s != ""
+ if current.file or current.line
+ fields = []
+ fields << current.file if current.file
+ fields << current.line.to_s if current.line
+ msg += " at #{fields.join(":")}"
+ end
+ msg += "; cannot redefine"
+ raise Puppet::ParseError.new(msg, param.line, param.file)
end
- # Accept a parameter from an override.
- def override_parameter(param)
- # This can happen if the override is defining a new parameter, rather
- # than replacing an existing one.
- (set_parameter(param) and return) unless current = @parameters[param.name]
-
- # The parameter is already set. Fail if they're not allowed to override it.
- unless param.source.child_of?(current.source)
- puts caller if Puppet[:trace]
- msg = "Parameter '#{param.name}' is already set on #{self}"
- msg += " by #{current.source}" if current.source.to_s != ""
- if current.file or current.line
- fields = []
- fields << current.file if current.file
- fields << current.line.to_s if current.line
- msg += " at #{fields.join(":")}"
- end
- msg += "; cannot redefine"
- raise Puppet::ParseError.new(msg, param.line, param.file)
- end
-
- # If we've gotten this far, we're allowed to override.
-
- # Merge with previous value, if the parameter was generated with the +>
- # syntax. It's important that we use a copy of the new param instance
- # here, not the old one, and not the original new one, so that the source
- # is registered correctly for later overrides but the values aren't
- # implcitly shared when multiple resources are overrriden at once (see
- # ticket #3556).
- if param.add
- param = param.dup
- param.value = [current.value, param.value].flatten
- end
-
- set_parameter(param)
+ # If we've gotten this far, we're allowed to override.
+
+ # Merge with previous value, if the parameter was generated with the +>
+ # syntax. It's important that we use a copy of the new param instance
+ # here, not the old one, and not the original new one, so that the source
+ # is registered correctly for later overrides but the values aren't
+ # implcitly shared when multiple resources are overrriden at once (see
+ # ticket #3556).
+ if param.add
+ param = param.dup
+ param.value = [current.value, param.value].flatten
end
- # Make sure the resource's parameters are all valid for the type.
- def validate
- @parameters.each do |name, param|
- validate_parameter(name)
- end
- rescue => detail
- fail Puppet::ParseError, detail.to_s
+ set_parameter(param)
+ end
+
+ # Make sure the resource's parameters are all valid for the type.
+ def validate
+ @parameters.each do |name, param|
+ validate_parameter(name)
end
+ rescue => detail
+ fail Puppet::ParseError, detail.to_s
+ end
- private
+ private
- def extract_parameters(params)
- params.each do |param|
- # Don't set the same parameter twice
- self.fail Puppet::ParseError, "Duplicate parameter '#{param.name}' for on #{self}" if @parameters[param.name]
+ def extract_parameters(params)
+ params.each do |param|
+ # Don't set the same parameter twice
+ self.fail Puppet::ParseError, "Duplicate parameter '#{param.name}' for on #{self}" if @parameters[param.name]
- set_parameter(param)
- end
+ set_parameter(param)
end
+ end
end
diff --git a/lib/puppet/parser/resource/param.rb b/lib/puppet/parser/resource/param.rb
index 7ca240df7..af2d98fe8 100644
--- a/lib/puppet/parser/resource/param.rb
+++ b/lib/puppet/parser/resource/param.rb
@@ -3,25 +3,25 @@ require 'puppet/parser/yaml_trimmer'
# The parameters we stick in Resources.
class Puppet::Parser::Resource::Param
- attr_accessor :name, :value, :source, :add
- include Puppet::Util
- include Puppet::Util::Errors
- include Puppet::Util::MethodHelper
+ attr_accessor :name, :value, :source, :add
+ include Puppet::Util
+ include Puppet::Util::Errors
+ include Puppet::Util::MethodHelper
- include Puppet::FileCollection::Lookup
- include Puppet::Parser::YamlTrimmer
+ include Puppet::FileCollection::Lookup
+ include Puppet::Parser::YamlTrimmer
- def initialize(hash)
- set_options(hash)
- requiredopts(:name, :value, :source)
- @name = symbolize(@name)
- end
+ def initialize(hash)
+ set_options(hash)
+ requiredopts(:name, :value, :source)
+ @name = symbolize(@name)
+ end
- def line_to_i
- line ? Integer(line) : nil
- end
+ def line_to_i
+ line ? Integer(line) : nil
+ end
- def to_s
- "#{self.name} => #{self.value}"
- end
+ def to_s
+ "#{self.name} => #{self.value}"
+ end
end
diff --git a/lib/puppet/parser/scope.rb b/lib/puppet/parser/scope.rb
index 9b49ab680..ae0f9ea4a 100644
--- a/lib/puppet/parser/scope.rb
+++ b/lib/puppet/parser/scope.rb
@@ -9,475 +9,475 @@ require 'strscan'
require 'puppet/resource/type_collection_helper'
class Puppet::Parser::Scope
- include Puppet::Resource::TypeCollectionHelper
- require 'puppet/parser/resource'
-
- AST = Puppet::Parser::AST
-
- Puppet::Util.logmethods(self)
-
- include Enumerable
- include Puppet::Util::Errors
- attr_accessor :level, :source, :resource
- attr_accessor :base, :keyword
- attr_accessor :top, :translated, :compiler
- attr_accessor :parent
- attr_reader :namespaces
-
- # thin wrapper around an ephemeral
- # symbol table.
- # when a symbol
- class Ephemeral
- def initialize(parent=nil)
- @symbols = {}
- @parent = parent
+ include Puppet::Resource::TypeCollectionHelper
+ require 'puppet/parser/resource'
+
+ AST = Puppet::Parser::AST
+
+ Puppet::Util.logmethods(self)
+
+ include Enumerable
+ include Puppet::Util::Errors
+ attr_accessor :level, :source, :resource
+ attr_accessor :base, :keyword
+ attr_accessor :top, :translated, :compiler
+ attr_accessor :parent
+ attr_reader :namespaces
+
+ # thin wrapper around an ephemeral
+ # symbol table.
+ # when a symbol
+ class Ephemeral
+ def initialize(parent=nil)
+ @symbols = {}
+ @parent = parent
+ end
+
+ [:include?, :delete, :[]=].each do |m|
+ define_method(m) do |*args|
+ @symbols.send(m, *args)
+ end
+ end
+
+ def [](name)
+ unless @symbols.include?(name) or @parent.nil?
+ @parent[name]
+ else
+ @symbols[name]
+ end
+ end
+ end
+
+ # A demeterific shortcut to the catalog.
+ def catalog
+ compiler.catalog
+ end
+
+ def environment
+ compiler.environment
+ end
+
+ # Proxy accessors
+ def host
+ @compiler.node.name
+ end
+
+ # Is the value true? This allows us to control the definition of truth
+ # in one place.
+ def self.true?(value)
+ (value != false and value != "" and value != :undef)
+ end
+
+ # Is the value a number?, return the correct object or nil if not a number
+ def self.number?(value)
+ return nil unless value.is_a?(Fixnum) or value.is_a?(Bignum) or value.is_a?(Float) or value.is_a?(String)
+
+ if value.is_a?(String)
+ if value =~ /^-?\d+(:?\.\d+|(:?\.\d+)?e\d+)$/
+ return value.to_f
+ elsif value =~ /^0x[0-9a-f]+$/i
+ return value.to_i(16)
+ elsif value =~ /^0[0-7]+$/
+ return value.to_i(8)
+ elsif value =~ /^-?\d+$/
+ return value.to_i
+ else
+ return nil
+ end
+ end
+ # it is one of Fixnum,Bignum or Float
+ value
+ end
+
+ # Add to our list of namespaces.
+ def add_namespace(ns)
+ return false if @namespaces.include?(ns)
+ if @namespaces == [""]
+ @namespaces = [ns]
+ else
+ @namespaces << ns
+ end
+ end
+
+ # Remove this when rebasing
+ def environment
+ compiler.environment
+ end
+
+ # Are we the top scope?
+ def topscope?
+ @level == 1
+ end
+
+ def find_hostclass(name)
+ known_resource_types.find_hostclass(namespaces, name)
+ end
+
+ def find_definition(name)
+ known_resource_types.find_definition(namespaces, name)
+ end
+
+ def findresource(string, name = nil)
+ compiler.findresource(string, name)
+ end
+
+ # Initialize our new scope. Defaults to having no parent.
+ def initialize(hash = {})
+ if hash.include?(:namespace)
+ if n = hash[:namespace]
+ @namespaces = [n]
+ end
+ hash.delete(:namespace)
+ else
+ @namespaces = [""]
+ end
+ hash.each { |name, val|
+ method = name.to_s + "="
+ if self.respond_to? method
+ self.send(method, val)
+ else
+ raise Puppet::DevError, "Invalid scope argument #{name}"
+ end
+ }
+
+ extend_with_functions_module
+
+ @tags = []
+
+ # The symbol table for this scope. This is where we store variables.
+ @symtable = {}
+
+ # the ephemeral symbol tables
+ # those should not persist long, and are used for the moment only
+ # for $0..$xy capture variables of regexes
+ # this is actually implemented as a stack, with each ephemeral scope
+ # shadowing the previous one
+ @ephemeral = [ Ephemeral.new ]
+
+ # All of the defaults set for types. It's a hash of hashes,
+ # with the first key being the type, then the second key being
+ # the parameter.
+ @defaults = Hash.new { |dhash,type|
+ dhash[type] = {}
+ }
+
+ # The table for storing class singletons. This will only actually
+ # be used by top scopes and node scopes.
+ @class_scopes = {}
+ end
+
+ # Store the fact that we've evaluated a class, and store a reference to
+ # the scope in which it was evaluated, so that we can look it up later.
+ def class_set(name, scope)
+ return parent.class_set(name,scope) if parent
+ @class_scopes[name] = scope
+ end
+
+ # Return the scope associated with a class. This is just here so
+ # that subclasses can set their parent scopes to be the scope of
+ # their parent class, and it's also used when looking up qualified
+ # variables.
+ def class_scope(klass)
+ # They might pass in either the class or class name
+ k = klass.respond_to?(:name) ? klass.name : klass
+ @class_scopes[k] || (parent && parent.class_scope(k))
+ end
+
+ # Collect all of the defaults set at any higher scopes.
+ # This is a different type of lookup because it's additive --
+ # it collects all of the defaults, with defaults in closer scopes
+ # overriding those in later scopes.
+ def lookupdefaults(type)
+ values = {}
+
+ # first collect the values from the parents
+ unless parent.nil?
+ parent.lookupdefaults(type).each { |var,value|
+ values[var] = value
+ }
+ end
+
+ # then override them with any current values
+ # this should probably be done differently
+ if @defaults.include?(type)
+ @defaults[type].each { |var,value|
+ values[var] = value
+ }
+ end
+
+ #Puppet.debug "Got defaults for %s: %s" %
+ # [type,values.inspect]
+ values
+ end
+
+ # Look up a defined type.
+ def lookuptype(name)
+ find_definition(name) || find_hostclass(name)
+ end
+
+ def lookup_qualified_var(name, usestring)
+ parts = name.split(/::/)
+ shortname = parts.pop
+ klassname = parts.join("::")
+ klass = find_hostclass(klassname)
+ unless klass
+ warning "Could not look up qualified variable '#{name}'; class #{klassname} could not be found"
+ return usestring ? "" : :undefined
+ end
+ unless kscope = class_scope(klass)
+ warning "Could not look up qualified variable '#{name}'; class #{klassname} has not been evaluated"
+ return usestring ? "" : :undefined
+ end
+ kscope.lookupvar(shortname, usestring)
+ end
+
+ private :lookup_qualified_var
+
+ # Look up a variable. The simplest value search we do. Default to returning
+ # an empty string for missing values, but support returning a constant.
+ def lookupvar(name, usestring = true)
+ table = ephemeral?(name) ? @ephemeral.last : @symtable
+ # If the variable is qualified, then find the specified scope and look the variable up there instead.
+ if name =~ /::/
+ return lookup_qualified_var(name, usestring)
+ end
+ # We can't use "if table[name]" here because the value might be false
+ if ephemeral_include?(name) or table.include?(name)
+ if usestring and table[name] == :undef
+ return ""
+ else
+ return table[name]
+ end
+ elsif self.parent
+ return parent.lookupvar(name, usestring)
+ elsif usestring
+ return ""
+ else
+ return :undefined
+ end
+ end
+
+ # Return a hash containing our variables and their values, optionally (and
+ # by default) including the values defined in our parent. Local values
+ # shadow parent values.
+ def to_hash(recursive = true)
+ target = parent.to_hash(recursive) if recursive and parent
+ target ||= Hash.new
+ @symtable.keys.each { |name|
+ value = @symtable[name]
+ if value == :undef
+ target.delete(name)
+ else
+ target[name] = value
+ end
+ }
+ target
+ end
+
+ def namespaces
+ @namespaces.dup
+ end
+
+ # Create a new scope and set these options.
+ def newscope(options = {})
+ compiler.newscope(self, options)
+ end
+
+ def parent_module_name
+ return nil unless @parent
+ return nil unless @parent.source
+ @parent.source.module_name
+ end
+
+ # Return the list of scopes up to the top scope, ordered with our own first.
+ # This is used for looking up variables and defaults.
+ def scope_path
+ if parent
+ [self, parent.scope_path].flatten.compact
+ else
+ [self]
+ end
+ end
+
+ # Set defaults for a type. The typename should already be downcased,
+ # so that the syntax is isolated. We don't do any kind of type-checking
+ # here; instead we let the resource do it when the defaults are used.
+ def setdefaults(type, params)
+ table = @defaults[type]
+
+ # if we got a single param, it'll be in its own array
+ params = [params] unless params.is_a?(Array)
+
+ params.each { |param|
+ #Puppet.debug "Default for %s is %s => %s" %
+ # [type,ary[0].inspect,ary[1].inspect]
+ if table.include?(param.name)
+ raise Puppet::ParseError.new("Default already defined for #{type} { #{param.name} }; cannot redefine", param.line, param.file)
+ end
+ table[param.name] = param
+ }
+ end
+
+ # Set a variable in the current scope. This will override settings
+ # in scopes above, but will not allow variables in the current scope
+ # to be reassigned.
+ def setvar(name,value, options = {})
+ table = options[:ephemeral] ? @ephemeral.last : @symtable
+ #Puppet.debug "Setting %s to '%s' at level %s mode append %s" %
+ # [name.inspect,value,self.level, append]
+ if table.include?(name)
+ unless options[:append]
+ error = Puppet::ParseError.new("Cannot reassign variable #{name}")
+ else
+ error = Puppet::ParseError.new("Cannot append, variable #{name} is defined in this scope")
+ end
+ error.file = options[:file] if options[:file]
+ error.line = options[:line] if options[:line]
+ raise error
+ end
+
+ unless options[:append]
+ table[name] = value
+ else # append case
+ # lookup the value in the scope if it exists and insert the var
+ table[name] = lookupvar(name)
+ # concatenate if string, append if array, nothing for other types
+ case value
+ when Array
+ table[name] += value
+ when Hash
+ raise ArgumentError, "Trying to append to a hash with something which is not a hash is unsupported" unless value.is_a?(Hash)
+ table[name].merge!(value)
+ else
+ table[name] << value
+ end
+ end
+ end
+
+ # Return an interpolated string.
+ def strinterp(string, file = nil, line = nil)
+ # Most strings won't have variables in them.
+ ss = StringScanner.new(string)
+ out = ""
+ while not ss.eos?
+ if ss.scan(/^\$\{((\w*::)*\w+|[0-9]+)\}|^\$([0-9])|^\$((\w*::)*\w+)/)
+ # If it matches the backslash, then just retun the dollar sign.
+ if ss.matched == '\\$'
+ out << '$'
+ else # look the variable up
+ # make sure $0-$9 are lookupable only if ephemeral
+ var = ss[1] || ss[3] || ss[4]
+ if var and var =~ /^[0-9]+$/ and not ephemeral_include?(var)
+ next
+ end
+ out << lookupvar(var).to_s || ""
end
-
- [:include?, :delete, :[]=].each do |m|
- define_method(m) do |*args|
- @symbols.send(m, *args)
- end
- end
-
- def [](name)
- unless @symbols.include?(name) or @parent.nil?
- @parent[name]
- else
- @symbols[name]
- end
- end
- end
-
- # A demeterific shortcut to the catalog.
- def catalog
- compiler.catalog
- end
-
- def environment
- compiler.environment
- end
-
- # Proxy accessors
- def host
- @compiler.node.name
- end
-
- # Is the value true? This allows us to control the definition of truth
- # in one place.
- def self.true?(value)
- (value != false and value != "" and value != :undef)
- end
-
- # Is the value a number?, return the correct object or nil if not a number
- def self.number?(value)
- return nil unless value.is_a?(Fixnum) or value.is_a?(Bignum) or value.is_a?(Float) or value.is_a?(String)
-
- if value.is_a?(String)
- if value =~ /^-?\d+(:?\.\d+|(:?\.\d+)?e\d+)$/
- return value.to_f
- elsif value =~ /^0x[0-9a-f]+$/i
- return value.to_i(16)
- elsif value =~ /^0[0-7]+$/
- return value.to_i(8)
- elsif value =~ /^-?\d+$/
- return value.to_i
- else
- return nil
- end
- end
- # it is one of Fixnum,Bignum or Float
- value
- end
-
- # Add to our list of namespaces.
- def add_namespace(ns)
- return false if @namespaces.include?(ns)
- if @namespaces == [""]
- @namespaces = [ns]
+ elsif ss.scan(/^\\(.)/)
+ # Puppet.debug("Got escape: pos:%d; m:%s" % [ss.pos, ss.matched])
+ case ss[1]
+ when 'n'
+ out << "\n"
+ when 't'
+ out << "\t"
+ when 's'
+ out << " "
+ when '\\'
+ out << '\\'
+ when '$'
+ out << '$'
else
- @namespaces << ns
+ str = "Unrecognised escape sequence '#{ss.matched}'"
+ str += " in file #{file}" if file
+ str += " at line #{line}" if line
+ Puppet.warning str
+ out << ss.matched
end
- end
-
- # Remove this when rebasing
- def environment
- compiler.environment
- end
-
- # Are we the top scope?
- def topscope?
- @level == 1
- end
-
- def find_hostclass(name)
- known_resource_types.find_hostclass(namespaces, name)
- end
-
- def find_definition(name)
- known_resource_types.find_definition(namespaces, name)
- end
-
- def findresource(string, name = nil)
- compiler.findresource(string, name)
- end
-
- # Initialize our new scope. Defaults to having no parent.
- def initialize(hash = {})
- if hash.include?(:namespace)
- if n = hash[:namespace]
- @namespaces = [n]
- end
- hash.delete(:namespace)
- else
- @namespaces = [""]
+ elsif ss.scan(/^\$/)
+ out << '$'
+ elsif ss.scan(/^\\\n/) # an escaped carriage return
+ next
+ else
+ tmp = ss.scan(/[^\\$]+/)
+ # Puppet.debug("Got other: pos:%d; m:%s" % [ss.pos, tmp])
+ unless tmp
+ error = Puppet::ParseError.new("Could not parse string #{string.inspect}")
+ {:file= => file, :line= => line}.each do |m,v|
+ error.send(m, v) if v
+ end
+ raise error
end
- hash.each { |name, val|
- method = name.to_s + "="
- if self.respond_to? method
- self.send(method, val)
- else
- raise Puppet::DevError, "Invalid scope argument #{name}"
- end
- }
-
- extend_with_functions_module
-
- @tags = []
-
- # The symbol table for this scope. This is where we store variables.
- @symtable = {}
-
- # the ephemeral symbol tables
- # those should not persist long, and are used for the moment only
- # for $0..$xy capture variables of regexes
- # this is actually implemented as a stack, with each ephemeral scope
- # shadowing the previous one
- @ephemeral = [ Ephemeral.new ]
-
- # All of the defaults set for types. It's a hash of hashes,
- # with the first key being the type, then the second key being
- # the parameter.
- @defaults = Hash.new { |dhash,type|
- dhash[type] = {}
- }
-
- # The table for storing class singletons. This will only actually
- # be used by top scopes and node scopes.
- @class_scopes = {}
+ out << tmp
+ end
end
- # Store the fact that we've evaluated a class, and store a reference to
- # the scope in which it was evaluated, so that we can look it up later.
- def class_set(name, scope)
- return parent.class_set(name,scope) if parent
- @class_scopes[name] = scope
- end
+ out
+ end
- # Return the scope associated with a class. This is just here so
- # that subclasses can set their parent scopes to be the scope of
- # their parent class, and it's also used when looking up qualified
- # variables.
- def class_scope(klass)
- # They might pass in either the class or class name
- k = klass.respond_to?(:name) ? klass.name : klass
- @class_scopes[k] || (parent && parent.class_scope(k))
- end
+ # Return the tags associated with this scope. It's basically
+ # just our parents' tags, plus our type. We don't cache this value
+ # because our parent tags might change between calls.
+ def tags
+ resource.tags
+ end
- # Collect all of the defaults set at any higher scopes.
- # This is a different type of lookup because it's additive --
- # it collects all of the defaults, with defaults in closer scopes
- # overriding those in later scopes.
- def lookupdefaults(type)
- values = {}
-
- # first collect the values from the parents
- unless parent.nil?
- parent.lookupdefaults(type).each { |var,value|
- values[var] = value
- }
- end
+ # Used mainly for logging
+ def to_s
+ "Scope(#{@resource})"
+ end
- # then override them with any current values
- # this should probably be done differently
- if @defaults.include?(type)
- @defaults[type].each { |var,value|
- values[var] = value
- }
- end
+ # Undefine a variable; only used for testing.
+ def unsetvar(var)
+ table = ephemeral?(var) ? @ephemeral.last : @symtable
+ table.delete(var) if table.include?(var)
+ end
- #Puppet.debug "Got defaults for %s: %s" %
- # [type,values.inspect]
- values
+ # remove ephemeral scope up to level
+ def unset_ephemeral_var(level=:all)
+ if level == :all
+ @ephemeral = [ Ephemeral.new ]
+ else
+ (@ephemeral.size - level).times do
+ @ephemeral.pop
+ end
end
+ end
- # Look up a defined type.
- def lookuptype(name)
- find_definition(name) || find_hostclass(name)
+ # check if name exists in one of the ephemeral scope.
+ def ephemeral_include?(name)
+ @ephemeral.reverse.each do |eph|
+ return true if eph.include?(name)
end
+ false
+ end
- def lookup_qualified_var(name, usestring)
- parts = name.split(/::/)
- shortname = parts.pop
- klassname = parts.join("::")
- klass = find_hostclass(klassname)
- unless klass
- warning "Could not look up qualified variable '#{name}'; class #{klassname} could not be found"
- return usestring ? "" : :undefined
- end
- unless kscope = class_scope(klass)
- warning "Could not look up qualified variable '#{name}'; class #{klassname} has not been evaluated"
- return usestring ? "" : :undefined
- end
- kscope.lookupvar(shortname, usestring)
- end
+ # is name an ephemeral variable?
+ def ephemeral?(name)
+ name =~ /^\d+$/
+ end
- private :lookup_qualified_var
+ def ephemeral_level
+ @ephemeral.size
+ end
- # Look up a variable. The simplest value search we do. Default to returning
- # an empty string for missing values, but support returning a constant.
- def lookupvar(name, usestring = true)
- table = ephemeral?(name) ? @ephemeral.last : @symtable
- # If the variable is qualified, then find the specified scope and look the variable up there instead.
- if name =~ /::/
- return lookup_qualified_var(name, usestring)
- end
- # We can't use "if table[name]" here because the value might be false
- if ephemeral_include?(name) or table.include?(name)
- if usestring and table[name] == :undef
- return ""
- else
- return table[name]
- end
- elsif self.parent
- return parent.lookupvar(name, usestring)
- elsif usestring
- return ""
- else
- return :undefined
- end
- end
+ def new_ephemeral
+ @ephemeral.push(Ephemeral.new(@ephemeral.last))
+ end
- # Return a hash containing our variables and their values, optionally (and
- # by default) including the values defined in our parent. Local values
- # shadow parent values.
- def to_hash(recursive = true)
- target = parent.to_hash(recursive) if recursive and parent
- target ||= Hash.new
- @symtable.keys.each { |name|
- value = @symtable[name]
- if value == :undef
- target.delete(name)
- else
- target[name] = value
- end
- }
- target
- end
+ def ephemeral_from(match, file = nil, line = nil)
+ raise(ArgumentError,"Invalid regex match data") unless match.is_a?(MatchData)
- def namespaces
- @namespaces.dup
- end
+ new_ephemeral
- # Create a new scope and set these options.
- def newscope(options = {})
- compiler.newscope(self, options)
+ setvar("0", match[0], :file => file, :line => line, :ephemeral => true)
+ match.captures.each_with_index do |m,i|
+ setvar("#{i+1}", m, :file => file, :line => line, :ephemeral => true)
end
+ end
- def parent_module_name
- return nil unless @parent
- return nil unless @parent.source
- @parent.source.module_name
- end
-
- # Return the list of scopes up to the top scope, ordered with our own first.
- # This is used for looking up variables and defaults.
- def scope_path
- if parent
- [self, parent.scope_path].flatten.compact
- else
- [self]
- end
- end
-
- # Set defaults for a type. The typename should already be downcased,
- # so that the syntax is isolated. We don't do any kind of type-checking
- # here; instead we let the resource do it when the defaults are used.
- def setdefaults(type, params)
- table = @defaults[type]
-
- # if we got a single param, it'll be in its own array
- params = [params] unless params.is_a?(Array)
-
- params.each { |param|
- #Puppet.debug "Default for %s is %s => %s" %
- # [type,ary[0].inspect,ary[1].inspect]
- if table.include?(param.name)
- raise Puppet::ParseError.new("Default already defined for #{type} { #{param.name} }; cannot redefine", param.line, param.file)
- end
- table[param.name] = param
- }
- end
-
- # Set a variable in the current scope. This will override settings
- # in scopes above, but will not allow variables in the current scope
- # to be reassigned.
- def setvar(name,value, options = {})
- table = options[:ephemeral] ? @ephemeral.last : @symtable
- #Puppet.debug "Setting %s to '%s' at level %s mode append %s" %
- # [name.inspect,value,self.level, append]
- if table.include?(name)
- unless options[:append]
- error = Puppet::ParseError.new("Cannot reassign variable #{name}")
- else
- error = Puppet::ParseError.new("Cannot append, variable #{name} is defined in this scope")
- end
- error.file = options[:file] if options[:file]
- error.line = options[:line] if options[:line]
- raise error
- end
-
- unless options[:append]
- table[name] = value
- else # append case
- # lookup the value in the scope if it exists and insert the var
- table[name] = lookupvar(name)
- # concatenate if string, append if array, nothing for other types
- case value
- when Array
- table[name] += value
- when Hash
- raise ArgumentError, "Trying to append to a hash with something which is not a hash is unsupported" unless value.is_a?(Hash)
- table[name].merge!(value)
- else
- table[name] << value
- end
- end
- end
-
- # Return an interpolated string.
- def strinterp(string, file = nil, line = nil)
- # Most strings won't have variables in them.
- ss = StringScanner.new(string)
- out = ""
- while not ss.eos?
- if ss.scan(/^\$\{((\w*::)*\w+|[0-9]+)\}|^\$([0-9])|^\$((\w*::)*\w+)/)
- # If it matches the backslash, then just retun the dollar sign.
- if ss.matched == '\\$'
- out << '$'
- else # look the variable up
- # make sure $0-$9 are lookupable only if ephemeral
- var = ss[1] || ss[3] || ss[4]
- if var and var =~ /^[0-9]+$/ and not ephemeral_include?(var)
- next
- end
- out << lookupvar(var).to_s || ""
- end
- elsif ss.scan(/^\\(.)/)
- # Puppet.debug("Got escape: pos:%d; m:%s" % [ss.pos, ss.matched])
- case ss[1]
- when 'n'
- out << "\n"
- when 't'
- out << "\t"
- when 's'
- out << " "
- when '\\'
- out << '\\'
- when '$'
- out << '$'
- else
- str = "Unrecognised escape sequence '#{ss.matched}'"
- str += " in file #{file}" if file
- str += " at line #{line}" if line
- Puppet.warning str
- out << ss.matched
- end
- elsif ss.scan(/^\$/)
- out << '$'
- elsif ss.scan(/^\\\n/) # an escaped carriage return
- next
- else
- tmp = ss.scan(/[^\\$]+/)
- # Puppet.debug("Got other: pos:%d; m:%s" % [ss.pos, tmp])
- unless tmp
- error = Puppet::ParseError.new("Could not parse string #{string.inspect}")
- {:file= => file, :line= => line}.each do |m,v|
- error.send(m, v) if v
- end
- raise error
- end
- out << tmp
- end
- end
-
- out
- end
-
- # Return the tags associated with this scope. It's basically
- # just our parents' tags, plus our type. We don't cache this value
- # because our parent tags might change between calls.
- def tags
- resource.tags
- end
-
- # Used mainly for logging
- def to_s
- "Scope(#{@resource})"
- end
-
- # Undefine a variable; only used for testing.
- def unsetvar(var)
- table = ephemeral?(var) ? @ephemeral.last : @symtable
- table.delete(var) if table.include?(var)
- end
-
- # remove ephemeral scope up to level
- def unset_ephemeral_var(level=:all)
- if level == :all
- @ephemeral = [ Ephemeral.new ]
- else
- (@ephemeral.size - level).times do
- @ephemeral.pop
- end
- end
- end
+ private
- # check if name exists in one of the ephemeral scope.
- def ephemeral_include?(name)
- @ephemeral.reverse.each do |eph|
- return true if eph.include?(name)
- end
- false
- end
-
- # is name an ephemeral variable?
- def ephemeral?(name)
- name =~ /^\d+$/
- end
-
- def ephemeral_level
- @ephemeral.size
- end
-
- def new_ephemeral
- @ephemeral.push(Ephemeral.new(@ephemeral.last))
- end
-
- def ephemeral_from(match, file = nil, line = nil)
- raise(ArgumentError,"Invalid regex match data") unless match.is_a?(MatchData)
-
- new_ephemeral
-
- setvar("0", match[0], :file => file, :line => line, :ephemeral => true)
- match.captures.each_with_index do |m,i|
- setvar("#{i+1}", m, :file => file, :line => line, :ephemeral => true)
- end
- end
-
- private
-
- def extend_with_functions_module
- extend Puppet::Parser::Functions.environment_module(Puppet::Node::Environment.root)
- extend Puppet::Parser::Functions.environment_module(compiler ? environment : nil)
- end
+ def extend_with_functions_module
+ extend Puppet::Parser::Functions.environment_module(Puppet::Node::Environment.root)
+ extend Puppet::Parser::Functions.environment_module(compiler ? environment : nil)
+ end
end
diff --git a/lib/puppet/parser/templatewrapper.rb b/lib/puppet/parser/templatewrapper.rb
index 6966387cf..73a4ad8aa 100644
--- a/lib/puppet/parser/templatewrapper.rb
+++ b/lib/puppet/parser/templatewrapper.rb
@@ -3,112 +3,112 @@
require 'puppet/parser/files'
class Puppet::Parser::TemplateWrapper
- attr_writer :scope
- attr_reader :file
- attr_accessor :string
- include Puppet::Util
- Puppet::Util.logmethods(self)
-
- def initialize(scope)
- @__scope__ = scope
+ attr_writer :scope
+ attr_reader :file
+ attr_accessor :string
+ include Puppet::Util
+ Puppet::Util.logmethods(self)
+
+ def initialize(scope)
+ @__scope__ = scope
+ end
+
+ def scope
+ @__scope__
+ end
+
+ # Should return true if a variable is defined, false if it is not
+ def has_variable?(name)
+ if scope.lookupvar(name.to_s, false) != :undefined
+ true
+ else
+ false
end
-
- def scope
- @__scope__
+ end
+
+ # Allow templates to access the defined classes
+ def classes
+ scope.catalog.classes
+ end
+
+ # Allow templates to access the tags defined in the current scope
+ def tags
+ scope.tags
+ end
+
+ # Allow templates to access the all the defined tags
+ def all_tags
+ scope.catalog.tags
+ end
+
+ # Ruby treats variables like methods, so we used to expose variables
+ # within scope to the ERB code via method_missing. As per RedMine #1427,
+ # though, this means that conflicts between methods in our inheritance
+ # tree (Kernel#fork) and variable names (fork => "yes/no") could arise.
+ #
+ # Worse, /new/ conflicts could pop up when a new kernel or object method
+ # was added to Ruby, causing templates to suddenly fail mysteriously when
+ # Ruby was upgraded.
+ #
+ # To ensure that legacy templates using unqualified names work we retain
+ # the missing_method definition here until we declare the syntax finally
+ # dead.
+ def method_missing(name, *args)
+ # We have to tell lookupvar to return :undefined to us when
+ # appropriate; otherwise it converts to "".
+ value = scope.lookupvar(name.to_s, false)
+ if value != :undefined
+ return value
+ else
+ # Just throw an error immediately, instead of searching for
+ # other missingmethod things or whatever.
+ raise Puppet::ParseError, "Could not find value for '#{name}'"
end
+ end
- # Should return true if a variable is defined, false if it is not
- def has_variable?(name)
- if scope.lookupvar(name.to_s, false) != :undefined
- true
- else
- false
- end
+ def file=(filename)
+ unless @file = Puppet::Parser::Files.find_template(filename, scope.compiler.environment.to_s)
+ raise Puppet::ParseError, "Could not find template '#{filename}'"
end
- # Allow templates to access the defined classes
- def classes
- scope.catalog.classes
- end
+ # We'll only ever not have a parser in testing, but, eh.
+ scope.known_resource_types.watch_file(file)
- # Allow templates to access the tags defined in the current scope
- def tags
- scope.tags
- end
+ @string = File.read(file)
+ end
- # Allow templates to access the all the defined tags
- def all_tags
- scope.catalog.tags
+ def result(string = nil)
+ if string
+ self.string = string
+ template_source = "inline template"
+ else
+ template_source = file
end
- # Ruby treats variables like methods, so we used to expose variables
- # within scope to the ERB code via method_missing. As per RedMine #1427,
- # though, this means that conflicts between methods in our inheritance
- # tree (Kernel#fork) and variable names (fork => "yes/no") could arise.
- #
- # Worse, /new/ conflicts could pop up when a new kernel or object method
- # was added to Ruby, causing templates to suddenly fail mysteriously when
- # Ruby was upgraded.
- #
- # To ensure that legacy templates using unqualified names work we retain
- # the missing_method definition here until we declare the syntax finally
- # dead.
- def method_missing(name, *args)
- # We have to tell lookupvar to return :undefined to us when
- # appropriate; otherwise it converts to "".
- value = scope.lookupvar(name.to_s, false)
- if value != :undefined
- return value
+ # Expose all the variables in our scope as instance variables of the
+ # current object, making it possible to access them without conflict
+ # to the regular methods.
+ benchmark(:debug, "Bound template variables for #{template_source}") do
+ scope.to_hash.each { |name, value|
+ if name.kind_of?(String)
+ realname = name.gsub(/[^\w]/, "_")
else
- # Just throw an error immediately, instead of searching for
- # other missingmethod things or whatever.
- raise Puppet::ParseError, "Could not find value for '#{name}'"
+ realname = name
end
+ instance_variable_set("@#{realname}", value)
+ }
end
- def file=(filename)
- unless @file = Puppet::Parser::Files.find_template(filename, scope.compiler.environment.to_s)
- raise Puppet::ParseError, "Could not find template '#{filename}'"
- end
-
- # We'll only ever not have a parser in testing, but, eh.
- scope.known_resource_types.watch_file(file)
-
- @string = File.read(file)
+ result = nil
+ benchmark(:debug, "Interpolated template #{template_source}") do
+ template = ERB.new(self.string, 0, "-")
+ result = template.result(binding)
end
- def result(string = nil)
- if string
- self.string = string
- template_source = "inline template"
- else
- template_source = file
- end
-
- # Expose all the variables in our scope as instance variables of the
- # current object, making it possible to access them without conflict
- # to the regular methods.
- benchmark(:debug, "Bound template variables for #{template_source}") do
- scope.to_hash.each { |name, value|
- if name.kind_of?(String)
- realname = name.gsub(/[^\w]/, "_")
- else
- realname = name
- end
- instance_variable_set("@#{realname}", value)
- }
- end
-
- result = nil
- benchmark(:debug, "Interpolated template #{template_source}") do
- template = ERB.new(self.string, 0, "-")
- result = template.result(binding)
- end
-
- result
- end
+ result
+ end
- def to_s
- "template[#{(file ? file : "inline")}]"
- end
+ def to_s
+ "template[#{(file ? file : "inline")}]"
+ end
end
diff --git a/lib/puppet/parser/type_loader.rb b/lib/puppet/parser/type_loader.rb
index 37fa03f20..e56ab9418 100644
--- a/lib/puppet/parser/type_loader.rb
+++ b/lib/puppet/parser/type_loader.rb
@@ -1,146 +1,146 @@
require 'puppet/node/environment'
class Puppet::Parser::TypeLoader
- include Puppet::Node::Environment::Helper
-
- class Helper < Hash
- include MonitorMixin
- def done_with(item)
- synchronize do
- delete(item)[:busy].signal if self.has_key?(item) and self[item][:loader] == Thread.current
- end
- 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
- else
- flag = self[item][:busy]
- flag.wait
- flag.signal
- :another_thread
- end
- end
- end
+ include Puppet::Node::Environment::Helper
+
+ class Helper < Hash
+ include MonitorMixin
+ def done_with(item)
+ synchronize do
+ delete(item)[:busy].signal if self.has_key?(item) and self[item][:loader] == Thread.current
+ end
end
-
- # Import our files.
- def import(file, current_file = nil)
- return if Puppet[:ignoreimport]
-
- # use a path relative to the file doing the importing
- if current_file
- dir = current_file.sub(%r{[^/]+$},'').sub(/\/$/, '')
+ 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
else
- dir = "."
- end
- if dir == ""
- dir = "."
- end
-
- pat = file
- modname, files = Puppet::Parser::Files.find_manifests(pat, :cwd => dir, :environment => environment)
- if files.size == 0
- raise Puppet::ImportError.new("No file(s) found for import of '#{pat}'")
- end
-
- files.each do |file|
- unless file =~ /^#{File::SEPARATOR}/
- file = File.join(dir, file)
- end
- @imported[file] = true
- parse_file(file)
+ flag = self[item][:busy]
+ flag.wait
+ flag.signal
+ :another_thread
end
-
- modname
+ end
end
+ end
- def imported?(file)
- @imported.has_key?(file)
- end
+ # Import our files.
+ def import(file, current_file = nil)
+ return if Puppet[:ignoreimport]
- def known_resource_types
- environment.known_resource_types
+ # use a path relative to the file doing the importing
+ if current_file
+ dir = current_file.sub(%r{[^/]+$},'').sub(/\/$/, '')
+ else
+ dir = "."
end
-
- def initialize(env)
- self.environment = env
- @loaded = []
- @loading = Helper.new
-
- @imported = {}
+ if dir == ""
+ dir = "."
end
- def load_until(namespaces, name)
- return nil if name == "" # special-case main.
- name2files(namespaces, name).each do |filename|
- modname = nil
- import_if_possible(filename) do
- modname = import(filename)
- @loaded << filename
- end
- if result = yield(filename)
- Puppet.info "Automatically imported #{name} from #{filename}"
- result.module_name = modname if modname and result.respond_to?(:module_name=)
- return result
- end
- end
- nil
+ pat = file
+ modname, files = Puppet::Parser::Files.find_manifests(pat, :cwd => dir, :environment => environment)
+ if files.size == 0
+ raise Puppet::ImportError.new("No file(s) found for import of '#{pat}'")
end
- def loaded?(name)
- @loaded.include?(name)
+ files.each do |file|
+ unless file =~ /^#{File::SEPARATOR}/
+ file = File.join(dir, file)
+ end
+ @imported[file] = true
+ parse_file(file)
end
- def name2files(namespaces, name)
- return [name.sub(/^::/, '').gsub("::", File::SEPARATOR)] if name =~ /^::/
+ 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 = {}
+ end
+
+ def load_until(namespaces, name)
+ return nil if name == "" # special-case main.
+ name2files(namespaces, name).each do |filename|
+ modname = nil
+ import_if_possible(filename) do
+ modname = import(filename)
+ @loaded << filename
+ end
+ if result = yield(filename)
+ Puppet.info "Automatically imported #{name} from #{filename}"
+ result.module_name = modname if modname and result.respond_to?(:module_name=)
+ return result
+ end
+ end
+ nil
+ end
- result = namespaces.inject([]) do |names_to_try, namespace|
- fullname = (namespace + "::#{name}").sub(/^::/, '')
+ def loaded?(name)
+ @loaded.include?(name)
+ end
- # Try to load the module init file if we're a qualified name
- names_to_try << fullname.split("::")[0] if fullname.include?("::")
+ def name2files(namespaces, name)
+ return [name.sub(/^::/, '').gsub("::", File::SEPARATOR)] if name =~ /^::/
- # Then the fully qualified name
- names_to_try << fullname
- end
+ result = namespaces.inject([]) do |names_to_try, namespace|
+ fullname = (namespace + "::#{name}").sub(/^::/, '')
- # Otherwise try to load the bare name on its own. This
- # is appropriate if the class we're looking for is in a
- # module that's different from our namespace.
- result << name
- result.uniq.collect { |f| f.gsub("::", File::SEPARATOR) }
- end
+ # Try to load the module init file if we're a qualified name
+ names_to_try << fullname.split("::")[0] if fullname.include?("::")
- def parse_file(file)
- Puppet.debug("importing '#{file}' in environment #{environment}")
- parser = Puppet::Parser::Parser.new(environment)
- parser.file = file
- parser.parse
+ # Then the fully qualified name
+ names_to_try << fullname
end
- private
-
- # 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)
- return if @loaded.include?(file)
- begin
- case @loading.owner_of(file)
- when :this_thread
- return
- when :another_thread
- return import_if_possible(file)
- when :nobody
- yield
- end
- rescue Puppet::ImportError => detail
- # We couldn't load the item
- ensure
- @loading.done_with(file)
- end
+ # Otherwise try to load the bare name on its own. This
+ # is appropriate if the class we're looking for is in a
+ # module that's different from our namespace.
+ result << name
+ result.uniq.collect { |f| f.gsub("::", File::SEPARATOR) }
+ end
+
+ def parse_file(file)
+ Puppet.debug("importing '#{file}' in environment #{environment}")
+ parser = Puppet::Parser::Parser.new(environment)
+ parser.file = file
+ parser.parse
+ end
+
+ private
+
+ # 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)
+ return if @loaded.include?(file)
+ begin
+ case @loading.owner_of(file)
+ when :this_thread
+ return
+ when :another_thread
+ return import_if_possible(file)
+ when :nobody
+ yield
+ end
+ rescue Puppet::ImportError => detail
+ # We couldn't load the item
+ ensure
+ @loading.done_with(file)
end
+ end
end
diff --git a/lib/puppet/parser/yaml_trimmer.rb b/lib/puppet/parser/yaml_trimmer.rb
index 131bafb8d..cf7870916 100644
--- a/lib/puppet/parser/yaml_trimmer.rb
+++ b/lib/puppet/parser/yaml_trimmer.rb
@@ -1,9 +1,9 @@
module Puppet::Parser::YamlTrimmer
- REMOVE = %w{@scope @source}
+ REMOVE = %w{@scope @source}
- def to_yaml_properties
- r = instance_variables - REMOVE
- r -= skip_for_yaml if respond_to?(:skip_for_yaml)
- r
- end
+ def to_yaml_properties
+ r = instance_variables - REMOVE
+ r -= skip_for_yaml if respond_to?(:skip_for_yaml)
+ r
+ end
end