summaryrefslogtreecommitdiffstats
path: root/lib/puppet
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2007-08-23 13:25:40 -0500
committerLuke Kanies <luke@madstop.com>2007-08-23 13:25:40 -0500
commit724fef1269bd593496bca9827a0ad7d9361e92d4 (patch)
tree8b8fb73ee625680bcbc3913e2ee007c8b344f44f /lib/puppet
parent3d68ed66ca7545c26b83a4c921d21f5aad710ee0 (diff)
downloadpuppet-724fef1269bd593496bca9827a0ad7d9361e92d4.tar.gz
puppet-724fef1269bd593496bca9827a0ad7d9361e92d4.tar.xz
puppet-724fef1269bd593496bca9827a0ad7d9361e92d4.zip
Everything up to the parser (and the Modules) is ready to support multiple environments, including the parser having an environment setting. I have also created my first spec-based tests, for the interpreter (and deleted the old test/unit tests).
Diffstat (limited to 'lib/puppet')
-rw-r--r--lib/puppet/network/handler/configuration.rb18
-rw-r--r--lib/puppet/network/handler/master.rb4
-rw-r--r--lib/puppet/parser/configuration.rb11
-rw-r--r--lib/puppet/parser/interpreter.rb140
-rw-r--r--lib/puppet/parser/parser_support.rb14
-rw-r--r--lib/puppet/transportable.rb13
6 files changed, 79 insertions, 121 deletions
diff --git a/lib/puppet/network/handler/configuration.rb b/lib/puppet/network/handler/configuration.rb
index 7e91d74d6..a1b22207e 100644
--- a/lib/puppet/network/handler/configuration.rb
+++ b/lib/puppet/network/handler/configuration.rb
@@ -57,14 +57,18 @@ class Puppet::Network::Handler
# Return the configuration version.
def version(client = nil, clientip = nil)
- v = interpreter.parsedate
- # If we can find the node, then store the fact that the node
- # has checked in.
- if client and node = node_handler.details(client)
- update_node_check(node)
+ if client
+ if node = node_handler.details(client)
+ update_node_check(node)
+ return interpreter.configuration_version(node)
+ else
+ raise Puppet::Error, "Could not find node '%s'" % client
+ end
+ else
+ # Just return something that will always result in a recompile, because
+ # this is local.
+ return 0
end
-
- return v
end
private
diff --git a/lib/puppet/network/handler/master.rb b/lib/puppet/network/handler/master.rb
index acc6c4cda..0cab94f69 100644
--- a/lib/puppet/network/handler/master.rb
+++ b/lib/puppet/network/handler/master.rb
@@ -32,8 +32,8 @@ class Puppet::Network::Handler
# Allow specification of a code snippet or of a file
if code = hash[:Code]
args[:Code] = code
- else
- args[:Manifest] = hash[:Manifest] || Puppet[:manifest]
+ elsif man = hash[:Manifest]
+ args[:Manifest] = man
end
if hash[:Local]
diff --git a/lib/puppet/parser/configuration.rb b/lib/puppet/parser/configuration.rb
index 44fb8c476..148f4dcd1 100644
--- a/lib/puppet/parser/configuration.rb
+++ b/lib/puppet/parser/configuration.rb
@@ -347,15 +347,8 @@ class Puppet::Parser::Configuration
# Retrive the bucket for the top-level scope and set the appropriate metadata.
result = buckets[topscope]
- case topscope.type
- when "": result.type = "main"
- when nil: devfail "A Scope with no type"
- else
- result.type = topscope.type
- end
- if topscope.name
- result.name = topscope.name
- end
+
+ result.copy_type_and_name(topscope)
unless classlist.empty?
result.classes = classlist
diff --git a/lib/puppet/parser/interpreter.rb b/lib/puppet/parser/interpreter.rb
index fa90838f0..0398115de 100644
--- a/lib/puppet/parser/interpreter.rb
+++ b/lib/puppet/parser/interpreter.rb
@@ -14,31 +14,32 @@ class Puppet::Parser::Interpreter
include Puppet::Util
attr_accessor :usenodes
- attr_reader :parser
+ attr_accessor :code, :file
include Puppet::Util::Errors
+ # Determine the configuration version for a given node's environment.
+ def configuration_version(node)
+ parser(node.environment).version
+ end
+
+ # evaluate our whole tree
+ def compile(node)
+ return Puppet::Parser::Configuration.new(node, parser(node.environment), :ast_nodes => usenodes?).compile
+ end
+
# create our interpreter
- def initialize(hash)
- if @code = hash[:Code]
- @file = nil # to avoid warnings
- elsif ! @file = hash[:Manifest]
- devfail "You must provide code or a manifest"
+ def initialize(options = {})
+ if @code = options[:Code]
+ elsif @file = options[:Manifest]
end
- if hash.include?(:UseNodes)
- @usenodes = hash[:UseNodes]
+ if options.include?(:UseNodes)
+ @usenodes = options[:UseNodes]
else
@usenodes = true
end
- # By default, we only search for parsed nodes.
- @nodesource = :code
-
- @setup = false
-
- @local = hash[:Local] || false
-
# The class won't always be defined during testing.
if Puppet[:storeconfigs]
if Puppet.features.rails?
@@ -48,98 +49,47 @@ class Puppet::Parser::Interpreter
end
end
- @files = []
-
- # Create our parser object
- parsefiles
+ @parsers = {}
end
- def parsedate
- parsefiles()
- @parsedate
- end
-
- # evaluate our whole tree
- def compile(node)
- parsefiles()
-
- return Puppet::Parser::Configuration.new(node, @parser, :ast_nodes => @usenodes).compile
+ # Should we parse ast nodes?
+ def usenodes?
+ defined?(@usenodes) and @usenodes
end
private
- # Check whether any of our files have changed.
- def checkfiles
- if @files.find { |f| f.changed? }
- @parsedate = Time.now.to_i
- end
- end
-
- # Parse the files, generating our parse tree. This automatically
- # reparses only if files are updated, so it's safe to call multiple
- # times.
- def parsefiles
- # First check whether there are updates to any non-puppet files
- # like templates. If we need to reparse, this will get quashed,
- # but it needs to be done first in case there's no reparse
- # but there are other file changes.
- checkfiles()
-
- # Check if the parser should reparse.
- if @file
- if defined? @parser
- if stamp = @parser.reparse?
- Puppet.notice "Reloading files"
- else
- return false
- end
- end
-
- unless FileTest.exists?(@file)
- # If we've already parsed, then we're ok.
- if findclass("", "")
- return
- else
- raise Puppet::Error, "Manifest %s must exist" % @file
- end
- end
- end
-
- # Create a new parser, just to keep things fresh. Don't replace our
- # current parser until we know weverything works.
- newparser = Puppet::Parser::Parser.new()
- if @code
- newparser.string = @code
- else
- newparser.file = @file
- end
-
- # Parsing stores all classes and defines and such in their
- # various tables, so we don't worry about the return.
+ # Create a new parser object and pre-parse the configuration.
+ def create_parser(environment)
begin
- if @local
- newparser.parse
- else
- benchmark(:info, "Parsed manifest") do
- newparser.parse
- end
- end
- # We've gotten this far, so it's ok to swap the parsers.
- oldparser = @parser
- @parser = newparser
- if oldparser
- oldparser.clear
+ parser = Puppet::Parser::Parser.new(environment)
+ if self.code
+ parser.code = self.code
+ elsif self.file
+ parser.file = self.file
end
-
- # Mark when we parsed, so we can check freshness
- @parsedate = Time.now.to_i
+ parser.parse
+ return parser
rescue => detail
if Puppet[:trace]
puts detail.backtrace
end
- Puppet.err "Could not parse; using old configuration: %s" % detail
+ Puppet.err "Could not parse for environment %s: %s" % [environment, detail]
+ return nil
end
end
-end
-# $Id$
+ # Return the parser for a specific environment.
+ def parser(environment)
+ if ! @parsers[environment] or @parsers[environment].reparse?
+ if tmp = create_parser(environment)
+ @parsers[environment].clear if @parsers[environment]
+ @parsers[environment] = tmp
+ end
+ unless @parsers[environment]
+ raise Puppet::Error, "Could not parse any configurations"
+ end
+ end
+ @parsers[environment]
+ end
+end
diff --git a/lib/puppet/parser/parser_support.rb b/lib/puppet/parser/parser_support.rb
index 967508e56..dfc91ba12 100644
--- a/lib/puppet/parser/parser_support.rb
+++ b/lib/puppet/parser/parser_support.rb
@@ -15,7 +15,7 @@ class Puppet::Parser::Parser
AST = Puppet::Parser::AST
- attr_reader :file, :interp
+ attr_reader :file, :version
attr_accessor :files
@@ -202,11 +202,9 @@ class Puppet::Parser::Parser
}
end
- def initialize(astset = nil)
+ def initialize(environment)
+ @environment = environment
initvars()
- if astset
- @astset = astset
- end
end
# Initialize or reset all of our variables.
@@ -427,6 +425,7 @@ class Puppet::Parser::Parser
# Store the results as the top-level class.
newclass("", :code => main)
end
+ @version = Time.now.to_i
return @astset
ensure
@lexer.clear
@@ -446,7 +445,8 @@ class Puppet::Parser::Parser
end
# Add a new file to be checked when we're checking to see if we should be
- # reparsed.
+ # reparsed. This is basically only used by the TemplateWrapper to let the
+ # parser know about templates that should be parsed.
def watch_file(*files)
files.each do |file|
unless file.is_a? Puppet::Util::LoadedFile
@@ -456,5 +456,3 @@ class Puppet::Parser::Parser
end
end
end
-
-# $Id$
diff --git a/lib/puppet/transportable.rb b/lib/puppet/transportable.rb
index aa7eb92f7..acd69fb0c 100644
--- a/lib/puppet/transportable.rb
+++ b/lib/puppet/transportable.rb
@@ -100,6 +100,19 @@ module Puppet
end
}
+ # Copy a scope's type and name.
+ def copy_type_and_name(scope)
+ case scope.type
+ when "": self.type = "main"
+ when nil: devfail "A Scope with no type"
+ else
+ self.type = scope.type
+ end
+ if scope.name
+ self.name = scope.name
+ end
+ end
+
# Remove all collectable objects from our tree, since the client
# should not see them.
def collectstrip!