diff options
-rw-r--r-- | lib/puppet/agent.rb | 2 | ||||
-rw-r--r-- | lib/puppet/agent/runner.rb | 65 | ||||
-rw-r--r-- | lib/puppet/configurer/downloader.rb | 2 | ||||
-rw-r--r-- | lib/puppet/indirector/runner/rest.rb | 7 | ||||
-rwxr-xr-x | lib/puppet/network/handler/runner.rb | 51 | ||||
-rwxr-xr-x | spec/unit/agent/runner.rb | 118 | ||||
-rwxr-xr-x | spec/unit/indirector/runner/rest.rb | 11 | ||||
-rwxr-xr-x | test/network/handler/runner.rb | 64 |
8 files changed, 220 insertions, 100 deletions
diff --git a/lib/puppet/agent.rb b/lib/puppet/agent.rb index 438b668a6..3add43ec1 100644 --- a/lib/puppet/agent.rb +++ b/lib/puppet/agent.rb @@ -7,6 +7,8 @@ class Puppet::Agent require 'puppet/agent/locker' include Puppet::Agent::Locker + require 'puppet/agent/runner' + attr_reader :client_class, :client, :needing_restart, :splayed attr_accessor :stopping diff --git a/lib/puppet/agent/runner.rb b/lib/puppet/agent/runner.rb new file mode 100644 index 000000000..705b6c269 --- /dev/null +++ b/lib/puppet/agent/runner.rb @@ -0,0 +1,65 @@ +require 'puppet/agent' +require 'puppet/configurer' +require 'puppet/indirector' + +# A basic class for running the agent. Used by +# puppetrun to kick off agents remotely. +class Puppet::Agent::Runner + extend Puppet::Indirector + indirects :runner, :terminus_class => :rest + + attr_reader :status, :background, :options + + def agent + Puppet::Agent.new(Puppet::Configurer) + end + + def background? + background + end + + def initialize(options = {}) + if options.include?(:background) + @background = options[:background] + options.delete(:background) + end + + valid_options = [:tags, :ignoreschedules] + options.each do |key, value| + raise ArgumentError, "Runner does not accept %s" % key unless valid_options.include?(key) + end + + @options = options + end + + def log_run + msg = "" + msg += "triggered run" % + if options[:tags] + msg += " with tags %s" % options[:tags] + end + + if options[:ignoreschedules] + msg += " ignoring schedules" + end + + Puppet.notice msg + end + + def run + if agent.running? + @status = "running" + return + end + + log_run() + + if background? + Thread.new { agent.run(options) } + else + agent.run(options) + end + + @status = "success" + end +end diff --git a/lib/puppet/configurer/downloader.rb b/lib/puppet/configurer/downloader.rb index f1c4c03b1..89af0233e 100644 --- a/lib/puppet/configurer/downloader.rb +++ b/lib/puppet/configurer/downloader.rb @@ -1,4 +1,4 @@ -require 'puppet/agent' +require 'puppet/configurer' require 'puppet/resource/catalog' class Puppet::Configurer::Downloader diff --git a/lib/puppet/indirector/runner/rest.rb b/lib/puppet/indirector/runner/rest.rb new file mode 100644 index 000000000..25d3def3f --- /dev/null +++ b/lib/puppet/indirector/runner/rest.rb @@ -0,0 +1,7 @@ +require 'puppet/agent' +require 'puppet/agent/runner' +require 'puppet/indirector/rest' + +class Puppet::Agent::Runner::Rest < Puppet::Indirector::REST + desc "Trigger Agent runs via REST." +end diff --git a/lib/puppet/network/handler/runner.rb b/lib/puppet/network/handler/runner.rb index c97e4791a..070cae114 100755 --- a/lib/puppet/network/handler/runner.rb +++ b/lib/puppet/network/handler/runner.rb @@ -1,3 +1,5 @@ +require 'puppet/agent/runner' + class Puppet::Network::Handler class MissingMasterError < RuntimeError; end # Cannot find the master client # A simple server for triggering a new run on a Puppet client. @@ -13,51 +15,16 @@ class Puppet::Network::Handler # Run the client configuration right now, optionally specifying # tags and whether to ignore schedules def run(tags = nil, ignoreschedules = false, fg = true, client = nil, clientip = nil) - # We need to retrieve the client - master = Puppet::Network::Client.client(:Master).instance - - unless master - raise MissingMasterError, "Could not find the master client" - end - - if Puppet::Util::Pidlock.new(Puppet[:puppetdlockfile]).locked? - Puppet.notice "Could not trigger run; already running" - return "running" - end - - if tags == "" - tags = nil - end - - if ignoreschedules == "" - ignoreschedules == nil - end - - msg = "" - if client - msg = "%s(%s) " % [client, clientip] - end - msg += "triggered run" % - if tags - msg += " with tags %s" % tags - end - - if ignoreschedules - msg += " ignoring schedules" - end + options = {} + options[:tags] = tags if tags + options[:ignoreschedules] = ignoreschedules if ignoreschedules + options[:background] = !fg - Puppet.notice msg + runner = Puppet::Agent::Runner.new(options) - # And then we need to tell it to run, with this extra info. - if fg - master.run(:tags => tags, :ignoreschedules => ignoreschedules) - else - Puppet.newthread do - master.run(:tags => tags, :ignoreschedules => ignoreschedules) - end - end + runner.run - return "success" + return runner.status end end end diff --git a/spec/unit/agent/runner.rb b/spec/unit/agent/runner.rb new file mode 100755 index 000000000..dfd267a5f --- /dev/null +++ b/spec/unit/agent/runner.rb @@ -0,0 +1,118 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../spec_helper' +require 'puppet/agent' +require 'puppet/agent/runner' + +describe Puppet::Agent::Runner do + before do + @runner = Puppet::Agent::Runner.new + end + + it "should indirect :runner" do + Puppet::Agent::Runner.indirection.name.should == :runner + end + + it "should use a configurer agent as its agent" do + agent = mock 'agent' + Puppet::Agent.expects(:new).with(Puppet::Configurer).returns agent + + @runner.agent.should equal(agent) + end + + it "should accept options at initialization" do + lambda { Puppet::Agent::Runner.new :background => true }.should_not raise_error + end + + it "should default to running in the foreground" do + Puppet::Agent::Runner.new.should_not be_background + end + + it "should default to its options being an empty hash" do + Puppet::Agent::Runner.new.options.should == {} + end + + it "should accept :tags for the agent" do + Puppet::Agent::Runner.new(:tags => "foo").options[:tags].should == "foo" + end + + it "should accept :ignoreschedules for the agent" do + Puppet::Agent::Runner.new(:ignoreschedules => true).options[:ignoreschedules].should be_true + end + + it "should accept an option to configure it to run in the background" do + Puppet::Agent::Runner.new(:background => true).should be_background + end + + it "should retain the background option" do + Puppet::Agent::Runner.new(:background => true).options[:background].should be_nil + end + + it "should not accept arbitrary options" do + lambda { Puppet::Agent::Runner.new(:foo => true) }.should raise_error(ArgumentError) + end + + describe "when asked to run" do + before do + @agent = stub 'agent', :run => nil, :running? => false + @runner.stubs(:agent).returns @agent + end + + it "should run its agent" do + agent = stub 'agent2', :running? => false + @runner.stubs(:agent).returns agent + + agent.expects(:run) + + @runner.run + end + + it "should pass any of its options on to the agent" do + @runner.stubs(:options).returns(:foo => :bar) + @agent.expects(:run).with(:foo => :bar) + + @runner.run + end + + it "should log its run using the provided options" do + @runner.expects(:log_run) + + @runner.run + end + + it "should set its status to 'already_running' if the agent is already running" do + @agent.expects(:running?).returns true + + @runner.run + + @runner.status.should == "running" + end + + it "should set its status to 'success' if the agent is run" do + @agent.expects(:running?).returns false + + @runner.run + + @runner.status.should == "success" + end + + it "should run the agent in a thread if asked to run it in the background" do + Thread.expects(:new) + + @runner.expects(:background?).returns true + + @agent.expects(:run).never # because our thread didn't yield + + @runner.run + end + + it "should run the agent directly if asked to run it in the foreground" do + Thread.expects(:new).never + + @runner.expects(:background?).returns false + @agent.expects(:run) + + @runner.run + end + end +end diff --git a/spec/unit/indirector/runner/rest.rb b/spec/unit/indirector/runner/rest.rb new file mode 100755 index 000000000..61457175d --- /dev/null +++ b/spec/unit/indirector/runner/rest.rb @@ -0,0 +1,11 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +require 'puppet/indirector/runner/rest' + +describe Puppet::Agent::Runner::Rest do + it "should be a sublcass of Puppet::Indirector::REST" do + Puppet::Agent::Runner::Rest.superclass.should equal(Puppet::Indirector::REST) + end +end diff --git a/test/network/handler/runner.rb b/test/network/handler/runner.rb index 171458ffa..71d86fd9d 100755 --- a/test/network/handler/runner.rb +++ b/test/network/handler/runner.rb @@ -3,68 +3,18 @@ require File.dirname(__FILE__) + '/../../lib/puppettest' require 'puppettest' +require 'puppet/network/handler/runner' class TestHandlerRunner < Test::Unit::TestCase include PuppetTest - def mkclient(code) - master = nil - client = nil - Puppet[:code] = code - # create our master - assert_nothing_raised() { - # this is the default server setup - master = Puppet::Network::Handler.master.new( - :Local => true - ) - } + def test_it_calls_agent_runner + runner = mock 'runner' + Puppet::Agent::Runner.expects(:new).with(:tags => "mytags", :ignoreschedules => true, :background => false).returns runner + runner.expects(:run) + runner.expects(:status).returns "yay" - # and our client - assert_nothing_raised() { - client = Puppet::Network::Client.master.new( - :Master => master - ) - } - client - end - - def setup - super - FileUtils.mkdir_p(Puppet[:statedir]) - Puppet[:ignoreschedules] = false - # Okay, make our manifest - file = tempfile() - created = tempfile() - # We specify the schedule here, because I was having problems with - # using default schedules. - @code = %{ - class yayness { - schedule { "yayness": period => weekly } - file { "#{created}": ensure => file, schedule => yayness } - } - - include yayness - } - - @client = mkclient(@code) - - @runner = Puppet::Network::Handler.runner.new - end - - def test_runner_when_in_foreground - @client.expects(:run).with(:tags => "mytags", :ignoreschedules => true) - - Process.expects(:newthread).never - - @runner.run("mytags", true, true) - end - - def test_runner_when_in_background - @client.expects(:run).with(:tags => "mytags", :ignoreschedules => true) - - Puppet.expects(:newthread).yields - - @runner.run("mytags", true, false) + assert_equal("yay", Puppet::Network::Handler.runner.new.run("mytags", true, true)) end end |