Sweet! I thought we'd never get this in, this is really awesome.
On Apr 12, 2011, at 2:52 PM, Nick Lewis wrote: > 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 > > Signed-off-by: Nick Lewis <n...@puppetlabs.com> > --- > Local-branch: ticket/next/2150 > lib/puppet/application.rb | 22 +++++++++++---- > lib/puppet/defaults.rb | 1 + > lib/puppet/indirector.rb | 16 +++++++++++ > spec/unit/application_spec.rb | 50 ++++++++++++++++++++++++++++++++++ > spec/unit/indirector_spec.rb | 59 +++++++++++++++++++++++++++++++++++++++++ > 5 files changed, 142 insertions(+), 6 deletions(-) > > diff --git a/lib/puppet/application.rb b/lib/puppet/application.rb > index 57bd888..4c5a5a9 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 76c4082..89f3e16 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 9effc5c..7267ac7 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 d8491bb..740b76f 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 c7d42c7..cca86e2 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 > -- > 1.7.4.1 > > -- > You received this message because you are subscribed to the Google Groups > "Puppet Developers" group. > To post to this group, send email to puppet-dev@googlegroups.com. > To unsubscribe from this group, send email to > puppet-dev+unsubscr...@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/puppet-dev?hl=en. > -- The people who are regarded as moral luminaries are those who forego ordinary pleasures themselves and find compensation in interfering with the pleasures of others. -- Bertrand Russell --------------------------------------------------------------------- Luke Kanies -|- http://puppetlabs.com -|- http://about.me/lak -- You received this message because you are subscribed to the Google Groups "Puppet Developers" group. To post to this group, send email to puppet-dev@googlegroups.com. To unsubscribe from this group, send email to puppet-dev+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-dev?hl=en.