Adding an Agent::Runner class.

This will eventually be used by puppetrun, but
for now is just called by the old-school Runner handler.

Signed-off-by: Luke Kanies <luke@madstop.com>
This commit is contained in:
Luke Kanies 2009-02-06 17:27:44 -06:00
Родитель c7d178d04f
Коммит 08a5d492dd
8 изменённых файлов: 220 добавлений и 100 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -1,4 +1,4 @@
require 'puppet/agent'
require 'puppet/configurer'
require 'puppet/resource/catalog'
class Puppet::Configurer::Downloader

Просмотреть файл

@ -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

Просмотреть файл

@ -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
options = {}
options[:tags] = tags if tags
options[:ignoreschedules] = ignoreschedules if ignoreschedules
options[:background] = !fg
unless master
raise MissingMasterError, "Could not find the master client"
end
runner = Puppet::Agent::Runner.new(options)
if Puppet::Util::Pidlock.new(Puppet[:puppetdlockfile]).locked?
Puppet.notice "Could not trigger run; already running"
return "running"
end
runner.run
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
Puppet.notice msg
# 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
return "success"
return runner.status
end
end
end

118
spec/unit/agent/runner.rb Executable file
Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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