summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/puppet/agent.rb2
-rw-r--r--lib/puppet/agent/runner.rb65
-rw-r--r--lib/puppet/configurer/downloader.rb2
-rw-r--r--lib/puppet/indirector/runner/rest.rb7
-rwxr-xr-xlib/puppet/network/handler/runner.rb51
-rwxr-xr-xspec/unit/agent/runner.rb118
-rwxr-xr-xspec/unit/indirector/runner/rest.rb11
-rwxr-xr-xtest/network/handler/runner.rb64
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