From 0dfae1217412b8d31ab3a325f5c99c30184f7103 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Mon, 8 Mar 2010 22:53:03 -0800 Subject: [PATCH] Adding a remote_resource type and provider The provider is a shell provider, so very simple but sufficient for some cases. Signed-off-by: Luke Kanies --- lib/puppet/provider/remote_resource/shell.rb | 13 ++++ lib/puppet/type/remote_resource.rb | 50 +++++++++++++ spec/unit/provider/remote_resource/shell.rb | 22 ++++++ spec/unit/type/remote_resource.rb | 79 ++++++++++++++++++++ 4 files changed, 164 insertions(+) create mode 100644 lib/puppet/provider/remote_resource/shell.rb create mode 100644 lib/puppet/type/remote_resource.rb create mode 100644 spec/unit/provider/remote_resource/shell.rb create mode 100644 spec/unit/type/remote_resource.rb diff --git a/lib/puppet/provider/remote_resource/shell.rb b/lib/puppet/provider/remote_resource/shell.rb new file mode 100644 index 0000000..e42925b --- /dev/null +++ b/lib/puppet/provider/remote_resource/shell.rb @@ -0,0 +1,13 @@ +require 'puppet/util' + +Puppet::Type.type(:remote_resource).provide(:shell) do + desc "Check the state of a remote resource using a shell script. + If the script exits with a non-zero code, the resource is considered + to not be up." + + include Puppet::Util + + def perform_check(command) + execute([command]) + end +end diff --git a/lib/puppet/type/remote_resource.rb b/lib/puppet/type/remote_resource.rb new file mode 100644 index 0000000..eab5cca --- /dev/null +++ b/lib/puppet/type/remote_resource.rb @@ -0,0 +1,50 @@ +Puppet::Type.newtype(:remote_resource) do + newparam(:name) do + desc "The name of the remote resource." + end + + newparam(:frequency) do + desc "How often the check should be executed, in seconds." + defaultto 10 + + munge { |i| Integer(i) } + end + + newparam(:check) do + desc "The check to perform. Usage and specifics are determined + by the provider." + end + + newparam(:timeout) do + desc "How long the resource should wait for the remote resource + to come up, in seconds." + + defaultto 300 + + munge { |i| Integer(i) } + end + + def retrieve + start = Time.now + while true + return {} if remote_resource_up? + if Time.now - start > self[:timeout] + fail "Remote resource not up within timeout #{self[:timeout]}" + end + + info "Remote resource is not up; delaying for #{self[:frequency]} seconds before next check" + sleep self[:frequency] + end + end + + private + + def remote_resource_up? + begin + provider.perform_check(self[:check]) + return true + rescue Puppet::ExecutionFailure + return false + end + end +end diff --git a/spec/unit/provider/remote_resource/shell.rb b/spec/unit/provider/remote_resource/shell.rb new file mode 100644 index 0000000..1858109 --- /dev/null +++ b/spec/unit/provider/remote_resource/shell.rb @@ -0,0 +1,22 @@ +Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") } + +describe Puppet::Type.type(:remote_resource).provider(:shell) do + before do + @resource = stub 'resource' + @provider = Puppet::Type.type(:remote_resource).provider(:shell).new(@resource) + end + + it "should exist" do + @provider.should_not be_nil + end + + it "should execute the provided shell command within an array" do + @provider.expects(:execute).with(["/my/cmd"]) + @provider.perform_check("/my/cmd") + end + + it "should pass on any encountered errors" do + @provider.expects(:execute).with(["/my/cmd"]).raises Puppet::ExecutionFailure.new("foo") + lambda { @provider.perform_check("/my/cmd") }.should raise_error(Puppet::ExecutionFailure) + end +end diff --git a/spec/unit/type/remote_resource.rb b/spec/unit/type/remote_resource.rb new file mode 100644 index 0000000..fef6a78 --- /dev/null +++ b/spec/unit/type/remote_resource.rb @@ -0,0 +1,79 @@ +Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") } + +describe Puppet::Type.type(:remote_resource) do + before do + @type = Puppet::Type.type(:remote_resource) + end + + it "should exist" do + @type.should_not be_nil + end + + it "should have a default provider" do + @type.defaultprovider.should_not be_nil + end + + describe "the name parameter" do + it "should exist" do + @type.attrclass(:name).should_not be_nil + end + end + + describe "the 'frequency' parameter" do + it "should exist" do + @type.attrclass(:frequency).should_not be_nil + end + + it "should convert values to integers" do + @type.new(:name => "foo", :frequency => "50")[:frequency].should == 50 + end + + it "should default to '10'" do + @type.new(:name => "foo")[:frequency].should == 10 + end + end + + describe "the 'timeout' parameter" do + it "should exist" do + @type.attrclass(:timeout).should_not be_nil + end + + it "should convert values to integers" do + @type.new(:name => "foo", :timeout => "10")[:timeout].should == 10 + end + + it "should default to '300'" do + @type.new(:name => "foo")[:timeout].should == 300 + end + end + + describe "when retrieving" do + before do + @resource = @type.new(:name => "foo", :check => "/bin/true") + end + + it "should perform_check the check with the provider" do + @resource.provider.expects(:perform_check).with("/bin/true") + @resource.retrieve + end + + it "should return '{}' if the check passes" do + @resource.provider.expects(:perform_check) + @resource.retrieve.should == {} + end + + it "should sleep for the specified frequency and check again if the check fails" do + @resource.provider.expects(:perform_check).times(2).raises(Puppet::ExecutionFailure.new("foo")).then.returns true + @resource.expects(:sleep).with(@resource[:frequency]) + @resource.retrieve.should == {} + end + + it "should fail if the check has not passed within the timeout" do + @resource[:timeout] = 1 + @resource[:frequency] = 1 + @resource.provider.stubs(:perform_check).raises(Puppet::ExecutionFailure.new("foo")) + @resource.stubs(:sleep).with(@resource[:frequency]) + lambda { @resource.retrieve }.should raise_error(Puppet::Error) + end + end +end