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:
Родитель
c7d178d04f
Коммит
08a5d492dd
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче