From 422dea05e755f0026c7786b46a7e93624da1ac0a Mon Sep 17 00:00:00 2001 From: Andrew Shafer Date: Mon, 16 Jun 2008 02:05:38 -0600 Subject: issue 1183 Added environment awareness to --configprint Pulled the logic for --configprint --genconfig and --genmanifest out of puppet.rb Put the logic in lib/puppet/util/settings.rb and refactored it a bit Added specs for the behavior Reformated the whole spec file to use nested describe Added the new method to the executables The old behavior should be preserved, except for the env is now used --- spec/unit/util/settings.rb | 1286 ++++++++++++++++++++++++-------------------- 1 file changed, 701 insertions(+), 585 deletions(-) (limited to 'spec/unit') diff --git a/spec/unit/util/settings.rb b/spec/unit/util/settings.rb index a6b358462..de6d6457c 100755 --- a/spec/unit/util/settings.rb +++ b/spec/unit/util/settings.rb @@ -2,705 +2,821 @@ require File.dirname(__FILE__) + '/../../spec_helper' -describe Puppet::Util::Settings, " when specifying defaults" do - before do - @settings = Puppet::Util::Settings.new - end +describe Puppet::Util::Settings do + describe "when specifying defaults" do + before do + @settings = Puppet::Util::Settings.new + end - it "should start with no defined parameters" do - @settings.params.length.should == 0 - end + it "should start with no defined parameters" do + @settings.params.length.should == 0 + end - it "should allow specification of default values associated with a section as an array" do - @settings.setdefaults(:section, :myvalue => ["defaultval", "my description"]) - end + it "should allow specification of default values associated with a section as an array" do + @settings.setdefaults(:section, :myvalue => ["defaultval", "my description"]) + end - it "should not allow duplicate parameter specifications" do - @settings.setdefaults(:section, :myvalue => ["a", "b"]) - lambda { @settings.setdefaults(:section, :myvalue => ["c", "d"]) }.should raise_error(ArgumentError) - end + it "should not allow duplicate parameter specifications" do + @settings.setdefaults(:section, :myvalue => ["a", "b"]) + lambda { @settings.setdefaults(:section, :myvalue => ["c", "d"]) }.should raise_error(ArgumentError) + end - it "should allow specification of default values associated with a section as a hash" do - @settings.setdefaults(:section, :myvalue => {:default => "defaultval", :desc => "my description"}) - end + it "should allow specification of default values associated with a section as a hash" do + @settings.setdefaults(:section, :myvalue => {:default => "defaultval", :desc => "my description"}) + end - it "should consider defined parameters to be valid" do - @settings.setdefaults(:section, :myvalue => ["defaultval", "my description"]) - @settings.valid?(:myvalue).should be_true - end + it "should consider defined parameters to be valid" do + @settings.setdefaults(:section, :myvalue => ["defaultval", "my description"]) + @settings.valid?(:myvalue).should be_true + end - it "should require a description when defaults are specified with an array" do - lambda { @settings.setdefaults(:section, :myvalue => ["a value"]) }.should raise_error(ArgumentError) - end + it "should require a description when defaults are specified with an array" do + lambda { @settings.setdefaults(:section, :myvalue => ["a value"]) }.should raise_error(ArgumentError) + end - it "should require a description when defaults are specified with a hash" do - lambda { @settings.setdefaults(:section, :myvalue => {:default => "a value"}) }.should raise_error(ArgumentError) - end + it "should require a description when defaults are specified with a hash" do + lambda { @settings.setdefaults(:section, :myvalue => {:default => "a value"}) }.should raise_error(ArgumentError) + end - it "should support specifying owner, group, and mode when specifying files" do - @settings.setdefaults(:section, :myvalue => {:default => "/some/file", :owner => "blah", :mode => "boo", :group => "yay", :desc => "whatever"}) - end + it "should support specifying owner, group, and mode when specifying files" do + @settings.setdefaults(:section, :myvalue => {:default => "/some/file", :owner => "blah", :mode => "boo", :group => "yay", :desc => "whatever"}) + end - it "should support specifying a short name" do - @settings.setdefaults(:section, :myvalue => {:default => "w", :desc => "b", :short => "m"}) - end + it "should support specifying a short name" do + @settings.setdefaults(:section, :myvalue => {:default => "w", :desc => "b", :short => "m"}) + end - it "should fail when short names conflict" do - @settings.setdefaults(:section, :myvalue => {:default => "w", :desc => "b", :short => "m"}) - lambda { @settings.setdefaults(:section, :myvalue => {:default => "w", :desc => "b", :short => "m"}) }.should raise_error(ArgumentError) + it "should fail when short names conflict" do + @settings.setdefaults(:section, :myvalue => {:default => "w", :desc => "b", :short => "m"}) + lambda { @settings.setdefaults(:section, :myvalue => {:default => "w", :desc => "b", :short => "m"}) }.should raise_error(ArgumentError) + end end -end -describe Puppet::Util::Settings, " when setting values" do - before do - @settings = Puppet::Util::Settings.new - @settings.setdefaults :main, :myval => ["val", "desc"] - @settings.setdefaults :main, :bool => [true, "desc"] - end + describe "when setting values" do + before do + @settings = Puppet::Util::Settings.new + @settings.setdefaults :main, :myval => ["val", "desc"] + @settings.setdefaults :main, :bool => [true, "desc"] + end - it "should provide a method for setting values from other objects" do - @settings[:myval] = "something else" - @settings[:myval].should == "something else" - end + it "should provide a method for setting values from other objects" do + @settings[:myval] = "something else" + @settings[:myval].should == "something else" + end - it "should support a getopt-specific mechanism for setting values" do - @settings.handlearg("--myval", "newval") - @settings[:myval].should == "newval" - end + it "should support a getopt-specific mechanism for setting values" do + @settings.handlearg("--myval", "newval") + @settings[:myval].should == "newval" + end - it "should support a getopt-specific mechanism for turning booleans off" do - @settings.handlearg("--no-bool") - @settings[:bool].should == false - end + it "should support a getopt-specific mechanism for turning booleans off" do + @settings.handlearg("--no-bool") + @settings[:bool].should == false + end - it "should support a getopt-specific mechanism for turning booleans on" do - # Turn it off first - @settings[:bool] = false - @settings.handlearg("--bool") - @settings[:bool].should == true - end + it "should support a getopt-specific mechanism for turning booleans on" do + # Turn it off first + @settings[:bool] = false + @settings.handlearg("--bool") + @settings[:bool].should == true + end - it "should clear the cache when setting getopt-specific values" do - @settings.setdefaults :mysection, :one => ["whah", "yay"], :two => ["$one yay", "bah"] - @settings[:two].should == "whah yay" - @settings.handlearg("--one", "else") - @settings[:two].should == "else yay" - end + it "should clear the cache when setting getopt-specific values" do + @settings.setdefaults :mysection, :one => ["whah", "yay"], :two => ["$one yay", "bah"] + @settings[:two].should == "whah yay" + @settings.handlearg("--one", "else") + @settings[:two].should == "else yay" + end - it "should not clear other values when setting getopt-specific values" do - @settings[:myval] = "yay" - @settings.handlearg("--no-bool") - @settings[:myval].should == "yay" - end + it "should not clear other values when setting getopt-specific values" do + @settings[:myval] = "yay" + @settings.handlearg("--no-bool") + @settings[:myval].should == "yay" + end - it "should call passed blocks when values are set" do - values = [] - @settings.setdefaults(:section, :hooker => {:default => "yay", :desc => "boo", :hook => lambda { |v| values << v }}) - values.should == [] + it "should call passed blocks when values are set" do + values = [] + @settings.setdefaults(:section, :hooker => {:default => "yay", :desc => "boo", :hook => lambda { |v| values << v }}) + values.should == [] - @settings[:hooker] = "something" - values.should == %w{something} - end + @settings[:hooker] = "something" + values.should == %w{something} + end - it "should provide an option to call passed blocks during definition" do - values = [] - @settings.setdefaults(:section, :hooker => {:default => "yay", :desc => "boo", :call_on_define => true, :hook => lambda { |v| values << v }}) - values.should == %w{yay} - end + it "should provide an option to call passed blocks during definition" do + values = [] + @settings.setdefaults(:section, :hooker => {:default => "yay", :desc => "boo", :call_on_define => true, :hook => lambda { |v| values << v }}) + values.should == %w{yay} + end - it "should pass the fully interpolated value to the hook when called on definition" do - values = [] - @settings.setdefaults(:section, :one => ["test", "a"]) - @settings.setdefaults(:section, :hooker => {:default => "$one/yay", :desc => "boo", :call_on_define => true, :hook => lambda { |v| values << v }}) - values.should == %w{test/yay} - end + it "should pass the fully interpolated value to the hook when called on definition" do + values = [] + @settings.setdefaults(:section, :one => ["test", "a"]) + @settings.setdefaults(:section, :hooker => {:default => "$one/yay", :desc => "boo", :call_on_define => true, :hook => lambda { |v| values << v }}) + values.should == %w{test/yay} + end - it "should munge values using the element-specific methods" do - @settings[:bool] = "false" - @settings[:bool].should == false - end + it "should munge values using the element-specific methods" do + @settings[:bool] = "false" + @settings[:bool].should == false + end - it "should prefer cli values to values set in Ruby code" do - @settings.handlearg("--myval", "cliarg") - @settings[:myval] = "memarg" - @settings[:myval].should == "cliarg" + it "should prefer cli values to values set in Ruby code" do + @settings.handlearg("--myval", "cliarg") + @settings[:myval] = "memarg" + @settings[:myval].should == "cliarg" + end end -end -describe Puppet::Util::Settings, " when returning values" do - before do - @settings = Puppet::Util::Settings.new - @settings.setdefaults :section, :one => ["ONE", "a"], :two => ["$one TWO", "b"], :three => ["$one $two THREE", "c"], :four => ["$two $three FOUR", "d"] - end + describe "when returning values" do + before do + @settings = Puppet::Util::Settings.new + @settings.setdefaults :section, :one => ["ONE", "a"], :two => ["$one TWO", "b"], :three => ["$one $two THREE", "c"], :four => ["$two $three FOUR", "d"] + end - it "should provide a mechanism for returning set values" do - @settings[:one] = "other" - @settings[:one].should == "other" - end + it "should provide a mechanism for returning set values" do + @settings[:one] = "other" + @settings[:one].should == "other" + end - it "should interpolate default values for other parameters into returned parameter values" do - @settings[:one].should == "ONE" - @settings[:two].should == "ONE TWO" - @settings[:three].should == "ONE ONE TWO THREE" - end + it "should interpolate default values for other parameters into returned parameter values" do + @settings[:one].should == "ONE" + @settings[:two].should == "ONE TWO" + @settings[:three].should == "ONE ONE TWO THREE" + end - it "should interpolate default values that themselves need to be interpolated" do - @settings[:four].should == "ONE TWO ONE ONE TWO THREE FOUR" - end + it "should interpolate default values that themselves need to be interpolated" do + @settings[:four].should == "ONE TWO ONE ONE TWO THREE FOUR" + end - it "should interpolate set values for other parameters into returned parameter values" do - @settings[:one] = "on3" - @settings[:two] = "$one tw0" - @settings[:three] = "$one $two thr33" - @settings[:four] = "$one $two $three f0ur" - @settings[:one].should == "on3" - @settings[:two].should == "on3 tw0" - @settings[:three].should == "on3 on3 tw0 thr33" - @settings[:four].should == "on3 on3 tw0 on3 on3 tw0 thr33 f0ur" - end + it "should interpolate set values for other parameters into returned parameter values" do + @settings[:one] = "on3" + @settings[:two] = "$one tw0" + @settings[:three] = "$one $two thr33" + @settings[:four] = "$one $two $three f0ur" + @settings[:one].should == "on3" + @settings[:two].should == "on3 tw0" + @settings[:three].should == "on3 on3 tw0 thr33" + @settings[:four].should == "on3 on3 tw0 on3 on3 tw0 thr33 f0ur" + end - it "should not cache interpolated values such that stale information is returned" do - @settings[:two].should == "ONE TWO" - @settings[:one] = "one" - @settings[:two].should == "one TWO" - end + it "should not cache interpolated values such that stale information is returned" do + @settings[:two].should == "ONE TWO" + @settings[:one] = "one" + @settings[:two].should == "one TWO" + end - it "should not cache values such that information from one environment is returned for another environment" do - text = "[env1]\none = oneval\n[env2]\none = twoval\n" - file = mock 'file' - file.stubs(:changed?).returns(true) - file.stubs(:file).returns("/whatever") - @settings.stubs(:read_file).with(file).returns(text) - @settings.parse(file) + it "should not cache values such that information from one environment is returned for another environment" do + text = "[env1]\none = oneval\n[env2]\none = twoval\n" + file = mock 'file' + file.stubs(:changed?).returns(true) + file.stubs(:file).returns("/whatever") + @settings.stubs(:read_file).with(file).returns(text) + @settings.parse(file) - @settings.value(:one, "env1").should == "oneval" - @settings.value(:one, "env2").should == "twoval" - end + @settings.value(:one, "env1").should == "oneval" + @settings.value(:one, "env2").should == "twoval" + end - it "should have a name determined by the 'name' parameter" do - @settings.setdefaults(:whatever, :name => ["something", "yayness"]) - @settings.name.should == :something - @settings[:name] = :other - @settings.name.should == :other + it "should have a name determined by the 'name' parameter" do + @settings.setdefaults(:whatever, :name => ["something", "yayness"]) + @settings.name.should == :something + @settings[:name] = :other + @settings.name.should == :other + end end -end -describe Puppet::Util::Settings, " when choosing which value to return" do - before do - @settings = Puppet::Util::Settings.new - @settings.setdefaults :section, - :one => ["ONE", "a"], - :name => ["myname", "w"] - end + describe "when choosing which value to return" do + before do + @settings = Puppet::Util::Settings.new + @settings.setdefaults :section, + :one => ["ONE", "a"], + :name => ["myname", "w"] + end - it "should return default values if no values have been set" do - @settings[:one].should == "ONE" - end + it "should return default values if no values have been set" do + @settings[:one].should == "ONE" + end - it "should return values set on the cli before values set in the configuration file" do - text = "[main]\none = fileval\n" - file = mock 'file' - file.stubs(:changed?).returns(true) - file.stubs(:file).returns("/whatever") - @settings.stubs(:parse_file).returns(text) - @settings.handlearg("--one", "clival") - @settings.parse(file) + it "should return values set on the cli before values set in the configuration file" do + text = "[main]\none = fileval\n" + file = mock 'file' + file.stubs(:changed?).returns(true) + file.stubs(:file).returns("/whatever") + @settings.stubs(:parse_file).returns(text) + @settings.handlearg("--one", "clival") + @settings.parse(file) - @settings[:one].should == "clival" - end + @settings[:one].should == "clival" + end - it "should return values set on the cli before values set in Ruby" do - @settings[:one] = "rubyval" - @settings.handlearg("--one", "clival") - @settings[:one].should == "clival" - end + it "should return values set on the cli before values set in Ruby" do + @settings[:one] = "rubyval" + @settings.handlearg("--one", "clival") + @settings[:one].should == "clival" + end - it "should return values set in the executable-specific section before values set in the main section" do - text = "[main]\none = mainval\n[myname]\none = nameval\n" - file = mock 'file' - file.stubs(:changed?).returns(true) - file.stubs(:file).returns("/whatever") - @settings.stubs(:read_file).with(file).returns(text) - @settings.parse(file) + it "should return values set in the executable-specific section before values set in the main section" do + text = "[main]\none = mainval\n[myname]\none = nameval\n" + file = mock 'file' + file.stubs(:changed?).returns(true) + file.stubs(:file).returns("/whatever") + @settings.stubs(:read_file).with(file).returns(text) + @settings.parse(file) - @settings[:one].should == "nameval" - end + @settings[:one].should == "nameval" + end - it "should not return values outside of its search path" do - text = "[other]\none = oval\n" - file = "/some/file" - file = mock 'file' - file.stubs(:changed?).returns(true) - file.stubs(:file).returns("/whatever") - @settings.stubs(:read_file).with(file).returns(text) - @settings.parse(file) - @settings[:one].should == "ONE" - end + it "should not return values outside of its search path" do + text = "[other]\none = oval\n" + file = "/some/file" + file = mock 'file' + file.stubs(:changed?).returns(true) + file.stubs(:file).returns("/whatever") + @settings.stubs(:read_file).with(file).returns(text) + @settings.parse(file) + @settings[:one].should == "ONE" + end - it "should return values in a specified environment" do - text = "[env]\none = envval\n" - file = "/some/file" - file = mock 'file' - file.stubs(:changed?).returns(true) - file.stubs(:file).returns("/whatever") - @settings.stubs(:read_file).with(file).returns(text) - @settings.parse(file) - @settings.value(:one, "env").should == "envval" - end + it "should return values in a specified environment" do + text = "[env]\none = envval\n" + file = "/some/file" + file = mock 'file' + file.stubs(:changed?).returns(true) + file.stubs(:file).returns("/whatever") + @settings.stubs(:read_file).with(file).returns(text) + @settings.parse(file) + @settings.value(:one, "env").should == "envval" + end - it "should return values in a specified environment before values in the main or name sections" do - text = "[env]\none = envval\n[main]\none = mainval\n[myname]\none = nameval\n" - file = "/some/file" - file = mock 'file' - file.stubs(:changed?).returns(true) - file.stubs(:file).returns("/whatever") - @settings.stubs(:read_file).with(file).returns(text) - @settings.parse(file) - @settings.value(:one, "env").should == "envval" + it "should return values in a specified environment before values in the main or name sections" do + text = "[env]\none = envval\n[main]\none = mainval\n[myname]\none = nameval\n" + file = "/some/file" + file = mock 'file' + file.stubs(:changed?).returns(true) + file.stubs(:file).returns("/whatever") + @settings.stubs(:read_file).with(file).returns(text) + @settings.parse(file) + @settings.value(:one, "env").should == "envval" + end end -end -describe Puppet::Util::Settings, " when parsing its configuration" do - before do - @settings = Puppet::Util::Settings.new - @settings.setdefaults :section, :one => ["ONE", "a"], :two => ["$one TWO", "b"], :three => ["$one $two THREE", "c"] - end + describe "when parsing its configuration" do + before do + @settings = Puppet::Util::Settings.new + @settings.setdefaults :section, :one => ["ONE", "a"], :two => ["$one TWO", "b"], :three => ["$one $two THREE", "c"] + end - it "should return values set in the configuration file" do - text = "[main] - one = fileval - " - file = "/some/file" - @settings.expects(:read_file).with(file).returns(text) - @settings.parse(file) - @settings[:one].should == "fileval" - end + it "should return values set in the configuration file" do + text = "[main] + one = fileval + " + file = "/some/file" + @settings.expects(:read_file).with(file).returns(text) + @settings.parse(file) + @settings[:one].should == "fileval" + end - #484 - this should probably be in the regression area - it "should not throw an exception on unknown parameters" do - text = "[main]\nnosuchparam = mval\n" - file = "/some/file" - @settings.expects(:read_file).with(file).returns(text) - lambda { @settings.parse(file) }.should_not raise_error - end + #484 - this should probably be in the regression area + it "should not throw an exception on unknown parameters" do + text = "[main]\nnosuchparam = mval\n" + file = "/some/file" + @settings.expects(:read_file).with(file).returns(text) + lambda { @settings.parse(file) }.should_not raise_error + end - it "should support an old parse method when per-executable configuration files still exist" do - # I'm not going to bother testing this method. - @settings.should respond_to(:old_parse) - end + it "should support an old parse method when per-executable configuration files still exist" do + # I'm not going to bother testing this method. + @settings.should respond_to(:old_parse) + end - it "should convert booleans in the configuration file into Ruby booleans" do - text = "[main] - one = true - two = false - " - file = "/some/file" - @settings.expects(:read_file).with(file).returns(text) - @settings.parse(file) - @settings[:one].should == true - @settings[:two].should == false - end + it "should convert booleans in the configuration file into Ruby booleans" do + text = "[main] + one = true + two = false + " + file = "/some/file" + @settings.expects(:read_file).with(file).returns(text) + @settings.parse(file) + @settings[:one].should == true + @settings[:two].should == false + end - it "should convert integers in the configuration file into Ruby Integers" do - text = "[main] - one = 65 - " - file = "/some/file" - @settings.expects(:read_file).with(file).returns(text) - @settings.parse(file) - @settings[:one].should == 65 - end + it "should convert integers in the configuration file into Ruby Integers" do + text = "[main] + one = 65 + " + file = "/some/file" + @settings.expects(:read_file).with(file).returns(text) + @settings.parse(file) + @settings[:one].should == 65 + end - it "should support specifying all metadata (owner, group, mode) in the configuration file" do - @settings.setdefaults :section, :myfile => ["/myfile", "a"] - - text = "[main] - myfile = /other/file {owner = luke, group = luke, mode = 644} - " - file = "/some/file" - @settings.expects(:read_file).with(file).returns(text) - @settings.parse(file) - @settings[:myfile].should == "/other/file" - @settings.metadata(:myfile).should == {:owner => "luke", :group => "luke", :mode => "644"} - end + it "should support specifying all metadata (owner, group, mode) in the configuration file" do + @settings.setdefaults :section, :myfile => ["/myfile", "a"] + + text = "[main] + myfile = /other/file {owner = luke, group = luke, mode = 644} + " + file = "/some/file" + @settings.expects(:read_file).with(file).returns(text) + @settings.parse(file) + @settings[:myfile].should == "/other/file" + @settings.metadata(:myfile).should == {:owner => "luke", :group => "luke", :mode => "644"} + end - it "should support specifying a single piece of metadata (owner, group, or mode) in the configuration file" do - @settings.setdefaults :section, :myfile => ["/myfile", "a"] - - text = "[main] - myfile = /other/file {owner = luke} - " - file = "/some/file" - @settings.expects(:read_file).with(file).returns(text) - @settings.parse(file) - @settings[:myfile].should == "/other/file" - @settings.metadata(:myfile).should == {:owner => "luke"} - end + it "should support specifying a single piece of metadata (owner, group, or mode) in the configuration file" do + @settings.setdefaults :section, :myfile => ["/myfile", "a"] + + text = "[main] + myfile = /other/file {owner = luke} + " + file = "/some/file" + @settings.expects(:read_file).with(file).returns(text) + @settings.parse(file) + @settings[:myfile].should == "/other/file" + @settings.metadata(:myfile).should == {:owner => "luke"} + end - it "should call hooks associated with values set in the configuration file" do - values = [] - @settings.setdefaults :section, :mysetting => {:default => "defval", :desc => "a", :hook => proc { |v| values << v }} - - text = "[main] - mysetting = setval - " - file = "/some/file" - @settings.expects(:read_file).with(file).returns(text) - @settings.parse(file) - values.should == ["setval"] - end + it "should call hooks associated with values set in the configuration file" do + values = [] + @settings.setdefaults :section, :mysetting => {:default => "defval", :desc => "a", :hook => proc { |v| values << v }} + + text = "[main] + mysetting = setval + " + file = "/some/file" + @settings.expects(:read_file).with(file).returns(text) + @settings.parse(file) + values.should == ["setval"] + end - it "should not call the same hook for values set multiple times in the configuration file" do - values = [] - @settings.setdefaults :section, :mysetting => {:default => "defval", :desc => "a", :hook => proc { |v| values << v }} - - text = "[main] - mysetting = setval - [puppet] - mysetting = other - " - file = "/some/file" - @settings.expects(:read_file).with(file).returns(text) - @settings.parse(file) - values.should == ["setval"] - end + it "should not call the same hook for values set multiple times in the configuration file" do + values = [] + @settings.setdefaults :section, :mysetting => {:default => "defval", :desc => "a", :hook => proc { |v| values << v }} + + text = "[main] + mysetting = setval + [puppet] + mysetting = other + " + file = "/some/file" + @settings.expects(:read_file).with(file).returns(text) + @settings.parse(file) + values.should == ["setval"] + end - it "should pass the environment-specific value to the hook when one is available" do - values = [] - @settings.setdefaults :section, :mysetting => {:default => "defval", :desc => "a", :hook => proc { |v| values << v }} - @settings.setdefaults :section, :environment => ["yay", "a"] - @settings.setdefaults :section, :environments => ["yay,foo", "a"] - - text = "[main] - mysetting = setval - [yay] - mysetting = other - " - file = "/some/file" - @settings.expects(:read_file).with(file).returns(text) - @settings.parse(file) - values.should == ["other"] - end + it "should pass the environment-specific value to the hook when one is available" do + values = [] + @settings.setdefaults :section, :mysetting => {:default => "defval", :desc => "a", :hook => proc { |v| values << v }} + @settings.setdefaults :section, :environment => ["yay", "a"] + @settings.setdefaults :section, :environments => ["yay,foo", "a"] + + text = "[main] + mysetting = setval + [yay] + mysetting = other + " + file = "/some/file" + @settings.expects(:read_file).with(file).returns(text) + @settings.parse(file) + values.should == ["other"] + end - it "should pass the interpolated value to the hook when one is available" do - values = [] - @settings.setdefaults :section, :base => {:default => "yay", :desc => "a", :hook => proc { |v| values << v }} - @settings.setdefaults :section, :mysetting => {:default => "defval", :desc => "a", :hook => proc { |v| values << v }} - - text = "[main] - mysetting = $base/setval - " - file = "/some/file" - @settings.expects(:read_file).with(file).returns(text) - @settings.parse(file) - values.should == ["yay/setval"] - end + it "should pass the interpolated value to the hook when one is available" do + values = [] + @settings.setdefaults :section, :base => {:default => "yay", :desc => "a", :hook => proc { |v| values << v }} + @settings.setdefaults :section, :mysetting => {:default => "defval", :desc => "a", :hook => proc { |v| values << v }} + + text = "[main] + mysetting = $base/setval + " + file = "/some/file" + @settings.expects(:read_file).with(file).returns(text) + @settings.parse(file) + values.should == ["yay/setval"] + end - it "should allow empty values" do - @settings.setdefaults :section, :myarg => ["myfile", "a"] + it "should allow empty values" do + @settings.setdefaults :section, :myarg => ["myfile", "a"] - text = "[main] - myarg = - " - @settings.stubs(:read_file).returns(text) - @settings.parse("/some/file") - @settings[:myarg].should == "" + text = "[main] + myarg = + " + @settings.stubs(:read_file).returns(text) + @settings.parse("/some/file") + @settings[:myarg].should == "" + end end -end -describe Puppet::Util::Settings, " when reparsing its configuration" do - before do - @settings = Puppet::Util::Settings.new - @settings.setdefaults :section, :one => ["ONE", "a"], :two => ["$one TWO", "b"], :three => ["$one $two THREE", "c"] - end + describe "when reparsing its configuration" do + before do + @settings = Puppet::Util::Settings.new + @settings.setdefaults :section, :one => ["ONE", "a"], :two => ["$one TWO", "b"], :three => ["$one $two THREE", "c"] + end - it "should replace in-memory values with on-file values" do - # Init the value - text = "[main]\none = disk-init\n" - file = mock 'file' - file.stubs(:changed?).returns(true) - file.stubs(:file).returns("/test/file") - @settings[:one] = "init" - @settings.file = file - - # Now replace the value - text = "[main]\none = disk-replace\n" - - # This is kinda ridiculous - the reason it parses twice is that - # it goes to parse again when we ask for the value, because the - # mock always says it should get reparsed. - @settings.expects(:read_file).with(file).returns(text).times(2) - @settings.reparse - @settings[:one].should == "disk-replace" - end + it "should replace in-memory values with on-file values" do + # Init the value + text = "[main]\none = disk-init\n" + file = mock 'file' + file.stubs(:changed?).returns(true) + file.stubs(:file).returns("/test/file") + @settings[:one] = "init" + @settings.file = file + + # Now replace the value + text = "[main]\none = disk-replace\n" + + # This is kinda ridiculous - the reason it parses twice is that + # it goes to parse again when we ask for the value, because the + # mock always says it should get reparsed. + @settings.expects(:read_file).with(file).returns(text).times(2) + @settings.reparse + @settings[:one].should == "disk-replace" + end - it "should retain parameters set by cli when configuration files are reparsed" do - @settings.handlearg("--one", "clival") + it "should retain parameters set by cli when configuration files are reparsed" do + @settings.handlearg("--one", "clival") - text = "[main]\none = on-disk\n" - file = mock 'file' - file.stubs(:file).returns("/test/file") - @settings.stubs(:read_file).with(file).returns(text) - @settings.parse(file) + text = "[main]\none = on-disk\n" + file = mock 'file' + file.stubs(:file).returns("/test/file") + @settings.stubs(:read_file).with(file).returns(text) + @settings.parse(file) - @settings[:one].should == "clival" - end + @settings[:one].should == "clival" + end - it "should remove in-memory values that are no longer set in the file" do - # Init the value - text = "[main]\none = disk-init\n" - file = mock 'file' - file.stubs(:changed?).returns(true) - file.stubs(:file).returns("/test/file") - @settings.expects(:read_file).with(file).returns(text) - @settings.parse(file) - @settings[:one].should == "disk-init" - - # Now replace the value - text = "[main]\ntwo = disk-replace\n" - @settings.expects(:read_file).with(file).returns(text) - @settings.parse(file) - #@settings.reparse - - # The originally-overridden value should be replaced with the default - @settings[:one].should == "ONE" - - # and we should now have the new value in memory - @settings[:two].should == "disk-replace" + it "should remove in-memory values that are no longer set in the file" do + # Init the value + text = "[main]\none = disk-init\n" + file = mock 'file' + file.stubs(:changed?).returns(true) + file.stubs(:file).returns("/test/file") + @settings.expects(:read_file).with(file).returns(text) + @settings.parse(file) + @settings[:one].should == "disk-init" + + # Now replace the value + text = "[main]\ntwo = disk-replace\n" + @settings.expects(:read_file).with(file).returns(text) + @settings.parse(file) + #@settings.reparse + + # The originally-overridden value should be replaced with the default + @settings[:one].should == "ONE" + + # and we should now have the new value in memory + @settings[:two].should == "disk-replace" + end end -end -describe Puppet::Util::Settings, " when being used to manage the host machine" do - before do - @settings = Puppet::Util::Settings.new - @settings.setdefaults :main, :maindir => ["/maindir", "a"], :seconddir => ["/seconddir", "a"] - @settings.setdefaults :other, :otherdir => {:default => "/otherdir", :desc => "a", :owner => "luke", :group => "johnny", :mode => 0755} - @settings.setdefaults :third, :thirddir => ["/thirddir", "b"] - @settings.setdefaults :files, :myfile => {:default => "/myfile", :desc => "a", :mode => 0755} - end + describe "when being used to manage the host machine" do + before do + @settings = Puppet::Util::Settings.new + @settings.setdefaults :main, :maindir => ["/maindir", "a"], :seconddir => ["/seconddir", "a"] + @settings.setdefaults :other, :otherdir => {:default => "/otherdir", :desc => "a", :owner => "luke", :group => "johnny", :mode => 0755} + @settings.setdefaults :third, :thirddir => ["/thirddir", "b"] + @settings.setdefaults :files, :myfile => {:default => "/myfile", :desc => "a", :mode => 0755} + end - def stub_transaction - @bucket = mock 'bucket' - @config = mock 'config', :clear => nil - @trans = mock 'transaction' + def stub_transaction + @bucket = mock 'bucket' + @config = mock 'config', :clear => nil + @trans = mock 'transaction' - @settings.expects(:to_transportable).with(:whatever).returns(@bucket) - @bucket.expects(:to_catalog).returns(@config) - @config.expects(:apply).yields(@trans) - @config.stubs(:host_config=) - end + @settings.expects(:to_transportable).with(:whatever).returns(@bucket) + @bucket.expects(:to_catalog).returns(@config) + @config.expects(:apply).yields(@trans) + @config.stubs(:host_config=) + end - it "should provide a method that writes files with the correct modes" do - pending "Not converted from test/unit yet" - end + it "should provide a method that writes files with the correct modes" do + pending "Not converted from test/unit yet" + end - it "should provide a method that creates directories with the correct modes" do - Puppet::Util::SUIDManager.expects(:asuser).with("luke", "johnny").yields - Dir.expects(:mkdir).with("/otherdir", 0755) - @settings.mkdir(:otherdir) - end + it "should provide a method that creates directories with the correct modes" do + Puppet::Util::SUIDManager.expects(:asuser).with("luke", "johnny").yields + Dir.expects(:mkdir).with("/otherdir", 0755) + @settings.mkdir(:otherdir) + end - it "should be able to create needed directories in a single section" do - Dir.expects(:mkdir).with("/maindir") - Dir.expects(:mkdir).with("/seconddir") - @settings.use(:main) - end + it "should be able to create needed directories in a single section" do + Dir.expects(:mkdir).with("/maindir") + Dir.expects(:mkdir).with("/seconddir") + @settings.use(:main) + end - it "should be able to create needed directories in multiple sections" do - Dir.expects(:mkdir).with("/maindir") - Dir.expects(:mkdir).with("/seconddir") - Dir.expects(:mkdir).with("/thirddir") - @settings.use(:main, :third) - end + it "should be able to create needed directories in multiple sections" do + Dir.expects(:mkdir).with("/maindir") + Dir.expects(:mkdir).with("/seconddir") + Dir.expects(:mkdir).with("/thirddir") + @settings.use(:main, :third) + end - it "should provide a method to trigger enforcing of file modes on existing files and directories" do - pending "Not converted from test/unit yet" - end + it "should provide a method to trigger enforcing of file modes on existing files and directories" do + pending "Not converted from test/unit yet" + end - it "should provide a method to convert the file mode enforcement into a Puppet manifest" do - pending "Not converted from test/unit yet" - end + it "should provide a method to convert the file mode enforcement into a Puppet manifest" do + pending "Not converted from test/unit yet" + end - it "should create files when configured to do so with the :create parameter" - - it "should provide a method to convert the file mode enforcement into transportable resources" do - # Make it think we're root so it tries to manage user and group. - Puppet.features.stubs(:root?).returns(true) - File.stubs(:exist?).with("/myfile").returns(true) - trans = nil - trans = @settings.to_transportable - resources = [] - trans.delve { |obj| resources << obj if obj.is_a? Puppet::TransObject } - %w{/maindir /seconddir /otherdir /myfile}.each do |path| - obj = resources.find { |r| r.type == "file" and r.name == path } - if path.include?("dir") - obj[:ensure].should == :directory - else - # Do not create the file, just manage mode - obj[:ensure].should be_nil + it "should create files when configured to do so with the :create parameter" + + it "should provide a method to convert the file mode enforcement into transportable resources" do + # Make it think we're root so it tries to manage user and group. + Puppet.features.stubs(:root?).returns(true) + File.stubs(:exist?).with("/myfile").returns(true) + trans = nil + trans = @settings.to_transportable + resources = [] + trans.delve { |obj| resources << obj if obj.is_a? Puppet::TransObject } + %w{/maindir /seconddir /otherdir /myfile}.each do |path| + obj = resources.find { |r| r.type == "file" and r.name == path } + if path.include?("dir") + obj[:ensure].should == :directory + else + # Do not create the file, just manage mode + obj[:ensure].should be_nil + end + obj.should be_instance_of(Puppet::TransObject) + case path + when "/otherdir": + obj[:owner].should == "luke" + obj[:group].should == "johnny" + obj[:mode].should == 0755 + when "/myfile": + obj[:mode].should == 0755 + end end - obj.should be_instance_of(Puppet::TransObject) - case path - when "/otherdir": - obj[:owner].should == "luke" - obj[:group].should == "johnny" - obj[:mode].should == 0755 - when "/myfile": - obj[:mode].should == 0755 + end + + it "should not try to manage user or group when not running as root" do + Puppet.features.stubs(:root?).returns(false) + trans = nil + trans = @settings.to_transportable(:other) + trans.delve do |obj| + next unless obj.is_a?(Puppet::TransObject) + obj[:owner].should be_nil + obj[:group].should be_nil end end - end - it "should not try to manage user or group when not running as root" do - Puppet.features.stubs(:root?).returns(false) - trans = nil - trans = @settings.to_transportable(:other) - trans.delve do |obj| - next unless obj.is_a?(Puppet::TransObject) - obj[:owner].should be_nil - obj[:group].should be_nil + it "should add needed users and groups to the manifest when asked" do + # This is how we enable user/group management + @settings.setdefaults :main, :mkusers => [true, "w"] + Puppet.features.stubs(:root?).returns(false) + trans = nil + trans = @settings.to_transportable(:other) + resources = [] + trans.delve { |obj| resources << obj if obj.is_a? Puppet::TransObject and obj.type != "file" } + + user = resources.find { |r| r.type == "user" } + user.should be_instance_of(Puppet::TransObject) + user.name.should == "luke" + user[:ensure].should == :present + + # This should maybe be a separate test, but... + group = resources.find { |r| r.type == "group" } + group.should be_instance_of(Puppet::TransObject) + group.name.should == "johnny" + group[:ensure].should == :present end - end - it "should add needed users and groups to the manifest when asked" do - # This is how we enable user/group management - @settings.setdefaults :main, :mkusers => [true, "w"] - Puppet.features.stubs(:root?).returns(false) - trans = nil - trans = @settings.to_transportable(:other) - resources = [] - trans.delve { |obj| resources << obj if obj.is_a? Puppet::TransObject and obj.type != "file" } - - user = resources.find { |r| r.type == "user" } - user.should be_instance_of(Puppet::TransObject) - user.name.should == "luke" - user[:ensure].should == :present - - # This should maybe be a separate test, but... - group = resources.find { |r| r.type == "group" } - group.should be_instance_of(Puppet::TransObject) - group.name.should == "johnny" - group[:ensure].should == :present - end + it "should ignore tags and schedules when creating files and directories" - it "should ignore tags and schedules when creating files and directories" + it "should apply all resources in debug mode to reduce logging" - it "should apply all resources in debug mode to reduce logging" + it "should not try to manage absent files" do + # Make it think we're root so it tries to manage user and group. + Puppet.features.stubs(:root?).returns(true) + trans = nil + trans = @settings.to_transportable + file = nil + trans.delve { |obj| file = obj if obj.name == "/myfile" } + file.should be_nil + end - it "should not try to manage absent files" do - # Make it think we're root so it tries to manage user and group. - Puppet.features.stubs(:root?).returns(true) - trans = nil - trans = @settings.to_transportable - file = nil - trans.delve { |obj| file = obj if obj.name == "/myfile" } - file.should be_nil - end + it "should not try to manage files in memory" do + main = Puppet::Type.type(:file).create(:path => "/maindir") - it "should not try to manage files in memory" do - main = Puppet::Type.type(:file).create(:path => "/maindir") + trans = @settings.to_transportable - trans = @settings.to_transportable + lambda { trans.to_catalog }.should_not raise_error + end - lambda { trans.to_catalog }.should_not raise_error - end + it "should do nothing if a catalog cannot be created" do + bucket = mock 'bucket' + catalog = mock 'catalog' - it "should do nothing if a catalog cannot be created" do - bucket = mock 'bucket' - catalog = mock 'catalog' + @settings.expects(:to_transportable).returns bucket + bucket.expects(:to_catalog).raises RuntimeError + catalog.expects(:apply).never - @settings.expects(:to_transportable).returns bucket - bucket.expects(:to_catalog).raises RuntimeError - catalog.expects(:apply).never + @settings.use(:mysection) + end - @settings.use(:mysection) - end + it "should clear the catalog after applying" do + bucket = mock 'bucket' + catalog = mock 'catalog' - it "should clear the catalog after applying" do - bucket = mock 'bucket' - catalog = mock 'catalog' + @settings.expects(:to_transportable).returns bucket + bucket.expects(:to_catalog).returns catalog + catalog.stubs(:host_config=) + catalog.stubs(:apply) + catalog.expects(:clear) - @settings.expects(:to_transportable).returns bucket - bucket.expects(:to_catalog).returns catalog - catalog.stubs(:host_config=) - catalog.stubs(:apply) - catalog.expects(:clear) + @settings.use(:mysection) + end - @settings.use(:mysection) - end + it "should clear the catalog even if there is an exception during applying" do + bucket = mock 'bucket' + catalog = mock 'catalog' - it "should clear the catalog even if there is an exception during applying" do - bucket = mock 'bucket' - catalog = mock 'catalog' + @settings.expects(:to_transportable).returns bucket + bucket.expects(:to_catalog).returns catalog + catalog.stubs(:host_config=) + catalog.expects(:apply).raises(ArgumentError) + catalog.expects(:clear) - @settings.expects(:to_transportable).returns bucket - bucket.expects(:to_catalog).returns catalog - catalog.stubs(:host_config=) - catalog.expects(:apply).raises(ArgumentError) - catalog.expects(:clear) + # We don't care about the raised exception, we just care that + # we clear the catalog even with the exception + lambda { @settings.use(:mysection) }.should raise_error + end - # We don't care about the raised exception, we just care that - # we clear the catalog even with the exception - lambda { @settings.use(:mysection) }.should raise_error - end + it "should do nothing if all specified sections have already been used" do + bucket = mock 'bucket' + catalog = mock 'catalog' - it "should do nothing if all specified sections have already been used" do - bucket = mock 'bucket' - catalog = mock 'catalog' + @settings.expects(:to_transportable).once.returns(bucket) + bucket.expects(:to_catalog).returns catalog + catalog.stub_everything - @settings.expects(:to_transportable).once.returns(bucket) - bucket.expects(:to_catalog).returns catalog - catalog.stub_everything + @settings.use(:whatever) - @settings.use(:whatever) + @settings.use(:whatever) + end - @settings.use(:whatever) - end + it "should ignore file settings whose values are not strings" do + @settings[:maindir] = false - it "should ignore file settings whose values are not strings" do - @settings[:maindir] = false + lambda { trans = @settings.to_transportable }.should_not raise_error + end - lambda { trans = @settings.to_transportable }.should_not raise_error - end + it "should be able to turn the current configuration into a parseable manifest" - it "should be able to turn the current configuration into a parseable manifest" + it "should convert octal numbers correctly when producing a manifest" - it "should convert octal numbers correctly when producing a manifest" + it "should be able to provide all of its parameters in a format compatible with GetOpt::Long" do + pending "Not converted from test/unit yet" + end - it "should be able to provide all of its parameters in a format compatible with GetOpt::Long" do - pending "Not converted from test/unit yet" - end + it "should not attempt to manage files within /dev" do + pending "Not converted from test/unit yet" + end - it "should not attempt to manage files within /dev" do - pending "Not converted from test/unit yet" - end + it "should not modify the stored state database when managing resources" do + Puppet::Util::Storage.expects(:store).never + Puppet::Util::Storage.expects(:load).never + Dir.expects(:mkdir).with("/maindir") + Dir.expects(:mkdir).with("/seconddir") + @settings.use(:main) + end - it "should not modify the stored state database when managing resources" do - Puppet::Util::Storage.expects(:store).never - Puppet::Util::Storage.expects(:load).never - Dir.expects(:mkdir).with("/maindir") - Dir.expects(:mkdir).with("/seconddir") - @settings.use(:main) - end + it "should convert all relative paths to fully-qualified paths (#795)" do + @settings[:myfile] = "unqualified" + dir = Dir.getwd + @settings[:myfile].should == File.join(dir, "unqualified") + end - it "should convert all relative paths to fully-qualified paths (#795)" do - @settings[:myfile] = "unqualified" - dir = Dir.getwd - @settings[:myfile].should == File.join(dir, "unqualified") - end + it "should support a method for re-using all currently used sections" do + Dir.expects(:mkdir).with("/thirddir").times(2) + @settings.use(:third) + @settings.reuse + end - it "should support a method for re-using all currently used sections" do - Dir.expects(:mkdir).with("/thirddir").times(2) - @settings.use(:third) - @settings.reuse - end + it "should fail if any resources fail" do + stub_transaction + @trans.expects(:any_failed?).returns(true) - it "should fail if any resources fail" do - stub_transaction - @trans.expects(:any_failed?).returns(true) + proc { @settings.use(:whatever) }.should raise_error(RuntimeError) + end - proc { @settings.use(:whatever) }.should raise_error(RuntimeError) + after { Puppet::Type.allclear } end - after { Puppet::Type.allclear } + describe "when dealing with printing configs" do + before do + @settings = Puppet::Util::Settings.new + #these are the magic default values + @settings.stubs(:value).with(:configprint).returns("") + @settings.stubs(:value).with(:genconfig).returns(false) + @settings.stubs(:value).with(:genmanifest).returns(false) + @settings.stubs(:value).with(:environment).returns(nil) + end + + describe "when checking print_config?" do + it "should return false when the :configprint, :genconfig and :genmanifest are not set" do + @settings.print_configs?.should be_false + end + + it "should return true when :configprint has a value" do + @settings.stubs(:value).with(:configprint).returns("something") + @settings.print_configs?.should be_true + end + + it "should return true when :genconfig has a value" do + @settings.stubs(:value).with(:genconfig).returns(true) + @settings.print_configs?.should be_true + end + + it "should return true when :genmanifest has a value" do + @settings.stubs(:value).with(:genmanifest).returns(true) + @settings.print_configs?.should be_true + end + end + + describe "when printing configs" do + describe "when :configprint has a value" do + it "should call print_config_options" do + @settings.stubs(:value).with(:configprint).returns("something") + @settings.expects(:print_config_options) + @settings.print_configs + end + + it "should get the value of the option using the environment" do + @settings.stubs(:value).with(:configprint).returns("something") + @settings.stubs(:include?).with("something").returns(true) + @settings.expects(:value).with(:environment).returns("env") + @settings.expects(:value).with("something", "env").returns("foo") + @settings.stubs(:puts).with("foo") + @settings.print_configs + end + + it "should print the value of the option" do + @settings.stubs(:value).with(:configprint).returns("something") + @settings.stubs(:include?).with("something").returns(true) + @settings.stubs(:value).with("something", nil).returns("foo") + @settings.expects(:puts).with("foo") + @settings.print_configs + end + + it "should print the value pairs if there are multiple options" do + @settings.stubs(:value).with(:configprint).returns("bar,baz") + @settings.stubs(:include?).with("bar").returns(true) + @settings.stubs(:include?).with("baz").returns(true) + @settings.stubs(:value).with("bar", nil).returns("foo") + @settings.stubs(:value).with("baz", nil).returns("fud") + @settings.expects(:puts).with("bar = foo") + @settings.expects(:puts).with("baz = fud") + @settings.print_configs + end + + it "should print a whole bunch of stuff if :configprint = all" + + it "should return true after printing" do + @settings.stubs(:value).with(:configprint).returns("something") + @settings.stubs(:include?).with("something").returns(true) + @settings.stubs(:value).with("something", nil).returns("foo") + @settings.stubs(:puts).with("foo") + @settings.print_configs.should be_true + end + + it "should return false if a config param is not found" do + @settings.stubs(:value).with(:configprint).returns("something") + @settings.stubs(:include?).with("something").returns(false) + @settings.print_configs.should be_false + end + end + + describe "when genconfig is true" do + it "should call to_config" do + @settings.stubs(:value).with(:genconfig).returns(true) + @settings.expects(:to_config) + @settings.print_configs + end + + it "should return true from print_configs" do + @settings.stubs(:value).with(:genconfig).returns(true) + @settings.stubs(:to_config) + @settings.print_configs.should be_true + end + end + + describe "when genmanifest is true" do + it "should call to_config" do + @settings.stubs(:value).with(:genmanifest).returns(true) + @settings.expects(:to_manifest) + @settings.print_configs + end + + it "should return true from print_configs" do + @settings.stubs(:value).with(:genmanifest).returns(true) + @settings.stubs(:to_manifest) + @settings.print_configs.should be_true + end + end + end + end end -- cgit From 24ca81fcdca9fa321a706453c96536e9bbeab7e2 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Mon, 16 Jun 2008 22:42:12 -0500 Subject: Fixed #1360 -- allowdupe works with groups again. I've added a couple of tests for this bit of the user and group useradd/groupadd providers, but I haven't migrated the rest of the tests. --- spec/unit/provider/group/groupadd.rb | 31 +++++++++++++++++++++++++++++++ spec/unit/provider/user/useradd.rb | 31 +++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100755 spec/unit/provider/group/groupadd.rb create mode 100755 spec/unit/provider/user/useradd.rb (limited to 'spec/unit') diff --git a/spec/unit/provider/group/groupadd.rb b/spec/unit/provider/group/groupadd.rb new file mode 100755 index 000000000..fb4b811cb --- /dev/null +++ b/spec/unit/provider/group/groupadd.rb @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +provider_class = Puppet::Type.type(:group).provider(:groupadd) + +describe provider_class do + before do + @resource = stub("resource", :name => "mygroup") + @provider = provider_class.new(@resource) + end + + # #1360 + it "should add -o when allowdupe is enabled and the group is being created" do + @resource.stubs(:should).returns "fakeval" + @resource.stubs(:[]).returns "fakeval" + @resource.expects(:allowdupe?).returns true + @provider.expects(:execute).with { |args| args.include?("-o") } + + @provider.create + end + + it "should add -o when allowdupe is enabled and the gid is being modified" do + @resource.stubs(:should).returns "fakeval" + @resource.stubs(:[]).returns "fakeval" + @resource.expects(:allowdupe?).returns true + @provider.expects(:execute).with { |args| args.include?("-o") } + + @provider.gid = 150 + end +end diff --git a/spec/unit/provider/user/useradd.rb b/spec/unit/provider/user/useradd.rb new file mode 100755 index 000000000..96a785589 --- /dev/null +++ b/spec/unit/provider/user/useradd.rb @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +provider_class = Puppet::Type.type(:user).provider(:useradd) + +describe provider_class do + before do + @resource = stub("resource", :name => "myuser", :managehome? => nil) + @provider = provider_class.new(@resource) + end + + # #1360 + it "should add -o when allowdupe is enabled and the user is being created" do + @resource.stubs(:should).returns "fakeval" + @resource.stubs(:[]).returns "fakeval" + @resource.expects(:allowdupe?).returns true + @provider.expects(:execute).with { |args| args.include?("-o") } + + @provider.create + end + + it "should add -o when allowdupe is enabled and the uid is being modified" do + @resource.stubs(:should).returns "fakeval" + @resource.stubs(:[]).returns "fakeval" + @resource.expects(:allowdupe?).returns true + @provider.expects(:execute).with { |args| args.include?("-o") } + + @provider.uid = 150 + end +end -- cgit From 4d9536418d8f684923063eac03d3a59d69bb3794 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Mon, 16 Jun 2008 23:41:33 -0500 Subject: Fixed #1221 - aliases to titles now work for resources. --- spec/unit/node/catalog.rb | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'spec/unit') diff --git a/spec/unit/node/catalog.rb b/spec/unit/node/catalog.rb index ff9ab6930..b4f1503da 100755 --- a/spec/unit/node/catalog.rb +++ b/spec/unit/node/catalog.rb @@ -345,9 +345,9 @@ end describe Puppet::Node::Catalog, " when functioning as a resource container" do before do @catalog = Puppet::Node::Catalog.new("host") - @one = stub 'resource1', :ref => "Me[one]", :catalog= => nil - @two = stub 'resource2', :ref => "Me[two]", :catalog= => nil - @dupe = stub 'resource3', :ref => "Me[one]", :catalog= => nil + @one = stub 'resource1', :ref => "Me[one]", :catalog= => nil, :title => "one" + @two = stub 'resource2', :ref => "Me[two]", :catalog= => nil, :title => "two" + @dupe = stub 'resource3', :ref => "Me[one]", :catalog= => nil, :title => "one" end it "should provide a method to add one or more resources" do @@ -482,6 +482,11 @@ describe Puppet::Node::Catalog, " when functioning as a resource container" do proc { @catalog.alias @one, "one" }.should_not raise_error end + it "should not create aliases that point back to the resource" do + @catalog.alias(@one, "one") + @catalog.resource(:me, "one").should be_nil + end + it "should be able to look resources up by their aliases" do @catalog.add_resource @one @catalog.alias @one, "two" -- cgit From 2380fcd4d187e8592398015e96605ce4b5d63e7d Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Mon, 16 Jun 2008 23:59:18 -0500 Subject: Fixed #1012 - templates in the templatedir are preferred to module templates. --- spec/unit/module.rb | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'spec/unit') diff --git a/spec/unit/module.rb b/spec/unit/module.rb index 06b2d016d..2dadaa501 100755 --- a/spec/unit/module.rb +++ b/spec/unit/module.rb @@ -80,6 +80,14 @@ describe Puppet::Module, " when searching for templates" do File.stubs(:directory?).returns(true) Puppet::Module.find_template("mymod/mytemplate").should == "/one/mymod/templates/mytemplate" end + + it "should return the file in the templatedir if it exists" do + Puppet.settings.expects(:value).with(:templatedir, nil).returns("/my/templates") + Puppet[:modulepath] = "/one:/two" + File.stubs(:directory?).returns(true) + File.stubs(:exists?).returns(true) + Puppet::Module.find_template("mymod/mytemplate").should == "/my/templates/mymod/mytemplate" + end it "should use the main templatedir if no module is found" do Puppet.settings.expects(:value).with(:templatedir, nil).returns("/my/templates") @@ -100,9 +108,10 @@ describe Puppet::Module, " when searching for templates" do end it "should use the node environment if specified" do - Puppet.settings.expects(:value).with(:modulepath, "myenv").returns("/my/templates") + Puppet.settings.stubs(:value).returns.returns("/my/directory") + Puppet.settings.expects(:value).with(:modulepath, "myenv").returns("/my/modules") File.stubs(:directory?).returns(true) - Puppet::Module.find_template("mymod/envtemplate", "myenv").should == "/my/templates/mymod/templates/envtemplate" + Puppet::Module.find_template("mymod/envtemplate", "myenv").should == "/my/modules/mymod/templates/envtemplate" end after { Puppet.settings.clear } -- cgit From 5a283d644b68bd89dc3c016ffd062b3ba792c617 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Tue, 17 Jun 2008 16:18:05 -0500 Subject: Fixing #1374 - Using Puppet::Type.type() in tests --- spec/unit/type/exec.rb | 6 +-- spec/unit/type/package.rb | 72 ++++++++++++++++---------------- spec/unit/type/schedule.rb | 40 +++++++++--------- spec/unit/type/service.rb | 100 ++++++++++++++++++++++----------------------- 4 files changed, 105 insertions(+), 113 deletions(-) (limited to 'spec/unit') diff --git a/spec/unit/type/exec.rb b/spec/unit/type/exec.rb index cf0e02929..c6c082dd5 100755 --- a/spec/unit/type/exec.rb +++ b/spec/unit/type/exec.rb @@ -2,8 +2,6 @@ require File.dirname(__FILE__) + '/../../spec_helper' -require 'puppet/type/exec' - module ExecModuleTesting def create_resource(command, output, exitstatus) @user_name = 'some_user_name' @@ -30,7 +28,7 @@ module ExecModuleTesting end end -describe Puppet::Type::Exec, " when execing" do +describe Puppet::Type.type(:exec), " when execing" do include ExecModuleTesting it "should use the 'run_and_capture' method to exec" do @@ -69,7 +67,7 @@ describe Puppet::Type::Exec, " when execing" do end -describe Puppet::Type::Exec, " when logoutput=>on_failure is set," do +describe Puppet::Type.type(:exec), " when logoutput=>on_failure is set," do include ExecModuleTesting it "should log the output on failure" do diff --git a/spec/unit/type/package.rb b/spec/unit/type/package.rb index 335910c63..3ceb8e32b 100755 --- a/spec/unit/type/package.rb +++ b/spec/unit/type/package.rb @@ -2,103 +2,101 @@ require File.dirname(__FILE__) + '/../../spec_helper' -require 'puppet/type/package' - -describe Puppet::Type::Package do +describe Puppet::Type.type(:package) do it "should have an :installable feature that requires the :install method" do - Puppet::Type::Package.provider_feature(:installable).methods.should == [:install] + Puppet::Type.type(:package).provider_feature(:installable).methods.should == [:install] end it "should have an :uninstallable feature that requires the :uninstall method" do - Puppet::Type::Package.provider_feature(:uninstallable).methods.should == [:uninstall] + Puppet::Type.type(:package).provider_feature(:uninstallable).methods.should == [:uninstall] end it "should have an :upgradeable feature that requires :update and :latest methods" do - Puppet::Type::Package.provider_feature(:upgradeable).methods.should == [:update, :latest] + Puppet::Type.type(:package).provider_feature(:upgradeable).methods.should == [:update, :latest] end it "should have a :purgeable feature that requires the :purge latest method" do - Puppet::Type::Package.provider_feature(:purgeable).methods.should == [:purge] + Puppet::Type.type(:package).provider_feature(:purgeable).methods.should == [:purge] end it "should have a :versionable feature" do - Puppet::Type::Package.provider_feature(:versionable).should_not be_nil + Puppet::Type.type(:package).provider_feature(:versionable).should_not be_nil end it "should default to being installed" do - pkg = Puppet::Type::Package.create(:name => "yay") + pkg = Puppet::Type.type(:package).create(:name => "yay") pkg.should(:ensure).should == :present end - after { Puppet::Type::Package.clear } + after { Puppet::Type.type(:package).clear } end -describe Puppet::Type::Package, "when validating attributes" do +describe Puppet::Type.type(:package), "when validating attributes" do [:name, :source, :instance, :status, :adminfile, :responsefile, :configfiles, :category, :platform, :root, :vendor, :description, :allowcdrom].each do |param| it "should have a #{param} parameter" do - Puppet::Type::Package.attrtype(param).should == :param + Puppet::Type.type(:package).attrtype(param).should == :param end end it "should have an ensure property" do - Puppet::Type::Package.attrtype(:ensure).should == :property + Puppet::Type.type(:package).attrtype(:ensure).should == :property end end -describe Puppet::Type::Package, "when validating attribute values" do +describe Puppet::Type.type(:package), "when validating attribute values" do before do - @provider = stub 'provider', :class => Puppet::Type::Package.defaultprovider, :clear => nil - Puppet::Type::Package.defaultprovider.expects(:new).returns(@provider) + @provider = stub 'provider', :class => Puppet::Type.type(:package).defaultprovider, :clear => nil + Puppet::Type.type(:package).defaultprovider.expects(:new).returns(@provider) end it "should support :present as a value to :ensure" do - Puppet::Type::Package.create(:name => "yay", :ensure => :present) + Puppet::Type.type(:package).create(:name => "yay", :ensure => :present) end it "should alias :installed to :present as a value to :ensure" do - pkg = Puppet::Type::Package.create(:name => "yay", :ensure => :installed) + pkg = Puppet::Type.type(:package).create(:name => "yay", :ensure => :installed) pkg.should(:ensure).should == :present end it "should support :absent as a value to :ensure" do - Puppet::Type::Package.create(:name => "yay", :ensure => :absent) + Puppet::Type.type(:package).create(:name => "yay", :ensure => :absent) end it "should support :purged as a value to :ensure if the provider has the :purgeable feature" do @provider.expects(:satisfies?).with(:purgeable).returns(true) - Puppet::Type::Package.create(:name => "yay", :ensure => :purged) + Puppet::Type.type(:package).create(:name => "yay", :ensure => :purged) end it "should not support :purged as a value to :ensure if the provider does not have the :purgeable feature" do @provider.expects(:satisfies?).with(:purgeable).returns(false) - proc { Puppet::Type::Package.create(:name => "yay", :ensure => :purged) }.should raise_error(Puppet::Error) + proc { Puppet::Type.type(:package).create(:name => "yay", :ensure => :purged) }.should raise_error(Puppet::Error) end it "should support :latest as a value to :ensure if the provider has the :upgradeable feature" do @provider.expects(:satisfies?).with(:upgradeable).returns(true) - Puppet::Type::Package.create(:name => "yay", :ensure => :latest) + Puppet::Type.type(:package).create(:name => "yay", :ensure => :latest) end it "should not support :latest as a value to :ensure if the provider does not have the :upgradeable feature" do @provider.expects(:satisfies?).with(:upgradeable).returns(false) - proc { Puppet::Type::Package.create(:name => "yay", :ensure => :latest) }.should raise_error(Puppet::Error) + proc { Puppet::Type.type(:package).create(:name => "yay", :ensure => :latest) }.should raise_error(Puppet::Error) end it "should support version numbers as a value to :ensure if the provider has the :versionable feature" do @provider.expects(:satisfies?).with(:versionable).returns(true) - Puppet::Type::Package.create(:name => "yay", :ensure => "1.0") + Puppet::Type.type(:package).create(:name => "yay", :ensure => "1.0") end it "should not support version numbers as a value to :ensure if the provider does not have the :versionable feature" do @provider.expects(:satisfies?).with(:versionable).returns(false) - proc { Puppet::Type::Package.create(:name => "yay", :ensure => "1.0") }.should raise_error(Puppet::Error) + proc { Puppet::Type.type(:package).create(:name => "yay", :ensure => "1.0") }.should raise_error(Puppet::Error) end it "should accept any string as an argument to :source" do - proc { Puppet::Type::Package.create(:name => "yay", :source => "stuff") }.should_not raise_error(Puppet::Error) + proc { Puppet::Type.type(:package).create(:name => "yay", :source => "stuff") }.should_not raise_error(Puppet::Error) end - after { Puppet::Type::Package.clear } + after { Puppet::Type.type(:package).clear } end module PackageEvaluationTesting @@ -107,11 +105,11 @@ module PackageEvaluationTesting end end -describe Puppet::Type::Package do +describe Puppet::Type.type(:package) do before :each do - @provider = stub 'provider', :class => Puppet::Type::Package.defaultprovider, :clear => nil, :satisfies? => true, :name => :mock - Puppet::Type::Package.defaultprovider.stubs(:new).returns(@provider) - @package = Puppet::Type::Package.create(:name => "yay") + @provider = stub 'provider', :class => Puppet::Type.type(:package).defaultprovider, :clear => nil, :satisfies? => true, :name => :mock + Puppet::Type.type(:package).defaultprovider.stubs(:new).returns(@provider) + @package = Puppet::Type.type(:package).create(:name => "yay") @catalog = Puppet::Node::Catalog.new @catalog.add_resource(@package) @@ -119,11 +117,11 @@ describe Puppet::Type::Package do after :each do @catalog.clear(true) - Puppet::Type::Package.clear + Puppet::Type.type(:package).clear end - describe Puppet::Type::Package, "when it should be purged" do + describe Puppet::Type.type(:package), "when it should be purged" do include PackageEvaluationTesting before { @package[:ensure] = :purged } @@ -142,7 +140,7 @@ describe Puppet::Type::Package do end end - describe Puppet::Type::Package, "when it should be absent" do + describe Puppet::Type.type(:package), "when it should be absent" do include PackageEvaluationTesting before { @package[:ensure] = :absent } @@ -163,7 +161,7 @@ describe Puppet::Type::Package do end end - describe Puppet::Type::Package, "when it should be present" do + describe Puppet::Type.type(:package), "when it should be present" do include PackageEvaluationTesting before { @package[:ensure] = :present } @@ -184,7 +182,7 @@ describe Puppet::Type::Package do end end - describe Puppet::Type::Package, "when it should be latest" do + describe Puppet::Type.type(:package), "when it should be latest" do include PackageEvaluationTesting before { @package[:ensure] = :latest } @@ -219,7 +217,7 @@ describe Puppet::Type::Package do end end - describe Puppet::Type::Package, "when it should be a specific version" do + describe Puppet::Type.type(:package), "when it should be a specific version" do include PackageEvaluationTesting before { @package[:ensure] = "1.0" } diff --git a/spec/unit/type/schedule.rb b/spec/unit/type/schedule.rb index da38f68a9..d5d4c6039 100755 --- a/spec/unit/type/schedule.rb +++ b/spec/unit/type/schedule.rb @@ -2,8 +2,6 @@ require File.dirname(__FILE__) + '/../../spec_helper' -require 'puppet/type/schedule' - module ScheduleTesting def format(time) @@ -41,20 +39,20 @@ module ScheduleTesting end -describe Puppet::Type::Schedule do +describe Puppet::Type.type(:schedule) do before :each do Puppet.settings.stubs(:value).with(:ignoreschedules).returns(false) - @schedule = Puppet::Type::Schedule.create(:name => "testing") + @schedule = Puppet::Type.type(:schedule).create(:name => "testing") end after :each do - Puppet::Type::Schedule.clear + Puppet::Type.type(:schedule).clear end - describe Puppet::Type::Schedule do + describe Puppet::Type.type(:schedule) do include ScheduleTesting it "should default to :distance for period-matching" do @@ -71,26 +69,26 @@ describe Puppet::Type::Schedule do end end - describe Puppet::Type::Schedule, "when producing default schedules" do + describe Puppet::Type.type(:schedule), "when producing default schedules" do include ScheduleTesting %w{hourly daily weekly monthly never}.each do |period| period = period.to_sym it "should produce a #{period} schedule with the period set appropriately" do - schedules = Puppet::Type::Schedule.mkdefaultschedules - schedules.find { |s| s[:name] == period.to_s and s[:period] == period }.should be_instance_of(Puppet::Type::Schedule) + schedules = Puppet::Type.type(:schedule).mkdefaultschedules + schedules.find { |s| s[:name] == period.to_s and s[:period] == period }.should be_instance_of(Puppet::Type.type(:schedule)) end end it "should produce a schedule named puppet with a period of hourly and a repeat of 2" do - schedules = Puppet::Type::Schedule.mkdefaultschedules + schedules = Puppet::Type.type(:schedule).mkdefaultschedules schedules.find { |s| s[:name] == "puppet" and s[:period] == :hourly and s[:repeat] == 2 - }.should be_instance_of(Puppet::Type::Schedule) + }.should be_instance_of(Puppet::Type.type(:schedule)) end end - describe Puppet::Type::Schedule, "when matching ranges" do + describe Puppet::Type.type(:schedule), "when matching ranges" do include ScheduleTesting it "should match when the start time is before the current time and the end time is after the current time" do @@ -109,7 +107,7 @@ describe Puppet::Type::Schedule do end end - describe Puppet::Type::Schedule, "when matching hourly by distance" do + describe Puppet::Type.type(:schedule), "when matching hourly by distance" do include ScheduleTesting before do @@ -130,7 +128,7 @@ describe Puppet::Type::Schedule do end end - describe Puppet::Type::Schedule, "when matching daily by distance" do + describe Puppet::Type.type(:schedule), "when matching daily by distance" do include ScheduleTesting before do @@ -151,7 +149,7 @@ describe Puppet::Type::Schedule do end end - describe Puppet::Type::Schedule, "when matching weekly by distance" do + describe Puppet::Type.type(:schedule), "when matching weekly by distance" do include ScheduleTesting before do @@ -172,7 +170,7 @@ describe Puppet::Type::Schedule do end end - describe Puppet::Type::Schedule, "when matching monthly by distance" do + describe Puppet::Type.type(:schedule), "when matching monthly by distance" do include ScheduleTesting before do @@ -193,7 +191,7 @@ describe Puppet::Type::Schedule do end end - describe Puppet::Type::Schedule, "when matching hourly by number" do + describe Puppet::Type.type(:schedule), "when matching hourly by number" do include ScheduleTesting before do @@ -226,7 +224,7 @@ describe Puppet::Type::Schedule do end end - describe Puppet::Type::Schedule, "when matching daily by number" do + describe Puppet::Type.type(:schedule), "when matching daily by number" do include ScheduleTesting before do @@ -261,7 +259,7 @@ describe Puppet::Type::Schedule do end end - describe Puppet::Type::Schedule, "when matching weekly by number" do + describe Puppet::Type.type(:schedule), "when matching weekly by number" do include ScheduleTesting before do @@ -288,7 +286,7 @@ describe Puppet::Type::Schedule do end end - describe Puppet::Type::Schedule, "when matching monthly by number" do + describe Puppet::Type.type(:schedule), "when matching monthly by number" do include ScheduleTesting before do @@ -315,7 +313,7 @@ describe Puppet::Type::Schedule do end end - describe Puppet::Type::Schedule, "when matching with a repeat greater than one" do + describe Puppet::Type.type(:schedule), "when matching with a repeat greater than one" do include ScheduleTesting before do diff --git a/spec/unit/type/service.rb b/spec/unit/type/service.rb index e8358cb22..12dda3edb 100755 --- a/spec/unit/type/service.rb +++ b/spec/unit/type/service.rb @@ -2,159 +2,157 @@ require File.dirname(__FILE__) + '/../../spec_helper' -require 'puppet/type/service' - -describe Puppet::Type::Service do +describe Puppet::Type.type(:service) do it "should have an :enableable feature that requires the :enable, :disable, and :enabled? methods" do - Puppet::Type::Service.provider_feature(:enableable).methods.should == [:disable, :enable, :enabled?] + Puppet::Type.type(:service).provider_feature(:enableable).methods.should == [:disable, :enable, :enabled?] end it "should have a :refreshable feature that requires the :restart method" do - Puppet::Type::Service.provider_feature(:refreshable).methods.should == [:restart] + Puppet::Type.type(:service).provider_feature(:refreshable).methods.should == [:restart] end end -describe Puppet::Type::Service, "when validating attributes" do +describe Puppet::Type.type(:service), "when validating attributes" do [:name, :binary, :hasstatus, :path, :pattern, :start, :restart, :stop, :status, :hasrestart, :control].each do |param| it "should have a #{param} parameter" do - Puppet::Type::Service.attrtype(param).should == :param + Puppet::Type.type(:service).attrtype(param).should == :param end end [:ensure, :enable].each do |param| it "should have an #{param} property" do - Puppet::Type::Service.attrtype(param).should == :property + Puppet::Type.type(:service).attrtype(param).should == :property end end end -describe Puppet::Type::Service, "when validating attribute values" do +describe Puppet::Type.type(:service), "when validating attribute values" do before do - @provider = stub 'provider', :class => Puppet::Type::Service.defaultprovider, :clear => nil, :controllable? => false - Puppet::Type::Service.defaultprovider.stubs(:new).returns(@provider) + @provider = stub 'provider', :class => Puppet::Type.type(:service).defaultprovider, :clear => nil, :controllable? => false + Puppet::Type.type(:service).defaultprovider.stubs(:new).returns(@provider) end it "should support :running as a value to :ensure" do - Puppet::Type::Service.create(:name => "yay", :ensure => :running) + Puppet::Type.type(:service).create(:name => "yay", :ensure => :running) end it "should support :stopped as a value to :ensure" do - Puppet::Type::Service.create(:name => "yay", :ensure => :stopped) + Puppet::Type.type(:service).create(:name => "yay", :ensure => :stopped) end it "should alias the value :true to :running in :ensure" do - svc = Puppet::Type::Service.create(:name => "yay", :ensure => true) + svc = Puppet::Type.type(:service).create(:name => "yay", :ensure => true) svc.should(:ensure).should == :running end it "should alias the value :false to :stopped in :ensure" do - svc = Puppet::Type::Service.create(:name => "yay", :ensure => false) + svc = Puppet::Type.type(:service).create(:name => "yay", :ensure => false) svc.should(:ensure).should == :stopped end it "should support :true as a value to :enable" do - Puppet::Type::Service.create(:name => "yay", :enable => :true) + Puppet::Type.type(:service).create(:name => "yay", :enable => :true) end it "should support :false as a value to :enable" do - Puppet::Type::Service.create(:name => "yay", :enable => :false) + Puppet::Type.type(:service).create(:name => "yay", :enable => :false) end it "should support :true as a value to :hasstatus" do - Puppet::Type::Service.create(:name => "yay", :hasstatus => :true) + Puppet::Type.type(:service).create(:name => "yay", :hasstatus => :true) end it "should support :false as a value to :hasstatus" do - Puppet::Type::Service.create(:name => "yay", :hasstatus => :false) + Puppet::Type.type(:service).create(:name => "yay", :hasstatus => :false) end it "should support :true as a value to :hasrestart" do - Puppet::Type::Service.create(:name => "yay", :hasrestart => :true) + Puppet::Type.type(:service).create(:name => "yay", :hasrestart => :true) end it "should support :false as a value to :hasrestart" do - Puppet::Type::Service.create(:name => "yay", :hasrestart => :false) + Puppet::Type.type(:service).create(:name => "yay", :hasrestart => :false) end it "should allow setting the :enable parameter if the provider has the :enableable feature" do - Puppet::Type::Service.defaultprovider.stubs(:supports_parameter?).returns(true) - Puppet::Type::Service.defaultprovider.expects(:supports_parameter?).with(Puppet::Type::Service.attrclass(:enable)).returns(true) - svc = Puppet::Type::Service.create(:name => "yay", :enable => true) + Puppet::Type.type(:service).defaultprovider.stubs(:supports_parameter?).returns(true) + Puppet::Type.type(:service).defaultprovider.expects(:supports_parameter?).with(Puppet::Type.type(:service).attrclass(:enable)).returns(true) + svc = Puppet::Type.type(:service).create(:name => "yay", :enable => true) svc.should(:enable).should == :true end it "should not allow setting the :enable parameter if the provider is missing the :enableable feature" do - Puppet::Type::Service.defaultprovider.stubs(:supports_parameter?).returns(true) - Puppet::Type::Service.defaultprovider.expects(:supports_parameter?).with(Puppet::Type::Service.attrclass(:enable)).returns(false) - svc = Puppet::Type::Service.create(:name => "yay", :enable => true) + Puppet::Type.type(:service).defaultprovider.stubs(:supports_parameter?).returns(true) + Puppet::Type.type(:service).defaultprovider.expects(:supports_parameter?).with(Puppet::Type.type(:service).attrclass(:enable)).returns(false) + svc = Puppet::Type.type(:service).create(:name => "yay", :enable => true) svc.should(:enable).should be_nil end it "should discard paths that do not exist" do FileTest.stubs(:exist?).returns(false) FileTest.stubs(:directory?).returns(false) - svc = Puppet::Type::Service.create(:name => "yay", :path => "/one/two") + svc = Puppet::Type.type(:service).create(:name => "yay", :path => "/one/two") svc[:path].should be_empty end it "should discard paths that are not directories" do FileTest.stubs(:exist?).returns(true) FileTest.stubs(:directory?).returns(false) - svc = Puppet::Type::Service.create(:name => "yay", :path => "/one/two") + svc = Puppet::Type.type(:service).create(:name => "yay", :path => "/one/two") svc[:path].should be_empty end it "should split paths on ':'" do FileTest.stubs(:exist?).returns(true) FileTest.stubs(:directory?).returns(true) - svc = Puppet::Type::Service.create(:name => "yay", :path => "/one/two:/three/four") + svc = Puppet::Type.type(:service).create(:name => "yay", :path => "/one/two:/three/four") svc[:path].should == %w{/one/two /three/four} end it "should accept arrays of paths joined by ':'" do FileTest.stubs(:exist?).returns(true) FileTest.stubs(:directory?).returns(true) - svc = Puppet::Type::Service.create(:name => "yay", :path => ["/one:/two", "/three:/four"]) + svc = Puppet::Type.type(:service).create(:name => "yay", :path => ["/one:/two", "/three:/four"]) svc[:path].should == %w{/one /two /three /four} end - after { Puppet::Type::Service.clear } + after { Puppet::Type.type(:service).clear } end -describe Puppet::Type::Service, "when setting default attribute values" do +describe Puppet::Type.type(:service), "when setting default attribute values" do it "should default to the provider's default path if one is available" do FileTest.stubs(:directory?).returns(true) FileTest.stubs(:exist?).returns(true) - Puppet::Type::Service.defaultprovider.stubs(:respond_to?).returns(true) - Puppet::Type::Service.defaultprovider.stubs(:defpath).returns("testing") - svc = Puppet::Type::Service.create(:name => "other") + Puppet::Type.type(:service).defaultprovider.stubs(:respond_to?).returns(true) + Puppet::Type.type(:service).defaultprovider.stubs(:defpath).returns("testing") + svc = Puppet::Type.type(:service).create(:name => "other") svc[:path].should == ["testing"] end it "should default 'pattern' to the binary if one is provided" do - svc = Puppet::Type::Service.create(:name => "other", :binary => "/some/binary") + svc = Puppet::Type.type(:service).create(:name => "other", :binary => "/some/binary") svc[:pattern].should == "/some/binary" end it "should default 'pattern' to the name if no pattern is provided" do - svc = Puppet::Type::Service.create(:name => "other") + svc = Puppet::Type.type(:service).create(:name => "other") svc[:pattern].should == "other" end it "should default 'control' to the upcased service name with periods replaced by underscores if the provider supports the 'controllable' feature" do - provider = stub 'provider', :controllable? => true, :class => Puppet::Type::Service.defaultprovider, :clear => nil - Puppet::Type::Service.defaultprovider.stubs(:new).returns(provider) - svc = Puppet::Type::Service.create(:name => "nfs.client") + provider = stub 'provider', :controllable? => true, :class => Puppet::Type.type(:service).defaultprovider, :clear => nil + Puppet::Type.type(:service).defaultprovider.stubs(:new).returns(provider) + svc = Puppet::Type.type(:service).create(:name => "nfs.client") svc[:control].should == "NFS_CLIENT_START" end - after { Puppet::Type::Service.clear } + after { Puppet::Type.type(:service).clear } end -describe Puppet::Type::Service, "when retrieving the host's current state" do +describe Puppet::Type.type(:service), "when retrieving the host's current state" do before do - @service = Puppet::Type::Service.create(:name => "yay") + @service = Puppet::Type.type(:service).create(:name => "yay") end it "should use the provider's status to determine whether the service is running" do @@ -170,12 +168,12 @@ describe Puppet::Type::Service, "when retrieving the host's current state" do @service.property(:enable).retrieve.should == :yepper end - after { Puppet::Type::Service.clear } + after { Puppet::Type.type(:service).clear } end -describe Puppet::Type::Service, "when changing the host" do +describe Puppet::Type.type(:service), "when changing the host" do before do - @service = Puppet::Type::Service.create(:name => "yay") + @service = Puppet::Type.type(:service).create(:name => "yay") end it "should start the service if it is supposed to be running" do @@ -218,12 +216,12 @@ describe Puppet::Type::Service, "when changing the host" do @service.property(:ensure).sync end - after { Puppet::Type::Service.clear } + after { Puppet::Type.type(:service).clear } end -describe Puppet::Type::Service, "when refreshing the service" do +describe Puppet::Type.type(:service), "when refreshing the service" do before do - @service = Puppet::Type::Service.create(:name => "yay") + @service = Puppet::Type.type(:service).create(:name => "yay") end it "should restart the service if it is running" do @@ -252,5 +250,5 @@ describe Puppet::Type::Service, "when refreshing the service" do @service.refresh end - after { Puppet::Type::Service.clear } + after { Puppet::Type.type(:service).clear } end -- cgit From a1d1abdd5a2fc11dceeed63da8c6f48d2fa21cfe Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Tue, 1 Jul 2008 21:20:13 -0500 Subject: Adding an 'instance' class method to ldap connections. This just returns a Connection instance with the default ldap configuration information already provided. --- spec/unit/util/ldap/connection.rb | 42 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'spec/unit') diff --git a/spec/unit/util/ldap/connection.rb b/spec/unit/util/ldap/connection.rb index 212f3ca54..9392466c7 100755 --- a/spec/unit/util/ldap/connection.rb +++ b/spec/unit/util/ldap/connection.rb @@ -111,4 +111,46 @@ describe Puppet::Util::Ldap::Connection do @connection.close end end + + it "should have a class-level method for creating a default connection" do + Puppet::Util::Ldap::Connection.should respond_to(:instance) + end + + describe "when creating a default connection" do + before do + Puppet.settings.stubs(:value).returns "whatever" + end + + it "should use the :ldapserver setting to determine the host" do + Puppet.settings.expects(:value).with(:ldapserver).returns "myserv" + Puppet::Util::Ldap::Connection.expects(:new).with { |host, port, options| host == "myserv" } + Puppet::Util::Ldap::Connection.instance + end + + it "should use the :ldapport setting to determine the port" do + Puppet.settings.expects(:value).with(:ldapport).returns "456" + Puppet::Util::Ldap::Connection.expects(:new).with { |host, port, options| port == "456" } + Puppet::Util::Ldap::Connection.instance + end + + it "should set ssl to :tls if tls is enabled" do + Puppet.settings.expects(:value).with(:ldaptls).returns true + Puppet::Util::Ldap::Connection.expects(:new).with { |host, port, options| options[:ssl] == :tls } + Puppet::Util::Ldap::Connection.instance + end + + it "should set ssl to 'true' if ssl is enabled and tls is not" do + Puppet.settings.expects(:value).with(:ldaptls).returns false + Puppet.settings.expects(:value).with(:ldapssl).returns true + Puppet::Util::Ldap::Connection.expects(:new).with { |host, port, options| options[:ssl] == true } + Puppet::Util::Ldap::Connection.instance + end + + it "should set ssl to false if neither ssl nor tls are enabled" do + Puppet.settings.expects(:value).with(:ldaptls).returns false + Puppet.settings.expects(:value).with(:ldapssl).returns false + Puppet::Util::Ldap::Connection.expects(:new).with { |host, port, options| options[:ssl] == false } + Puppet::Util::Ldap::Connection.instance + end + end end -- cgit From b47d4e1b3e1224541e555648854baf0503b1612e Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Tue, 1 Jul 2008 21:55:53 -0500 Subject: Added a 'search' method to the ldap node terminus. This makes it easy to find multiple nodes in ldap, and was done so it can be used by puppetrun. --- spec/unit/indirector/ldap.rb | 18 +- spec/unit/indirector/node/ldap.rb | 439 +++++++++++++++++++------------------- 2 files changed, 226 insertions(+), 231 deletions(-) (limited to 'spec/unit') diff --git a/spec/unit/indirector/ldap.rb b/spec/unit/indirector/ldap.rb index 2599bcecf..cf802d856 100755 --- a/spec/unit/indirector/ldap.rb +++ b/spec/unit/indirector/ldap.rb @@ -28,8 +28,9 @@ describe Puppet::Indirector::Ldap, " when searching ldap" do @request = stub 'request', :key => "yay" end - it "should call the ldapsearch method with the name being searched for" do - @searcher.expects(:ldapsearch).with("yay") + it "should call the ldapsearch method with the search filter" do + @searcher.expects(:search_filter).with("yay").returns("yay's filter") + @searcher.expects(:ldapsearch).with("yay's filter") @searcher.find @request end @@ -61,15 +62,6 @@ describe Puppet::Indirector::Ldap, " when searching ldap" do @searcher.find @request end - it "should use the results of the :search_filter method as the search filter" do - @searcher.stubs(:search_filter).with("yay").returns("yay's filter") - @connection.expects(:search).with do |*args| - args[2].should == "yay's filter" - true - end - @searcher.find @request - end - it "should use depth 2 when searching" do @connection.expects(:search).with do |*args| args[1].should == 2 @@ -80,7 +72,7 @@ describe Puppet::Indirector::Ldap, " when searching ldap" do it "should call process() on the first found entry" do @connection.expects(:search).yields("myresult") - @searcher.expects(:process).with("yay", "myresult") + @searcher.expects(:process).with("myresult") @searcher.find @request end @@ -94,7 +86,7 @@ describe Puppet::Indirector::Ldap, " when searching ldap" do raise "failed" end end.yields("myresult") - @searcher.expects(:process).with("yay", "myresult") + @searcher.expects(:process).with("myresult") @searcher.find @request end diff --git a/spec/unit/indirector/node/ldap.rb b/spec/unit/indirector/node/ldap.rb index 24b2dd759..03faaa557 100755 --- a/spec/unit/indirector/node/ldap.rb +++ b/spec/unit/indirector/node/ldap.rb @@ -5,304 +5,307 @@ require File.dirname(__FILE__) + '/../../../spec_helper' require 'puppet/indirector/node/ldap' describe Puppet::Node::Ldap do - describe "when searching for nodes" do + before do + Puppet::Node::Facts.stubs(:terminus_class).returns :yaml + end + + describe "when searching for a single node" do before :each do @searcher = Puppet::Node::Ldap.new - @entries = {} - entries = @entries - @connection = mock 'connection' - @entry = mock 'entry' - @connection.stubs(:search).yields(@entry) - @searcher.stubs(:connection).returns(@connection) - @searcher.stubs(:class_attributes).returns([]) - @searcher.stubs(:parent_attribute).returns(nil) - @searcher.stubs(:stacked_attributes).returns([]) - @searcher.stubs(:search_base).returns(:yay) - @searcher.stubs(:search_filter).returns(:filter) - @name = "mynode.domain.com" - @node = stub 'node', :name => @name - @node.stubs(:fact_merge) - Puppet::Node.stubs(:new).with(@name).returns(@node) + @node = stub 'node', :name => @name, :name= => nil + @node.stub_everything + + Puppet::Node.stubs(:new).returns(@node) @request = stub 'request', :key => @name end - it "should search first for the provided key" do - @searcher.expects(:entry2hash).with("mynode.domain.com").returns({}) - @searcher.find(@request) + it "should convert the hostname into a search filter" do + entry = stub 'entry', :dn => 'cn=mynode.domain.com,ou=hosts,dc=madstop,dc=com', :vals => %w{}, :to_hash => {} + @searcher.expects(:ldapsearch).with("(&(objectclass=puppetClient)(cn=#{@name}))").yields entry + @searcher.name2hash(@name) end - it "should search for the short version of the provided key if the key looks like a hostname and no results are found for the key itself" do - @searcher.expects(:entry2hash).with("mynode.domain.com").returns(nil) - @searcher.expects(:entry2hash).with("mynode").returns({}) - @searcher.find(@request) + it "should convert any found entry into a hash" do + entry = stub 'entry', :dn => 'cn=mynode.domain.com,ou=hosts,dc=madstop,dc=com', :vals => %w{}, :to_hash => {} + @searcher.expects(:ldapsearch).with("(&(objectclass=puppetClient)(cn=#{@name}))").yields entry + @searcher.expects(:entry2hash).with(entry).returns "myhash" + @searcher.name2hash(@name).should == "myhash" end - it "should search for default information if no information can be found for the key" do - @searcher.expects(:entry2hash).with("mynode.domain.com").returns(nil) - @searcher.expects(:entry2hash).with("mynode").returns(nil) - @searcher.expects(:entry2hash).with("default").returns({}) - @searcher.find(@request) - end + # This heavily tests our entry2hash method, so we don't have to stub out the stupid entry information any more. + describe "when an ldap entry is found" do + before do + @entry = stub 'entry', :dn => 'cn=mynode.domain.com,ou=hosts,dc=madstop,dc=com', :vals => %w{}, :to_hash => {} + @searcher.stubs(:ldapsearch).yields @entry + end - it "should return nil if no results are found in ldap" do - @connection.stubs(:search) - @searcher.find(@request).should be_nil - end + it "should convert the entry to a hash" do + @searcher.entry2hash(@entry).should be_instance_of(Hash) + end - it "should return a node object if results are found in ldap" do - @entry.stubs(:to_hash).returns({}) - @searcher.find(@request).should equal(@node) - end + it "should add the entry's common name to the hash" do + @searcher.entry2hash(@entry)[:name].should == "mynode.domain.com" + end - it "should deduplicate class values" do - @entry.stubs(:to_hash).returns({}) - @searcher.stubs(:class_attributes).returns(%w{one two}) - @entry.stubs(:vals).with("one").returns(%w{a b}) - @entry.stubs(:vals).with("two").returns(%w{b c}) - @node.expects(:classes=).with(%w{a b c}) - @searcher.find(@request) - end + it "should add all of the entry's classes to the hash" do + @entry.stubs(:vals).with("puppetclass").returns %w{one two} + @searcher.entry2hash(@entry)[:classes].should == %w{one two} + end - it "should add any values stored in the class_attributes attributes to the node classes" do - @entry.stubs(:to_hash).returns({}) - @searcher.stubs(:class_attributes).returns(%w{one two}) - @entry.stubs(:vals).with("one").returns(%w{a b}) - @entry.stubs(:vals).with("two").returns(%w{c d}) - @node.expects(:classes=).with(%w{a b c d}) - @searcher.find(@request) + it "should deduplicate class values" do + @entry.stubs(:to_hash).returns({}) + @searcher.stubs(:class_attributes).returns(%w{one two}) + @entry.stubs(:vals).with("one").returns(%w{a b}) + @entry.stubs(:vals).with("two").returns(%w{b c}) + @searcher.entry2hash(@entry)[:classes].should == %w{a b c} + end + + it "should add the entry's environment to the hash" do + @entry.stubs(:to_hash).returns("environment" => %w{production}) + @searcher.entry2hash(@entry)[:environment].should == "production" + end + + it "should add all stacked parameters as parameters in the hash" do + @entry.stubs(:vals).with("puppetvar").returns(%w{one=two three=four}) + result = @searcher.entry2hash(@entry) + result[:parameters]["one"].should == "two" + result[:parameters]["three"].should == "four" + end + + it "should not add the stacked parameter as a normal parameter" do + @entry.stubs(:vals).with("puppetvar").returns(%w{one=two three=four}) + @entry.stubs(:to_hash).returns("puppetvar" => %w{one=two three=four}) + @searcher.entry2hash(@entry)[:parameters]["puppetvar"].should be_nil + end + + it "should add all other attributes as parameters in the hash" do + @entry.stubs(:to_hash).returns("foo" => %w{one two}) + @searcher.entry2hash(@entry)[:parameters]["foo"].should == %w{one two} + end + + it "should return single-value parameters as strings, not arrays" do + @entry.stubs(:to_hash).returns("foo" => %w{one}) + @searcher.entry2hash(@entry)[:parameters]["foo"].should == "one" + end + + it "should add the parent's name if present" do + @entry.stubs(:vals).with("parentnode").returns(%w{foo}) + @searcher.entry2hash(@entry)[:parent].should == "foo" + end + + it "should fail if more than one parent is specified" do + @entry.stubs(:vals).with("parentnode").returns(%w{foo}) + @searcher.entry2hash(@entry)[:parent].should == "foo" + end end - it "should add all entry attributes as node parameters" do - @entry.stubs(:to_hash).returns("one" => ["two"], "three" => ["four"]) - @node.expects(:parameters=).with("one" => "two", "three" => "four") + it "should search first for the provided key" do + @searcher.expects(:name2hash).with("mynode.domain.com").returns({}) @searcher.find(@request) end - it "should set the node's environment to the environment of the results" do - @entry.stubs(:to_hash).returns("environment" => ["test"]) - @node.stubs(:parameters=) - @node.expects(:environment=).with("test") + it "should search for the short version of the provided key if the key looks like a hostname and no results are found for the key itself" do + @searcher.expects(:name2hash).with("mynode.domain.com").returns(nil) + @searcher.expects(:name2hash).with("mynode").returns({}) @searcher.find(@request) end - it "should retain false parameter values" do - @entry.stubs(:to_hash).returns("one" => [false]) - @node.expects(:parameters=).with("one" => false) + it "should search for default information if no information can be found for the key" do + @searcher.expects(:name2hash).with("mynode.domain.com").returns(nil) + @searcher.expects(:name2hash).with("mynode").returns(nil) + @searcher.expects(:name2hash).with("default").returns({}) @searcher.find(@request) end - it "should turn single-value parameter value arrays into single non-arrays" do - @entry.stubs(:to_hash).returns("one" => ["a"]) - @node.expects(:parameters=).with("one" => "a") - @searcher.find(@request) + it "should return nil if no results are found in ldap" do + @searcher.stubs(:name2hash).returns nil + @searcher.find(@request).should be_nil end - it "should keep multi-valued parametes as arrays" do - @entry.stubs(:to_hash).returns("one" => ["a", "b"]) - @node.expects(:parameters=).with("one" => ["a", "b"]) - @searcher.find(@request) + it "should return a node object if results are found in ldap" do + @searcher.stubs(:name2hash).returns({}) + @searcher.find(@request).should equal(@node) end - describe "and a parent node is specified" do + describe "and node information is found in LDAP" do before do - @parent = mock 'parent' - @parent_parent = mock 'parent_parent' - - @searcher.meta_def(:search_filter) do |name| - return name - end - @connection.stubs(:search).with { |*args| args[2] == @name }.yields(@entry) - @connection.stubs(:search).with { |*args| args[2] == 'parent' }.yields(@parent) - @connection.stubs(:search).with { |*args| args[2] == 'parent_parent' }.yields(@parent_parent) - - @searcher.stubs(:parent_attribute).returns(:parent) + @result = {} + @searcher.stubs(:name2hash).returns @result end - it "should fail if the parent cannot be found" do - @connection.stubs(:search).with { |*args| args[2] == 'parent' }.returns("whatever") - - @entry.stubs(:to_hash).returns({}) - @entry.stubs(:vals).with(:parent).returns(%w{parent}) - - proc { @searcher.find(@request) }.should raise_error(Puppet::Error) - end - - it "should add any parent classes to the node's classes" do - @entry.stubs(:to_hash).returns({}) - @entry.stubs(:vals).with(:parent).returns(%w{parent}) - @entry.stubs(:vals).with("classes").returns(%w{a b}) - - @parent.stubs(:to_hash).returns({}) - @parent.stubs(:vals).with("classes").returns(%w{c d}) - @parent.stubs(:vals).with(:parent).returns(nil) - - @searcher.stubs(:class_attributes).returns(%w{classes}) + it "should add any classes from ldap" do + @result[:classes] = %w[a b c d] @node.expects(:classes=).with(%w{a b c d}) @searcher.find(@request) end - it "should add any parent parameters to the node's parameters" do - @entry.stubs(:to_hash).returns("one" => "two") - @entry.stubs(:vals).with(:parent).returns(%w{parent}) - - @parent.stubs(:to_hash).returns("three" => "four") - @parent.stubs(:vals).with(:parent).returns(nil) - + it "should add all entry attributes as node parameters" do + @result[:parameters] = {"one" => "two", "three" => "four"} @node.expects(:parameters=).with("one" => "two", "three" => "four") @searcher.find(@request) end - it "should prefer node parameters over parent parameters" do - @entry.stubs(:to_hash).returns("one" => "two") - @entry.stubs(:vals).with(:parent).returns(%w{parent}) - - @parent.stubs(:to_hash).returns("one" => "three") - @parent.stubs(:vals).with(:parent).returns(nil) + it "should set the node's environment to the environment of the results" do + @result[:environment] = "test" + @node.expects(:environment=).with("test") + @searcher.find(@request) + end - @node.expects(:parameters=).with("one" => "two") + it "should retain false parameter values" do + @result[:parameters] = {} + @result[:parameters]["one"] = false + @node.expects(:parameters=).with("one" => false) @searcher.find(@request) end - it "should use the parent's environment if the node has none" do - @entry.stubs(:to_hash).returns({}) - @entry.stubs(:vals).with(:parent).returns(%w{parent}) + describe "and a parent node is specified" do + before do + @entry = {:classes => [], :parameters => {}} + @parent = {:classes => [], :parameters => {}} + @parent_parent = {:classes => [], :parameters => {}} - @parent.stubs(:to_hash).returns("environment" => ["parent"]) - @parent.stubs(:vals).with(:parent).returns(nil) + @searcher.stubs(:name2hash).with(@name).returns(@entry) + @searcher.stubs(:name2hash).with('parent').returns(@parent) + @searcher.stubs(:name2hash).with('parent_parent').returns(@parent_parent) - @node.stubs(:parameters=) - @node.expects(:environment=).with("parent") - @searcher.find(@request) - end + @searcher.stubs(:parent_attribute).returns(:parent) + end - it "should prefer the node's environment to the parent's" do - @entry.stubs(:to_hash).returns("environment" => %w{child}) - @entry.stubs(:vals).with(:parent).returns(%w{parent}) + it "should search for the parent node" do + @entry[:parent] = "parent" - @parent.stubs(:to_hash).returns("environment" => ["parent"]) - @parent.stubs(:vals).with(:parent).returns(nil) + @searcher.expects(:name2hash).with(@name).returns @entry + @searcher.expects(:name2hash).with('parent').returns @parent - @node.stubs(:parameters=) - @node.expects(:environment=).with("child") - @searcher.find(@request) - end + @searcher.find(@request) + end - it "should recursively look up parent information" do - @entry.stubs(:to_hash).returns("one" => "two") - @entry.stubs(:vals).with(:parent).returns(%w{parent}) + it "should fail if the parent cannot be found" do + @entry[:parent] = "parent" - @parent.stubs(:to_hash).returns("three" => "four") - @parent.stubs(:vals).with(:parent).returns(['parent_parent']) + @searcher.expects(:name2hash).with('parent').returns nil - @parent_parent.stubs(:to_hash).returns("five" => "six") - @parent_parent.stubs(:vals).with(:parent).returns(nil) - @parent_parent.stubs(:vals).with(:parent).returns(nil) + proc { @searcher.find(@request) }.should raise_error(Puppet::Error) + end - @node.expects(:parameters=).with("one" => "two", "three" => "four", "five" => "six") - @searcher.find(@request) - end + it "should add any parent classes to the node's classes" do + @entry[:parent] = "parent" + @entry[:classes] = %w{a b} - it "should not allow loops in parent declarations" do - @entry.stubs(:to_hash).returns("one" => "two") - @entry.stubs(:vals).with(:parent).returns(%w{parent}) + @parent[:classes] = %w{c d} - @parent.stubs(:to_hash).returns("three" => "four") - @parent.stubs(:vals).with(:parent).returns([@name]) - proc { @searcher.find(@request) }.should raise_error(ArgumentError) - end - end + @node.expects(:classes=).with(%w{a b c d}) + @searcher.find(@request) + end - describe "and a puppet variable is specified" do - before do - @searcher.stubs(:stacked_attributes).returns(['puppetvar']) - end + it "should add any parent parameters to the node's parameters" do + @entry[:parent] = "parent" + @entry[:parameters]["one"] = "two" - it "should add the variable to the node parameters" do - @entry.stubs(:vals).with("puppetvar").returns(%w{one=two}) - @entry.stubs(:to_hash).returns({}) - @node.expects(:parameters=).with("one" => "two") - @searcher.find(@request) - end + @parent[:parameters]["three"] = "four" - it "should not overwrite node parameters specified as ldap object attribute" do - @entry.stubs(:vals).with("puppetvar").returns(%w{one=two}) - @entry.stubs(:to_hash).returns("one" => "three") - @node.expects(:parameters=).with("one" => "three") - @searcher.find(@request) - end + @node.expects(:parameters=).with("one" => "two", "three" => "four") + @searcher.find(@request) + end - it "should set entries without an equal sign to nil" do - @entry.stubs(:vals).with("puppetvar").returns(%w{one}) - @entry.stubs(:to_hash).returns({}) - @node.expects(:parameters=).with("one" => nil) - @searcher.find(@request) - end + it "should prefer node parameters over parent parameters" do + @entry[:parent] = "parent" + @entry[:parameters]["one"] = "two" - it "should ignore empty entries" do - @entry.stubs(:vals).with("puppetvar").returns(%w{}) - @entry.stubs(:to_hash).returns({}) - @searcher.find(@request) - end - end - describe "and a puppet variable as well as a parent node are specified" do - before do - @parent = mock 'parent' + @parent[:parameters]["one"] = "three" - @searcher.meta_def(:search_filter) do |name| - return name + @node.expects(:parameters=).with("one" => "two") + @searcher.find(@request) end - @connection.stubs(:search).with { |*args| args[2] == @name }.yields(@entry) - @connection.stubs(:search).with { |*args| args[2] == 'parent' }.yields(@parent) - @searcher.stubs(:stacked_attributes).returns(['puppetvar']) - @searcher.stubs(:parent_attribute).returns(:parent) - end + it "should use the parent's environment if the node has none" do + @entry[:parent] = "parent" - it "should add parent node variables to the child node parameters" do - @parent.stubs(:to_hash).returns({}) - @parent.stubs(:vals).with("puppetvar").returns(%w{one=two}) - @parent.stubs(:vals).with(:parent).returns(nil) + @parent[:environment] = "parent" - @entry.stubs(:to_hash).returns({}) - @entry.stubs(:vals).with("puppetvar").returns(%w{}) - @entry.stubs(:vals).with(:parent).returns(%w{parent}) + @node.stubs(:parameters=) + @node.expects(:environment=).with("parent") + @searcher.find(@request) + end - @node.expects(:parameters=).with("one" => "two") + it "should prefer the node's environment to the parent's" do + @entry[:parent] = "parent" + @entry[:environment] = "child" - @searcher.find(@request) - end + @parent[:environment] = "parent" - it "should overwrite parent node variables with child node parameters" do - @parent.stubs(:to_hash).returns({}) - @parent.stubs(:vals).with("puppetvar").returns(%w{one=two}) - @parent.stubs(:vals).with(:parent).returns(nil) + @node.stubs(:parameters=) + @node.expects(:environment=).with("child") + @searcher.find(@request) + end - @entry.stubs(:to_hash).returns({}) - @entry.stubs(:vals).with("puppetvar").returns(%w{one=three}) - @entry.stubs(:vals).with(:parent).returns(%w{parent}) + it "should recursively look up parent information" do + @entry[:parent] = "parent" + @entry[:parameters]["one"] = "two" - @node.expects(:parameters=).with("one" => "three") + @parent[:parent] = "parent_parent" + @parent[:parameters]["three"] = "four" - @searcher.find(@request) + @parent_parent[:parameters]["five"] = "six" + + @node.expects(:parameters=).with("one" => "two", "three" => "four", "five" => "six") + @searcher.find(@request) + end + + it "should not allow loops in parent declarations" do + @entry[:parent] = "parent" + @parent[:parent] = @name + proc { @searcher.find(@request) }.should raise_error(ArgumentError) + end end + end + end - it "should not overwrite parent node parameters specified as ldap object attribute" do - @parent.stubs(:to_hash).returns("one" => "three") - @parent.stubs(:vals).with("puppetvar").returns(%w{}) - @parent.stubs(:vals).with(:parent).returns(nil) + describe "when searching for multiple nodes" do + before :each do + @searcher = Puppet::Node::Ldap.new + @request = stub 'request', :key => @name - @entry.stubs(:vals).with("puppetvar").returns(%w{one=two}) - @entry.stubs(:to_hash).returns({}) - @entry.stubs(:vals).with(:parent).returns(%w{parent}) + Puppet::Node::Facts.stubs(:terminus_class).returns :yaml + end - @node.expects(:parameters=).with("one" => "three") + it "should find all nodes if no arguments are provided" do + @searcher.expects(:ldapsearch).with("(objectclass=puppetClient)") + # LAK:NOTE The search method requires an essentially bogus key. It's + # an API problem that I don't really know how to fix. + @searcher.search "foo" + end - @searcher.find(@request) + describe "and a class is specified" do + it "should find all nodes that are members of that class" do + @searcher.expects(:ldapsearch).with("(&(objectclass=puppetClient)(puppetclass=one))") + @searcher.search "foo", :class => "one" + end + end + + describe "multiple classes are specified" do + it "should find all nodes that are members of all classes" do + @searcher.expects(:ldapsearch).with("(&(objectclass=puppetClient)(puppetclass=one)(puppetclass=two))") + @searcher.search "foo", :class => ["one", "two"] end + end + + it "should process each found entry" do + # .yields can't be used to yield multiple values :/ + @searcher.expects(:ldapsearch).yields("one") + @searcher.expects(:entry2hash).with("one").returns(:name => "foo") + @searcher.search "foo" + end + it "should return a node for each processed entry" do + @searcher.expects(:ldapsearch).yields("one") + @searcher.expects(:entry2hash).with("one").returns(:name => "foo") + result = @searcher.search("foo") + result[0].should be_instance_of(Puppet::Node) + result[0].name.should == "foo" end end end -- cgit From 4d22a95b571991eb47046c3b0103b2e733b2801d Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Tue, 1 Jul 2008 22:06:40 -0500 Subject: Switching the ldap terminus to use Util::Ldap::Connection. This is a simplified class for managing ldap connections, and this work just removes some duplication. --- spec/unit/indirector/ldap.rb | 186 +++++++++++++++++++++---------------------- 1 file changed, 89 insertions(+), 97 deletions(-) (limited to 'spec/unit') diff --git a/spec/unit/indirector/ldap.rb b/spec/unit/indirector/ldap.rb index cf802d856..52abd413a 100755 --- a/spec/unit/indirector/ldap.rb +++ b/spec/unit/indirector/ldap.rb @@ -4,7 +4,7 @@ require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/indirector/ldap' -describe Puppet::Indirector::Ldap, " when searching ldap" do +describe Puppet::Indirector::Ldap do before do @indirection = stub 'indirection', :name => :testing Puppet::Indirector::Indirection.stubs(:instance).returns(@indirection) @@ -17,125 +17,117 @@ describe Puppet::Indirector::Ldap, " when searching ldap" do @connection = mock 'ldap' @searcher = @ldap_class.new - - # Stub everything, and we can selectively replace with an expect as - # we need to for testing. - @searcher.stubs(:connection).returns(@connection) - @searcher.stubs(:search_filter).returns(:filter) - @searcher.stubs(:search_base).returns(:base) - @searcher.stubs(:process) - - @request = stub 'request', :key => "yay" end - it "should call the ldapsearch method with the search filter" do - @searcher.expects(:search_filter).with("yay").returns("yay's filter") - @searcher.expects(:ldapsearch).with("yay's filter") - @searcher.find @request - end - - it "should fail if no block is passed to the ldapsearch method" do - proc { @searcher.ldapsearch("blah") }.should raise_error(ArgumentError) - end + describe "when searching ldap" do + before do + # Stub everything, and we can selectively replace with an expect as + # we need to for testing. + @searcher.stubs(:connection).returns(@connection) + @searcher.stubs(:search_filter).returns(:filter) + @searcher.stubs(:search_base).returns(:base) + @searcher.stubs(:process) - it "should use the results of the ldapbase method as the ldap search base" do - @searcher.stubs(:search_base).returns("mybase") - @connection.expects(:search).with do |*args| - args[0].should == "mybase" - true + @request = stub 'request', :key => "yay" end - @searcher.find @request - end - - it "should default to the value of the :search_base setting as the result of the ldapbase method" do - Puppet.expects(:[]).with(:ldapbase).returns("myldapbase") - searcher = @ldap_class.new - searcher.search_base.should == "myldapbase" - end - it "should use the results of the :search_attributes method as the list of attributes to return" do - @searcher.stubs(:search_attributes).returns(:myattrs) - @connection.expects(:search).with do |*args| - args[3].should == :myattrs - true + it "should call the ldapsearch method with the search filter" do + @searcher.expects(:search_filter).with("yay").returns("yay's filter") + @searcher.expects(:ldapsearch).with("yay's filter") + @searcher.find @request end - @searcher.find @request - end - it "should use depth 2 when searching" do - @connection.expects(:search).with do |*args| - args[1].should == 2 - true + it "should fail if no block is passed to the ldapsearch method" do + proc { @searcher.ldapsearch("blah") }.should raise_error(ArgumentError) end - @searcher.find @request - end - it "should call process() on the first found entry" do - @connection.expects(:search).yields("myresult") - @searcher.expects(:process).with("myresult") - @searcher.find @request - end - - it "should reconnect and retry the search if there is a failure" do - run = false - @connection.stubs(:search).with do |*args| - if run + it "should use the results of the ldapbase method as the ldap search base" do + @searcher.stubs(:search_base).returns("mybase") + @connection.expects(:search).with do |*args| + args[0].should == "mybase" true - else - run = true - raise "failed" end - end.yields("myresult") - @searcher.expects(:process).with("myresult") - - @searcher.find @request - end - - it "should not reconnect on failure more than once" do - count = 0 - @connection.stubs(:search).with do |*args| - count += 1 - raise ArgumentError, "yay" + @searcher.find @request end - proc { @searcher.find(@request) }.should raise_error(Puppet::Error) - count.should == 2 - end - - it "should return true if an entry is found" do - @connection.expects(:search).yields("result") - @searcher.ldapsearch("whatever") { |r| }.should be_true - end -end -describe Puppet::Indirector::Ldap, " when connecting to ldap" do - confine "LDAP is not available" => Puppet.features.ldap? - confine "No LDAP test data for networks other than Luke's" => Facter.value(:domain) == "madstop.com" - - it "should only create the ldap connection when asked for it the first time" + it "should default to the value of the :search_base setting as the result of the ldapbase method" do + Puppet.expects(:[]).with(:ldapbase).returns("myldapbase") + searcher = @ldap_class.new + searcher.search_base.should == "myldapbase" + end - it "should throw an exception if it cannot connect to LDAP" + it "should use the results of the :search_attributes method as the list of attributes to return" do + @searcher.stubs(:search_attributes).returns(:myattrs) + @connection.expects(:search).with do |*args| + args[3].should == :myattrs + true + end + @searcher.find @request + end - it "should use SSL when the :ldapssl setting is true" + it "should use depth 2 when searching" do + @connection.expects(:search).with do |*args| + args[1].should == 2 + true + end + @searcher.find @request + end - it "should connect to the server specified in the :ldapserver setting" + it "should call process() on the first found entry" do + @connection.expects(:search).yields("myresult") + @searcher.expects(:process).with("myresult") + @searcher.find @request + end - it "should use the port specified in the :ldapport setting" + it "should reconnect and retry the search if there is a failure" do + run = false + @connection.stubs(:search).with do |*args| + if run + true + else + run = true + raise "failed" + end + end.yields("myresult") + @searcher.expects(:process).with("myresult") + + @searcher.find @request + end - it "should use protocol version 3" + it "should not reconnect on failure more than once" do + count = 0 + @connection.stubs(:search).with do |*args| + count += 1 + raise ArgumentError, "yay" + end + proc { @searcher.find(@request) }.should raise_error(Puppet::Error) + count.should == 2 + end - it "should follow referrals" + it "should return true if an entry is found" do + @connection.expects(:search).yields("result") + @searcher.ldapsearch("whatever") { |r| }.should be_true + end + end - it "should use the user specified in the :ldapuser setting" + describe "when connecting to ldap" do + confine "LDAP is not available" => Puppet.features.ldap? - it "should use the password specified in the :ldappassord setting" + it "should only create the ldap connection when asked for it the first time" do + @searcher.connection.should equal(@searcher.connection) + end - it "should have an ldap method that returns an LDAP connection object" + it "should create and start a Util::Ldap::Connection instance" do + conn = mock 'connection', :connection => "myconn", :start => nil + Puppet::Util::Ldap::Connection.expects(:instance).returns conn - it "should fail when LDAP support is missing" -end + @searcher.connection.should == "myconn" + end + end -describe Puppet::Indirector::Ldap, " when reconnecting to ldap" do - confine "Not running on culain as root" => (Puppet::Util::SUIDManager.uid == 0 and Facter.value("hostname") == "culain") + describe "when reconnecting to ldap" do + confine "Not running on culain as root" => (Puppet::Util::SUIDManager.uid == 0 and Facter.value("hostname") == "culain") - it "should reconnect to ldap when connections are lost" + it "should reconnect to ldap when connections are lost" + end end -- cgit From c1e010fb7dfe4666b3db3d958627f70f7325cf85 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Tue, 1 Jul 2008 22:20:26 -0500 Subject: Fixing the Node::Ldap.search method to use an indirection request. I foolishly was just using the old-style api. Added an integration test to catch this in the future. --- spec/unit/indirector/node/ldap.rb | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'spec/unit') diff --git a/spec/unit/indirector/node/ldap.rb b/spec/unit/indirector/node/ldap.rb index 03faaa557..01d148631 100755 --- a/spec/unit/indirector/node/ldap.rb +++ b/spec/unit/indirector/node/ldap.rb @@ -267,7 +267,8 @@ describe Puppet::Node::Ldap do describe "when searching for multiple nodes" do before :each do @searcher = Puppet::Node::Ldap.new - @request = stub 'request', :key => @name + @options = {} + @request = stub 'request', :key => "foo", :options => @options Puppet::Node::Facts.stubs(:terminus_class).returns :yaml end @@ -276,20 +277,23 @@ describe Puppet::Node::Ldap do @searcher.expects(:ldapsearch).with("(objectclass=puppetClient)") # LAK:NOTE The search method requires an essentially bogus key. It's # an API problem that I don't really know how to fix. - @searcher.search "foo" + @searcher.search @request end describe "and a class is specified" do it "should find all nodes that are members of that class" do @searcher.expects(:ldapsearch).with("(&(objectclass=puppetClient)(puppetclass=one))") - @searcher.search "foo", :class => "one" + + @options[:class] = "one" + @searcher.search @request end end describe "multiple classes are specified" do it "should find all nodes that are members of all classes" do @searcher.expects(:ldapsearch).with("(&(objectclass=puppetClient)(puppetclass=one)(puppetclass=two))") - @searcher.search "foo", :class => ["one", "two"] + @options[:class] = %w{one two} + @searcher.search @request end end @@ -297,13 +301,13 @@ describe Puppet::Node::Ldap do # .yields can't be used to yield multiple values :/ @searcher.expects(:ldapsearch).yields("one") @searcher.expects(:entry2hash).with("one").returns(:name => "foo") - @searcher.search "foo" + @searcher.search @request end it "should return a node for each processed entry" do @searcher.expects(:ldapsearch).yields("one") @searcher.expects(:entry2hash).with("one").returns(:name => "foo") - result = @searcher.search("foo") + result = @searcher.search(@request) result[0].should be_instance_of(Puppet::Node) result[0].name.should == "foo" end -- cgit