summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2007-08-26 21:54:17 -0500
committerLuke Kanies <luke@madstop.com>2007-08-26 21:54:17 -0500
commit11081ce8864dca2bc92d8c9f825c3fe7f96333f4 (patch)
tree89bc049324cd3d20bcb05b55e6c267e50b82aec9
parent9ea8e6cc8772053548d3438393dd1ead986ed719 (diff)
downloadpuppet-11081ce8864dca2bc92d8c9f825c3fe7f96333f4.tar.gz
puppet-11081ce8864dca2bc92d8c9f825c3fe7f96333f4.tar.xz
puppet-11081ce8864dca2bc92d8c9f825c3fe7f96333f4.zip
Multiple environment support now works, and I have even tested it in real life. This commit is mostly a bug-fix commit, resulting from the difference between real-life testing and unit testing.
-rw-r--r--lib/puppet/network/handler/configuration.rb8
-rw-r--r--lib/puppet/parser/interpreter.rb3
-rw-r--r--lib/puppet/parser/parser_support.rb6
-rw-r--r--lib/puppet/util/config.rb45
-rwxr-xr-xspec/unit/parser/interpreter.rb72
-rwxr-xr-xspec/unit/util/config.rb12
-rwxr-xr-xtest/network/handler/configuration.rb22
-rwxr-xr-xtest/network/handler/node.rb2
8 files changed, 118 insertions, 52 deletions
diff --git a/lib/puppet/network/handler/configuration.rb b/lib/puppet/network/handler/configuration.rb
index fd1ee86ed..b2b16d022 100644
--- a/lib/puppet/network/handler/configuration.rb
+++ b/lib/puppet/network/handler/configuration.rb
@@ -92,6 +92,10 @@ class Puppet::Network::Handler
end
# Ask the interpreter to compile the configuration.
+ str = "Compiled configuration for %s" % node.name
+ if node.environment
+ str += " in environment %s" % node.environment
+ end
config = nil
benchmark(level, "Compiled configuration for %s" % node.name) do
begin
@@ -117,8 +121,8 @@ class Puppet::Network::Handler
# Allow specification of a code snippet or of a file
if code = options[:Code]
args[:Code] = code
- else
- args[:Manifest] = options[:Manifest] || Puppet[:manifest]
+ elsif options[:Manifest]
+ args[:Manifest] = options[:Manifest]
end
args[:Local] = local?
diff --git a/lib/puppet/parser/interpreter.rb b/lib/puppet/parser/interpreter.rb
index b6c61d202..93a4bc170 100644
--- a/lib/puppet/parser/interpreter.rb
+++ b/lib/puppet/parser/interpreter.rb
@@ -67,6 +67,9 @@ class Puppet::Parser::Interpreter
parser.string = self.code
elsif self.file
parser.file = self.file
+ else
+ file = Puppet.config.value(:manifest, environment)
+ parser.file = file
end
parser.parse
return parser
diff --git a/lib/puppet/parser/parser_support.rb b/lib/puppet/parser/parser_support.rb
index 401b5b1c0..660fa8169 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, :version
+ attr_reader :version, :environment
attr_accessor :files
@@ -85,6 +85,10 @@ class Puppet::Parser::Parser
raise except
end
+ def file
+ @lexer.file
+ end
+
def file=(file)
unless FileTest.exists?(file)
unless file =~ /\.pp$/
diff --git a/lib/puppet/util/config.rb b/lib/puppet/util/config.rb
index b6831ba9b..fb1c01d56 100644
--- a/lib/puppet/util/config.rb
+++ b/lib/puppet/util/config.rb
@@ -38,7 +38,7 @@ class Puppet::Util::Config
@name = nil
end
@values[:memory][param] = value
- @values[:cache].clear
+ @cache.clear
end
return value
@@ -113,12 +113,14 @@ class Puppet::Util::Config
@used = []
end
+ @cache.clear
+
@name = nil
end
# This is mostly just used for testing.
def clearused
- @values[:cache].clear
+ @cache.clear
@used = []
end
@@ -173,6 +175,7 @@ class Puppet::Util::Config
# Handle a command-line argument.
def handlearg(opt, value = nil)
+ clear(true)
value = munge_value(value) if value
str = opt.sub(/^--/,'')
bool = true
@@ -215,6 +218,9 @@ class Puppet::Util::Config
# Keep track of set values.
@values = Hash.new { |hash, key| hash[key] = {} }
+ # And keep a per-environment cache
+ @cache = Hash.new { |hash, key| hash[key] = {} }
+
# A central concept of a name.
@name = nil
end
@@ -448,9 +454,9 @@ class Puppet::Util::Config
# The order in which to search for values.
def searchpath(environment = nil)
if environment
- [:cache, :cli, :memory, environment, :name, :main]
+ [:cli, :memory, environment, :name, :main]
else
- [:cache, :cli, :memory, :name, :main]
+ [:cli, :memory, :name, :main]
end
end
@@ -730,7 +736,15 @@ Generated on #{Time.now}.
# Yay, recursion.
self.reparse() unless param == :filetimeout
+ # Check the cache first. It needs to be a per-environment
+ # cache so that we don't spread values from one env
+ # to another.
+ if @cache[environment||"none"].include?(param)
+ return @cache[environment||"none"][param]
+ end
+
# See if we can find it within our searchable list of values
+ val = nil
searchpath(environment).each do |source|
# Modify the source as necessary.
source = case source
@@ -740,21 +754,24 @@ Generated on #{Time.now}.
source
end
- # Look for the value.
+ # Look for the value. We have to test the hash for whether
+ # it exists, because the value might be false.
if @values[source].include?(param)
val = @values[source][param]
- # Cache the value, because we do so many parameter lookups.
- unless source == :cache
- val = convert(val)
- @values[:cache][param] = val
- end
- return val
+ break
end
end
- # No normal source, so get the default and cache it
- val = convert(@config[param].default)
- @values[:cache][param] = val
+ # If we didn't get a value, use the default
+ if val.nil?
+ val = @config[param].default
+ end
+
+ # Convert it if necessary
+ val = convert(val)
+
+ # And cache it
+ @cache[environment||"none"][param] = val
return val
end
diff --git a/spec/unit/parser/interpreter.rb b/spec/unit/parser/interpreter.rb
index 7328e2651..ebb7d4cbf 100755
--- a/spec/unit/parser/interpreter.rb
+++ b/spec/unit/parser/interpreter.rb
@@ -44,29 +44,51 @@ describe Puppet::Parser::Interpreter, " when creating parser instances" do
it "should create a parser with code passed in at initialization time" do
@interp.code = :some_code
- @parser.expects(:code=).with(:some_code)
+ @parser.expects(:string=).with(:some_code)
@parser.expects(:parse)
- Puppet::Parser::Parser.expects(:new).with(:environment).returns(@parser)
- @interp.send(:create_parser, :environment).object_id.should equal(@parser.object_id)
+ Puppet::Parser::Parser.expects(:new).with(:environment => :myenv).returns(@parser)
+ @interp.send(:create_parser, :myenv).object_id.should equal(@parser.object_id)
end
it "should create a parser with a file passed in at initialization time" do
@interp.file = :a_file
@parser.expects(:file=).with(:a_file)
@parser.expects(:parse)
- Puppet::Parser::Parser.expects(:new).with(:environment).returns(@parser)
- @interp.send(:create_parser, :environment).should equal(@parser)
+ Puppet::Parser::Parser.expects(:new).with(:environment => :myenv).returns(@parser)
+ @interp.send(:create_parser, :myenv).should equal(@parser)
end
- it "should create a parser when passed neither code nor file" do
+ it "should create a parser with the main manifest when passed neither code nor file" do
@parser.expects(:parse)
- Puppet::Parser::Parser.expects(:new).with(:environment).returns(@parser)
- @interp.send(:create_parser, :environment).should equal(@parser)
+ @parser.expects(:file=).with(Puppet[:manifest])
+ Puppet::Parser::Parser.expects(:new).with(:environment => :myenv).returns(@parser)
+ @interp.send(:create_parser, :myenv).should equal(@parser)
end
it "should return nothing when new parsers fail" do
- Puppet::Parser::Parser.expects(:new).with(:environment).raises(ArgumentError)
- @interp.send(:create_parser, :environment).should be_nil
+ Puppet::Parser::Parser.expects(:new).with(:environment => :myenv).raises(ArgumentError)
+ @interp.send(:create_parser, :myenv).should be_nil
+ end
+
+ it "should create parsers with environment-appropriate manifests" do
+ # Set our per-environment values. We can't just stub :value, because
+ # it's called by too much of the rest of the code.
+ text = "[env1]\nmanifest = /t/env1.pp\n[env2]\nmanifest = /t/env2.pp"
+ file = mock 'file'
+ file.stubs(:changed?).returns(true)
+ file.stubs(:file).returns("/whatever")
+ Puppet.config.stubs(:read_file).with(file).returns(text)
+ Puppet.config.parse(file)
+
+ parser1 = mock 'parser1'
+ Puppet::Parser::Parser.expects(:new).with(:environment => :env1).returns(parser1)
+ parser1.expects(:file=).with("/t/env1.pp")
+ @interp.send(:create_parser, :env1)
+
+ parser2 = mock 'parser2'
+ Puppet::Parser::Parser.expects(:new).with(:environment => :env2).returns(parser2)
+ parser2.expects(:file=).with("/t/env2.pp")
+ @interp.send(:create_parser, :env2)
end
end
@@ -77,16 +99,16 @@ describe Puppet::Parser::Interpreter, " when managing parser instances" do
end
it "it should an exception when nothing is there and nil is returned" do
- @interp.expects(:create_parser).with(:environment).returns(nil)
- lambda { @interp.send(:parser, :environment) }.should raise_error(Puppet::Error)
+ @interp.expects(:create_parser).with(:myenv).returns(nil)
+ lambda { @interp.send(:parser, :myenv) }.should raise_error(Puppet::Error)
end
it "should create and return a new parser and use the same parser when the parser does not need reparsing" do
- @interp.expects(:create_parser).with(:environment).returns(@parser)
- @interp.send(:parser, :environment).should equal(@parser)
+ @interp.expects(:create_parser).with(:myenv).returns(@parser)
+ @interp.send(:parser, :myenv).should equal(@parser)
@parser.expects(:reparse?).returns(false)
- @interp.send(:parser, :environment).should equal(@parser)
+ @interp.send(:parser, :myenv).should equal(@parser)
end
it "should create a new parser when reparse is true" do
@@ -95,25 +117,25 @@ describe Puppet::Parser::Interpreter, " when managing parser instances" do
oldparser.expects(:reparse?).returns(true)
oldparser.expects(:clear)
- @interp.expects(:create_parser).with(:environment).returns(oldparser)
- @interp.send(:parser, :environment).should equal(oldparser)
- @interp.expects(:create_parser).with(:environment).returns(newparser)
- @interp.send(:parser, :environment).should equal(newparser)
+ @interp.expects(:create_parser).with(:myenv).returns(oldparser)
+ @interp.send(:parser, :myenv).should equal(oldparser)
+ @interp.expects(:create_parser).with(:myenv).returns(newparser)
+ @interp.send(:parser, :myenv).should equal(newparser)
end
it "should keep the old parser if create_parser doesn't return anything." do
# Get the first parser in the hash.
- @interp.expects(:create_parser).with(:environment).returns(@parser)
- @interp.send(:parser, :environment).should equal(@parser)
+ @interp.expects(:create_parser).with(:myenv).returns(@parser)
+ @interp.send(:parser, :myenv).should equal(@parser)
# Have it indicate something has changed
@parser.expects(:reparse?).returns(true)
# But fail to create a new parser
- @interp.expects(:create_parser).with(:environment).returns(nil)
+ @interp.expects(:create_parser).with(:myenv).returns(nil)
# And make sure we still get the old valid parser
- @interp.send(:parser, :environment).should equal(@parser)
+ @interp.send(:parser, :myenv).should equal(@parser)
end
it "should use different parsers for different environments" do
@@ -140,7 +162,7 @@ describe Puppet::Parser::Interpreter, " when compiling configurations" do
parser = mock 'parser'
@interp.expects(:parser).with(:myenv).returns(parser)
@interp.expects(:usenodes?).returns(true)
- Puppet::Parser::Configuration.expects(:new).with(node, parser, :ast_nodes => true).returns(compile)
+ Puppet::Parser::Compile.expects(:new).with(node, parser, :ast_nodes => true).returns(compile)
@interp.compile(node)
# Now try it when usenodes is true
@@ -149,7 +171,7 @@ describe Puppet::Parser::Interpreter, " when compiling configurations" do
compile.expects(:compile).returns(:config)
@interp.expects(:parser).with(:myenv).returns(parser)
@interp.expects(:usenodes?).returns(false)
- Puppet::Parser::Configuration.expects(:new).with(node, parser, :ast_nodes => false).returns(compile)
+ Puppet::Parser::Compile.expects(:new).with(node, parser, :ast_nodes => false).returns(compile)
@interp.compile(node).should equal(:config)
end
end
diff --git a/spec/unit/util/config.rb b/spec/unit/util/config.rb
index 7f9b64c94..0b3b65c28 100755
--- a/spec/unit/util/config.rb
+++ b/spec/unit/util/config.rb
@@ -139,6 +139,18 @@ describe Puppet::Util::Config, " when returning values" do
@config[:two].should == "one TWO"
end
+ it "should not cache values such that information from one environment is returned for another environment" do
+ text = "[env1]\none = oneval\n[env2]\none = twoval\n"
+ file = mock 'file'
+ file.stubs(:changed?).returns(true)
+ file.stubs(:file).returns("/whatever")
+ @config.stubs(:read_file).with(file).returns(text)
+ @config.parse(file)
+
+ @config.value(:one, "env1").should == "oneval"
+ @config.value(:one, "env2").should == "twoval"
+ end
+
it "should have a name determined by the 'name' parameter" do
@config.setdefaults(:whatever, :name => ["something", "yayness"])
@config.name.should == :something
diff --git a/test/network/handler/configuration.rb b/test/network/handler/configuration.rb
index a34952208..072fdc053 100755
--- a/test/network/handler/configuration.rb
+++ b/test/network/handler/configuration.rb
@@ -52,7 +52,7 @@ class TestHandlerConfiguration < Test::Unit::TestCase
args = {}
# Try it first with defaults.
- Puppet::Parser::Interpreter.expects(:new).with(:Local => config.local?, :Manifest => Puppet[:manifest]).returns(:interp)
+ Puppet::Parser::Interpreter.expects(:new).with(:Local => config.local?).returns(:interp)
assert_equal(:interp, config.send(:create_interpreter, args), "Did not return the interpreter")
# Now reset it and make sure a specified manifest passes through
@@ -93,10 +93,12 @@ class TestHandlerConfiguration < Test::Unit::TestCase
config = Config.new
# First do a local
- node = Object.new
- node.expects(:name).returns(:mynode)
+ node = mock 'node'
+ node.stubs(:name).returns(:mynode)
+ node.stubs(:environment).returns(:myenv)
- interp = Object.new
+ interp = mock 'interpreter'
+ interp.stubs(:environment)
interp.expects(:compile).with(node).returns(:config)
config.expects(:interpreter).returns(interp)
@@ -105,13 +107,15 @@ class TestHandlerConfiguration < Test::Unit::TestCase
assert_equal(:config, config.send(:compile, node), "Did not return config")
# Now try it non-local
- config = Config.new(:Local => true)
-
- node = Object.new
- node.expects(:name).returns(:mynode)
+ node = mock 'node'
+ node.stubs(:name).returns(:mynode)
+ node.stubs(:environment).returns(:myenv)
- interp = Object.new
+ interp = mock 'interpreter'
+ interp.stubs(:environment)
interp.expects(:compile).with(node).returns(:config)
+
+ config = Config.new(:Local => true)
config.expects(:interpreter).returns(interp)
assert_equal(:config, config.send(:compile, node), "Did not return config")
diff --git a/test/network/handler/node.rb b/test/network/handler/node.rb
index f7cbf6017..6b8ab9290 100755
--- a/test/network/handler/node.rb
+++ b/test/network/handler/node.rb
@@ -531,7 +531,7 @@ class LdapNodeTest < PuppetTest::TestCase
end
def ldaphost(name)
- node = NodeDef.new(:name => name)
+ node = Puppet::Node.new(name)
parent = nil
found = false
@ldap.search( "ou=hosts, dc=madstop, dc=com", 2,