summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Lewis <nick@puppetlabs.com>2011-04-12 14:40:12 -0700
committerNick Lewis <nick@puppetlabs.com>2011-04-12 14:48:18 -0700
commitb2831e102f4cc57d6e0101f55e208695188d426a (patch)
tree60c02e8aeafb42952a9fd9a86f68e635bf39c206
parent2dfa0afb57ec80f451a54ef96341d413819c14c7 (diff)
downloadpuppet-b2831e102f4cc57d6e0101f55e208695188d426a.tar.gz
puppet-b2831e102f4cc57d6e0101f55e208695188d426a.tar.xz
puppet-b2831e102f4cc57d6e0101f55e208695188d426a.zip
(#2150) Add routes file for indirector
Puppet[:route_file] is a YAML file specifying the termini to use for various indirections, in the format: agent: catalog: terminus: rest cache: yaml master: catalog: terminus: compiler cache: active_record This file is optional, and will override application defaults set in "setup", as well as terminus settings, ie. facts_terminus. Paired-With: Jesse Wolfe
-rw-r--r--lib/puppet/application.rb22
-rw-r--r--lib/puppet/defaults.rb1
-rw-r--r--lib/puppet/indirector.rb16
-rwxr-xr-xspec/unit/application_spec.rb50
-rwxr-xr-xspec/unit/indirector_spec.rb59
5 files changed, 142 insertions, 6 deletions
diff --git a/lib/puppet/application.rb b/lib/puppet/application.rb
index 57bd88877..4c5a5a967 100644
--- a/lib/puppet/application.rb
+++ b/lib/puppet/application.rb
@@ -299,11 +299,12 @@ class Application
# This is the main application entry point
def run
- exit_on_fail("initialize") { hook('preinit') { preinit } }
- exit_on_fail("parse options") { hook('parse_options') { parse_options } }
- exit_on_fail("parse configuration file") { Puppet.settings.parse } if should_parse_config?
- exit_on_fail("prepare for execution") { hook('setup') { setup } }
- exit_on_fail("run") { hook('run_command') { run_command } }
+ exit_on_fail("initialize") { hook('preinit') { preinit } }
+ exit_on_fail("parse options") { hook('parse_options') { parse_options } }
+ exit_on_fail("parse configuration file") { Puppet.settings.parse } if should_parse_config?
+ exit_on_fail("prepare for execution") { hook('setup') { setup } }
+ exit_on_fail("configure routes from #{Puppet[:route_file]}") { configure_indirector_routes }
+ exit_on_fail("run") { hook('run_command') { run_command } }
end
def main
@@ -328,6 +329,15 @@ class Application
Puppet::Util::Log.newdestination(:syslog) unless options[:setdest]
end
+ def configure_indirector_routes
+ route_file = Puppet[:route_file]
+ if File.exists?(route_file)
+ routes = YAML.load_file(route_file)
+ application_routes = routes[name.to_s]
+ Puppet::Indirector.configure_routes(application_routes) if application_routes
+ end
+ end
+
def parse_options
# Create an option parser
option_parser = OptionParser.new(self.class.banner)
@@ -394,7 +404,7 @@ class Application
def exit_on_fail(message, code = 1)
yield
- rescue RuntimeError, NotImplementedError => detail
+ rescue ArgumentError, RuntimeError, NotImplementedError => detail
puts detail.backtrace if Puppet[:trace]
$stderr.puts "Could not #{message}: #{detail}"
exit(code)
diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb
index 76c40824c..89f3e169d 100644
--- a/lib/puppet/defaults.rb
+++ b/lib/puppet/defaults.rb
@@ -116,6 +116,7 @@ module Puppet
but then ship with tools that do not know how to handle signed ints, so the UIDs show up as
huge numbers that can then not be fed back into the system. This is a hackish way to fail in a
slightly more useful way when that happens."],
+ :route_file => ["$confdir/routes.yaml", "The YAML file containing indirector route configuration."],
:node_terminus => ["plain", "Where to find information about nodes."],
:catalog_terminus => ["compiler", "Where to get node catalogs. This is useful to change if, for instance,
you'd like to pre-compile catalogs and store them in memcached or some other easily-accessed store."],
diff --git a/lib/puppet/indirector.rb b/lib/puppet/indirector.rb
index 9effc5cdd..7267ac7f3 100644
--- a/lib/puppet/indirector.rb
+++ b/lib/puppet/indirector.rb
@@ -12,6 +12,22 @@ module Puppet::Indirector
require 'puppet/indirector/envelope'
require 'puppet/network/format_handler'
+ def self.configure_routes(application_routes)
+ application_routes.each do |indirection_name, termini|
+ indirection_name = indirection_name.to_sym
+ terminus_name = termini["terminus"]
+ cache_name = termini["cache"]
+
+ Puppet::Indirector::Terminus.terminus_classes(indirection_name)
+
+ indirection = Puppet::Indirector::Indirection.instance(indirection_name)
+ raise "Indirection #{indirection_name} does not exist" unless indirection
+
+ indirection.terminus_class = terminus_name if terminus_name
+ indirection.cache_class = cache_name if cache_name
+ end
+ end
+
# Declare that the including class indirects its methods to
# this terminus. The terminus name must be the name of a Puppet
# default, not the value -- if it's the value, then it gets
diff --git a/spec/unit/application_spec.rb b/spec/unit/application_spec.rb
index d8491bb75..740b76f62 100755
--- a/spec/unit/application_spec.rb
+++ b/spec/unit/application_spec.rb
@@ -12,6 +12,7 @@ describe Puppet::Application do
@app = Class.new(Puppet::Application).new
@appclass = @app.class
+ @app.stubs(:name).returns("test_app")
# avoid actually trying to parse any settings
Puppet.settings.stubs(:parse)
end
@@ -396,6 +397,55 @@ describe Puppet::Application do
end
+ describe "when configuring routes" do
+ include PuppetSpec::Files
+
+ before :each do
+ Puppet::Node.indirection.reset_terminus_class
+ end
+
+ after :each do
+ Puppet::Node.indirection.reset_terminus_class
+ end
+
+ it "should use the routes specified for only the active application" do
+ Puppet[:route_file] = tmpfile('routes')
+ File.open(Puppet[:route_file], 'w') do |f|
+ f.print <<-ROUTES
+ test_app:
+ node:
+ terminus: exec
+ other_app:
+ node:
+ terminus: plain
+ catalog:
+ terminus: invalid
+ ROUTES
+ end
+
+ @app.configure_indirector_routes
+
+ Puppet::Node.indirection.terminus_class.should == 'exec'
+ end
+
+ it "should not fail if the route file doesn't exist" do
+ Puppet[:route_file] = "/dev/null/non-existent"
+
+ expect { @app.configure_indirector_routes }.should_not raise_error
+ end
+
+ it "should raise an error if the routes file is invalid" do
+ Puppet[:route_file] = tmpfile('routes')
+ File.open(Puppet[:route_file], 'w') do |f|
+ f.print <<-ROUTES
+ invalid : : yaml
+ ROUTES
+ end
+
+ expect { @app.configure_indirector_routes }.should raise_error
+ end
+ end
+
describe "when running" do
before :each do
diff --git a/spec/unit/indirector_spec.rb b/spec/unit/indirector_spec.rb
index c7d42c707..cca86e218 100755
--- a/spec/unit/indirector_spec.rb
+++ b/spec/unit/indirector_spec.rb
@@ -5,6 +5,65 @@ require 'spec_helper'
require 'puppet/defaults'
require 'puppet/indirector'
+describe Puppet::Indirector, "when configuring routes" do
+ before :each do
+ Puppet::Node.indirection.reset_terminus_class
+ Puppet::Node.indirection.cache_class = nil
+ end
+
+ after :each do
+ Puppet::Node.indirection.reset_terminus_class
+ Puppet::Node.indirection.cache_class = nil
+ end
+
+ it "should configure routes as requested" do
+ routes = {
+ "node" => {
+ "terminus" => "exec",
+ "cache" => "plain"
+ }
+ }
+
+ Puppet::Indirector.configure_routes(routes)
+
+ Puppet::Node.indirection.terminus_class.should == "exec"
+ Puppet::Node.indirection.cache_class.should == "plain"
+ end
+
+ it "should fail when given an invalid indirection" do
+ routes = {
+ "fake_indirection" => {
+ "terminus" => "exec",
+ "cache" => "plain"
+ }
+ }
+
+ expect { Puppet::Indirector.configure_routes(routes) }.should raise_error(/fake_indirection does not exist/)
+ end
+
+ it "should fail when given an invalid terminus" do
+ routes = {
+ "node" => {
+ "terminus" => "fake_terminus",
+ "cache" => "plain"
+ }
+ }
+
+ expect { Puppet::Indirector.configure_routes(routes) }.should raise_error(/Could not find terminus fake_terminus/)
+ end
+
+ it "should fail when given an invalid cache" do
+ routes = {
+ "node" => {
+ "terminus" => "exec",
+ "cache" => "fake_cache"
+ }
+ }
+
+ expect { Puppet::Indirector.configure_routes(routes) }.should raise_error(/Could not find terminus fake_cache/)
+ end
+end
+
describe Puppet::Indirector, " when available to a model" do
before do
@thingie = Class.new do