diff --git a/lib/puppet/string/indirector.rb b/lib/puppet/string/indirector.rb index 48280cc77..bb081533f 100644 --- a/lib/puppet/string/indirector.rb +++ b/lib/puppet/string/indirector.rb @@ -1,86 +1,94 @@ require 'puppet' require 'puppet/string' class Puppet::String::Indirector < Puppet::String - warn "REVISIT: Need to redefine this to take arguments again, eh." option "--terminus TERMINUS" do desc "REVISIT: You can select a terminus, which has some bigger effect that we should describe in this file somehow." end def self.indirections Puppet::Indirector::Indirection.instances.collect { |t| t.to_s }.sort end def self.terminus_classes(indirection) Puppet::Indirector::Terminus.terminus_classes(indirection.to_sym).collect { |t| t.to_s }.sort end + def call_indirection_method(method, *args) + options = args.pop + options.has_key?(:terminus) and set_terminus(options[:terminus]) + + begin + result = indirection.__send__(method, *args) + rescue => detail + puts detail.backtrace if Puppet[:trace] + raise "Could not call '#{method}' on '#{indirection_name}': #{detail}" + end + + indirection.reset_terminus_class + return result + end + action :destroy do invoke { |*args| call_indirection_method(:destroy, *args) } end action :find do invoke { |*args| call_indirection_method(:find, *args) } end action :save do invoke { |*args| call_indirection_method(:save, *args) } end action :search do invoke { |*args| call_indirection_method(:search, *args) } end # Print the configuration for the current terminus class action :info do invoke do |*args| + options = args.pop + options.has_key?(:terminus) and set_terminus(options[:terminus]) + if t = indirection.terminus_class puts "Run mode '#{Puppet.run_mode.name}': #{t}" else $stderr.puts "No default terminus class for run mode '#{Puppet.run_mode.name}'" end + + indirection.reset_terminus_class end end attr_accessor :from def indirection_name @indirection_name || name.to_sym end # Here's your opportunity to override the indirection name. By default # it will be the same name as the string. def set_indirection_name(name) @indirection_name = name end # Return an indirection associated with an string, if one exists # One usually does. def indirection unless @indirection @indirection = Puppet::Indirector::Indirection.instance(indirection_name) @indirection or raise "Could not find terminus for #{indirection_name}" end @indirection end def set_terminus(from) begin indirection.terminus_class = from rescue => detail raise "Could not set '#{indirection.name}' terminus to '#{from}' (#{detail}); valid terminus types are #{self.class.terminus_classes(indirection.name).join(", ") }" end end - - def call_indirection_method(method, *args) - begin - result = indirection.__send__(method, *args) - rescue => detail - puts detail.backtrace if Puppet[:trace] - raise "Could not call '#{method}' on '#{indirection_name}': #{detail}" - end - - result - end end diff --git a/spec/unit/application/indirection_base_spec.rb b/spec/unit/application/indirection_base_spec.rb index f636613c4..66b3009fb 100755 --- a/spec/unit/application/indirection_base_spec.rb +++ b/spec/unit/application/indirection_base_spec.rb @@ -1,39 +1,39 @@ #!/usr/bin/env ruby require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb') require 'puppet/application/indirection_base' require 'puppet/string/indirector' ######################################################################## # Stub for testing; the names are critical, sadly. --daniel 2011-03-30 class Puppet::Application::TestIndirection < Puppet::Application::IndirectionBase end string = Puppet::String::Indirector.define(:testindirection, '0.0.1') do end # REVISIT: This horror is required because we don't allow anything to be # :current except for if it lives on, and is loaded from, disk. --daniel 2011-03-29 string.version = :current Puppet::String.register(string) ######################################################################## describe Puppet::Application::IndirectionBase do subject { Puppet::Application::TestIndirection.new } it "should accept a terminus command line option" do # It would be nice not to have to stub this, but whatever... writing an # entire indirection stack would cause us more grief. --daniel 2011-03-31 terminus = mock("test indirection terminus") Puppet::Indirector::Indirection.expects(:instance). - with(:testindirection).returns() + with(:testindirection).twice.returns() subject.command_line. instance_variable_set('@args', %w{--terminus foo save}) # Not a very nice thing. :( $stderr.stubs(:puts) expect { subject.run }.should raise_error SystemExit end end diff --git a/spec/unit/string/indirector_spec.rb b/spec/unit/string/indirector_spec.rb index da5f569dc..29e8e7086 100755 --- a/spec/unit/string/indirector_spec.rb +++ b/spec/unit/string/indirector_spec.rb @@ -1,55 +1,56 @@ #!/usr/bin/env ruby require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb') require 'puppet/string/indirector' describe Puppet::String::Indirector do - before do - @instance = Puppet::String::Indirector.new(:test, '0.0.1') - - @indirection = stub 'indirection', :name => :stub_indirection - - @instance.stubs(:indirection).returns @indirection + subject do + instance = Puppet::String::Indirector.new(:test, '0.0.1') + indirection = stub('indirection', + :name => :stub_indirection, + :reset_terminus_class => nil) + instance.stubs(:indirection).returns indirection + instance end it "should be able to return a list of indirections" do Puppet::String::Indirector.indirections.should be_include("catalog") end it "should be able to return a list of terminuses for a given indirection" do Puppet::String::Indirector.terminus_classes(:catalog).should be_include("compiler") end describe "as an instance" do it "should be able to determine its indirection" do # Loading actions here an get, um, complicated Puppet::String.stubs(:load_actions) Puppet::String::Indirector.new(:catalog, '0.0.1').indirection.should equal(Puppet::Resource::Catalog.indirection) end end [:find, :search, :save, :destroy].each do |method| it "should define a '#{method}' action" do Puppet::String::Indirector.should be_action(method) end it "should call the indirection method when the '#{method}' action is invoked" do - @instance.indirection.expects(method).with(:test, "myargs", {}) - @instance.send(method, :test, "myargs") + subject.indirection.expects(method).with(:test, "myargs") + subject.send(method, :test, "myargs") end end it "should be able to override its indirection name" do @instance.set_indirection_name :foo @instance.indirection_name.should == :foo end it "should be able to set its terminus class" do @instance.indirection.expects(:terminus_class=).with(:myterm) @instance.set_terminus(:myterm) end it "should define a class-level 'info' action" do Puppet::String::Indirector.should be_action(:info) end end