summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2008-02-12 17:37:51 -0600
committerLuke Kanies <luke@madstop.com>2008-02-12 17:37:51 -0600
commitda78d96cb139db0775e634b2fa4bd9c173752127 (patch)
tree4139d3a2011baedb171a8307c4830c5ac3fe3625 /lib
parentbee9aba2da453151a80c6e1f25f16bec3bfde8d2 (diff)
parent3af6827875f4e02b47fe2293280ff9afe811485f (diff)
downloadpuppet-da78d96cb139db0775e634b2fa4bd9c173752127.tar.gz
puppet-da78d96cb139db0775e634b2fa4bd9c173752127.tar.xz
puppet-da78d96cb139db0775e634b2fa4bd9c173752127.zip
Merge branch '0.24.x'
Conflicts: CHANGELOG
Diffstat (limited to 'lib')
-rw-r--r--lib/puppet/defaults.rb8
-rw-r--r--lib/puppet/metatype/metaparams.rb2
-rw-r--r--lib/puppet/network/http_server/mongrel.rb7
-rw-r--r--lib/puppet/network/http_server/webrick.rb4
-rw-r--r--lib/puppet/network/xmlrpc/client.rb13
-rw-r--r--lib/puppet/node/catalog.rb68
-rw-r--r--lib/puppet/parser/ast.rb76
-rw-r--r--lib/puppet/parser/ast/astarray.rb5
-rw-r--r--lib/puppet/parser/ast/caseopt.rb8
-rw-r--r--lib/puppet/parser/ast/casestatement.rb9
-rw-r--r--lib/puppet/parser/ast/collection.rb8
-rw-r--r--lib/puppet/parser/ast/collexpr.rb8
-rw-r--r--lib/puppet/parser/ast/definition.rb310
-rw-r--r--lib/puppet/parser/ast/else.rb5
-rw-r--r--lib/puppet/parser/ast/function.rb13
-rw-r--r--lib/puppet/parser/ast/hostclass.rb120
-rw-r--r--lib/puppet/parser/ast/ifstatement.rb9
-rw-r--r--lib/puppet/parser/ast/leaf.rb12
-rw-r--r--lib/puppet/parser/ast/node.rb84
-rw-r--r--lib/puppet/parser/ast/resource.rb12
-rw-r--r--lib/puppet/parser/ast/resource_defaults.rb6
-rw-r--r--lib/puppet/parser/ast/resource_override.rb10
-rw-r--r--lib/puppet/parser/ast/resource_reference.rb6
-rw-r--r--lib/puppet/parser/ast/resourceparam.rb6
-rw-r--r--lib/puppet/parser/ast/selector.rb11
-rw-r--r--lib/puppet/parser/ast/tag.rb6
-rw-r--r--lib/puppet/parser/ast/vardef.rb7
-rw-r--r--lib/puppet/parser/collector.rb8
-rw-r--r--lib/puppet/parser/compiler.rb (renamed from lib/puppet/parser/compile.rb)170
-rw-r--r--lib/puppet/parser/functions.rb6
-rw-r--r--lib/puppet/parser/interpreter.rb4
-rw-r--r--lib/puppet/parser/lexer.rb671
-rw-r--r--lib/puppet/parser/parser_support.rb7
-rw-r--r--lib/puppet/parser/resource.rb48
-rw-r--r--lib/puppet/parser/resource/param.rb2
-rw-r--r--lib/puppet/parser/resource/reference.rb10
-rw-r--r--lib/puppet/parser/scope.rb19
-rw-r--r--lib/puppet/parser/templatewrapper.rb2
-rw-r--r--lib/puppet/pgraph.rb14
-rwxr-xr-xlib/puppet/provider/package/fink.rb2
-rwxr-xr-xlib/puppet/provider/package/openbsd.rb2
-rw-r--r--lib/puppet/provider/user/useradd.rb2
-rw-r--r--lib/puppet/resource_reference.rb2
-rw-r--r--lib/puppet/simple_graph.rb8
-rw-r--r--lib/puppet/sslcertificates/ca.rb6
-rw-r--r--lib/puppet/transaction.rb4
-rw-r--r--lib/puppet/transportable.rb2
-rwxr-xr-xlib/puppet/type/cron.rb25
-rwxr-xr-xlib/puppet/type/exec.rb23
-rwxr-xr-xlib/puppet/type/host.rb13
-rw-r--r--lib/puppet/type/package.rb4
-rw-r--r--lib/puppet/type/pfile.rb2
-rwxr-xr-xlib/puppet/type/pfile/ensure.rb5
-rwxr-xr-xlib/puppet/type/pfile/source.rb4
-rw-r--r--lib/puppet/util/constant_inflector.rb14
-rw-r--r--lib/puppet/util/graph.rb2
-rw-r--r--lib/puppet/util/settings.rb35
-rw-r--r--lib/puppet/util/tagging.rb39
58 files changed, 1027 insertions, 961 deletions
diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb
index cfbdf7bc7..4fb03f164 100644
--- a/lib/puppet/defaults.rb
+++ b/lib/puppet/defaults.rb
@@ -66,7 +66,11 @@ module Puppet
:owner => "root",
:desc => "Where SSL certificates are kept."
},
- :rundir => { :default => rundir,
+ :rundir => {
+ :default => rundir,
+ :mode => 01777,
+ :owner => "$user",
+ :group => "$group",
:desc => "Where Puppet PID files are kept."
},
:genconfig => [false,
@@ -228,7 +232,7 @@ module Puppet
:owner => "$user",
:group => "$group",
:mode => 0664,
- :desc => "The certificate revocation list (CRL) for the CA. Set this to 'none' if you do not want to use a CRL."
+ :desc => "The certificate revocation list (CRL) for the CA. Set this to 'false' if you do not want to use a CRL."
},
:caprivatedir => { :default => "$cadir/private",
:owner => "$user",
diff --git a/lib/puppet/metatype/metaparams.rb b/lib/puppet/metatype/metaparams.rb
index b35adae66..9983c34d2 100644
--- a/lib/puppet/metatype/metaparams.rb
+++ b/lib/puppet/metatype/metaparams.rb
@@ -258,7 +258,7 @@ class Puppet::Type
@value.each do |value|
unless @resource.catalog.resource(*value)
description = self.class.direction == :in ? "dependency" : "dependent"
- raise Puppet::Error, "Could not find #{description} %s[%s]" % [value[0].to_s.capitalize, value[1]]
+ fail Puppet::Error, "Could not find #{description} %s[%s] for %s" % [value[0].to_s.capitalize, value[1], resource.ref]
end
end
end
diff --git a/lib/puppet/network/http_server/mongrel.rb b/lib/puppet/network/http_server/mongrel.rb
index d6e21b189..d340f3d63 100644
--- a/lib/puppet/network/http_server/mongrel.rb
+++ b/lib/puppet/network/http_server/mongrel.rb
@@ -127,7 +127,12 @@ module Puppet::Network
client = dn_matchdata[1].to_str
valid = (params[Puppet[:ssl_client_verify_header]] == 'SUCCESS')
else
- client = Resolv.getname(ip)
+ begin
+ client = Resolv.getname(ip)
+ rescue => detail
+ Puppet.err "Could not resolve %s: %s" % [ip, detail]
+ client = "unknown"
+ end
valid = false
end
diff --git a/lib/puppet/network/http_server/webrick.rb b/lib/puppet/network/http_server/webrick.rb
index 3c9f72e17..e4f00dd73 100644
--- a/lib/puppet/network/http_server/webrick.rb
+++ b/lib/puppet/network/http_server/webrick.rb
@@ -22,12 +22,12 @@ module Puppet
# with them, with flags appropriate for checking client
# certificates for revocation
def x509store
- if Puppet[:cacrl] == 'none'
+ if Puppet[:cacrl] == 'false'
# No CRL, no store needed
return nil
end
unless File.exist?(Puppet[:cacrl])
- raise Puppet::Error, "Could not find CRL; set 'cacrl' to 'none' to disable CRL usage"
+ raise Puppet::Error, "Could not find CRL; set 'cacrl' to 'false' to disable CRL usage"
end
crl = OpenSSL::X509::CRL.new(File.read(Puppet[:cacrl]))
store = OpenSSL::X509::Store.new
diff --git a/lib/puppet/network/xmlrpc/client.rb b/lib/puppet/network/xmlrpc/client.rb
index 27bb3dc5e..f6a5e8db6 100644
--- a/lib/puppet/network/xmlrpc/client.rb
+++ b/lib/puppet/network/xmlrpc/client.rb
@@ -90,6 +90,13 @@ module Puppet::Network
@clients[handler] || self.mkclient(handler)
end
+ def http
+ unless @http
+ @http = Puppet::Network::HttpPool.http_instance(@host, @port, true)
+ end
+ @http
+ end
+
def initialize(hash = {})
hash[:Path] ||= "/RPC2"
hash[:Server] ||= Puppet[:server]
@@ -125,7 +132,11 @@ module Puppet::Network
end
def start
- @http.start unless @http.started?
+ begin
+ @http.start unless @http.started?
+ rescue => detail
+ Puppet.err "Could not connect to server: %s" % detail
+ end
end
def local
diff --git a/lib/puppet/node/catalog.rb b/lib/puppet/node/catalog.rb
index 9601309d8..b74947107 100644
--- a/lib/puppet/node/catalog.rb
+++ b/lib/puppet/node/catalog.rb
@@ -1,5 +1,7 @@
require 'puppet/indirector'
+require 'puppet/util/tagging'
+
# This class models a node catalog. It is the thing
# meant to be passed from server to client, and it contains all
# of the information in the catalog, including the resources
@@ -8,6 +10,8 @@ class Puppet::Node::Catalog < Puppet::PGraph
extend Puppet::Indirector
indirects :catalog, :terminus_class => :compiler
+ include Puppet::Util::Tagging
+
# The host name this is a catalog for.
attr_accessor :name
@@ -58,14 +62,14 @@ class Puppet::Node::Catalog < Puppet::PGraph
raise ArgumentError, "Can only add objects that respond to :ref"
end
+ fail_unless_unique(resource)
+
ref = resource.ref
- if @resource_table.include?(ref)
- raise ArgumentError, "Resource %s is already defined" % ref
- else
- @resource_table[ref] = resource
- end
- resource.catalog = self unless is_relationship_graph
- add_vertex!(resource)
+
+ @resource_table[ref] = resource
+
+ resource.catalog = self if resource.respond_to?(:catalog=) and ! is_relationship_graph
+ add_vertex(resource)
end
end
@@ -268,7 +272,6 @@ class Puppet::Node::Catalog < Puppet::PGraph
super()
@name = name if name
@extraction_format ||= :transportable
- @tags = []
@classes = []
@resource_table = {}
@transient_resources = []
@@ -313,9 +316,9 @@ class Puppet::Node::Catalog < Puppet::PGraph
# First create the dependency graph
self.vertices.each do |vertex|
- @relationship_graph.add_vertex! vertex
+ @relationship_graph.add_vertex vertex
vertex.builddepends.each do |edge|
- @relationship_graph.add_edge!(edge)
+ @relationship_graph.add_edge(edge)
end
end
@@ -325,7 +328,7 @@ class Puppet::Node::Catalog < Puppet::PGraph
unless @relationship_graph.edge?(edge.source, edge.target) # don't let automatic relationships conflict with manual ones.
unless @relationship_graph.edge?(edge.target, edge.source)
vertex.debug "Autorequiring %s" % [edge.source]
- @relationship_graph.add_edge!(edge)
+ @relationship_graph.add_edge(edge)
else
vertex.debug "Skipping automatic relationship with %s" % (edge.source == vertex ? edge.target : edge.source)
end
@@ -381,25 +384,6 @@ class Puppet::Node::Catalog < Puppet::PGraph
@resource_table.keys
end
- # Add a tag.
- def tag(*names)
- names.each do |name|
- name = name.to_s
- @tags << name unless @tags.include?(name)
- if name.include?("::")
- name.split("::").each do |sub|
- @tags << sub unless @tags.include?(sub)
- end
- end
- end
- nil
- end
-
- # Return the list of tags.
- def tags
- @tags.dup
- end
-
# Convert our catalog into a RAL catalog.
def to_ral
to_catalog :to_type
@@ -447,6 +431,28 @@ class Puppet::Node::Catalog < Puppet::PGraph
end
end
+ # Verify that the given resource isn't defined elsewhere.
+ def fail_unless_unique(resource)
+ # Short-curcuit the common case,
+ return unless existing_resource = @resource_table[resource.ref]
+
+ # Either it's a defined type, which are never
+ # isomorphic, or it's a non-isomorphic type, so
+ # we should throw an exception.
+ msg = "Duplicate definition: %s is already defined" % resource.ref
+
+ if existing_resource.file and existing_resource.line
+ msg << " in file %s at line %s" %
+ [existing_resource.file, existing_resource.line]
+ end
+
+ if resource.line or resource.file
+ msg << "; cannot redefine"
+ end
+
+ raise ArgumentError.new(msg)
+ end
+
# An abstracted method for converting one catalog into another type of catalog.
# This pretty much just converts all of the resources from one class to another, using
# a conversion method.
@@ -481,7 +487,7 @@ class Puppet::Node::Catalog < Puppet::PGraph
raise Puppet::DevError, "Could not find resource %s when converting %s resources" % [edge.target.ref, message]
end
- result.add_edge!(source, target, edge.label)
+ result.add_edge(source, target, edge.label)
end
map.clear
diff --git a/lib/puppet/parser/ast.rb b/lib/puppet/parser/ast.rb
index 14b686e2f..c9bd7c9e8 100644
--- a/lib/puppet/parser/ast.rb
+++ b/lib/puppet/parser/ast.rb
@@ -14,30 +14,6 @@ class Puppet::Parser::AST
include Puppet::Util::MethodHelper
attr_accessor :line, :file, :parent, :scope
- # Just used for 'tree', which is only used in debugging.
- @@pink = ""
- @@green = ""
- @@yellow = ""
- @@slate = ""
- @@reset = ""
-
- # Just used for 'tree', which is only used in debugging.
- @@indent = " " * 4
- @@indline = @@pink + ("-" * 4) + @@reset
- @@midline = @@slate + ("-" * 4) + @@reset
-
- @@settypes = {}
-
- # Just used for 'tree', which is only used in debugging.
- def AST.indention
- return @@indent * @@indention
- end
-
- # Just used for 'tree', which is only used in debugging.
- def AST.midline
- return @@midline
- end
-
# Does this ast object set something? If so, it gets evaluated first.
def self.settor?
if defined? @settor
@@ -47,16 +23,12 @@ class Puppet::Parser::AST
end
end
- # Evaluate the current object. Basically just iterates across all
+ # 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(args)
- #Puppet.debug("Evaluating ast %s" % @name)
- value = self.collect { |obj|
- obj.safeevaluate(args)
- }.reject { |obj|
- obj.nil?
- }
+ def evaluate(*options)
+ raise Puppet::DevError, "Did not override #evaluate in %s" % self.class
end
# Throw a parse error.
@@ -75,11 +47,11 @@ class Puppet::Parser::AST
# 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)
+ 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)
+ return self.evaluate(*options)
rescue Puppet::Error => detail
raise adderrorcontext(detail)
rescue => detail
@@ -90,14 +62,6 @@ class Puppet::Parser::AST
end
end
- # Again, just used for printing out the parse tree.
- def typewrap(string)
- #return self.class.to_s.sub(/.+::/,'') +
- #"(" + @@green + string.to_s + @@reset + ")"
- return @@green + string.to_s + @@reset +
- "(" + self.class.to_s.sub(/.+::/,'') + ")"
- 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
@@ -107,13 +71,27 @@ class Puppet::Parser::AST
@line = nil
set_options(args)
end
- #---------------------------------------------------------------
- # Now autoload everything.
- @autoloader = Puppet::Util::Autoload.new(self,
- "puppet/parser/ast"
- )
- @autoloader.loadall
end
+# And include all of the AST subclasses.
+require 'puppet/parser/ast/astarray'
+require 'puppet/parser/ast/branch'
+require 'puppet/parser/ast/caseopt'
+require 'puppet/parser/ast/casestatement'
+require 'puppet/parser/ast/collection'
+require 'puppet/parser/ast/collexpr'
+require 'puppet/parser/ast/definition'
+require 'puppet/parser/ast/else'
+require 'puppet/parser/ast/function'
+require 'puppet/parser/ast/hostclass'
+require 'puppet/parser/ast/ifstatement'
require 'puppet/parser/ast/leaf'
-
+require 'puppet/parser/ast/node'
+require 'puppet/parser/ast/resource'
+require 'puppet/parser/ast/resource_defaults'
+require 'puppet/parser/ast/resource_override'
+require 'puppet/parser/ast/resource_reference'
+require 'puppet/parser/ast/resourceparam'
+require 'puppet/parser/ast/selector'
+require 'puppet/parser/ast/tag'
+require 'puppet/parser/ast/vardef'
diff --git a/lib/puppet/parser/ast/astarray.rb b/lib/puppet/parser/ast/astarray.rb
index 5f1e838d0..b66fd6bba 100644
--- a/lib/puppet/parser/ast/astarray.rb
+++ b/lib/puppet/parser/ast/astarray.rb
@@ -15,8 +15,7 @@ class Puppet::Parser::AST
end
# Evaluate our children.
- def evaluate(hash)
- scope = hash[:scope]
+ def evaluate(scope)
rets = nil
# We basically always operate declaratively, and when we
# do we need to evaluate the settor-like statements first. This
@@ -51,7 +50,7 @@ class Puppet::Parser::AST
}
rets = [settors, others].flatten.collect { |child|
- child.safeevaluate(:scope => scope)
+ child.safeevaluate(scope)
}
return rets.reject { |o| o.nil? }
end
diff --git a/lib/puppet/parser/ast/caseopt.rb b/lib/puppet/parser/ast/caseopt.rb
index d1d9d0e9c..824bde853 100644
--- a/lib/puppet/parser/ast/caseopt.rb
+++ b/lib/puppet/parser/ast/caseopt.rb
@@ -44,17 +44,17 @@ class Puppet::Parser::AST
def eachvalue(scope)
if @value.is_a?(AST::ASTArray)
@value.each { |subval|
- yield subval.evaluate(:scope => scope)
+ yield subval.safeevaluate(scope)
}
else
- yield @value.evaluate(:scope => scope)
+ yield @value.safeevaluate(scope)
end
end
# Evaluate the actual statements; this only gets called if
# our option matched.
- def evaluate(hash)
- return @statements.safeevaluate(hash)
+ def evaluate(scope)
+ return @statements.safeevaluate(scope)
end
end
end
diff --git a/lib/puppet/parser/ast/casestatement.rb b/lib/puppet/parser/ast/casestatement.rb
index 3c6f9c7e2..aa03090de 100644
--- a/lib/puppet/parser/ast/casestatement.rb
+++ b/lib/puppet/parser/ast/casestatement.rb
@@ -8,9 +8,8 @@ class Puppet::Parser::AST
# Short-curcuit evaluation. Return the value of the statements for
# the first option that matches.
- def evaluate(hash)
- scope = hash[:scope]
- value = @test.safeevaluate(:scope => scope)
+ def evaluate(scope)
+ value = @test.safeevaluate(scope)
sensitive = Puppet[:casesensitive]
value = value.downcase if ! sensitive and value.respond_to?(:downcase)
@@ -30,7 +29,7 @@ class Puppet::Parser::AST
if found
# we found a matching option
- retvalue = option.safeevaluate(:scope => scope)
+ retvalue = option.safeevaluate(scope)
break
end
@@ -42,7 +41,7 @@ class Puppet::Parser::AST
# Unless we found something, look for the default.
unless found
if default
- retvalue = default.safeevaluate(:scope => scope)
+ retvalue = default.safeevaluate(scope)
else
Puppet.debug "No true answers and no default"
retvalue = nil
diff --git a/lib/puppet/parser/ast/collection.rb b/lib/puppet/parser/ast/collection.rb
index e05977a47..9e795a33c 100644
--- a/lib/puppet/parser/ast/collection.rb
+++ b/lib/puppet/parser/ast/collection.rb
@@ -9,18 +9,16 @@ class Collection < AST::Branch
attr_accessor :type, :query, :form
# We return an object that does a late-binding evaluation.
- def evaluate(hash)
- scope = hash[:scope]
-
+ def evaluate(scope)
if self.query
- str, code = self.query.safeevaluate :scope => scope
+ str, code = self.query.safeevaluate scope
else
str = code = nil
end
newcoll = Puppet::Parser::Collector.new(scope, @type, str, code, self.form)
- scope.compile.add_collection(newcoll)
+ scope.compiler.add_collection(newcoll)
newcoll
end
diff --git a/lib/puppet/parser/ast/collexpr.rb b/lib/puppet/parser/ast/collexpr.rb
index 4a96d9c61..3e13d9400 100644
--- a/lib/puppet/parser/ast/collexpr.rb
+++ b/lib/puppet/parser/ast/collexpr.rb
@@ -9,9 +9,7 @@ class CollExpr < AST::Branch
attr_accessor :test1, :test2, :oper, :form, :type, :parens
# We return an object that does a late-binding evaluation.
- def evaluate(hash)
- scope = hash[:scope]
-
+ 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)
@@ -21,8 +19,8 @@ class CollExpr < AST::Branch
end
# The code is only used for virtual lookups
- str1, code1 = @test1.safeevaluate :scope => scope
- str2, code2 = @test2.safeevaluate :scope => scope
+ 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
diff --git a/lib/puppet/parser/ast/definition.rb b/lib/puppet/parser/ast/definition.rb
index 3d6d6188c..2b7506446 100644
--- a/lib/puppet/parser/ast/definition.rb
+++ b/lib/puppet/parser/ast/definition.rb
@@ -1,155 +1,148 @@
require 'puppet/parser/ast/branch'
-class Puppet::Parser::AST
- # Evaluate the stored parse tree for a given component. This will
- # receive the arguments passed to the component and also the type and
- # name of the component.
- class Definition < AST::Branch
- include Puppet::Util
- include Puppet::Util::Warnings
- include Puppet::Util::MethodHelper
- class << self
- attr_accessor :name
- end
+require 'puppet/util/warnings'
- # The class name
- @name = :definition
+# The AST class for defined types, which is also the base class
+# nodes and classes.
+class Puppet::Parser::AST::Definition < Puppet::Parser::AST::Branch
+ include Puppet::Util::Warnings
+ class << self
+ attr_accessor :name
+ end
- attr_accessor :classname, :arguments, :code, :scope, :keyword
- attr_accessor :exported, :namespace, :parser, :virtual
+ # The class name
+ @name = :definition
- # These are retrieved when looking up the superclass
- attr_accessor :name
+ attr_accessor :classname, :arguments, :code, :scope, :keyword
+ attr_accessor :exported, :namespace, :parser, :virtual, :name
- attr_reader :parentclass
+ attr_reader :parentclass
- def child_of?(klass)
- false
- end
+ def child_of?(klass)
+ false
+ end
- def evaluate(options)
- origscope = options[:scope]
- resource = options[:resource]
+ # Create a resource that knows how to evaluate our actual code.
+ def evaluate(scope)
+ # Do nothing if the resource already exists; this provides the singleton nature classes need.
+ return if scope.catalog.resource(self.class.name, self.classname)
- # Create a new scope.
- scope = subscope(origscope, resource)
+ resource = Puppet::Parser::Resource.new(:type => self.class.name, :title => self.classname, :scope => scope, :source => scope.source)
- # Additionally, add a tag for whatever kind of class
- # we are
- if @classname != "" and ! @classname.nil?
- @classname.split(/::/).each { |tag| scope.resource.tag(tag) }
- end
+ scope.catalog.tag(*resource.tags)
- [resource.name, resource.title].each do |str|
- unless str.nil? or str =~ /[^\w]/ or str == ""
- scope.resource.tag(str)
- end
- end
+ scope.compiler.add_resource(scope, resource)
- set_resource_parameters(scope, resource)
+ return resource
+ end
- if self.code
- return self.code.safeevaluate(:scope => scope)
- else
- return nil
- end
+ # Now evaluate the code associated with this class or definition.
+ def evaluate_code(resource)
+ # Create a new scope.
+ scope = subscope(resource.scope, resource)
+
+ set_resource_parameters(scope, resource)
+
+ if self.code
+ return self.code.safeevaluate(scope)
+ else
+ return nil
end
+ end
- def initialize(hash = {})
- @arguments = nil
- @parentclass = nil
- super
+ def initialize(hash = {})
+ @arguments = nil
+ @parentclass = nil
+ super
- # Convert the arguments to a hash for ease of later use.
- if @arguments
- unless @arguments.is_a? Array
- @arguments = [@arguments]
- end
- oldargs = @arguments
- @arguments = {}
- oldargs.each do |arg, val|
- @arguments[arg] = val
- end
- else
- @arguments = {}
+ # Convert the arguments to a hash for ease of later use.
+ if @arguments
+ unless @arguments.is_a? Array
+ @arguments = [@arguments]
end
-
- # Deal with metaparams in the argument list.
- @arguments.each do |arg, defvalue|
- next unless Puppet::Type.metaparamclass(arg)
- if defvalue
- warnonce "%s is a metaparam; this value will inherit to all contained resources" % arg
- else
- raise Puppet::ParseError, "%s is a metaparameter; please choose another parameter name in the %s definition" % [arg, self.classname]
- end
+ oldargs = @arguments
+ @arguments = {}
+ oldargs.each do |arg, val|
+ @arguments[arg] = val
end
+ else
+ @arguments = {}
end
- def find_parentclass
- @parser.findclass(namespace, parentclass)
+ # Deal with metaparams in the argument list.
+ @arguments.each do |arg, defvalue|
+ next unless Puppet::Type.metaparamclass(arg)
+ if defvalue
+ warnonce "%s is a metaparam; this value will inherit to all contained resources" % arg
+ else
+ raise Puppet::ParseError, "%s is a metaparameter; please choose another parameter name in the %s definition" % [arg, self.classname]
+ end
end
+ end
- # Set our parent class, with a little check to avoid some potential
- # weirdness.
- def parentclass=(name)
- if name == self.classname
- parsefail "Parent classes must have dissimilar names"
- end
+ def find_parentclass
+ @parser.findclass(namespace, parentclass)
+ end
- @parentclass = name
+ # Set our parent class, with a little check to avoid some potential
+ # weirdness.
+ def parentclass=(name)
+ if name == self.classname
+ parsefail "Parent classes must have dissimilar names"
end
- # Hunt down our class object.
- def parentobj
- if @parentclass
- # Cache our result, since it should never change.
- unless defined?(@parentobj)
- unless tmp = find_parentclass
- parsefail "Could not find %s %s" % [self.class.name, @parentclass]
- end
+ @parentclass = name
+ end
- if tmp == self
- parsefail "Parent classes must have dissimilar names"
- end
+ # Hunt down our class object.
+ def parentobj
+ return nil unless @parentclass
- @parentobj = tmp
- end
- @parentobj
- else
- nil
+ # Cache our result, since it should never change.
+ unless defined?(@parentobj)
+ unless tmp = find_parentclass
+ parsefail "Could not find %s parent %s" % [self.class.name, @parentclass]
+ end
+
+ if tmp == self
+ parsefail "Parent classes must have dissimilar names"
end
+
+ @parentobj = tmp
end
+ @parentobj
+ end
- # Create a new subscope in which to evaluate our code.
- def subscope(scope, resource)
- args = {
- :resource => resource,
- :keyword => self.keyword,
- :namespace => self.namespace,
- :source => self
- }
+ # Create a new subscope in which to evaluate our code.
+ def subscope(scope, resource)
+ args = {
+ :resource => resource,
+ :keyword => self.keyword,
+ :namespace => self.namespace,
+ :source => self
+ }
- oldscope = scope
- scope = scope.newscope(args)
- scope.source = self
+ oldscope = scope
+ scope = scope.newscope(args)
+ scope.source = self
- return scope
- end
+ return scope
+ end
- def to_s
- classname
- end
+ def to_s
+ classname
+ end
- # Check whether a given argument is valid. Searches up through
- # any parent classes that might exist.
- def validattr?(param)
- param = param.to_s
+ # Check whether a given argument is valid. Searches up through
+ # any parent classes that might exist.
+ def validattr?(param)
+ param = param.to_s
- if @arguments.include?(param)
- # It's a valid arg for us
- return true
- elsif param == "name"
- return true
+ if @arguments.include?(param)
+ # It's a valid arg for us
+ return true
+ elsif param == "name"
+ return true
# elsif defined? @parentclass and @parentclass
# # Else, check any existing parent
# if parent = @scope.lookuptype(@parentclass) and parent != []
@@ -160,53 +153,52 @@ class Puppet::Parser::AST
# raise Puppet::Error, "Could not find parent class %s" %
# @parentclass
# end
- elsif Puppet::Type.metaparam?(param)
- return true
- else
- # Or just return false
- return false
- end
+ elsif Puppet::Type.metaparam?(param)
+ return true
+ else
+ # Or just return false
+ return false
end
+ end
- private
-
- # Set any arguments passed by the resource as variables in the scope.
- def set_resource_parameters(scope, resource)
- args = symbolize_options(resource.to_hash || {})
-
- # Verify that all required arguments are either present or
- # have been provided with defaults.
- if self.arguments
- self.arguments.each { |arg, default|
- arg = symbolize(arg)
- unless args.include?(arg)
- if defined? default and ! default.nil?
- default = default.safeevaluate :scope => scope
- args[arg] = default
- #Puppet.debug "Got default %s for %s in %s" %
- # [default.inspect, arg.inspect, @name.inspect]
- else
- parsefail "Must pass %s to %s of type %s" %
- [arg, resource.title, @classname]
- end
+ private
+
+ # Set any arguments passed by the resource as variables in the scope.
+ def set_resource_parameters(scope, resource)
+ args = symbolize_options(resource.to_hash || {})
+
+ # Verify that all required arguments are either present or
+ # have been provided with defaults.
+ if self.arguments
+ self.arguments.each { |arg, default|
+ arg = arg.to_sym
+ unless args.include?(arg)
+ if defined? default and ! default.nil?
+ default = default.safeevaluate scope
+ args[arg] = default
+ #Puppet.debug "Got default %s for %s in %s" %
+ # [default.inspect, arg.inspect, @name.inspect]
+ else
+ parsefail "Must pass %s to %s of type %s" %
+ [arg, resource.title, @classname]
end
- }
- end
-
- # Set each of the provided arguments as variables in the
- # definition's scope.
- args.each { |arg,value|
- unless validattr?(arg)
- parsefail "%s does not accept attribute %s" % [@classname, arg]
- end
-
- exceptwrap do
- scope.setvar(arg.to_s, args[arg])
end
}
-
- scope.setvar("title", resource.title) unless args.include? :title
- scope.setvar("name", resource.name) unless args.include? :name
end
+
+ # Set each of the provided arguments as variables in the
+ # definition's scope.
+ args.each { |arg,value|
+ unless validattr?(arg)
+ parsefail "%s does not accept attribute %s" % [@classname, arg]
+ end
+
+ exceptwrap do
+ scope.setvar(arg.to_s, args[arg])
+ end
+ }
+
+ scope.setvar("title", resource.title) unless args.include? :title
+ scope.setvar("name", resource.name) unless args.include? :name
end
end
diff --git a/lib/puppet/parser/ast/else.rb b/lib/puppet/parser/ast/else.rb
index e76051372..affac625d 100644
--- a/lib/puppet/parser/ast/else.rb
+++ b/lib/puppet/parser/ast/else.rb
@@ -12,9 +12,8 @@ class Puppet::Parser::AST
# Evaluate the actual statements; this only gets called if
# our test was true matched.
- def evaluate(hash)
- scope = hash[:scope]
- return @statements.safeevaluate(:scope => scope)
+ def evaluate(scope)
+ return @statements.safeevaluate(scope)
end
end
end
diff --git a/lib/puppet/parser/ast/function.rb b/lib/puppet/parser/ast/function.rb
index 0cd1fff62..63d7c7abf 100644
--- a/lib/puppet/parser/ast/function.rb
+++ b/lib/puppet/parser/ast/function.rb
@@ -7,18 +7,11 @@ class Puppet::Parser::AST
@settor = true
- def evaluate(hash)
+ def evaluate(scope)
# We don't need to evaluate the name, because it's plaintext
+ args = @arguments.safeevaluate(scope)
- # Just evaluate the arguments
- scope = hash[:scope]
-
- args = @arguments.safeevaluate(:scope => scope)
-
- #exceptwrap :message => "Failed to execute %s" % @name,
- # :type => Puppet::ParseError do
- return scope.send("function_" + @name, args)
- #end
+ return scope.send("function_" + @name, args)
end
def initialize(hash)
diff --git a/lib/puppet/parser/ast/hostclass.rb b/lib/puppet/parser/ast/hostclass.rb
index 63900d0e3..8d4d01660 100644
--- a/lib/puppet/parser/ast/hostclass.rb
+++ b/lib/puppet/parser/ast/hostclass.rb
@@ -1,80 +1,80 @@
require 'puppet/parser/ast/definition'
-class Puppet::Parser::AST
- # The code associated with a class. This is different from definitions
- # in that each class is a singleton -- only one will exist for a given
- # node.
- class HostClass < AST::Definition
- @name = :class
+# The code associated with a class. This is different from definitions
+# in that each class is a singleton -- only one will exist for a given
+# node.
+class Puppet::Parser::AST::HostClass < Puppet::Parser::AST::Definition
+ @name = :class
- # Are we a child of the passed class? Do a recursive search up our
- # parentage tree to figure it out.
- def child_of?(klass)
- return false unless self.parentclass
+ # Are we a child of the passed class? Do a recursive search up our
+ # parentage tree to figure it out.
+ def child_of?(klass)
+ return false unless self.parentclass
- if klass == self.parentobj
- return true
- else
- return self.parentobj.child_of?(klass)
- end
+ if klass == self.parentobj
+ return true
+ else
+ return self.parentobj.child_of?(klass)
end
+ end
- # Evaluate the code associated with this class.
- def evaluate(options)
- scope = options[:scope]
- raise(ArgumentError, "Classes require resources") unless options[:resource]
- # Verify that we haven't already been evaluated. This is
- # what provides the singleton aspect.
- if existing_scope = scope.compile.class_scope(self)
- Puppet.debug "Class '%s' already evaluated; not evaluating again" % (classname == "" ? "main" : classname)
- return nil
- end
-
- scope.compile.catalog.tag(self.classname)
+ # Make sure our parent class has been evaluated, if we have one.
+ def evaluate(scope)
+ if parentclass and ! scope.catalog.resource(self.class.name, parentclass)
+ resource = parentobj.evaluate(scope)
+ end
- pnames = nil
- if pklass = self.parentobj
- pklass.safeevaluate :scope => scope, :resource => options[:resource]
+ super
+ end
- scope = parent_scope(scope, pklass)
- pnames = scope.namespaces
- end
+ # Evaluate the code associated with this class.
+ def evaluate_code(resource)
+ scope = resource.scope
+ # Verify that we haven't already been evaluated. This is
+ # what provides the singleton aspect.
+ if existing_scope = scope.compiler.class_scope(self)
+ Puppet.debug "Class '%s' already evaluated; not evaluating again" % (classname == "" ? "main" : classname)
+ return nil
+ end
- # Don't create a subscope for the top-level class, since it already
- # has its own scope.
- unless options[:resource].title == :main
- scope = subscope(scope, options[:resource])
- end
+ pnames = nil
+ if pklass = self.parentobj
+ parent_resource = resource.scope.compiler.catalog.resource(self.class.name, pklass.classname)
+ # This shouldn't evaluate if the class has already been evaluated.
+ pklass.evaluate_code(parent_resource)
- if pnames
- pnames.each do |ns|
- scope.add_namespace(ns)
- end
- end
+ scope = parent_scope(scope, pklass)
+ pnames = scope.namespaces
+ end
- # Set the class before we do anything else, so that it's set
- # during the evaluation and can be inspected.
- scope.compile.class_set(self.classname, scope)
+ # Don't create a subscope for the top-level class, since it already
+ # has its own scope.
+ scope = subscope(scope, resource) unless resource.title == :main
- # Now evaluate our code, yo.
- if self.code
- return self.code.evaluate(:scope => scope)
- else
- return nil
+ # Add the parent scope namespaces to our own.
+ if pnames
+ pnames.each do |ns|
+ scope.add_namespace(ns)
end
end
- def initialize(options)
- @parentclass = nil
- super
+ # Set the class before we evaluate the code, so that it's set during
+ # the evaluation and can be inspected.
+ scope.compiler.class_set(self.classname, scope)
+
+ # Now evaluate our code, yo.
+ if self.code
+ return self.code.safeevaluate(scope)
+ else
+ return nil
end
+ end
- def parent_scope(scope, klass)
- if s = scope.compile.class_scope(klass)
- return s
- else
- raise Puppet::DevError, "Could not find scope for %s" % klass.classname
- end
+ def parent_scope(scope, klass)
+ if s = scope.compiler.class_scope(klass)
+ return s
+ else
+ raise Puppet::DevError, "Could not find scope for %s" % klass.classname
end
end
end
diff --git a/lib/puppet/parser/ast/ifstatement.rb b/lib/puppet/parser/ast/ifstatement.rb
index 66a07b01f..afa2cd572 100644
--- a/lib/puppet/parser/ast/ifstatement.rb
+++ b/lib/puppet/parser/ast/ifstatement.rb
@@ -12,15 +12,14 @@ class Puppet::Parser::AST
# 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(hash)
- scope = hash[:scope]
- value = @test.safeevaluate(:scope => scope)
+ def evaluate(scope)
+ value = @test.safeevaluate(scope)
if Puppet::Parser::Scope.true?(value)
- return @statements.safeevaluate(:scope => scope)
+ return @statements.safeevaluate(scope)
else
if defined? @else
- return @else.safeevaluate(:scope => scope)
+ return @else.safeevaluate(scope)
else
return nil
end
diff --git a/lib/puppet/parser/ast/leaf.rb b/lib/puppet/parser/ast/leaf.rb
index 225253061..c545c1e47 100644
--- a/lib/puppet/parser/ast/leaf.rb
+++ b/lib/puppet/parser/ast/leaf.rb
@@ -6,7 +6,7 @@ class Puppet::Parser::AST
attr_accessor :value, :type
# Return our value.
- def evaluate(hash)
+ def evaluate(scope)
return @value
end
@@ -35,14 +35,14 @@ class Puppet::Parser::AST
class String < AST::Leaf
# Interpolate the string looking for variables, and then return
# the result.
- def evaluate(hash)
- return hash[:scope].strinterp(@value, @file, @line)
+ def evaluate(scope)
+ return scope.strinterp(@value, @file, @line)
end
end
# An uninterpreted string.
class FlatString < AST::Leaf
- def evaluate(hash)
+ def evaluate(scope)
return @value
end
end
@@ -81,9 +81,9 @@ class Puppet::Parser::AST
class Variable < Name
# Looks up the value of the object in the scope tree (does
# not include syntactical constructs, like '$' and '{}').
- def evaluate(hash)
+ def evaluate(scope)
parsewrap do
- return hash[:scope].lookupvar(@value)
+ return scope.lookupvar(@value)
end
end
end
diff --git a/lib/puppet/parser/ast/node.rb b/lib/puppet/parser/ast/node.rb
index a296e43ba..2bf6c1882 100644
--- a/lib/puppet/parser/ast/node.rb
+++ b/lib/puppet/parser/ast/node.rb
@@ -1,67 +1,35 @@
require 'puppet/parser/ast/hostclass'
-class Puppet::Parser::AST
- # The specific code associated with a host. Nodes are annoyingly unlike
- # other objects. That's just the way it is, at least for now.
- class Node < AST::HostClass
- @name = :node
- attr_accessor :name
-
- def evaluate(options)
- scope = options[:scope]
-
- #pscope = if ! Puppet[:lexical] or options[:asparent]
- # @scope
- #else
- # origscope
- #end
-
- # We don't have to worry about the declarativeness of node parentage,
- # because the entry point is always a single node definition.
- if parent = self.parentobj
- scope = parent.safeevaluate :scope => scope, :resource => options[:resource]
- end
-
- scope = scope.newscope(
- :resource => options[:resource],
- :keyword => @keyword,
- :source => self,
- :namespace => "" # nodes are always in ""
- )
-
- # Mark our node name as a class, too, but strip it of the domain
- # name. Make the mark before we evaluate the code, so that it is
- # marked within the code itself.
- scope.compile.class_set(self.classname, scope)
-
- # And then evaluate our code if we have any
- if self.code
- @code.safeevaluate(:scope => scope)
- end
-
- return scope
+# The specific code associated with a host. Nodes are annoyingly unlike
+# other objects. That's just the way it is, at least for now.
+class Puppet::Parser::AST::Node < Puppet::Parser::AST::HostClass
+ @name = :node
+
+ def initialize(options)
+ @parentclass = nil
+ super
+
+ # Do some validation on the node name
+ if @name =~ /[^-\w.]/
+ raise Puppet::ParseError, "Invalid node name %s" % @name
end
+ end
- def initialize(options)
- @parentclass = nil
- super
+ def namespace
+ ""
+ end
- # Do some validation on the node name
- if @name =~ /[^-\w.]/
- raise Puppet::ParseError, "Invalid node name %s" % @name
- end
- end
+ # Make sure node scopes are marked as such.
+ def subscope(*args)
+ scope = super
+ scope.nodescope = true
+ scope
+ end
- # Make sure node scopes are marked as such.
- def subscope(*args)
- scope = super
- scope.nodescope = true
- end
+ private
- private
- # Search for the object matching our parent class.
- def find_parentclass
- @parser.findnode(parentclass)
- end
+ # Search for the object matching our parent class.
+ def find_parentclass
+ @parser.findnode(parentclass)
end
end
diff --git a/lib/puppet/parser/ast/resource.rb b/lib/puppet/parser/ast/resource.rb
index c53ab0a68..8a60522a3 100644
--- a/lib/puppet/parser/ast/resource.rb
+++ b/lib/puppet/parser/ast/resource.rb
@@ -9,15 +9,13 @@ class Resource < AST::ResourceReference
# Does not actually return an object; instead sets an object
# in the current scope.
- def evaluate(options)
- scope = options[:scope]
-
+ def evaluate(scope)
# Evaluate all of the specified params.
paramobjects = @params.collect { |param|
- param.safeevaluate(:scope => scope)
+ param.safeevaluate(scope)
}
- objtitles = @title.safeevaluate(:scope => scope)
+ objtitles = @title.safeevaluate(scope)
# it's easier to always use an array, even for only one name
unless objtitles.is_a?(Array)
@@ -50,10 +48,10 @@ class Resource < AST::ResourceReference
:scope => scope
)
- # And then store the resource in the compile.
+ # And then store the resource in the compiler.
# At some point, we need to switch all of this to return
# objects instead of storing them like this.
- scope.compile.store_resource(scope, obj)
+ scope.compiler.add_resource(scope, obj)
obj
end
}.reject { |obj| obj.nil? }
diff --git a/lib/puppet/parser/ast/resource_defaults.rb b/lib/puppet/parser/ast/resource_defaults.rb
index 8f9c1b8df..4856f0594 100644
--- a/lib/puppet/parser/ast/resource_defaults.rb
+++ b/lib/puppet/parser/ast/resource_defaults.rb
@@ -8,13 +8,11 @@ class Puppet::Parser::AST
# As opposed to ResourceDef, this stores each default for the given
# object type.
- def evaluate(hash)
- scope = hash[:scope]
-
+ def evaluate(scope)
# Use a resource reference to canonize the type
ref = Puppet::ResourceReference.new(@type, "whatever")
type = ref.type
- params = @params.safeevaluate(:scope => scope)
+ params = @params.safeevaluate(scope)
parsewrap do
scope.setdefaults(type, params)
diff --git a/lib/puppet/parser/ast/resource_override.rb b/lib/puppet/parser/ast/resource_override.rb
index 46c930902..f9464acda 100644
--- a/lib/puppet/parser/ast/resource_override.rb
+++ b/lib/puppet/parser/ast/resource_override.rb
@@ -17,17 +17,15 @@ class Puppet::Parser::AST
# Does not actually return an object; instead sets an object
# in the current scope.
- def evaluate(hash)
- scope = hash[:scope]
-
+ def evaluate(scope)
# Get our object reference.
- object = @object.safeevaluate(:scope => scope)
+ object = @object.safeevaluate(scope)
hash = {}
# Evaluate all of the specified params.
params = @params.collect { |param|
- param.safeevaluate(:scope => scope)
+ param.safeevaluate(scope)
}
# Now we just create a normal resource, but we call a very different
@@ -44,7 +42,7 @@ class Puppet::Parser::AST
# Now we tell the scope that it's an override, and it behaves as
# necessary.
- scope.compile.store_override(obj)
+ scope.compiler.add_override(obj)
obj
end
diff --git a/lib/puppet/parser/ast/resource_reference.rb b/lib/puppet/parser/ast/resource_reference.rb
index b06ea17be..4bb41165a 100644
--- a/lib/puppet/parser/ast/resource_reference.rb
+++ b/lib/puppet/parser/ast/resource_reference.rb
@@ -22,10 +22,8 @@ class Puppet::Parser::AST
# Evaluate our object, but just return a simple array of the type
# and name.
- def evaluate(hash)
- scope = hash[:scope]
-
- title = @title.safeevaluate(:scope => scope)
+ def evaluate(scope)
+ title = @title.safeevaluate(scope)
if @type.to_s.downcase == "class"
objtype = "class"
title = qualified_class(scope, title)
diff --git a/lib/puppet/parser/ast/resourceparam.rb b/lib/puppet/parser/ast/resourceparam.rb
index 8b1e7b367..c552a7ee5 100644
--- a/lib/puppet/parser/ast/resourceparam.rb
+++ b/lib/puppet/parser/ast/resourceparam.rb
@@ -10,12 +10,10 @@ class Puppet::Parser::AST
end
# Return the parameter and the value.
- def evaluate(hash)
- scope = hash[:scope]
-
+ def evaluate(scope)
return Puppet::Parser::Resource::Param.new(
:name => @param,
- :value => @value.safeevaluate(:scope => scope),
+ :value => @value.safeevaluate(scope),
:source => scope.source, :line => self.line, :file => self.file,
:add => self.add
)
diff --git a/lib/puppet/parser/ast/selector.rb b/lib/puppet/parser/ast/selector.rb
index d363ab7e4..399d405a3 100644
--- a/lib/puppet/parser/ast/selector.rb
+++ b/lib/puppet/parser/ast/selector.rb
@@ -11,13 +11,12 @@ class Puppet::Parser::AST
end
# Find the value that corresponds with the test.
- def evaluate(hash)
- scope = hash[:scope]
+ def evaluate(scope)
retvalue = nil
found = nil
# Get our parameter.
- paramvalue = @param.safeevaluate(:scope => scope)
+ paramvalue = @param.safeevaluate(scope)
sensitive = Puppet[:casesensitive]
@@ -33,13 +32,13 @@ class Puppet::Parser::AST
# Then look for a match in the options.
@values.each { |obj|
- param = obj.param.safeevaluate(:scope => scope)
+ param = obj.param.safeevaluate(scope)
if ! sensitive && param.respond_to?(:downcase)
param = param.downcase
end
if param == paramvalue
# we found a matching option
- retvalue = obj.value.safeevaluate(:scope => scope)
+ retvalue = obj.value.safeevaluate(scope)
found = true
break
elsif obj.param.is_a?(Default)
@@ -51,7 +50,7 @@ class Puppet::Parser::AST
# Unless we found something, look for the default.
unless found
if default
- retvalue = default.value.safeevaluate(:scope => scope)
+ retvalue = default.value.safeevaluate(scope)
else
self.fail Puppet::ParseError,
"No matching value for selector param '%s'" % paramvalue
diff --git a/lib/puppet/parser/ast/tag.rb b/lib/puppet/parser/ast/tag.rb
index e2882d2f0..2909504a7 100644
--- a/lib/puppet/parser/ast/tag.rb
+++ b/lib/puppet/parser/ast/tag.rb
@@ -8,10 +8,8 @@ class Puppet::Parser::AST
@name = :class
attr_accessor :type
- def evaluate(hash)
- scope = hash[:scope]
-
- types = @type.safeevaluate(:scope => scope)
+ def evaluate(scope)
+ types = @type.safeevaluate(scope)
types = [types] unless types.is_a? Array
diff --git a/lib/puppet/parser/ast/vardef.rb b/lib/puppet/parser/ast/vardef.rb
index 1e7f874bc..ee79159d7 100644
--- a/lib/puppet/parser/ast/vardef.rb
+++ b/lib/puppet/parser/ast/vardef.rb
@@ -9,10 +9,9 @@ class Puppet::Parser::AST
# Look up our name and value, and store them appropriately. The
# lexer strips off the syntax stuff like '$'.
- def evaluate(hash)
- scope = hash[:scope]
- name = @name.safeevaluate(:scope => scope)
- value = @value.safeevaluate(:scope => scope)
+ def evaluate(scope)
+ name = @name.safeevaluate(scope)
+ value = @value.safeevaluate(scope)
parsewrap do
scope.setvar(name,value, @file, @line)
diff --git a/lib/puppet/parser/collector.rb b/lib/puppet/parser/collector.rb
index b8165a84f..e0c37cd35 100644
--- a/lib/puppet/parser/collector.rb
+++ b/lib/puppet/parser/collector.rb
@@ -118,20 +118,20 @@ class Puppet::Parser::Collector
# If there are no more resources to find, delete this from the list
# of collections.
if @resources.empty?
- @scope.compile.delete_collection(self)
+ @scope.compiler.delete_collection(self)
end
return result
end
- # Collect just virtual objects, from our local compile.
+ # Collect just virtual objects, from our local compiler.
def collect_virtual(exported = false)
if exported
method = :exported?
else
method = :virtual?
end
- scope.compile.resources.find_all do |resource|
+ scope.compiler.resources.find_all do |resource|
resource.type == @type and resource.send(method) and match?(resource)
end
end
@@ -150,7 +150,7 @@ class Puppet::Parser::Collector
resource.exported = false
- scope.compile.store_resource(scope, resource)
+ scope.compiler.add_resource(scope, resource)
return resource
end
diff --git a/lib/puppet/parser/compile.rb b/lib/puppet/parser/compiler.rb
index f76103a28..132ec15db 100644
--- a/lib/puppet/parser/compile.rb
+++ b/lib/puppet/parser/compiler.rb
@@ -7,7 +7,7 @@ require 'puppet/util/errors'
# Maintain a graph of scopes, along with a bunch of data
# about the individual catalog we're compiling.
-class Puppet::Parser::Compile
+class Puppet::Parser::Compiler
include Puppet::Util
include Puppet::Util::Errors
attr_reader :parser, :node, :facts, :collections, :catalog, :node_scope
@@ -17,6 +17,29 @@ class Puppet::Parser::Compile
@collections << coll
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
+
+ # Store a resource in our resource table.
+ def add_resource(scope, resource)
+ # Note that this will fail if the resource is not unique.
+ @catalog.add_resource(resource)
+
+ # And in the resource graph. At some point, this might supercede
+ # the global resource table, but the table is a lot faster
+ # so it makes sense to maintain for now.
+ @catalog.add_edge(scope.resource, resource)
+ end
+
# Do we use nodes found in the code, vs. the external node sources?
def ast_nodes?
parser.nodes.length > 0
@@ -26,10 +49,10 @@ class Puppet::Parser::Compile
# the scope in which it was evaluated, so that we can look it up later.
def class_set(name, scope)
if existing = @class_scopes[name]
- if existing.nodescope? or scope.nodescope?
+ if existing.nodescope? != scope.nodescope?
raise Puppet::ParseError, "Cannot have classes, nodes, or definitions with the same name"
else
- raise Puppet::DevError, "Somehow evaluated the same class twice"
+ raise Puppet::DevError, "Somehow evaluated %s %s twice" % [ existing.nodescope? ? "node" : "class", name]
end
end
@class_scopes[name] = scope
@@ -54,7 +77,7 @@ class Puppet::Parser::Compile
return @catalog.classes
end
- # Compile our catalog. This mostly revolves around finding and evaluating classes.
+ # 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.
@@ -68,10 +91,10 @@ class Puppet::Parser::Compile
evaluate_generators()
- fail_on_unevaluated()
-
finish()
+ fail_on_unevaluated()
+
if Puppet[:storeconfigs]
store()
end
@@ -84,11 +107,6 @@ class Puppet::Parser::Compile
@collections.delete(coll) if @collections.include?(coll)
end
- # LAK:FIXME There are no tests for this.
- def delete_resource(resource)
- @resource_table.delete(resource.ref) if @resource_table.include?(resource.ref)
- end
-
# Return the node's environment.
def environment
unless defined? @environment
@@ -120,16 +138,11 @@ class Puppet::Parser::Compile
if klass = scope.findclass(name)
found << name and next if class_scope(klass)
- # Create a resource to model this class, and then add it to the list
- # of resources.
- resource = Puppet::Parser::Resource.new(:type => "class", :title => klass.classname, :scope => scope, :source => scope.source)
-
- store_resource(scope, resource)
+ resource = klass.evaluate(scope)
# If they've disabled lazy evaluation (which the :include function does),
# then evaluate our resource immediately.
resource.evaluate unless lazy_evaluate
- @catalog.tag(klass.classname)
found << name
else
Puppet.info "Could not find class %s for %s" % [name, node.name]
@@ -140,10 +153,8 @@ class Puppet::Parser::Compile
end
# Return a resource by either its ref or its type and title.
- def findresource(string, name = nil)
- string = "%s[%s]" % [string.capitalize, name] if name
-
- @resource_table[string]
+ def findresource(*args)
+ @catalog.resource(*args)
end
# Set up our compile. We require a parser
@@ -158,7 +169,7 @@ class Puppet::Parser::Compile
begin
send(param.to_s + "=", value)
rescue NoMethodError
- raise ArgumentError, "Compile objects do not accept %s" % param
+ raise ArgumentError, "Compiler objects do not accept %s" % param
end
end
@@ -171,10 +182,10 @@ class Puppet::Parser::Compile
# its parent to the graph.
def newscope(parent, options = {})
parent ||= topscope
- options[:compile] = self
+ options[:compiler] = self
options[:parser] ||= self.parser
scope = Puppet::Parser::Scope.new(options)
- @scope_graph.add_edge!(parent, scope)
+ @scope_graph.add_edge(parent, scope)
scope
end
@@ -195,35 +206,7 @@ class Puppet::Parser::Compile
# Return a list of all resources.
def resources
- @resource_table.values
- end
-
- # Store a resource override.
- def store_override(override)
- override.override = true
-
- # If possible, merge the override in immediately.
- if resource = @resource_table[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
-
- # Store a resource in our resource table.
- def store_resource(scope, resource)
- # This might throw an exception
- verify_uniqueness(resource)
-
- # Store it in the global table.
- @resource_table[resource.ref] = resource
-
- # And in the resource graph. At some point, this might supercede
- # the global resource table, but the table is a lot faster
- # so it makes sense to maintain for now.
- @catalog.add_edge!(scope.resource, resource)
+ @catalog.vertices
end
# The top scope is usually the top-level scope, but if we're using AST nodes,
@@ -250,9 +233,7 @@ class Puppet::Parser::Compile
# Create a resource to model this node, and then add it to the list
# of resources.
- resource = Puppet::Parser::Resource.new(:type => "node", :title => astnode.classname, :scope => topscope, :source => topscope.source)
- store_resource(topscope, resource)
- @catalog.tag(astnode.classname)
+ resource = astnode.evaluate(topscope)
resource.evaluate
@@ -285,11 +266,15 @@ class Puppet::Parser::Compile
def evaluate_definitions
exceptwrap do
if ary = unevaluated_resources
+ evaluated = false
ary.each do |resource|
- resource.evaluate
+ if not resource.virtual?
+ resource.evaluate
+ evaluated = true
+ end
end
# If we evaluated, let the loop know.
- return true
+ return evaluated
else
return false
end
@@ -309,6 +294,9 @@ class Puppet::Parser::Compile
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
@@ -322,9 +310,7 @@ class Puppet::Parser::Compile
@main_resource = Puppet::Parser::Resource.new(:type => "class", :title => :main, :scope => @topscope, :source => @main)
@topscope.resource = @main_resource
- @catalog.add_vertex!(@main_resource)
-
- @resource_table["Class[main]"] = @main_resource
+ @catalog.add_resource(@main_resource)
@main_resource.evaluate
end
@@ -380,14 +366,29 @@ class Puppet::Parser::Compile
# Make sure all of our resources and such have done any last work
# necessary.
def finish
- @resource_table.each { |name, resource| resource.finish if resource.respond_to?(:finish) }
+ @catalog.resources.each do |name|
+ resource = @catalog.resource(name)
+
+ # 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)
+ end
end
# Initialize the top-level scope, class, and resource.
def init_main
# Create our initial scope and a resource that will evaluate main.
- @topscope = Puppet::Parser::Scope.new(:compile => self, :parser => self.parser)
- @scope_graph.add_vertex!(@topscope)
+ @topscope = Puppet::Parser::Scope.new(:compiler => self, :parser => self.parser)
+ @scope_graph.add_vertex(@topscope)
end
# Set up all of our internal variables.
@@ -396,9 +397,6 @@ class Puppet::Parser::Compile
# be used by top scopes and node scopes.
@class_scopes = {}
- # The table for all defined resources.
- @resource_table = {}
-
# The list of objects that will available for export.
@exported_resources = {}
@@ -412,9 +410,6 @@ class Puppet::Parser::Compile
# but they each refer back to the scope that created them.
@collections = []
- # A list of tags we've generated; most class names.
- @tags = []
-
# A graph for maintaining scope relationships.
@scope_graph = Puppet::SimpleGraph.new
@@ -443,7 +438,7 @@ class Puppet::Parser::Compile
# We used to have hooks here for forking and saving, but I don't
# think it's worth retaining at this point.
- store_to_active_record(@node, @resource_table.values)
+ store_to_active_record(@node, @catalog.vertices)
end
# Do the actual storage.
@@ -466,9 +461,7 @@ class Puppet::Parser::Compile
# 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 = @resource_table.find_all do |name, object|
- ! object.builtin? and ! object.evaluated?
- end.collect { |name, object| object }
+ ary = @catalog.vertices.reject { |resource| resource.builtin? or resource.evaluated? }
if ary.empty?
return nil
@@ -476,33 +469,4 @@ class Puppet::Parser::Compile
return ary
end
end
-
- # Verify that the given resource isn't defined elsewhere.
- def verify_uniqueness(resource)
- # Short-curcuit the common case,
- unless existing_resource = @resource_table[resource.ref]
- return true
- end
-
- if typeclass = Puppet::Type.type(resource.type) and ! typeclass.isomorphic?
- Puppet.info "Allowing duplicate %s" % typeclass.name
- return true
- end
-
- # Either it's a defined type, which are never
- # isomorphic, or it's a non-isomorphic type, so
- # we should throw an exception.
- msg = "Duplicate definition: %s is already defined" % resource.ref
-
- if existing_resource.file and existing_resource.line
- msg << " in file %s at line %s" %
- [existing_resource.file, existing_resource.line]
- end
-
- if resource.line or resource.file
- msg << "; cannot redefine"
- end
-
- raise Puppet::ParseError.new(msg)
- end
end
diff --git a/lib/puppet/parser/functions.rb b/lib/puppet/parser/functions.rb
index 34b38b809..e0b60e161 100644
--- a/lib/puppet/parser/functions.rb
+++ b/lib/puppet/parser/functions.rb
@@ -111,7 +111,7 @@ module Functions
vals = [vals] unless vals.is_a?(Array)
# The 'false' disables lazy evaluation.
- klasses = compile.evaluate_classes(vals, self, false)
+ klasses = compiler.evaluate_classes(vals, self, false)
missing = vals.find_all do |klass|
! klasses.include?(klass)
@@ -146,7 +146,7 @@ module Functions
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 = compile.catalog.tags
+ configtags = compiler.catalog.tags
resourcetags = resource.tags
retval = true
@@ -235,7 +235,7 @@ module Functions
vals = [vals] unless vals.is_a?(Array)
coll.resources = vals
- compile.add_collection(coll)
+ compiler.add_collection(coll)
end
newfunction(:search, :doc => "Add another namespace for this class to search.
diff --git a/lib/puppet/parser/interpreter.rb b/lib/puppet/parser/interpreter.rb
index e29e19944..1d93193dd 100644
--- a/lib/puppet/parser/interpreter.rb
+++ b/lib/puppet/parser/interpreter.rb
@@ -3,7 +3,7 @@ require 'timeout'
require 'puppet/rails'
require 'puppet/util/methodhelper'
require 'puppet/parser/parser'
-require 'puppet/parser/compile'
+require 'puppet/parser/compiler'
require 'puppet/parser/scope'
# The interpreter is a very simple entry-point class that
@@ -25,7 +25,7 @@ class Puppet::Parser::Interpreter
# evaluate our whole tree
def compile(node)
raise Puppet::ParseError, "Could not parse configuration; cannot compile" unless env_parser = parser(node.environment)
- return Puppet::Parser::Compile.new(node, env_parser).compile
+ return Puppet::Parser::Compiler.new(node, env_parser).compile
end
# create our interpreter
diff --git a/lib/puppet/parser/lexer.rb b/lib/puppet/parser/lexer.rb
index 086d82c09..6661650ba 100644
--- a/lib/puppet/parser/lexer.rb
+++ b/lib/puppet/parser/lexer.rb
@@ -1,4 +1,3 @@
-
# the scanner/lexer
require 'strscan'
@@ -7,326 +6,432 @@ require 'puppet'
module Puppet
class LexError < RuntimeError; end
- module Parser
- #---------------------------------------------------------------
- class Lexer
- attr_reader :line, :last, :file
-
- attr_accessor :indefine
-
- #%r{\w+} => :WORD,
- @@tokens = {
- %r{#.*} => :COMMENT,
- %r{\[} => :LBRACK,
- %r{\]} => :RBRACK,
- %r{\{} => :LBRACE,
- %r{\}} => :RBRACE,
- %r{\(} => :LPAREN,
- %r{\)} => :RPAREN,
- %r{\"} => :DQUOTE,
- %r{\n} => :RETURN,
- %r{\'} => :SQUOTE,
- %r{=} => :EQUALS,
- %r{==} => :ISEQUAL,
- %r{>=} => :GREATEREQUAL,
- %r{>} => :GREATERTHAN,
- %r{<} => :LESSTHAN,
- %r{<=} => :LESSEQUAL,
- %r{!=} => :NOTEQUAL,
- %r{!} => :NOT,
- %r{,} => :COMMA,
- %r{\.} => :DOT,
- %r{:} => :COLON,
- %r{@} => :AT,
- %r{<<\|} => :LLCOLLECT,
- %r{\|>>} => :RRCOLLECT,
- %r{<\|} => :LCOLLECT,
- %r{\|>} => :RCOLLECT,
- %r{;} => :SEMIC,
- %r{\?} => :QMARK,
- %r{\\} => :BACKSLASH,
- %r{=>} => :FARROW,
- %r{\+>} => :PARROW,
- %r{[a-z][-\w]*} => :NAME,
- %r{([a-z][-\w]*::)+[a-z][-\w]*} => :CLASSNAME,
- %r{((::){0,1}[A-Z][-\w]*)+} => :CLASSREF,
- %r{[0-9]+} => :NUMBER,
- %r{\$(\w*::)*\w+} => :VARIABLE
- }
-
- @@pairs = {
- "{" => "}",
- "(" => ")",
- "[" => "]",
- "<|" => "|>",
- "<<|" => "|>>"
- }
-
- @@reverse_pairs = @@pairs.inject({}) { |hash, pair| hash[pair[1]] = pair[0]; hash }
-
- @@keywords = {
- "case" => :CASE,
- "class" => :CLASS,
- "default" => :DEFAULT,
- "define" => :DEFINE,
- "false" => :BOOLEAN,
- "import" => :IMPORT,
- "if" => :IF,
- "elsif" => :ELSIF,
- "else" => :ELSE,
- "inherits" => :INHERITS,
- "node" => :NODE,
- "true" => :BOOLEAN,
- "and" => :AND,
- "or" => :OR,
- "undef" => :UNDEF
- }
-
- def clear
- initvars
- end
+end
- def expected
- if @expected.empty?
- nil
- else
- token = @expected[-1]
- @@tokens.each do |value, name|
- if token == name
- return value
- end
- end
- return token
- end
- end
+module Puppet::Parser; end
- # scan the whole file
- # basically just used for testing
- def fullscan
- array = []
-
- self.scan { |token,str|
- # Ignore any definition nesting problems
- @indefine = false
- #Puppet.debug("got token '%s' => '%s'" % [token,str])
- if token.nil?
- return array
- else
- array.push([token,str])
- end
- }
- return array
- end
+class Puppet::Parser::Lexer
+ attr_reader :last, :file
+
+ attr_accessor :line, :indefine
- # this is probably pretty damned inefficient...
- # it'd be nice not to have to load the whole file first...
- def file=(file)
- @file = file
- @line = 1
- File.open(file) { |of|
- str = ""
- of.each { |line| str += line }
- @scanner = StringScanner.new(str)
- }
+ # Our base token class.
+ class Token
+ attr_accessor :regex, :name, :string, :skip, :incr_line, :skip_text
+
+ 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
- def indefine?
- if defined? @indefine
- @indefine
- else
- false
- end
+ def skip?
+ self.skip
+ end
+
+ def to_s
+ "Lexer token %s" % @name.to_s
+ 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 %s already exists" % name) 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
- def initialize
- initvars()
+ options.each do |name, option|
+ token.send(name.to_s + "=", option)
end
- def initvars
- @line = 1
- @last = ""
- @lasttoken = nil
- @scanner = nil
- @file = nil
- # AAARRGGGG! okay, regexes in ruby are bloody annoying
- # no one else has "\n" =~ /\s/
- @skip = %r{[ \t]+}
+ token.meta_def(:convert, &block) if block_given?
- @namestack = []
- @indefine = false
+ token
+ end
- @expected = []
- end
+ def initialize
+ @tokens = {}
+ @regex_tokens = []
+ @string_tokens = []
+ @tokens_by_string = {}
+ end
- # Go up one in the namespace.
- def namepop
- @namestack.pop
+ # 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
- # Collect the current namespace.
- def namespace
- @namestack.join("::")
+ # 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,
+ '==' => :ISEQUAL,
+ '>=' => :GREATEREQUAL,
+ '>' => :GREATERTHAN,
+ '<' => :LESSTHAN,
+ '<=' => :LESSEQUAL,
+ '!=' => :NOTEQUAL,
+ '!' => :NOT,
+ ',' => :COMMA,
+ '.' => :DOT,
+ ':' => :COLON,
+ '@' => :AT,
+ '<<|' => :LLCOLLECT,
+ '|>>' => :RRCOLLECT,
+ '<|' => :LCOLLECT,
+ '|>' => :RCOLLECT,
+ ';' => :SEMIC,
+ '?' => :QMARK,
+ '\\' => :BACKSLASH,
+ '=>' => :FARROW,
+ '+>' => :PARROW,
+ %r{([a-z][-\w]*::)+[a-z][-\w]*} => :CLASSNAME,
+ %r{((::){0,1}[A-Z][-\w]*)+} => :CLASSREF
+ )
+
+ TOKENS.add_tokens "Whatever" => :DQTEXT, "Nomatter" => :SQTEXT, "alsonomatter" => :BOOLEAN
+
+ TOKENS.add_token :NAME, %r{[a-z][-\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
+
+ TOKENS.add_token :NUMBER, %r{[0-9]+} do |lexer, value|
+ [TOKENS[:NAME], value]
+ end
+
+ TOKENS.add_token :COMMENT, %r{#.*}, :skip => true
+
+ TOKENS.add_token :RETURN, "\n", :skip => true, :incr_line => true, :skip_text => true
+
+ TOKENS.add_token :SQUOTE, "'" do |lexer, value|
+ value = lexer.slurpstring(value)
+ [TOKENS[:SQTEXT], value]
+ 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
+ TOKENS.add_token :DQUOTE, '"' do |lexer, value|
+ value = lexer.slurpstring(value)
+ [TOKENS[:DQTEXT], value]
+ end
+
+ TOKENS.add_token :VARIABLE, %r{\$(\w*::)*\w+} do |lexer, value|
+ value = value.sub(/^\$/, '')
+ [self, value]
+ end
+
+ 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
+ )
+
+ def clear
+ initvars
+ end
+
+ def expected
+ return nil if @expected.empty?
+ name = @expected[-1]
+ raise "Could not find expected token %s" % name unless token = TOKENS.lookup(name)
+
+ return token
+ 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])
+ }
+ return array
+ end
+
+ # this is probably pretty damned inefficient...
+ # it'd be nice not to have to load the whole file first...
+ def file=(file)
+ @file = file
+ @line = 1
+ File.open(file) { |of|
+ str = ""
+ of.each { |line| str += line }
+ @scanner = StringScanner.new(str)
+ }
+ end
+
+ def find_string_token
+ matched_token = value = nil
+
+ # 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 chars we have. Also,
+ # the lookups are optimized hash lookups, instead of regex scans.
+ [3, 2, 1].each do |i|
+ str = @scanner.peek(i)
+ if matched_token = TOKENS.lookup(str)
+ value = @scanner.scan(matched_token.regex)
+ break
end
+ end
+
+ return matched_token, value
+ end
- def rest
- @scanner.rest
+ # Find the next token that matches a regex. We look for these first.
+ def find_regex_token
+ @regex += 1
+ matched_token = nil
+ value = ""
+ 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|
+ next unless match_length = @scanner.match?(token.regex)
+
+ # We've found a longer match
+ if match_length > length
+ value = @scanner.scan(token.regex)
+ length = value.length
+ matched_token = token
end
+ end
- # this is the heart of the lexer
- def scan
- #Puppet.debug("entering scan")
- if @scanner.nil?
- raise TypeError.new("Invalid or empty string")
- end
+ return matched_token, value
+ end
- @scanner.skip(@skip)
- until @scanner.eos? do
- yielded = false
- sendbreak = false # gah, this is a nasty hack
- stoken = nil
- sregex = nil
- value = ""
-
- # first find out which type of token we've got
- @@tokens.each { |regex,token|
- # we're just checking, which doesn't advance the scan
- # pointer
- tmp = @scanner.check(regex)
- if tmp.nil?
- #puppet.debug("did not match %s to '%s'" %
- # [regex,@scanner.rest])
- next
- end
-
- # find the longest match
- if tmp.length > value.length
- value = tmp
- stoken = token
- sregex = regex
- else
- # we've already got a longer match
- next
- end
- }
-
- # error out if we didn't match anything at all
- if stoken.nil?
- nword = nil
- if @scanner.rest =~ /^(\S+)/
- nword = $1
- elsif@scanner.rest =~ /^(\s+)/
- nword = $1
- else
- nword = @scanner.rest
- end
- raise "Could not match '%s'" % nword
- end
+ # Find the next token, returning the string and the token.
+ def find_token
+ @find += 1
+ matched_token, value = find_regex_token
- value = @scanner.scan(sregex)
+ unless matched_token
+ matched_token, value = find_string_token
+ end
- if value == ""
- raise "Didn't match regex on token %s" % stoken
- end
+ return matched_token, value
+ end
- # token-specific operations
- # if this gets much more complicated, it should
- # be moved up to where the tokens themselves are defined
- # which will get me about 75% of the way to a lexer generator
- ptoken = stoken
- case stoken
- when :NAME then
- wtoken = stoken
- # we're looking for keywords here
- if @@keywords.include?(value)
- wtoken = @@keywords[value]
- #Puppet.debug("token '%s'" % wtoken)
- if wtoken == :BOOLEAN
- value = eval(value)
- end
- end
- ptoken = wtoken
- when :NUMBER then
- ptoken = :NAME
- when :COMMENT then
- # just throw comments away
- next
- when :RETURN then
- @line += 1
- @scanner.skip(@skip)
- next
- when :SQUOTE then
- #Puppet.debug("searching '%s' after '%s'" % [self.rest,value])
- value = self.slurpstring(value)
- ptoken = :SQTEXT
- #Puppet.debug("got string '%s' => '%s'" % [:DQTEXT,value])
- when :DQUOTE then
- value = self.slurpstring(value)
- ptoken = :DQTEXT
- when :VARIABLE then
- value = value.sub(/^\$/, '')
- end
+ def indefine?
+ if defined? @indefine
+ @indefine
+ else
+ false
+ end
+ end
- if match = @@pairs[value] and ptoken != :DQUOTE and ptoken != :SQUOTE
- @expected << match
- elsif exp = @expected[-1] and exp == value and ptoken != :DQUOTE and ptoken != :SQUOTE
- @expected.pop
- end
+ def initialize
+ @find = 0
+ @regex = 0
+ initvars()
+ end
- yield [ptoken, value]
+ 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]+}
+
+ @namestack = []
+ @indefine = false
+ @expected = []
+ end
- if @lasttoken == :CLASS
- namestack(value)
- end
+ # Make any necessary changes to the token and/or value.
+ def munge_token(token, value)
+ @line += 1 if token.incr_line
- if @lasttoken == :DEFINE
- if indefine?
- msg = "Cannot nest definition %s inside %s" % [value, @indefine]
- self.indefine = false
- raise Puppet::ParseError, msg
- end
+ skip() if token.skip_text
- @indefine = value
- end
+ return if token.skip
- @last = value
- @lasttoken = ptoken
+ token, value = token.convert(self, value) if token.respond_to?(:convert)
- @scanner.skip(@skip)
- end
- @scanner = nil
- yield [false,false]
- end
+ return unless token
+
+ return token, value
+ end
+
+ # Go up one in the namespace.
+ def namepop
+ @namestack.pop
+ end
- # we've encountered an opening quote...
- # slurp in the rest of the string and return it
- def slurpstring(quote)
- # 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(/([^\\]|^)#{quote}/)
- if str.nil?
- raise Puppet::LexError.new("Unclosed quote after '%s' in '%s'" %
- [self.last,self.rest])
+ # Collect the current namespace.
+ def namespace
+ @namestack.join("::")
+ 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")
+ raise Puppet::LexError.new("Invalid or empty string") unless @scanner
+
+ # Skip any initial whitespace.
+ skip()
+
+ until @scanner.eos? do
+ yielded = false
+ matched_token, value = find_token
+
+ # error out if we didn't match anything at all
+ if matched_token.nil?
+ nword = nil
+ # Try to pull a 'word' out of the remaining string.
+ if @scanner.rest =~ /^(\S+)/
+ nword = $1
+ elsif @scanner.rest =~ /^(\s+)/
+ nword = $1
else
- str.sub!(/#{quote}\Z/,"")
- str.gsub!(/\\#{quote}/,quote)
+ nword = @scanner.rest
end
+ raise "Could not match '%s'" % nword
+ end
- return str
+ final_token, value = munge_token(matched_token, value)
+
+ next unless final_token
+
+ 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
- # just parse a string, not a whole file
- def string=(string)
- @scanner = StringScanner.new(string)
+ yield [final_token.name, value]
+
+ if @previous_token
+ namestack(value) if @previous_token.name == :CLASS
+
+ if @previous_token.name == :DEFINE
+ if indefine?
+ msg = "Cannot nest definition %s inside %s" % [value, @indefine]
+ self.indefine = false
+ raise Puppet::ParseError, msg
+ end
+
+ @indefine = value
+ end
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
-end
+ # we've encountered an opening quote...
+ # slurp in the rest of the string and return it
+ def slurpstring(quote)
+ # 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(/([^\\]|^)#{quote}/)
+ if str.nil?
+ raise Puppet::LexError.new("Unclosed quote after '%s' in '%s'" %
+ [self.last,self.rest])
+ else
+ str.sub!(/#{quote}\Z/,"")
+ str.gsub!(/\\#{quote}/,quote)
+ end
+
+ return str
+ end
+
+ # just parse a string, not a whole file
+ def string=(string)
+ @scanner = StringScanner.new(string)
+ end
+end
diff --git a/lib/puppet/parser/parser_support.rb b/lib/puppet/parser/parser_support.rb
index b7c68e630..ccfc4d48a 100644
--- a/lib/puppet/parser/parser_support.rb
+++ b/lib/puppet/parser/parser_support.rb
@@ -47,11 +47,8 @@ class Puppet::Parser::Parser
# Create an AST object, and automatically add the file and line information if
# available.
- def ast(klass, hash = nil)
- hash ||= {}
- unless hash.include?(:line)
- hash[:line] = @lexer.line
- end
+ def ast(klass, hash = {})
+ hash[:line] = @lexer.line unless hash.include?(:line)
unless hash.include?(:file)
if file = @lexer.file
diff --git a/lib/puppet/parser/resource.rb b/lib/puppet/parser/resource.rb
index 3f346166e..fb0799011 100644
--- a/lib/puppet/parser/resource.rb
+++ b/lib/puppet/parser/resource.rb
@@ -3,18 +3,18 @@
class Puppet::Parser::Resource
require 'puppet/parser/resource/param'
require 'puppet/parser/resource/reference'
+ require 'puppet/util/tagging'
include Puppet::Util
include Puppet::Util::MethodHelper
include Puppet::Util::Errors
include Puppet::Util::Logging
+ include Puppet::Util::Tagging
attr_accessor :source, :line, :file, :scope, :rails_id
attr_accessor :virtual, :override, :translated
attr_reader :exported, :evaluated, :params
- attr_writer :tags
-
# Determine whether the provided parameter name is a relationship parameter.
def self.relationship_parameter?(name)
unless defined?(@relationship_names)
@@ -58,8 +58,7 @@ class Puppet::Parser::Resource
def evaluate
if klass = @ref.definedtype
finish()
- scope.compile.delete_resource(self)
- return klass.evaluate(:scope => scope, :resource => self)
+ return klass.evaluate_code(self)
elsif builtin?
devfail "Cannot evaluate a builtin type"
else
@@ -83,9 +82,9 @@ class Puppet::Parser::Resource
# Do any finishing work on this object, called before evaluation or
# before storage/translation.
def finish
- add_overrides()
add_defaults()
add_metaparams()
+ add_scope_tags()
validate()
end
@@ -130,13 +129,8 @@ class Puppet::Parser::Resource
raise ArgumentError, "Resources do not accept %s" % options.keys.collect { |k| k.to_s }.join(", ")
end
- @tags = []
tag(@ref.type)
- tag(@ref.title) if @ref.title.to_s =~ /^[-\w]+$/
-
- if scope.resource
- @tags += scope.resource.tags
- end
+ tag(@ref.title) if valid_tag?(@ref.title.to_s)
end
# Merge an override resource in. This will throw exceptions if
@@ -223,23 +217,6 @@ class Puppet::Parser::Resource
@ref.to_s
end
- # Add a tag to our current list. These tags will be added to all
- # of the objects contained in this scope.
- def tag(*ary)
- ary.collect { |tag| tag.to_s.downcase }.collect { |tag| tag.split("::") }.flatten.each do |tag|
- unless tag =~ /^\w[-\w]*$/
- fail Puppet::ParseError, "Invalid tag %s" % tag.inspect
- end
- unless @tags.include?(tag)
- @tags << tag
- end
- end
- end
-
- def tags
- @tags.dup
- end
-
def to_hash
@params.inject({}) do |hash, ary|
param = ary[1]
@@ -260,6 +237,8 @@ class Puppet::Parser::Resource
# Handle file specially
db_resource.file = self.file
+ db_resource.save
+
@params.each { |name, param|
param.to_rails(db_resource)
}
@@ -361,16 +340,9 @@ class Puppet::Parser::Resource
end
end
- # Add any overrides for this object.
- def add_overrides
- if overrides = scope.compile.resource_overrides(self)
- overrides.each do |over|
- self.merge(over)
- end
-
- # Remove the overrides, so that the configuration knows there
- # are none left.
- overrides.clear
+ def add_scope_tags
+ if scope_resource = scope.resource
+ tag(*scope_resource.tags)
end
end
diff --git a/lib/puppet/parser/resource/param.rb b/lib/puppet/parser/resource/param.rb
index 9352311d6..9dd3f26d2 100644
--- a/lib/puppet/parser/resource/param.rb
+++ b/lib/puppet/parser/resource/param.rb
@@ -12,7 +12,7 @@ class Puppet::Parser::Resource::Param
end
def inspect
- "#<#{self.class} @name => #{self.name}, @value => #{self.value}, @source => #{self.source.name}>"
+ "#<#{self.class} @name => #{name}, @value => #{value}, @source => #{source.name}>"
end
def line_to_i
diff --git a/lib/puppet/parser/resource/reference.rb b/lib/puppet/parser/resource/reference.rb
index 6e70d23b7..c59748049 100644
--- a/lib/puppet/parser/resource/reference.rb
+++ b/lib/puppet/parser/resource/reference.rb
@@ -37,10 +37,14 @@ class Puppet::Parser::Resource::Reference < Puppet::ResourceReference
if self.title == :main
tmp = @scope.findclass("")
else
- tmp = @scope.findclass(self.title)
+ unless tmp = @scope.findclass(self.title)
+ fail Puppet::ParseError, "Could not find class '%s'" % self.title
+ end
end
when "Node": # look for node definitions
- tmp = @scope.parser.nodes[self.title]
+ unless tmp = @scope.parser.nodes[self.title]
+ fail Puppet::ParseError, "Could not find node '%s'" % self.title
+ end
else # normal definitions
# We have to swap these variables around so the errors are right.
tmp = @scope.finddefine(self.type)
@@ -49,7 +53,7 @@ class Puppet::Parser::Resource::Reference < Puppet::ResourceReference
if tmp
@definedtype = tmp
else
- fail Puppet::ParseError, "Could not find resource '%s'" % self
+ fail Puppet::ParseError, "Could not find resource type '%s'" % self.type
end
end
diff --git a/lib/puppet/parser/scope.rb b/lib/puppet/parser/scope.rb
index 028414cc0..a6e43e7b3 100644
--- a/lib/puppet/parser/scope.rb
+++ b/lib/puppet/parser/scope.rb
@@ -17,15 +17,20 @@ class Puppet::Parser::Scope
include Puppet::Util::Errors
attr_accessor :parent, :level, :parser, :source, :resource
attr_accessor :base, :keyword, :nodescope
- attr_accessor :top, :translated, :compile
+ attr_accessor :top, :translated, :compiler
+
+ # A demeterific shortcut to the catalog.
+ def catalog
+ compiler.catalog
+ end
# Proxy accessors
def host
- @compile.node.name
+ @compiler.node.name
end
def interpreter
- @compile.interpreter
+ @compiler.interpreter
end
# Is the value true? This allows us to control the definition of truth
@@ -72,7 +77,7 @@ class Puppet::Parser::Scope
end
def findresource(string, name = nil)
- compile.findresource(string, name)
+ compiler.findresource(string, name)
end
# Initialize our new scope. Defaults to having no parent.
@@ -147,7 +152,7 @@ class Puppet::Parser::Scope
unless klass
raise Puppet::ParseError, "Could not find class %s" % klassname
end
- unless kscope = compile.class_scope(klass)
+ unless kscope = compiler.class_scope(klass)
raise Puppet::ParseError, "Class %s has not been evaluated so its variables cannot be referenced" % klass.classname
end
return kscope.lookupvar(shortname, usestring)
@@ -184,7 +189,7 @@ class Puppet::Parser::Scope
# Create a new scope and set these options.
def newscope(options = {})
- compile.newscope(self, options)
+ compiler.newscope(self, options)
end
# Is this class for a node? This is used to make sure that
@@ -199,7 +204,7 @@ class Puppet::Parser::Scope
# than doing lots of queries.
def parent
unless defined?(@parent)
- @parent = compile.parent(self)
+ @parent = compiler.parent(self)
end
@parent
end
diff --git a/lib/puppet/parser/templatewrapper.rb b/lib/puppet/parser/templatewrapper.rb
index 13823d483..7a8f74156 100644
--- a/lib/puppet/parser/templatewrapper.rb
+++ b/lib/puppet/parser/templatewrapper.rb
@@ -7,7 +7,7 @@ class Puppet::Parser::TemplateWrapper
def initialize(scope, file)
@scope = scope
- @file = Puppet::Module::find_template(file, @scope.compile.environment)
+ @file = Puppet::Module::find_template(file, @scope.compiler.environment)
unless FileTest.exists?(@file)
raise Puppet::ParseError,
diff --git a/lib/puppet/pgraph.rb b/lib/puppet/pgraph.rb
index 54b815b45..71547802e 100644
--- a/lib/puppet/pgraph.rb
+++ b/lib/puppet/pgraph.rb
@@ -7,17 +7,14 @@ require 'puppet/simple_graph'
# This class subclasses a graph class in order to handle relationships
# among resources.
class Puppet::PGraph < Puppet::SimpleGraph
- # This is the type used for splicing.
- attr_accessor :container_type
-
include Puppet::Util
- def add_edge!(*args)
+ def add_edge(*args)
@reversal = nil
super
end
- def add_vertex!(*args)
+ def add_vertex(*args)
@reversal = nil
super
end
@@ -57,11 +54,6 @@ class Puppet::PGraph < Puppet::SimpleGraph
@reversal.tree_from_vertex(resource, :out).keys
end
- # Override this method to use our class instead.
- def edge_class()
- Puppet::Relationship
- end
-
# Determine all of the leaf nodes below a given vertex.
def leaves(vertex, direction = :out)
tree = tree_from_vertex(vertex, direction)
@@ -133,7 +125,7 @@ class Puppet::PGraph < Puppet::SimpleGraph
copy_label(s, t, edge.label)
next
end
- add_edge!(s, t, edge.label)
+ add_edge(s, t, edge.label)
end
# Now get rid of the edge, so remove_vertex! works correctly.
diff --git a/lib/puppet/provider/package/fink.rb b/lib/puppet/provider/package/fink.rb
index e0933df08..030e1a347 100755
--- a/lib/puppet/provider/package/fink.rb
+++ b/lib/puppet/provider/package/fink.rb
@@ -9,8 +9,6 @@ Puppet::Type.type(:package).provide :fink, :parent => :dpkg, :source => :dpkg do
commands :aptcache => "/sw/bin/apt-cache"
commands :dpkgquery => "/sw/bin/dpkg-query"
- defaultfor :operatingsystem => :darwin
-
has_feature :versionable
# A derivative of DPKG; this is how most people actually manage
diff --git a/lib/puppet/provider/package/openbsd.rb b/lib/puppet/provider/package/openbsd.rb
index ce69dd432..f76c37176 100755
--- a/lib/puppet/provider/package/openbsd.rb
+++ b/lib/puppet/provider/package/openbsd.rb
@@ -66,7 +66,7 @@ Puppet::Type.type(:package).provide :openbsd, :parent => Puppet::Provider::Packa
info = pkginfo @resource[:name]
# Search for the version info
- if info =~ /Information for #{@resource[:name]}-(\S+)/
+ if info =~ /Information for (inst:)?#{@resource[:name]}-(\S+)/
hash[:ensure] = $1
else
return nil
diff --git a/lib/puppet/provider/user/useradd.rb b/lib/puppet/provider/user/useradd.rb
index c2476203a..9ecaad87d 100644
--- a/lib/puppet/provider/user/useradd.rb
+++ b/lib/puppet/provider/user/useradd.rb
@@ -19,7 +19,7 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
has_features :manages_homedir, :allows_duplicates
- if Puppet.features.libshadow? and (Facter.value(:kernel) == "Linux")
+ if Puppet.features.libshadow?
has_feature :manages_passwords
end
diff --git a/lib/puppet/resource_reference.rb b/lib/puppet/resource_reference.rb
index 3e92662b2..771a91be7 100644
--- a/lib/puppet/resource_reference.rb
+++ b/lib/puppet/resource_reference.rb
@@ -36,7 +36,7 @@ class Puppet::ResourceReference
# If the title has square brackets, treat it like a reference and
# set things appropriately; else, just set it.
def title=(value)
- if value =~ /^(.+)\[(.+)\]$/
+ if value =~ /^([^\[\]]+)\[(.+)\]$/
self.type = $1
@title = $2
else
diff --git a/lib/puppet/simple_graph.rb b/lib/puppet/simple_graph.rb
index 11542ad53..503e4814c 100644
--- a/lib/puppet/simple_graph.rb
+++ b/lib/puppet/simple_graph.rb
@@ -100,10 +100,10 @@ class Puppet::SimpleGraph
# Return a reversed version of this graph.
def reversal
result = self.class.new
- vertices.each { |vertex| result.add_vertex!(vertex) }
+ vertices.each { |vertex| result.add_vertex(vertex) }
edges.each do |edge|
newedge = edge.class.new(edge.target, edge.source, edge.label)
- result.add_edge!(newedge)
+ result.add_edge(newedge)
end
result
end
@@ -150,7 +150,7 @@ class Puppet::SimpleGraph
end
# Add a new vertex to the graph.
- def add_vertex!(vertex)
+ def add_vertex(vertex)
return false if vertex?(vertex)
setup_vertex(vertex)
true # don't return the VertexWrapper instance.
@@ -176,7 +176,7 @@ class Puppet::SimpleGraph
# Add a new edge. The graph user has to create the edge instance,
# since they have to specify what kind of edge it is.
- def add_edge!(source, target = nil, label = nil)
+ def add_edge(source, target = nil, label = nil)
if target
edge = Puppet::Relationship.new(source, target, label)
else
diff --git a/lib/puppet/sslcertificates/ca.rb b/lib/puppet/sslcertificates/ca.rb
index a3edd2cb4..888bcf5b2 100644
--- a/lib/puppet/sslcertificates/ca.rb
+++ b/lib/puppet/sslcertificates/ca.rb
@@ -194,8 +194,8 @@ class Puppet::SSLCertificates::CA
# Revoke the certificate with serial number SERIAL issued by this
# CA. The REASON must be one of the OpenSSL::OCSP::REVOKED_* reasons
def revoke(serial, reason = OpenSSL::OCSP::REVOKED_STATUS_KEYCOMPROMISE)
- if @config[:cacrl] == 'none'
- raise Puppet::Error, "Revocation requires a CRL, but ca_crl is set to 'none'"
+ if @config[:cacrl] == 'false'
+ raise Puppet::Error, "Revocation requires a CRL, but ca_crl is set to 'false'"
end
time = Time.now
revoked = OpenSSL::X509::Revoked.new
@@ -372,7 +372,7 @@ class Puppet::SSLCertificates::CA
@crl = OpenSSL::X509::CRL.new(
File.read(@config[:cacrl])
)
- elsif @config[:cacrl] == 'none'
+ elsif @config[:cacrl] == 'false'
@crl = nil
else
# Create new CRL
diff --git a/lib/puppet/transaction.rb b/lib/puppet/transaction.rb
index 6a4981298..976bf7c68 100644
--- a/lib/puppet/transaction.rb
+++ b/lib/puppet/transaction.rb
@@ -173,7 +173,7 @@ class Transaction
relationship_graph.add_resource(gen_child) unless relationship_graph.resource(gen_child.ref)
unless relationship_graph.edge?(edge[1], edge[0])
- relationship_graph.add_edge!(*edge)
+ relationship_graph.add_edge(*edge)
else
resource.debug "Skipping automatic relationship to %s" % gen_child
end
@@ -424,7 +424,7 @@ class Transaction
# Should we ignore tags?
def ignore_tags?
- ! @catalog.host_config?
+ ! (@catalog.host_config? or Puppet[:name] == "puppet")
end
# this should only be called by a Puppet::Type::Component resource now
diff --git a/lib/puppet/transportable.rb b/lib/puppet/transportable.rb
index c1d68a881..f686fbb78 100644
--- a/lib/puppet/transportable.rb
+++ b/lib/puppet/transportable.rb
@@ -193,7 +193,7 @@ module Puppet
next unless resource = child.to_type
config.add_resource resource
end
- config.add_edge!(container, resource)
+ config.add_edge(container, resource)
if child.is_a?(self.class)
delver.call(child)
end
diff --git a/lib/puppet/type/cron.rb b/lib/puppet/type/cron.rb
index 7882745dc..c46a7c83b 100755
--- a/lib/puppet/type/cron.rb
+++ b/lib/puppet/type/cron.rb
@@ -8,13 +8,6 @@ Puppet::Type.newtype(:cron) do
fields would result in the command being executed every
minute. While the name of the cron job is not part of the actual
job, it is used by Puppet to store and retrieve it.
-
- You may specify periodic fields as integers, using the standard cron
- range syntax (two numbers separated by a hyphen to indicate a range
- of values), or using the cron step syntax (for example, '*/2' to
- indicate command execution every other time unit). This type does
- not yet support the combiantion of these two syntaxes, or lists of
- ranges.
If you specify a cron job that matches an existing job in every way
except name, then the jobs will be considered equivalent and the
@@ -30,6 +23,24 @@ Puppet::Type.newtype(:cron) do
hour => 2,
minute => 0
}
+
+ Note that all cron values can be specified as an array of values::
+
+ cron { logrotate:
+ command => \"/usr/sbin/logrotate\",
+ user => root,
+ hour => [2, 4]
+ }
+
+ Or using ranges, or the step syntax ``*/2`` (although there's no guarantee that
+ your ``cron`` daemon supports it)::
+
+ cron { logrotate:
+ command => \"/usr/sbin/logrotate\",
+ user => root,
+ hour => ['2-4'],
+ minute => '*/10'
+ }
"
ensurable
diff --git a/lib/puppet/type/exec.rb b/lib/puppet/type/exec.rb
index 5bb3158c4..7d3b1abe1 100755
--- a/lib/puppet/type/exec.rb
+++ b/lib/puppet/type/exec.rb
@@ -229,6 +229,15 @@ module Puppet
end
newparam(:env) do
+ desc "This parameter is deprecated. Use 'environment' instead."
+
+ munge do |value|
+ warning "'env' is deprecated on exec; use 'environment' instead."
+ resource[:environment] = value
+ end
+ end
+
+ newparam(:environment) do
desc "Any additional environment variables you want to set for a
command. Note that if you use this to set PATH, it will override
the ``path`` attribute. Multiple environment variables should be
@@ -554,32 +563,32 @@ module Puppet
begin
# Do our chdir
Dir.chdir(dir) do
- env = {}
+ environment = {}
if self[:path]
- env[:PATH] = self[:path].join(":")
+ environment[:PATH] = self[:path].join(":")
end
- if envlist = self[:env]
+ if envlist = self[:environment]
envlist = [envlist] unless envlist.is_a? Array
envlist.each do |setting|
if setting =~ /^(\w+)=((.|\n)+)$/
name = $1
value = $2
- if env.include? name
+ if environment.include? name
warning(
"Overriding environment setting '%s' with '%s'" %
[name, value]
)
end
- env[name] = value
+ environment[name] = value
else
- warning "Cannot understand env setting %s" % setting.inspect
+ warning "Cannot understand environment setting %s" % setting.inspect
end
end
end
- withenv env do
+ withenv environment do
Timeout::timeout(self[:timeout]) do
output, status = Puppet::Util::SUIDManager.run_and_capture(
[command], self[:user], self[:group]
diff --git a/lib/puppet/type/host.rb b/lib/puppet/type/host.rb
index be5c2ed72..3e34c0b60 100755
--- a/lib/puppet/type/host.rb
+++ b/lib/puppet/type/host.rb
@@ -4,6 +4,13 @@ module Puppet
newproperty(:ip) do
desc "The host's IP address, IPv4 or IPv6."
+
+ validate do |value|
+ unless value =~ /((([0-9a-fA-F]+:){7}[0-9a-fA-F]+)|(([0-9a-fA-F]+:)*[0-9a-fA-F]+)?::(([0-9a-fA-F]+:)*[0-9a-fA-F]+)?)|((25[0-5]|2[0-4][\d]|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3})/
+ raise Puppet::Error, "Invalid IP address"
+ end
+ end
+
end
newproperty(:alias) do
@@ -78,6 +85,12 @@ module Puppet
desc "The host name."
isnamevar
+
+ validate do |value|
+ unless value =~ /^\w+-?[\w+]?\.?[\w+.{1}]*\w+$/
+ raise Puppet::Error, "Invalid host name"
+ end
+ end
end
@doc = "Installs and manages host entries. For most systems, these
diff --git a/lib/puppet/type/package.rb b/lib/puppet/type/package.rb
index 9173eaa1c..24b187e5f 100644
--- a/lib/puppet/type/package.rb
+++ b/lib/puppet/type/package.rb
@@ -176,7 +176,7 @@ module Puppet
a common name to packages::
# In the 'openssl' class
- $ssl = $operationgsystem ? {
+ $ssl = $operatingsystem ? {
solaris => SMCossl,
default => openssl
}
@@ -190,7 +190,7 @@ module Puppet
. etc. .
- $ssh = $operationgsystem ? {
+ $ssh = $operatingsystem ? {
solaris => SMCossh,
default => openssh
}
diff --git a/lib/puppet/type/pfile.rb b/lib/puppet/type/pfile.rb
index 7d928d959..c32a4d474 100644
--- a/lib/puppet/type/pfile.rb
+++ b/lib/puppet/type/pfile.rb
@@ -650,7 +650,7 @@ module Puppet
# LAK:FIXME This shouldn't be necessary, but as long as we're
# modeling the relationship graph specifically, it is.
- catalog.relationship_graph.add_edge! self, child
+ catalog.relationship_graph.add_edge self, child
return child
end
diff --git a/lib/puppet/type/pfile/ensure.rb b/lib/puppet/type/pfile/ensure.rb
index 0a6f73d95..3aa918f65 100755
--- a/lib/puppet/type/pfile/ensure.rb
+++ b/lib/puppet/type/pfile/ensure.rb
@@ -136,6 +136,11 @@ module Puppet
# We have to treat :present specially, because it works with any
# type of file.
def insync?(currentvalue)
+ if property = @resource.property(:source) and ! property.described?
+ warning "No specified sources exist"
+ return true
+ end
+
if self.should == :present
if currentvalue.nil? or currentvalue == :absent
return false
diff --git a/lib/puppet/type/pfile/source.rb b/lib/puppet/type/pfile/source.rb
index 1849d5a61..3dfb5cccd 100755
--- a/lib/puppet/type/pfile/source.rb
+++ b/lib/puppet/type/pfile/source.rb
@@ -138,10 +138,10 @@ module Puppet
# Use the info we get from describe() to check if we're in sync.
def insync?(currentvalue)
unless described?
- info "No specified sources exist"
+ warning "No specified sources exist"
return true
end
-
+
if currentvalue == :nocopy
return true
end
diff --git a/lib/puppet/util/constant_inflector.rb b/lib/puppet/util/constant_inflector.rb
new file mode 100644
index 000000000..8b083951f
--- /dev/null
+++ b/lib/puppet/util/constant_inflector.rb
@@ -0,0 +1,14 @@
+# Created on 2008-02-12
+# Copyright Luke Kanies
+
+# A common module for converting between constants and
+# file names.
+module Puppet::Util::ConstantInflector
+ def file2constant(file)
+ file.split("/").collect { |name| name.capitalize }.join("::").gsub(/_+(.)/) { |term| $1.capitalize }
+ end
+
+ def constant2file(constant)
+ constant.to_s.gsub(/([a-z])([A-Z])/) { |term| $1 + "_" + $2 }.gsub("::", "/").downcase
+ end
+end
diff --git a/lib/puppet/util/graph.rb b/lib/puppet/util/graph.rb
index a9744578b..d1ef36f8e 100644
--- a/lib/puppet/util/graph.rb
+++ b/lib/puppet/util/graph.rb
@@ -16,7 +16,7 @@ module Puppet::Util::Graph
self.each do |child|
unless block_given? and ! yield(child)
- graph.add_edge!(self, child)
+ graph.add_edge(self, child)
if child.respond_to?(:to_graph)
child.to_graph(graph, &block)
diff --git a/lib/puppet/util/settings.rb b/lib/puppet/util/settings.rb
index f87f96980..2c8fc682a 100644
--- a/lib/puppet/util/settings.rb
+++ b/lib/puppet/util/settings.rb
@@ -421,19 +421,19 @@ class Puppet::Util::Settings
objects += add_user_resources(section, obj, done)
end
+ value = obj.value
+
# Only files are convertable to transportable resources.
- if obj.respond_to? :to_transportable
- next if value(obj.name) =~ /^\/dev/
- transobjects = obj.to_transportable
- transobjects = [transobjects] unless transobjects.is_a? Array
- transobjects.each do |trans|
- # transportable could return nil
- next unless trans
- unless done[:file].include? trans.name
- @created << trans.name
- objects << trans
- done[:file][trans.name] = trans
- end
+ next unless obj.respond_to? :to_transportable and transobjects = obj.to_transportable
+
+ transobjects = [transobjects] unless transobjects.is_a? Array
+ transobjects.each do |trans|
+ # transportable could return nil
+ next unless trans
+ unless done[:file].include? trans.name
+ @created << trans.name
+ objects << trans
+ done[:file][trans.name] = trans
end
end
end
@@ -1036,7 +1036,7 @@ Generated on #{Time.now}.
# the variable 'dir', or adding a slash at the end.
def munge(value)
# If it's not a fully qualified path...
- if value.is_a?(String) and value !~ /^\$/ and value !~ /^\//
+ if value.is_a?(String) and value !~ /^\$/ and value !~ /^\// and value != 'false'
# Make it one
value = File.join(Dir.getwd, value)
end
@@ -1065,12 +1065,15 @@ Generated on #{Time.now}.
def to_transportable
type = self.type
return nil unless type
- path = @parent.value(self.name).split(File::SEPARATOR)
- path.shift # remove the leading nil
- objects = []
path = self.value
+ return nil unless path.is_a?(String)
+ return nil if path =~ /^\/dev/
+ return nil if Puppet::Type::File[path] # skip files that are in our global resource list.
+
+ objects = []
+
# Skip plain files that don't exist, since we won't be managing them anyway.
return nil unless self.name.to_s =~ /dir$/ or File.exist?(path) or self.create
obj = Puppet::TransObject.new(path, "file")
diff --git a/lib/puppet/util/tagging.rb b/lib/puppet/util/tagging.rb
new file mode 100644
index 000000000..9abb3fb2b
--- /dev/null
+++ b/lib/puppet/util/tagging.rb
@@ -0,0 +1,39 @@
+# Created on 2008-01-19
+# Copyright Luke Kanies
+
+# A common module to handle tagging.
+module Puppet::Util::Tagging
+ # Add a tag to our current list. These tags will be added to all
+ # of the objects contained in this scope.
+ def tag(*ary)
+ @tags ||= []
+
+ qualified = []
+
+ ary.collect { |tag| tag.to_s.downcase }.each do |tag|
+ fail(Puppet::ParseError, "Invalid tag %s" % tag.inspect) unless valid_tag?(tag)
+ qualified << tag if tag.include?("::")
+ @tags << tag unless @tags.include?(tag)
+ end
+
+ qualified.collect { |name| name.split("::") }.flatten.each { |tag| @tags << tag unless @tags.include?(tag) }
+ end
+
+ # Are we tagged with the provided tag?
+ def tagged?(tag)
+ defined?(@tags) and @tags.include?(tag.to_s)
+ end
+
+ # Return a copy of the tag list, so someone can't ask for our tags
+ # and then modify them.
+ def tags
+ @tags ||= []
+ @tags.dup
+ end
+
+ private
+
+ def valid_tag?(tag)
+ tag =~ /^\w[-\w:]*$/
+ end
+end