summaryrefslogtreecommitdiffstats
path: root/spec/unit/agent.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/unit/agent.rb')
-rwxr-xr-xspec/unit/agent.rb407
1 files changed, 176 insertions, 231 deletions
diff --git a/spec/unit/agent.rb b/spec/unit/agent.rb
index c4f5793d2..5622af4a6 100755
--- a/spec/unit/agent.rb
+++ b/spec/unit/agent.rb
@@ -6,255 +6,200 @@
require File.dirname(__FILE__) + '/../spec_helper'
require 'puppet/agent'
-describe Puppet::Agent do
- it "should include the Plugin Handler module" do
- Puppet::Agent.ancestors.should be_include(Puppet::Agent::PluginHandler)
+class AgentTestClient
+ def run
+ # no-op
end
-
- it "should include the Fact Handler module" do
- Puppet::Agent.ancestors.should be_include(Puppet::Agent::FactHandler)
- end
-
- it "should include the Locker module" do
- Puppet::Agent.ancestors.should be_include(Puppet::Agent::Locker)
+ def stop
+ # no-op
end
end
-describe Puppet::Agent, "when executing a catalog run" do
+describe Puppet::Agent do
before do
- Puppet.settings.stubs(:use).returns(true)
- @agent = Puppet::Agent.new
- @agent.stubs(:splay)
- @agent.stubs(:lock).yields.then.returns true
- end
+ @agent = Puppet::Agent.new(AgentTestClient)
- it "should splay" do
- Puppet::Util.sync(:puppetrun).stubs(:synchronize)
- @agent.expects(:splay)
- @agent.run
+ # So we don't actually try to hit the filesystem.
+ @agent.stubs(:lock).yields
end
- it "should use a global mutex to make sure no other thread is executing the catalog" do
- sync = mock 'sync'
- Puppet::Util.expects(:sync).with(:puppetrun).returns sync
-
- sync.expects(:synchronize)
-
- @agent.expects(:retrieve_config).never # i.e., if we don't yield, we don't retrieve the config
- @agent.run
+ it "should set its client class at initialization" do
+ Puppet::Agent.new("foo").client_class.should == "foo"
end
- it "should retrieve the catalog if a lock is attained" do
- @agent.expects(:lock).yields.then.returns true
-
- @agent.expects(:retrieve_catalog)
-
- @agent.run
- end
-
- it "should log and do nothing if the lock cannot be acquired" do
- @agent.expects(:lock).returns false
-
- @agent.expects(:retrieve_catalog).never
-
- Puppet.expects(:notice)
-
- @agent.run
- end
-
- it "should retrieve the catalog" do
- @agent.expects(:retrieve_catalog)
-
- @agent.run
+ it "should include the Locker module" do
+ Puppet::Agent.ancestors.should be_include(Puppet::Agent::Locker)
end
- it "should log a failure and do nothing if no catalog can be retrieved" do
- @agent.expects(:retrieve_catalog).returns nil
+ it "should create an instance of its client class and run it when asked to run" do
+ client = mock 'client'
+ AgentTestClient.expects(:new).returns client
- Puppet.expects(:err)
+ client.expects(:run)
@agent.run
end
- it "should apply the catalog with all options to :run" do
- catalog = stub 'catalog', :retrieval_duration= => nil
- @agent.expects(:retrieve_catalog).returns catalog
-
- catalog.expects(:apply).with(:one => true)
- @agent.run :one => true
+ it "should determine its lock file path by asking the client class" do
+ AgentTestClient.expects(:lockfile_path).returns "/my/lock"
+ @agent.lockfile_path.should == "/my/lock"
+ end
+
+ describe "when running" do
+ it "should splay" do
+ @agent.expects(:splay)
+
+ @agent.run
+ end
+
+ it "should do nothing if a client instance exists" do
+ @agent.expects(:client).returns "eh"
+ AgentTestClient.expects(:new).never
+ @agent.run
+ end
+
+ it "should do nothing if it is in the process of stopping" do
+ @agent.expects(:stopping?).returns true
+ AgentTestClient.expects(:new).never
+ @agent.run
+ end
+
+ it "should not fail if a client class instance cannot be created" do
+ AgentTestClient.expects(:new).raises "eh"
+ Puppet.expects(:err)
+ @agent.run
+ end
+
+ it "should not fail if there is an exception while running its client" do
+ client = AgentTestClient.new
+ AgentTestClient.expects(:new).returns client
+ client.expects(:run).raises "eh"
+ Puppet.expects(:err)
+ @agent.run
+ end
+
+ it "should use a mutex to restrict multi-threading" do
+ client = AgentTestClient.new
+ AgentTestClient.expects(:new).returns client
+
+ mutex = mock 'mutex'
+ @agent.expects(:sync).returns mutex
+
+ mutex.expects(:synchronize)
+ client.expects(:run).never # if it doesn't run, then we know our yield is what triggers it
+ @agent.run
+ end
+
+ it "should use a filesystem lock to restrict multiple processes running the agent" do
+ client = AgentTestClient.new
+ AgentTestClient.expects(:new).returns client
+
+ @agent.expects(:lock)
+
+ client.expects(:run).never # if it doesn't run, then we know our yield is what triggers it
+ @agent.run
+ end
+
+ it "should make its client instance available while running" do
+ client = AgentTestClient.new
+ AgentTestClient.expects(:new).returns client
+
+ client.expects(:run).with { @agent.client.should equal(client); true }
+ @agent.run
+ end
+ end
+
+ describe "when splaying" do
+ before do
+ Puppet.settings.stubs(:value).with(:splay).returns true
+ Puppet.settings.stubs(:value).with(:splaylimit).returns "10"
+ end
+
+ it "should do nothing if splay is disabled" do
+ Puppet.settings.expects(:value).returns false
+ @agent.expects(:sleep).never
+ @agent.splay
+ end
+
+ it "should do nothing if it has already splayed" do
+ @agent.expects(:splayed?).returns true
+ @agent.expects(:sleep).never
+ @agent.splay
+ end
+
+ it "should log that it is splaying" do
+ @agent.stubs :sleep
+ Puppet.expects :info
+ @agent.splay
+ end
+
+ it "should sleep for a random portion of the splaylimit plus 1" do
+ Puppet.settings.expects(:value).with(:splaylimit).returns "50"
+ @agent.expects(:rand).with(51).returns 10
+ @agent.expects(:sleep).with(10)
+ @agent.splay
+ end
+
+ it "should mark that it has splayed" do
+ @agent.stubs(:sleep)
+ @agent.splay
+ @agent.should be_splayed
+ end
end
- it "should benchmark how long it takes to apply the catalog" do
- @agent.expects(:benchmark).with(:notice, "Finished catalog run")
-
- catalog = stub 'catalog', :retrieval_duration= => nil
- @agent.expects(:retrieve_catalog).returns catalog
-
- catalog.expects(:apply).never # because we're not yielding
- @agent.run
- end
-
- it "should HUP itself if it should be restarted" do
- catalog = stub 'catalog', :retrieval_duration= => nil, :apply => nil
- @agent.expects(:retrieve_catalog).returns catalog
-
- Process.expects(:kill).with(:HUP, $$)
-
- @agent.expects(:restart?).returns true
-
- @agent.run
- end
-
- it "should not HUP itself if it should not be restarted" do
- catalog = stub 'catalog', :retrieval_duration= => nil, :apply => nil
- @agent.expects(:retrieve_catalog).returns catalog
-
- Process.expects(:kill).never
-
- @agent.expects(:restart?).returns false
-
- @agent.run
- end
-end
-
-describe Puppet::Agent, "when retrieving a catalog" do
- before do
- Puppet.settings.stubs(:use).returns(true)
- @agent = Puppet::Agent.new
-
- @catalog = Puppet::Resource::Catalog.new
-
- @agent.stubs(:convert_catalog).returns @catalog
- end
-
- it "should use the Catalog class to get its catalog" do
- Puppet::Resource::Catalog.expects(:find).returns @catalog
-
- @agent.retrieve_catalog
- end
-
- it "should use its Facter name to retrieve the catalog" do
- Facter.stubs(:value).returns "eh"
- Facter.expects(:value).with("hostname").returns "myhost"
- Puppet::Resource::Catalog.expects(:find).with { |name, options| name == "myhost" }.returns @catalog
-
- @agent.retrieve_catalog
- end
-
- it "should default to returning a catalog retrieved directly from the server, skipping the cache" do
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:use_cache] == false }.returns @catalog
-
- @agent.retrieve_catalog.should == @catalog
- end
-
- it "should return the cached catalog when no catalog can be retrieved from the server" do
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:use_cache] == false }.returns nil
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:use_cache] == true }.returns @catalog
-
- @agent.retrieve_catalog.should == @catalog
- end
-
- it "should not look in the cache for a catalog if one is returned from the server" do
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:use_cache] == false }.returns @catalog
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:use_cache] == true }.never
-
- @agent.retrieve_catalog.should == @catalog
- end
-
- it "should return the cached catalog when retrieving the remote catalog throws an exception" do
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:use_cache] == false }.raises "eh"
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:use_cache] == true }.returns @catalog
-
- @agent.retrieve_catalog.should == @catalog
- end
-
- it "should return nil if no cached catalog is available and no catalog can be retrieved from the server" do
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:use_cache] == false }.returns nil
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:use_cache] == true }.returns nil
-
- @agent.retrieve_catalog.should be_nil
- end
-
- it "should convert the catalog before returning" do
- Puppet::Resource::Catalog.stubs(:find).returns @catalog
-
- @agent.expects(:convert_catalog).with { |cat, dur| cat == @catalog }.returns "converted catalog"
- @agent.retrieve_catalog.should == "converted catalog"
- end
-
- it "should return nil if there is an error while retrieving the catalog" do
- Puppet::Resource::Catalog.expects(:find).raises "eh"
-
- @agent.retrieve_catalog.should be_nil
- end
-end
-
-describe Puppet::Agent, "when converting the catalog" do
- before do
- Puppet.settings.stubs(:use).returns(true)
- @agent = Puppet::Agent.new
-
- @catalog = Puppet::Resource::Catalog.new
- @oldcatalog = stub 'old_catalog', :to_ral => @catalog
- end
-
- it "should convert the catalog to a RAL-formed catalog" do
- @oldcatalog.expects(:to_ral).returns @catalog
-
- @agent.convert_catalog(@oldcatalog, 10).should equal(@catalog)
- end
-
- it "should record the passed retrieval time with the RAL catalog" do
- @catalog.expects(:retrieval_duration=).with 10
-
- @agent.convert_catalog(@oldcatalog, 10)
- end
-
- it "should write the RAL catalog's class file" do
- @catalog.expects(:write_class_file)
-
- @agent.convert_catalog(@oldcatalog, 10)
- end
-
- it "should mark the RAL catalog as a host catalog" do
- @catalog.expects(:host_config=).with true
-
- @agent.convert_catalog(@oldcatalog, 10)
- end
-end
-
-describe Puppet::Agent, "when preparing for a run" do
- before do
- Puppet.settings.stubs(:use).returns(true)
- @agent = Puppet::Agent.new
- @agent.stubs(:dostorage)
- @agent.stubs(:upload_facts)
- @facts = {"one" => "two", "three" => "four"}
- end
-
- it "should initialize the metadata store" do
- @agent.class.stubs(:facts).returns(@facts)
- @agent.expects(:dostorage)
- @agent.prepare
- end
-
- it "should download fact plugins" do
- @agent.stubs(:dostorage)
- @agent.expects(:download_fact_plugins)
-
- @agent.prepare
- end
-
- it "should download plugins" do
- @agent.stubs(:dostorage)
- @agent.expects(:download_plugins)
-
- @agent.prepare
- end
-
- it "should upload facts to use for catalog retrieval" do
- @agent.stubs(:dostorage)
- @agent.expects(:upload_facts)
- @agent.prepare
+ describe "when shutting down" do
+ it "should do nothing if already stopping" do
+ @agent.expects(:stopping?).returns true
+ @agent.shutdown
+ end
+
+ it "should stop the client if one is available and it responds to 'stop'" do
+ client = AgentTestClient.new
+
+ @agent.stubs(:client).returns client
+ client.expects(:stop)
+ @agent.shutdown
+ end
+
+ it "should remove its pid file" do
+ @agent.expects(:rmpidfile)
+ @agent.shutdown
+ end
+
+ it "should mark itself as stopping while waiting for the client to stop" do
+ client = AgentTestClient.new
+
+ @agent.stubs(:client).returns client
+ client.expects(:stop).with { @agent.should be_stopping; true }
+
+ @agent.shutdown
+ end
+ end
+
+ describe "when starting" do
+ it "should create a timer with the runinterval, a tolerance of 1, and :start? set to true" do
+ Puppet.settings.expects(:value).with(:runinterval).returns 5
+ Puppet.expects(:newtimer).with(:interval => 5, :start? => true, :tolerance => 1)
+ @agent.stubs(:run)
+ @agent.start
+ end
+
+ it "should run once immediately" do
+ Puppet.stubs(:newtimer)
+ @agent.expects(:run)
+ @agent.start
+ end
+
+ it "should run within the block passed to the timer" do
+ Puppet.stubs(:newtimer).yields
+ @agent.expects(:run).times(2)
+ @agent.start
+ end
+
+ it "should run within the block passed to the timer" do
+ Puppet.stubs(:newtimer).yields
+ @agent.expects(:run).times(2)
+ @agent.start
+ end
end
end