From f0975df7ae2d57f8ac38ab5466b2a378ccabd855 Mon Sep 17 00:00:00 2001 From: David Lutterkort Date: Mon, 25 Feb 2008 10:10:01 -0800 Subject: Trac #1038: not a fix, just an attempt at improving the situation. That ticket is caused by _some_ process crashing whiule holding rpmdb locks (and doing that a lot) It is unclear whether yumhelper is that process, and why it would be crashing. This version tries much harder to exit cleanly no matter what. --- lib/puppet/provider/package/yumhelper.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/puppet/provider/package/yumhelper.py b/lib/puppet/provider/package/yumhelper.py index 1142401b9..962b96ce4 100644 --- a/lib/puppet/provider/package/yumhelper.py +++ b/lib/puppet/provider/package/yumhelper.py @@ -13,8 +13,7 @@ OVERRIDE_OPTS = { 'logfile': '/dev/null' } -def pkg_lists(): - my = yum.YumBase() +def pkg_lists(my): my.doConfigSetup() for k in OVERRIDE_OPTS.keys(): @@ -28,10 +27,13 @@ def pkg_lists(): return my.doPackageLists('updates') try: - ypl = pkg_lists() + try: + my = yum.YumBase() + ypl = pkg_lists(my) + for pkg in ypl.updates: + print "_pkg %s %s %s %s %s" % (pkg.name, pkg.epoch, pkg.version, pkg.release, pkg.arch) + finally: + my.closeRpmDB() except IOError, e: print "_err IOError %d %s" % (e.errno, e) sys.exit(1) - -for pkg in ypl.updates: - print "_pkg %s %s %s %s %s" % (pkg.name, pkg.epoch, pkg.version, pkg.release, pkg.arch) -- cgit From ff4f65a48392b41b2943e8ccd6762059d10bb46f Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Wed, 27 Feb 2008 14:52:20 -0500 Subject: replacing tabs with spaces in the redhat interface provider --- lib/puppet/provider/interface/redhat.rb | 130 ++++++++++++++++---------------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/lib/puppet/provider/interface/redhat.rb b/lib/puppet/provider/interface/redhat.rb index aa217620e..4a9fcb491 100644 --- a/lib/puppet/provider/interface/redhat.rb +++ b/lib/puppet/provider/interface/redhat.rb @@ -5,7 +5,7 @@ Puppet::Type.type(:interface).provide(:redhat) do desc "Manage network interfaces on Red Hat operating systems. This provider parses and generates configuration files in ``/etc/sysconfig/network-scripts``." - INTERFACE_DIR = "/etc/sysconfig/network-scripts" + INTERFACE_DIR = "/etc/sysconfig/network-scripts" confine :exists => INTERFACE_DIR defaultfor :operatingsystem => [:fedora, :centos, :redhat] @@ -43,52 +43,52 @@ NETMASK=<%= self.netmask %> BROADCAST= LOOPBACKDUMMY - # maximum number of dummy interfaces - @max_dummies = 10 + # maximum number of dummy interfaces + @max_dummies = 10 - # maximum number of aliases per interface - @max_aliases_per_iface = 10 + # maximum number of aliases per interface + @max_aliases_per_iface = 10 - @@dummies = [] - @@aliases = Hash.new { |hash, key| hash[key] = [] } + @@dummies = [] + @@aliases = Hash.new { |hash, key| hash[key] = [] } - # calculate which dummy interfaces are currently already in - # use prior to needing to call self.next_dummy later on. - def self.instances - # parse all of the config files at once - Dir.glob("%s/ifcfg-*" % INTERFACE_DIR).collect do |file| - record = parse(file) + # calculate which dummy interfaces are currently already in + # use prior to needing to call self.next_dummy later on. + def self.instances + # parse all of the config files at once + Dir.glob("%s/ifcfg-*" % INTERFACE_DIR).collect do |file| + record = parse(file) - # store the existing dummy interfaces + # store the existing dummy interfaces @@dummies << record[:ifnum] if (record[:interface_type] == :dummy and ! @@dummies.include?(record[:ifnum])) @@aliases[record[:interface]] << record[:ifnum] if record[:interface_type] == :alias new(record) - end - end - - # return the next avaliable dummy interface number, in the case where - # ifnum is not manually specified - def self.next_dummy - @max_dummies.times do |i| - unless @@dummies.include?(i.to_s) - @@dummies << i.to_s - return i.to_s - end - end - end - - # return the next available alias on a given interface, in the case - # where ifnum if not manually specified - def self.next_alias(interface) - @max_aliases_per_iface.times do |i| - unless @@aliases[interface].include?(i.to_s) - @@aliases[interface] << i.to_s - return i.to_s - end - end - end + end + end + + # return the next avaliable dummy interface number, in the case where + # ifnum is not manually specified + def self.next_dummy + @max_dummies.times do |i| + unless @@dummies.include?(i.to_s) + @@dummies << i.to_s + return i.to_s + end + end + end + + # return the next available alias on a given interface, in the case + # where ifnum if not manually specified + def self.next_alias(interface) + @max_aliases_per_iface.times do |i| + unless @@aliases[interface].include?(i.to_s) + @@aliases[interface] << i.to_s + return i.to_s + end + end + end # base the ifnum, for dummy / loopback interface in linux # on the last octect of the IP address @@ -139,14 +139,14 @@ LOOPBACKDUMMY # on whether we are adding an alias to a real interface, or a loopback # address (also dummy) on linux. For linux it's quite involved, and we # will use an ERB template - def generate + def generate itype = self.interface_type == :alias ? :alias : :normal self.class.template(itype).result(binding) - end + end # Where should the file be written out? - # This defaults to INTERFACE_DIR/ifcfg-, but can have a - # more symbolic name by setting interface_desc in the type. + # This defaults to INTERFACE_DIR/ifcfg-, but can have a + # more symbolic name by setting interface_desc in the type. def file_path if resource and val = resource[:interface_desc] desc = val @@ -185,16 +185,16 @@ LOOPBACKDUMMY end end - # create the device name, so this based on the IP, and interface + type - def device - case @resource.should(:interface_type) - when :loopback - @property_hash[:ifnum] ||= self.class.next_dummy - return "dummy" + @property_hash[:ifnum] - when :alias - @property_hash[:ifnum] ||= self.class.next_alias(@resource[:interface]) - return @resource[:interface] + ":" + @property_hash[:ifnum] - end + # create the device name, so this based on the IP, and interface + type + def device + case @resource.should(:interface_type) + when :loopback + @property_hash[:ifnum] ||= self.class.next_dummy + return "dummy" + @property_hash[:ifnum] + when :alias + @property_hash[:ifnum] ||= self.class.next_alias(@resource[:interface]) + return @resource[:interface] + ":" + @property_hash[:ifnum] + end end # Set the name to our ip address. @@ -202,19 +202,19 @@ LOOPBACKDUMMY @property_hash[:name] = value end - # whether the device is to be brought up on boot or not. converts - # the true / false of the type, into yes / no values respectively - # writing out the ifcfg-* files - def on_boot - case @property_hash[:onboot].to_s - when "true" - return "yes" - when "false" - return "no" - else - return "neither" - end - end + # whether the device is to be brought up on boot or not. converts + # the true / false of the type, into yes / no values respectively + # writing out the ifcfg-* files + def on_boot + case @property_hash[:onboot].to_s + when "true" + return "yes" + when "false" + return "no" + else + return "neither" + end + end # Mark whether the interface should be started on boot. def on_boot=(value) -- cgit From bb8051bc406d1da67db8212e852bb36d1368e953 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Wed, 27 Feb 2008 15:43:09 -0500 Subject: Removed the loglevels from the valid values for 'logoutput' in the Exec resource type -- the log levels are specified using the 'loglevel' parameter, not 'logoutput'. This never worked, or at least hasn't for ages, and now the docs are just correct. --- CHANGELOG | 6 ++++++ lib/puppet/type/exec.rb | 5 +---- test/ral/types/exec.rb | 4 ++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 234b24393..a82fd567a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,9 @@ + Removed the loglevels from the valid values for 'logoutput' + in the Exec resource type -- the log levels are specified + using the 'loglevel' parameter, not 'logoutput'. This never + worked, or at least hasn't for ages, and now the docs are + just correct. + Somewhat refactored fileserving so that it no longer caches any objects, nor does it use Puppet's RAL resources. In the process, I fixed #894 (you can now copy links) and refactored diff --git a/lib/puppet/type/exec.rb b/lib/puppet/type/exec.rb index f8049236f..2772b54a8 100755 --- a/lib/puppet/type/exec.rb +++ b/lib/puppet/type/exec.rb @@ -211,10 +211,7 @@ module Puppet log the output when the command reports an error. Values are **true**, *false*, *on_failure*, and any legal log level." - values = [:true, :false, :on_failure] - # And all of the log levels - Puppet::Util::Log.eachlevel { |level| values << level } - newvalues(*values) + newvalues(:true, :false, :on_failure) end newparam(:refresh) do diff --git a/test/ral/types/exec.rb b/test/ral/types/exec.rb index 4133d8519..e2a3dd9ed 100755 --- a/test/ral/types/exec.rb +++ b/test/ral/types/exec.rb @@ -394,8 +394,8 @@ class TestExec < Test::Unit::TestCase assert_apply(exec) assert_nothing_raised { - exec[:command] = "echo logoutput is warning" - exec[:logoutput] = "warning" + exec[:command] = "echo logoutput is on_failure" + exec[:logoutput] = "on_failure" } assert_apply(exec) -- cgit From 614ab9fcc33a7c4abffc0b407335f4a713f2fabd Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Thu, 28 Feb 2008 13:58:56 -0600 Subject: Adding a 'control' parameter to services, for those service types that need a control variable to enable/disable. --- lib/puppet/type/service.rb | 9 +++++++++ spec/unit/ral/types/service.rb | 15 +++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/puppet/type/service.rb b/lib/puppet/type/service.rb index c41a7883b..1b625cc41 100644 --- a/lib/puppet/type/service.rb +++ b/lib/puppet/type/service.rb @@ -28,6 +28,8 @@ module Puppet feature :enableable, "The provider can enable and disable the service", :methods => [:disable, :enable, :enabled?] + feature :controllable, "The provider uses a control variable." + newproperty(:enable, :required_features => :enableable) do desc "Whether a service should be enabled to start at boot. This property behaves quite differently depending on the platform; @@ -163,6 +165,13 @@ module Puppet desc "Specify a *stop* command manually." end + newparam(:control) do + desc "The control variable used to manage services (originally for HP-UX). + Defaults to the upcased service name plus ``START`` replacing dots with + underscores, for those providers that support the ``controllable`` feature." + defaultto { resource.name.gsub(".","_").upcase + "_START" if resource.provider.controllable? } + end + newparam :hasrestart do desc "Specify that an init script has a ``restart`` option. Otherwise, the init script's ``stop`` and ``start`` methods are used." diff --git a/spec/unit/ral/types/service.rb b/spec/unit/ral/types/service.rb index 981d38a15..0f00992fa 100755 --- a/spec/unit/ral/types/service.rb +++ b/spec/unit/ral/types/service.rb @@ -15,7 +15,7 @@ describe Puppet::Type::Service do end describe Puppet::Type::Service, "when validating attributes" do - [:name, :binary, :hasstatus, :path, :pattern, :start, :restart, :stop, :status, :hasrestart].each do |param| + [: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 end @@ -30,7 +30,7 @@ end describe Puppet::Type::Service, "when validating attribute values" do before do - @provider = stub 'provider', :class => Puppet::Type::Service.defaultprovider, :clear => nil + @provider = stub 'provider', :class => Puppet::Type::Service.defaultprovider, :clear => nil, :controllable? => false Puppet::Type::Service.defaultprovider.stubs(:new).returns(@provider) end @@ -132,16 +132,23 @@ describe Puppet::Type::Service, "when setting default attribute values" do svc[:path].should == ["testing"] end - it "should default to the binary for the pattern if one is provided" do + it "should default 'pattern' to the binary if one is provided" do svc = Puppet::Type::Service.create(:name => "other", :binary => "/some/binary") svc[:pattern].should == "/some/binary" end - it "should default to the name for the pattern if no pattern is provided" do + it "should default 'pattern' to the name if no pattern is provided" do svc = Puppet::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") + svc[:control].should == "NFS_CLIENT_START" + end + after { Puppet::Type::Service.clear } end -- cgit From c0b5352851d3fdef20b2a432f6f06d31fdc9ce99 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Thu, 28 Feb 2008 14:07:01 -0600 Subject: testing automatic commit emails --- CHANGELOG | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index a82fd567a..59dde24a2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,7 @@ - Removed the loglevels from the valid values for 'logoutput' + Removed the loglevels from the valid values for `logoutput` in the Exec resource type -- the log levels are specified - using the 'loglevel' parameter, not 'logoutput'. This never - worked, or at least hasn't for ages, and now the docs are + using the `loglevel` parameter, not `logoutput`. This never + worked, or at least hasn`t for ages, and now the docs are just correct. Somewhat refactored fileserving so that it no longer caches -- cgit From dd17d4ca71e17deba8cf19e376e2d711fa516d92 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Thu, 28 Feb 2008 14:44:29 -0600 Subject: Fixing #1093 -- 0.23.2 clients are again compatible with 0.24.x servers. :ignore links is now equivalent to :manage links. --- lib/puppet/file_serving/file_base.rb | 1 + spec/unit/file_serving/file_base.rb | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/puppet/file_serving/file_base.rb b/lib/puppet/file_serving/file_base.rb index 06b3ad9ef..e87d683aa 100644 --- a/lib/puppet/file_serving/file_base.rb +++ b/lib/puppet/file_serving/file_base.rb @@ -46,6 +46,7 @@ class Puppet::FileServing::FileBase # Determine how we deal with links. attr_reader :links def links=(value) + value = :manage if value == :ignore raise(ArgumentError, ":links can only be set to :manage or :follow") unless [:manage, :follow].include?(value) @links = value end diff --git a/spec/unit/file_serving/file_base.rb b/spec/unit/file_serving/file_base.rb index e1a61cd65..ded6ae4a8 100755 --- a/spec/unit/file_serving/file_base.rb +++ b/spec/unit/file_serving/file_base.rb @@ -13,7 +13,11 @@ describe Puppet::FileServing::FileBase do Puppet::FileServing::FileBase.new("puppet://host/module/dir/file", :links => :manage).links.should == :manage end - it "should fail if :links is set to anything other than :manage or :follow" do + it "should consider :ignore links equivalent to :manage links" do + Puppet::FileServing::FileBase.new("puppet://host/module/dir/file", :links => :ignore).links.should == :manage + end + + it "should fail if :links is set to anything other than :manage, :follow, or :ignore" do proc { Puppet::FileServing::FileBase.new("puppet://host/module/dir/file", :links => :else) }.should raise_error(ArgumentError) end -- cgit From 82b02b90493f0abc173ec4cc09948106ae5190cd Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Thu, 28 Feb 2008 14:49:32 -0600 Subject: Fixing #1101 -- puppetrun works again. --- bin/puppetrun | 7 +------ lib/puppet/network/client.rb | 2 ++ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/bin/puppetrun b/bin/puppetrun index c92b59fc6..d0823b9c5 100755 --- a/bin/puppetrun +++ b/bin/puppetrun @@ -274,12 +274,7 @@ else end # Now parse the config -config = File.join(Puppet[:confdir], "puppet.conf") -Puppet.parse_config(config) - -if File.exists? config - Puppet.settings.parse(config) -end +Puppet.parse_config if Puppet[:node_terminus] = "ldap" if options[:all] diff --git a/lib/puppet/network/client.rb b/lib/puppet/network/client.rb index 0a0a72345..cf1782f79 100644 --- a/lib/puppet/network/client.rb +++ b/lib/puppet/network/client.rb @@ -7,6 +7,8 @@ require 'puppet/util/subclass_loader' require 'puppet/util/methodhelper' require 'puppet/sslcertificates/support' +require 'puppet/network/handler' + require 'net/http' # Some versions of ruby don't have this method defined, which basically causes -- cgit From 29aafb4e98b8751a11787be33b2dfcf910a84fa3 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Thu, 28 Feb 2008 15:54:03 -0600 Subject: Fixing an integration test so it cleans up after itself --- spec/integration/node.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spec/integration/node.rb b/spec/integration/node.rb index e4a311998..87ff448e4 100755 --- a/spec/integration/node.rb +++ b/spec/integration/node.rb @@ -10,10 +10,15 @@ require 'puppet/node' describe Puppet::Node, " when using the memory terminus" do before do @name = "me" + @old_terminus = Puppet::Node.indirection.terminus_class Puppet::Node.terminus_class = :memory @node = Puppet::Node.new(@name) end + after do + Puppet::Node.terminus_class = @old_terminus + end + it "should find no nodes by default" do Puppet::Node.find(@name).should be_nil end -- cgit From abd688ea1a0ebd555eac20185d82cc6430507edf Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Thu, 28 Feb 2008 15:55:39 -0600 Subject: Fixing #1092 by no longer using the resource reference to look resources up, which means there's no concern about not finding the resource, which is where the nil was coming from. We now just iterate over the vertices. --- lib/puppet/parser/compiler.rb | 5 ++--- spec/unit/parser/compiler.rb | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/puppet/parser/compiler.rb b/lib/puppet/parser/compiler.rb index 132ec15db..70cd6e11a 100644 --- a/lib/puppet/parser/compiler.rb +++ b/lib/puppet/parser/compiler.rb @@ -366,9 +366,8 @@ class Puppet::Parser::Compiler # Make sure all of our resources and such have done any last work # necessary. def finish - @catalog.resources.each do |name| - resource = @catalog.resource(name) - + #@catalog.resources.each do |name| + @catalog.vertices.each do |resource| # Add in any resource overrides. if overrides = resource_overrides(resource) overrides.each do |over| diff --git a/spec/unit/parser/compiler.rb b/spec/unit/parser/compiler.rb index 9980f2c6a..ab430da62 100755 --- a/spec/unit/parser/compiler.rb +++ b/spec/unit/parser/compiler.rb @@ -7,7 +7,7 @@ describe Puppet::Parser::Compiler do @node = Puppet::Node.new "testnode" @parser = Puppet::Parser::Parser.new :environment => "development" - @scope_resource = stub 'scope_resource', :builtin? => true + @scope_resource = stub 'scope_resource', :builtin? => true, :finish => nil, :ref => 'Class[main]' @scope = stub 'scope', :resource => @scope_resource, :source => mock("source") @compiler = Puppet::Parser::Compiler.new(@node, @parser) end @@ -529,4 +529,4 @@ describe Puppet::Parser::Compiler do lambda { @compiler.class_set("one", @node) }.should raise_error(Puppet::ParseError) end end -end \ No newline at end of file +end -- cgit From 9d6e926d8196294afe6b5a03c20a9035056575f1 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Thu, 28 Feb 2008 16:12:48 -0600 Subject: Fixed #1063 -- the master correctly logs syntax errors when reparsing during a single run. --- CHANGELOG | 3 + lib/puppet/parser/interpreter.rb | 6 +- spec/unit/parser/interpreter.rb | 286 ++++++++++++++++++++------------------- 3 files changed, 156 insertions(+), 139 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 59dde24a2..f878f9c8f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ + Fixed #1063 -- the master correctly logs syntax errors when + reparsing during a single run. + Removed the loglevels from the valid values for `logoutput` in the Exec resource type -- the log levels are specified using the `loglevel` parameter, not `logoutput`. This never diff --git a/lib/puppet/parser/interpreter.rb b/lib/puppet/parser/interpreter.rb index d4655c403..f27c1c5c8 100644 --- a/lib/puppet/parser/interpreter.rb +++ b/lib/puppet/parser/interpreter.rb @@ -61,7 +61,11 @@ class Puppet::Parser::Interpreter # If a parser already exists, than assume that we logged the # exception elsewhere and reuse the parser. If one doesn't # exist, then reraise. - raise detail unless @parsers[environment] + if @parsers[environment] + Puppet.err detail + else + raise detail + end end end @parsers[environment] diff --git a/spec/unit/parser/interpreter.rb b/spec/unit/parser/interpreter.rb index eb5dd9aaf..f2526c73d 100755 --- a/spec/unit/parser/interpreter.rb +++ b/spec/unit/parser/interpreter.rb @@ -2,148 +2,158 @@ require File.dirname(__FILE__) + '/../../spec_helper' -describe Puppet::Parser::Interpreter, " when creating parser instances" do +describe Puppet::Parser::Interpreter do before do @interp = Puppet::Parser::Interpreter.new - @parser = mock('parser') - end - - it "should create a parser with code if there is code defined in the :code setting" do - Puppet.settings.stubs(:value).with(:code, :myenv).returns("mycode") - @parser.expects(:string=).with("mycode") - @parser.expects(:parse) - Puppet::Parser::Parser.expects(:new).with(:environment => :myenv).returns(@parser) - @interp.send(:create_parser, :myenv).object_id.should equal(@parser.object_id) - end - - it "should create a parser with the main manifest when the code setting is an empty string" do - Puppet.settings.stubs(:value).with(:code, :myenv).returns("") - Puppet.settings.stubs(:value).with(:manifest, :myenv).returns("/my/file") - @parser.expects(:parse) - @parser.expects(:file=).with("/my/file") - Puppet::Parser::Parser.expects(:new).with(:environment => :myenv).returns(@parser) - @interp.send(:create_parser, :myenv).should equal(@parser) - end - - it "should return nothing when new parsers fail" do - Puppet::Parser::Parser.expects(:new).with(:environment => :myenv).raises(ArgumentError) - proc { @interp.send(:create_parser, :myenv) }.should raise_error(Puppet::Error) - end - - it "should create parsers with environment-appropriate manifests" do - # Set our per-environment values. We can't just stub :value, because - # it's called by too much of the rest of the code. - text = "[env1]\nmanifest = /t/env1.pp\n[env2]\nmanifest = /t/env2.pp" - file = mock 'file' - file.stubs(:changed?).returns(true) - file.stubs(:file).returns("/whatever") - Puppet.settings.stubs(:read_file).with(file).returns(text) - Puppet.settings.parse(file) - - parser1 = mock 'parser1' - Puppet::Parser::Parser.expects(:new).with(:environment => :env1).returns(parser1) - parser1.expects(:file=).with("/t/env1.pp") - parser1.expects(:parse) - @interp.send(:create_parser, :env1) - - parser2 = mock 'parser2' - Puppet::Parser::Parser.expects(:new).with(:environment => :env2).returns(parser2) - parser2.expects(:file=).with("/t/env2.pp") - parser2.expects(:parse) - @interp.send(:create_parser, :env2) - end -end - -describe Puppet::Parser::Interpreter, " when managing parser instances" do - before do - @interp = Puppet::Parser::Interpreter.new - @parser = mock('parser') - end - - it "should use the same parser when the parser does not need reparsing" do - @interp.expects(:create_parser).with(:myenv).returns(@parser) - @interp.send(:parser, :myenv).should equal(@parser) - - @parser.expects(:reparse?).returns(false) - @interp.send(:parser, :myenv).should equal(@parser) - end - - it "should create a new parser when reparse is true" do - oldparser = mock('oldparser') - newparser = mock('newparser') - oldparser.expects(:reparse?).returns(true) - oldparser.expects(:clear) - - @interp.expects(:create_parser).with(:myenv).returns(oldparser) - @interp.send(:parser, :myenv).should equal(oldparser) - @interp.expects(:create_parser).with(:myenv).returns(newparser) - @interp.send(:parser, :myenv).should equal(newparser) - end - - it "should fail intelligently if a parser cannot be created and one does not already exist" do - @interp.expects(:create_parser).with(:myenv).raises(ArgumentError) - proc { @interp.send(:parser, :myenv) }.should raise_error(ArgumentError) - end - - it "should keep the old parser if a new parser cannot be created" do - # Get the first parser in the hash. - @interp.expects(:create_parser).with(:myenv).returns(@parser) - @interp.send(:parser, :myenv).should equal(@parser) - - # Have it indicate something has changed - @parser.expects(:reparse?).returns(true) - - # But fail to create a new parser - @interp.expects(:create_parser).with(:myenv).raises(ArgumentError) - - # And make sure we still get the old valid parser - @interp.send(:parser, :myenv).should equal(@parser) - end - - it "should use different parsers for different environments" do - # get one for the first env - @interp.expects(:create_parser).with(:first_env).returns(@parser) - @interp.send(:parser, :first_env).should equal(@parser) - - other_parser = mock('otherparser') - @interp.expects(:create_parser).with(:second_env).returns(other_parser) - @interp.send(:parser, :second_env).should equal(other_parser) - end -end - -describe Puppet::Parser::Interpreter, " when compiling catalog" do - before do - @interp = Puppet::Parser::Interpreter.new - @node = stub 'node', :environment => :myenv - @compiler = mock 'compile' @parser = mock 'parser' end - it "should create a compile with the node and parser" do - @compiler.expects(:compile).returns(:config) - @interp.expects(:parser).with(:myenv).returns(@parser) - Puppet::Parser::Compiler.expects(:new).with(@node, @parser).returns(@compiler) - @interp.compile(@node) - end - - it "should fail intelligently when no parser can be found" do - @node.stubs(:name).returns("whatever") - @interp.expects(:parser).with(:myenv).returns(nil) - proc { @interp.compile(@node) }.should raise_error(Puppet::ParseError) - end -end - -describe Puppet::Parser::Interpreter, " when returning catalog version" do - before do - @interp = Puppet::Parser::Interpreter.new - end - - it "should ask the appropriate parser for the catalog version" do - node = mock 'node' - node.expects(:environment).returns(:myenv) - parser = mock 'parser' - parser.expects(:version).returns(:myvers) - @interp.expects(:parser).with(:myenv).returns(parser) - @interp.configuration_version(node).should equal(:myvers) + describe "when creating parser instances" do + it "should create a parser with code if there is code defined in the :code setting" do + Puppet.settings.stubs(:value).with(:code, :myenv).returns("mycode") + @parser.expects(:string=).with("mycode") + @parser.expects(:parse) + Puppet::Parser::Parser.expects(:new).with(:environment => :myenv).returns(@parser) + @interp.send(:create_parser, :myenv).object_id.should equal(@parser.object_id) + end + + it "should create a parser with the main manifest when the code setting is an empty string" do + Puppet.settings.stubs(:value).with(:code, :myenv).returns("") + Puppet.settings.stubs(:value).with(:manifest, :myenv).returns("/my/file") + @parser.expects(:parse) + @parser.expects(:file=).with("/my/file") + Puppet::Parser::Parser.expects(:new).with(:environment => :myenv).returns(@parser) + @interp.send(:create_parser, :myenv).should equal(@parser) + end + + it "should return nothing when new parsers fail" do + Puppet::Parser::Parser.expects(:new).with(:environment => :myenv).raises(ArgumentError) + proc { @interp.send(:create_parser, :myenv) }.should raise_error(Puppet::Error) + end + + it "should create parsers with environment-appropriate manifests" do + # Set our per-environment values. We can't just stub :value, because + # it's called by too much of the rest of the code. + text = "[env1]\nmanifest = /t/env1.pp\n[env2]\nmanifest = /t/env2.pp" + file = mock 'file' + file.stubs(:changed?).returns(true) + file.stubs(:file).returns("/whatever") + Puppet.settings.stubs(:read_file).with(file).returns(text) + Puppet.settings.parse(file) + + parser1 = mock 'parser1' + Puppet::Parser::Parser.expects(:new).with(:environment => :env1).returns(parser1) + parser1.expects(:file=).with("/t/env1.pp") + parser1.expects(:parse) + @interp.send(:create_parser, :env1) + + parser2 = mock 'parser2' + Puppet::Parser::Parser.expects(:new).with(:environment => :env2).returns(parser2) + parser2.expects(:file=).with("/t/env2.pp") + parser2.expects(:parse) + @interp.send(:create_parser, :env2) + end + end + + describe "when managing parser instances" do + it "should use the same parser when the parser does not need reparsing" do + @interp.expects(:create_parser).with(:myenv).returns(@parser) + @interp.send(:parser, :myenv).should equal(@parser) + + @parser.expects(:reparse?).returns(false) + @interp.send(:parser, :myenv).should equal(@parser) + end + + it "should fail intelligently if a parser cannot be created and one does not already exist" do + @interp.expects(:create_parser).with(:myenv).raises(ArgumentError) + proc { @interp.send(:parser, :myenv) }.should raise_error(ArgumentError) + end + + it "should use different parsers for different environments" do + # get one for the first env + @interp.expects(:create_parser).with(:first_env).returns(@parser) + @interp.send(:parser, :first_env).should equal(@parser) + + other_parser = mock('otherparser') + @interp.expects(:create_parser).with(:second_env).returns(other_parser) + @interp.send(:parser, :second_env).should equal(other_parser) + end + + describe "when files need reparsing" do + it "should create a new parser" do + oldparser = mock('oldparser') + newparser = mock('newparser') + oldparser.expects(:reparse?).returns(true) + oldparser.expects(:clear) + + @interp.expects(:create_parser).with(:myenv).returns(oldparser) + @interp.send(:parser, :myenv).should equal(oldparser) + @interp.expects(:create_parser).with(:myenv).returns(newparser) + @interp.send(:parser, :myenv).should equal(newparser) + end + + it "should keep the old parser if a new parser cannot be created" do + # Get the first parser in the hash. + @interp.expects(:create_parser).with(:myenv).returns(@parser) + @interp.send(:parser, :myenv).should equal(@parser) + + # Have it indicate something has changed + @parser.expects(:reparse?).returns(true) + + # But fail to create a new parser + @interp.expects(:create_parser).with(:myenv).raises(ArgumentError) + + # And make sure we still get the old valid parser + @interp.send(:parser, :myenv).should equal(@parser) + end + + it "should log syntax errors when using the old parser" do + # Get the first parser in the hash. + @interp.stubs(:create_parser).with(:myenv).returns(@parser) + @interp.send(:parser, :myenv) + + # Have it indicate something has changed + @parser.stubs(:reparse?).returns(true) + + # But fail to create a new parser + @interp.stubs(:create_parser).with(:myenv).raises(ArgumentError) + + Puppet.expects(:err) + + # And make sure we still get the old valid parser + @interp.send(:parser, :myenv) + end + end + end + + describe "when compiling a catalog" do + before do + @node = stub 'node', :environment => :myenv + @compiler = mock 'compile' + end + + it "should create a compile with the node and parser" do + @compiler.expects(:compile).returns(:config) + @interp.expects(:parser).with(:myenv).returns(@parser) + Puppet::Parser::Compiler.expects(:new).with(@node, @parser).returns(@compiler) + @interp.compile(@node) + end + + it "should fail intelligently when no parser can be found" do + @node.stubs(:name).returns("whatever") + @interp.expects(:parser).with(:myenv).returns(nil) + proc { @interp.compile(@node) }.should raise_error(Puppet::ParseError) + end + end + + describe "when returning catalog version" do + it "should ask the appropriate parser for the catalog version" do + node = mock 'node' + node.expects(:environment).returns(:myenv) + parser = mock 'parser' + parser.expects(:version).returns(:myvers) + @interp.expects(:parser).with(:myenv).returns(parser) + @interp.configuration_version(node).should equal(:myvers) + end end end -- cgit From fd1573fdb696803deb7a220d6bfd06b8afff55fb Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Thu, 28 Feb 2008 17:21:35 -0600 Subject: Fixed #1047 -- Puppet's parser no longer changes the order in which statements are evaluated, which means that case statements can now set variables that are used by other variables. --- CHANGELOG | 5 +++++ lib/puppet/parser/ast/astarray.rb | 24 +++--------------------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index f878f9c8f..cafb2d959 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ + Fixed #1047 -- Puppet's parser no longer changes the order + in which statements are evaluated, which means that case + statements can now set variables that are used by other + variables. + Fixed #1063 -- the master correctly logs syntax errors when reparsing during a single run. diff --git a/lib/puppet/parser/ast/astarray.rb b/lib/puppet/parser/ast/astarray.rb index b66fd6bba..8f09aa922 100644 --- a/lib/puppet/parser/ast/astarray.rb +++ b/lib/puppet/parser/ast/astarray.rb @@ -16,16 +16,6 @@ class Puppet::Parser::AST # Evaluate our children. def evaluate(scope) - rets = nil - # We basically always operate declaratively, and when we - # do we need to evaluate the settor-like statements first. This - # is basically variable and type-default declarations. - # This is such a stupid hack. I've no real idea how to make a - # "real" declarative language, so I hack it so it looks like - # one, yay. - settors = [] - others = [] - # Make a new array, so we don't have to deal with the details of # flattening and such items = [] @@ -34,22 +24,14 @@ class Puppet::Parser::AST @children.each { |child| if child.instance_of?(AST::ASTArray) child.each do |ac| - if ac.class.settor? - settors << ac - else - others << ac - end + items << ac end else - if child.class.settor? - settors << child - else - others << child - end + items << child end } - rets = [settors, others].flatten.collect { |child| + rets = items.flatten.collect { |child| child.safeevaluate(scope) } return rets.reject { |o| o.nil? } -- cgit From 879ee22ee31309b04428d22f73953026e9111ed3 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Thu, 28 Feb 2008 17:40:01 -0600 Subject: Fixing #1062 by moving the yamldir setting to its own yaml section. This should keep the yamldir from being created on clients. --- CHANGELOG | 4 ++++ lib/puppet/defaults.rb | 7 +++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index cafb2d959..825fad225 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ + Fixing #1062 by moving the yamldir setting to its own yaml + section. This should keep the yamldir from being created + on clients. + Fixed #1047 -- Puppet's parser no longer changes the order in which statements are evaluated, which means that case statements can now set variables that are used by other diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb index 520a18d1a..77792172f 100644 --- a/lib/puppet/defaults.rb +++ b/lib/puppet/defaults.rb @@ -140,8 +140,6 @@ module Puppet :show_diff => [false, "Whether to print a contextual diff when files are being replaced. The diff is printed on stdout, so this option is meaningless unless you are running Puppet interactively. This feature currently requires the ``diff/lcs`` Ruby library."], - :yamldir => {:default => "$vardir/yaml", :owner => "$user", :group => "$user", :mode => "750", - :desc => "The directory in which YAML data is stored, usually in a subdirectory."}, :daemonize => { :default => true, :desc => "Send the process into the background. This is the default.", :short => "D" @@ -672,5 +670,10 @@ module Puppet :rrdinterval => ["$runinterval", "How often RRD should expect data. This should match how often the hosts report back to the server."] ) + + Puppet.setdefaults(:yaml, + :yamldir => {:default => "$vardir/yaml", :owner => "$user", :group => "$user", :mode => "750", + :desc => "The directory in which YAML data is stored, usually in a subdirectory."} + ) end -- cgit From 43aea83eb1ac388566246e5418394e31a4cad697 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Thu, 28 Feb 2008 17:53:46 -0600 Subject: renaming ral/types to ral/type in the tests --- spec/unit/ral/type/exec.rb | 93 ++ spec/unit/ral/type/file.rb | 99 ++ spec/unit/ral/type/interface.rb | 95 ++ spec/unit/ral/type/mount.rb | 192 ++++ spec/unit/ral/type/nagios.rb | 55 ++ spec/unit/ral/type/package.rb | 247 +++++ spec/unit/ral/type/schedule.rb | 341 +++++++ spec/unit/ral/type/service.rb | 256 ++++++ spec/unit/ral/type/user.rb | 58 ++ spec/unit/ral/types/exec.rb | 93 -- spec/unit/ral/types/file.rb | 99 -- spec/unit/ral/types/interface.rb | 95 -- spec/unit/ral/types/mount.rb | 192 ---- spec/unit/ral/types/nagios.rb | 55 -- spec/unit/ral/types/package.rb | 247 ----- spec/unit/ral/types/schedule.rb | 341 ------- spec/unit/ral/types/service.rb | 256 ------ spec/unit/ral/types/user.rb | 58 -- test/ral/type/basic.rb | 85 ++ test/ral/type/cron.rb | 499 ++++++++++ test/ral/type/exec.rb | 770 ++++++++++++++++ test/ral/type/file.rb | 1782 ++++++++++++++++++++++++++++++++++++ test/ral/type/file/target.rb | 364 ++++++++ test/ral/type/filebucket.rb | 157 ++++ test/ral/type/fileignoresource.rb | 245 +++++ test/ral/type/filesources.rb | 997 ++++++++++++++++++++ test/ral/type/group.rb | 171 ++++ test/ral/type/host.rb | 181 ++++ test/ral/type/mailalias.rb | 49 + test/ral/type/parameter.rb | 174 ++++ test/ral/type/port.rb | 147 +++ test/ral/type/property.rb | 388 ++++++++ test/ral/type/resources.rb | 208 +++++ test/ral/type/service.rb | 38 + test/ral/type/sshkey.rb | 194 ++++ test/ral/type/tidy.rb | 291 ++++++ test/ral/type/user.rb | 492 ++++++++++ test/ral/type/yumrepo.rb | 106 +++ test/ral/type/zone.rb | 420 +++++++++ test/ral/types/basic.rb | 85 -- test/ral/types/cron.rb | 499 ---------- test/ral/types/exec.rb | 770 ---------------- test/ral/types/file.rb | 1782 ------------------------------------ test/ral/types/file/target.rb | 364 -------- test/ral/types/filebucket.rb | 157 ---- test/ral/types/fileignoresource.rb | 245 ----- test/ral/types/filesources.rb | 997 -------------------- test/ral/types/group.rb | 171 ---- test/ral/types/host.rb | 181 ---- test/ral/types/mailalias.rb | 49 - test/ral/types/parameter.rb | 174 ---- test/ral/types/port.rb | 147 --- test/ral/types/property.rb | 388 -------- test/ral/types/resources.rb | 208 ----- test/ral/types/service.rb | 38 - test/ral/types/sshkey.rb | 194 ---- test/ral/types/tidy.rb | 291 ------ test/ral/types/user.rb | 492 ---------- test/ral/types/yumrepo.rb | 106 --- test/ral/types/zone.rb | 420 --------- 60 files changed, 9194 insertions(+), 9194 deletions(-) create mode 100755 spec/unit/ral/type/exec.rb create mode 100755 spec/unit/ral/type/file.rb create mode 100755 spec/unit/ral/type/interface.rb create mode 100755 spec/unit/ral/type/mount.rb create mode 100755 spec/unit/ral/type/nagios.rb create mode 100755 spec/unit/ral/type/package.rb create mode 100755 spec/unit/ral/type/schedule.rb create mode 100755 spec/unit/ral/type/service.rb create mode 100755 spec/unit/ral/type/user.rb delete mode 100755 spec/unit/ral/types/exec.rb delete mode 100755 spec/unit/ral/types/file.rb delete mode 100755 spec/unit/ral/types/interface.rb delete mode 100755 spec/unit/ral/types/mount.rb delete mode 100755 spec/unit/ral/types/nagios.rb delete mode 100755 spec/unit/ral/types/package.rb delete mode 100755 spec/unit/ral/types/schedule.rb delete mode 100755 spec/unit/ral/types/service.rb delete mode 100755 spec/unit/ral/types/user.rb create mode 100755 test/ral/type/basic.rb create mode 100755 test/ral/type/cron.rb create mode 100755 test/ral/type/exec.rb create mode 100755 test/ral/type/file.rb create mode 100755 test/ral/type/file/target.rb create mode 100755 test/ral/type/filebucket.rb create mode 100755 test/ral/type/fileignoresource.rb create mode 100755 test/ral/type/filesources.rb create mode 100755 test/ral/type/group.rb create mode 100755 test/ral/type/host.rb create mode 100755 test/ral/type/mailalias.rb create mode 100755 test/ral/type/parameter.rb create mode 100755 test/ral/type/port.rb create mode 100755 test/ral/type/property.rb create mode 100755 test/ral/type/resources.rb create mode 100755 test/ral/type/service.rb create mode 100755 test/ral/type/sshkey.rb create mode 100755 test/ral/type/tidy.rb create mode 100755 test/ral/type/user.rb create mode 100755 test/ral/type/yumrepo.rb create mode 100755 test/ral/type/zone.rb delete mode 100755 test/ral/types/basic.rb delete mode 100755 test/ral/types/cron.rb delete mode 100755 test/ral/types/exec.rb delete mode 100755 test/ral/types/file.rb delete mode 100755 test/ral/types/file/target.rb delete mode 100755 test/ral/types/filebucket.rb delete mode 100755 test/ral/types/fileignoresource.rb delete mode 100755 test/ral/types/filesources.rb delete mode 100755 test/ral/types/group.rb delete mode 100755 test/ral/types/host.rb delete mode 100755 test/ral/types/mailalias.rb delete mode 100755 test/ral/types/parameter.rb delete mode 100755 test/ral/types/port.rb delete mode 100755 test/ral/types/property.rb delete mode 100755 test/ral/types/resources.rb delete mode 100755 test/ral/types/service.rb delete mode 100755 test/ral/types/sshkey.rb delete mode 100755 test/ral/types/tidy.rb delete mode 100755 test/ral/types/user.rb delete mode 100755 test/ral/types/yumrepo.rb delete mode 100755 test/ral/types/zone.rb diff --git a/spec/unit/ral/type/exec.rb b/spec/unit/ral/type/exec.rb new file mode 100755 index 000000000..260804227 --- /dev/null +++ b/spec/unit/ral/type/exec.rb @@ -0,0 +1,93 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +require 'puppet/type/exec' + +module ExecModuleTesting + def create_resource(command, output, exitstatus) + @user_name = 'some_user_name' + @group_name = 'some_group_name' + Puppet.features.stubs(:root?).returns(true) + @execer = Puppet::Type.type(:exec).create(:name => command, :path => %w{/usr/bin /bin}, :user => @user_name, :group => @group_name) + + status = stub "process" + status.stubs(:exitstatus).returns(exitstatus) + + Puppet::Util::SUIDManager.expects(:run_and_capture).with([command], @user_name, @group_name).returns([output, status]) + end + + def create_logging_resource(command, output, exitstatus, logoutput, loglevel) + create_resource(command, output, exitstatus) + @execer[:logoutput] = logoutput + @execer[:loglevel] = loglevel + end + + def expect_output(output, loglevel) + output.split(/\n/).each do |line| + @execer.property(:returns).expects(loglevel).with(line) + end + end +end + +describe Puppet::Type::Exec, " when execing" do + include ExecModuleTesting + + it "should use the 'run_and_capture' method to exec" do + command = "true" + create_resource(command, "", 0) + + @execer.refresh.should == :executed_command + end + + it "should report a failure" do + command = "false" + create_resource(command, "", 1) + + proc { @execer.refresh }.should raise_error(Puppet::Error) + end + + it "should log the output on success" do + #Puppet::Util::Log.newdestination :console + command = "false" + output = "output1\noutput2\n" + create_logging_resource(command, output, 0, true, :err) + expect_output(output, :err) + @execer.refresh + end + + it "should log the output on failure" do + #Puppet::Util::Log.newdestination :console + command = "false" + output = "output1\noutput2\n" + create_logging_resource(command, output, 1, true, :err) + expect_output(output, :err) + + proc { @execer.refresh }.should raise_error(Puppet::Error) + end + +end + + +describe Puppet::Type::Exec, " when logoutput=>on_failure is set," do + include ExecModuleTesting + + it "should log the output on failure" do + #Puppet::Util::Log.newdestination :console + command = "false" + output = "output1\noutput2\n" + create_logging_resource(command, output, 1, :on_failure, :err) + expect_output(output, :err) + + proc { @execer.refresh }.should raise_error(Puppet::Error) + end + + it "shouldn't log the output on success" do + #Puppet::Util::Log.newdestination :console + command = "true" + output = "output1\noutput2\n" + create_logging_resource(command, output, 0, :on_failure, :err) + @execer.property(:returns).expects(:err).never + @execer.refresh + end +end diff --git a/spec/unit/ral/type/file.rb b/spec/unit/ral/type/file.rb new file mode 100755 index 000000000..b213987bb --- /dev/null +++ b/spec/unit/ral/type/file.rb @@ -0,0 +1,99 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +require 'puppet/type/file' + +describe Puppet::Type::File do + before do + @path = Tempfile.new("puppetspec") + @path.close!() + @path = @path.path + @file = Puppet::Type::File.create(:name => @path) + end + + describe "when used with content and replace=>false" do + before do + @file[:content] = "foo" + @file[:replace] = false + end + + it "should be insync if the file exists and the content is different" do + File.open(@path, "w") do |f| f.puts "bar" end + @file.property(:content).insync?("bar").should be_true + end + + it "should be insync if the file exists and the content is right" do + File.open(@path, "w") do |f| f.puts "foo" end + @file.property(:content).insync?("foo").should be_true + end + + it "should not be insync if the file does not exist" do + @file.property(:content).insync?(:nil).should be_false + end + end + + describe "when retrieving remote files" do + before do + @filesource = Puppet::Type::File::FileSource.new + @filesource.server = mock 'fileserver' + + @file.stubs(:uri2obj).returns(@filesource) + + @file[:source] = "puppet:///test" + end + + it "should fail without writing if it cannot retrieve remote contents" do + # create the file, because we only get the problem when it starts + # out absent. + File.open(@file[:path], "w") { |f| f.puts "a" } + @file.expects(:write).never + + @filesource.server.stubs(:describe).returns("493\tfile\t100\t0\t{md5}3f5fef3bddbc4398c46a7bd7ba7b3af7") + @filesource.server.stubs(:retrieve).raises(RuntimeError) + @file.property(:source).retrieve + lambda { @file.property(:source).sync }.should raise_error(Puppet::Error) + end + end + + describe "when managing links" do + require 'puppettest/support/assertions' + include PuppetTest + + before do + @basedir = tempfile() + Dir.mkdir(@basedir) + @file = File.join(@basedir, "file") + @link = File.join(@basedir, "link") + + File.open(@file, "w", 0644) { |f| f.puts "yayness"; f.flush } + File.symlink(@file, @link) + + @resource = Puppet.type(:file).create( + :path => @link, + :mode => "755" + ) + end + + after do + teardown + end + + it "should default to managing the link" do + assert_events([], @resource) + # I convert them to strings so they display correctly if there's an error. + ("%o" % (File.stat(@file).mode & 007777)).should == "%o" % 0644 + end + + it "should be able to follow links" do + @resource[:links] = :follow + assert_events([:file_changed], @resource) + + ("%o" % (File.stat(@file).mode & 007777)).should == "%o" % 0755 + end + end + + after do + Puppet::Type::File.clear + end +end diff --git a/spec/unit/ral/type/interface.rb b/spec/unit/ral/type/interface.rb new file mode 100755 index 000000000..2e0176152 --- /dev/null +++ b/spec/unit/ral/type/interface.rb @@ -0,0 +1,95 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +interface = Puppet::Type.type(:interface) + +describe interface do + before do + @class = Puppet::Type.type(:interface) + + @provider_class = stub 'provider_class', :name => "fake", :suitable? => true, :supports_parameter? => true + @class.stubs(:defaultprovider).returns(@provider_class) + @class.stubs(:provider).returns(@provider_class) + + @provider = stub 'provider', :class => @provider_class, :file_path => "/tmp/whatever", :clear => nil + @provider_class.stubs(:new).returns(@provider) + end + + it "should have a name parameter" do + @class.attrtype(:name).should == :param + end + + it "should have :name be its namevar" do + @class.namevar.should == :name + end + + it "should have a :provider parameter" do + @class.attrtype(:provider).should == :param + end + + it "should have an ensure property" do + @class.attrtype(:ensure).should == :property + end + + it "should support :present as a value for :ensure" do + proc { @class.create(:name => "whev", :ensure => :present) }.should_not raise_error + end + + it "should support :absent as a value for :ensure" do + proc { @class.create(:name => "whev", :ensure => :absent) }.should_not raise_error + end + + it "should have an interface_type property" do + @class.attrtype(:interface_type).should == :property + end + it "should support :loopback as an interface_type value" do + proc { @class.create(:name => "whev", :interface_type => :loopback) }.should_not raise_error + end + it "should support :alias as an interface_type value" do + proc { @class.create(:name => "whev", :interface_type => :alias) }.should_not raise_error + end + it "should support :normal as an interface_type value" do + proc { @class.create(:name => "whev", :interface_type => :normal) }.should_not raise_error + end + it "should alias :dummy to the :loopback interface_type value" do + int = @class.create(:name => "whev", :interface_type => :dummy) + int.should(:interface_type).should == :loopback + end + + it "should not support values other than :loopback, :alias, :normal, and :dummy in the interface_type" do + proc { @class.create(:name => "whev", :interface_type => :something) }.should raise_error(Puppet::Error) + end + + it "should have an interface_desc parameter" do + @class.attrtype(:interface_desc).should == :param + end + + it "should have an onboot property" do + @class.attrtype(:onboot).should == :property + end + it "should support :true as an onboot value" do + proc { @class.create(:name => "whev", :onboot => :true) }.should_not raise_error + end + it "should support :false as an onboot value" do + proc { @class.create(:name => "whev", :onboot => :false) }.should_not raise_error + end + + it "should have an ifnum property" do + @class.attrtype(:ifnum).should == :property + end + + it "should have a netmask property" do + @class.attrtype(:netmask).should == :property + end + + it "should have an ifopts property" do + @class.attrtype(:ifopts).should == :property + end + + it "should have a target parameter" do + @class.attrtype(:target).should == :param + end + + after { @class.clear } +end diff --git a/spec/unit/ral/type/mount.rb b/spec/unit/ral/type/mount.rb new file mode 100755 index 000000000..9247601e6 --- /dev/null +++ b/spec/unit/ral/type/mount.rb @@ -0,0 +1,192 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +require 'puppet/type/mount' + +describe Puppet::Type::Mount do + it "should have a :refreshable feature that requires the :remount method" do + Puppet::Type::Mount.provider_feature(:refreshable).methods.should == [:remount] + end + + it "should have no default value for :ensure" do + mount = Puppet::Type::Mount.create(:name => "yay") + mount.should(:ensure).should be_nil + end + + after { Puppet::Type::Mount.clear } +end + +describe Puppet::Type::Mount, "when validating attributes" do + [:name, :remounts].each do |param| + it "should have a #{param} parameter" do + Puppet::Type::Mount.attrtype(param).should == :param + end + end + + [:ensure, :device, :blockdevice, :fstype, :options, :pass, :dump, :atboot, :target].each do |param| + it "should have a #{param} property" do + Puppet::Type::Mount.attrtype(param).should == :property + end + end +end + +describe Puppet::Type::Mount::Ensure, "when validating values" do + before do + @provider = stub 'provider', :class => Puppet::Type::Mount.defaultprovider, :clear => nil + Puppet::Type::Mount.defaultprovider.expects(:new).returns(@provider) + end + + it "should support :present as a value to :ensure" do + Puppet::Type::Mount.create(:name => "yay", :ensure => :present) + end + + it "should alias :unmounted to :present as a value to :ensure" do + mount = Puppet::Type::Mount.create(:name => "yay", :ensure => :unmounted) + mount.should(:ensure).should == :present + end + + it "should support :absent as a value to :ensure" do + Puppet::Type::Mount.create(:name => "yay", :ensure => :absent) + end + + it "should support :mounted as a value to :ensure" do + Puppet::Type::Mount.create(:name => "yay", :ensure => :mounted) + end + + after { Puppet::Type::Mount.clear } +end + +describe Puppet::Type::Mount::Ensure do + before :each do + @provider = stub 'provider', :class => Puppet::Type::Mount.defaultprovider, :clear => nil, :satisfies? => true, :name => :mock + Puppet::Type::Mount.defaultprovider.stubs(:new).returns(@provider) + @mount = Puppet::Type::Mount.create(:name => "yay", :check => :ensure) + + @ensure = @mount.property(:ensure) + end + + after :each do + Puppet::Type::Mount.clear + end + + def mount_stub(params) + Puppet::Type::Mount.validproperties.each do |prop| + unless params[prop] + params[prop] = :absent + @mount[prop] = :absent + end + end + + params.each do |param, value| + @provider.stubs(param).returns(value) + end + end + + describe Puppet::Type::Mount::Ensure, "when retrieving its current state" do + + it "should return the provider's value if it is :absent" do + @provider.expects(:ensure).returns(:absent) + @ensure.retrieve.should == :absent + end + + it "should return :mounted if the provider indicates it is mounted and the value is not :absent" do + @provider.expects(:ensure).returns(:present) + @provider.expects(:mounted?).returns(true) + @ensure.retrieve.should == :mounted + end + + it "should return :present if the provider indicates it is not mounted and the value is not :absent" do + @provider.expects(:ensure).returns(:present) + @provider.expects(:mounted?).returns(false) + @ensure.retrieve.should == :present + end + end + + describe Puppet::Type::Mount::Ensure, "when changing the host" do + + it "should destroy itself if it should be absent" do + @provider.stubs(:mounted?).returns(false) + @provider.expects(:destroy) + @ensure.should = :absent + @ensure.sync + end + + it "should unmount itself before destroying if it is mounted and should be absent" do + @provider.expects(:mounted?).returns(true) + @provider.expects(:unmount) + @provider.expects(:destroy) + @ensure.should = :absent + @ensure.sync + end + + it "should create itself if it is absent and should be present" do + @provider.stubs(:mounted?).returns(false) + @provider.expects(:create) + @ensure.should = :present + @ensure.sync + end + + it "should unmount itself if it is mounted and should be present" do + @provider.stubs(:mounted?).returns(true) + + # The interface here is just too much work to test right now. + @ensure.stubs(:syncothers) + @provider.expects(:unmount) + @ensure.should = :present + @ensure.sync + end + + it "should create and mount itself if it does not exist and should be mounted" do + @provider.stubs(:ensure).returns(:absent) + @provider.stubs(:mounted?).returns(false) + @provider.expects(:create) + @ensure.stubs(:syncothers) + @provider.expects(:mount) + @ensure.should = :mounted + @ensure.sync + end + + it "should mount itself if it is present and should be mounted" do + @provider.stubs(:ensure).returns(:present) + @provider.stubs(:mounted?).returns(false) + @ensure.stubs(:syncothers) + @provider.expects(:mount) + @ensure.should = :mounted + @ensure.sync + end + + it "should create but not mount itself if it is absent and mounted and should be mounted" do + @provider.stubs(:ensure).returns(:absent) + @provider.stubs(:mounted?).returns(true) + @ensure.stubs(:syncothers) + @provider.expects(:create) + @ensure.should = :mounted + @ensure.sync + end + end + + describe Puppet::Type::Mount, "when responding to events" do + + it "should remount if it is currently mounted" do + @provider.expects(:mounted?).returns(true) + @provider.expects(:remount) + + @mount.refresh + end + + it "should not remount if it is not currently mounted" do + @provider.expects(:mounted?).returns(false) + @provider.expects(:remount).never + + @mount.refresh + end + + it "should not remount swap filesystems" do + @mount[:fstype] = "swap" + @provider.expects(:remount).never + + @mount.refresh + end + end +end \ No newline at end of file diff --git a/spec/unit/ral/type/nagios.rb b/spec/unit/ral/type/nagios.rb new file mode 100755 index 000000000..8aca7d401 --- /dev/null +++ b/spec/unit/ral/type/nagios.rb @@ -0,0 +1,55 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +require 'puppet/external/nagios' + +Nagios::Base.eachtype do |name, nagios_type| + puppet_type = Puppet::Type.type("nagios_" + name.to_s) + + describe puppet_type do + it "should be defined as a Puppet resource type" do + puppet_type.should_not be_nil + end + + it "should have documentation" do + puppet_type.instance_variable_get("@doc").should_not == "" + end + + it "should have %s as its namevar" % nagios_type.namevar do + puppet_type.namevar.should == nagios_type.namevar + end + + it "should have documentation for its %s parameter" % nagios_type.namevar do + puppet_type.attrclass(nagios_type.namevar).instance_variable_get("@doc").should_not be_nil + end + + it "should have an ensure property" do + puppet_type.should be_validproperty(:ensure) + end + + it "should have a target property" do + puppet_type.should be_validproperty(:target) + end + + it "should have documentation for its target property" do + puppet_type.attrclass(:target).instance_variable_get("@doc").should_not be_nil + end + + nagios_type.parameters.reject { |param| param == nagios_type.namevar or param.to_s =~ /^[0-9]/ }.each do |param| + it "should have a %s property" % param do + puppet_type.should be_validproperty(param) + end + + it "should have documentation for its %s property" % param do + puppet_type.attrclass(param).instance_variable_get("@doc").should_not be_nil + end + end + + nagios_type.parameters.find_all { |param| param.to_s =~ /^[0-9]/ }.each do |param| + it "should have not have a %s property" % param do + puppet_type.should_not be_validproperty(:param) + end + end + end +end diff --git a/spec/unit/ral/type/package.rb b/spec/unit/ral/type/package.rb new file mode 100755 index 000000000..5d96dc4ae --- /dev/null +++ b/spec/unit/ral/type/package.rb @@ -0,0 +1,247 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +require 'puppet/type/package' + +describe Puppet::Type::Package do + it "should have an :installable feature that requires the :install method" do + Puppet::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] + end + + it "should have an :upgradeable feature that requires :update and :latest methods" do + Puppet::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] + end + + it "should have a :versionable feature" do + Puppet::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.should(:ensure).should == :present + end + + after { Puppet::Type::Package.clear } +end + +describe Puppet::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 + end + end + + it "should have an ensure property" do + Puppet::Type::Package.attrtype(:ensure).should == :property + end +end + +describe Puppet::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) + end + + it "should support :present as a value to :ensure" do + Puppet::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.should(:ensure).should == :present + end + + it "should support :absent as a value to :ensure" do + Puppet::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) + 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) + 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) + 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) + 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") + 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) + 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) + end + + after { Puppet::Type::Package.clear } +end + +module PackageEvaluationTesting + def setprops(properties) + @provider.stubs(:properties).returns(properties) + end +end + +describe Puppet::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") + + @catalog = Puppet::Node::Catalog.new + @catalog.add_resource(@package) + end + + after :each do + @catalog.clear(true) + Puppet::Type::Package.clear + end + + + describe Puppet::Type::Package, "when it should be purged" do + include PackageEvaluationTesting + + before { @package[:ensure] = :purged } + + it "should do nothing if it is :purged" do + @provider.expects(:properties).returns(:ensure => :purged) + @catalog.apply + end + + [:absent, :installed, :present, :latest].each do |state| + it "should purge if it is #{state.to_s}" do + @provider.stubs(:properties).returns(:ensure => state) + @provider.expects(:purge) + @catalog.apply + end + end + end + + describe Puppet::Type::Package, "when it should be absent" do + include PackageEvaluationTesting + + before { @package[:ensure] = :absent } + + [:purged, :absent].each do |state| + it "should do nothing if it is #{state.to_s}" do + @provider.expects(:properties).returns(:ensure => state) + @catalog.apply + end + end + + [:installed, :present, :latest].each do |state| + it "should uninstall if it is #{state.to_s}" do + @provider.stubs(:properties).returns(:ensure => state) + @provider.expects(:uninstall) + @catalog.apply + end + end + end + + describe Puppet::Type::Package, "when it should be present" do + include PackageEvaluationTesting + + before { @package[:ensure] = :present } + + [:present, :latest, "1.0"].each do |state| + it "should do nothing if it is #{state.to_s}" do + @provider.expects(:properties).returns(:ensure => state) + @catalog.apply + end + end + + [:purged, :absent].each do |state| + it "should install if it is #{state.to_s}" do + @provider.stubs(:properties).returns(:ensure => state) + @provider.expects(:install) + @catalog.apply + end + end + end + + describe Puppet::Type::Package, "when it should be latest" do + include PackageEvaluationTesting + + before { @package[:ensure] = :latest } + + [:purged, :absent].each do |state| + it "should upgrade if it is #{state.to_s}" do + @provider.stubs(:properties).returns(:ensure => state) + @provider.expects(:update) + @catalog.apply + end + end + + it "should upgrade if the current version is not equal to the latest version" do + @provider.stubs(:properties).returns(:ensure => "1.0") + @provider.stubs(:latest).returns("2.0") + @provider.expects(:update) + @catalog.apply + end + + it "should do nothing if it is equal to the latest version" do + @provider.stubs(:properties).returns(:ensure => "1.0") + @provider.stubs(:latest).returns("1.0") + @provider.expects(:update).never + @catalog.apply + end + + it "should do nothing if the provider returns :present as the latest version" do + @provider.stubs(:properties).returns(:ensure => :present) + @provider.stubs(:latest).returns("1.0") + @provider.expects(:update).never + @catalog.apply + end + end + + describe Puppet::Type::Package, "when it should be a specific version" do + include PackageEvaluationTesting + + before { @package[:ensure] = "1.0" } + + [:purged, :absent].each do |state| + it "should install if it is #{state.to_s}" do + @provider.stubs(:properties).returns(:ensure => state) + @provider.expects(:install) + @catalog.apply + end + end + + it "should do nothing if the current version is equal to the desired version" do + @provider.stubs(:properties).returns(:ensure => "1.0") + @provider.expects(:install).never + @catalog.apply + end + + it "should install if the current version is not equal to the specified version" do + @provider.stubs(:properties).returns(:ensure => "2.0") + @provider.expects(:install) + @catalog.apply + end + end +end diff --git a/spec/unit/ral/type/schedule.rb b/spec/unit/ral/type/schedule.rb new file mode 100755 index 000000000..4e9840c34 --- /dev/null +++ b/spec/unit/ral/type/schedule.rb @@ -0,0 +1,341 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +require 'puppet/type/schedule' + +module ScheduleTesting + + def format(time) + time.strftime("%H:%M:%S") + end + + def diff(unit, incr, method, count) + diff = Time.now.to_i.send(method, incr * count) + Time.at(diff) + end + + def month(method, count) + diff(:hour, 3600 * 24 * 30, method, count) + end + + def week(method, count) + diff(:hour, 3600 * 24 * 7, method, count) + end + + def day(method, count) + diff(:hour, 3600 * 24, method, count) + end + + def hour(method, count) + diff(:hour, 3600, method, count) + end + + def min(method, count) + diff(:min, 60, method, count) + end + + def sec(method, count) + diff(:sec, 1, method, count) + end + +end + +describe Puppet::Type::Schedule do + + before :each do + Puppet.settings.stubs(:value).with(:ignoreschedules).returns(false) + + @schedule = Puppet::Type::Schedule.create(:name => "testing") + end + + after :each do + Puppet::Type::Schedule.clear + end + + + describe Puppet::Type::Schedule do + include ScheduleTesting + + it "should default to :distance for period-matching" do + @schedule[:periodmatch].should == :distance + end + + it "should default to a :repeat of 1" do + @schedule[:repeat].should == 1 + end + + it "should never match when the period is :never" do + @schedule[:period] = :never + @schedule.match?.should be_false + end + end + + describe Puppet::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) + 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.find { |s| + s[:name] == "puppet" and s[:period] == :hourly and s[:repeat] == 2 + }.should be_instance_of(Puppet::Type::Schedule) + end + end + + describe Puppet::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 + @schedule[:range] = "%s - %s" % [format(Time.now - 10), format(Time.now + 10)] + @schedule.match?.should be_true + end + + it "should not match when the start time is after the current time" do + @schedule[:range] = "%s - %s" % [format(Time.now + 5), format(Time.now + 10)] + @schedule.match?.should be_false + end + + it "should not match when the end time is previous to the current time" do + @schedule[:range] = "%s - %s" % [format(Time.now - 10), format(Time.now - 5)] + @schedule.match?.should be_false + end + end + + describe Puppet::Type::Schedule, "when matching hourly by distance" do + include ScheduleTesting + + before do + @schedule[:period] = :hourly + @schedule[:periodmatch] = :distance + end + + it "should match an hour ago" do + @schedule.match?(hour("-", 1)).should be_true + end + + it "should not match now" do + @schedule.match?(Time.now).should be_false + end + + it "should not match 59 minutes ago" do + @schedule.match?(min("-", 59)).should be_false + end + end + + describe Puppet::Type::Schedule, "when matching daily by distance" do + include ScheduleTesting + + before do + @schedule[:period] = :daily + @schedule[:periodmatch] = :distance + end + + it "should match when the previous time was one day ago" do + @schedule.match?(day("-", 1)).should be_true + end + + it "should not match when the previous time is now" do + @schedule.match?(Time.now).should be_false + end + + it "should not match when the previous time was 23 hours ago" do + @schedule.match?(hour("-", 23)).should be_false + end + end + + describe Puppet::Type::Schedule, "when matching weekly by distance" do + include ScheduleTesting + + before do + @schedule[:period] = :weekly + @schedule[:periodmatch] = :distance + end + + it "should match seven days ago" do + @schedule.match?(day("-", 7)).should be_true + end + + it "should not match now" do + @schedule.match?(Time.now).should be_false + end + + it "should not match six days ago" do + @schedule.match?(day("-", 6)).should be_false + end + end + + describe Puppet::Type::Schedule, "when matching monthly by distance" do + include ScheduleTesting + + before do + @schedule[:period] = :monthly + @schedule[:periodmatch] = :distance + end + + it "should match 32 days ago" do + @schedule.match?(day("-", 32)).should be_true + end + + it "should not match now" do + @schedule.match?(Time.now).should be_false + end + + it "should not match 27 days ago" do + @schedule.match?(day("-", 27)).should be_false + end + end + + describe Puppet::Type::Schedule, "when matching hourly by number" do + include ScheduleTesting + + before do + @schedule[:period] = :hourly + @schedule[:periodmatch] = :number + end + + it "should match if the times are one minute apart and the current minute is 0" do + current = Time.now + + # Subtract an hour, reset the minute to zero, then add 59 minutes, so we're the previous hour plus 59 minutes. + previous = (current - 3600 - (current.min * 60) + (59 * 60)) + + # Now set the "current" time to the zero minute of the current hour. + now = (current - (current.min * 60)) + Time.stubs(:now).returns(now) + @schedule.match?(previous).should be_true + end + + it "should not match if the times are 58 minutes apart and the current minute is 59" do + current = Time.now + + # reset the minute to zero + previous = current - (current.min * 60) + + # Now set the "current" time to the 59th minute of the current hour. + now = (current - (current.min * 60) + (59 * 60)) + Time.stubs(:now).returns(now) + @schedule.match?(previous).should be_false + end + end + + describe Puppet::Type::Schedule, "when matching daily by number" do + include ScheduleTesting + + before do + @schedule[:period] = :daily + @schedule[:periodmatch] = :number + end + + it "should match if the times are one minute apart and the current minute and hour are 0" do + zero = Time.now + + # Reset the current time to X:00:00 + current = zero - (zero.hour * 3600) - (zero.min * 60) - zero.sec + + # Now set the previous time to one minute before that + previous = current - 60 + + Time.stubs(:now).returns(current) + @schedule.match?(previous).should be_true + end + + it "should not match if the times are 23 hours and 58 minutes apart and the current hour is 23 and the current minute is 59" do + zero = Time.now + + # Reset the previous time to 00:00:00 + previous = zero - (zero.hour * 3600) - (zero.min * 60) - zero.sec + + # Set the current time to 23:59 + now = previous + (23 * 3600) + (59 * 60) + + Time.stubs(:now).returns(now) + @schedule.match?(previous).should be_false + end + end + + describe Puppet::Type::Schedule, "when matching weekly by number" do + include ScheduleTesting + + before do + @schedule[:period] = :weekly + @schedule[:periodmatch] = :number + end + + it "should match if the previous time is prior to the most recent Sunday" do + now = Time.now + + # Subtract the number days we've progressed into the week, plus one because we're zero-indexed. + previous = now - (3600 * 24 * (now.wday + 1)) + + @schedule.match?(previous).should be_true + end + + it "should not match if the previous time is after the most recent Saturday" do + now = Time.now + + # Subtract the number days we've progressed into the week + previous = now - (3600 * 24 * now.wday) + + @schedule.match?(previous).should be_false + end + end + + describe Puppet::Type::Schedule, "when matching monthly by number" do + include ScheduleTesting + + before do + @schedule[:period] = :monthly + @schedule[:periodmatch] = :number + end + + it "should match when the previous time is prior to the first day of this month" do + now = Time.now + + # Subtract the number days we've progressed into the month + previous = now - (3600 * 24 * now.day) + + @schedule.match?(previous).should be_true + end + + it "should not match when the previous time is after the last day of last month" do + now = Time.now + + # Subtract the number days we've progressed into the month, minus one + previous = now - (3600 * 24 * (now.day - 1)) + + @schedule.match?(previous).should be_false + end + end + + describe Puppet::Type::Schedule, "when matching with a repeat greater than one" do + include ScheduleTesting + + before do + @schedule[:period] = :daily + @schedule[:repeat] = 2 + end + + it "should fail if the periodmatch is 'number'" do + @schedule[:periodmatch] = :number + proc { @schedule[:repeat] = 2 }.should raise_error(Puppet::Error) + end + + it "should match if the previous run was further away than the distance divided by the repeat" do + previous = Time.now - (3600 * 13) + @schedule.match?(previous).should be_true + end + + it "should not match if the previous run was closer than the distance divided by the repeat" do + previous = Time.now - (3600 * 11) + @schedule.match?(previous).should be_false + end + end +end diff --git a/spec/unit/ral/type/service.rb b/spec/unit/ral/type/service.rb new file mode 100755 index 000000000..0f00992fa --- /dev/null +++ b/spec/unit/ral/type/service.rb @@ -0,0 +1,256 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +require 'puppet/type/service' + +describe Puppet::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?] + end + + it "should have a :refreshable feature that requires the :restart method" do + Puppet::Type::Service.provider_feature(:refreshable).methods.should == [:restart] + end +end + +describe Puppet::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 + end + end + + [:ensure, :enable].each do |param| + it "should have an #{param} property" do + Puppet::Type::Service.attrtype(param).should == :property + end + end +end + +describe Puppet::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) + end + + it "should support :running as a value to :ensure" do + Puppet::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) + end + + it "should alias the value :true to :running in :ensure" do + svc = Puppet::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.should(:ensure).should == :stopped + end + + it "should support :true as a value to :enable" do + Puppet::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) + end + + it "should support :true as a value to :hasstatus" do + Puppet::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) + end + + it "should support :true as a value to :hasrestart" do + Puppet::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) + 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) + 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) + 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[: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[: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[: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[:path].should == %w{/one /two /three /four} + end + + after { Puppet::Type::Service.clear } +end + +describe Puppet::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") + 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[: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[: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") + svc[:control].should == "NFS_CLIENT_START" + end + + after { Puppet::Type::Service.clear } +end + +describe Puppet::Type::Service, "when retrieving the host's current state" do + before do + @service = Puppet::Type::Service.create(:name => "yay") + end + + it "should use the provider's status to determine whether the service is running" do + @service.provider.expects(:status).returns(:yepper) + @service[:ensure] = :running + @service.property(:ensure).retrieve.should == :yepper + end + + it "should ask the provider whether it is enabled" do + @service.provider.class.stubs(:supports_parameter?).returns(true) + @service.provider.expects(:enabled?).returns(:yepper) + @service[:enable] = true + @service.property(:enable).retrieve.should == :yepper + end + + after { Puppet::Type::Service.clear } +end + +describe Puppet::Type::Service, "when changing the host" do + before do + @service = Puppet::Type::Service.create(:name => "yay") + end + + it "should start the service if it is supposed to be running" do + @service[:ensure] = :running + @service.provider.expects(:start) + @service.property(:ensure).sync + end + + it "should stop the service if it is supposed to be stopped" do + @service[:ensure] = :stopped + @service.provider.expects(:stop) + @service.property(:ensure).sync + end + + it "should enable the service if it is supposed to be enabled" do + @service.provider.class.stubs(:supports_parameter?).returns(true) + @service[:enable] = true + @service.provider.expects(:enable) + @service.property(:enable).sync + end + + it "should disable the service if it is supposed to be disabled" do + @service.provider.class.stubs(:supports_parameter?).returns(true) + @service[:enable] = false + @service.provider.expects(:disable) + @service.property(:enable).sync + end + + it "should sync the service's enable state when changing the state of :ensure if :enable is being managed" do + @service.provider.class.stubs(:supports_parameter?).returns(true) + @service[:enable] = false + @service[:ensure] = :stopped + + @service.property(:enable).expects(:retrieve).returns("whatever") + @service.property(:enable).expects(:insync?).returns(false) + @service.property(:enable).expects(:sync) + + @service.provider.stubs(:stop) + + @service.property(:ensure).sync + end + + after { Puppet::Type::Service.clear } +end + +describe Puppet::Type::Service, "when refreshing the service" do + before do + @service = Puppet::Type::Service.create(:name => "yay") + end + + it "should restart the service if it is running" do + @service[:ensure] = :running + @service.provider.expects(:status).returns(:running) + @service.provider.expects(:restart) + @service.refresh + end + + it "should restart the service if it is running, even if it is supposed to stopped" do + @service[:ensure] = :stopped + @service.provider.expects(:status).returns(:running) + @service.provider.expects(:restart) + @service.refresh + end + + it "should not restart the service if it is not running" do + @service[:ensure] = :running + @service.provider.expects(:status).returns(:stopped) + @service.refresh + end + + it "should add :ensure as a property if it is not being managed" do + @service.provider.expects(:status).returns(:running) + @service.provider.expects(:restart) + @service.refresh + end + + after { Puppet::Type::Service.clear } +end diff --git a/spec/unit/ral/type/user.rb b/spec/unit/ral/type/user.rb new file mode 100755 index 000000000..4e43a8ceb --- /dev/null +++ b/spec/unit/ral/type/user.rb @@ -0,0 +1,58 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +require 'puppet/type/user' + +module UserTestFunctions + def mkuser(name) + user = nil; + lambda { + user = Puppet::Type::User.create( + :name => name, + :comment => "Puppet Testing User", + :gid => Puppet::Util::SUIDManager.gid, + :shell => "/bin/sh", + :home => "/home/%s" % name + ) }.should_not raise_error + user.should_not be_nil + user + end + + def test_provider_class(klass) + klass.should_not be_nil + klass.should be_an_instance_of(Class) + superclasses = [] + while klass = klass.superclass + superclasses << klass + end + superclasses.should include(Puppet::Provider) + end +end + +describe Puppet::Type::User do + + include UserTestFunctions + + it "should have a default provider inheriting from Puppet::Provider" do + test_provider_class Puppet::Type::User.defaultprovider + end + + it "should be able to create a instance" do + mkuser "123testuser1" + end +end + +describe Puppet::Type::User, "instances" do + + include UserTestFunctions + + it "should have a valid provider" do + user = mkuser "123testuser2" + user.provider.should_not be_nil + test_provider_class user.provider.class + end + +end + + diff --git a/spec/unit/ral/types/exec.rb b/spec/unit/ral/types/exec.rb deleted file mode 100755 index 260804227..000000000 --- a/spec/unit/ral/types/exec.rb +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../../spec_helper' - -require 'puppet/type/exec' - -module ExecModuleTesting - def create_resource(command, output, exitstatus) - @user_name = 'some_user_name' - @group_name = 'some_group_name' - Puppet.features.stubs(:root?).returns(true) - @execer = Puppet::Type.type(:exec).create(:name => command, :path => %w{/usr/bin /bin}, :user => @user_name, :group => @group_name) - - status = stub "process" - status.stubs(:exitstatus).returns(exitstatus) - - Puppet::Util::SUIDManager.expects(:run_and_capture).with([command], @user_name, @group_name).returns([output, status]) - end - - def create_logging_resource(command, output, exitstatus, logoutput, loglevel) - create_resource(command, output, exitstatus) - @execer[:logoutput] = logoutput - @execer[:loglevel] = loglevel - end - - def expect_output(output, loglevel) - output.split(/\n/).each do |line| - @execer.property(:returns).expects(loglevel).with(line) - end - end -end - -describe Puppet::Type::Exec, " when execing" do - include ExecModuleTesting - - it "should use the 'run_and_capture' method to exec" do - command = "true" - create_resource(command, "", 0) - - @execer.refresh.should == :executed_command - end - - it "should report a failure" do - command = "false" - create_resource(command, "", 1) - - proc { @execer.refresh }.should raise_error(Puppet::Error) - end - - it "should log the output on success" do - #Puppet::Util::Log.newdestination :console - command = "false" - output = "output1\noutput2\n" - create_logging_resource(command, output, 0, true, :err) - expect_output(output, :err) - @execer.refresh - end - - it "should log the output on failure" do - #Puppet::Util::Log.newdestination :console - command = "false" - output = "output1\noutput2\n" - create_logging_resource(command, output, 1, true, :err) - expect_output(output, :err) - - proc { @execer.refresh }.should raise_error(Puppet::Error) - end - -end - - -describe Puppet::Type::Exec, " when logoutput=>on_failure is set," do - include ExecModuleTesting - - it "should log the output on failure" do - #Puppet::Util::Log.newdestination :console - command = "false" - output = "output1\noutput2\n" - create_logging_resource(command, output, 1, :on_failure, :err) - expect_output(output, :err) - - proc { @execer.refresh }.should raise_error(Puppet::Error) - end - - it "shouldn't log the output on success" do - #Puppet::Util::Log.newdestination :console - command = "true" - output = "output1\noutput2\n" - create_logging_resource(command, output, 0, :on_failure, :err) - @execer.property(:returns).expects(:err).never - @execer.refresh - end -end diff --git a/spec/unit/ral/types/file.rb b/spec/unit/ral/types/file.rb deleted file mode 100755 index b213987bb..000000000 --- a/spec/unit/ral/types/file.rb +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../../spec_helper' - -require 'puppet/type/file' - -describe Puppet::Type::File do - before do - @path = Tempfile.new("puppetspec") - @path.close!() - @path = @path.path - @file = Puppet::Type::File.create(:name => @path) - end - - describe "when used with content and replace=>false" do - before do - @file[:content] = "foo" - @file[:replace] = false - end - - it "should be insync if the file exists and the content is different" do - File.open(@path, "w") do |f| f.puts "bar" end - @file.property(:content).insync?("bar").should be_true - end - - it "should be insync if the file exists and the content is right" do - File.open(@path, "w") do |f| f.puts "foo" end - @file.property(:content).insync?("foo").should be_true - end - - it "should not be insync if the file does not exist" do - @file.property(:content).insync?(:nil).should be_false - end - end - - describe "when retrieving remote files" do - before do - @filesource = Puppet::Type::File::FileSource.new - @filesource.server = mock 'fileserver' - - @file.stubs(:uri2obj).returns(@filesource) - - @file[:source] = "puppet:///test" - end - - it "should fail without writing if it cannot retrieve remote contents" do - # create the file, because we only get the problem when it starts - # out absent. - File.open(@file[:path], "w") { |f| f.puts "a" } - @file.expects(:write).never - - @filesource.server.stubs(:describe).returns("493\tfile\t100\t0\t{md5}3f5fef3bddbc4398c46a7bd7ba7b3af7") - @filesource.server.stubs(:retrieve).raises(RuntimeError) - @file.property(:source).retrieve - lambda { @file.property(:source).sync }.should raise_error(Puppet::Error) - end - end - - describe "when managing links" do - require 'puppettest/support/assertions' - include PuppetTest - - before do - @basedir = tempfile() - Dir.mkdir(@basedir) - @file = File.join(@basedir, "file") - @link = File.join(@basedir, "link") - - File.open(@file, "w", 0644) { |f| f.puts "yayness"; f.flush } - File.symlink(@file, @link) - - @resource = Puppet.type(:file).create( - :path => @link, - :mode => "755" - ) - end - - after do - teardown - end - - it "should default to managing the link" do - assert_events([], @resource) - # I convert them to strings so they display correctly if there's an error. - ("%o" % (File.stat(@file).mode & 007777)).should == "%o" % 0644 - end - - it "should be able to follow links" do - @resource[:links] = :follow - assert_events([:file_changed], @resource) - - ("%o" % (File.stat(@file).mode & 007777)).should == "%o" % 0755 - end - end - - after do - Puppet::Type::File.clear - end -end diff --git a/spec/unit/ral/types/interface.rb b/spec/unit/ral/types/interface.rb deleted file mode 100755 index 2e0176152..000000000 --- a/spec/unit/ral/types/interface.rb +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../../spec_helper' - -interface = Puppet::Type.type(:interface) - -describe interface do - before do - @class = Puppet::Type.type(:interface) - - @provider_class = stub 'provider_class', :name => "fake", :suitable? => true, :supports_parameter? => true - @class.stubs(:defaultprovider).returns(@provider_class) - @class.stubs(:provider).returns(@provider_class) - - @provider = stub 'provider', :class => @provider_class, :file_path => "/tmp/whatever", :clear => nil - @provider_class.stubs(:new).returns(@provider) - end - - it "should have a name parameter" do - @class.attrtype(:name).should == :param - end - - it "should have :name be its namevar" do - @class.namevar.should == :name - end - - it "should have a :provider parameter" do - @class.attrtype(:provider).should == :param - end - - it "should have an ensure property" do - @class.attrtype(:ensure).should == :property - end - - it "should support :present as a value for :ensure" do - proc { @class.create(:name => "whev", :ensure => :present) }.should_not raise_error - end - - it "should support :absent as a value for :ensure" do - proc { @class.create(:name => "whev", :ensure => :absent) }.should_not raise_error - end - - it "should have an interface_type property" do - @class.attrtype(:interface_type).should == :property - end - it "should support :loopback as an interface_type value" do - proc { @class.create(:name => "whev", :interface_type => :loopback) }.should_not raise_error - end - it "should support :alias as an interface_type value" do - proc { @class.create(:name => "whev", :interface_type => :alias) }.should_not raise_error - end - it "should support :normal as an interface_type value" do - proc { @class.create(:name => "whev", :interface_type => :normal) }.should_not raise_error - end - it "should alias :dummy to the :loopback interface_type value" do - int = @class.create(:name => "whev", :interface_type => :dummy) - int.should(:interface_type).should == :loopback - end - - it "should not support values other than :loopback, :alias, :normal, and :dummy in the interface_type" do - proc { @class.create(:name => "whev", :interface_type => :something) }.should raise_error(Puppet::Error) - end - - it "should have an interface_desc parameter" do - @class.attrtype(:interface_desc).should == :param - end - - it "should have an onboot property" do - @class.attrtype(:onboot).should == :property - end - it "should support :true as an onboot value" do - proc { @class.create(:name => "whev", :onboot => :true) }.should_not raise_error - end - it "should support :false as an onboot value" do - proc { @class.create(:name => "whev", :onboot => :false) }.should_not raise_error - end - - it "should have an ifnum property" do - @class.attrtype(:ifnum).should == :property - end - - it "should have a netmask property" do - @class.attrtype(:netmask).should == :property - end - - it "should have an ifopts property" do - @class.attrtype(:ifopts).should == :property - end - - it "should have a target parameter" do - @class.attrtype(:target).should == :param - end - - after { @class.clear } -end diff --git a/spec/unit/ral/types/mount.rb b/spec/unit/ral/types/mount.rb deleted file mode 100755 index 9247601e6..000000000 --- a/spec/unit/ral/types/mount.rb +++ /dev/null @@ -1,192 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../../spec_helper' - -require 'puppet/type/mount' - -describe Puppet::Type::Mount do - it "should have a :refreshable feature that requires the :remount method" do - Puppet::Type::Mount.provider_feature(:refreshable).methods.should == [:remount] - end - - it "should have no default value for :ensure" do - mount = Puppet::Type::Mount.create(:name => "yay") - mount.should(:ensure).should be_nil - end - - after { Puppet::Type::Mount.clear } -end - -describe Puppet::Type::Mount, "when validating attributes" do - [:name, :remounts].each do |param| - it "should have a #{param} parameter" do - Puppet::Type::Mount.attrtype(param).should == :param - end - end - - [:ensure, :device, :blockdevice, :fstype, :options, :pass, :dump, :atboot, :target].each do |param| - it "should have a #{param} property" do - Puppet::Type::Mount.attrtype(param).should == :property - end - end -end - -describe Puppet::Type::Mount::Ensure, "when validating values" do - before do - @provider = stub 'provider', :class => Puppet::Type::Mount.defaultprovider, :clear => nil - Puppet::Type::Mount.defaultprovider.expects(:new).returns(@provider) - end - - it "should support :present as a value to :ensure" do - Puppet::Type::Mount.create(:name => "yay", :ensure => :present) - end - - it "should alias :unmounted to :present as a value to :ensure" do - mount = Puppet::Type::Mount.create(:name => "yay", :ensure => :unmounted) - mount.should(:ensure).should == :present - end - - it "should support :absent as a value to :ensure" do - Puppet::Type::Mount.create(:name => "yay", :ensure => :absent) - end - - it "should support :mounted as a value to :ensure" do - Puppet::Type::Mount.create(:name => "yay", :ensure => :mounted) - end - - after { Puppet::Type::Mount.clear } -end - -describe Puppet::Type::Mount::Ensure do - before :each do - @provider = stub 'provider', :class => Puppet::Type::Mount.defaultprovider, :clear => nil, :satisfies? => true, :name => :mock - Puppet::Type::Mount.defaultprovider.stubs(:new).returns(@provider) - @mount = Puppet::Type::Mount.create(:name => "yay", :check => :ensure) - - @ensure = @mount.property(:ensure) - end - - after :each do - Puppet::Type::Mount.clear - end - - def mount_stub(params) - Puppet::Type::Mount.validproperties.each do |prop| - unless params[prop] - params[prop] = :absent - @mount[prop] = :absent - end - end - - params.each do |param, value| - @provider.stubs(param).returns(value) - end - end - - describe Puppet::Type::Mount::Ensure, "when retrieving its current state" do - - it "should return the provider's value if it is :absent" do - @provider.expects(:ensure).returns(:absent) - @ensure.retrieve.should == :absent - end - - it "should return :mounted if the provider indicates it is mounted and the value is not :absent" do - @provider.expects(:ensure).returns(:present) - @provider.expects(:mounted?).returns(true) - @ensure.retrieve.should == :mounted - end - - it "should return :present if the provider indicates it is not mounted and the value is not :absent" do - @provider.expects(:ensure).returns(:present) - @provider.expects(:mounted?).returns(false) - @ensure.retrieve.should == :present - end - end - - describe Puppet::Type::Mount::Ensure, "when changing the host" do - - it "should destroy itself if it should be absent" do - @provider.stubs(:mounted?).returns(false) - @provider.expects(:destroy) - @ensure.should = :absent - @ensure.sync - end - - it "should unmount itself before destroying if it is mounted and should be absent" do - @provider.expects(:mounted?).returns(true) - @provider.expects(:unmount) - @provider.expects(:destroy) - @ensure.should = :absent - @ensure.sync - end - - it "should create itself if it is absent and should be present" do - @provider.stubs(:mounted?).returns(false) - @provider.expects(:create) - @ensure.should = :present - @ensure.sync - end - - it "should unmount itself if it is mounted and should be present" do - @provider.stubs(:mounted?).returns(true) - - # The interface here is just too much work to test right now. - @ensure.stubs(:syncothers) - @provider.expects(:unmount) - @ensure.should = :present - @ensure.sync - end - - it "should create and mount itself if it does not exist and should be mounted" do - @provider.stubs(:ensure).returns(:absent) - @provider.stubs(:mounted?).returns(false) - @provider.expects(:create) - @ensure.stubs(:syncothers) - @provider.expects(:mount) - @ensure.should = :mounted - @ensure.sync - end - - it "should mount itself if it is present and should be mounted" do - @provider.stubs(:ensure).returns(:present) - @provider.stubs(:mounted?).returns(false) - @ensure.stubs(:syncothers) - @provider.expects(:mount) - @ensure.should = :mounted - @ensure.sync - end - - it "should create but not mount itself if it is absent and mounted and should be mounted" do - @provider.stubs(:ensure).returns(:absent) - @provider.stubs(:mounted?).returns(true) - @ensure.stubs(:syncothers) - @provider.expects(:create) - @ensure.should = :mounted - @ensure.sync - end - end - - describe Puppet::Type::Mount, "when responding to events" do - - it "should remount if it is currently mounted" do - @provider.expects(:mounted?).returns(true) - @provider.expects(:remount) - - @mount.refresh - end - - it "should not remount if it is not currently mounted" do - @provider.expects(:mounted?).returns(false) - @provider.expects(:remount).never - - @mount.refresh - end - - it "should not remount swap filesystems" do - @mount[:fstype] = "swap" - @provider.expects(:remount).never - - @mount.refresh - end - end -end \ No newline at end of file diff --git a/spec/unit/ral/types/nagios.rb b/spec/unit/ral/types/nagios.rb deleted file mode 100755 index 8aca7d401..000000000 --- a/spec/unit/ral/types/nagios.rb +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../../spec_helper' - -require 'puppet/external/nagios' - -Nagios::Base.eachtype do |name, nagios_type| - puppet_type = Puppet::Type.type("nagios_" + name.to_s) - - describe puppet_type do - it "should be defined as a Puppet resource type" do - puppet_type.should_not be_nil - end - - it "should have documentation" do - puppet_type.instance_variable_get("@doc").should_not == "" - end - - it "should have %s as its namevar" % nagios_type.namevar do - puppet_type.namevar.should == nagios_type.namevar - end - - it "should have documentation for its %s parameter" % nagios_type.namevar do - puppet_type.attrclass(nagios_type.namevar).instance_variable_get("@doc").should_not be_nil - end - - it "should have an ensure property" do - puppet_type.should be_validproperty(:ensure) - end - - it "should have a target property" do - puppet_type.should be_validproperty(:target) - end - - it "should have documentation for its target property" do - puppet_type.attrclass(:target).instance_variable_get("@doc").should_not be_nil - end - - nagios_type.parameters.reject { |param| param == nagios_type.namevar or param.to_s =~ /^[0-9]/ }.each do |param| - it "should have a %s property" % param do - puppet_type.should be_validproperty(param) - end - - it "should have documentation for its %s property" % param do - puppet_type.attrclass(param).instance_variable_get("@doc").should_not be_nil - end - end - - nagios_type.parameters.find_all { |param| param.to_s =~ /^[0-9]/ }.each do |param| - it "should have not have a %s property" % param do - puppet_type.should_not be_validproperty(:param) - end - end - end -end diff --git a/spec/unit/ral/types/package.rb b/spec/unit/ral/types/package.rb deleted file mode 100755 index 5d96dc4ae..000000000 --- a/spec/unit/ral/types/package.rb +++ /dev/null @@ -1,247 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../../spec_helper' - -require 'puppet/type/package' - -describe Puppet::Type::Package do - it "should have an :installable feature that requires the :install method" do - Puppet::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] - end - - it "should have an :upgradeable feature that requires :update and :latest methods" do - Puppet::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] - end - - it "should have a :versionable feature" do - Puppet::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.should(:ensure).should == :present - end - - after { Puppet::Type::Package.clear } -end - -describe Puppet::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 - end - end - - it "should have an ensure property" do - Puppet::Type::Package.attrtype(:ensure).should == :property - end -end - -describe Puppet::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) - end - - it "should support :present as a value to :ensure" do - Puppet::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.should(:ensure).should == :present - end - - it "should support :absent as a value to :ensure" do - Puppet::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) - 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) - 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) - 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) - 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") - 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) - 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) - end - - after { Puppet::Type::Package.clear } -end - -module PackageEvaluationTesting - def setprops(properties) - @provider.stubs(:properties).returns(properties) - end -end - -describe Puppet::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") - - @catalog = Puppet::Node::Catalog.new - @catalog.add_resource(@package) - end - - after :each do - @catalog.clear(true) - Puppet::Type::Package.clear - end - - - describe Puppet::Type::Package, "when it should be purged" do - include PackageEvaluationTesting - - before { @package[:ensure] = :purged } - - it "should do nothing if it is :purged" do - @provider.expects(:properties).returns(:ensure => :purged) - @catalog.apply - end - - [:absent, :installed, :present, :latest].each do |state| - it "should purge if it is #{state.to_s}" do - @provider.stubs(:properties).returns(:ensure => state) - @provider.expects(:purge) - @catalog.apply - end - end - end - - describe Puppet::Type::Package, "when it should be absent" do - include PackageEvaluationTesting - - before { @package[:ensure] = :absent } - - [:purged, :absent].each do |state| - it "should do nothing if it is #{state.to_s}" do - @provider.expects(:properties).returns(:ensure => state) - @catalog.apply - end - end - - [:installed, :present, :latest].each do |state| - it "should uninstall if it is #{state.to_s}" do - @provider.stubs(:properties).returns(:ensure => state) - @provider.expects(:uninstall) - @catalog.apply - end - end - end - - describe Puppet::Type::Package, "when it should be present" do - include PackageEvaluationTesting - - before { @package[:ensure] = :present } - - [:present, :latest, "1.0"].each do |state| - it "should do nothing if it is #{state.to_s}" do - @provider.expects(:properties).returns(:ensure => state) - @catalog.apply - end - end - - [:purged, :absent].each do |state| - it "should install if it is #{state.to_s}" do - @provider.stubs(:properties).returns(:ensure => state) - @provider.expects(:install) - @catalog.apply - end - end - end - - describe Puppet::Type::Package, "when it should be latest" do - include PackageEvaluationTesting - - before { @package[:ensure] = :latest } - - [:purged, :absent].each do |state| - it "should upgrade if it is #{state.to_s}" do - @provider.stubs(:properties).returns(:ensure => state) - @provider.expects(:update) - @catalog.apply - end - end - - it "should upgrade if the current version is not equal to the latest version" do - @provider.stubs(:properties).returns(:ensure => "1.0") - @provider.stubs(:latest).returns("2.0") - @provider.expects(:update) - @catalog.apply - end - - it "should do nothing if it is equal to the latest version" do - @provider.stubs(:properties).returns(:ensure => "1.0") - @provider.stubs(:latest).returns("1.0") - @provider.expects(:update).never - @catalog.apply - end - - it "should do nothing if the provider returns :present as the latest version" do - @provider.stubs(:properties).returns(:ensure => :present) - @provider.stubs(:latest).returns("1.0") - @provider.expects(:update).never - @catalog.apply - end - end - - describe Puppet::Type::Package, "when it should be a specific version" do - include PackageEvaluationTesting - - before { @package[:ensure] = "1.0" } - - [:purged, :absent].each do |state| - it "should install if it is #{state.to_s}" do - @provider.stubs(:properties).returns(:ensure => state) - @provider.expects(:install) - @catalog.apply - end - end - - it "should do nothing if the current version is equal to the desired version" do - @provider.stubs(:properties).returns(:ensure => "1.0") - @provider.expects(:install).never - @catalog.apply - end - - it "should install if the current version is not equal to the specified version" do - @provider.stubs(:properties).returns(:ensure => "2.0") - @provider.expects(:install) - @catalog.apply - end - end -end diff --git a/spec/unit/ral/types/schedule.rb b/spec/unit/ral/types/schedule.rb deleted file mode 100755 index 4e9840c34..000000000 --- a/spec/unit/ral/types/schedule.rb +++ /dev/null @@ -1,341 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../../spec_helper' - -require 'puppet/type/schedule' - -module ScheduleTesting - - def format(time) - time.strftime("%H:%M:%S") - end - - def diff(unit, incr, method, count) - diff = Time.now.to_i.send(method, incr * count) - Time.at(diff) - end - - def month(method, count) - diff(:hour, 3600 * 24 * 30, method, count) - end - - def week(method, count) - diff(:hour, 3600 * 24 * 7, method, count) - end - - def day(method, count) - diff(:hour, 3600 * 24, method, count) - end - - def hour(method, count) - diff(:hour, 3600, method, count) - end - - def min(method, count) - diff(:min, 60, method, count) - end - - def sec(method, count) - diff(:sec, 1, method, count) - end - -end - -describe Puppet::Type::Schedule do - - before :each do - Puppet.settings.stubs(:value).with(:ignoreschedules).returns(false) - - @schedule = Puppet::Type::Schedule.create(:name => "testing") - end - - after :each do - Puppet::Type::Schedule.clear - end - - - describe Puppet::Type::Schedule do - include ScheduleTesting - - it "should default to :distance for period-matching" do - @schedule[:periodmatch].should == :distance - end - - it "should default to a :repeat of 1" do - @schedule[:repeat].should == 1 - end - - it "should never match when the period is :never" do - @schedule[:period] = :never - @schedule.match?.should be_false - end - end - - describe Puppet::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) - 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.find { |s| - s[:name] == "puppet" and s[:period] == :hourly and s[:repeat] == 2 - }.should be_instance_of(Puppet::Type::Schedule) - end - end - - describe Puppet::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 - @schedule[:range] = "%s - %s" % [format(Time.now - 10), format(Time.now + 10)] - @schedule.match?.should be_true - end - - it "should not match when the start time is after the current time" do - @schedule[:range] = "%s - %s" % [format(Time.now + 5), format(Time.now + 10)] - @schedule.match?.should be_false - end - - it "should not match when the end time is previous to the current time" do - @schedule[:range] = "%s - %s" % [format(Time.now - 10), format(Time.now - 5)] - @schedule.match?.should be_false - end - end - - describe Puppet::Type::Schedule, "when matching hourly by distance" do - include ScheduleTesting - - before do - @schedule[:period] = :hourly - @schedule[:periodmatch] = :distance - end - - it "should match an hour ago" do - @schedule.match?(hour("-", 1)).should be_true - end - - it "should not match now" do - @schedule.match?(Time.now).should be_false - end - - it "should not match 59 minutes ago" do - @schedule.match?(min("-", 59)).should be_false - end - end - - describe Puppet::Type::Schedule, "when matching daily by distance" do - include ScheduleTesting - - before do - @schedule[:period] = :daily - @schedule[:periodmatch] = :distance - end - - it "should match when the previous time was one day ago" do - @schedule.match?(day("-", 1)).should be_true - end - - it "should not match when the previous time is now" do - @schedule.match?(Time.now).should be_false - end - - it "should not match when the previous time was 23 hours ago" do - @schedule.match?(hour("-", 23)).should be_false - end - end - - describe Puppet::Type::Schedule, "when matching weekly by distance" do - include ScheduleTesting - - before do - @schedule[:period] = :weekly - @schedule[:periodmatch] = :distance - end - - it "should match seven days ago" do - @schedule.match?(day("-", 7)).should be_true - end - - it "should not match now" do - @schedule.match?(Time.now).should be_false - end - - it "should not match six days ago" do - @schedule.match?(day("-", 6)).should be_false - end - end - - describe Puppet::Type::Schedule, "when matching monthly by distance" do - include ScheduleTesting - - before do - @schedule[:period] = :monthly - @schedule[:periodmatch] = :distance - end - - it "should match 32 days ago" do - @schedule.match?(day("-", 32)).should be_true - end - - it "should not match now" do - @schedule.match?(Time.now).should be_false - end - - it "should not match 27 days ago" do - @schedule.match?(day("-", 27)).should be_false - end - end - - describe Puppet::Type::Schedule, "when matching hourly by number" do - include ScheduleTesting - - before do - @schedule[:period] = :hourly - @schedule[:periodmatch] = :number - end - - it "should match if the times are one minute apart and the current minute is 0" do - current = Time.now - - # Subtract an hour, reset the minute to zero, then add 59 minutes, so we're the previous hour plus 59 minutes. - previous = (current - 3600 - (current.min * 60) + (59 * 60)) - - # Now set the "current" time to the zero minute of the current hour. - now = (current - (current.min * 60)) - Time.stubs(:now).returns(now) - @schedule.match?(previous).should be_true - end - - it "should not match if the times are 58 minutes apart and the current minute is 59" do - current = Time.now - - # reset the minute to zero - previous = current - (current.min * 60) - - # Now set the "current" time to the 59th minute of the current hour. - now = (current - (current.min * 60) + (59 * 60)) - Time.stubs(:now).returns(now) - @schedule.match?(previous).should be_false - end - end - - describe Puppet::Type::Schedule, "when matching daily by number" do - include ScheduleTesting - - before do - @schedule[:period] = :daily - @schedule[:periodmatch] = :number - end - - it "should match if the times are one minute apart and the current minute and hour are 0" do - zero = Time.now - - # Reset the current time to X:00:00 - current = zero - (zero.hour * 3600) - (zero.min * 60) - zero.sec - - # Now set the previous time to one minute before that - previous = current - 60 - - Time.stubs(:now).returns(current) - @schedule.match?(previous).should be_true - end - - it "should not match if the times are 23 hours and 58 minutes apart and the current hour is 23 and the current minute is 59" do - zero = Time.now - - # Reset the previous time to 00:00:00 - previous = zero - (zero.hour * 3600) - (zero.min * 60) - zero.sec - - # Set the current time to 23:59 - now = previous + (23 * 3600) + (59 * 60) - - Time.stubs(:now).returns(now) - @schedule.match?(previous).should be_false - end - end - - describe Puppet::Type::Schedule, "when matching weekly by number" do - include ScheduleTesting - - before do - @schedule[:period] = :weekly - @schedule[:periodmatch] = :number - end - - it "should match if the previous time is prior to the most recent Sunday" do - now = Time.now - - # Subtract the number days we've progressed into the week, plus one because we're zero-indexed. - previous = now - (3600 * 24 * (now.wday + 1)) - - @schedule.match?(previous).should be_true - end - - it "should not match if the previous time is after the most recent Saturday" do - now = Time.now - - # Subtract the number days we've progressed into the week - previous = now - (3600 * 24 * now.wday) - - @schedule.match?(previous).should be_false - end - end - - describe Puppet::Type::Schedule, "when matching monthly by number" do - include ScheduleTesting - - before do - @schedule[:period] = :monthly - @schedule[:periodmatch] = :number - end - - it "should match when the previous time is prior to the first day of this month" do - now = Time.now - - # Subtract the number days we've progressed into the month - previous = now - (3600 * 24 * now.day) - - @schedule.match?(previous).should be_true - end - - it "should not match when the previous time is after the last day of last month" do - now = Time.now - - # Subtract the number days we've progressed into the month, minus one - previous = now - (3600 * 24 * (now.day - 1)) - - @schedule.match?(previous).should be_false - end - end - - describe Puppet::Type::Schedule, "when matching with a repeat greater than one" do - include ScheduleTesting - - before do - @schedule[:period] = :daily - @schedule[:repeat] = 2 - end - - it "should fail if the periodmatch is 'number'" do - @schedule[:periodmatch] = :number - proc { @schedule[:repeat] = 2 }.should raise_error(Puppet::Error) - end - - it "should match if the previous run was further away than the distance divided by the repeat" do - previous = Time.now - (3600 * 13) - @schedule.match?(previous).should be_true - end - - it "should not match if the previous run was closer than the distance divided by the repeat" do - previous = Time.now - (3600 * 11) - @schedule.match?(previous).should be_false - end - end -end diff --git a/spec/unit/ral/types/service.rb b/spec/unit/ral/types/service.rb deleted file mode 100755 index 0f00992fa..000000000 --- a/spec/unit/ral/types/service.rb +++ /dev/null @@ -1,256 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../../spec_helper' - -require 'puppet/type/service' - -describe Puppet::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?] - end - - it "should have a :refreshable feature that requires the :restart method" do - Puppet::Type::Service.provider_feature(:refreshable).methods.should == [:restart] - end -end - -describe Puppet::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 - end - end - - [:ensure, :enable].each do |param| - it "should have an #{param} property" do - Puppet::Type::Service.attrtype(param).should == :property - end - end -end - -describe Puppet::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) - end - - it "should support :running as a value to :ensure" do - Puppet::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) - end - - it "should alias the value :true to :running in :ensure" do - svc = Puppet::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.should(:ensure).should == :stopped - end - - it "should support :true as a value to :enable" do - Puppet::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) - end - - it "should support :true as a value to :hasstatus" do - Puppet::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) - end - - it "should support :true as a value to :hasrestart" do - Puppet::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) - 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) - 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) - 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[: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[: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[: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[:path].should == %w{/one /two /three /four} - end - - after { Puppet::Type::Service.clear } -end - -describe Puppet::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") - 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[: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[: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") - svc[:control].should == "NFS_CLIENT_START" - end - - after { Puppet::Type::Service.clear } -end - -describe Puppet::Type::Service, "when retrieving the host's current state" do - before do - @service = Puppet::Type::Service.create(:name => "yay") - end - - it "should use the provider's status to determine whether the service is running" do - @service.provider.expects(:status).returns(:yepper) - @service[:ensure] = :running - @service.property(:ensure).retrieve.should == :yepper - end - - it "should ask the provider whether it is enabled" do - @service.provider.class.stubs(:supports_parameter?).returns(true) - @service.provider.expects(:enabled?).returns(:yepper) - @service[:enable] = true - @service.property(:enable).retrieve.should == :yepper - end - - after { Puppet::Type::Service.clear } -end - -describe Puppet::Type::Service, "when changing the host" do - before do - @service = Puppet::Type::Service.create(:name => "yay") - end - - it "should start the service if it is supposed to be running" do - @service[:ensure] = :running - @service.provider.expects(:start) - @service.property(:ensure).sync - end - - it "should stop the service if it is supposed to be stopped" do - @service[:ensure] = :stopped - @service.provider.expects(:stop) - @service.property(:ensure).sync - end - - it "should enable the service if it is supposed to be enabled" do - @service.provider.class.stubs(:supports_parameter?).returns(true) - @service[:enable] = true - @service.provider.expects(:enable) - @service.property(:enable).sync - end - - it "should disable the service if it is supposed to be disabled" do - @service.provider.class.stubs(:supports_parameter?).returns(true) - @service[:enable] = false - @service.provider.expects(:disable) - @service.property(:enable).sync - end - - it "should sync the service's enable state when changing the state of :ensure if :enable is being managed" do - @service.provider.class.stubs(:supports_parameter?).returns(true) - @service[:enable] = false - @service[:ensure] = :stopped - - @service.property(:enable).expects(:retrieve).returns("whatever") - @service.property(:enable).expects(:insync?).returns(false) - @service.property(:enable).expects(:sync) - - @service.provider.stubs(:stop) - - @service.property(:ensure).sync - end - - after { Puppet::Type::Service.clear } -end - -describe Puppet::Type::Service, "when refreshing the service" do - before do - @service = Puppet::Type::Service.create(:name => "yay") - end - - it "should restart the service if it is running" do - @service[:ensure] = :running - @service.provider.expects(:status).returns(:running) - @service.provider.expects(:restart) - @service.refresh - end - - it "should restart the service if it is running, even if it is supposed to stopped" do - @service[:ensure] = :stopped - @service.provider.expects(:status).returns(:running) - @service.provider.expects(:restart) - @service.refresh - end - - it "should not restart the service if it is not running" do - @service[:ensure] = :running - @service.provider.expects(:status).returns(:stopped) - @service.refresh - end - - it "should add :ensure as a property if it is not being managed" do - @service.provider.expects(:status).returns(:running) - @service.provider.expects(:restart) - @service.refresh - end - - after { Puppet::Type::Service.clear } -end diff --git a/spec/unit/ral/types/user.rb b/spec/unit/ral/types/user.rb deleted file mode 100755 index 4e43a8ceb..000000000 --- a/spec/unit/ral/types/user.rb +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../../spec_helper' - -require 'puppet/type/user' - -module UserTestFunctions - def mkuser(name) - user = nil; - lambda { - user = Puppet::Type::User.create( - :name => name, - :comment => "Puppet Testing User", - :gid => Puppet::Util::SUIDManager.gid, - :shell => "/bin/sh", - :home => "/home/%s" % name - ) }.should_not raise_error - user.should_not be_nil - user - end - - def test_provider_class(klass) - klass.should_not be_nil - klass.should be_an_instance_of(Class) - superclasses = [] - while klass = klass.superclass - superclasses << klass - end - superclasses.should include(Puppet::Provider) - end -end - -describe Puppet::Type::User do - - include UserTestFunctions - - it "should have a default provider inheriting from Puppet::Provider" do - test_provider_class Puppet::Type::User.defaultprovider - end - - it "should be able to create a instance" do - mkuser "123testuser1" - end -end - -describe Puppet::Type::User, "instances" do - - include UserTestFunctions - - it "should have a valid provider" do - user = mkuser "123testuser2" - user.provider.should_not be_nil - test_provider_class user.provider.class - end - -end - - diff --git a/test/ral/type/basic.rb b/test/ral/type/basic.rb new file mode 100755 index 000000000..3c5faeee0 --- /dev/null +++ b/test/ral/type/basic.rb @@ -0,0 +1,85 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../lib/puppettest' + +require 'puppettest' + +class TestBasic < Test::Unit::TestCase + include PuppetTest + + def setup + super + @component = nil + @configfile = nil + @command = nil + + assert_nothing_raised() { + @component = Puppet.type(:component).create( + :name => "yaytest", + :type => "testing" + ) + } + + assert_nothing_raised() { + @filepath = tempfile() + @configfile = Puppet.type(:file).create( + :path => @filepath, + :ensure => "file", + :checksum => "md5" + ) + } + assert_nothing_raised() { + @command = Puppet.type(:exec).create( + :title => "echo", + :command => "echo yay", + :path => ENV["PATH"] + ) + } + @config = mk_catalog(@component, @configfile, @command) + @config.add_edge @component, @configfile + @config.add_edge @component, @command + end + + def teardown + super + stopservices + end + + def test_values + [:ensure, :checksum].each do |param| + prop = @configfile.property(param) + assert(prop, "got no property for %s" % param) + assert(prop.value, "got no value for %s" % param) + end + end + + def test_name_calls + [@command, @configfile].each { |obj| + Puppet.debug "obj is %s" % obj + assert_nothing_raised(){ + obj.name + } + } + end + + def test_name_equality + assert_equal(@filepath, @configfile.title) + + assert_equal("echo", @command.title) + end + + def test_object_retrieval + [@command, @configfile].each { |obj| + assert_equal(obj.class[obj.name].object_id, obj.object_id, + "%s did not match class version" % obj.ref) + } + end + + def test_paths + [@configfile, @command, @component].each { |obj| + assert_nothing_raised { + assert_instance_of(String, obj.path) + } + } + end +end diff --git a/test/ral/type/cron.rb b/test/ral/type/cron.rb new file mode 100755 index 000000000..73e941894 --- /dev/null +++ b/test/ral/type/cron.rb @@ -0,0 +1,499 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../lib/puppettest' + +require 'puppettest' + +# Test cron job creation, modification, and destruction + +class TestCron < Test::Unit::TestCase + include PuppetTest + + def setup + super + + setme() + + @crontype = Puppet::Type.type(:cron) + @provider = @crontype.defaultprovider + if @provider.respond_to?(:filetype=) + @provider.stubs(:filetype).returns(Puppet::Util::FileType.filetype(:ram)) + end + @crontype = Puppet::Type.type(:cron) + end + + def teardown + super + @crontype.defaultprovider = nil + Puppet::Util::FileType.filetype(:ram).clear + end + + def eachprovider + @crontype.suitableprovider.each do |provider| + yield provider + end + end + + # Back up the user's existing cron tab if they have one. + def cronback + tab = nil + assert_nothing_raised { + tab = Puppet.type(:cron).filetype.read(@me) + } + + if $? == 0 + @currenttab = tab + else + @currenttab = nil + end + end + + # Restore the cron tab to its original form. + def cronrestore + assert_nothing_raised { + if @currenttab + @crontype.filetype.new(@me).write(@currenttab) + else + @crontype.filetype.new(@me).remove + end + } + end + + # Create a cron job with all fields filled in. + def mkcron(name, addargs = true) + cron = nil + command = "date > %s/crontest%s" % [tmpdir(), name] + args = nil + if addargs + args = { + :command => command, + :name => name, + :user => @me, + :minute => rand(59), + :month => "1", + :monthday => "1", + :hour => "1" + } + else + args = {:command => command, :name => name} + end + assert_nothing_raised { + cron = @crontype.create(args) + } + + return cron + end + + # Run the cron through its paces -- install it then remove it. + def cyclecron(cron) + obj = Puppet::Type::Cron.cronobj(@me) + + text = obj.read + name = cron.name + comp = mk_catalog(name, cron) + + assert_events([:cron_created], comp) + cron.provider.class.prefetch + currentvalue = cron.retrieve + + assert(cron.insync?(currentvalue), "Cron is not in sync") + + assert_events([], comp) + + curtext = obj.read + text.split("\n").each do |line| + assert(curtext.include?(line), "Missing '%s'" % line) + end + obj = Puppet::Type::Cron.cronobj(@me) + + cron[:ensure] = :absent + + assert_events([:cron_removed], comp) + + cron.provider.class.prefetch + currentvalue = cron.retrieve + + assert(cron.insync?(currentvalue), "Cron is not in sync") + assert_events([], comp) + end + + # Test that a cron job with spaces at the end doesn't get rewritten + def test_trailingspaces + eachprovider do |provider| + cron = nil + # make the cron + name = "yaytest" + command = "date > /dev/null " + assert_nothing_raised { + cron = @crontype.create( + :name => name, + :command => "date > /dev/null ", + :month => "May", + :user => @me + ) + } + property = cron.send(:property, :command) + cron.provider.command = command + cron.provider.ensure = :present + cron.provider.user = @me + cron.provider.month = ["4"] + cron.provider.class.prefetch + currentvalue = cron.retrieve + + currentvalue.each do |prop, value| + # We're only interested in comparing the command. + next unless prop.name.to_s == "command" + assert(prop.insync?(value), "Property %s is not considered in sync with value %s" % [prop.name, value.inspect]) + end + + @crontype.clear + end + end + + def test_makeandretrievecron + %w{storeandretrieve a-name another-name more_naming SomeName}.each do |name| + cron = mkcron(name) + comp = mk_catalog(name, cron) + trans = assert_events([:cron_created], comp, name) + + cron.provider.class.prefetch + cron = nil + + assert(cron = Puppet.type(:cron)[name], "Could not retrieve named cron") + assert_instance_of(Puppet.type(:cron), cron) + end + end + + # Do input validation testing on all of the parameters. + def test_arguments + values = { + :monthday => { + :valid => [ 1, 13, "1" ], + :invalid => [ -1, 0, 32 ] + }, + :weekday => { + :valid => [ 0, 3, 6, "1", "tue", "wed", + "Wed", "MOnday", "SaTurday" ], + :invalid => [ -1, 7, "13", "tues", "teusday", "thurs" ] + }, + :hour => { + :valid => [ 0, 21, 23 ], + :invalid => [ -1, 24 ] + }, + :minute => { + :valid => [ 0, 34, 59 ], + :invalid => [ -1, 60 ] + }, + :month => { + :valid => [ 1, 11, 12, "mar", "March", "apr", "October", "DeCeMbEr" ], + :invalid => [ -1, 0, 13, "marc", "sept" ] + } + } + + cron = mkcron("valtesting") + values.each { |param, hash| + # We have to test the valid ones first, because otherwise the + # property will fail to create at all. + [:valid, :invalid].each { |type| + hash[type].each { |value| + case type + when :valid: + assert_nothing_raised { + cron[param] = value + } + + if value.is_a?(Integer) + assert_equal([value.to_s], cron.should(param), + "Cron value was not set correctly") + end + when :invalid: + assert_raise(Puppet::Error, "%s is incorrectly a valid %s" % + [value, param]) { + cron[param] = value + } + end + + if value.is_a?(Integer) + value = value.to_s + redo + end + } + } + } + end + + # Verify that comma-separated numbers are not resulting in rewrites + def test_comma_separated_vals_work + eachprovider do |provider| + cron = nil + assert_nothing_raised { + cron = @crontype.create( + :command => "/bin/date > /dev/null", + :minute => [0, 30], + :name => "crontest", + :provider => provider.name + ) + } + + + cron.provider.ensure = :present + cron.provider.command = '/bin/date > /dev/null' + cron.provider.minute = %w{0 30} + cron.provider.class.prefetch + currentvalue = cron.retrieve + + currentvalue.each do |prop, value| + # We're only interested in comparing minutes. + next unless prop.name.to_s == "minute" + assert(prop.insync?(value), "Property %s is not considered in sync with value %s" % [prop.name, value.inspect]) + end + @crontype.clear + end + end + + def test_fieldremoval + cron = nil + assert_nothing_raised { + cron = @crontype.create( + :command => "/bin/date > /dev/null", + :minute => [0, 30], + :name => "crontest", + :provider => :crontab + ) + } + + assert_events([:cron_created], cron) + cron.provider.class.prefetch + + cron[:minute] = :absent + assert_events([:cron_changed], cron) + + current_values = nil + assert_nothing_raised { + cron.provider.class.prefetch + current_values = cron.retrieve + } + assert_equal(:absent, current_values[cron.property(:minute)]) + end + + def test_listing + # Make a crontab cron for testing + provider = @crontype.provider(:crontab) + return unless provider.suitable? + + ft = provider.filetype + provider.filetype = :ram + cleanup { provider.filetype = ft } + + setme + cron = @crontype.create(:name => "testing", + :minute => [0, 30], + :command => "/bin/testing", + :user => @me + ) + # Write it to our file + assert_apply(cron) + + @crontype.clear + + crons = [] + assert_nothing_raised { + @crontype.instances.each do |cron| + crons << cron + end + } + + crons.each do |cron| + assert_instance_of(@crontype, cron, "Did not receive a real cron object") + assert_instance_of(String, cron.value(:user), + "Cron user is not a string") + end + end + + def verify_failonnouser + assert_raise(Puppet::Error) do + @crontype.retrieve("nosuchuser") + end + end + + def test_divisionnumbers + cron = mkcron("divtest") + cron[:minute] = "*/5" + + assert_apply(cron) + + cron.provider.class.prefetch + currentvalue = cron.retrieve + + assert_equal(["*/5"], currentvalue[cron.property(:minute)]) + end + + def test_ranges + cron = mkcron("rangetest") + cron[:minute] = "2-4" + + assert_apply(cron) + + current_values = nil + assert_nothing_raised { + cron.provider.class.prefetch + current_values = cron.retrieve + } + + assert_equal(["2-4"], current_values[cron.property(:minute)]) + end + + + def provider_set(cron, param, value) + unless param =~ /=$/ + param = "%s=" % param + end + + cron.provider.send(param, value) + end + + def test_value + cron = mkcron("valuetesting", false) + + # First, test the normal properties + [:minute, :hour, :month].each do |param| + cron.newattr(param) + property = cron.property(param) + + assert(property, "Did not get %s property" % param) + + assert_nothing_raised { +# property.is = :absent + provider_set(cron, param, :absent) + } + + val = "*" + assert_equal(val, cron.value(param)) + + # Make sure arrays work, too + provider_set(cron, param, ["1"]) + assert_equal(%w{1}, cron.value(param)) + + # Make sure values get comma-joined + provider_set(cron, param, %w{2 3}) + assert_equal(%w{2 3}, cron.value(param)) + + # Make sure "should" values work, too + cron[param] = "4" + assert_equal(%w{4}, cron.value(param)) + + cron[param] = ["4"] + assert_equal(%w{4}, cron.value(param)) + + cron[param] = ["4", "5"] + assert_equal(%w{4 5}, cron.value(param)) + + provider_set(cron, param, :absent) + assert_equal(%w{4 5}, cron.value(param)) + end + + Puppet[:trace] = false + + # Now make sure that :command works correctly + cron.delete(:command) + cron.newattr(:command) + property = cron.property(:command) + + assert_nothing_raised { + provider_set(cron, :command, :absent) + } + + param = :command + # Make sure arrays work, too + provider_set(cron, param, ["/bin/echo"]) + assert_equal("/bin/echo", cron.value(param)) + + # Make sure values are not comma-joined + provider_set(cron, param, %w{/bin/echo /bin/test}) + assert_equal("/bin/echo", cron.value(param)) + + # Make sure "should" values work, too + cron[param] = "/bin/echo" + assert_equal("/bin/echo", cron.value(param)) + + cron[param] = ["/bin/echo"] + assert_equal("/bin/echo", cron.value(param)) + + cron[param] = %w{/bin/echo /bin/test} + assert_equal("/bin/echo", cron.value(param)) + + provider_set(cron, param, :absent) + assert_equal("/bin/echo", cron.value(param)) + end + + def test_multiple_users + crons = [] + users = ["root", nonrootuser.name] + users.each do |user| + cron = Puppet::Type.type(:cron).create( + :name => "testcron-#{user}", + :user => user, + :command => "/bin/echo", + :minute => [0,30] + ) + crons << cron + + assert_equal(cron.should(:user), cron.should(:target), + "Target was not set correctly for %s" % user) + end + provider = crons[0].provider.class + + assert_apply(*crons) + + users.each do |user| + users.each do |other| + next if user == other + text = provider.target_object(other).read + + assert(text !~ /testcron-#{user}/, + "%s's cron job is in %s's tab" % + [user, other]) + end + end + end + + # Make sure the user stuff defaults correctly. + def test_default_user + crontab = @crontype.provider(:crontab) + if crontab.suitable? + inst = @crontype.create( + :name => "something", :command => "/some/thing", + :provider => :crontab) + assert_equal(Etc.getpwuid(Process.uid).name, inst.should(:user), + "user did not default to current user with crontab") + assert_equal(Etc.getpwuid(Process.uid).name, inst.should(:target), + "target did not default to current user with crontab") + + # Now make a new cron with a user, and make sure it gets copied + # over + inst = @crontype.create(:name => "yay", :command => "/some/thing", + :user => "bin", :provider => :crontab) + assert_equal("bin", inst.should(:target), + "target did not default to user with crontab") + end + end + + # #705 - make sure extra spaces don't screw things up + def test_spaces_in_command + string = "echo multiple spaces" + cron = @crontype.create(:name => "space testing", :command => string) + assert_apply(cron) + + cron.class.clear + cron = @crontype.create(:name => "space testing", :command => string) + + # Now make sure that it's correctly in sync + cron.provider.class.prefetch("testing" => cron) + properties = cron.retrieve + command, result = properties.find { |prop, value| prop.name == :command } + assert_equal(string, result, "Cron did not pick up extra spaces in command") + assert(command.insync?(string), "Command changed with multiple spaces") + end +end + + diff --git a/test/ral/type/exec.rb b/test/ral/type/exec.rb new file mode 100755 index 000000000..e2a3dd9ed --- /dev/null +++ b/test/ral/type/exec.rb @@ -0,0 +1,770 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../lib/puppettest' + +require 'puppettest' + +class TestExec < Test::Unit::TestCase + include PuppetTest + def test_execution + command = nil + output = nil + assert_nothing_raised { + command = Puppet.type(:exec).create( + :command => "/bin/echo" + ) + } + assert_nothing_raised { + command.evaluate + } + assert_events([:executed_command], command) + end + + def test_numvsstring + [0, "0"].each { |val| + Puppet.type(:exec).clear + Puppet.type(:component).clear + command = nil + output = nil + assert_nothing_raised { + command = Puppet.type(:exec).create( + :command => "/bin/echo", + :returns => val + ) + } + assert_events([:executed_command], command) + } + end + + def test_path_or_qualified + command = nil + output = nil + assert_raise(Puppet::Error) { + command = Puppet.type(:exec).create( + :command => "echo" + ) + } + assert_nothing_raised { + command = Puppet.type(:exec).create( + :command => "echo", + :path => "/usr/bin:/bin:/usr/sbin:/sbin" + ) + } + Puppet.type(:exec).clear + assert_nothing_raised { + command = Puppet.type(:exec).create( + :command => "/bin/echo" + ) + } + Puppet.type(:exec).clear + assert_nothing_raised { + command = Puppet.type(:exec).create( + :command => "/bin/echo", + :path => "/usr/bin:/bin:/usr/sbin:/sbin" + ) + } + end + + def test_nonzero_returns + assert_nothing_raised { + command = Puppet.type(:exec).create( + :command => "mkdir /this/directory/does/not/exist", + :path => "/usr/bin:/bin:/usr/sbin:/sbin", + :returns => 1 + ) + } + assert_nothing_raised { + command = Puppet.type(:exec).create( + :command => "touch /etc", + :path => "/usr/bin:/bin:/usr/sbin:/sbin", + :returns => 1 + ) + } + assert_nothing_raised { + command = Puppet.type(:exec).create( + :command => "thiscommanddoesnotexist", + :path => "/usr/bin:/bin:/usr/sbin:/sbin", + :returns => 127 + ) + } + end + + def test_cwdsettings + command = nil + dir = "/tmp" + wd = Dir.chdir(dir) { + Dir.getwd + } + assert_nothing_raised { + command = Puppet.type(:exec).create( + :command => "pwd", + :cwd => dir, + :path => "/usr/bin:/bin:/usr/sbin:/sbin", + :returns => 0 + ) + } + assert_events([:executed_command], command) + assert_equal(wd,command.output.chomp) + end + + def test_refreshonly_functional + file = nil + cmd = nil + tmpfile = tempfile() + @@tmpfiles.push tmpfile + trans = nil + file = Puppet.type(:file).create( + :path => tmpfile, + :content => "yay" + ) + # Get the file in sync + assert_apply(file) + + # Now make an exec + maker = tempfile() + assert_nothing_raised { + cmd = Puppet.type(:exec).create( + :command => "touch %s" % maker, + :path => "/usr/bin:/bin:/usr/sbin:/sbin", + :subscribe => file, + :refreshonly => true + ) + } + + assert(cmd, "did not make exec") + + assert_nothing_raised do + assert(! cmd.check, "Check passed when refreshonly is set") + end + + assert_events([], file, cmd) + assert(! FileTest.exists?(maker), "made file without refreshing") + + # Now change our content, so we throw a refresh + file[:content] = "yayness" + assert_events([:file_changed, :triggered], file, cmd) + assert(FileTest.exists?(maker), "file was not made in refresh") + end + + def test_refreshonly + cmd = true + assert_nothing_raised { + cmd = Puppet.type(:exec).create( + :command => "pwd", + :path => "/usr/bin:/bin:/usr/sbin:/sbin", + :refreshonly => true + ) + } + + # Checks should always fail when refreshonly is enabled + assert(!cmd.check, "Check passed with refreshonly true") + + # Now make sure it passes if we pass in "true" + assert(cmd.check(true), "Check failed with refreshonly true while refreshing") + + # Now set it to false + cmd[:refreshonly] = false + assert(cmd.check, "Check failed with refreshonly false") + end + + def test_creates + file = tempfile() + exec = nil + assert(! FileTest.exists?(file), "File already exists") + assert_nothing_raised { + exec = Puppet.type(:exec).create( + :command => "touch %s" % file, + :path => "/usr/bin:/bin:/usr/sbin:/sbin", + :creates => file + ) + } + + comp = mk_catalog("createstest", exec) + assert_events([:executed_command], comp, "creates") + assert_events([], comp, "creates") + end + + # Verify that we can download the file that we're going to execute. + def test_retrievethenmkexe + exe = tempfile() + oexe = tempfile() + sh = %x{which sh} + File.open(exe, "w") { |f| f.puts "#!#{sh}\necho yup" } + + file = Puppet.type(:file).create( + :path => oexe, + :source => exe, + :mode => 0755 + ) + + exec = Puppet.type(:exec).create( + :command => oexe, + :require => [:file, oexe] + ) + + comp = mk_catalog("Testing", file, exec) + + assert_events([:file_created, :executed_command], comp) + end + + # Verify that we auto-require any managed scripts. + def test_autorequire_files + exe = tempfile() + oexe = tempfile() + sh = %x{which sh} + File.open(exe, "w") { |f| f.puts "#!#{sh}\necho yup" } + + file = Puppet.type(:file).create( + :path => oexe, + :source => exe, + :mode => 755 + ) + + basedir = File.dirname(oexe) + baseobj = Puppet.type(:file).create( + :path => basedir, + :source => exe, + :mode => 755 + ) + + ofile = Puppet.type(:file).create( + :path => exe, + :mode => 755 + ) + + exec = Puppet.type(:exec).create( + :command => oexe, + :path => ENV["PATH"], + :cwd => basedir + ) + + cat = Puppet.type(:exec).create( + :command => "cat %s %s" % [exe, oexe], + :path => ENV["PATH"] + ) + + rels = nil + assert_nothing_raised do + rels = exec.autorequire + end + + # Verify we get the script itself + assert(rels.detect { |r| r.source == file }, "Exec did not autorequire its command") + + # Verify we catch the cwd + assert(rels.detect { |r| r.source == baseobj }, "Exec did not autorequire its cwd") + + # Verify we don't require ourselves + assert(! rels.detect { |r| r.source == ofile }, "Exec incorrectly required mentioned file") + assert(!exec.requires?(ofile), "Exec incorrectly required file") + + # We not longer autorequire inline files + assert_nothing_raised do + rels = cat.autorequire + end + assert(! rels.detect { |r| r.source == ofile }, "Exec required second inline file") + assert(! rels.detect { |r| r.source == file }, "Exec required inline file") + end + + def test_ifonly + afile = tempfile() + bfile = tempfile() + + exec = nil + assert_nothing_raised { + exec = Puppet.type(:exec).create( + :command => "touch %s" % bfile, + :onlyif => "test -f %s" % afile, + :path => ENV['PATH'] + ) + } + + assert_events([], exec) + system("touch %s" % afile) + assert_events([:executed_command], exec) + assert_events([:executed_command], exec) + system("rm %s" % afile) + assert_events([], exec) + end + + def test_unless + afile = tempfile() + bfile = tempfile() + + exec = nil + assert_nothing_raised { + exec = Puppet.type(:exec).create( + :command => "touch %s" % bfile, + :unless => "test -f %s" % afile, + :path => ENV['PATH'] + ) + } + comp = mk_catalog(exec) + + assert_events([:executed_command], comp) + assert_events([:executed_command], comp) + system("touch %s" % afile) + assert_events([], comp) + assert_events([], comp) + system("rm %s" % afile) + assert_events([:executed_command], comp) + assert_events([:executed_command], comp) + end + + if Puppet::Util::SUIDManager.uid == 0 + # Verify that we can execute commands as a special user + def mknverify(file, user, group = nil, id = true) + File.umask(0022) + + args = { + :command => "touch %s" % file, + :path => "/usr/bin:/bin:/usr/sbin:/sbin", + } + + if user + #Puppet.warning "Using user %s" % user.name + if id + # convert to a string, because that's what the object expects + args[:user] = user.uid.to_s + else + args[:user] = user.name + end + end + + if group + #Puppet.warning "Using group %s" % group.name + if id + args[:group] = group.gid.to_s + else + args[:group] = group.name + end + end + exec = nil + assert_nothing_raised { + exec = Puppet.type(:exec).create(args) + } + + comp = mk_catalog("usertest", exec) + assert_events([:executed_command], comp, "usertest") + + assert(FileTest.exists?(file), "File does not exist") + if user + assert_equal(user.uid, File.stat(file).uid, "File UIDs do not match") + end + + # We can't actually test group ownership, unfortunately, because + # behaviour changes wildlly based on platform. + Puppet::Type.allclear + end + + def test_userngroup + file = tempfile() + [ + [nonrootuser()], # just user, by name + [nonrootuser(), nil, true], # user, by uid + [nil, nonrootgroup()], # just group + [nil, nonrootgroup(), true], # just group, by id + [nonrootuser(), nonrootgroup()], # user and group, by name + [nonrootuser(), nonrootgroup(), true], # user and group, by id + ].each { |ary| + mknverify(file, *ary) { + } + } + end + end + + def test_logoutput + exec = nil + assert_nothing_raised { + exec = Puppet.type(:exec).create( + :title => "logoutputesting", + :path => "/usr/bin:/bin", + :command => "echo logoutput is false", + :logoutput => false + ) + } + + assert_apply(exec) + + assert_nothing_raised { + exec[:command] = "echo logoutput is true" + exec[:logoutput] = true + } + + assert_apply(exec) + + assert_nothing_raised { + exec[:command] = "echo logoutput is on_failure" + exec[:logoutput] = "on_failure" + } + + assert_apply(exec) + end + + def test_execthenfile + exec = nil + file = nil + basedir = tempfile() + path = File.join(basedir, "subfile") + assert_nothing_raised { + exec = Puppet.type(:exec).create( + :title => "mkdir", + :path => "/usr/bin:/bin", + :creates => basedir, + :command => "mkdir %s; touch %s" % [basedir, path] + + ) + } + + assert_nothing_raised { + file = Puppet.type(:file).create( + :path => basedir, + :recurse => true, + :mode => "755", + :require => ["exec", "mkdir"] + ) + } + + comp = mk_catalog(file, exec) + comp.finalize + assert_events([:executed_command, :file_changed], comp) + + assert(FileTest.exists?(path), "Exec ran first") + assert(File.stat(path).mode & 007777 == 0755) + end + + # Make sure all checks need to be fully qualified. + def test_falsevals + exec = nil + assert_nothing_raised do + exec = Puppet.type(:exec).create( + :command => "/bin/touch yayness" + ) + end + + Puppet.type(:exec).checks.each do |check| + klass = Puppet.type(:exec).paramclass(check) + next if klass.values.include? :false + assert_raise(Puppet::Error, "Check '%s' did not fail on false" % check) do + exec[check] = false + end + end + end + + def test_createcwdandexe + exec1 = exec2 = nil + dir = tempfile() + file = tempfile() + + assert_nothing_raised { + exec1 = Puppet.type(:exec).create( + :title => "one", + :path => ENV["PATH"], + :command => "mkdir #{dir}" + ) + } + + assert_nothing_raised("Could not create exec w/out existing cwd") { + exec2 = Puppet.type(:exec).create( + :title => "two", + :path => ENV["PATH"], + :command => "touch #{file}", + :cwd => dir + ) + } + + # Throw a check in there with our cwd and make sure it works + assert_nothing_raised("Could not check with a missing cwd") do + exec2[:unless] = "test -f /this/file/does/not/exist" + exec2.retrieve + end + + assert_raise(Puppet::Error) do + exec2.property(:returns).sync + end + + assert_nothing_raised do + exec2[:require] = exec1 + end + + assert_apply(exec1, exec2) + + assert(FileTest.exists?(file)) + end + + def test_checkarrays + exec = nil + file = tempfile() + + test = "test -f #{file}" + + assert_nothing_raised { + exec = Puppet.type(:exec).create( + :path => ENV["PATH"], + :command => "touch #{file}" + ) + } + + assert_nothing_raised { + exec[:unless] = test + } + + assert_nothing_raised { + assert(exec.check, "Check did not pass") + } + + assert_nothing_raised { + exec[:unless] = [test, test] + } + + + assert_nothing_raised { + exec.finish + } + + assert_nothing_raised { + assert(exec.check, "Check did not pass") + } + + assert_apply(exec) + + assert_nothing_raised { + assert(! exec.check, "Check passed") + } + end + + def test_missing_checks_cause_failures + # Solaris's sh exits with 1 here instead of 127 + return if Facter.value(:operatingsystem) == "Solaris" + exec = Puppet::Type.type(:exec).create( + :command => "echo true", + :path => ENV["PATH"], + :onlyif => "/bin/nosuchthingexists" + ) + + assert_raise(ArgumentError, "Missing command did not raise error") { + exec.run("/bin/nosuchthingexists") + } + end + + def test_envparam + exec = Puppet::Type.newexec( + :command => "echo $envtest", + :path => ENV["PATH"], + :env => "envtest=yayness" + ) + + assert(exec, "Could not make exec") + + output = status = nil + assert_nothing_raised { + output, status = exec.run("echo $envtest") + } + + assert_equal("yayness\n", output) + + # Now check whether we can do multiline settings + assert_nothing_raised do + exec[:env] = "envtest=a list of things +and stuff" + end + + output = status = nil + assert_nothing_raised { + output, status = exec.run('echo "$envtest"') + } + assert_equal("a list of things\nand stuff\n", output) + + # Now test arrays + assert_nothing_raised do + exec[:env] = ["funtest=A", "yaytest=B"] + end + + output = status = nil + assert_nothing_raised { + output, status = exec.run('echo "$funtest" "$yaytest"') + } + assert_equal("A B\n", output) + end + + def test_environmentparam + exec = Puppet::Type.newexec( + :command => "echo $environmenttest", + :path => ENV["PATH"], + :environment => "environmenttest=yayness" + ) + + assert(exec, "Could not make exec") + + output = status = nil + assert_nothing_raised { + output, status = exec.run("echo $environmenttest") + } + + assert_equal("yayness\n", output) + + # Now check whether we can do multiline settings + assert_nothing_raised do + exec[:environment] = "environmenttest=a list of things +and stuff" + end + + output = status = nil + assert_nothing_raised { + output, status = exec.run('echo "$environmenttest"') + } + assert_equal("a list of things\nand stuff\n", output) + + # Now test arrays + assert_nothing_raised do + exec[:environment] = ["funtest=A", "yaytest=B"] + end + + output = status = nil + assert_nothing_raised { + output, status = exec.run('echo "$funtest" "$yaytest"') + } + assert_equal("A B\n", output) + end + + def test_timeout + exec = Puppet::Type.type(:exec).create(:command => "sleep 1", :path => ENV["PATH"], :timeout => "0.2") + time = Time.now + + assert_raise(Timeout::Error) { + exec.run("sleep 1") + } + Puppet.info "%s seconds, vs a timeout of %s" % [Time.now.to_f - time.to_f, exec[:timeout]] + + + assert_apply(exec) + end + + # Testing #470 + def test_run_as_created_user + exec = nil + if Process.uid == 0 + user = "nosuchuser" + assert_nothing_raised("Could not create exec with non-existent user") do + exec = Puppet::Type.type(:exec).create( + :command => "/bin/echo yay", + :user => user + ) + end + end + + # Now try the group + group = "nosuchgroup" + assert_nothing_raised("Could not create exec with non-existent user") do + exec = Puppet::Type.type(:exec).create( + :command => "/bin/echo yay", + :group => group + ) + end + end + + # make sure paths work both as arrays and strings + def test_paths_as_arrays + path = %w{/usr/bin /usr/sbin /sbin} + exec = nil + assert_nothing_raised("Could not use an array for the path") do + exec = Puppet::Type.type(:exec).create(:command => "echo yay", + :path => path) + end + assert_equal(path, exec[:path], "array-based path did not match") + assert_nothing_raised("Could not use a string for the path") do + exec = Puppet::Type.type(:exec).create(:command => "echo yay", + :path => path.join(":")) + end + assert_equal(path, exec[:path], "string-based path did not match") + assert_nothing_raised("Could not use a colon-separated strings in an array for the path") do + exec = Puppet::Type.type(:exec).create(:command => "echo yay", + :path => ["/usr/bin", "/usr/sbin:/sbin"]) + end + assert_equal(path, exec[:path], "colon-separated array path did not match") + end + + def test_checks_apply_to_refresh + file = tempfile() + maker = tempfile() + exec = Puppet::Type.type(:exec).create( + :title => "maker", + :command => "touch #{maker}", + :path => ENV["PATH"] + ) + + # Make sure it runs normally + assert_apply(exec) + assert(FileTest.exists?(maker), "exec did not run") + File.unlink(maker) + + # Now make sure it refreshes + assert_nothing_raised("Failed to refresh exec") do + exec.refresh + end + assert(FileTest.exists?(maker), "exec did not run refresh") + File.unlink(maker) + + # Now add the checks + exec[:creates] = file + + # Make sure it runs when the file doesn't exist + assert_nothing_raised("Failed to refresh exec") do + exec.refresh + end + assert(FileTest.exists?(maker), "exec did not refresh when checks passed") + File.unlink(maker) + + # Now create the file and make sure it doesn't refresh + File.open(file, "w") { |f| f.puts "" } + assert_nothing_raised("Failed to refresh exec") do + exec.refresh + end + assert(! FileTest.exists?(maker), "exec refreshed with failing checks") + end + + def test_explicit_refresh + refresher = tempfile() + maker = tempfile() + exec = Puppet::Type.type(:exec).create( + :title => "maker", + :command => "touch #{maker}", + :path => ENV["PATH"] + ) + + # Call refresh normally + assert_nothing_raised do + exec.refresh + end + + # Make sure it created the normal file + assert(FileTest.exists?(maker), "normal refresh did not work") + File.unlink(maker) + + # Now reset refresh, and make sure it wins + assert_nothing_raised("Could not set refresh parameter") do + exec[:refresh] = "touch #{refresher}" + end + assert_nothing_raised do + exec.refresh + end + + # Make sure it created the normal file + assert(FileTest.exists?(refresher), "refresh param was ignored") + assert(! FileTest.exists?(maker), "refresh param also ran command") + end + + if Puppet.features.root? + def test_autorequire_user + user = Puppet::Type.type(:user).create(:name => "yay") + exec = Puppet::Type.type(:exec).create(:command => "/bin/echo fun", :user => "yay") + + rels = nil + assert_nothing_raised("Could not evaluate autorequire") do + rels = exec.autorequire + end + assert(rels.find { |r| r.source == user and r.target == exec }, "Exec did not autorequire user") + end + end +end + diff --git a/test/ral/type/file.rb b/test/ral/type/file.rb new file mode 100755 index 000000000..cbbe818ae --- /dev/null +++ b/test/ral/type/file.rb @@ -0,0 +1,1782 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../lib/puppettest' + +require 'puppettest' +require 'puppettest/support/utils' +require 'fileutils' + +class TestFile < Test::Unit::TestCase + include PuppetTest::Support::Utils + include PuppetTest::FileTesting + + def mkfile(hash) + file = nil + assert_nothing_raised { + file = Puppet.type(:file).create(hash) + } + return file + end + + def mktestfile + tmpfile = tempfile() + File.open(tmpfile, "w") { |f| f.puts rand(100) } + @@tmpfiles.push tmpfile + mkfile(:name => tmpfile) + end + + def setup + super + @file = Puppet::Type.type(:file) + $method = @method_name + Puppet[:filetimeout] = -1 + end + + def teardown + Puppet::Util::Storage.clear + system("rm -rf %s" % Puppet[:statefile]) + super + end + + def initstorage + Puppet::Util::Storage.init + Puppet::Util::Storage.load + end + + def clearstorage + Puppet::Util::Storage.store + Puppet::Util::Storage.clear + end + + def test_owner + file = mktestfile() + + users = {} + count = 0 + + # collect five users + Etc.passwd { |passwd| + if count > 5 + break + else + count += 1 + end + users[passwd.uid] = passwd.name + } + + fake = {} + # find a fake user + while true + a = rand(1000) + begin + Etc.getpwuid(a) + rescue + fake[a] = "fakeuser" + break + end + end + + uid, name = users.shift + us = {} + us[uid] = name + users.each { |uid, name| + assert_apply(file) + assert_nothing_raised() { + file[:owner] = name + } + assert_nothing_raised() { + file.retrieve + } + assert_apply(file) + } + end + + def test_group + file = mktestfile() + [%x{groups}.chomp.split(/ /), Process.groups].flatten.each { |group| + assert_nothing_raised() { + file[:group] = group + } + assert(file.property(:group)) + assert(file.property(:group).should) + } + end + + def test_groups_fails_when_invalid + assert_raise(Puppet::Error, "did not fail when the group was empty") do + Puppet::Type.type(:file).create :path => "/some/file", :group => "" + end + end + + if Puppet::Util::SUIDManager.uid == 0 + def test_createasuser + dir = tmpdir() + + user = nonrootuser() + path = File.join(tmpdir, "createusertesting") + @@tmpfiles << path + + file = nil + assert_nothing_raised { + file = Puppet.type(:file).create( + :path => path, + :owner => user.name, + :ensure => "file", + :mode => "755" + ) + } + + comp = mk_catalog("createusertest", file) + + assert_events([:file_created], comp) + end + + def test_nofollowlinks + basedir = tempfile() + Dir.mkdir(basedir) + file = File.join(basedir, "file") + link = File.join(basedir, "link") + + File.open(file, "w", 0644) { |f| f.puts "yayness"; f.flush } + File.symlink(file, link) + + # First test 'user' + user = nonrootuser() + + inituser = File.lstat(link).uid + File.lchown(inituser, nil, link) + + obj = nil + assert_nothing_raised { + obj = Puppet.type(:file).create( + :title => link, + :owner => user.name + ) + } + obj.retrieve + + # Make sure it defaults to managing the link + assert_events([:file_changed], obj) + assert_equal(user.uid, File.lstat(link).uid) + assert_equal(inituser, File.stat(file).uid) + File.chown(inituser, nil, file) + File.lchown(inituser, nil, link) + + # Try following + obj[:links] = :follow + assert_events([:file_changed], obj) + assert_equal(user.uid, File.stat(file).uid) + assert_equal(inituser, File.lstat(link).uid) + + # And then explicitly managing + File.chown(inituser, nil, file) + File.lchown(inituser, nil, link) + obj[:links] = :manage + assert_events([:file_changed], obj) + assert_equal(user.uid, File.lstat(link).uid) + assert_equal(inituser, File.stat(file).uid) + + obj.delete(:owner) + obj[:links] = :follow + + # And then test 'group' + group = nonrootgroup + + initgroup = File.stat(file).gid + obj[:group] = group.name + + assert_events([:file_changed], obj) + assert_equal(initgroup, File.stat(file).gid) + assert_equal(group.gid, File.lstat(link).gid) + File.chown(nil, initgroup, file) + File.lchown(nil, initgroup, link) + + obj[:links] = :follow + assert_events([:file_changed], obj) + assert_equal(group.gid, File.stat(file).gid) + File.chown(nil, initgroup, file) + File.lchown(nil, initgroup, link) + + obj[:links] = :manage + assert_events([:file_changed], obj) + assert_equal(group.gid, File.lstat(link).gid) + assert_equal(initgroup, File.stat(file).gid) + end + + def test_ownerasroot + file = mktestfile() + + users = {} + count = 0 + + # collect five users + Etc.passwd { |passwd| + if count > 5 + break + else + count += 1 + end + next if passwd.uid < 0 + users[passwd.uid] = passwd.name + } + + fake = {} + # find a fake user + while true + a = rand(1000) + begin + Etc.getpwuid(a) + rescue + fake[a] = "fakeuser" + break + end + end + + users.each { |uid, name| + assert_nothing_raised() { + file[:owner] = name + } + changes = [] + assert_nothing_raised() { + changes << file.evaluate + } + assert(changes.length > 0) + assert_apply(file) + currentvalue = file.retrieve + assert(file.insync?(currentvalue)) + assert_nothing_raised() { + file[:owner] = uid + } + assert_apply(file) + currentvalue = file.retrieve + # make sure changing to number doesn't cause a sync + assert(file.insync?(currentvalue)) + } + + # We no longer raise an error here, because we check at run time + #fake.each { |uid, name| + # assert_raise(Puppet::Error) { + # file[:owner] = name + # } + # assert_raise(Puppet::Error) { + # file[:owner] = uid + # } + #} + end + + def test_groupasroot + file = mktestfile() + [%x{groups}.chomp.split(/ /), Process.groups].flatten.each { |group| + next unless Puppet::Util.gid(group) # grr. + assert_nothing_raised() { + file[:group] = group + } + assert(file.property(:group)) + assert(file.property(:group).should) + assert_apply(file) + currentvalue = file.retrieve + assert(file.insync?(currentvalue)) + assert_nothing_raised() { + file.delete(:group) + } + } + end + + if Facter.value(:operatingsystem) == "Darwin" + def test_sillyowner + file = tempfile() + File.open(file, "w") { |f| f.puts "" } + File.chown(-2, nil, file) + + assert(File.stat(file).uid > 120000, "eh?") + user = nonrootuser + obj = Puppet::Type.newfile( + :path => file, + :owner => user.name + ) + + assert_apply(obj) + + assert_equal(user.uid, File.stat(file).uid) + end + end + else + $stderr.puts "Run as root for complete owner and group testing" + end + + def test_create + %w{a b c d}.collect { |name| tempfile() + name.to_s }.each { |path| + file =nil + assert_nothing_raised() { + file = Puppet.type(:file).create( + :name => path, + :ensure => "file" + ) + } + assert_events([:file_created], file) + assert_events([], file) + assert(FileTest.file?(path), "File does not exist") + assert(file.insync?(file.retrieve)) + @@tmpfiles.push path + } + end + + def test_create_dir + basedir = tempfile() + Dir.mkdir(basedir) + %w{a b c d}.collect { |name| "#{basedir}/%s" % name }.each { |path| + file = nil + assert_nothing_raised() { + file = Puppet.type(:file).create( + :name => path, + :ensure => "directory" + ) + } + assert(! FileTest.directory?(path), "Directory %s already exists" % + [path]) + assert_events([:directory_created], file) + assert_events([], file) + assert(file.insync?(file.retrieve)) + assert(FileTest.directory?(path)) + @@tmpfiles.push path + } + end + + def test_modes + file = mktestfile + # Set it to something else initially + File.chmod(0775, file.title) + [0644,0755,0777,0641].each { |mode| + assert_nothing_raised() { + file[:mode] = mode + } + assert_events([:file_changed], file) + assert_events([], file) + + assert(file.insync?(file.retrieve)) + + assert_nothing_raised() { + file.delete(:mode) + } + } + end + + def test_checksums + types = %w{md5 md5lite timestamp time} + exists = "/tmp/sumtest-exists" + nonexists = "/tmp/sumtest-nonexists" + + @@tmpfiles << exists + @@tmpfiles << nonexists + + # try it both with files that exist and ones that don't + files = [exists, nonexists] + initstorage + File.open(exists,File::CREAT|File::TRUNC|File::WRONLY) { |of| + of.puts "initial text" + } + types.each { |type| + files.each { |path| + if Puppet[:debug] + Puppet.warning "Testing %s on %s" % [type,path] + end + file = nil + events = nil + # okay, we now know that we have a file... + assert_nothing_raised() { + file = Puppet.type(:file).create( + :name => path, + :ensure => "file", + :checksum => type + ) + } + trans = nil + + currentvalues = file.retrieve + + if file.title !~ /nonexists/ + sum = file.property(:checksum) + assert(sum.insync?(currentvalues[sum]), "file is not in sync") + end + + events = assert_apply(file) + + assert(events) + + assert(! events.include?(:file_changed), "File incorrectly changed") + assert_events([], file) + + # We have to sleep because the time resolution of the time-based + # mechanisms is greater than one second + sleep 1 if type =~ /time/ + + assert_nothing_raised() { + File.open(path,File::CREAT|File::TRUNC|File::WRONLY) { |of| + of.puts "some more text, yo" + } + } + Puppet.type(:file).clear + + # now recreate the file + assert_nothing_raised() { + file = Puppet.type(:file).create( + :name => path, + :checksum => type + ) + } + trans = nil + + assert_events([:file_changed], file) + + # Run it a few times to make sure we aren't getting + # spurious changes. + sum = nil + assert_nothing_raised do + sum = file.property(:checksum).retrieve + end + assert(file.property(:checksum).insync?(sum), + "checksum is not in sync") + + sleep 1.1 if type =~ /time/ + assert_nothing_raised() { + File.unlink(path) + File.open(path,File::CREAT|File::TRUNC|File::WRONLY) { |of| + # We have to put a certain amount of text in here or + # the md5-lite test fails + 2.times { + of.puts rand(100) + } + of.flush + } + } + assert_events([:file_changed], file) + + # verify that we're actually getting notified when a file changes + assert_nothing_raised() { + Puppet.type(:file).clear + } + + if path =~ /nonexists/ + File.unlink(path) + end + } + } + end + + def cyclefile(path) + # i had problems with using :name instead of :path + [:name,:path].each { |param| + file = nil + changes = nil + comp = nil + trans = nil + + initstorage + assert_nothing_raised { + file = Puppet.type(:file).create( + param => path, + :recurse => true, + :checksum => "md5" + ) + } + comp = Puppet.type(:component).create( + :name => "component" + ) + comp.push file + assert_nothing_raised { + trans = comp.evaluate + } + assert_nothing_raised { + trans.evaluate + } + clearstorage + Puppet::Type.allclear + } + end + + def test_localrecurse + # Create a test directory + path = tempfile() + dir = @file.create :path => path, :mode => 0755, :recurse => true + config = mk_catalog(dir) + + Dir.mkdir(path) + + # Make sure we return nothing when there are no children + ret = nil + assert_nothing_raised() { ret = dir.localrecurse(true) } + assert_equal([], ret, "empty dir returned children") + + # Now make a file and make sure we get it + test = File.join(path, "file") + File.open(test, "w") { |f| f.puts "yay" } + assert_nothing_raised() { ret = dir.localrecurse(true) } + fileobj = @file[test] + assert(fileobj, "child object was not created") + assert_equal([fileobj], ret, "child object was not returned") + + # And that it inherited our recurse setting + assert_equal(true, fileobj[:recurse], "file did not inherit recurse") + + # Make sure it's not returned again + assert_nothing_raised() { ret = dir.localrecurse(true) } + assert_equal([], ret, "child object was returned twice") + + # Now just for completion, make sure we will return many files + files = [] + 10.times do |i| + f = File.join(path, i.to_s) + files << f + File.open(f, "w") do |o| o.puts "" end + end + assert_nothing_raised() { ret = dir.localrecurse(true) } + assert_equal(files.sort, ret.collect { |f| f.title }.sort, + "child object was returned twice") + + # Clean everything up and start over + files << test + files.each do |f| File.unlink(f) end + + # Now make sure we correctly ignore things + dir[:ignore] = "*.out" + bad = File.join(path, "test.out") + good = File.join(path, "yayness") + [good, bad].each do |f| + File.open(f, "w") { |o| o.puts "" } + end + + assert_nothing_raised() { ret = dir.localrecurse(true) } + assert_equal([good], ret.collect { |f| f.title }, "ignore failed") + + # Now make sure purging works + dir[:purge] = true + dir[:ignore] = "svn" + + assert_nothing_raised() { ret = dir.localrecurse(true) } + assert_equal([bad], ret.collect { |f| f.title }, "purge failed") + + badobj = @file[bad] + assert(badobj, "did not create bad object") + end + + def test_recurse + basedir = tempfile() + FileUtils.mkdir_p(basedir) + + # Create our file + dir = nil + assert_nothing_raised { + dir = Puppet.type(:file).create( + :path => basedir, + :check => %w{owner mode group} + ) + } + + return_nil = false + + # and monkey-patch it + [:localrecurse, :linkrecurse].each do |m| + dir.meta_def(m) do |recurse| + if return_nil # for testing nil return, of course + return nil + else + return [recurse] + end + end + end + + # We have to special-case this, because it returns a list of + # found files. + dir.meta_def(:sourcerecurse) do |recurse| + if return_nil # for testing nil return, of course + return nil + else + return [recurse], [] + end + end + + # First try it with recurse set to false + dir[:recurse] = false + assert_nothing_raised do + assert_nil(dir.recurse) + end + + # Now try it with the different valid positive values + [true, "true", "inf", 50].each do |value| + assert_nothing_raised { dir[:recurse] = value} + + # Now make sure the methods are called appropriately + ret = nil + assert_nothing_raised do + ret = dir.recurse + end + + # We should only call the localrecurse method, so make sure + # that's the case + if value == 50 + # Make sure our counter got decremented + assert_equal([49], ret, "did not call localrecurse") + else + assert_equal([true], ret, "did not call localrecurse") + end + end + + # Make sure it doesn't recurse when we've set recurse to false + [false, "false"].each do |value| + assert_nothing_raised { dir[:recurse] = value } + + ret = nil + assert_nothing_raised() { ret = dir.recurse } + assert_nil(ret) + end + dir[:recurse] = true + + # Now add a target, so we do the linking thing + dir[:target] = tempfile() + ret = nil + assert_nothing_raised { ret = dir.recurse } + assert_equal([true, true], ret, "did not call linkrecurse") + + # And add a source, and make sure we call that + dir[:source] = tempfile() + assert_nothing_raised { ret = dir.recurse } + assert_equal([true, true, true], ret, "did not call linkrecurse") + + # Lastly, make sure we correctly handle returning nil + return_nil = true + assert_nothing_raised { ret = dir.recurse } + end + + def test_recurse? + file = Puppet::Type.type(:file).create :path => tempfile + + # Make sure we default to false + assert(! file.recurse?, "Recurse defaulted to true") + + [true, "true", 10, "inf"].each do |value| + file[:recurse] = value + assert(file.recurse?, "%s did not cause recursion" % value) + end + + [false, "false", 0].each do |value| + file[:recurse] = value + assert(! file.recurse?, "%s caused recursion" % value) + end + end + + def test_recursion + basedir = tempfile() + subdir = File.join(basedir, "subdir") + tmpfile = File.join(basedir,"testing") + FileUtils.mkdir_p(subdir) + + dir = nil + [true, "true", "inf", 50].each do |value| + assert_nothing_raised { + dir = Puppet.type(:file).create( + :path => basedir, + :recurse => value, + :check => %w{owner mode group} + ) + } + config = mk_catalog dir + + children = nil + + assert_nothing_raised { + children = dir.eval_generate + } + + assert_equal([subdir], children.collect {|c| c.title }, + "Incorrect generated children") + + # Remove our subdir resource, + subdir_resource = config.resource(:file, subdir) + config.remove_resource(subdir_resource) + + # Create the test file + File.open(tmpfile, "w") { |f| f.puts "yayness" } + + assert_nothing_raised { + children = dir.eval_generate + } + + # And make sure we get both resources back. + assert_equal([subdir, tmpfile].sort, children.collect {|c| c.title }.sort, + "Incorrect generated children when recurse == %s" % value.inspect) + + File.unlink(tmpfile) + Puppet.type(:file).clear + end + end + + def test_filetype_retrieval + file = nil + + # Verify it retrieves files of type directory + assert_nothing_raised { + file = Puppet.type(:file).create( + :name => tmpdir(), + :check => :type + ) + } + + assert_nothing_raised { + file.evaluate + } + + assert_equal("directory", file.property(:type).retrieve) + + # And then check files + assert_nothing_raised { + file = Puppet.type(:file).create( + :name => tempfile(), + :ensure => "file" + ) + } + + assert_apply(file) + file[:check] = "type" + assert_apply(file) + + assert_equal("file", file.property(:type).retrieve) + + file[:type] = "directory" + + currentvalues = {} + assert_nothing_raised { currentvalues = file.retrieve } + + # The 'retrieve' method sets @should to @is, so they're never + # out of sync. It's a read-only class. + assert(file.insync?(currentvalues)) + end + + def test_remove + basedir = tempfile() + subdir = File.join(basedir, "this") + FileUtils.mkdir_p(subdir) + + dir = nil + assert_nothing_raised { + dir = Puppet.type(:file).create( + :path => basedir, + :recurse => true, + :check => %w{owner mode group} + ) + } + mk_catalog dir + + assert_nothing_raised { + dir.eval_generate + } + + obj = nil + assert_nothing_raised { + obj = Puppet.type(:file)[subdir] + } + + assert(obj, "Could not retrieve subdir object") + + assert_nothing_raised { + obj.remove(true) + } + + assert_nothing_raised { + obj = Puppet.type(:file)[subdir] + } + + assert_nil(obj, "Retrieved removed object") + end + + def test_path + dir = tempfile() + + path = File.join(dir, "subdir") + + assert_nothing_raised("Could not make file") { + FileUtils.mkdir_p(File.dirname(path)) + File.open(path, "w") { |f| f.puts "yayness" } + } + + file = nil + dirobj = nil + assert_nothing_raised("Could not make file object") { + dirobj = Puppet.type(:file).create( + :path => dir, + :recurse => true, + :check => %w{mode owner group} + ) + } + mk_catalog dirobj + + assert_nothing_raised { + dirobj.eval_generate + } + + assert_nothing_raised { + file = dirobj.class[path] + } + + assert(file, "Could not retrieve file object") + + assert_equal("/%s" % file.ref, file.path) + end + + def test_autorequire + basedir = tempfile() + subfile = File.join(basedir, "subfile") + + baseobj = Puppet.type(:file).create( + :name => basedir, + :ensure => "directory" + ) + + subobj = Puppet.type(:file).create( + :name => subfile, + :ensure => "file" + ) + edge = nil + assert_nothing_raised do + edge = subobj.autorequire.shift + end + assert_equal(baseobj, edge.source, "file did not require its parent dir") + assert_equal(subobj, edge.target, "file did not require its parent dir") + end + + def test_content + file = tempfile() + str = "This is some content" + + obj = nil + assert_nothing_raised { + obj = Puppet.type(:file).create( + :name => file, + :content => str + ) + } + + assert(!obj.insync?(obj.retrieve), "Object is incorrectly in sync") + + assert_events([:file_created], obj) + + currentvalues = obj.retrieve + + assert(obj.insync?(currentvalues), "Object is not in sync") + + text = File.read(file) + + assert_equal(str, text, "Content did not copy correctly") + + newstr = "Another string, yo" + + obj[:content] = newstr + + assert(!obj.insync?(obj.retrieve), "Object is incorrectly in sync") + + assert_events([:file_changed], obj) + + text = File.read(file) + + assert_equal(newstr, text, "Content did not copy correctly") + + currentvalues = obj.retrieve + assert(obj.insync?(currentvalues), "Object is not in sync") + end + + # Unfortunately, I know this fails + def disabled_test_recursivemkdir + path = tempfile() + subpath = File.join(path, "this", "is", "a", "dir") + file = nil + assert_nothing_raised { + file = Puppet.type(:file).create( + :name => subpath, + :ensure => "directory", + :recurse => true + ) + } + + comp = mk_catalog("yay", file) + comp.finalize + assert_apply(comp) + #assert_events([:directory_created], comp) + + assert(FileTest.directory?(subpath), "Did not create directory") + end + + # Make sure that content updates the checksum on the same run + def test_checksumchange_for_content + dest = tempfile() + File.open(dest, "w") { |f| f.puts "yayness" } + + file = nil + assert_nothing_raised { + file = Puppet.type(:file).create( + :name => dest, + :checksum => "md5", + :content => "This is some content" + ) + } + + file.retrieve + + assert_events([:file_changed], file) + file.retrieve + assert_events([], file) + end + + # Make sure that content updates the checksum on the same run + def test_checksumchange_for_ensure + dest = tempfile() + + file = nil + assert_nothing_raised { + file = Puppet.type(:file).create( + :name => dest, + :checksum => "md5", + :ensure => "file" + ) + } + + file.retrieve + + assert_events([:file_created], file) + file.retrieve + assert_events([], file) + end + + # Make sure that content gets used before ensure + def test_contentbeatsensure + dest = tempfile() + + file = nil + assert_nothing_raised { + file = Puppet.type(:file).create( + :name => dest, + :ensure => "file", + :content => "this is some content, yo" + ) + } + + currentvalues = file.retrieve + + assert_events([:file_created], file) + file.retrieve + assert_events([], file) + assert_events([], file) + end + + # Make sure that content gets used before ensure + def test_deletion_beats_source + dest = tempfile() + source = tempfile() + File.open(source, "w") { |f| f.puts "yay" } + + file = nil + assert_nothing_raised { + file = Puppet.type(:file).create( + :name => dest, + :ensure => :absent, + :source => source + ) + } + + file.retrieve + + assert_events([], file) + assert(! FileTest.exists?(dest), "file was copied during deletion") + + # Now create the dest, and make sure it gets deleted + File.open(dest, "w") { |f| f.puts "boo" } + assert_events([:file_removed], file) + assert(! FileTest.exists?(dest), "file was not deleted during deletion") + end + + def test_nameandpath + path = tempfile() + + file = nil + assert_nothing_raised { + file = Puppet.type(:file).create( + :title => "fileness", + :path => path, + :content => "this is some content" + ) + } + + assert_apply(file) + + assert(FileTest.exists?(path)) + end + + # Make sure that a missing group isn't fatal at object instantiation time. + def test_missinggroup + file = nil + assert_nothing_raised { + file = Puppet.type(:file).create( + :path => tempfile(), + :group => "fakegroup" + ) + } + + assert(file.property(:group), "Group property failed") + end + + def test_modecreation + path = tempfile() + file = Puppet.type(:file).create( + :path => path, + :ensure => "file", + :mode => "0777" + ) + assert_equal(0777, file.should(:mode), + "Mode did not get set correctly") + assert_apply(file) + assert_equal(0777, File.stat(path).mode & 007777, + "file mode is incorrect") + File.unlink(path) + file[:ensure] = "directory" + assert_apply(file) + assert_equal(0777, File.stat(path).mode & 007777, + "directory mode is incorrect") + end + + # If both 'ensure' and 'content' are used, make sure that all of the other + # properties are handled correctly. + def test_contentwithmode + path = tempfile() + + file = nil + assert_nothing_raised { + file = Puppet.type(:file).create( + :path => path, + :ensure => "file", + :content => "some text\n", + :mode => 0755 + ) + } + + assert_apply(file) + assert_equal("%o" % 0755, "%o" % (File.stat(path).mode & 007777)) + end + + def test_backupmodes + File.umask(0022) + + file = tempfile() + newfile = tempfile() + + File.open(file, "w", 0411) { |f| f.puts "yayness" } + + obj = nil + assert_nothing_raised { + obj = Puppet::Type.type(:file).create( + :path => file, :content => "rahness\n", :backup => ".puppet-bak" + ) + } + + assert_apply(obj) + + backupfile = file + obj[:backup] + @@tmpfiles << backupfile + assert(FileTest.exists?(backupfile), + "Backup file %s does not exist" % backupfile) + + assert_equal(0411, filemode(backupfile), + "File mode is wrong for backupfile") + + bucket = "bucket" + bpath = tempfile() + Dir.mkdir(bpath) + Puppet::Type.type(:filebucket).create( + :title => bucket, :path => bpath + ) + + obj[:backup] = bucket + obj[:content] = "New content" + assert_apply(obj) + + md5 = "18cc17fa3047fcc691fdf49c0a7f539a" + dir, file, pathfile = Puppet::Network::Handler.filebucket.paths(bpath, md5) + + assert_equal(0440, filemode(file)) + end + + def test_largefilechanges + source = tempfile() + dest = tempfile() + + # Now make a large file + File.open(source, "w") { |f| + 500.times { |i| f.puts "line %s" % i } + } + + obj = Puppet::Type.type(:file).create( + :title => dest, :source => source + ) + + assert_events([:file_created], obj) + + File.open(source, File::APPEND|File::WRONLY) { |f| f.puts "another line" } + + assert_events([:file_changed], obj) + + # Now modify the dest file + File.open(dest, File::APPEND|File::WRONLY) { |f| f.puts "one more line" } + + assert_events([:file_changed, :file_changed], obj) + + end + + def test_replacefilewithlink + path = tempfile() + link = tempfile() + + File.open(path, "w") { |f| f.puts "yay" } + File.open(link, "w") { |f| f.puts "a file" } + + file = nil + assert_nothing_raised { + file = Puppet.type(:file).create( + :ensure => path, + :path => link + ) + } + + assert_events([:link_created], file) + + assert(FileTest.symlink?(link), "Link was not created") + + assert_equal(path, File.readlink(link), "Link was created incorrectly") + end + + def test_file_with_spaces + dir = tempfile() + Dir.mkdir(dir) + source = File.join(dir, "file spaces") + dest = File.join(dir, "another space") + + File.open(source, "w") { |f| f.puts :yay } + obj = Puppet::Type.type(:file).create( + :path => dest, + :source => source + ) + assert(obj, "Did not create file") + + assert_apply(obj) + + assert(FileTest.exists?(dest), "File did not get created") + end + + def test_present_matches_anything + path = tempfile() + + file = Puppet::Type.newfile(:path => path, :ensure => :present) + + currentvalues = file.retrieve + assert(! file.insync?(currentvalues), "File incorrectly in sync") + + # Now make a file + File.open(path, "w") { |f| f.puts "yay" } + + currentvalues = file.retrieve + assert(file.insync?(currentvalues), "File not in sync") + + # Now make a directory + File.unlink(path) + Dir.mkdir(path) + + currentvalues = file.retrieve + assert(file.insync?(currentvalues), "Directory not considered 'present'") + + Dir.rmdir(path) + + # Now make a link + file[:links] = :manage + + otherfile = tempfile() + File.symlink(otherfile, path) + + currentvalues = file.retrieve + assert(file.insync?(currentvalues), "Symlink not considered 'present'") + File.unlink(path) + + # Now set some content, and make sure it works + file[:content] = "yayness" + + assert_apply(file) + + assert_equal("yayness", File.read(path), "Content did not get set correctly") + end + + # Make sure unmanaged files are purged. + def test_purge + sourcedir = tempfile() + destdir = tempfile() + Dir.mkdir(sourcedir) + Dir.mkdir(destdir) + sourcefile = File.join(sourcedir, "sourcefile") + dsourcefile = File.join(destdir, "sourcefile") + localfile = File.join(destdir, "localfile") + purgee = File.join(destdir, "to_be_purged") + File.open(sourcefile, "w") { |f| f.puts "funtest" } + # this file should get removed + File.open(purgee, "w") { |f| f.puts "footest" } + + lfobj = Puppet::Type.newfile( + :title => "localfile", + :path => localfile, + :content => "rahtest", + :ensure => :file, + :backup => false + ) + + destobj = Puppet::Type.newfile(:title => "destdir", :path => destdir, + :source => sourcedir, + :backup => false, + :recurse => true) + + config = mk_catalog(lfobj, destobj) + config.apply + + assert(FileTest.exists?(dsourcefile), "File did not get copied") + assert(FileTest.exists?(localfile), "Local file did not get created") + assert(FileTest.exists?(purgee), "Purge target got prematurely purged") + + assert_nothing_raised { destobj[:purge] = true } + config.apply + + assert(FileTest.exists?(localfile), "Local file got purged") + assert(FileTest.exists?(dsourcefile), "Source file got purged") + assert(! FileTest.exists?(purgee), "File did not get purged") + end + + # Testing #274. Make sure target can be used without 'ensure'. + def test_target_without_ensure + source = tempfile() + dest = tempfile() + File.open(source, "w") { |f| f.puts "funtest" } + + obj = nil + assert_nothing_raised { + obj = Puppet::Type.newfile(:path => dest, :target => source) + } + + assert_apply(obj) + end + + def test_autorequire_owner_and_group + file = tempfile() + comp = nil + user = nil + group =nil + home = nil + ogroup = nil + assert_nothing_raised { + user = Puppet.type(:user).create( + :name => "pptestu", + :home => file, + :gid => "pptestg" + ) + home = Puppet.type(:file).create( + :path => file, + :owner => "pptestu", + :group => "pptestg", + :ensure => "directory" + ) + group = Puppet.type(:group).create( + :name => "pptestg" + ) + comp = mk_catalog(user, group, home) + } + + # Now make sure we get a relationship for each of these + rels = nil + assert_nothing_raised { rels = home.autorequire } + assert(rels.detect { |e| e.source == user }, "owner was not autorequired") + assert(rels.detect { |e| e.source == group }, "group was not autorequired") + end + + # Testing #309 -- //my/file => /my/file + def test_slash_deduplication + ["/my/////file/for//testing", "//my/file/for/testing///", + "/my/file/for/testing"].each do |path| + file = nil + assert_nothing_raised do + file = Puppet::Type.newfile(:path => path) + end + + assert_equal("/my/file/for/testing", file.title) + assert_equal(file, Puppet::Type.type(:file)["/my/file/for/testing"]) + Puppet::Type.type(:file).clear + end + end + + # Testing #304 + def test_links_to_directories + link = tempfile() + file = tempfile() + dir = tempfile() + Dir.mkdir(dir) + + bucket = Puppet::Type.newfilebucket :name => "main" + File.symlink(dir, link) + File.open(file, "w") { |f| f.puts "" } + assert_equal(dir, File.readlink(link)) + obj = Puppet::Type.newfile :path => link, :ensure => :link, :target => file, :recurse => false, :backup => "main" + + assert_apply(obj) + + assert_equal(file, File.readlink(link)) + end + + # Testing #303 + def test_nobackups_with_links + link = tempfile() + new = tempfile() + + File.open(link, "w") { |f| f.puts "old" } + File.open(new, "w") { |f| f.puts "new" } + obj = Puppet::Type.newfile :path => link, :ensure => :link, + :target => new, :recurse => true, :backup => false + + assert_nothing_raised do + obj.handlebackup + end + + bfile = [link, "puppet-bak"].join(".") + + assert(! FileTest.exists?(bfile), "Backed up when told not to") + + assert_apply(obj) + + assert(! FileTest.exists?(bfile), "Backed up when told not to") + end + + # Make sure we consistently handle backups for all cases. + def test_ensure_with_backups + # We've got three file types, so make sure we can replace any type + # with the other type and that backups are done correctly. + types = [:file, :directory, :link] + + dir = tempfile() + path = File.join(dir, "test") + linkdest = tempfile() + creators = { + :file => proc { File.open(path, "w") { |f| f.puts "initial" } }, + :directory => proc { Dir.mkdir(path) }, + :link => proc { File.symlink(linkdest, path) } + } + + bucket = Puppet::Type.newfilebucket :name => "main", :path => tempfile() + + obj = Puppet::Type.newfile :path => path, :force => true, + :links => :manage + + Puppet[:trace] = true + ["main", false].each do |backup| + obj[:backup] = backup + obj.finish + types.each do |should| + types.each do |is| + # It makes no sense to replace a directory with a directory + # next if should == :directory and is == :directory + + Dir.mkdir(dir) + + # Make the thing + creators[is].call + + obj[:ensure] = should + + if should == :link + obj[:target] = linkdest + else + if obj.property(:target) + obj.delete(:target) + end + end + + # First try just removing the initial data + assert_nothing_raised do + obj.remove_existing(should) + end + + unless is == should + # Make sure the original is gone + assert(! FileTest.exists?(obj[:path]), + "remove_existing did not work: " + + "did not remove %s with %s" % [is, should]) + end + FileUtils.rmtree(obj[:path]) + + # Now make it again + creators[is].call + + property = obj.property(:ensure) + + currentvalue = property.retrieve + unless property.insync?(currentvalue) + assert_nothing_raised do + property.sync + end + end + FileUtils.rmtree(dir) + end + end + end + end + + if Process.uid == 0 + # Testing #364. + def test_writing_in_directories_with_no_write_access + # Make a directory that our user does not have access to + dir = tempfile() + Dir.mkdir(dir) + + # Get a fake user + user = nonrootuser + # and group + group = nonrootgroup + + # First try putting a file in there + path = File.join(dir, "file") + file = Puppet::Type.newfile :path => path, :owner => user.name, :group => group.name, :content => "testing" + + # Make sure we can create it + assert_apply(file) + assert(FileTest.exists?(path), "File did not get created") + # And that it's owned correctly + assert_equal(user.uid, File.stat(path).uid, "File has the wrong owner") + assert_equal(group.gid, File.stat(path).gid, "File has the wrong group") + + assert_equal("testing", File.read(path), "file has the wrong content") + + # Now make a dir + subpath = File.join(dir, "subdir") + subdir = Puppet::Type.newfile :path => subpath, :owner => user.name, :group => group.name, :ensure => :directory + # Make sure we can create it + assert_apply(subdir) + assert(FileTest.directory?(subpath), "File did not get created") + # And that it's owned correctly + assert_equal(user.uid, File.stat(subpath).uid, "File has the wrong owner") + assert_equal(group.gid, File.stat(subpath).gid, "File has the wrong group") + + assert_equal("testing", File.read(path), "file has the wrong content") + end + end + + # #366 + def test_replace_aliases + file = Puppet::Type.newfile :path => tempfile() + file[:replace] = :yes + assert_equal(:true, file[:replace], ":replace did not alias :true to :yes") + file[:replace] = :no + assert_equal(:false, file[:replace], ":replace did not alias :false to :no") + end + + # #365 -- make sure generated files also use filebuckets. + def test_recursive_filebuckets + source = tempfile() + dest = tempfile() + s1 = File.join(source, "1") + sdir = File.join(source, "dir") + s2 = File.join(sdir, "2") + Dir.mkdir(source) + Dir.mkdir(sdir) + [s1, s2].each { |file| File.open(file, "w") { |f| f.puts "yay: %s" % File.basename(file) } } + + sums = {} + [s1, s2].each do |f| + sums[File.basename(f)] = Digest::MD5.hexdigest(File.read(f)) + end + + dfiles = [File.join(dest, "1"), File.join(dest, "dir", "2")] + + bpath = tempfile + bucket = Puppet::Type.type(:filebucket).create :name => "rtest", :path => bpath + dipper = bucket.bucket + dipper = Puppet::Network::Handler.filebucket.new( + :Path => bpath + ) + assert(dipper, "did not receive bucket client") + file = Puppet::Type.newfile :path => dest, :source => source, :recurse => true, :backup => "rtest" + + assert_apply(file) + dfiles.each do |f| + assert(FileTest.exists?(f), "destfile %s was not created" % f) + end + + # Now modify the source files to make sure things get backed up correctly + [s1, s2].each { |sf| File.open(sf, "w") { |f| + f.puts "boo: %s" % File.basename(sf) + } } + + assert_apply(file) + dfiles.each do |f| + assert_equal("boo: %s\n" % File.basename(f), File.read(f), + "file was not copied correctly") + end + + # Make sure we didn't just copy the files over to backup locations + dfiles.each do |f| + assert(! FileTest.exists?(f + "rtest"), + "file %s was copied for backup instead of bucketed" % File.basename(f)) + end + + # Now make sure we can get the source sums from the bucket + sums.each do |f, sum| + result = nil + assert_nothing_raised do + result = dipper.getfile(sum) + end + assert(result, "file %s was not backed to filebucket" % f) + assert_equal("yay: %s\n" % f, result, "file backup was not correct") + end + end + + def test_backup + path = tempfile() + file = Puppet::Type.newfile :path => path, :content => "yay" + + [false, :false, "false"].each do |val| + assert_nothing_raised do + file[:backup] = val + end + assert_equal(false, file[:backup], "%s did not translate" % val.inspect) + end + [true, :true, "true", ".puppet-bak"].each do |val| + assert_nothing_raised do + file[:backup] = val + end + assert_equal(".puppet-bak", file[:backup], "%s did not translate" % val.inspect) + end + + # Now try a non-bucket string + assert_nothing_raised do + file[:backup] = ".bak" + end + assert_equal(".bak", file[:backup], ".bak did not translate") + + # Now try a non-existent bucket + assert_nothing_raised do + file[:backup] = "main" + end + assert_equal("main", file[:backup], "bucket name was not retained") + assert_equal("main", file.bucket, "file's bucket was not set") + + # And then an existing bucket + obj = Puppet::Type.type(:filebucket).create :name => "testing" + bucket = obj.bucket + + assert_nothing_raised do + file[:backup] = "testing" + end + assert_equal("testing", file[:backup], "backup value was reset") + assert_equal(obj.bucket, file.bucket, "file's bucket was not set") + end + + def test_pathbuilder + dir = tempfile() + Dir.mkdir(dir) + file = File.join(dir, "file") + File.open(file, "w") { |f| f.puts "" } + obj = Puppet::Type.newfile :path => dir, :recurse => true, :mode => 0755 + mk_catalog obj + + assert_equal("/%s" % obj.ref, obj.path) + + list = obj.eval_generate + fileobj = obj.class[file] + assert(fileobj, "did not generate file object") + assert_equal("/%s" % fileobj.ref, fileobj.path, "did not generate correct subfile path") + end + + # Testing #403 + def test_removal_with_content_set + path = tempfile() + File.open(path, "w") { |f| f.puts "yay" } + file = Puppet::Type.newfile(:name => path, :ensure => :absent, :content => "foo") + + assert_apply(file) + assert(! FileTest.exists?(path), "File was not removed") + end + + # Testing #434 + def test_stripping_extra_slashes_during_lookup + file = Puppet::Type.newfile(:path => "/one/two") + %w{/one/two/ /one/two /one//two //one//two//}.each do |path| + assert(Puppet::Type.type(:file)[path], "could not look up file via path %s" % path) + end + end + + # Testing #438 + def test_creating_properties_conflict + file = tempfile() + first = tempfile() + second = tempfile() + params = [:content, :source, :target] + params.each do |param| + assert_nothing_raised("%s conflicted with ensure" % [param]) do + Puppet::Type.newfile(:path => file, param => first, :ensure => :file) + end + Puppet::Type.type(:file).clear + params.each do |other| + next if other == param + assert_raise(Puppet::Error, "%s and %s did not conflict" % [param, other]) do + Puppet::Type.newfile(:path => file, other => first, param => second) + end + end + end + end + + # Testing #508 + if Process.uid == 0 + def test_files_replace_with_right_attrs + source = tempfile() + File.open(source, "w") { |f| + f.puts "some text" + } + File.chmod(0755, source) + user = nonrootuser + group = nonrootgroup + path = tempfile() + good = {:uid => user.uid, :gid => group.gid, :mode => 0640} + + run = Proc.new do |obj, msg| + assert_apply(obj) + stat = File.stat(obj[:path]) + good.each do |should, sval| + if should == :mode + current = filemode(obj[:path]) + else + current = stat.send(should) + end + assert_equal(sval, current, + "Attr %s was not correct %s" % [should, msg]) + end + end + + file = Puppet::Type.newfile(:path => path, :owner => user.name, + :group => group.name, :mode => 0640, :backup => false) + {:source => source, :content => "some content"}.each do |attr, value| + file[attr] = value + # First create the file + run.call(file, "upon creation with %s" % attr) + + # Now change something so that we replace the file + case attr + when :source: + File.open(source, "w") { |f| f.puts "some different text" } + when :content: file[:content] = "something completely different" + else + raise "invalid attr %s" % attr + end + + # Run it again + run.call(file, "after modification with %s" % attr) + + # Now remove the file and the attr + file.delete(attr) + File.unlink(path) + end + end + end + + # #505 + def test_numeric_recurse + dir = tempfile() + subdir = File.join(dir, "subdir") + other = File.join(subdir, "deeper") + file = File.join(other, "file") + [dir, subdir, other].each { |d| Dir.mkdir(d) } + File.open(file, "w") { |f| f.puts "yay" } + File.chmod(0644, file) + obj = Puppet::Type.newfile(:path => dir, :mode => 0750, :recurse => "2") + config = mk_catalog(obj) + + children = nil + assert_nothing_raised("Failure when recursing") do + children = obj.eval_generate + end + assert(obj.class[subdir], "did not create subdir object") + children.each do |c| + assert_nothing_raised("Failure when recursing on %s" % c) do + c.catalog = config + others = c.eval_generate + end + end + oobj = obj.class[other] + assert(oobj, "did not create other object") + + assert_nothing_raised do + assert_nil(oobj.eval_generate, "recursed too far") + end + end + + # Make sure we default to the "puppet" filebucket, rather than a string + def test_backup_defaults_to_bucket + path = tempfile + file = Puppet::Type.newfile(:path => path, :content => 'some content') + file.finish + + assert_instance_of(Puppet::Network::Client::Dipper, file.bucket, + "did not default to a filebucket for backups") + end + + # #515 - make sure 'ensure' other than "link" is deleted during recursion + def test_ensure_deleted_during_recursion + dir = tempfile() + Dir.mkdir(dir) + file = File.join(dir, "file") + File.open(file, "w") { |f| f.puts "asdfasdf" } + + obj = Puppet::Type.newfile(:path => dir, :ensure => :directory, + :recurse => true) + + config = mk_catalog(obj) + children = nil + assert_nothing_raised do + children = obj.eval_generate + end + fobj = obj.class[file] + assert(fobj, "did not create file object") + assert(fobj.should(:ensure) != :directory, "ensure was passed to child") + end + + # #567 + def test_missing_files_are_in_sync + file = tempfile + obj = Puppet::Type.newfile(:path => file, :mode => 0755) + + changes = obj.evaluate + assert(changes.empty?, "Missing file with no ensure resulted in changes") + end + + def test_root_dir_is_named_correctly + obj = Puppet::Type.newfile(:path => '/', :mode => 0755) + assert_equal("/", obj.title, "/ directory was changed to empty string") + end + + # #1010 and #1037 -- write should fail if the written checksum does not + # match the file we thought we were writing. + def test_write_validates_checksum + file = tempfile + inst = Puppet::Type.newfile(:path => file, :content => "something") + + tmpfile = file + ".puppettmp" + + wh = mock 'writehandle', :print => nil + rh = mock 'readhandle' + rh.expects(:read).with(512).times(2).returns("other").then.returns(nil) + File.expects(:open).with { |*args| args[0] == tmpfile and args[1] != "r" }.yields(wh) + File.expects(:open).with { |*args| args[0] == tmpfile and args[1] == "r" }.yields(rh) + + File.stubs(:rename) + FileTest.stubs(:exist?).returns(true) + FileTest.stubs(:file?).returns(true) + + inst.expects(:fail) + inst.write("something", :whatever) + end +end diff --git a/test/ral/type/file/target.rb b/test/ral/type/file/target.rb new file mode 100755 index 000000000..035ea905b --- /dev/null +++ b/test/ral/type/file/target.rb @@ -0,0 +1,364 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../lib/puppettest' + +require 'puppettest' +require 'puppettest/support/utils' +require 'fileutils' + +class TestFileTarget < Test::Unit::TestCase + include PuppetTest::Support::Utils + include PuppetTest::FileTesting + + def setup + super + @file = Puppet::Type.type(:file) + end + + # Make sure we can create symlinks + def test_symlinks + path = tempfile() + link = tempfile() + + File.open(path, "w") { |f| f.puts "yay" } + + file = nil + assert_nothing_raised { + file = Puppet.type(:file).create( + :title => "somethingelse", + :ensure => path, + :path => link + ) + } + + assert_events([:link_created], file) + + assert(FileTest.symlink?(link), "Link was not created") + + assert_equal(path, File.readlink(link), "Link was created incorrectly") + + # Make sure running it again works + assert_events([], file) + assert_events([], file) + assert_events([], file) + end + + def test_linkrecurse + dest = tempfile() + link = @file.create :path => tempfile(), :recurse => true, :ensure => dest + mk_catalog link + + ret = nil + + # Start with nothing, just to make sure we get nothing back + assert_nothing_raised { ret = link.linkrecurse(true) } + assert_nil(ret, "got a return when the dest doesn't exist") + + # then with a directory with only one file + Dir.mkdir(dest) + one = File.join(dest, "one") + File.open(one, "w") { |f| f.puts "" } + link[:ensure] = dest + assert_nothing_raised { ret = link.linkrecurse(true) } + + assert_equal(:directory, link.should(:ensure), "ensure was not set to directory") + assert_equal([File.join(link.title, "one")], ret.collect { |f| f.title }, + "Did not get linked file") + oneobj = @file[File.join(link.title, "one")] + assert_equal(one, oneobj.should(:target), "target was not set correctly") + + oneobj.remove + File.unlink(one) + + # Then make sure we get multiple files + returns = [] + 5.times do |i| + path = File.join(dest, i.to_s) + returns << File.join(link.title, i.to_s) + File.open(path, "w") { |f| f.puts "" } + end + assert_nothing_raised { ret = link.linkrecurse(true) } + + assert_equal(returns.sort, ret.collect { |f| f.title }.sort, + "Did not get links back") + + returns.each do |path| + obj = @file[path] + assert(path, "did not get obj for %s" % path) + sdest = File.join(dest, File.basename(path)) + assert_equal(sdest, obj.should(:target), + "target was not set correctly for %s" % path) + end + end + + def test_simplerecursivelinking + source = tempfile() + path = tempfile() + subdir = File.join(source, "subdir") + file = File.join(subdir, "file") + + system("mkdir -p %s" % subdir) + system("touch %s" % file) + + link = nil + assert_nothing_raised { + link = Puppet.type(:file).create( + :ensure => source, + :path => path, + :recurse => true + ) + } + + assert_apply(link) + + sublink = File.join(path, "subdir") + linkpath = File.join(sublink, "file") + assert(File.directory?(path), "dest is not a dir") + assert(File.directory?(sublink), "subdest is not a dir") + assert(File.symlink?(linkpath), "path is not a link") + assert_equal(file, File.readlink(linkpath)) + + assert_nil(@file[sublink], "objects were not removed") + assert_equal([], link.evaluate, "Link is not in sync") + end + + def test_recursivelinking + source = tempfile() + dest = tempfile() + + files = [] + dirs = [] + + # Make a bunch of files and dirs + Dir.mkdir(source) + Dir.chdir(source) do + system("mkdir -p %s" % "some/path/of/dirs") + system("mkdir -p %s" % "other/path/of/dirs") + system("touch %s" % "file") + system("touch %s" % "other/file") + system("touch %s" % "some/path/of/file") + system("touch %s" % "some/path/of/dirs/file") + system("touch %s" % "other/path/of/file") + + files = %x{find . -type f}.chomp.split(/\n/) + dirs = %x{find . -type d}.chomp.split(/\n/).reject{|d| d =~ /^\.+$/ } + end + + link = nil + assert_nothing_raised { + link = Puppet.type(:file).create( + :ensure => source, + :path => dest, + :recurse => true + ) + } + + assert_apply(link) + + files.each do |f| + f.sub!(/^\.#{File::SEPARATOR}/, '') + path = File.join(dest, f) + assert(FileTest.exists?(path), "Link %s was not created" % path) + assert(FileTest.symlink?(path), "%s is not a link" % f) + target = File.readlink(path) + assert_equal(File.join(source, f), target) + end + + dirs.each do |d| + d.sub!(/^\.#{File::SEPARATOR}/, '') + path = File.join(dest, d) + assert(FileTest.exists?(path), "Dir %s was not created" % path) + assert(FileTest.directory?(path), "%s is not a directory" % d) + end + end + + def test_localrelativelinks + dir = tempfile() + Dir.mkdir(dir) + source = File.join(dir, "source") + File.open(source, "w") { |f| f.puts "yay" } + dest = File.join(dir, "link") + + link = nil + assert_nothing_raised { + link = Puppet.type(:file).create( + :path => dest, + :ensure => "source" + ) + } + + assert_events([:link_created], link) + assert(FileTest.symlink?(dest), "Did not create link") + assert_equal("source", File.readlink(dest)) + assert_equal("yay\n", File.read(dest)) + end + + def test_recursivelinkingmissingtarget + source = tempfile() + dest = tempfile() + + objects = [] + objects << Puppet.type(:exec).create( + :command => "mkdir %s; touch %s/file" % [source, source], + :title => "yay", + :path => ENV["PATH"] + ) + objects << Puppet.type(:file).create( + :ensure => source, + :path => dest, + :recurse => true, + :require => objects[0] + ) + + assert_apply(*objects) + + link = File.join(dest, "file") + assert(FileTest.symlink?(link), "Did not make link") + assert_equal(File.join(source, "file"), File.readlink(link)) + end + + def test_insync? + source = tempfile() + dest = tempfile() + + obj = @file.create(:path => source, :target => dest) + + prop = obj.send(:property, :target) + prop.send(:instance_variable_set, "@should", [:nochange]) + assert(prop.insync?(prop.retrieve), + "Property not in sync with should == :nochange") + + prop = obj.send(:property, :target) + prop.send(:instance_variable_set, "@should", [:notlink]) + assert(prop.insync?(prop.retrieve), + "Property not in sync with should == :nochange") + + # Lastly, make sure that we don't try to do anything when we're + # recursing, since 'ensure' does the work. + obj[:recurse] = true + prop.should = dest + assert(prop.insync?(prop.retrieve), + "Still out of sync during recursion") + end + + def test_replacedirwithlink + Puppet[:trace] = false + path = tempfile() + link = tempfile() + + File.open(path, "w") { |f| f.puts "yay" } + Dir.mkdir(link) + File.open(File.join(link, "yay"), "w") do |f| f.puts "boo" end + + file = nil + assert_nothing_raised { + file = Puppet.type(:file).create( + :ensure => path, + :path => link, + :backup => false + ) + } + + # First run through without :force + assert_events([], file) + + assert(FileTest.directory?(link), "Link replaced dir without force") + + assert_nothing_raised { file[:force] = true } + + assert_events([:link_created], file) + + assert(FileTest.symlink?(link), "Link was not created") + + assert_equal(path, File.readlink(link), "Link was created incorrectly") + end + + def test_replace_links_with_files + base = tempfile() + + Dir.mkdir(base) + + file = File.join(base, "file") + link = File.join(base, "link") + File.open(file, "w") { |f| f.puts "yayness" } + File.symlink(file, link) + + obj = Puppet::Type.type(:file).create( + :path => link, + :ensure => "file" + ) + + assert_apply(obj) + + assert_equal("yayness\n", File.read(file), + "Original file got changed") + assert_equal("file", File.lstat(link).ftype, "File is still a link") + end + + def test_no_erase_linkedto_files + base = tempfile() + + Dir.mkdir(base) + + dirs = {} + %w{other source target}.each do |d| + dirs[d] = File.join(base, d) + Dir.mkdir(dirs[d]) + end + + file = File.join(dirs["other"], "file") + sourcefile = File.join(dirs["source"], "sourcefile") + link = File.join(dirs["target"], "sourcefile") + + File.open(file, "w") { |f| f.puts "other" } + File.open(sourcefile, "w") { |f| f.puts "source" } + File.symlink(file, link) + + obj = Puppet::Type.type(:file).create( + :path => dirs["target"], + :ensure => :file, + :source => dirs["source"], + :recurse => true + ) + config = mk_catalog obj + config.apply + + newfile = File.join(dirs["target"], "sourcefile") + + assert(File.directory?(dirs["target"]), "Dir did not get created") + assert(File.file?(newfile), "File did not get copied") + + assert_equal(File.read(sourcefile), File.read(newfile), + "File did not get copied correctly.") + + assert_equal("other\n", File.read(file), + "Original file got changed") + assert_equal("file", File.lstat(link).ftype, "File is still a link") + end + + def test_replace_links + dest = tempfile() + otherdest = tempfile() + link = tempfile() + + File.open(dest, "w") { |f| f.puts "boo" } + File.open(otherdest, "w") { |f| f.puts "yay" } + + obj = Puppet::Type.type(:file).create( + :path => link, + :ensure => otherdest + ) + + + assert_apply(obj) + + assert_equal(otherdest, File.readlink(link), "Link did not get created") + + obj[:ensure] = dest + + assert_apply(obj) + + assert_equal(dest, File.readlink(link), "Link did not get changed") + end +end + diff --git a/test/ral/type/filebucket.rb b/test/ral/type/filebucket.rb new file mode 100755 index 000000000..f9706663b --- /dev/null +++ b/test/ral/type/filebucket.rb @@ -0,0 +1,157 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../lib/puppettest' + +require 'puppettest' +require 'puppettest/support/utils' +require 'fileutils' + +class TestFileBucket < Test::Unit::TestCase + include PuppetTest::Support::Utils + include PuppetTest::FileTesting + # hmmm + # this is complicated, because we store references to the created + # objects in a central store + def mkfile(hash) + file = nil + assert_nothing_raised { + file = Puppet.type(:file).create(hash) + } + return file + end + + def mkbucket(name,path) + bucket = nil + assert_nothing_raised { + bucket = Puppet.type(:filebucket).create( + :name => name, + :path => path + ) + } + + @@tmpfiles.push path + + return bucket + end + + def mktestfile + # because luke's home directory is on nfs, it can't be used for testing + # as root + tmpfile = tempfile() + File.open(tmpfile, "w") { |f| f.puts rand(100) } + @@tmpfiles.push tmpfile + mkfile(:name => tmpfile) + end + + def setup + super + begin + initstorage + rescue + system("rm -rf %s" % Puppet[:statefile]) + end + end + + def initstorage + Puppet::Util::Storage.init + Puppet::Util::Storage.load + end + + def clearstorage + Puppet::Util::Storage.store + Puppet::Util::Storage.clear + end + + def test_simplebucket + name = "yayness" + bucketpath = tempfile() + mkbucket(name, bucketpath) + + bucket = nil + assert_nothing_raised { + bucket = Puppet.type(:filebucket).bucket(name) + } + + assert_instance_of(Puppet::Network::Client.dipper, bucket) + + md5 = nil + newpath = tempfile() + @@tmpfiles << newpath + system("cp /etc/passwd %s" % newpath) + assert_nothing_raised { + md5 = bucket.backup(newpath) + } + + assert(md5) + + dir, file, pathfile = Puppet::Network::Handler.filebucket.paths(bucketpath, md5) + + assert(FileTest.directory?(dir), + "MD5 directory does not exist") + + newmd5 = nil + + # Just in case the file isn't writable + File.chmod(0644, newpath) + File.open(newpath, "w") { |f| f.puts ";lkjasdf;lkjasdflkjwerlkj134lkj" } + + assert_nothing_raised { + newmd5 = bucket.backup(newpath) + } + + assert(md5 != newmd5) + + assert_nothing_raised { + bucket.restore(newpath, md5) + } + + File.open(newpath) { |f| newmd5 = Digest::MD5.hexdigest(f.read) } + + assert_equal(md5, newmd5) + end + + def test_fileswithbuckets + name = "yayness" + mkbucket(name, tempfile()) + + bucket = nil + assert_nothing_raised { + bucket = Puppet.type(:filebucket).bucket(name) + } + + file = mktestfile() + assert_nothing_raised { + file[:backup] = name + } + + opath = tempfile() + @@tmpfiles << opath + File.open(opath, "w") { |f| f.puts "yaytest" } + + origmd5 = File.open(file.name) { |f| newmd5 = Digest::MD5.hexdigest(f.read) } + + file[:source] = opath + #assert_nothing_raised { + # file[:backup] = true + #} + + assert_apply(file) + + # so, we've now replaced the file with the opath file + assert_equal( + File.open(opath) { |f| newmd5 = Digest::MD5.hexdigest(f.read) }, + File.open(file.name) { |f| newmd5 = Digest::MD5.hexdigest(f.read) } + ) + + #File.chmod(0644, file.name) + assert_nothing_raised { + bucket.restore(file.name, origmd5) + } + + assert_equal( + origmd5, + File.open(file.name) { |f| newmd5 = Digest::MD5.hexdigest(f.read) } + ) + end +end + diff --git a/test/ral/type/fileignoresource.rb b/test/ral/type/fileignoresource.rb new file mode 100755 index 000000000..ff867c879 --- /dev/null +++ b/test/ral/type/fileignoresource.rb @@ -0,0 +1,245 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../lib/puppettest' + +require 'puppettest' +require 'puppettest/support/utils' +require 'cgi' +require 'fileutils' + +class TestFileIgnoreSources < Test::Unit::TestCase + include PuppetTest::Support::Utils + include PuppetTest::FileTesting + + def setup + super + begin + initstorage + rescue + system("rm -rf %s" % Puppet[:statefile]) + end + end + +#This is not needed unless using md5 (correct me if I'm wrong) + def initstorage + Puppet::Util::Storage.init + Puppet::Util::Storage.load + end + + def clearstorage + Puppet::Util::Storage.store + Puppet::Util::Storage.clear + end + + def test_ignore_simple_source + + #Temp directory to run tests in + path = tempfile() + @@tmpfiles.push path + + #source directory + sourcedir = "sourcedir" + sourcefile1 = "sourcefile1" + sourcefile2 = "sourcefile2" + + frompath = File.join(path,sourcedir) + FileUtils.mkdir_p frompath + + topath = File.join(path,"destdir") + FileUtils.mkdir topath + + #initialize variables before block + tofile = nil + trans = nil + + #create source files + + File.open(File.join(frompath,sourcefile1), + File::WRONLY|File::CREAT|File::APPEND) { |of| + of.puts "yayness" + } + + File.open(File.join(frompath,sourcefile2), + File::WRONLY|File::CREAT|File::APPEND) { |of| + of.puts "even yayer" + } + + + #makes Puppet file Object + assert_nothing_raised { + tofile = Puppet.type(:file).create( + :name => topath, + :source => frompath, + :recurse => true, + :ignore => "sourcefile2" + ) + } + + config = mk_catalog(tofile) + config.apply + + + #topath should exist as a directory with sourcedir as a directory + + #This file should exist + assert(FileTest.exists?(File.join(topath,sourcefile1))) + + #This file should not + assert(!(FileTest.exists?(File.join(topath,sourcefile2)))) + + Puppet::Type.allclear + end + + def test_ignore_with_wildcard + #Temp directory to run tests in + path = tempfile() + @@tmpfiles.push path + + #source directory + sourcedir = "sourcedir" + subdir = "subdir" + subdir2 = "subdir2" + sourcefile1 = "sourcefile1" + sourcefile2 = "sourcefile2" + + frompath = File.join(path,sourcedir) + FileUtils.mkdir_p frompath + + FileUtils.mkdir_p(File.join(frompath, subdir)) + FileUtils.mkdir_p(File.join(frompath, subdir2)) + dir = Dir.glob(File.join(path,"**/*")) + + topath = File.join(path,"destdir") + FileUtils.mkdir topath + + #initialize variables before block + tofile = nil + trans = nil + + #create source files + + dir.each { |dir| + File.open(File.join(dir,sourcefile1), + File::WRONLY|File::CREAT|File::APPEND) { |of| + of.puts "yayness" + } + + File.open(File.join(dir,sourcefile2), + File::WRONLY|File::CREAT|File::APPEND) { |of| + of.puts "even yayer" + } + + } + + #makes Puppet file Object + assert_nothing_raised { + tofile = Puppet.type(:file).create( + :name => topath, + :source => frompath, + :recurse => true, + :ignore => "*2" + ) + } + + config = mk_catalog(tofile) + config.apply + + #topath should exist as a directory with sourcedir as a directory + + #This file should exist + assert(FileTest.exists?(File.join(topath,sourcefile1))) + assert(FileTest.exists?(File.join(topath,subdir))) + assert(FileTest.exists?(File.join(File.join(topath,subdir),sourcefile1))) + + #This file should not + assert(!(FileTest.exists?(File.join(topath,sourcefile2)))) + assert(!(FileTest.exists?(File.join(topath,subdir2)))) + assert(!(FileTest.exists?(File.join(File.join(topath,subdir),sourcefile2)))) + Puppet::Type.allclear + + end + + def test_ignore_array + #Temp directory to run tests in + path = tempfile() + @@tmpfiles.push path + + #source directory + sourcedir = "sourcedir" + subdir = "subdir" + subdir2 = "subdir2" + subdir3 = "anotherdir" + sourcefile1 = "sourcefile1" + sourcefile2 = "sourcefile2" + + frompath = File.join(path,sourcedir) + FileUtils.mkdir_p frompath + + FileUtils.mkdir_p(File.join(frompath, subdir)) + FileUtils.mkdir_p(File.join(frompath, subdir2)) + FileUtils.mkdir_p(File.join(frompath, subdir3)) + sourcedir = Dir.glob(File.join(path,"**/*")) + + topath = File.join(path,"destdir") + FileUtils.mkdir topath + + #initialize variables before block + tofile = nil + trans = nil + + #create source files + + + + sourcedir.each { |dir| + File.open(File.join(dir,sourcefile1), + File::WRONLY|File::CREAT|File::APPEND) { |of| + of.puts "yayness" + } + + File.open(File.join(dir,sourcefile2), + File::WRONLY|File::CREAT|File::APPEND) { |of| + of.puts "even yayer" + } + + } + + + #makes Puppet file Object + assert_nothing_raised { + tofile = Puppet.type(:file).create( + :name => topath, + :source => frompath, + :recurse => true, + :ignore => ["*2", "an*"] + # :ignore => ["*2", "an*", "nomatch"] + ) + } + + config = mk_catalog(tofile) + config.apply + + #topath should exist as a directory with sourcedir as a directory + + # This file should exist + # proper files in destination + assert(FileTest.exists?(File.join(topath,sourcefile1)), "file1 not in destdir") + assert(FileTest.exists?(File.join(topath,subdir)), "subdir1 not in destdir") + assert(FileTest.exists?(File.join(File.join(topath,subdir),sourcefile1)), "file1 not in subdir") + # proper files in source + assert(FileTest.exists?(File.join(frompath,subdir)), "subdir not in source") + assert(FileTest.exists?(File.join(frompath,subdir2)), "subdir2 not in source") + assert(FileTest.exists?(File.join(frompath,subdir3)), "subdir3 not in source") + + # This file should not + assert(!(FileTest.exists?(File.join(topath,sourcefile2))), "file2 in dest") + assert(!(FileTest.exists?(File.join(topath,subdir2))), "subdir2 in dest") + assert(!(FileTest.exists?(File.join(topath,subdir3))), "anotherdir in dest") + assert(!(FileTest.exists?(File.join(File.join(topath,subdir),sourcefile2))), "file2 in dest/sub") + + + Puppet::Type.allclear + + end + +end diff --git a/test/ral/type/filesources.rb b/test/ral/type/filesources.rb new file mode 100755 index 000000000..a7bb6fefa --- /dev/null +++ b/test/ral/type/filesources.rb @@ -0,0 +1,997 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../lib/puppettest' + +require 'puppettest' +require 'puppettest/support/utils' +require 'cgi' +require 'fileutils' +require 'mocha' + +class TestFileSources < Test::Unit::TestCase + include PuppetTest::Support::Utils + include PuppetTest::FileTesting + def setup + super + if defined? @port + @port += 1 + else + @port = 12345 + end + @file = Puppet::Type.type(:file) + Puppet[:filetimeout] = -1 + Puppet::Util::SUIDManager.stubs(:asuser).yields + end + + def teardown + super + Puppet::Network::HttpPool.clear_http_instances + end + + def use_storage + begin + initstorage + rescue + system("rm -rf %s" % Puppet[:statefile]) + end + end + + def initstorage + Puppet::Util::Storage.init + Puppet::Util::Storage.load + end + + # Make a simple recursive tree. + def mk_sourcetree + source = tempfile() + sourcefile = File.join(source, "file") + Dir.mkdir source + File.open(sourcefile, "w") { |f| f.puts "yay" } + + dest = tempfile() + destfile = File.join(dest, "file") + return source, dest, sourcefile, destfile + end + + def test_newchild + path = tempfile() + @@tmpfiles.push path + + FileUtils.mkdir_p path + File.open(File.join(path,"childtest"), "w") { |of| + of.puts "yayness" + } + file = nil + comp = nil + trans = nil + assert_nothing_raised { + file = Puppet.type(:file).create( + :name => path + ) + } + config = mk_catalog(file) + child = nil + assert_nothing_raised { + child = file.newchild("childtest", true) + } + assert(child) + assert_raise(Puppet::DevError) { + file.newchild(File.join(path,"childtest"), true) + } + end + + def test_describe + source = tempfile() + dest = tempfile() + + file = Puppet::Type.newfile :path => dest, :source => source, :title => "copier" + + property = file.property(:source) + + # First try describing with a normal source + result = nil + assert_nothing_raised do + result = property.describe(source) + end + assert_nil(result, "Got a result back when source is missing") + + # Now make a remote directory + Dir.mkdir(source) + assert_nothing_raised do + result = property.describe(source) + end + assert_equal("directory", result[:type]) + + # And as a file + Dir.rmdir(source) + File.open(source, "w") { |f| f.puts "yay" } + assert_nothing_raised do + result = property.describe(source) + end + assert_equal("file", result[:type]) + assert(result[:checksum], "did not get value for checksum") + if Puppet::Util::SUIDManager.uid == 0 + assert(result.has_key?(:owner), "Lost owner in describe") + else + assert(! result.has_key?(:owner), + "Kept owner in describe even tho not root") + end + + # Now let's do the various link things + File.unlink(source) + target = tempfile() + File.open(target, "w") { |f| f.puts "yay" } + File.symlink(target, source) + + file[:links] = :manage + assert_equal("link", property.describe(source)[:type]) + + # And then make sure links get followed + file[:links] = :follow + assert_equal("file", property.describe(source)[:type]) + end + + def test_source_retrieve + source = tempfile() + dest = tempfile() + + file = Puppet::Type.newfile :path => dest, :source => source, + :title => "copier" + + assert(file.property(:checksum), "source property did not create checksum property") + property = file.property(:source) + assert(property, "did not get source property") + + # Make sure the munge didn't actually change the source + assert_equal([source], property.should, "munging changed the source") + + # First try it with a missing source + currentvalue = nil + assert_nothing_raised do + currentvalue = property.retrieve + end + + # And make sure the property considers itself in sync, since there's nothing + # to do + assert(property.insync?(currentvalue), "source thinks there's work to do with no file or dest") + + # Now make the dest a directory, and make sure the object sets :ensure + # up to create a directory + Dir.mkdir(source) + assert_nothing_raised do + currentvalue = property.retrieve + end + assert_equal(:directory, file.should(:ensure), + "Did not set to create directory") + + # And make sure the source property won't try to do anything with a + # remote dir + assert(property.insync?(currentvalue), "Source was out of sync even tho remote is dir") + + # Now remove the source, and make sure :ensure was not modified + Dir.rmdir(source) + assert_nothing_raised do + property.retrieve + end + assert_equal(:directory, file.should(:ensure), + "Did not keep :ensure setting") + + # Now have a remote file and make sure things work correctly + File.open(source, "w") { |f| f.puts "yay" } + File.chmod(0755, source) + + assert_nothing_raised do + property.retrieve + end + assert_equal(:file, file.should(:ensure), + "Did not make correct :ensure setting") + assert_equal(0755, file.should(:mode), + "Mode was not copied over") + + # Now let's make sure that we get the first found source + fake = tempfile() + property.should = [fake, source] + assert_nothing_raised do + property.retrieve + end + assert_equal(Digest::MD5.hexdigest(File.read(source)), property.checksum.sub(/^\{\w+\}/, ''), + "Did not catch later source") + end + + def test_insync + source = tempfile() + dest = tempfile() + + file = Puppet::Type.newfile :path => dest, :source => source, + :title => "copier" + + property = file.property(:source) + assert(property, "did not get source property") + + # Try it with no source at all + currentvalues = file.retrieve + assert(property.insync?(currentvalues[property]), "source property not in sync with missing source") + + # with a directory + Dir.mkdir(source) + currentvalues = file.retrieve + assert(property.insync?(currentvalues[property]), "source property not in sync with directory as source") + Dir.rmdir(source) + + # with a file + File.open(source, "w") { |f| f.puts "yay" } + currentvalues = file.retrieve + assert(!property.insync?(currentvalues[property]), "source property was in sync when file was missing") + + # With a different file + File.open(dest, "w") { |f| f.puts "foo" } + currentvalues = file.retrieve + assert(!property.insync?(currentvalues[property]), "source property was in sync with different file") + + # with matching files + File.open(dest, "w") { |f| f.puts "yay" } + currentvalues = file.retrieve + assert(property.insync?(currentvalues[property]), "source property was not in sync with matching file") + end + + def test_source_sync + source = tempfile() + dest = tempfile() + + file = Puppet::Type.newfile :path => dest, :source => source, + :title => "copier" + property = file.property(:source) + + File.open(source, "w") { |f| f.puts "yay" } + + currentvalues = file.retrieve + assert(! property.insync?(currentvalues[property]), "source thinks it's in sync") + + event = nil + assert_nothing_raised do + event = property.sync + end + assert_equal(:file_created, event) + assert_equal(File.read(source), File.read(dest), + "File was not copied correctly") + + # Now write something different + File.open(source, "w") { |f| f.puts "rah" } + currentvalues = file.retrieve + assert(! property.insync?(currentvalues[property]), "source should be out of sync") + assert_nothing_raised do + event = property.sync + end + assert_equal(:file_changed, event) + assert_equal(File.read(source), File.read(dest), + "File was not copied correctly") + end + + # XXX This test doesn't cover everything. Specifically, + # it doesn't handle 'ignore' and 'links'. + def test_sourcerecurse + source, dest, sourcefile, destfile = mk_sourcetree + + # The sourcerecurse method will only ever get called when we're + # recursing, so we go ahead and set it. + obj = Puppet::Type.newfile :source => source, :path => dest, :recurse => true + config = mk_catalog(obj) + + result = nil + sourced = nil + assert_nothing_raised do + result, sourced = obj.sourcerecurse(true) + end + + assert_equal([destfile], sourced, "Did not get correct list of sourced objects") + dfileobj = @file[destfile] + assert(dfileobj, "Did not create destfile object") + assert_equal([dfileobj], result) + + # Clean this up so it can be recreated + config.remove_resource(dfileobj) + + # Make sure we correctly iterate over the sources + nosource = tempfile() + obj[:source] = [nosource, source] + + result = nil + assert_nothing_raised do + result, sourced = obj.sourcerecurse(true) + end + assert_equal([destfile], sourced, "Did not get correct list of sourced objects") + dfileobj = @file[destfile] + assert(dfileobj, "Did not create destfile object with a missing source") + assert_equal([dfileobj], result) + dfileobj.remove + + # Lastly, make sure we return an empty array when no sources are there + obj[:source] = [nosource, tempfile()] + + assert_nothing_raised do + result, sourced = obj.sourcerecurse(true) + end + assert_equal([], sourced, "Did not get correct list of sourced objects") + assert_equal([], result, "Sourcerecurse failed when all sources are missing") + end + + def test_simplelocalsource + path = tempfile() + FileUtils.mkdir_p path + frompath = File.join(path,"source") + topath = File.join(path,"dest") + fromfile = nil + tofile = nil + trans = nil + + File.open(frompath, File::WRONLY|File::CREAT|File::APPEND) { |of| + of.puts "yayness" + } + assert_nothing_raised { + tofile = Puppet.type(:file).create( + :name => topath, + :source => frompath + ) + } + + assert_apply(tofile) + + assert(FileTest.exists?(topath), "File #{topath} is missing") + from = File.open(frompath) { |o| o.read } + to = File.open(topath) { |o| o.read } + assert_equal(from,to) + end + + # Make sure a simple recursive copy works + def test_simple_recursive_source + source, dest, sourcefile, destfile = mk_sourcetree + + file = Puppet::Type.newfile :path => dest, :source => source, :recurse => true + + assert_events([:directory_created, :file_created], file) + + assert(FileTest.directory?(dest), "Dest dir was not created") + assert(FileTest.file?(destfile), "dest file was not created") + assert_equal("yay\n", File.read(destfile), "dest file was not copied correctly") + end + + def recursive_source_test(fromdir, todir) + Puppet::Type.allclear + initstorage + tofile = nil + trans = nil + + assert_nothing_raised { + tofile = Puppet.type(:file).create( + :path => todir, + :recurse => true, + :backup => false, + :source => fromdir + ) + } + assert_apply(tofile) + + assert(FileTest.exists?(todir), "Created dir %s does not exist" % todir) + Puppet::Type.allclear + end + + def run_complex_sources(networked = false) + path = tempfile() + + # first create the source directory + FileUtils.mkdir_p path + + # okay, let's create a directory structure + fromdir = File.join(path,"fromdir") + Dir.mkdir(fromdir) + FileUtils.cd(fromdir) { + File.open("one", "w") { |f| f.puts "onefile"} + File.open("two", "w") { |f| f.puts "twofile"} + } + + todir = File.join(path, "todir") + source = fromdir + if networked + source = "puppet://localhost/%s%s" % [networked, fromdir] + end + recursive_source_test(source, todir) + + return [fromdir,todir, File.join(todir, "one"), File.join(todir, "two")] + end + + def test_complex_sources_twice + fromdir, todir, one, two = run_complex_sources + assert_trees_equal(fromdir,todir) + recursive_source_test(fromdir, todir) + assert_trees_equal(fromdir,todir) + # Now remove the whole tree and try it again. + [one, two].each do |f| File.unlink(f) end + Dir.rmdir(todir) + recursive_source_test(fromdir, todir) + assert_trees_equal(fromdir,todir) + end + + def test_sources_with_deleted_destfiles + fromdir, todir, one, two = run_complex_sources + assert(FileTest.exists?(todir)) + + # We shouldn't have a 'two' file object in memory + assert_nil(@file[two], "object for 'two' is still in memory") + + # then delete a file + File.unlink(two) + + # and run + recursive_source_test(fromdir, todir) + + assert(FileTest.exists?(two), "Deleted file was not recopied") + + # and make sure they're still equal + assert_trees_equal(fromdir,todir) + end + + def test_sources_with_readonly_destfiles + fromdir, todir, one, two = run_complex_sources + assert(FileTest.exists?(todir)) + File.chmod(0600, one) + recursive_source_test(fromdir, todir) + + # and make sure they're still equal + assert_trees_equal(fromdir,todir) + + # Now try it with the directory being read-only + File.chmod(0111, todir) + recursive_source_test(fromdir, todir) + + # and make sure they're still equal + assert_trees_equal(fromdir,todir) + end + + def test_sources_with_modified_dest_files + fromdir, todir, one, two = run_complex_sources + + assert(FileTest.exists?(todir)) + + # Modify a dest file + File.open(two, "w") { |f| f.puts "something else" } + + recursive_source_test(fromdir, todir) + + # and make sure they're still equal + assert_trees_equal(fromdir,todir) + end + + def test_sources_with_added_destfiles + fromdir, todir = run_complex_sources + assert(FileTest.exists?(todir)) + # and finally, add some new files + add_random_files(todir) + + recursive_source_test(fromdir, todir) + + fromtree = file_list(fromdir) + totree = file_list(todir) + + assert(fromtree != totree, "Trees are incorrectly equal") + + # then remove our new files + FileUtils.cd(todir) { + %x{find . 2>/dev/null}.chomp.split(/\n/).each { |file| + if file =~ /file[0-9]+/ + File.unlink(file) + end + } + } + + # and make sure they're still equal + assert_trees_equal(fromdir,todir) + end + + # Make sure added files get correctly caught during recursion + def test_RecursionWithAddedFiles + basedir = tempfile() + Dir.mkdir(basedir) + @@tmpfiles << basedir + file1 = File.join(basedir, "file1") + file2 = File.join(basedir, "file2") + subdir1 = File.join(basedir, "subdir1") + file3 = File.join(subdir1, "file") + File.open(file1, "w") { |f| f.puts "yay" } + rootobj = nil + assert_nothing_raised { + rootobj = Puppet.type(:file).create( + :name => basedir, + :recurse => true, + :check => %w{type owner}, + :mode => 0755 + ) + } + + assert_apply(rootobj) + assert_equal(0755, filemode(file1)) + + File.open(file2, "w") { |f| f.puts "rah" } + assert_apply(rootobj) + assert_equal(0755, filemode(file2)) + + Dir.mkdir(subdir1) + File.open(file3, "w") { |f| f.puts "foo" } + assert_apply(rootobj) + assert_equal(0755, filemode(file3)) + end + + def mkfileserverconf(mounts) + file = tempfile() + File.open(file, "w") { |f| + mounts.each { |path, name| + f.puts "[#{name}]\n\tpath #{path}\n\tallow *\n" + } + } + + @@tmpfiles << file + return file + end + + def test_NetworkSources + server = nil + mounts = { + "/" => "root" + } + + fileserverconf = mkfileserverconf(mounts) + + Puppet[:autosign] = true + + Puppet[:masterport] = 8762 + Puppet[:name] = "puppetmasterd" + Puppet[:certdnsnames] = "localhost" + + serverpid = nil + assert_nothing_raised() { + server = Puppet::Network::HTTPServer::WEBrick.new( + :Handlers => { + :CA => {}, # so that certs autogenerate + :FileServer => { + :Config => fileserverconf + } + } + ) + + } + serverpid = fork { + assert_nothing_raised() { + #trap(:INT) { server.shutdown; Kernel.exit! } + trap(:INT) { server.shutdown } + server.start + } + } + @@tmppids << serverpid + + sleep(1) + + fromdir, todir = run_complex_sources("root") + assert_trees_equal(fromdir,todir) + recursive_source_test(fromdir, todir) + assert_trees_equal(fromdir,todir) + + assert_nothing_raised { + system("kill -INT %s" % serverpid) + } + end + + def test_unmountedNetworkSources + server = nil + mounts = { + "/" => "root", + "/noexistokay" => "noexist" + } + + fileserverconf = mkfileserverconf(mounts) + + Puppet[:autosign] = true + Puppet[:masterport] = @port + Puppet[:certdnsnames] = "localhost" + + serverpid = nil + assert_nothing_raised("Could not start on port %s" % @port) { + server = Puppet::Network::HTTPServer::WEBrick.new( + :Port => @port, + :Handlers => { + :CA => {}, # so that certs autogenerate + :FileServer => { + :Config => fileserverconf + } + } + ) + + } + + serverpid = fork { + assert_nothing_raised() { + #trap(:INT) { server.shutdown; Kernel.exit! } + trap(:INT) { server.shutdown } + server.start + } + } + @@tmppids << serverpid + + sleep(1) + + name = File.join(tmpdir(), "nosourcefile") + file = Puppet.type(:file).create( + :source => "puppet://localhost/noexist/file", + :name => name + ) + + assert_nothing_raised { + file.retrieve + } + + comp = mk_catalog(file) + comp.apply + + assert(!FileTest.exists?(name), "File with no source exists anyway") + end + + def test_alwayschecksum + from = tempfile() + to = tempfile() + + File.open(from, "w") { |f| f.puts "yayness" } + File.open(to, "w") { |f| f.puts "yayness" } + + file = nil + + # Now the files should be exactly the same, so we should not see attempts + # at copying + assert_nothing_raised { + file = Puppet.type(:file).create( + :path => to, + :source => from + ) + } + + currentvalue = file.retrieve + + assert(currentvalue[file.property(:checksum)], + "File does not have a checksum property") + + assert_equal(0, file.evaluate.length, "File produced changes") + end + + def test_sourcepaths + files = [] + 3.times { + files << tempfile() + } + + to = tempfile() + + File.open(files[-1], "w") { |f| f.puts "yee-haw" } + + file = nil + assert_nothing_raised { + file = Puppet.type(:file).create( + :name => to, + :source => files + ) + } + + comp = mk_catalog(file) + assert_events([:file_created], comp) + + assert(File.exists?(to), "File does not exist") + + txt = nil + File.open(to) { |f| txt = f.read.chomp } + + assert_equal("yee-haw", txt, "Contents do not match") + end + + # Make sure that source-copying updates the checksum on the same run + def test_checksumchange + source = tempfile() + dest = tempfile() + File.open(dest, "w") { |f| f.puts "boo" } + File.open(source, "w") { |f| f.puts "yay" } + + file = nil + assert_nothing_raised { + file = Puppet.type(:file).create( + :name => dest, + :source => source + ) + } + + file.retrieve + + assert_events([:file_changed], file) + file.retrieve + assert_events([], file) + end + + # Make sure that source-copying updates the checksum on the same run + def test_sourcebeatsensure + source = tempfile() + dest = tempfile() + File.open(source, "w") { |f| f.puts "yay" } + + file = nil + assert_nothing_raised { + file = Puppet.type(:file).create( + :name => dest, + :ensure => "file", + :source => source + ) + } + + file.retrieve + + assert_events([:file_created], file) + file.retrieve + assert_events([], file) + assert_events([], file) + end + + def test_sourcewithlinks + source = tempfile() + link = tempfile() + dest = tempfile() + + File.open(source, "w") { |f| f.puts "yay" } + File.symlink(source, link) + + file = nil + assert_nothing_raised { + file = Puppet.type(:file).create( + :name => dest, + :source => link, + :links => :follow + ) + } + + assert_events([:file_created], file) + assert(FileTest.file?(dest), "Destination is not a file") + + # Now copy the links + file[:links] = :manage + assert_events([:link_created], file) + assert(FileTest.symlink?(dest), "Destination is not a link") + end + + def test_changes + source = tempfile() + dest = tempfile() + + File.open(source, "w") { |f| f.puts "yay" } + + obj = nil + assert_nothing_raised { + obj = Puppet.type(:file).create( + :name => dest, + :source => source + ) + } + + assert_events([:file_created], obj) + assert_equal(File.read(source), File.read(dest), "Files are not equal") + assert_events([], obj) + + File.open(source, "w") { |f| f.puts "boo" } + + assert_events([:file_changed], obj) + assert_equal(File.read(source), File.read(dest), "Files are not equal") + assert_events([], obj) + + File.open(dest, "w") { |f| f.puts "kaboom" } + + # There are two changes, because first the checksum is noticed, and + # then the source causes a change + assert_events([:file_changed, :file_changed], obj) + assert_equal(File.read(source), File.read(dest), "Files are not equal") + assert_events([], obj) + end + + def test_file_source_with_space + dir = tempfile() + source = File.join(dir, "file with spaces") + Dir.mkdir(dir) + File.open(source, "w") { |f| f.puts "yayness" } + + newdir = tempfile() + newpath = File.join(newdir, "file with spaces") + + file = Puppet::Type.newfile( + :path => newdir, + :source => dir, + :recurse => true + ) + + + assert_apply(file) + + assert(FileTest.exists?(newpath), "Did not create file") + assert_equal("yayness\n", File.read(newpath)) + end + + # Make sure files aren't replaced when replace is false, but otherwise + # are. + def test_replace + source = tempfile() + File.open(source, "w") { |f| f.puts "yayness" } + + dest = tempfile() + file = Puppet::Type.newfile( + :path => dest, + :source => source, + :recurse => true + ) + + + assert_apply(file) + + assert(FileTest.exists?(dest), "Did not create file") + assert_equal("yayness\n", File.read(dest)) + + # Now set :replace + assert_nothing_raised { + file[:replace] = false + } + + File.open(source, "w") { |f| f.puts "funtest" } + assert_apply(file) + + # Make sure it doesn't change. + assert_equal("yayness\n", File.read(dest), + "File got replaced when :replace was false") + + # Now set it to true and make sure it does change. + assert_nothing_raised { + file[:replace] = true + } + assert_apply(file) + + # Make sure it doesn't change. + assert_equal("funtest\n", File.read(dest), + "File was not replaced when :replace was true") + end + + # Testing #285. This just makes sure that URI parsing works correctly. + def test_fileswithpoundsigns + dir = tstdir() + subdir = File.join(dir, "#dir") + Dir.mkdir(subdir) + file = File.join(subdir, "file") + File.open(file, "w") { |f| f.puts "yayness" } + + dest = tempfile() + source = "file://localhost#{dir}" + obj = Puppet::Type.newfile( + :path => dest, + :source => source, + :recurse => true + ) + + newfile = File.join(dest, "#dir", "file") + + poundsource = "file://localhost#{subdir}" + + sourceobj = path = nil + assert_nothing_raised { + sourceobj, path = obj.uri2obj(poundsource) + } + + assert_equal("/localhost" + URI.escape(subdir), path) + + assert_apply(obj) + + assert(FileTest.exists?(newfile), "File did not get created") + assert_equal("yayness\n", File.read(newfile)) + end + + def test_sourceselect + dest = tempfile() + sources = [] + 2.times { |i| + i = i + 1 + source = tempfile() + sources << source + file = File.join(source, "file%s" % i) + Dir.mkdir(source) + File.open(file, "w") { |f| f.print "yay" } + } + file1 = File.join(dest, "file1") + file2 = File.join(dest, "file2") + file3 = File.join(dest, "file3") + + # Now make different files with the same name in each source dir + sources.each_with_index do |source, i| + File.open(File.join(source, "file3"), "w") { |f| + f.print i.to_s + } + end + + obj = Puppet::Type.newfile(:path => dest, :recurse => true, + :source => sources) + + assert_equal(:first, obj[:sourceselect], "sourceselect has the wrong default") + # First, make sure we default to just copying file1 + assert_apply(obj) + + assert(FileTest.exists?(file1), "File from source 1 was not copied") + assert(! FileTest.exists?(file2), "File from source 2 was copied") + assert(FileTest.exists?(file3), "File from source 1 was not copied") + assert_equal("0", File.read(file3), "file3 got wrong contents") + + # Now reset sourceselect + assert_nothing_raised do + obj[:sourceselect] = :all + end + File.unlink(file1) + File.unlink(file3) + Puppet.err :yay + assert_apply(obj) + + assert(FileTest.exists?(file1), "File from source 1 was not copied") + assert(FileTest.exists?(file2), "File from source 2 was copied") + assert(FileTest.exists?(file3), "File from source 1 was not copied") + assert_equal("0", File.read(file3), "file3 got wrong contents") + end + + def test_recursive_sourceselect + dest = tempfile() + source1 = tempfile() + source2 = tempfile() + files = [] + [source1, source2, File.join(source1, "subdir"), File.join(source2, "subdir")].each_with_index do |dir, i| + Dir.mkdir(dir) + # Make a single file in each directory + file = File.join(dir, "file%s" % i) + File.open(file, "w") { |f| f.puts "yay%s" % i} + + # Now make a second one in each directory + file = File.join(dir, "second-file%s" % i) + File.open(file, "w") { |f| f.puts "yaysecond-%s" % i} + files << file + end + + obj = Puppet::Type.newfile(:path => dest, :source => [source1, source2], :sourceselect => :all, :recurse => true) + + assert_apply(obj) + + ["file0", "file1", "second-file0", "second-file1", "subdir/file2", "subdir/second-file2", "subdir/file3", "subdir/second-file3"].each do |file| + path = File.join(dest, file) + assert(FileTest.exists?(path), "did not create %s" % file) + + assert_equal("yay%s\n" % File.basename(file).sub("file", ''), File.read(path), "file was not copied correctly") + end + end + + # #594 + def test_purging_missing_remote_files + source = tempfile() + dest = tempfile() + s1 = File.join(source, "file1") + s2 = File.join(source, "file2") + d1 = File.join(dest, "file1") + d2 = File.join(dest, "file2") + Dir.mkdir(source) + [s1, s2].each { |name| File.open(name, "w") { |file| file.puts "something" } } + + # We have to add a second parameter, because that's the only way to expose the "bug". + file = Puppet::Type.newfile(:path => dest, :source => source, :recurse => true, :purge => true, :mode => "755") + + assert_apply(file) + + assert(FileTest.exists?(d1), "File1 was not copied") + assert(FileTest.exists?(d2), "File2 was not copied") + + File.unlink(s2) + + assert_apply(file) + + assert(FileTest.exists?(d1), "File1 was not kept") + assert(! FileTest.exists?(d2), "File2 was not purged") + end +end + diff --git a/test/ral/type/group.rb b/test/ral/type/group.rb new file mode 100755 index 000000000..d28c8eea5 --- /dev/null +++ b/test/ral/type/group.rb @@ -0,0 +1,171 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../lib/puppettest' + +require 'puppettest' +require 'etc' + +class TestGroup < Test::Unit::TestCase + include PuppetTest + + p = Puppet::Type.type(:group).provide :fake, :parent => PuppetTest::FakeProvider do + @name = :fake + apimethods :ensure, :gid + + def create + @ensure = :present + end + + def delete + @ensure = :absent + end + + def exists? + if defined? @ensure and @ensure == :present + true + else + false + end + end + end + + FakeGroupProvider = p + + @@fakeproviders[:group] = p + + def setup + super + Puppet::Type.type(:group).defaultprovider = FakeGroupProvider + end + + def teardown + Puppet.type(:group).clear + Puppet::Type.type(:group).defaultprovider = nil + super + end + + def mkgroup(name, hash = {}) + group = nil + hash[:name] = name + assert_nothing_raised { + group = Puppet.type(:group).create(hash) + } + + return group + end + + def groupnames + %x{groups}.chomp.split(/ /) + end + + def groupids + Process.groups + end + + def attrtest_ensure(group) + group[:ensure] = :absent + + comp = mk_catalog("ensuretest", group) + assert_apply(comp) + assert_equal(:absent, group.provider.ensure, "Group is still present") + group[:ensure] = :present + assert_events([:group_created], comp) + assert_equal(:present, group.provider.ensure, "Group is absent") + group[:ensure] = :absent + trans = assert_events([:group_removed], comp) + assert_equal(:absent, group.provider.ensure, "Group is present") + + assert_rollback_events(trans, [:group_created], "group") + assert_equal(:present, group.provider.ensure, "Group is absent") + end + + # This is a bit odd, since we're not actually doing anything on the machine. + # Just make sure we can set the gid and that it will work correctly. + def attrtest_gid(group) + + # Check the validation. + assert_nothing_raised { + group[:gid] = "15" + } + + assert_equal(15, group.should(:gid), + "Did not convert gid to number") + + comp = mk_catalog(group) + trans = assert_events([:group_modified], comp, "group") + assert_equal(15, group.provider.gid, "GID was not changed") + + assert_nothing_raised { + group[:gid] = 16 + } + + assert_equal(16, group.should(:gid), + "Did not keep gid as number") + + # Now switch to 16 + trans = assert_events([:group_modified], comp, "group") + assert_equal(16, group.provider.gid, "GID was not changed") + + # And then rollback + assert_rollback_events(trans, [:group_modified], "group") + assert_equal(15, group.provider.gid, "GID was not changed") + end + + def test_owngroups + groupnames().each { |group| + gobj = nil + comp = nil + assert_nothing_raised { + gobj = Puppet.type(:group).create( + :name => group, + :check => [:gid] + ) + } + + # Set a fake gid + gobj.provider.gid = rand(100) + + current_values = nil + assert_nothing_raised { + current_values = gobj.retrieve + } + + assert(current_values[gobj.property(:gid)], + "Failed to retrieve gid") + } + end + + def test_mkgroup + gobj = nil + name = "pptestgr" + + assert_nothing_raised { + gobj = Puppet.type(:group).create( + :name => name, + :gid => 123 + ) + } + gobj.finish + + trans = assert_events([:group_created], gobj, "group") + + assert(gobj.provider.exists?, + "Did not create group") + + tests = Puppet.type(:group).validproperties + + gobj.retrieve + tests.each { |test| + if self.respond_to?("attrtest_%s" % test) + self.send("attrtest_%s" % test, gobj) + else + #$stderr.puts "Not testing attr %s of group" % test + end + } + + assert_rollback_events(trans, [:group_removed], "group") + + assert(! gobj.provider.exists?, + "Did not delete group") + end +end diff --git a/test/ral/type/host.rb b/test/ral/type/host.rb new file mode 100755 index 000000000..a5d645bd1 --- /dev/null +++ b/test/ral/type/host.rb @@ -0,0 +1,181 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../lib/puppettest' + +require 'puppettest' +require 'test/unit' +require 'facter' + +class TestHost < Test::Unit::TestCase + include PuppetTest + + def setup + super + @hosttype = Puppet::Type.type(:host) + + @provider = @hosttype.defaultprovider + + # Make sure they aren't using something funky like netinfo + unless @provider.name == :parsed + @hosttype.defaultprovider = @hosttype.provider(:parsed) + end + + cleanup do @hosttype.defaultprovider = nil end + + if @provider.respond_to?(:default_target=) + @default_file = @provider.default_target + cleanup do + @provider.default_target = @default_file + end + @target = tempfile() + @provider.default_target = @target + end + end + + def mkhost + if defined? @hcount + @hcount += 1 + else + @hcount = 1 + end + + @catalog ||= mk_catalog + + host = nil + assert_nothing_raised { + host = Puppet.type(:host).create( + :name => "fakehost%s" % @hcount, + :ip => "192.168.27.%s" % @hcount, + :alias => "alias%s" % @hcount, + :catalog => @catalog + ) + } + + return host + end + + def test_list + assert_nothing_raised do + @hosttype.defaultprovider.prefetch + end + + count = 0 + @hosttype.each do |h| + count += 1 + end + + assert_equal(0, count, "Found hosts in empty file somehow") + end + + # Darwin will actually write to netinfo here. + if Facter.value(:operatingsystem) != "Darwin" or Process.uid == 0 + def test_simplehost + host = nil + # We want to actually use the netinfo provider on darwin + if Facter.value(:operatingsystem) == "Darwin" + Puppet::Type.type(:host).defaultprovider = nil + end + + assert_nothing_raised { + host = Puppet.type(:host).create( + :name => "culain", + :ip => "192.168.0.3" + ) + } + + current_values = nil + assert_nothing_raised { current_values = host.retrieve } + assert_events([:host_created], host) + + assert_nothing_raised { current_values = host.retrieve } + + assert_equal(:present, current_values[host.property(:ensure)]) + + host[:ensure] = :absent + + assert_events([:host_removed], host) + + assert_nothing_raised { current_values = host.retrieve } + + assert_equal(:absent, current_values[host.property(:ensure)]) + end + + def test_moddinghost + # We want to actually use the netinfo provider on darwin + if Facter.value(:operatingsystem) == "Darwin" + Puppet::Type.type(:host).defaultprovider = nil + end + host = mkhost() + if Facter.value(:operatingsystem) == "Darwin" + assert_equal(:netinfo, host[:provider], "Got incorrect provider") + end + cleanup do + host[:ensure] = :absent + assert_apply(host) + end + + assert_events([:host_created], host) + + current_values = nil + assert_nothing_raised { + current_values = host.retrieve + } + + # This was a hard bug to track down. + assert_instance_of(String, current_values[host.property(:ip)]) + + host[:alias] = %w{madstop kirby yayness} + + assert_events([:host_changed], host) + + assert_nothing_raised { + current_values = host.retrieve + } + + assert_equal(%w{madstop kirby yayness}, + current_values[host.property(:alias)]) + + host[:ensure] = :absent + assert_events([:host_removed], host) + end + + def test_invalid_ipaddress + host = mkhost() + + assert_raise(Puppet::Error) { + host[:ip] = "abc.def.ghi.jkl" + } + end + + def test_invalid_hostname + host = mkhost() + + assert_raise(Puppet::Error) { + host[:name] = "!invalid.hostname.$$$" + } + end + + end + def test_aliasisproperty + assert_equal(:property, @hosttype.attrtype(:alias)) + end + + def test_multivalues + host = mkhost + assert_raise(Puppet::Error) { + host[:alias] = "puppetmasterd yayness" + } + end + + def test_puppetalias + host = mkhost() + + assert_nothing_raised { + host[:alias] = "testing" + } + + same = host.class["testing"] + assert(same, "Could not retrieve by alias") + end +end + diff --git a/test/ral/type/mailalias.rb b/test/ral/type/mailalias.rb new file mode 100755 index 000000000..ff1dd562a --- /dev/null +++ b/test/ral/type/mailalias.rb @@ -0,0 +1,49 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../lib/puppettest' + +require 'puppettest' +require 'mocha' + +class TestMailAlias < Test::Unit::TestCase + include PuppetTest + + def setup + super + @type = Puppet::Type.type(:mailalias) + + @provider = @type.defaultprovider + + # Make sure they aren't using something funky like netinfo + unless @provider.name == :aliases + @type.defaultprovider = @type.provider(:aliases) + end + + cleanup do @type.defaultprovider = nil end + + if @provider.respond_to?(:default_target=) + @default_file = @provider.default_target + cleanup do + @provider.default_target = @default_file + end + @target = tempfile() + @provider.default_target = @target + end + end + + # This isn't much of a test, but then, it's not much of a type. + def test_recipient_arrays + resource = @type.create(:name => "luke", :recipient => "yay", :target => tempfile) + resource.provider.expects(:recipient).returns([:absent]) + values = nil + assert_nothing_raised("Could not retrieve mailalias") do + values = resource.retrieve.inject({}) { |hash, a| hash[a[0].name] = a[1]; hash } + end + assert_equal([:absent], values[:recipient]) + resource.property(:recipient).expects(:set).with(%w{yay}) + assert_nothing_raised("Could not sync mailalias") do + resource.property(:recipient).sync + end + end +end + diff --git a/test/ral/type/parameter.rb b/test/ral/type/parameter.rb new file mode 100755 index 000000000..e1b8e00b3 --- /dev/null +++ b/test/ral/type/parameter.rb @@ -0,0 +1,174 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../lib/puppettest' + +require 'puppettest' + +class TestParameter < Test::Unit::TestCase + include PuppetTest + + def newparam(name = :fakeparam) + assert_nothing_raised { + param = Class.new(Puppet::Parameter) do + @name = :fakeparam + end + param.initvars + + return param + } + end + + def newinst(param) + assert_nothing_raised { + return param.new(:resource => "yay") + } + end + + # Test the basic newvalue stuff. + def test_newvalue + param = newparam() + + # Try it with both symbols and strings. + assert_nothing_raised { + param.newvalues(:one, "two") + } + + inst = newinst(param) + + assert_nothing_raised { + inst.value = "one" + } + + assert_equal(:one, inst.value) + + assert_nothing_raised { + inst.value = :two + } + assert_equal(:two, inst.value) + + assert_raise(ArgumentError) { + inst.value = :three + } + assert_equal(:two, inst.value) + end + + # Test using regexes. + def test_regexvalues + param = newparam + + assert_nothing_raised { + param.newvalues(/^\d+$/) + } + assert(param.match?("14")) + assert(param.match?(14)) + + inst = newinst(param) + + assert_nothing_raised { + inst.value = 14 + } + + assert_nothing_raised { + inst.value = "14" + } + + assert_raise(ArgumentError) { + inst.value = "a14" + } + end + + # Test using both. Equality should beat matching. + def test_regexesandnormals + param = newparam + + assert_nothing_raised { + param.newvalues(:one, /^\w+$/) + } + + inst = newinst(param) + + assert_nothing_raised { + inst.value = "one" + } + + assert_equal(:one, inst.value, "Value used regex instead of equality") + + assert_nothing_raised { + inst.value = "two" + } + assert_equal("two", inst.value, "Matched value didn't take") + end + + def test_shadowing + type = Puppet::Type.newtype(:faketype) { newparam(:name) {} } + + cleanup { Puppet::Type.rmtype(:faketype) } + + param = nil + assert_nothing_raised do + param = type.newproperty(:alias) + end + + assert(param, "did not create param") + + inst = type.create(:name => "test") + + config = mk_catalog + inst.catalog = config + + assert_nothing_raised("Could not create shadowed param") { + inst[:alias] = "foo" + } + + # Get the parameter hash from the instance so we can check the shadow + params = inst.instance_variable_get("@parameters") + obj = params[:alias] + assert(obj, "did not get alias parameter") + assert(obj.shadow, "shadow was not created for alias param") + + assert(obj.is_a?(Puppet::Property), + "alias instance is not a property") + assert_instance_of(param, obj, "alias is an instance of the wrong class") + + # Make sure the alias got created + assert(type["foo"], "Did not retrieve object by its alias") + + # Now try it during initialization + other = nil + assert_nothing_raised("Could not create instance with shadow") do + other = type.create(:name => "rah", :alias => "one", :catalog => config) + end + params = other.instance_variable_get("@parameters") + obj = params[:alias] + assert(obj, "did not get alias parameter") + assert(obj.shadow, "shadow was not created for alias param") + + assert_instance_of(param, obj, "alias is an instance of the wrong class") + assert(obj.is_a?(Puppet::Property), + "alias instance is not a property") + + # Now change the alias and make sure it works out well + assert_nothing_raised("Could not modify shadowed alias") do + other[:alias] = "two" + end + + obj = params[:alias] + assert(obj, "did not get alias parameter") + assert_instance_of(param, obj, "alias is now an instance of the wrong class") + assert(obj.is_a?(Puppet::Property), + "alias instance is now not a property") + end + + # Make sure properties can correctly require features and behave appropriately when + # those features are missing. + def test_requires_features + param = newparam(:feature_tests) + + assert_nothing_raised("could not add feature requirements to property") do + param.required_features = "testing" + end + + assert_equal([:testing], param.required_features, "required features value was not arrayfied and interned") + end +end + diff --git a/test/ral/type/port.rb b/test/ral/type/port.rb new file mode 100755 index 000000000..e28904d55 --- /dev/null +++ b/test/ral/type/port.rb @@ -0,0 +1,147 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../lib/puppettest' + +require 'puppettest' + +#require 'facter' +# +#class TestPort < Test::Unit::TestCase +# include PuppetTest +# +# def setup +# super +# @porttype = Puppet.type(:port) +# +# @provider = @porttype.defaultprovider +# +# # Make sure they aren't using something funky like netinfo +# unless @provider.name == :parsed +# @porttype.defaultprovider = @porttype.provider(:parsed) +# end +# +# cleanup do @porttype.defaultprovider = nil end +# +# if @provider.respond_to?(:default_target) +# oldpath = @provider.default_target +# cleanup do +# @provider.default_target = oldpath +# end +# @provider.default_target = tempfile() +# end +# end +# +# def mkport +# port = nil +# +# if defined? @pcount +# @pcount += 1 +# else +# @pcount = 1 +# end +# assert_nothing_raised { +# port = Puppet.type(:port).create( +# :name => "puppet%s" % @pcount, +# :number => "813%s" % @pcount, +# :protocols => "tcp", +# :description => "The port that Puppet runs on", +# :alias => "coolness%s" % @pcount +# ) +# } +# +# return port +# end +# +# def test_list +# assert_nothing_raised { +# Puppet.type(:port).list +# } +# +# count = 0 +# @porttype.each do |h| +# count += 1 +# end +# +# assert_equal(0, count, "Found hosts in empty file somehow") +# +# dns = @porttype["domain"] +# assert(dns, "Did not retrieve dns service") +# end +# +# def test_simpleport +# host = nil +# +# port = mkport +# +# assert_apply(port) +# assert_nothing_raised { +# port.retrieve +# } +# +# assert(port.provider.exists?, "Port did not get created") +# end +# +# def test_moddingport +# port = nil +# port = mkport +# +# assert_events([:port_created], port) +# +# port.retrieve +# +# port[:protocols] = %w{tcp udp} +# +# assert_events([:port_changed], port) +# end +# +# def test_multivalues +# port = mkport +# assert_raise(Puppet::Error) { +# port[:protocols] = "udp tcp" +# } +# assert_raise(Puppet::Error) { +# port[:alias] = "puppetmasterd yayness" +# } +# end +# +# def test_removal +# port = mkport() +# assert_nothing_raised { +# port[:ensure] = :present +# } +# assert_events([:port_created], port) +# assert_events([], port) +# +# assert(port.provider.exists?, "port was not created") +# assert_nothing_raised { +# port[:ensure] = :absent +# } +# +# assert_events([:port_removed], port) +# assert(! port.provider.exists?, "port was not removed") +# assert_events([], port) +# end +# +# def test_addingproperties +# port = mkport() +# assert_events([:port_created], port) +# +# port.delete(:alias) +# assert(! port.property(:alias)) +# assert_events([:port_changed], port) +# +# assert_nothing_raised { +# port.retrieve +# } +# +# assert_equal(:present, port.is(:ensure)) +# +# assert_equal(:absent, port.is(:alias)) +# +# port[:alias] = "yaytest" +# assert_events([:port_changed], port) +# port.retrieve +# assert(port.property(:alias).is == ["yaytest"]) +# end +#end + diff --git a/test/ral/type/property.rb b/test/ral/type/property.rb new file mode 100755 index 000000000..6a3370caa --- /dev/null +++ b/test/ral/type/property.rb @@ -0,0 +1,388 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../lib/puppettest' + +require 'puppettest' + +class TestProperty < Test::Unit::TestCase + include PuppetTest + + def newinst(property, resource = nil) + inst = nil + unless resource + resource = "fakeresource" + resource.meta_def(:pathbuilder) do [self.to_s] end + resource.meta_def(:provider) do nil end + resource.meta_def(:fakeproperty) do '' end + end + assert_nothing_raised { + newinst = property.new(:resource => resource) + def newinst.retrieve(); return @fakeprovidervalue; end; + return newinst + } + end + + def newproperty(name = :fakeproperty) + property = Class.new(Puppet::Property) do + @name = name + end + Object.const_set("FakeProperty", property) + property.initvars + cleanup do + Object.send(:remove_const, "FakeProperty") + end + + return property + end + + def newmodel(name) + # Create an object that responds to myproperty as an attr + provklass = Class.new { attr_accessor name + def pathbuilder + ["provklass"] + end + } + prov = provklass.new + + klass = Class.new { attr_accessor :provider, :path + def pathbuilder + ["instklass"] + end + } + klassinst = klass.new + klassinst.path = "instpath" + klassinst.provider = prov + + return prov, klassinst + end + + # Make sure we correctly look up names. + def test_value_name + property = newproperty() + + property.newvalue(:one) + property.newvalue(/\d+/) + + name = nil + ["one", :one].each do |value| + assert_nothing_raised do + name = property.value_name(value) + end + assert_equal(:one, name) + end + ["42"].each do |value| + assert_nothing_raised do + name = property.value_name(value) + end + assert_equal(/\d+/, name) + end + # these values should not have a name + ["two", :three, ''].each do |value| + assert_nothing_raised do + name = property.value_name(value) + end + assert_nil(name) + end + end + + # Test that we correctly look up options for values. + def test_value_option + property = newproperty() + + options = { + :one => {:event => :yay, :call => :before}, + /\d+/ => {:event => :fun, :call => :instead} + } + property.newvalue(:one, options[:one]) + property.newvalue(/\d+/, options[/\d+/]) + + options.each do |name, opts| + opts.each do |param, value| + assert_equal(value, property.value_option(name, param)) + end + end + end + + def test_newvalue + property = newproperty() + + # These are bogus because they don't define events. :/ + assert_nothing_raised { + property.newvalue(:one) do + @fakeprovidervalue = 1 + end + } + + assert_nothing_raised { + property.newvalue("two") do + @fakeprovidervalue = 2 + end + } + + # Make sure we default to using the block instead + assert_equal(:instead, property.value_option(:one, :call), + ":call was not set to :instead when a block was provided") + + inst = newinst(property) + + assert_nothing_raised { + inst.should = "one" + } + + assert_equal(:one, inst.should) + ret = nil + assert_nothing_raised { inst.set_one } + assert_equal(1, inst.retrieve) + + assert_nothing_raised { + inst.should = :two + } + + assert_equal(:two, inst.should) + assert_nothing_raised { inst.set_two } + assert_equal(2, inst.retrieve) + end + + def test_newpropertyvaluewithregexes + property = newproperty() + + assert_nothing_raised { + property.newvalue(/^\w+$/) do + return :regex_matched + end + } + + inst = newinst(property) + + assert_nothing_raised { + inst.should = "yayness" + } + + assert_equal("yayness", inst.should) + + assert_nothing_raised { + inst.sync + } + + assert_equal("yayness".upcase, inst.retrieve) + end + + def test_newvalue_event_option + property = newproperty() + + assert_nothing_raised do + property.newvalue(:myvalue, :event => :fake_valued) do + end + property.newvalue(:other, :event => "fake_other") do + end + end + inst = newinst(property) + + assert_nothing_raised { + inst.should = :myvalue + } + + ret = nil + assert_nothing_raised { + ret = inst.sync + } + + assert_equal(:fake_valued, ret, + "Event did not get returned correctly") + + assert_nothing_raised { + inst.should = :other + } + + assert_nothing_raised { + ret = inst.sync + } + + assert_equal(:fake_other, ret, + "Event did not get returned correctly") + end + + # We want to support values with no blocks, either regexes or strings. + # If there's no block provided, then we should call the provider mechanism + # like we would normally. + def test_newvalue_with_no_block + property = newproperty(:myproperty) + + assert_nothing_raised { + property.newvalue(:value, :event => :matched_value) + } + assert_nothing_raised { + property.newvalue(/^\d+$/, :event => :matched_number) + } + + assert_equal(:none, property.value_option(:value, :call), + ":call was not set to none when no block is provided") + + prov, klassinst = newmodel(:myproperty) + + inst = newinst(property, klassinst) + + # Now make sure we can set the values, they get validated as normal, + # and they set the values on the resource rather than trying to call + # a method + {:value => :matched_value, "27" => :matched_number}.each do |value, event| + assert_nothing_raised do + inst.should = value + end + ret = nil + assert_nothing_raised do + ret = inst.sync + end + assert_equal(event, ret, "Did not return correct event for %s" % value) + assert_equal(value, prov.myproperty, "%s was not set right" % value) + end + + # And make sure we still fail validations + assert_raise(ArgumentError) do + inst.should = "invalid" + end + end + + def test_tags + obj = "yay" + metaobj = class << obj; self; end + + metaobj.send(:attr_accessor, :tags) + + tags = [:some, :tags, :for, :testing] + obj.tags = tags + + propertyklass = newproperty + + inst = nil + assert_nothing_raised do + inst = propertyklass.new(:resource => obj) + end + + assert_nothing_raised do + assert_equal(tags + [inst.name], inst.tags) + end + end + + def test_failure + s = Struct.new(:line, :file, :path, :pathbuilder, :name) + p = s.new(1, "yay", "rah", "struct", "name") + + myprovider = Class.new(Puppet::Provider) + + def p.provider; nil; end; + myproperty = Class.new(Puppet::Property) do + @name = 'name' + end + myproperty.initvars + + myproperty.newvalue :mkfailure do + raise "It's all broken" + end + property = myproperty.new(:resource => p) + + assert_raise(Puppet::Error) do + property.set(:mkfailure) + end + end + + # Make sure 'set' behaves correctly WRT to call order. This tests that the + # :call value is handled correctly in all cases. + def test_set + property = newproperty(:myproperty) + + $setting = [] + + newval = proc do |name, call| + options = {} + if call + options[:call] = name + block = proc { $setting << name } + end + assert_nothing_raised("Could not create %s value" % name) { + if block + property.newvalue(name, options, &block) + else + property.newvalue(name, options) + end + } + end + + newval.call(:none, false) + + # Create a value with no block; it should default to :none + newval.call(:before, true) + + # One with a block but after + newval.call(:after, true) + + # One with an explicit instead + newval.call(:instead, true) + + # And one with an implicit instead + assert_nothing_raised do + property.newvalue(:implicit) do + $setting << :implicit + end + end + + # Now create a provider + prov, model = newmodel(:myproperty) + inst = newinst(property, model) + + # Mark when we're called + prov.meta_def(:myproperty=) do |value| $setting << :provider end + + # Now run through the list and make sure everything is correct + {:before => [:before, :provider], + :after => [:provider, :after], + :instead => [:instead], + :none => [:provider], + :implicit => [:implicit] + }.each do |name, result| + inst.set(name) + + assert_equal(result, $setting, "%s was not handled right" % name) + $setting.clear + end + end + + # Make sure we can specify that we want to use the whole array, rather + # than just individual values. + def test_array_handling + property = newproperty(:arraytests) + + prov, model = newmodel(:array_testing) + inst = newinst(property, model) + + # Make sure it defaults to first + assert_equal(:first, property.array_matching, "Property did not default to matching first value in an array") + assert(! inst.match_all?, "match_all? returned true when array_matching is :first") + + vals = %w{one two three} + inst.should = vals + + # Make sure we only get the first value back + assert_equal("one", inst.should, "Returned wrong value when array_matching == first") + + # And make sure any of these values is considered in sync + vals.each do |value| + assert(inst.insync?(value), "#{value} was not considered in sync when array_matching == first") + end + + # Now change it to all + property.array_matching = :all + assert_equal(:all, property.array_matching, "Property did not change value of array_matching") + assert(inst.match_all?, "match_all? returned false when array_matching is :all") + + # Make sure we only get the first value back + assert_equal(vals, inst.should, "Returned wrong value when array_matching == all") + + # And make sure any of these values is considered in sync + %w{one two three}.each do |value| + assert(! inst.insync?(value), "individual value #{value} was considered in sync when array_matching == all") + end + assert(inst.insync?(vals), "value array was not considered in sync when array_matching == all") + end +end + diff --git a/test/ral/type/resources.rb b/test/ral/type/resources.rb new file mode 100755 index 000000000..0663fe795 --- /dev/null +++ b/test/ral/type/resources.rb @@ -0,0 +1,208 @@ +#!/usr/bin/env ruby +# +# Created by Luke Kanies on 2006-12-12. +# Copyright (c) 2006. All rights reserved. + +require File.dirname(__FILE__) + '/../../lib/puppettest' + +require 'puppettest' + +class TestResources < Test::Unit::TestCase + include PuppetTest + + def add_purge_lister + # Now define the list method + class << @purgetype + def instances + $purgemembers.values + end + end + end + + def mk_purger(managed = false) + @purgenum ||= 0 + @purgenum += 1 + obj = @purgetype.create :name => "purger%s" % @purgenum + $purgemembers[obj[:name]] = obj + if managed + obj[:fake] = "testing" + end + obj + end + + def mkpurgertype + # Create a purgeable type + $purgemembers = {} + @purgetype = Puppet::Type.newtype(:purgetest) do + newparam(:name, :namevar => true) {} + newproperty(:ensure) do + newvalue(:absent) do + $purgemembers[@parent[:name]] = @parent + end + newvalue(:present) do + $purgemembers.delete(@parent[:name]) + end + end + newproperty(:fake) do + def sync + :faked + end + end + end + cleanup do + Puppet::Type.rmtype(:purgetest) + end + end + + def setup + super + @type = Puppet::Type.type(:resources) + end + + def test_initialize + assert(@type, "Could not retrieve resources type") + # Make sure we can't create them for types that don't exist + assert_raise(Puppet::Error) do + @type.create :name => "thereisnotypewiththisname" + end + + # Now make sure it works for a normal type + usertype = nil + assert_nothing_raised do + usertype = @type.create :name => "user" + end + assert(usertype, "did not create user resource type") + assert_equal(Puppet::Type.type(:user), usertype.resource_type, + "resource_type was not set correctly") + end + + def test_purge + # Create a purgeable type + mkpurgertype + + purger = nil + assert_nothing_raised do + purger = @type.create :name => "purgetest", :noop => true, :loglevel => :warning + end + assert(purger, "did not get purger manager") + add_purge_lister() + + assert_equal($purgemembers.values.sort, @purgetype.instances.sort) + + # and it should now succeed + assert_nothing_raised do + purger[:purge] = true + end + assert(purger.purge?, "purge boolean was not enabled") + + # Okay, now let's try doing some purging, yo + managed = [] + unmanned = [] + 3.times { managed << mk_purger(true) } # 3 managed + 3.times { unmanned << mk_purger(false) } # 3 unmanaged + + managed.each do |m| + assert(m.managed?, "managed resource was not considered managed") + end + unmanned.each do |u| + assert(! u.managed?, "unmanaged resource was considered managed") + end + + # First make sure we get nothing back when purge is false + genned = nil + purger[:purge] = false + assert_nothing_raised do + genned = purger.generate + end + assert_equal([], genned, "Purged even when purge is false") + + # Now make sure we can purge + purger[:purge] = true + assert_nothing_raised do + genned = purger.generate + end + assert(genned, "Did not get any generated resources") + + genned.each do |res| + assert(res.purging, "did not mark resource for purging") + end + assert(! genned.empty?, "generated resource list was empty") + + # Now make sure the generate method only finds the unmanaged resources + assert_equal(unmanned.collect { |r| r.title }.sort, genned.collect { |r| r.title }, + "Did not return correct purge list") + + # Now make sure our metaparams carried over + genned.each do |res| + [:noop, :loglevel].each do |param| + assert_equal(purger[param], res[param], "metaparam %s did not carry over" % param) + end + end + end + + # Part of #408. + def test_check + # First check a non-user + res = Puppet::Type.type(:resources).create :name => :package + assert_nil(res[:unless_system_user], "got bad default for package") + + + assert_nothing_raised { + assert(res.check("A String"), "String failed check") + assert(res.check(Puppet::Type.newfile(:path => tempfile())), "File failed check") + assert(res.check(Puppet::Type.type(:user).create(:name => "yayness")), "User failed check in package") + } + + # Now create a user manager + res = Puppet::Type.type(:resources).create :name => :user + + # Make sure the default is 500 + assert_equal(500, res[:unless_system_user], "got bad default") + + # Now make sure root fails the test + @user = Puppet::Type.type(:user) + assert_nothing_raised { + assert(! res.check(@user.create(:name => "root")), "root passed check") + assert(! res.check(@user.create(:name => "nobody")), "nobody passed check") + } + + # Now find a user between 0 and the limit + low = high = nil + Etc.passwd { |entry| + if ! low and (entry.uid > 10 and entry.uid < 500) + low = entry.name + else + # We'll reset the limit, since we can't really guarantee that + # there are any users with uid > 500 + if ! high and entry.uid > 100 and ! res.system_users.include?(entry.name) + high = entry.name + break + end + end + } + + if low + assert(! res.check(@user.create(:name => low)), "low user %s passed check" % low) + end + if high + res[:unless_system_user] = 50 + assert(res.check(@user.create(:name => high)), "high user %s failed check" % high) + end + end + + # The other half of #408. + def test_check_is_called + res = Puppet::Type.type(:resources).create :name => :user, :purge => true + + list = nil + assert_nothing_raised { list = res.generate } + + assert(! list.empty?, "did not get any users") + + bad = list.find_all { |u| + %w{root bin nobody}.include?(u[:name]) or (cv = u.retrieve and cv[u.property(:uid)] < 500) + } + assert(bad.empty?, "incorrectly passed users %s" % bad.collect { |u| u[:name]}.join(", ")) + end +end + diff --git a/test/ral/type/service.rb b/test/ral/type/service.rb new file mode 100755 index 000000000..01533c63e --- /dev/null +++ b/test/ral/type/service.rb @@ -0,0 +1,38 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../lib/puppettest' + +require 'puppettest' +require 'mocha' + +class TestServiceType < Test::Unit::TestCase + include PuppetTest + + # #199 + def test_no_refresh_when_starting + service = Puppet::Type.type(:service).create :name => "hopefully_this_isnt_in_the_process_table", + :ensure => :running, :provider => :base + + assert_equal :running, service.instance_eval('@parameters[:ensure]').should + assert_not_equal :running, service.instance_eval('@parameters[:ensure]').retrieve, "You have something called #{service.name} in your process table" + + # First make sure it does not refresh + service.provider.expects(:restart).never + + assert_nothing_raised do + service.refresh + end + end + + def test_refresh_normally + service = Puppet::Type.type(:service).create :name => "testing", + :ensure => :running, :provider => :base, :status => "cat /dev/null" + + service.provider.expects(:restart) + + assert_nothing_raised do + service.refresh + end + end +end + diff --git a/test/ral/type/sshkey.rb b/test/ral/type/sshkey.rb new file mode 100755 index 000000000..b9aed20e8 --- /dev/null +++ b/test/ral/type/sshkey.rb @@ -0,0 +1,194 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../lib/puppettest' + +require 'puppettest' +require 'puppet/type/sshkey' +require 'facter' + +class TestSSHKey < Test::Unit::TestCase + include PuppetTest + def setup + super + # god i'm lazy + @sshkeytype = Puppet.type(:sshkey) + + @provider = @sshkeytype.defaultprovider + + # Make sure they aren't using something funky like netinfo + unless @provider.name == :parsed + @sshkeytype.defaultprovider = @sshkeytype.provider(:parsed) + end + + cleanup do @sshkeytype.defaultprovider = nil end + + if @provider.respond_to?(:default_target) + oldpath = @provider.default_target + cleanup do + @provider.default_target = oldpath + end + @provider.default_target = tempfile() + end + end + + def teardown + super + if @provider.respond_to?(:clear) + @provider.clear + end + end + + def mkkey + key = nil + + if defined? @kcount + @kcount += 1 + else + @kcount = 1 + end + + @catalog ||= mk_catalog + + assert_nothing_raised { + key = @sshkeytype.create( + :name => "host%s.madstop.com" % @kcount, + :key => "%sAAAAB3NzaC1kc3MAAACBAMnhSiku76y3EGkNCDsUlvpO8tRgS9wL4Eh54WZfQ2lkxqfd2uT/RTT9igJYDtm/+UHuBRdNGpJYW1Nw2i2JUQgQEEuitx4QKALJrBotejGOAWxxVk6xsh9xA0OW8Q3ZfuX2DDitfeC8ZTCl4xodUMD8feLtP+zEf8hxaNamLlt/AAAAFQDYJyf3vMCWRLjTWnlxLtOyj/bFpwAAAIEAmRxxXb4jjbbui9GYlZAHK00689DZuX0EabHNTl2yGO5KKxGC6Esm7AtjBd+onfu4Rduxut3jdI8GyQCIW8WypwpJofCIyDbTUY4ql0AQUr3JpyVytpnMijlEyr41FfIb4tnDqnRWEsh2H7N7peW+8DWZHDFnYopYZJ9Yu4/jHRYAAACAERG50e6aRRb43biDr7Ab9NUCgM9bC0SQscI/xdlFjac0B/kSWJYTGVARWBDWug705hTnlitY9cLC5Ey/t/OYOjylTavTEfd/bh/8FkAYO+pWdW3hx6p97TBffK0b6nrc6OORT2uKySbbKOn0681nNQh4a6ueR3JRppNkRPnTk5c=" % @kcount, + :type => "ssh-dss", + :alias => ["192.168.0.%s" % @kcount], + :catalog => @catalog + ) + } + + return key + end + + def test_instances + assert_nothing_raised { + Puppet.type(:sshkey).instances + } + + count = 0 + @sshkeytype.each do |h| + count += 1 + end + + assert_equal(0, count, "Found sshkeys in empty file somehow") + end + + def test_simplekey + key = mkkey + file = tempfile() + key[:target] = file + key[:provider] = :parsed + + assert_apply(key) + + assert_events([], key, "created events on in-sync key") + + assert(key.provider.exists?, "Key did not get created") + + # Now create a new key object + name = key.name + key = nil + @sshkeytype.clear + + key = @sshkeytype.create :name => name, :target => file, :provider => :parsed + key.retrieve + + assert(key.provider.exists?, "key thinks it does not exist") + + end + + def test_moddingkey + key = mkkey() + + assert_events([:sshkey_created], key) + + key.retrieve + + aliases = %w{madstop kirby yayness} + key[:alias] = aliases + + params = key.instance_variable_get("@parameters") + assert_events([:sshkey_changed], key) + + aliases.each do |name| + assert_equal(key, key.class[name], + "alias was not set") + end + end + + def test_aliasisproperty + assert_equal(:property, @sshkeytype.attrtype(:alias)) + end + + def test_multivalues + key = mkkey + assert_raise(Puppet::Error) { + key[:alias] = "puppetmasterd yayness" + } + end + + def test_puppetalias + key = mkkey() + + assert_nothing_raised { + key[:alias] = "testing" + } + + same = key.class["testing"] + assert(same, "Could not retrieve by alias") + end + + def test_removal + sshkey = mkkey() + assert_nothing_raised { + sshkey[:ensure] = :present + } + assert_events([:sshkey_created], sshkey) + + assert(sshkey.provider.exists?, "key was not created") + assert_nothing_raised { + sshkey[:ensure] = :absent + } + + assert_events([:sshkey_removed], sshkey) + assert(! sshkey.provider.exists?, "Key was not deleted") + assert_events([], sshkey) + end + + # Make sure changes actually modify the file. + def test_modifyingfile + keys = [] + names = [] + 3.times { + k = mkkey() + #h[:ensure] = :present + #h.retrieve + keys << k + names << k.name + } + assert_apply(*keys) + keys.clear + Puppet.type(:sshkey).clear + newkey = mkkey() + #newkey[:ensure] = :present + names << newkey.name + assert_apply(newkey) + + # Verify we can retrieve that info + assert_nothing_raised("Could not retrieve after second write") { + newkey.provider.class.prefetch + newkey.retrieve + } + + # And verify that we have data for everything + names.each { |name| + key = Puppet.type(:sshkey)[name] || + Puppet.type(:sshkey).create(:name => name) + assert(key, "Could not retrieve key for %s" % name) + assert(key.provider.exists?, "key %s is missing" % name) + } + end +end + diff --git a/test/ral/type/tidy.rb b/test/ral/type/tidy.rb new file mode 100755 index 000000000..60fad6516 --- /dev/null +++ b/test/ral/type/tidy.rb @@ -0,0 +1,291 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../lib/puppettest' + +require 'puppettest' +require 'puppettest/support/utils' + +class TestTidy < Test::Unit::TestCase + include PuppetTest::Support::Utils + include PuppetTest::FileTesting + def mktmpfile + # because luke's home directory is on nfs, it can't be used for testing + # as root + tmpfile = tempfile() + File.open(tmpfile, "w") { |f| f.puts rand(100) } + @@tmpfiles.push tmpfile + return tmpfile + end + + def mktmpdir + dir = File.join(tmpdir(), "puppetlinkdir") + unless FileTest.exists?(dir) + Dir.mkdir(dir) + end + @@tmpfiles.push dir + return dir + end + + def test_tidydirs + dir = mktmpdir + file = File.join(dir, "file") + File.open(file, "w") { |f| + f.puts "some stuff" + } + + tidy = Puppet.type(:tidy).create( + :name => dir, + :size => "1b", + :rmdirs => true, + :recurse => true + ) + + assert_events([:file_tidied, :file_tidied], tidy) + + assert(!FileTest.exists?(file), "Tidied %s still exists" % file) + assert(!FileTest.exists?(dir), "Tidied %s still exists" % dir) + + end + + def disabled_test_recursion + source = mktmpdir() + FileUtils.cd(source) { + mkranddirsandfiles() + } + + link = nil + assert_nothing_raised { + link = newlink(:target => source, :recurse => true) + } + comp = mk_catalog("linktest",link) + cycle(comp) + + path = link.name + list = file_list(path) + FileUtils.cd(path) { + list.each { |file| + unless FileTest.directory?(file) + assert(FileTest.symlink?(file)) + target = File.readlink(file) + assert_equal(target,File.join(source,file.sub(/^\.\//,''))) + end + } + } + end + + # Test the different age iterations. + def test_age_conversions + tidy = Puppet::Type.newtidy :path => tempfile(), :age => "1m" + + convertors = { + :second => 1, + :minute => 60 + } + + convertors[:hour] = convertors[:minute] * 60 + convertors[:day] = convertors[:hour] * 24 + convertors[:week] = convertors[:day] * 7 + + # First make sure we default to days + assert_nothing_raised do + tidy[:age] = "2" + end + + assert_equal(2 * convertors[:day], tidy.should(:age), + "Converted 2 wrong") + + convertors.each do |name, number| + init = name.to_s[0..0] # The first letter + [0, 1, 5].each do |multi| + [init, init.upcase].each do |letter| + age = multi.to_s + letter.to_s + assert_nothing_raised do + tidy[:age] = age + end + + assert_equal(multi * convertors[name], tidy.should(:age), + "Converted %s wrong" % age) + end + end + end + end + + def test_size_conversions + convertors = { + :b => 0, + :kb => 1, + :mb => 2, + :gb => 3 + } + + tidy = Puppet::Type.newtidy :path => tempfile(), :age => "1m" + + # First make sure we default to kb + assert_nothing_raised do + tidy[:size] = "2" + end + + assert_equal(2048, tidy.should(:size), + "Converted 2 wrong") + + convertors.each do |name, number| + init = name.to_s[0..0] # The first letter + [0, 1, 5].each do |multi| + [init, init.upcase].each do |letter| + size = multi.to_s + letter.to_s + assert_nothing_raised do + tidy[:size] = size + end + + total = multi + number.times do total *= 1024 end + + assert_equal(total, tidy.should(:size), + "Converted %s wrong" % size) + end + end + end + end + + def test_agetest + tidy = Puppet::Type.newtidy :path => tempfile(), :age => "1m" + + age = tidy.property(:age) + + # Set it to something that should be fine + assert(age.insync?(Time.now.to_i - 5), "Tried to tidy a low age") + + # Now to something that should fail + assert(! age.insync?(Time.now.to_i - 120), "Incorrectly skipped tidy") + end + + def test_sizetest + tidy = Puppet::Type.newtidy :path => tempfile(), :size => "1k" + + size = tidy.property(:size) + + # Set it to something that should be fine + assert(size.insync?(50), "Tried to tidy a low size") + + # Now to something that should fail + assert(! size.insync?(2048), "Incorrectly skipped tidy") + end + + # Make sure we can remove different types of files + def test_tidytypes + path = tempfile() + tidy = Puppet::Type.newtidy :path => path, :size => "1b", :age => "1s" + + # Start with a file + File.open(path, "w") { |f| f.puts "this is a test" } + assert_events([:file_tidied], tidy) + assert(! FileTest.exists?(path), "File was not removed") + + # Then a link + dest = tempfile + File.open(dest, "w") { |f| f.puts "this is a test" } + File.symlink(dest, path) + assert_events([:file_tidied], tidy) + assert(! FileTest.exists?(path), "Link was not removed") + assert(FileTest.exists?(dest), "Destination was removed") + + # And a directory + Dir.mkdir(path) + tidy[:rmdirs] = true + assert_events([:file_tidied], tidy) + assert(! FileTest.exists?(path), "File was not removed") + end + + # Make sure we can specify either attribute and get appropriate behaviour. + # I found that the original implementation of this did not work unless both + # size and age were specified. + def test_one_attribute + path = tempfile() + File.open(path, "w") { |f| 10.times { f.puts "yayness " } } + tidy = Puppet::Type.type(:tidy).create :path => path, :size => "1b" + + assert_apply(tidy) + assert(! FileTest.exists?(path), "file did not get tidied") + + tidy.class.clear + + # Now try one with just an age attribute. + time = Time.now - 10 + stat = stub 'stat', :mtime => time, :atime => time, :ftype => "file" + File.stubs(:lstat) + File.stubs(:lstat).with(path).returns(stat) + + File.open(path, "w") { |f| 10.times { f.puts "yayness " } } + tidy = Puppet::Type.type(:tidy).create :path => path, :age => "5s" + + + assert_apply(tidy) + assert(! FileTest.exists?(path), "file did not get tidied") + end + + # Testing #355. + def test_remove_dead_links + dir = tempfile() + link = File.join(dir, "link") + target = tempfile() + Dir.mkdir(dir) + File.symlink(target, link) + + tidy = Puppet::Type.newtidy :path => dir, :size => "1b", :recurse => true + assert_apply(tidy) + assert(! FileTest.symlink?(link), "link was not tidied") + end + + def test_glob_matches_single + dir = mktmpdir + files = { + :remove => File.join(dir, "01-foo"), + :keep => File.join(dir, "default") + } + files.each do |tag, file| + File.open(file, "w") { |f| + f.puts "some stuff" + } + end + + tidy = Puppet.type(:tidy).create( + :name => dir, + :size => "1b", + :rmdirs => true, + :recurse => true, + :matches => "01-*" + ) + assert_apply(tidy) + + assert(FileTest.exists?(files[:keep]), "%s was tidied" % files[:keep]) + assert(!FileTest.exists?(files[:remove]), "Tidied %s still exists" % files[:remove]) + end + + def test_glob_matches_multiple + dir = mktmpdir + files = { + :remove1 => File.join(dir, "01-foo"), + :remove2 => File.join(dir, "02-bar"), + :keep1 => File.join(dir, "default") + } + files.each do |tag, file| + File.open(file, "w") { |f| + f.puts "some stuff" + } + end + + tidy = Puppet.type(:tidy).create( + :name => dir, + :size => "1b", + :rmdirs => true, + :recurse => true, + :matches => ["01-*", "02-*"] + ) + assert_apply(tidy) + + assert(FileTest.exists?(files[:keep1]), "%s was tidied" % files[:keep1]) + assert(!FileTest.exists?(files[:remove1]), "Tidied %s still exists" % files[:remove1]) + assert(!FileTest.exists?(files[:remove2]), "Tidied %s still exists" % files[:remove2]) + end +end + diff --git a/test/ral/type/user.rb b/test/ral/type/user.rb new file mode 100755 index 000000000..b280acfed --- /dev/null +++ b/test/ral/type/user.rb @@ -0,0 +1,492 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../lib/puppettest' + +require 'puppettest' +require 'etc' + +class TestUser < Test::Unit::TestCase + include PuppetTest + + p = Puppet::Type.type(:user).provide :fake, :parent => PuppetTest::FakeProvider do + @name = :fake + apimethods + def create + @ensure = :present + @resource.send(:properties).each do |property| + next if property.name == :ensure + property.sync + end + end + + def delete + @ensure = :absent + @resource.send(:properties).each do |property| + send(property.name.to_s + "=", :absent) + end + end + + def exists? + if defined? @ensure and @ensure == :present + true + else + false + end + end + end + + FakeUserProvider = p + + @@fakeproviders[:group] = p + + def findshell(old = nil) + %w{/bin/sh /bin/bash /sbin/sh /bin/ksh /bin/zsh /bin/csh /bin/tcsh + /usr/bin/sh /usr/bin/bash /usr/bin/ksh /usr/bin/zsh /usr/bin/csh + /usr/bin/tcsh}.find { |shell| + if old + FileTest.exists?(shell) and shell != old + else + FileTest.exists?(shell) + end + } + end + + def setup + super + Puppet::Type.type(:user).defaultprovider = FakeUserProvider + end + + def teardown + Puppet::Type.type(:user).defaultprovider = nil + super + end + + def mkuser(name) + user = nil + assert_nothing_raised { + user = Puppet.type(:user).create( + :name => name, + :comment => "Puppet Testing User", + :gid => Puppet::Util::SUIDManager.gid, + :shell => findshell(), + :home => "/home/%s" % name + ) + } + + assert(user, "Did not create user") + + return user + end + + def attrtest_ensure(user) + old = user.provider.ensure + user[:ensure] = :absent + + comp = mk_catalog("ensuretest", user) + assert_apply(user) + assert(!user.provider.exists?, "User is still present") + user[:ensure] = :present + assert_events([:user_created], comp) + assert(user.provider.exists?, "User is absent") + user[:ensure] = :absent + trans = assert_events([:user_removed], comp) + + assert_rollback_events(trans, [:user_created], "user") + + user[:ensure] = old + assert_apply(user) + end + + def attrtest_comment(user) + user.retrieve + old = user.provider.comment + user[:comment] = "A different comment" + + comp = mk_catalog("commenttest", user) + + trans = assert_events([:user_changed], comp, "user") + + assert_equal("A different comment", user.provider.comment, + "Comment was not changed") + + assert_rollback_events(trans, [:user_changed], "user") + + assert_equal(old, user.provider.comment, + "Comment was not reverted") + end + + def attrtest_home(user) + obj = nil + comp = mk_catalog("hometest", user) + + old = user.provider.home + user[:home] = old + + trans = assert_events([], comp, "user") + + user[:home] = "/tmp" + + trans = assert_events([:user_changed], comp, "user") + + assert_equal("/tmp", user.provider.home, "Home was not changed") + + assert_rollback_events(trans, [:user_changed], "user") + + assert_equal(old, user.provider.home, "Home was not reverted") + end + + def attrtest_shell(user) + old = user.provider.shell + comp = mk_catalog("shelltest", user) + + user[:shell] = old + + trans = assert_events([], comp, "user") + + newshell = findshell(old) + + unless newshell + $stderr.puts "Cannot find alternate shell; skipping shell test" + return + end + + user[:shell] = newshell + + trans = assert_events([:user_changed], comp, "user") + + user.retrieve + assert_equal(newshell, user.provider.shell, + "Shell was not changed") + + assert_rollback_events(trans, [:user_changed], "user") + user.retrieve + + assert_equal(old, user.provider.shell, "Shell was not reverted") + end + + def attrtest_gid(user) + obj = nil + old = user.provider.gid + comp = mk_catalog("gidtest", user) + + user.retrieve + + user[:gid] = old + + trans = assert_events([], comp, "user") + + newgid = %w{nogroup nobody staff users daemon}.find { |gid| + begin + group = Etc.getgrnam(gid) + rescue ArgumentError => detail + next + end + old != group.gid and group.gid > 0 + } + + unless newgid + $stderr.puts "Cannot find alternate group; skipping gid test" + return + end + + # first test by name + assert_nothing_raised("Failed to specify group by name") { + user[:gid] = newgid + } + + trans = assert_events([:user_changed], comp, "user") + + # then by id + newgid = Etc.getgrnam(newgid).gid + + assert_nothing_raised("Failed to specify group by id for %s" % newgid) { + user[:gid] = newgid + } + + user.retrieve + + assert_events([], comp, "user") + + assert_equal(newgid, user.provider.gid, "GID was not changed") + + assert_rollback_events(trans, [:user_changed], "user") + + assert_equal(old, user.provider.gid, "GID was not reverted") + end + + def attrtest_uid(user) + obj = nil + comp = mk_catalog("uidtest", user) + + user.provider.uid = 1 + + old = 1 + newuid = 1 + while true + newuid += 1 + + if newuid - old > 1000 + $stderr.puts "Could not find extra test UID" + return + end + begin + newuser = Etc.getpwuid(newuid) + rescue ArgumentError => detail + break + end + end + + assert_nothing_raised("Failed to change user id") { + user[:uid] = newuid + } + + trans = assert_events([:user_changed], comp, "user") + + assert_equal(newuid, user.provider.uid, "UID was not changed") + + assert_rollback_events(trans, [:user_changed], "user") + + assert_equal(old, user.provider.uid, "UID was not reverted") + end + + def attrtest_groups(user) + Etc.setgrent + max = 0 + while group = Etc.getgrent + if group.gid > max and group.gid < 5000 + max = group.gid + end + end + + groups = [] + main = [] + extra = [] + 5.times do |i| + i += 1 + name = "pptstgr%s" % i + groups << name + if i < 3 + main << name + else + extra << name + end + end + + assert(user[:membership] == :minimum, "Membership did not default correctly") + + assert_nothing_raised { + user.retrieve + } + + # Now add some of them to our user + assert_nothing_raised { + user[:groups] = extra + } + assert_nothing_raised { + user.retrieve + } + + assert_instance_of(String, user.property(:groups).should) + + # Some tests to verify that groups work correctly startig from nothing + # Remove our user + user[:ensure] = :absent + assert_apply(user) + + assert_nothing_raised do + user.retrieve + end + + # And add it again + user[:ensure] = :present + assert_apply(user) + + # Make sure that the groups are a string, not an array + assert(user.provider.groups.is_a?(String), + "Incorrectly passed an array to groups") + + currentvalue = user.retrieve + + assert(currentvalue[user.property(:groups)], "Did not retrieve group list") + + list = currentvalue[user.property(:groups)] + assert_equal(extra.sort, list.sort, "Group list is not equal") + + # Now set to our main list of groups + assert_nothing_raised { + user[:groups] = main + } + + assert_equal((main + extra).sort, user.property(:groups).should.split(",").sort) + + currentvalue = nil + assert_nothing_raised { + currentvalue = user.retrieve + } + + assert(!user.insync?(currentvalue), "User is incorrectly in sync") + + assert_apply(user) + + assert_nothing_raised { + currentvalue = user.retrieve + } + + # We're not managing inclusively, so it should keep the old group + # memberships and add the new ones + list = currentvalue[user.property(:groups)] + assert_equal((main + extra).sort, list.sort, "Group list is not equal") + + assert_nothing_raised { + user[:membership] = :inclusive + } + assert_nothing_raised { + currentvalue = user.retrieve + } + + assert(!user.insync?(currentvalue), "User is incorrectly in sync") + + assert_events([:user_changed], user) + assert_nothing_raised { + currentvalue = user.retrieve + } + + list = currentvalue[user.property(:groups)] + assert_equal(main.sort, list.sort, "Group list is not equal") + + # Set the values a bit differently. + user.property(:groups).should = list.sort { |a,b| b <=> a } + + assert(user.property(:groups).insync?(list.sort), "Groups property did not sort groups") + + user.delete(:groups) + end + + def test_autorequire + file = tempfile() + comp = nil + user = nil + group =nil + home = nil + ogroup = nil + assert_nothing_raised { + user = Puppet.type(:user).create( + :name => "pptestu", + :home => file, + :gid => "pptestg", + :groups => "yayness" + ) + home = Puppet.type(:file).create( + :path => file, + :owner => "pptestu", + :ensure => "directory" + ) + group = Puppet.type(:group).create( + :name => "pptestg" + ) + ogroup = Puppet.type(:group).create( + :name => "yayness" + ) + comp = mk_catalog(user, group, home, ogroup) + } + + rels = nil + assert_nothing_raised() { rels = user.autorequire } + + assert(rels.detect { |r| r.source == group }, "User did not require group") + assert(rels.detect { |r| r.source == ogroup }, "User did not require other groups") + assert_nothing_raised() { rels = home.autorequire } + assert(rels.detect { |r| r.source == user }, "Homedir did not require user") + end + + def test_simpleuser + name = "pptest" + + user = mkuser(name) + + comp = mk_catalog("usercomp", user) + + trans = assert_events([:user_created], comp, "user") + + assert_equal(user.should(:comment), user.provider.comment, + "Comment was not set correctly") + + assert_rollback_events(trans, [:user_removed], "user") + + assert(! user.provider.exists?, "User did not get deleted") + end + + def test_allusermodelproperties + user = nil + name = "pptest" + + user = mkuser(name) + + assert(! user.provider.exists?, "User %s is present" % name) + + comp = mk_catalog("usercomp", user) + + trans = assert_events([:user_created], comp, "user") + + user.retrieve + assert_equal("Puppet Testing User", user.provider.comment, + "Comment was not set") + + tests = Puppet.type(:user).validproperties + + tests.each { |test| + if self.respond_to?("attrtest_%s" % test) + self.send("attrtest_%s" % test, user) + else + Puppet.err "Not testing attr %s of user" % test + end + } + + user[:ensure] = :absent + assert_apply(user) + end + + # Testing #455 + def test_autorequire_with_no_group_should + user = Puppet::Type.type(:user).create(:name => "yaytest", :check => :all) + + assert_nothing_raised do + user.autorequire + end + + user[:ensure] = :absent + + assert_nothing_raised do + user.evaluate + end + + assert(user.send(:property, :groups).insync?(nil), + "Groups state considered out of sync with no :should value") + end + + # Make sure the 'managehome' param can only be set when the provider + # has that feature. Uses a patch from #432. + def test_managehome + user = Puppet::Type.type(:user).create(:name => "yaytest", :check => :all) + + prov = user.provider + + home = false + prov.class.meta_def(:manages_homedir?) { home } + + assert_nothing_raised("failed on false managehome") do + user[:managehome] = false + end + + assert_raise(ArgumentError, "did not fail when managehome? is false") do + user[:managehome] = true + end + + home = true + assert(prov.class.manages_homedir?, "provider did not enable homedir") + assert_nothing_raised("failed when managehome is true") do + user[:managehome] = true + end + end +end + diff --git a/test/ral/type/yumrepo.rb b/test/ral/type/yumrepo.rb new file mode 100755 index 000000000..899a02135 --- /dev/null +++ b/test/ral/type/yumrepo.rb @@ -0,0 +1,106 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../lib/puppettest' + +require 'puppettest' +require 'fileutils' + +class TestYumRepo < Test::Unit::TestCase + include PuppetTest + + def setup + super + @yumdir = tempfile() + Dir.mkdir(@yumdir) + @yumconf = File.join(@yumdir, "yum.conf") + File.open(@yumconf, "w") do |f| + f.print "[main]\nreposdir=#{@yumdir} /no/such/dir\n" + end + Puppet.type(:yumrepo).yumconf = @yumconf + end + + # Modify one existing section + def test_modify + copy_datafiles + devel = make_repo("development", { :descr => "New description" }) + current_values = devel.retrieve + assert_equal("development", devel[:name]) + assert_equal('Fedora Core $releasever - Development Tree', + current_values[devel.property(:descr)]) + assert_equal('New description', + devel.property(:descr).should) + assert_apply(devel) + inifile = Puppet.type(:yumrepo).read() + assert_equal('New description', inifile['development']['name']) + assert_equal('Fedora Core $releasever - $basearch - Base', + inifile['base']['name']) + assert_equal("foo\n bar\n baz", inifile['base']['exclude']) + assert_equal(['base', 'development', 'main'], + all_sections(inifile)) + end + + # Create a new section + def test_create + values = { + :descr => "Fedora Core $releasever - $basearch - Base", + :baseurl => "http://example.com/yum/$releasever/$basearch/os/", + :enabled => "1", + :gpgcheck => "1", + :includepkgs => "absent", + :gpgkey => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora" + } + repo = make_repo("base", values) + + assert_apply(repo) + inifile = Puppet.type(:yumrepo).read() + sections = all_sections(inifile) + assert_equal(['base', 'main'], sections) + text = inifile["base"].format + assert_equal(CREATE_EXP, text) + end + + # Delete mirrorlist by setting it to :absent and enable baseurl + def test_absent + copy_datafiles + baseurl = 'http://example.com/' + devel = make_repo("development", + { :mirrorlist => 'absent', + :baseurl => baseurl }) + devel.retrieve + assert_apply(devel) + inifile = Puppet.type(:yumrepo).read() + sec = inifile["development"] + assert_nil(sec["mirrorlist"]) + assert_equal(baseurl, sec["baseurl"]) + end + + def make_repo(name, hash={}) + hash[:name] = name + Puppet.type(:yumrepo).create(hash) + end + + def all_sections(inifile) + sections = [] + inifile.each_section { |section| sections << section.name } + return sections.sort + end + + def copy_datafiles + fakedata("data/types/yumrepos").select { |file| + file =~ /\.repo$/ + }.each { |src| + dst = File::join(@yumdir, File::basename(src)) + FileUtils::copy(src, dst) + } + end + + CREATE_EXP = <<'EOF' +[base] +name=Fedora Core $releasever - $basearch - Base +baseurl=http://example.com/yum/$releasever/$basearch/os/ +enabled=1 +gpgcheck=1 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora +EOF + +end diff --git a/test/ral/type/zone.rb b/test/ral/type/zone.rb new file mode 100755 index 000000000..eb485b944 --- /dev/null +++ b/test/ral/type/zone.rb @@ -0,0 +1,420 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../lib/puppettest' + +require 'puppettest' +require 'puppet/type/zone' + +class TestZone < PuppetTest::TestCase + confine "Zones are only functional on Solaris" => (Facter["operatingsystem"].value == "Solaris") + + def setup + super + @@zones = [] + end + + def mkzone(name) + zone = nil + + base = tempfile() + Dir.mkdir(base) + File.chmod(0700, base) + root = File.join(base, "zonebase") + assert_nothing_raised { + zone = Puppet::Type.type(:zone).create( + :name => name, + :path => root, + :ensure => "configured" # don't want to install zones automatically + ) + } + + @@zones << name + + return zone + end + + def test_instances + list = nil + assert_nothing_raised { + list = Puppet::Type.type(:zone).instances + } + + assert(! list.empty?, "Got no zones back") + + assert(list.find { |z| z[:name] == "global" }, "Could not find global zone") + end + + def test_state_sequence + zone = mkzone("slicetest") + + property = zone.property(:ensure) + + slice = nil + assert_nothing_raised { + slice = property.class.state_sequence(:absent, :installed).collect do |o| + o[:name] + end + } + + + assert_equal([:configured, :installed], slice) + + assert_nothing_raised { + slice = property.class.state_sequence(:running, :installed).collect do |o| + o[:name] + end + } + + + assert_equal(slice, [:installed]) + + end + + # Make sure the ensure stuff behaves as we expect + def test_zoneensure + zone = mkzone("ensurezone") + + property = zone.property(:ensure) + + assert(property, "Did not get ensure property") + + values = nil + assert_nothing_raised { + values = zone.retrieve + } + + assert(! property.insync?(values[property]), "Property is somehow in sync") + + assert(property.up?, "Property incorrectly thinks it is not moving up") + + zone[:ensure] = :installed + assert(property.up?, "Property incorrectly thinks it is not moving up") + zone[:ensure] = :absent + assert(! property.up?, "Property incorrectly thinks it is moving up") + end + + # Make sure all mentioned methods actually exist. + def test_zonemethods_exist + methods = [] + zone = mkzone("methodtest") + + property = zone.property(:ensure) + assert_nothing_raised { + property.class.state_sequence(:absent, :running).each do |st| + [:up, :down].each do |m| + if st[m] + methods << st[m] + end + end + end + } + + methods.each do |m| + Puppet::Type.type(:zone).suitableprovider.each do |prov| + assert(prov.method_defined?(m), + "Zone provider %s does not define method %s" % + [prov.name, m]) + end + end + + end + + # Make sure our property generates the correct text. + def test_inherit_property + zone = mkzone("configtesting") + zone[:ensure] = :configured + + assert_nothing_raised { + zone[:inherit] = "/usr" + } + property = zone.property(:inherit) + assert(zone, "Did not get 'inherit' property") + + assert_equal("add inherit-pkg-dir\nset dir=/usr\nend", property.configtext, + "Got incorrect config text") + + zone.provider.inherit = "/usr" + + assert_equal("", property.configtext, + "Got incorrect config text") + + # Now we want multiple directories + property.should = %w{/usr /sbin /lib} + + # The statements are sorted + text = "add inherit-pkg-dir +set dir=/lib +end +add inherit-pkg-dir +set dir=/sbin +end" + + assert_equal(text, property.configtext, + "Got incorrect config text") + + zone.provider.inherit = %w{/usr /sbin /lib} + property.should = %w{/usr /sbin} + + text = "remove inherit-pkg-dir dir=/lib" + + assert_equal(text, property.configtext, + "Got incorrect config text") + end +end + +class TestZoneAsRoot < TestZone + confine "Not running Zone creation tests" => Puppet.features.root? + confine "Zones are only functional on Solaris" => (Facter["operatingsystem"].value == "Solaris") + + def teardown + current = %x{zoneadm list -cp}.split("\n").inject({}) { |h, line| + ary = line.split(":") + h[ary[1]] = ary[2] + h + } + + Puppet::Type.type(:zone).clear + + # Get rid of any lingering zones + @@zones.each do |zone| + next unless current.include? zone + + obj = Puppet::Type.type(:zone).create(:name => zone) + obj[:ensure] = :absent + assert_apply(obj) + end + + # We can't delete the temp files until the zones are stopped and removed. + super + end + # Make sure our ensure process actually works. + def test_ensure_sync + zone = mkzone("ensuretesting") + + zone[:ensure] = :configured + + assert_apply(zone) + + assert(zone.insync?(zone.retrieve), "Zone is not insync") + end + + def test_getconfig + zone = mkzone("configtesting") + + base = tempfile() + zone[:path] = base + + ip = "192.168.0.1" + interface = "bge0" + zone[:ip] = "#{interface}:#{ip}" + + IO.popen("zonecfg -z configtesting -f -", "w") do |f| + f.puts %{create -b +set zonepath=#{tempfile()} +set autoboot=true +add inherit-pkg-dir +set dir=/lib +end +add inherit-pkg-dir +set dir=/platform +end +add inherit-pkg-dir +set dir=/sbin +end +add inherit-pkg-dir +set dir=/opt/csw +end +add inherit-pkg-dir +set dir=/usr +end +add net +set address=#{ip} +set physical=bge0 +end +} + end + + assert_equal(0, $?, "Did not successfully create zone") + + hash = nil + assert_nothing_raised { + hash = zone.provider.send(:getconfig) + } + + zone[:check] = [:inherit, :autoboot] + + values = nil + assert_nothing_raised("Could not retrieve zone values") do + values = zone.retrieve.inject({}) { |result, newvals| result[newvals[0].name] = newvals[1]; result } + end + + # And make sure it gets set correctly. + assert_equal(%w{/sbin /usr /opt/csw /lib /platform}.sort, + values[:inherit].sort, "Inherited dirs did not get collected correctly." + ) + + assert_equal(["#{interface}:#{ip}"], values[:ip], + "IP addresses did not get collected correctly.") + + assert_equal(:true, values[:autoboot], + "Autoboot did not get collected correctly.") + end + + # Make sure we can do all the various and sundry configuring things. + def test_configuring_zones + zone = mkzone("configtesting") + + assert_nothing_raised { + zone[:inherit] = "/usr" + } + + zone[:ensure] = :configured + + assert_apply(zone) + + assert(zone.insync?(zone.retrieve), "Zone is not insync") + + # Now add a new directory to inherit + assert_nothing_raised { + zone[:inherit] = ["/sbin", "/usr"] + } + assert_apply(zone) + + assert(zone.insync?(zone.retrieve), "Zone is not insync") + + assert(%x{/usr/sbin/zonecfg -z #{zone[:name]} info} =~ /dir: \/sbin/, + "sbin was not added") + + # And then remove it. + assert_nothing_raised { + zone[:inherit] = "/usr" + } + assert_apply(zone) + + assert(zone.insync?(zone.retrieve), "Zone is not insync") + + assert(%x{/usr/sbin/zonecfg -z #{zone[:name]} info} !~ /dir: \/sbin/, + "sbin was not removed") + + # Now add an ip adddress. Fortunately (or not), zonecfg doesn't verify + # that the interface exists. + zone[:ip] = "hme0:192.168.0.1" + + assert(! zone.insync?(zone.retrieve), "Zone is marked as in sync") + + assert_apply(zone) + assert(zone.insync?(zone.retrieve), "Zone is not in sync") + assert(%x{/usr/sbin/zonecfg -z #{zone[:name]} info} =~ /192.168.0.1/, + "ip was not added") + zone[:ip] = ["hme1:192.168.0.2", "hme0:192.168.0.1"] + assert_apply(zone) + assert(zone.insync?(zone.retrieve), "Zone is not in sync") + assert(%x{/usr/sbin/zonecfg -z #{zone[:name]} info} =~ /192.168.0.2/, + "ip was not added") + zone[:ip] = ["hme1:192.168.0.2"] + assert_apply(zone) + zone.retrieve + assert(%x{/usr/sbin/zonecfg -z #{zone[:name]} info} !~ /192.168.0.1/, + "ip was not removed") + end + + # Test creating and removing a zone, but only up to the configured property, + # so it's faster. + def test_smallcreate + zone = mkzone("smallcreate") + # Include a bunch of stuff so the zone isn't as large + dirs = %w{/usr /sbin /lib /platform} + + %w{/opt/csw}.each do |dir| + dirs << dir if FileTest.exists? dir + end + zone[:inherit] = dirs + + assert(zone, "Did not make zone") + + zone[:ensure] = :configured + + assert(! zone.insync?(zone.retrieve), "Zone is incorrectly in sync") + + assert_apply(zone) + + assert(zone.insync?(zone.retrieve), "Zone is incorrectly out of sync") + + zone[:ensure] = :absent + + assert_apply(zone) + + currentvalues = zone.retrieve + + assert_equal(:absent, currentvalues[zone.property(:ensure)], + "Zone is not absent") + end + + # Just go through each method linearly and make sure it works. + def test_each_method + zone = mkzone("methodtesting") + dirs = %w{/usr /sbin /lib /platform} + + %w{/opt/csw}.each do |dir| + dirs << dir if FileTest.exists? dir + end + zone[:inherit] = dirs + + [[:configure, :configured], + [:install, :installed], + [:start, :running], + [:stop, :installed], + [:uninstall, :configured], + [:unconfigure, :absent] + ].each do |method, property| + Puppet.info "Testing %s" % method + current_values = nil + assert_nothing_raised { + current_values = zone.retrieve + } + assert_nothing_raised { + zone.provider.send(method) + } + current_values = nil + assert_nothing_raised { + current_values = zone.retrieve + } + assert_equal(property, current_values[zone.property(:ensure)], + "Method %s did not correctly set property %s" % + [method, property]) + end + end + + def test_mkzone + zone = mkzone("testmaking") + # Include a bunch of stuff so the zone isn't as large + dirs = %w{/usr /sbin /lib /platform} + + %w{/opt/csw}.each do |dir| + dirs << dir if FileTest.exists? dir + end + zone[:inherit] = dirs + + assert(zone, "Did not make zone") + + + [:configured, :installed, :running, :installed, :absent].each do |value| + assert_nothing_raised { + zone[:ensure] = value + } + assert(! zone.insync?(zone.retrieve), "Zone is incorrectly in sync") + + assert_apply(zone) + + assert_nothing_raised { + assert(zone.insync?(zone.retrieve), "Zone is incorrectly out of sync") + } + end + + currentvalues = zone.retrieve + + assert_equal(:absent, currentvalues[zone.property(:ensure)], + "Zone is not absent") + end +end + diff --git a/test/ral/types/basic.rb b/test/ral/types/basic.rb deleted file mode 100755 index 3c5faeee0..000000000 --- a/test/ral/types/basic.rb +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' - -class TestBasic < Test::Unit::TestCase - include PuppetTest - - def setup - super - @component = nil - @configfile = nil - @command = nil - - assert_nothing_raised() { - @component = Puppet.type(:component).create( - :name => "yaytest", - :type => "testing" - ) - } - - assert_nothing_raised() { - @filepath = tempfile() - @configfile = Puppet.type(:file).create( - :path => @filepath, - :ensure => "file", - :checksum => "md5" - ) - } - assert_nothing_raised() { - @command = Puppet.type(:exec).create( - :title => "echo", - :command => "echo yay", - :path => ENV["PATH"] - ) - } - @config = mk_catalog(@component, @configfile, @command) - @config.add_edge @component, @configfile - @config.add_edge @component, @command - end - - def teardown - super - stopservices - end - - def test_values - [:ensure, :checksum].each do |param| - prop = @configfile.property(param) - assert(prop, "got no property for %s" % param) - assert(prop.value, "got no value for %s" % param) - end - end - - def test_name_calls - [@command, @configfile].each { |obj| - Puppet.debug "obj is %s" % obj - assert_nothing_raised(){ - obj.name - } - } - end - - def test_name_equality - assert_equal(@filepath, @configfile.title) - - assert_equal("echo", @command.title) - end - - def test_object_retrieval - [@command, @configfile].each { |obj| - assert_equal(obj.class[obj.name].object_id, obj.object_id, - "%s did not match class version" % obj.ref) - } - end - - def test_paths - [@configfile, @command, @component].each { |obj| - assert_nothing_raised { - assert_instance_of(String, obj.path) - } - } - end -end diff --git a/test/ral/types/cron.rb b/test/ral/types/cron.rb deleted file mode 100755 index 73e941894..000000000 --- a/test/ral/types/cron.rb +++ /dev/null @@ -1,499 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' - -# Test cron job creation, modification, and destruction - -class TestCron < Test::Unit::TestCase - include PuppetTest - - def setup - super - - setme() - - @crontype = Puppet::Type.type(:cron) - @provider = @crontype.defaultprovider - if @provider.respond_to?(:filetype=) - @provider.stubs(:filetype).returns(Puppet::Util::FileType.filetype(:ram)) - end - @crontype = Puppet::Type.type(:cron) - end - - def teardown - super - @crontype.defaultprovider = nil - Puppet::Util::FileType.filetype(:ram).clear - end - - def eachprovider - @crontype.suitableprovider.each do |provider| - yield provider - end - end - - # Back up the user's existing cron tab if they have one. - def cronback - tab = nil - assert_nothing_raised { - tab = Puppet.type(:cron).filetype.read(@me) - } - - if $? == 0 - @currenttab = tab - else - @currenttab = nil - end - end - - # Restore the cron tab to its original form. - def cronrestore - assert_nothing_raised { - if @currenttab - @crontype.filetype.new(@me).write(@currenttab) - else - @crontype.filetype.new(@me).remove - end - } - end - - # Create a cron job with all fields filled in. - def mkcron(name, addargs = true) - cron = nil - command = "date > %s/crontest%s" % [tmpdir(), name] - args = nil - if addargs - args = { - :command => command, - :name => name, - :user => @me, - :minute => rand(59), - :month => "1", - :monthday => "1", - :hour => "1" - } - else - args = {:command => command, :name => name} - end - assert_nothing_raised { - cron = @crontype.create(args) - } - - return cron - end - - # Run the cron through its paces -- install it then remove it. - def cyclecron(cron) - obj = Puppet::Type::Cron.cronobj(@me) - - text = obj.read - name = cron.name - comp = mk_catalog(name, cron) - - assert_events([:cron_created], comp) - cron.provider.class.prefetch - currentvalue = cron.retrieve - - assert(cron.insync?(currentvalue), "Cron is not in sync") - - assert_events([], comp) - - curtext = obj.read - text.split("\n").each do |line| - assert(curtext.include?(line), "Missing '%s'" % line) - end - obj = Puppet::Type::Cron.cronobj(@me) - - cron[:ensure] = :absent - - assert_events([:cron_removed], comp) - - cron.provider.class.prefetch - currentvalue = cron.retrieve - - assert(cron.insync?(currentvalue), "Cron is not in sync") - assert_events([], comp) - end - - # Test that a cron job with spaces at the end doesn't get rewritten - def test_trailingspaces - eachprovider do |provider| - cron = nil - # make the cron - name = "yaytest" - command = "date > /dev/null " - assert_nothing_raised { - cron = @crontype.create( - :name => name, - :command => "date > /dev/null ", - :month => "May", - :user => @me - ) - } - property = cron.send(:property, :command) - cron.provider.command = command - cron.provider.ensure = :present - cron.provider.user = @me - cron.provider.month = ["4"] - cron.provider.class.prefetch - currentvalue = cron.retrieve - - currentvalue.each do |prop, value| - # We're only interested in comparing the command. - next unless prop.name.to_s == "command" - assert(prop.insync?(value), "Property %s is not considered in sync with value %s" % [prop.name, value.inspect]) - end - - @crontype.clear - end - end - - def test_makeandretrievecron - %w{storeandretrieve a-name another-name more_naming SomeName}.each do |name| - cron = mkcron(name) - comp = mk_catalog(name, cron) - trans = assert_events([:cron_created], comp, name) - - cron.provider.class.prefetch - cron = nil - - assert(cron = Puppet.type(:cron)[name], "Could not retrieve named cron") - assert_instance_of(Puppet.type(:cron), cron) - end - end - - # Do input validation testing on all of the parameters. - def test_arguments - values = { - :monthday => { - :valid => [ 1, 13, "1" ], - :invalid => [ -1, 0, 32 ] - }, - :weekday => { - :valid => [ 0, 3, 6, "1", "tue", "wed", - "Wed", "MOnday", "SaTurday" ], - :invalid => [ -1, 7, "13", "tues", "teusday", "thurs" ] - }, - :hour => { - :valid => [ 0, 21, 23 ], - :invalid => [ -1, 24 ] - }, - :minute => { - :valid => [ 0, 34, 59 ], - :invalid => [ -1, 60 ] - }, - :month => { - :valid => [ 1, 11, 12, "mar", "March", "apr", "October", "DeCeMbEr" ], - :invalid => [ -1, 0, 13, "marc", "sept" ] - } - } - - cron = mkcron("valtesting") - values.each { |param, hash| - # We have to test the valid ones first, because otherwise the - # property will fail to create at all. - [:valid, :invalid].each { |type| - hash[type].each { |value| - case type - when :valid: - assert_nothing_raised { - cron[param] = value - } - - if value.is_a?(Integer) - assert_equal([value.to_s], cron.should(param), - "Cron value was not set correctly") - end - when :invalid: - assert_raise(Puppet::Error, "%s is incorrectly a valid %s" % - [value, param]) { - cron[param] = value - } - end - - if value.is_a?(Integer) - value = value.to_s - redo - end - } - } - } - end - - # Verify that comma-separated numbers are not resulting in rewrites - def test_comma_separated_vals_work - eachprovider do |provider| - cron = nil - assert_nothing_raised { - cron = @crontype.create( - :command => "/bin/date > /dev/null", - :minute => [0, 30], - :name => "crontest", - :provider => provider.name - ) - } - - - cron.provider.ensure = :present - cron.provider.command = '/bin/date > /dev/null' - cron.provider.minute = %w{0 30} - cron.provider.class.prefetch - currentvalue = cron.retrieve - - currentvalue.each do |prop, value| - # We're only interested in comparing minutes. - next unless prop.name.to_s == "minute" - assert(prop.insync?(value), "Property %s is not considered in sync with value %s" % [prop.name, value.inspect]) - end - @crontype.clear - end - end - - def test_fieldremoval - cron = nil - assert_nothing_raised { - cron = @crontype.create( - :command => "/bin/date > /dev/null", - :minute => [0, 30], - :name => "crontest", - :provider => :crontab - ) - } - - assert_events([:cron_created], cron) - cron.provider.class.prefetch - - cron[:minute] = :absent - assert_events([:cron_changed], cron) - - current_values = nil - assert_nothing_raised { - cron.provider.class.prefetch - current_values = cron.retrieve - } - assert_equal(:absent, current_values[cron.property(:minute)]) - end - - def test_listing - # Make a crontab cron for testing - provider = @crontype.provider(:crontab) - return unless provider.suitable? - - ft = provider.filetype - provider.filetype = :ram - cleanup { provider.filetype = ft } - - setme - cron = @crontype.create(:name => "testing", - :minute => [0, 30], - :command => "/bin/testing", - :user => @me - ) - # Write it to our file - assert_apply(cron) - - @crontype.clear - - crons = [] - assert_nothing_raised { - @crontype.instances.each do |cron| - crons << cron - end - } - - crons.each do |cron| - assert_instance_of(@crontype, cron, "Did not receive a real cron object") - assert_instance_of(String, cron.value(:user), - "Cron user is not a string") - end - end - - def verify_failonnouser - assert_raise(Puppet::Error) do - @crontype.retrieve("nosuchuser") - end - end - - def test_divisionnumbers - cron = mkcron("divtest") - cron[:minute] = "*/5" - - assert_apply(cron) - - cron.provider.class.prefetch - currentvalue = cron.retrieve - - assert_equal(["*/5"], currentvalue[cron.property(:minute)]) - end - - def test_ranges - cron = mkcron("rangetest") - cron[:minute] = "2-4" - - assert_apply(cron) - - current_values = nil - assert_nothing_raised { - cron.provider.class.prefetch - current_values = cron.retrieve - } - - assert_equal(["2-4"], current_values[cron.property(:minute)]) - end - - - def provider_set(cron, param, value) - unless param =~ /=$/ - param = "%s=" % param - end - - cron.provider.send(param, value) - end - - def test_value - cron = mkcron("valuetesting", false) - - # First, test the normal properties - [:minute, :hour, :month].each do |param| - cron.newattr(param) - property = cron.property(param) - - assert(property, "Did not get %s property" % param) - - assert_nothing_raised { -# property.is = :absent - provider_set(cron, param, :absent) - } - - val = "*" - assert_equal(val, cron.value(param)) - - # Make sure arrays work, too - provider_set(cron, param, ["1"]) - assert_equal(%w{1}, cron.value(param)) - - # Make sure values get comma-joined - provider_set(cron, param, %w{2 3}) - assert_equal(%w{2 3}, cron.value(param)) - - # Make sure "should" values work, too - cron[param] = "4" - assert_equal(%w{4}, cron.value(param)) - - cron[param] = ["4"] - assert_equal(%w{4}, cron.value(param)) - - cron[param] = ["4", "5"] - assert_equal(%w{4 5}, cron.value(param)) - - provider_set(cron, param, :absent) - assert_equal(%w{4 5}, cron.value(param)) - end - - Puppet[:trace] = false - - # Now make sure that :command works correctly - cron.delete(:command) - cron.newattr(:command) - property = cron.property(:command) - - assert_nothing_raised { - provider_set(cron, :command, :absent) - } - - param = :command - # Make sure arrays work, too - provider_set(cron, param, ["/bin/echo"]) - assert_equal("/bin/echo", cron.value(param)) - - # Make sure values are not comma-joined - provider_set(cron, param, %w{/bin/echo /bin/test}) - assert_equal("/bin/echo", cron.value(param)) - - # Make sure "should" values work, too - cron[param] = "/bin/echo" - assert_equal("/bin/echo", cron.value(param)) - - cron[param] = ["/bin/echo"] - assert_equal("/bin/echo", cron.value(param)) - - cron[param] = %w{/bin/echo /bin/test} - assert_equal("/bin/echo", cron.value(param)) - - provider_set(cron, param, :absent) - assert_equal("/bin/echo", cron.value(param)) - end - - def test_multiple_users - crons = [] - users = ["root", nonrootuser.name] - users.each do |user| - cron = Puppet::Type.type(:cron).create( - :name => "testcron-#{user}", - :user => user, - :command => "/bin/echo", - :minute => [0,30] - ) - crons << cron - - assert_equal(cron.should(:user), cron.should(:target), - "Target was not set correctly for %s" % user) - end - provider = crons[0].provider.class - - assert_apply(*crons) - - users.each do |user| - users.each do |other| - next if user == other - text = provider.target_object(other).read - - assert(text !~ /testcron-#{user}/, - "%s's cron job is in %s's tab" % - [user, other]) - end - end - end - - # Make sure the user stuff defaults correctly. - def test_default_user - crontab = @crontype.provider(:crontab) - if crontab.suitable? - inst = @crontype.create( - :name => "something", :command => "/some/thing", - :provider => :crontab) - assert_equal(Etc.getpwuid(Process.uid).name, inst.should(:user), - "user did not default to current user with crontab") - assert_equal(Etc.getpwuid(Process.uid).name, inst.should(:target), - "target did not default to current user with crontab") - - # Now make a new cron with a user, and make sure it gets copied - # over - inst = @crontype.create(:name => "yay", :command => "/some/thing", - :user => "bin", :provider => :crontab) - assert_equal("bin", inst.should(:target), - "target did not default to user with crontab") - end - end - - # #705 - make sure extra spaces don't screw things up - def test_spaces_in_command - string = "echo multiple spaces" - cron = @crontype.create(:name => "space testing", :command => string) - assert_apply(cron) - - cron.class.clear - cron = @crontype.create(:name => "space testing", :command => string) - - # Now make sure that it's correctly in sync - cron.provider.class.prefetch("testing" => cron) - properties = cron.retrieve - command, result = properties.find { |prop, value| prop.name == :command } - assert_equal(string, result, "Cron did not pick up extra spaces in command") - assert(command.insync?(string), "Command changed with multiple spaces") - end -end - - diff --git a/test/ral/types/exec.rb b/test/ral/types/exec.rb deleted file mode 100755 index e2a3dd9ed..000000000 --- a/test/ral/types/exec.rb +++ /dev/null @@ -1,770 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' - -class TestExec < Test::Unit::TestCase - include PuppetTest - def test_execution - command = nil - output = nil - assert_nothing_raised { - command = Puppet.type(:exec).create( - :command => "/bin/echo" - ) - } - assert_nothing_raised { - command.evaluate - } - assert_events([:executed_command], command) - end - - def test_numvsstring - [0, "0"].each { |val| - Puppet.type(:exec).clear - Puppet.type(:component).clear - command = nil - output = nil - assert_nothing_raised { - command = Puppet.type(:exec).create( - :command => "/bin/echo", - :returns => val - ) - } - assert_events([:executed_command], command) - } - end - - def test_path_or_qualified - command = nil - output = nil - assert_raise(Puppet::Error) { - command = Puppet.type(:exec).create( - :command => "echo" - ) - } - assert_nothing_raised { - command = Puppet.type(:exec).create( - :command => "echo", - :path => "/usr/bin:/bin:/usr/sbin:/sbin" - ) - } - Puppet.type(:exec).clear - assert_nothing_raised { - command = Puppet.type(:exec).create( - :command => "/bin/echo" - ) - } - Puppet.type(:exec).clear - assert_nothing_raised { - command = Puppet.type(:exec).create( - :command => "/bin/echo", - :path => "/usr/bin:/bin:/usr/sbin:/sbin" - ) - } - end - - def test_nonzero_returns - assert_nothing_raised { - command = Puppet.type(:exec).create( - :command => "mkdir /this/directory/does/not/exist", - :path => "/usr/bin:/bin:/usr/sbin:/sbin", - :returns => 1 - ) - } - assert_nothing_raised { - command = Puppet.type(:exec).create( - :command => "touch /etc", - :path => "/usr/bin:/bin:/usr/sbin:/sbin", - :returns => 1 - ) - } - assert_nothing_raised { - command = Puppet.type(:exec).create( - :command => "thiscommanddoesnotexist", - :path => "/usr/bin:/bin:/usr/sbin:/sbin", - :returns => 127 - ) - } - end - - def test_cwdsettings - command = nil - dir = "/tmp" - wd = Dir.chdir(dir) { - Dir.getwd - } - assert_nothing_raised { - command = Puppet.type(:exec).create( - :command => "pwd", - :cwd => dir, - :path => "/usr/bin:/bin:/usr/sbin:/sbin", - :returns => 0 - ) - } - assert_events([:executed_command], command) - assert_equal(wd,command.output.chomp) - end - - def test_refreshonly_functional - file = nil - cmd = nil - tmpfile = tempfile() - @@tmpfiles.push tmpfile - trans = nil - file = Puppet.type(:file).create( - :path => tmpfile, - :content => "yay" - ) - # Get the file in sync - assert_apply(file) - - # Now make an exec - maker = tempfile() - assert_nothing_raised { - cmd = Puppet.type(:exec).create( - :command => "touch %s" % maker, - :path => "/usr/bin:/bin:/usr/sbin:/sbin", - :subscribe => file, - :refreshonly => true - ) - } - - assert(cmd, "did not make exec") - - assert_nothing_raised do - assert(! cmd.check, "Check passed when refreshonly is set") - end - - assert_events([], file, cmd) - assert(! FileTest.exists?(maker), "made file without refreshing") - - # Now change our content, so we throw a refresh - file[:content] = "yayness" - assert_events([:file_changed, :triggered], file, cmd) - assert(FileTest.exists?(maker), "file was not made in refresh") - end - - def test_refreshonly - cmd = true - assert_nothing_raised { - cmd = Puppet.type(:exec).create( - :command => "pwd", - :path => "/usr/bin:/bin:/usr/sbin:/sbin", - :refreshonly => true - ) - } - - # Checks should always fail when refreshonly is enabled - assert(!cmd.check, "Check passed with refreshonly true") - - # Now make sure it passes if we pass in "true" - assert(cmd.check(true), "Check failed with refreshonly true while refreshing") - - # Now set it to false - cmd[:refreshonly] = false - assert(cmd.check, "Check failed with refreshonly false") - end - - def test_creates - file = tempfile() - exec = nil - assert(! FileTest.exists?(file), "File already exists") - assert_nothing_raised { - exec = Puppet.type(:exec).create( - :command => "touch %s" % file, - :path => "/usr/bin:/bin:/usr/sbin:/sbin", - :creates => file - ) - } - - comp = mk_catalog("createstest", exec) - assert_events([:executed_command], comp, "creates") - assert_events([], comp, "creates") - end - - # Verify that we can download the file that we're going to execute. - def test_retrievethenmkexe - exe = tempfile() - oexe = tempfile() - sh = %x{which sh} - File.open(exe, "w") { |f| f.puts "#!#{sh}\necho yup" } - - file = Puppet.type(:file).create( - :path => oexe, - :source => exe, - :mode => 0755 - ) - - exec = Puppet.type(:exec).create( - :command => oexe, - :require => [:file, oexe] - ) - - comp = mk_catalog("Testing", file, exec) - - assert_events([:file_created, :executed_command], comp) - end - - # Verify that we auto-require any managed scripts. - def test_autorequire_files - exe = tempfile() - oexe = tempfile() - sh = %x{which sh} - File.open(exe, "w") { |f| f.puts "#!#{sh}\necho yup" } - - file = Puppet.type(:file).create( - :path => oexe, - :source => exe, - :mode => 755 - ) - - basedir = File.dirname(oexe) - baseobj = Puppet.type(:file).create( - :path => basedir, - :source => exe, - :mode => 755 - ) - - ofile = Puppet.type(:file).create( - :path => exe, - :mode => 755 - ) - - exec = Puppet.type(:exec).create( - :command => oexe, - :path => ENV["PATH"], - :cwd => basedir - ) - - cat = Puppet.type(:exec).create( - :command => "cat %s %s" % [exe, oexe], - :path => ENV["PATH"] - ) - - rels = nil - assert_nothing_raised do - rels = exec.autorequire - end - - # Verify we get the script itself - assert(rels.detect { |r| r.source == file }, "Exec did not autorequire its command") - - # Verify we catch the cwd - assert(rels.detect { |r| r.source == baseobj }, "Exec did not autorequire its cwd") - - # Verify we don't require ourselves - assert(! rels.detect { |r| r.source == ofile }, "Exec incorrectly required mentioned file") - assert(!exec.requires?(ofile), "Exec incorrectly required file") - - # We not longer autorequire inline files - assert_nothing_raised do - rels = cat.autorequire - end - assert(! rels.detect { |r| r.source == ofile }, "Exec required second inline file") - assert(! rels.detect { |r| r.source == file }, "Exec required inline file") - end - - def test_ifonly - afile = tempfile() - bfile = tempfile() - - exec = nil - assert_nothing_raised { - exec = Puppet.type(:exec).create( - :command => "touch %s" % bfile, - :onlyif => "test -f %s" % afile, - :path => ENV['PATH'] - ) - } - - assert_events([], exec) - system("touch %s" % afile) - assert_events([:executed_command], exec) - assert_events([:executed_command], exec) - system("rm %s" % afile) - assert_events([], exec) - end - - def test_unless - afile = tempfile() - bfile = tempfile() - - exec = nil - assert_nothing_raised { - exec = Puppet.type(:exec).create( - :command => "touch %s" % bfile, - :unless => "test -f %s" % afile, - :path => ENV['PATH'] - ) - } - comp = mk_catalog(exec) - - assert_events([:executed_command], comp) - assert_events([:executed_command], comp) - system("touch %s" % afile) - assert_events([], comp) - assert_events([], comp) - system("rm %s" % afile) - assert_events([:executed_command], comp) - assert_events([:executed_command], comp) - end - - if Puppet::Util::SUIDManager.uid == 0 - # Verify that we can execute commands as a special user - def mknverify(file, user, group = nil, id = true) - File.umask(0022) - - args = { - :command => "touch %s" % file, - :path => "/usr/bin:/bin:/usr/sbin:/sbin", - } - - if user - #Puppet.warning "Using user %s" % user.name - if id - # convert to a string, because that's what the object expects - args[:user] = user.uid.to_s - else - args[:user] = user.name - end - end - - if group - #Puppet.warning "Using group %s" % group.name - if id - args[:group] = group.gid.to_s - else - args[:group] = group.name - end - end - exec = nil - assert_nothing_raised { - exec = Puppet.type(:exec).create(args) - } - - comp = mk_catalog("usertest", exec) - assert_events([:executed_command], comp, "usertest") - - assert(FileTest.exists?(file), "File does not exist") - if user - assert_equal(user.uid, File.stat(file).uid, "File UIDs do not match") - end - - # We can't actually test group ownership, unfortunately, because - # behaviour changes wildlly based on platform. - Puppet::Type.allclear - end - - def test_userngroup - file = tempfile() - [ - [nonrootuser()], # just user, by name - [nonrootuser(), nil, true], # user, by uid - [nil, nonrootgroup()], # just group - [nil, nonrootgroup(), true], # just group, by id - [nonrootuser(), nonrootgroup()], # user and group, by name - [nonrootuser(), nonrootgroup(), true], # user and group, by id - ].each { |ary| - mknverify(file, *ary) { - } - } - end - end - - def test_logoutput - exec = nil - assert_nothing_raised { - exec = Puppet.type(:exec).create( - :title => "logoutputesting", - :path => "/usr/bin:/bin", - :command => "echo logoutput is false", - :logoutput => false - ) - } - - assert_apply(exec) - - assert_nothing_raised { - exec[:command] = "echo logoutput is true" - exec[:logoutput] = true - } - - assert_apply(exec) - - assert_nothing_raised { - exec[:command] = "echo logoutput is on_failure" - exec[:logoutput] = "on_failure" - } - - assert_apply(exec) - end - - def test_execthenfile - exec = nil - file = nil - basedir = tempfile() - path = File.join(basedir, "subfile") - assert_nothing_raised { - exec = Puppet.type(:exec).create( - :title => "mkdir", - :path => "/usr/bin:/bin", - :creates => basedir, - :command => "mkdir %s; touch %s" % [basedir, path] - - ) - } - - assert_nothing_raised { - file = Puppet.type(:file).create( - :path => basedir, - :recurse => true, - :mode => "755", - :require => ["exec", "mkdir"] - ) - } - - comp = mk_catalog(file, exec) - comp.finalize - assert_events([:executed_command, :file_changed], comp) - - assert(FileTest.exists?(path), "Exec ran first") - assert(File.stat(path).mode & 007777 == 0755) - end - - # Make sure all checks need to be fully qualified. - def test_falsevals - exec = nil - assert_nothing_raised do - exec = Puppet.type(:exec).create( - :command => "/bin/touch yayness" - ) - end - - Puppet.type(:exec).checks.each do |check| - klass = Puppet.type(:exec).paramclass(check) - next if klass.values.include? :false - assert_raise(Puppet::Error, "Check '%s' did not fail on false" % check) do - exec[check] = false - end - end - end - - def test_createcwdandexe - exec1 = exec2 = nil - dir = tempfile() - file = tempfile() - - assert_nothing_raised { - exec1 = Puppet.type(:exec).create( - :title => "one", - :path => ENV["PATH"], - :command => "mkdir #{dir}" - ) - } - - assert_nothing_raised("Could not create exec w/out existing cwd") { - exec2 = Puppet.type(:exec).create( - :title => "two", - :path => ENV["PATH"], - :command => "touch #{file}", - :cwd => dir - ) - } - - # Throw a check in there with our cwd and make sure it works - assert_nothing_raised("Could not check with a missing cwd") do - exec2[:unless] = "test -f /this/file/does/not/exist" - exec2.retrieve - end - - assert_raise(Puppet::Error) do - exec2.property(:returns).sync - end - - assert_nothing_raised do - exec2[:require] = exec1 - end - - assert_apply(exec1, exec2) - - assert(FileTest.exists?(file)) - end - - def test_checkarrays - exec = nil - file = tempfile() - - test = "test -f #{file}" - - assert_nothing_raised { - exec = Puppet.type(:exec).create( - :path => ENV["PATH"], - :command => "touch #{file}" - ) - } - - assert_nothing_raised { - exec[:unless] = test - } - - assert_nothing_raised { - assert(exec.check, "Check did not pass") - } - - assert_nothing_raised { - exec[:unless] = [test, test] - } - - - assert_nothing_raised { - exec.finish - } - - assert_nothing_raised { - assert(exec.check, "Check did not pass") - } - - assert_apply(exec) - - assert_nothing_raised { - assert(! exec.check, "Check passed") - } - end - - def test_missing_checks_cause_failures - # Solaris's sh exits with 1 here instead of 127 - return if Facter.value(:operatingsystem) == "Solaris" - exec = Puppet::Type.type(:exec).create( - :command => "echo true", - :path => ENV["PATH"], - :onlyif => "/bin/nosuchthingexists" - ) - - assert_raise(ArgumentError, "Missing command did not raise error") { - exec.run("/bin/nosuchthingexists") - } - end - - def test_envparam - exec = Puppet::Type.newexec( - :command => "echo $envtest", - :path => ENV["PATH"], - :env => "envtest=yayness" - ) - - assert(exec, "Could not make exec") - - output = status = nil - assert_nothing_raised { - output, status = exec.run("echo $envtest") - } - - assert_equal("yayness\n", output) - - # Now check whether we can do multiline settings - assert_nothing_raised do - exec[:env] = "envtest=a list of things -and stuff" - end - - output = status = nil - assert_nothing_raised { - output, status = exec.run('echo "$envtest"') - } - assert_equal("a list of things\nand stuff\n", output) - - # Now test arrays - assert_nothing_raised do - exec[:env] = ["funtest=A", "yaytest=B"] - end - - output = status = nil - assert_nothing_raised { - output, status = exec.run('echo "$funtest" "$yaytest"') - } - assert_equal("A B\n", output) - end - - def test_environmentparam - exec = Puppet::Type.newexec( - :command => "echo $environmenttest", - :path => ENV["PATH"], - :environment => "environmenttest=yayness" - ) - - assert(exec, "Could not make exec") - - output = status = nil - assert_nothing_raised { - output, status = exec.run("echo $environmenttest") - } - - assert_equal("yayness\n", output) - - # Now check whether we can do multiline settings - assert_nothing_raised do - exec[:environment] = "environmenttest=a list of things -and stuff" - end - - output = status = nil - assert_nothing_raised { - output, status = exec.run('echo "$environmenttest"') - } - assert_equal("a list of things\nand stuff\n", output) - - # Now test arrays - assert_nothing_raised do - exec[:environment] = ["funtest=A", "yaytest=B"] - end - - output = status = nil - assert_nothing_raised { - output, status = exec.run('echo "$funtest" "$yaytest"') - } - assert_equal("A B\n", output) - end - - def test_timeout - exec = Puppet::Type.type(:exec).create(:command => "sleep 1", :path => ENV["PATH"], :timeout => "0.2") - time = Time.now - - assert_raise(Timeout::Error) { - exec.run("sleep 1") - } - Puppet.info "%s seconds, vs a timeout of %s" % [Time.now.to_f - time.to_f, exec[:timeout]] - - - assert_apply(exec) - end - - # Testing #470 - def test_run_as_created_user - exec = nil - if Process.uid == 0 - user = "nosuchuser" - assert_nothing_raised("Could not create exec with non-existent user") do - exec = Puppet::Type.type(:exec).create( - :command => "/bin/echo yay", - :user => user - ) - end - end - - # Now try the group - group = "nosuchgroup" - assert_nothing_raised("Could not create exec with non-existent user") do - exec = Puppet::Type.type(:exec).create( - :command => "/bin/echo yay", - :group => group - ) - end - end - - # make sure paths work both as arrays and strings - def test_paths_as_arrays - path = %w{/usr/bin /usr/sbin /sbin} - exec = nil - assert_nothing_raised("Could not use an array for the path") do - exec = Puppet::Type.type(:exec).create(:command => "echo yay", - :path => path) - end - assert_equal(path, exec[:path], "array-based path did not match") - assert_nothing_raised("Could not use a string for the path") do - exec = Puppet::Type.type(:exec).create(:command => "echo yay", - :path => path.join(":")) - end - assert_equal(path, exec[:path], "string-based path did not match") - assert_nothing_raised("Could not use a colon-separated strings in an array for the path") do - exec = Puppet::Type.type(:exec).create(:command => "echo yay", - :path => ["/usr/bin", "/usr/sbin:/sbin"]) - end - assert_equal(path, exec[:path], "colon-separated array path did not match") - end - - def test_checks_apply_to_refresh - file = tempfile() - maker = tempfile() - exec = Puppet::Type.type(:exec).create( - :title => "maker", - :command => "touch #{maker}", - :path => ENV["PATH"] - ) - - # Make sure it runs normally - assert_apply(exec) - assert(FileTest.exists?(maker), "exec did not run") - File.unlink(maker) - - # Now make sure it refreshes - assert_nothing_raised("Failed to refresh exec") do - exec.refresh - end - assert(FileTest.exists?(maker), "exec did not run refresh") - File.unlink(maker) - - # Now add the checks - exec[:creates] = file - - # Make sure it runs when the file doesn't exist - assert_nothing_raised("Failed to refresh exec") do - exec.refresh - end - assert(FileTest.exists?(maker), "exec did not refresh when checks passed") - File.unlink(maker) - - # Now create the file and make sure it doesn't refresh - File.open(file, "w") { |f| f.puts "" } - assert_nothing_raised("Failed to refresh exec") do - exec.refresh - end - assert(! FileTest.exists?(maker), "exec refreshed with failing checks") - end - - def test_explicit_refresh - refresher = tempfile() - maker = tempfile() - exec = Puppet::Type.type(:exec).create( - :title => "maker", - :command => "touch #{maker}", - :path => ENV["PATH"] - ) - - # Call refresh normally - assert_nothing_raised do - exec.refresh - end - - # Make sure it created the normal file - assert(FileTest.exists?(maker), "normal refresh did not work") - File.unlink(maker) - - # Now reset refresh, and make sure it wins - assert_nothing_raised("Could not set refresh parameter") do - exec[:refresh] = "touch #{refresher}" - end - assert_nothing_raised do - exec.refresh - end - - # Make sure it created the normal file - assert(FileTest.exists?(refresher), "refresh param was ignored") - assert(! FileTest.exists?(maker), "refresh param also ran command") - end - - if Puppet.features.root? - def test_autorequire_user - user = Puppet::Type.type(:user).create(:name => "yay") - exec = Puppet::Type.type(:exec).create(:command => "/bin/echo fun", :user => "yay") - - rels = nil - assert_nothing_raised("Could not evaluate autorequire") do - rels = exec.autorequire - end - assert(rels.find { |r| r.source == user and r.target == exec }, "Exec did not autorequire user") - end - end -end - diff --git a/test/ral/types/file.rb b/test/ral/types/file.rb deleted file mode 100755 index cbbe818ae..000000000 --- a/test/ral/types/file.rb +++ /dev/null @@ -1,1782 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' -require 'puppettest/support/utils' -require 'fileutils' - -class TestFile < Test::Unit::TestCase - include PuppetTest::Support::Utils - include PuppetTest::FileTesting - - def mkfile(hash) - file = nil - assert_nothing_raised { - file = Puppet.type(:file).create(hash) - } - return file - end - - def mktestfile - tmpfile = tempfile() - File.open(tmpfile, "w") { |f| f.puts rand(100) } - @@tmpfiles.push tmpfile - mkfile(:name => tmpfile) - end - - def setup - super - @file = Puppet::Type.type(:file) - $method = @method_name - Puppet[:filetimeout] = -1 - end - - def teardown - Puppet::Util::Storage.clear - system("rm -rf %s" % Puppet[:statefile]) - super - end - - def initstorage - Puppet::Util::Storage.init - Puppet::Util::Storage.load - end - - def clearstorage - Puppet::Util::Storage.store - Puppet::Util::Storage.clear - end - - def test_owner - file = mktestfile() - - users = {} - count = 0 - - # collect five users - Etc.passwd { |passwd| - if count > 5 - break - else - count += 1 - end - users[passwd.uid] = passwd.name - } - - fake = {} - # find a fake user - while true - a = rand(1000) - begin - Etc.getpwuid(a) - rescue - fake[a] = "fakeuser" - break - end - end - - uid, name = users.shift - us = {} - us[uid] = name - users.each { |uid, name| - assert_apply(file) - assert_nothing_raised() { - file[:owner] = name - } - assert_nothing_raised() { - file.retrieve - } - assert_apply(file) - } - end - - def test_group - file = mktestfile() - [%x{groups}.chomp.split(/ /), Process.groups].flatten.each { |group| - assert_nothing_raised() { - file[:group] = group - } - assert(file.property(:group)) - assert(file.property(:group).should) - } - end - - def test_groups_fails_when_invalid - assert_raise(Puppet::Error, "did not fail when the group was empty") do - Puppet::Type.type(:file).create :path => "/some/file", :group => "" - end - end - - if Puppet::Util::SUIDManager.uid == 0 - def test_createasuser - dir = tmpdir() - - user = nonrootuser() - path = File.join(tmpdir, "createusertesting") - @@tmpfiles << path - - file = nil - assert_nothing_raised { - file = Puppet.type(:file).create( - :path => path, - :owner => user.name, - :ensure => "file", - :mode => "755" - ) - } - - comp = mk_catalog("createusertest", file) - - assert_events([:file_created], comp) - end - - def test_nofollowlinks - basedir = tempfile() - Dir.mkdir(basedir) - file = File.join(basedir, "file") - link = File.join(basedir, "link") - - File.open(file, "w", 0644) { |f| f.puts "yayness"; f.flush } - File.symlink(file, link) - - # First test 'user' - user = nonrootuser() - - inituser = File.lstat(link).uid - File.lchown(inituser, nil, link) - - obj = nil - assert_nothing_raised { - obj = Puppet.type(:file).create( - :title => link, - :owner => user.name - ) - } - obj.retrieve - - # Make sure it defaults to managing the link - assert_events([:file_changed], obj) - assert_equal(user.uid, File.lstat(link).uid) - assert_equal(inituser, File.stat(file).uid) - File.chown(inituser, nil, file) - File.lchown(inituser, nil, link) - - # Try following - obj[:links] = :follow - assert_events([:file_changed], obj) - assert_equal(user.uid, File.stat(file).uid) - assert_equal(inituser, File.lstat(link).uid) - - # And then explicitly managing - File.chown(inituser, nil, file) - File.lchown(inituser, nil, link) - obj[:links] = :manage - assert_events([:file_changed], obj) - assert_equal(user.uid, File.lstat(link).uid) - assert_equal(inituser, File.stat(file).uid) - - obj.delete(:owner) - obj[:links] = :follow - - # And then test 'group' - group = nonrootgroup - - initgroup = File.stat(file).gid - obj[:group] = group.name - - assert_events([:file_changed], obj) - assert_equal(initgroup, File.stat(file).gid) - assert_equal(group.gid, File.lstat(link).gid) - File.chown(nil, initgroup, file) - File.lchown(nil, initgroup, link) - - obj[:links] = :follow - assert_events([:file_changed], obj) - assert_equal(group.gid, File.stat(file).gid) - File.chown(nil, initgroup, file) - File.lchown(nil, initgroup, link) - - obj[:links] = :manage - assert_events([:file_changed], obj) - assert_equal(group.gid, File.lstat(link).gid) - assert_equal(initgroup, File.stat(file).gid) - end - - def test_ownerasroot - file = mktestfile() - - users = {} - count = 0 - - # collect five users - Etc.passwd { |passwd| - if count > 5 - break - else - count += 1 - end - next if passwd.uid < 0 - users[passwd.uid] = passwd.name - } - - fake = {} - # find a fake user - while true - a = rand(1000) - begin - Etc.getpwuid(a) - rescue - fake[a] = "fakeuser" - break - end - end - - users.each { |uid, name| - assert_nothing_raised() { - file[:owner] = name - } - changes = [] - assert_nothing_raised() { - changes << file.evaluate - } - assert(changes.length > 0) - assert_apply(file) - currentvalue = file.retrieve - assert(file.insync?(currentvalue)) - assert_nothing_raised() { - file[:owner] = uid - } - assert_apply(file) - currentvalue = file.retrieve - # make sure changing to number doesn't cause a sync - assert(file.insync?(currentvalue)) - } - - # We no longer raise an error here, because we check at run time - #fake.each { |uid, name| - # assert_raise(Puppet::Error) { - # file[:owner] = name - # } - # assert_raise(Puppet::Error) { - # file[:owner] = uid - # } - #} - end - - def test_groupasroot - file = mktestfile() - [%x{groups}.chomp.split(/ /), Process.groups].flatten.each { |group| - next unless Puppet::Util.gid(group) # grr. - assert_nothing_raised() { - file[:group] = group - } - assert(file.property(:group)) - assert(file.property(:group).should) - assert_apply(file) - currentvalue = file.retrieve - assert(file.insync?(currentvalue)) - assert_nothing_raised() { - file.delete(:group) - } - } - end - - if Facter.value(:operatingsystem) == "Darwin" - def test_sillyowner - file = tempfile() - File.open(file, "w") { |f| f.puts "" } - File.chown(-2, nil, file) - - assert(File.stat(file).uid > 120000, "eh?") - user = nonrootuser - obj = Puppet::Type.newfile( - :path => file, - :owner => user.name - ) - - assert_apply(obj) - - assert_equal(user.uid, File.stat(file).uid) - end - end - else - $stderr.puts "Run as root for complete owner and group testing" - end - - def test_create - %w{a b c d}.collect { |name| tempfile() + name.to_s }.each { |path| - file =nil - assert_nothing_raised() { - file = Puppet.type(:file).create( - :name => path, - :ensure => "file" - ) - } - assert_events([:file_created], file) - assert_events([], file) - assert(FileTest.file?(path), "File does not exist") - assert(file.insync?(file.retrieve)) - @@tmpfiles.push path - } - end - - def test_create_dir - basedir = tempfile() - Dir.mkdir(basedir) - %w{a b c d}.collect { |name| "#{basedir}/%s" % name }.each { |path| - file = nil - assert_nothing_raised() { - file = Puppet.type(:file).create( - :name => path, - :ensure => "directory" - ) - } - assert(! FileTest.directory?(path), "Directory %s already exists" % - [path]) - assert_events([:directory_created], file) - assert_events([], file) - assert(file.insync?(file.retrieve)) - assert(FileTest.directory?(path)) - @@tmpfiles.push path - } - end - - def test_modes - file = mktestfile - # Set it to something else initially - File.chmod(0775, file.title) - [0644,0755,0777,0641].each { |mode| - assert_nothing_raised() { - file[:mode] = mode - } - assert_events([:file_changed], file) - assert_events([], file) - - assert(file.insync?(file.retrieve)) - - assert_nothing_raised() { - file.delete(:mode) - } - } - end - - def test_checksums - types = %w{md5 md5lite timestamp time} - exists = "/tmp/sumtest-exists" - nonexists = "/tmp/sumtest-nonexists" - - @@tmpfiles << exists - @@tmpfiles << nonexists - - # try it both with files that exist and ones that don't - files = [exists, nonexists] - initstorage - File.open(exists,File::CREAT|File::TRUNC|File::WRONLY) { |of| - of.puts "initial text" - } - types.each { |type| - files.each { |path| - if Puppet[:debug] - Puppet.warning "Testing %s on %s" % [type,path] - end - file = nil - events = nil - # okay, we now know that we have a file... - assert_nothing_raised() { - file = Puppet.type(:file).create( - :name => path, - :ensure => "file", - :checksum => type - ) - } - trans = nil - - currentvalues = file.retrieve - - if file.title !~ /nonexists/ - sum = file.property(:checksum) - assert(sum.insync?(currentvalues[sum]), "file is not in sync") - end - - events = assert_apply(file) - - assert(events) - - assert(! events.include?(:file_changed), "File incorrectly changed") - assert_events([], file) - - # We have to sleep because the time resolution of the time-based - # mechanisms is greater than one second - sleep 1 if type =~ /time/ - - assert_nothing_raised() { - File.open(path,File::CREAT|File::TRUNC|File::WRONLY) { |of| - of.puts "some more text, yo" - } - } - Puppet.type(:file).clear - - # now recreate the file - assert_nothing_raised() { - file = Puppet.type(:file).create( - :name => path, - :checksum => type - ) - } - trans = nil - - assert_events([:file_changed], file) - - # Run it a few times to make sure we aren't getting - # spurious changes. - sum = nil - assert_nothing_raised do - sum = file.property(:checksum).retrieve - end - assert(file.property(:checksum).insync?(sum), - "checksum is not in sync") - - sleep 1.1 if type =~ /time/ - assert_nothing_raised() { - File.unlink(path) - File.open(path,File::CREAT|File::TRUNC|File::WRONLY) { |of| - # We have to put a certain amount of text in here or - # the md5-lite test fails - 2.times { - of.puts rand(100) - } - of.flush - } - } - assert_events([:file_changed], file) - - # verify that we're actually getting notified when a file changes - assert_nothing_raised() { - Puppet.type(:file).clear - } - - if path =~ /nonexists/ - File.unlink(path) - end - } - } - end - - def cyclefile(path) - # i had problems with using :name instead of :path - [:name,:path].each { |param| - file = nil - changes = nil - comp = nil - trans = nil - - initstorage - assert_nothing_raised { - file = Puppet.type(:file).create( - param => path, - :recurse => true, - :checksum => "md5" - ) - } - comp = Puppet.type(:component).create( - :name => "component" - ) - comp.push file - assert_nothing_raised { - trans = comp.evaluate - } - assert_nothing_raised { - trans.evaluate - } - clearstorage - Puppet::Type.allclear - } - end - - def test_localrecurse - # Create a test directory - path = tempfile() - dir = @file.create :path => path, :mode => 0755, :recurse => true - config = mk_catalog(dir) - - Dir.mkdir(path) - - # Make sure we return nothing when there are no children - ret = nil - assert_nothing_raised() { ret = dir.localrecurse(true) } - assert_equal([], ret, "empty dir returned children") - - # Now make a file and make sure we get it - test = File.join(path, "file") - File.open(test, "w") { |f| f.puts "yay" } - assert_nothing_raised() { ret = dir.localrecurse(true) } - fileobj = @file[test] - assert(fileobj, "child object was not created") - assert_equal([fileobj], ret, "child object was not returned") - - # And that it inherited our recurse setting - assert_equal(true, fileobj[:recurse], "file did not inherit recurse") - - # Make sure it's not returned again - assert_nothing_raised() { ret = dir.localrecurse(true) } - assert_equal([], ret, "child object was returned twice") - - # Now just for completion, make sure we will return many files - files = [] - 10.times do |i| - f = File.join(path, i.to_s) - files << f - File.open(f, "w") do |o| o.puts "" end - end - assert_nothing_raised() { ret = dir.localrecurse(true) } - assert_equal(files.sort, ret.collect { |f| f.title }.sort, - "child object was returned twice") - - # Clean everything up and start over - files << test - files.each do |f| File.unlink(f) end - - # Now make sure we correctly ignore things - dir[:ignore] = "*.out" - bad = File.join(path, "test.out") - good = File.join(path, "yayness") - [good, bad].each do |f| - File.open(f, "w") { |o| o.puts "" } - end - - assert_nothing_raised() { ret = dir.localrecurse(true) } - assert_equal([good], ret.collect { |f| f.title }, "ignore failed") - - # Now make sure purging works - dir[:purge] = true - dir[:ignore] = "svn" - - assert_nothing_raised() { ret = dir.localrecurse(true) } - assert_equal([bad], ret.collect { |f| f.title }, "purge failed") - - badobj = @file[bad] - assert(badobj, "did not create bad object") - end - - def test_recurse - basedir = tempfile() - FileUtils.mkdir_p(basedir) - - # Create our file - dir = nil - assert_nothing_raised { - dir = Puppet.type(:file).create( - :path => basedir, - :check => %w{owner mode group} - ) - } - - return_nil = false - - # and monkey-patch it - [:localrecurse, :linkrecurse].each do |m| - dir.meta_def(m) do |recurse| - if return_nil # for testing nil return, of course - return nil - else - return [recurse] - end - end - end - - # We have to special-case this, because it returns a list of - # found files. - dir.meta_def(:sourcerecurse) do |recurse| - if return_nil # for testing nil return, of course - return nil - else - return [recurse], [] - end - end - - # First try it with recurse set to false - dir[:recurse] = false - assert_nothing_raised do - assert_nil(dir.recurse) - end - - # Now try it with the different valid positive values - [true, "true", "inf", 50].each do |value| - assert_nothing_raised { dir[:recurse] = value} - - # Now make sure the methods are called appropriately - ret = nil - assert_nothing_raised do - ret = dir.recurse - end - - # We should only call the localrecurse method, so make sure - # that's the case - if value == 50 - # Make sure our counter got decremented - assert_equal([49], ret, "did not call localrecurse") - else - assert_equal([true], ret, "did not call localrecurse") - end - end - - # Make sure it doesn't recurse when we've set recurse to false - [false, "false"].each do |value| - assert_nothing_raised { dir[:recurse] = value } - - ret = nil - assert_nothing_raised() { ret = dir.recurse } - assert_nil(ret) - end - dir[:recurse] = true - - # Now add a target, so we do the linking thing - dir[:target] = tempfile() - ret = nil - assert_nothing_raised { ret = dir.recurse } - assert_equal([true, true], ret, "did not call linkrecurse") - - # And add a source, and make sure we call that - dir[:source] = tempfile() - assert_nothing_raised { ret = dir.recurse } - assert_equal([true, true, true], ret, "did not call linkrecurse") - - # Lastly, make sure we correctly handle returning nil - return_nil = true - assert_nothing_raised { ret = dir.recurse } - end - - def test_recurse? - file = Puppet::Type.type(:file).create :path => tempfile - - # Make sure we default to false - assert(! file.recurse?, "Recurse defaulted to true") - - [true, "true", 10, "inf"].each do |value| - file[:recurse] = value - assert(file.recurse?, "%s did not cause recursion" % value) - end - - [false, "false", 0].each do |value| - file[:recurse] = value - assert(! file.recurse?, "%s caused recursion" % value) - end - end - - def test_recursion - basedir = tempfile() - subdir = File.join(basedir, "subdir") - tmpfile = File.join(basedir,"testing") - FileUtils.mkdir_p(subdir) - - dir = nil - [true, "true", "inf", 50].each do |value| - assert_nothing_raised { - dir = Puppet.type(:file).create( - :path => basedir, - :recurse => value, - :check => %w{owner mode group} - ) - } - config = mk_catalog dir - - children = nil - - assert_nothing_raised { - children = dir.eval_generate - } - - assert_equal([subdir], children.collect {|c| c.title }, - "Incorrect generated children") - - # Remove our subdir resource, - subdir_resource = config.resource(:file, subdir) - config.remove_resource(subdir_resource) - - # Create the test file - File.open(tmpfile, "w") { |f| f.puts "yayness" } - - assert_nothing_raised { - children = dir.eval_generate - } - - # And make sure we get both resources back. - assert_equal([subdir, tmpfile].sort, children.collect {|c| c.title }.sort, - "Incorrect generated children when recurse == %s" % value.inspect) - - File.unlink(tmpfile) - Puppet.type(:file).clear - end - end - - def test_filetype_retrieval - file = nil - - # Verify it retrieves files of type directory - assert_nothing_raised { - file = Puppet.type(:file).create( - :name => tmpdir(), - :check => :type - ) - } - - assert_nothing_raised { - file.evaluate - } - - assert_equal("directory", file.property(:type).retrieve) - - # And then check files - assert_nothing_raised { - file = Puppet.type(:file).create( - :name => tempfile(), - :ensure => "file" - ) - } - - assert_apply(file) - file[:check] = "type" - assert_apply(file) - - assert_equal("file", file.property(:type).retrieve) - - file[:type] = "directory" - - currentvalues = {} - assert_nothing_raised { currentvalues = file.retrieve } - - # The 'retrieve' method sets @should to @is, so they're never - # out of sync. It's a read-only class. - assert(file.insync?(currentvalues)) - end - - def test_remove - basedir = tempfile() - subdir = File.join(basedir, "this") - FileUtils.mkdir_p(subdir) - - dir = nil - assert_nothing_raised { - dir = Puppet.type(:file).create( - :path => basedir, - :recurse => true, - :check => %w{owner mode group} - ) - } - mk_catalog dir - - assert_nothing_raised { - dir.eval_generate - } - - obj = nil - assert_nothing_raised { - obj = Puppet.type(:file)[subdir] - } - - assert(obj, "Could not retrieve subdir object") - - assert_nothing_raised { - obj.remove(true) - } - - assert_nothing_raised { - obj = Puppet.type(:file)[subdir] - } - - assert_nil(obj, "Retrieved removed object") - end - - def test_path - dir = tempfile() - - path = File.join(dir, "subdir") - - assert_nothing_raised("Could not make file") { - FileUtils.mkdir_p(File.dirname(path)) - File.open(path, "w") { |f| f.puts "yayness" } - } - - file = nil - dirobj = nil - assert_nothing_raised("Could not make file object") { - dirobj = Puppet.type(:file).create( - :path => dir, - :recurse => true, - :check => %w{mode owner group} - ) - } - mk_catalog dirobj - - assert_nothing_raised { - dirobj.eval_generate - } - - assert_nothing_raised { - file = dirobj.class[path] - } - - assert(file, "Could not retrieve file object") - - assert_equal("/%s" % file.ref, file.path) - end - - def test_autorequire - basedir = tempfile() - subfile = File.join(basedir, "subfile") - - baseobj = Puppet.type(:file).create( - :name => basedir, - :ensure => "directory" - ) - - subobj = Puppet.type(:file).create( - :name => subfile, - :ensure => "file" - ) - edge = nil - assert_nothing_raised do - edge = subobj.autorequire.shift - end - assert_equal(baseobj, edge.source, "file did not require its parent dir") - assert_equal(subobj, edge.target, "file did not require its parent dir") - end - - def test_content - file = tempfile() - str = "This is some content" - - obj = nil - assert_nothing_raised { - obj = Puppet.type(:file).create( - :name => file, - :content => str - ) - } - - assert(!obj.insync?(obj.retrieve), "Object is incorrectly in sync") - - assert_events([:file_created], obj) - - currentvalues = obj.retrieve - - assert(obj.insync?(currentvalues), "Object is not in sync") - - text = File.read(file) - - assert_equal(str, text, "Content did not copy correctly") - - newstr = "Another string, yo" - - obj[:content] = newstr - - assert(!obj.insync?(obj.retrieve), "Object is incorrectly in sync") - - assert_events([:file_changed], obj) - - text = File.read(file) - - assert_equal(newstr, text, "Content did not copy correctly") - - currentvalues = obj.retrieve - assert(obj.insync?(currentvalues), "Object is not in sync") - end - - # Unfortunately, I know this fails - def disabled_test_recursivemkdir - path = tempfile() - subpath = File.join(path, "this", "is", "a", "dir") - file = nil - assert_nothing_raised { - file = Puppet.type(:file).create( - :name => subpath, - :ensure => "directory", - :recurse => true - ) - } - - comp = mk_catalog("yay", file) - comp.finalize - assert_apply(comp) - #assert_events([:directory_created], comp) - - assert(FileTest.directory?(subpath), "Did not create directory") - end - - # Make sure that content updates the checksum on the same run - def test_checksumchange_for_content - dest = tempfile() - File.open(dest, "w") { |f| f.puts "yayness" } - - file = nil - assert_nothing_raised { - file = Puppet.type(:file).create( - :name => dest, - :checksum => "md5", - :content => "This is some content" - ) - } - - file.retrieve - - assert_events([:file_changed], file) - file.retrieve - assert_events([], file) - end - - # Make sure that content updates the checksum on the same run - def test_checksumchange_for_ensure - dest = tempfile() - - file = nil - assert_nothing_raised { - file = Puppet.type(:file).create( - :name => dest, - :checksum => "md5", - :ensure => "file" - ) - } - - file.retrieve - - assert_events([:file_created], file) - file.retrieve - assert_events([], file) - end - - # Make sure that content gets used before ensure - def test_contentbeatsensure - dest = tempfile() - - file = nil - assert_nothing_raised { - file = Puppet.type(:file).create( - :name => dest, - :ensure => "file", - :content => "this is some content, yo" - ) - } - - currentvalues = file.retrieve - - assert_events([:file_created], file) - file.retrieve - assert_events([], file) - assert_events([], file) - end - - # Make sure that content gets used before ensure - def test_deletion_beats_source - dest = tempfile() - source = tempfile() - File.open(source, "w") { |f| f.puts "yay" } - - file = nil - assert_nothing_raised { - file = Puppet.type(:file).create( - :name => dest, - :ensure => :absent, - :source => source - ) - } - - file.retrieve - - assert_events([], file) - assert(! FileTest.exists?(dest), "file was copied during deletion") - - # Now create the dest, and make sure it gets deleted - File.open(dest, "w") { |f| f.puts "boo" } - assert_events([:file_removed], file) - assert(! FileTest.exists?(dest), "file was not deleted during deletion") - end - - def test_nameandpath - path = tempfile() - - file = nil - assert_nothing_raised { - file = Puppet.type(:file).create( - :title => "fileness", - :path => path, - :content => "this is some content" - ) - } - - assert_apply(file) - - assert(FileTest.exists?(path)) - end - - # Make sure that a missing group isn't fatal at object instantiation time. - def test_missinggroup - file = nil - assert_nothing_raised { - file = Puppet.type(:file).create( - :path => tempfile(), - :group => "fakegroup" - ) - } - - assert(file.property(:group), "Group property failed") - end - - def test_modecreation - path = tempfile() - file = Puppet.type(:file).create( - :path => path, - :ensure => "file", - :mode => "0777" - ) - assert_equal(0777, file.should(:mode), - "Mode did not get set correctly") - assert_apply(file) - assert_equal(0777, File.stat(path).mode & 007777, - "file mode is incorrect") - File.unlink(path) - file[:ensure] = "directory" - assert_apply(file) - assert_equal(0777, File.stat(path).mode & 007777, - "directory mode is incorrect") - end - - # If both 'ensure' and 'content' are used, make sure that all of the other - # properties are handled correctly. - def test_contentwithmode - path = tempfile() - - file = nil - assert_nothing_raised { - file = Puppet.type(:file).create( - :path => path, - :ensure => "file", - :content => "some text\n", - :mode => 0755 - ) - } - - assert_apply(file) - assert_equal("%o" % 0755, "%o" % (File.stat(path).mode & 007777)) - end - - def test_backupmodes - File.umask(0022) - - file = tempfile() - newfile = tempfile() - - File.open(file, "w", 0411) { |f| f.puts "yayness" } - - obj = nil - assert_nothing_raised { - obj = Puppet::Type.type(:file).create( - :path => file, :content => "rahness\n", :backup => ".puppet-bak" - ) - } - - assert_apply(obj) - - backupfile = file + obj[:backup] - @@tmpfiles << backupfile - assert(FileTest.exists?(backupfile), - "Backup file %s does not exist" % backupfile) - - assert_equal(0411, filemode(backupfile), - "File mode is wrong for backupfile") - - bucket = "bucket" - bpath = tempfile() - Dir.mkdir(bpath) - Puppet::Type.type(:filebucket).create( - :title => bucket, :path => bpath - ) - - obj[:backup] = bucket - obj[:content] = "New content" - assert_apply(obj) - - md5 = "18cc17fa3047fcc691fdf49c0a7f539a" - dir, file, pathfile = Puppet::Network::Handler.filebucket.paths(bpath, md5) - - assert_equal(0440, filemode(file)) - end - - def test_largefilechanges - source = tempfile() - dest = tempfile() - - # Now make a large file - File.open(source, "w") { |f| - 500.times { |i| f.puts "line %s" % i } - } - - obj = Puppet::Type.type(:file).create( - :title => dest, :source => source - ) - - assert_events([:file_created], obj) - - File.open(source, File::APPEND|File::WRONLY) { |f| f.puts "another line" } - - assert_events([:file_changed], obj) - - # Now modify the dest file - File.open(dest, File::APPEND|File::WRONLY) { |f| f.puts "one more line" } - - assert_events([:file_changed, :file_changed], obj) - - end - - def test_replacefilewithlink - path = tempfile() - link = tempfile() - - File.open(path, "w") { |f| f.puts "yay" } - File.open(link, "w") { |f| f.puts "a file" } - - file = nil - assert_nothing_raised { - file = Puppet.type(:file).create( - :ensure => path, - :path => link - ) - } - - assert_events([:link_created], file) - - assert(FileTest.symlink?(link), "Link was not created") - - assert_equal(path, File.readlink(link), "Link was created incorrectly") - end - - def test_file_with_spaces - dir = tempfile() - Dir.mkdir(dir) - source = File.join(dir, "file spaces") - dest = File.join(dir, "another space") - - File.open(source, "w") { |f| f.puts :yay } - obj = Puppet::Type.type(:file).create( - :path => dest, - :source => source - ) - assert(obj, "Did not create file") - - assert_apply(obj) - - assert(FileTest.exists?(dest), "File did not get created") - end - - def test_present_matches_anything - path = tempfile() - - file = Puppet::Type.newfile(:path => path, :ensure => :present) - - currentvalues = file.retrieve - assert(! file.insync?(currentvalues), "File incorrectly in sync") - - # Now make a file - File.open(path, "w") { |f| f.puts "yay" } - - currentvalues = file.retrieve - assert(file.insync?(currentvalues), "File not in sync") - - # Now make a directory - File.unlink(path) - Dir.mkdir(path) - - currentvalues = file.retrieve - assert(file.insync?(currentvalues), "Directory not considered 'present'") - - Dir.rmdir(path) - - # Now make a link - file[:links] = :manage - - otherfile = tempfile() - File.symlink(otherfile, path) - - currentvalues = file.retrieve - assert(file.insync?(currentvalues), "Symlink not considered 'present'") - File.unlink(path) - - # Now set some content, and make sure it works - file[:content] = "yayness" - - assert_apply(file) - - assert_equal("yayness", File.read(path), "Content did not get set correctly") - end - - # Make sure unmanaged files are purged. - def test_purge - sourcedir = tempfile() - destdir = tempfile() - Dir.mkdir(sourcedir) - Dir.mkdir(destdir) - sourcefile = File.join(sourcedir, "sourcefile") - dsourcefile = File.join(destdir, "sourcefile") - localfile = File.join(destdir, "localfile") - purgee = File.join(destdir, "to_be_purged") - File.open(sourcefile, "w") { |f| f.puts "funtest" } - # this file should get removed - File.open(purgee, "w") { |f| f.puts "footest" } - - lfobj = Puppet::Type.newfile( - :title => "localfile", - :path => localfile, - :content => "rahtest", - :ensure => :file, - :backup => false - ) - - destobj = Puppet::Type.newfile(:title => "destdir", :path => destdir, - :source => sourcedir, - :backup => false, - :recurse => true) - - config = mk_catalog(lfobj, destobj) - config.apply - - assert(FileTest.exists?(dsourcefile), "File did not get copied") - assert(FileTest.exists?(localfile), "Local file did not get created") - assert(FileTest.exists?(purgee), "Purge target got prematurely purged") - - assert_nothing_raised { destobj[:purge] = true } - config.apply - - assert(FileTest.exists?(localfile), "Local file got purged") - assert(FileTest.exists?(dsourcefile), "Source file got purged") - assert(! FileTest.exists?(purgee), "File did not get purged") - end - - # Testing #274. Make sure target can be used without 'ensure'. - def test_target_without_ensure - source = tempfile() - dest = tempfile() - File.open(source, "w") { |f| f.puts "funtest" } - - obj = nil - assert_nothing_raised { - obj = Puppet::Type.newfile(:path => dest, :target => source) - } - - assert_apply(obj) - end - - def test_autorequire_owner_and_group - file = tempfile() - comp = nil - user = nil - group =nil - home = nil - ogroup = nil - assert_nothing_raised { - user = Puppet.type(:user).create( - :name => "pptestu", - :home => file, - :gid => "pptestg" - ) - home = Puppet.type(:file).create( - :path => file, - :owner => "pptestu", - :group => "pptestg", - :ensure => "directory" - ) - group = Puppet.type(:group).create( - :name => "pptestg" - ) - comp = mk_catalog(user, group, home) - } - - # Now make sure we get a relationship for each of these - rels = nil - assert_nothing_raised { rels = home.autorequire } - assert(rels.detect { |e| e.source == user }, "owner was not autorequired") - assert(rels.detect { |e| e.source == group }, "group was not autorequired") - end - - # Testing #309 -- //my/file => /my/file - def test_slash_deduplication - ["/my/////file/for//testing", "//my/file/for/testing///", - "/my/file/for/testing"].each do |path| - file = nil - assert_nothing_raised do - file = Puppet::Type.newfile(:path => path) - end - - assert_equal("/my/file/for/testing", file.title) - assert_equal(file, Puppet::Type.type(:file)["/my/file/for/testing"]) - Puppet::Type.type(:file).clear - end - end - - # Testing #304 - def test_links_to_directories - link = tempfile() - file = tempfile() - dir = tempfile() - Dir.mkdir(dir) - - bucket = Puppet::Type.newfilebucket :name => "main" - File.symlink(dir, link) - File.open(file, "w") { |f| f.puts "" } - assert_equal(dir, File.readlink(link)) - obj = Puppet::Type.newfile :path => link, :ensure => :link, :target => file, :recurse => false, :backup => "main" - - assert_apply(obj) - - assert_equal(file, File.readlink(link)) - end - - # Testing #303 - def test_nobackups_with_links - link = tempfile() - new = tempfile() - - File.open(link, "w") { |f| f.puts "old" } - File.open(new, "w") { |f| f.puts "new" } - obj = Puppet::Type.newfile :path => link, :ensure => :link, - :target => new, :recurse => true, :backup => false - - assert_nothing_raised do - obj.handlebackup - end - - bfile = [link, "puppet-bak"].join(".") - - assert(! FileTest.exists?(bfile), "Backed up when told not to") - - assert_apply(obj) - - assert(! FileTest.exists?(bfile), "Backed up when told not to") - end - - # Make sure we consistently handle backups for all cases. - def test_ensure_with_backups - # We've got three file types, so make sure we can replace any type - # with the other type and that backups are done correctly. - types = [:file, :directory, :link] - - dir = tempfile() - path = File.join(dir, "test") - linkdest = tempfile() - creators = { - :file => proc { File.open(path, "w") { |f| f.puts "initial" } }, - :directory => proc { Dir.mkdir(path) }, - :link => proc { File.symlink(linkdest, path) } - } - - bucket = Puppet::Type.newfilebucket :name => "main", :path => tempfile() - - obj = Puppet::Type.newfile :path => path, :force => true, - :links => :manage - - Puppet[:trace] = true - ["main", false].each do |backup| - obj[:backup] = backup - obj.finish - types.each do |should| - types.each do |is| - # It makes no sense to replace a directory with a directory - # next if should == :directory and is == :directory - - Dir.mkdir(dir) - - # Make the thing - creators[is].call - - obj[:ensure] = should - - if should == :link - obj[:target] = linkdest - else - if obj.property(:target) - obj.delete(:target) - end - end - - # First try just removing the initial data - assert_nothing_raised do - obj.remove_existing(should) - end - - unless is == should - # Make sure the original is gone - assert(! FileTest.exists?(obj[:path]), - "remove_existing did not work: " + - "did not remove %s with %s" % [is, should]) - end - FileUtils.rmtree(obj[:path]) - - # Now make it again - creators[is].call - - property = obj.property(:ensure) - - currentvalue = property.retrieve - unless property.insync?(currentvalue) - assert_nothing_raised do - property.sync - end - end - FileUtils.rmtree(dir) - end - end - end - end - - if Process.uid == 0 - # Testing #364. - def test_writing_in_directories_with_no_write_access - # Make a directory that our user does not have access to - dir = tempfile() - Dir.mkdir(dir) - - # Get a fake user - user = nonrootuser - # and group - group = nonrootgroup - - # First try putting a file in there - path = File.join(dir, "file") - file = Puppet::Type.newfile :path => path, :owner => user.name, :group => group.name, :content => "testing" - - # Make sure we can create it - assert_apply(file) - assert(FileTest.exists?(path), "File did not get created") - # And that it's owned correctly - assert_equal(user.uid, File.stat(path).uid, "File has the wrong owner") - assert_equal(group.gid, File.stat(path).gid, "File has the wrong group") - - assert_equal("testing", File.read(path), "file has the wrong content") - - # Now make a dir - subpath = File.join(dir, "subdir") - subdir = Puppet::Type.newfile :path => subpath, :owner => user.name, :group => group.name, :ensure => :directory - # Make sure we can create it - assert_apply(subdir) - assert(FileTest.directory?(subpath), "File did not get created") - # And that it's owned correctly - assert_equal(user.uid, File.stat(subpath).uid, "File has the wrong owner") - assert_equal(group.gid, File.stat(subpath).gid, "File has the wrong group") - - assert_equal("testing", File.read(path), "file has the wrong content") - end - end - - # #366 - def test_replace_aliases - file = Puppet::Type.newfile :path => tempfile() - file[:replace] = :yes - assert_equal(:true, file[:replace], ":replace did not alias :true to :yes") - file[:replace] = :no - assert_equal(:false, file[:replace], ":replace did not alias :false to :no") - end - - # #365 -- make sure generated files also use filebuckets. - def test_recursive_filebuckets - source = tempfile() - dest = tempfile() - s1 = File.join(source, "1") - sdir = File.join(source, "dir") - s2 = File.join(sdir, "2") - Dir.mkdir(source) - Dir.mkdir(sdir) - [s1, s2].each { |file| File.open(file, "w") { |f| f.puts "yay: %s" % File.basename(file) } } - - sums = {} - [s1, s2].each do |f| - sums[File.basename(f)] = Digest::MD5.hexdigest(File.read(f)) - end - - dfiles = [File.join(dest, "1"), File.join(dest, "dir", "2")] - - bpath = tempfile - bucket = Puppet::Type.type(:filebucket).create :name => "rtest", :path => bpath - dipper = bucket.bucket - dipper = Puppet::Network::Handler.filebucket.new( - :Path => bpath - ) - assert(dipper, "did not receive bucket client") - file = Puppet::Type.newfile :path => dest, :source => source, :recurse => true, :backup => "rtest" - - assert_apply(file) - dfiles.each do |f| - assert(FileTest.exists?(f), "destfile %s was not created" % f) - end - - # Now modify the source files to make sure things get backed up correctly - [s1, s2].each { |sf| File.open(sf, "w") { |f| - f.puts "boo: %s" % File.basename(sf) - } } - - assert_apply(file) - dfiles.each do |f| - assert_equal("boo: %s\n" % File.basename(f), File.read(f), - "file was not copied correctly") - end - - # Make sure we didn't just copy the files over to backup locations - dfiles.each do |f| - assert(! FileTest.exists?(f + "rtest"), - "file %s was copied for backup instead of bucketed" % File.basename(f)) - end - - # Now make sure we can get the source sums from the bucket - sums.each do |f, sum| - result = nil - assert_nothing_raised do - result = dipper.getfile(sum) - end - assert(result, "file %s was not backed to filebucket" % f) - assert_equal("yay: %s\n" % f, result, "file backup was not correct") - end - end - - def test_backup - path = tempfile() - file = Puppet::Type.newfile :path => path, :content => "yay" - - [false, :false, "false"].each do |val| - assert_nothing_raised do - file[:backup] = val - end - assert_equal(false, file[:backup], "%s did not translate" % val.inspect) - end - [true, :true, "true", ".puppet-bak"].each do |val| - assert_nothing_raised do - file[:backup] = val - end - assert_equal(".puppet-bak", file[:backup], "%s did not translate" % val.inspect) - end - - # Now try a non-bucket string - assert_nothing_raised do - file[:backup] = ".bak" - end - assert_equal(".bak", file[:backup], ".bak did not translate") - - # Now try a non-existent bucket - assert_nothing_raised do - file[:backup] = "main" - end - assert_equal("main", file[:backup], "bucket name was not retained") - assert_equal("main", file.bucket, "file's bucket was not set") - - # And then an existing bucket - obj = Puppet::Type.type(:filebucket).create :name => "testing" - bucket = obj.bucket - - assert_nothing_raised do - file[:backup] = "testing" - end - assert_equal("testing", file[:backup], "backup value was reset") - assert_equal(obj.bucket, file.bucket, "file's bucket was not set") - end - - def test_pathbuilder - dir = tempfile() - Dir.mkdir(dir) - file = File.join(dir, "file") - File.open(file, "w") { |f| f.puts "" } - obj = Puppet::Type.newfile :path => dir, :recurse => true, :mode => 0755 - mk_catalog obj - - assert_equal("/%s" % obj.ref, obj.path) - - list = obj.eval_generate - fileobj = obj.class[file] - assert(fileobj, "did not generate file object") - assert_equal("/%s" % fileobj.ref, fileobj.path, "did not generate correct subfile path") - end - - # Testing #403 - def test_removal_with_content_set - path = tempfile() - File.open(path, "w") { |f| f.puts "yay" } - file = Puppet::Type.newfile(:name => path, :ensure => :absent, :content => "foo") - - assert_apply(file) - assert(! FileTest.exists?(path), "File was not removed") - end - - # Testing #434 - def test_stripping_extra_slashes_during_lookup - file = Puppet::Type.newfile(:path => "/one/two") - %w{/one/two/ /one/two /one//two //one//two//}.each do |path| - assert(Puppet::Type.type(:file)[path], "could not look up file via path %s" % path) - end - end - - # Testing #438 - def test_creating_properties_conflict - file = tempfile() - first = tempfile() - second = tempfile() - params = [:content, :source, :target] - params.each do |param| - assert_nothing_raised("%s conflicted with ensure" % [param]) do - Puppet::Type.newfile(:path => file, param => first, :ensure => :file) - end - Puppet::Type.type(:file).clear - params.each do |other| - next if other == param - assert_raise(Puppet::Error, "%s and %s did not conflict" % [param, other]) do - Puppet::Type.newfile(:path => file, other => first, param => second) - end - end - end - end - - # Testing #508 - if Process.uid == 0 - def test_files_replace_with_right_attrs - source = tempfile() - File.open(source, "w") { |f| - f.puts "some text" - } - File.chmod(0755, source) - user = nonrootuser - group = nonrootgroup - path = tempfile() - good = {:uid => user.uid, :gid => group.gid, :mode => 0640} - - run = Proc.new do |obj, msg| - assert_apply(obj) - stat = File.stat(obj[:path]) - good.each do |should, sval| - if should == :mode - current = filemode(obj[:path]) - else - current = stat.send(should) - end - assert_equal(sval, current, - "Attr %s was not correct %s" % [should, msg]) - end - end - - file = Puppet::Type.newfile(:path => path, :owner => user.name, - :group => group.name, :mode => 0640, :backup => false) - {:source => source, :content => "some content"}.each do |attr, value| - file[attr] = value - # First create the file - run.call(file, "upon creation with %s" % attr) - - # Now change something so that we replace the file - case attr - when :source: - File.open(source, "w") { |f| f.puts "some different text" } - when :content: file[:content] = "something completely different" - else - raise "invalid attr %s" % attr - end - - # Run it again - run.call(file, "after modification with %s" % attr) - - # Now remove the file and the attr - file.delete(attr) - File.unlink(path) - end - end - end - - # #505 - def test_numeric_recurse - dir = tempfile() - subdir = File.join(dir, "subdir") - other = File.join(subdir, "deeper") - file = File.join(other, "file") - [dir, subdir, other].each { |d| Dir.mkdir(d) } - File.open(file, "w") { |f| f.puts "yay" } - File.chmod(0644, file) - obj = Puppet::Type.newfile(:path => dir, :mode => 0750, :recurse => "2") - config = mk_catalog(obj) - - children = nil - assert_nothing_raised("Failure when recursing") do - children = obj.eval_generate - end - assert(obj.class[subdir], "did not create subdir object") - children.each do |c| - assert_nothing_raised("Failure when recursing on %s" % c) do - c.catalog = config - others = c.eval_generate - end - end - oobj = obj.class[other] - assert(oobj, "did not create other object") - - assert_nothing_raised do - assert_nil(oobj.eval_generate, "recursed too far") - end - end - - # Make sure we default to the "puppet" filebucket, rather than a string - def test_backup_defaults_to_bucket - path = tempfile - file = Puppet::Type.newfile(:path => path, :content => 'some content') - file.finish - - assert_instance_of(Puppet::Network::Client::Dipper, file.bucket, - "did not default to a filebucket for backups") - end - - # #515 - make sure 'ensure' other than "link" is deleted during recursion - def test_ensure_deleted_during_recursion - dir = tempfile() - Dir.mkdir(dir) - file = File.join(dir, "file") - File.open(file, "w") { |f| f.puts "asdfasdf" } - - obj = Puppet::Type.newfile(:path => dir, :ensure => :directory, - :recurse => true) - - config = mk_catalog(obj) - children = nil - assert_nothing_raised do - children = obj.eval_generate - end - fobj = obj.class[file] - assert(fobj, "did not create file object") - assert(fobj.should(:ensure) != :directory, "ensure was passed to child") - end - - # #567 - def test_missing_files_are_in_sync - file = tempfile - obj = Puppet::Type.newfile(:path => file, :mode => 0755) - - changes = obj.evaluate - assert(changes.empty?, "Missing file with no ensure resulted in changes") - end - - def test_root_dir_is_named_correctly - obj = Puppet::Type.newfile(:path => '/', :mode => 0755) - assert_equal("/", obj.title, "/ directory was changed to empty string") - end - - # #1010 and #1037 -- write should fail if the written checksum does not - # match the file we thought we were writing. - def test_write_validates_checksum - file = tempfile - inst = Puppet::Type.newfile(:path => file, :content => "something") - - tmpfile = file + ".puppettmp" - - wh = mock 'writehandle', :print => nil - rh = mock 'readhandle' - rh.expects(:read).with(512).times(2).returns("other").then.returns(nil) - File.expects(:open).with { |*args| args[0] == tmpfile and args[1] != "r" }.yields(wh) - File.expects(:open).with { |*args| args[0] == tmpfile and args[1] == "r" }.yields(rh) - - File.stubs(:rename) - FileTest.stubs(:exist?).returns(true) - FileTest.stubs(:file?).returns(true) - - inst.expects(:fail) - inst.write("something", :whatever) - end -end diff --git a/test/ral/types/file/target.rb b/test/ral/types/file/target.rb deleted file mode 100755 index 035ea905b..000000000 --- a/test/ral/types/file/target.rb +++ /dev/null @@ -1,364 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../../lib/puppettest' - -require 'puppettest' -require 'puppettest/support/utils' -require 'fileutils' - -class TestFileTarget < Test::Unit::TestCase - include PuppetTest::Support::Utils - include PuppetTest::FileTesting - - def setup - super - @file = Puppet::Type.type(:file) - end - - # Make sure we can create symlinks - def test_symlinks - path = tempfile() - link = tempfile() - - File.open(path, "w") { |f| f.puts "yay" } - - file = nil - assert_nothing_raised { - file = Puppet.type(:file).create( - :title => "somethingelse", - :ensure => path, - :path => link - ) - } - - assert_events([:link_created], file) - - assert(FileTest.symlink?(link), "Link was not created") - - assert_equal(path, File.readlink(link), "Link was created incorrectly") - - # Make sure running it again works - assert_events([], file) - assert_events([], file) - assert_events([], file) - end - - def test_linkrecurse - dest = tempfile() - link = @file.create :path => tempfile(), :recurse => true, :ensure => dest - mk_catalog link - - ret = nil - - # Start with nothing, just to make sure we get nothing back - assert_nothing_raised { ret = link.linkrecurse(true) } - assert_nil(ret, "got a return when the dest doesn't exist") - - # then with a directory with only one file - Dir.mkdir(dest) - one = File.join(dest, "one") - File.open(one, "w") { |f| f.puts "" } - link[:ensure] = dest - assert_nothing_raised { ret = link.linkrecurse(true) } - - assert_equal(:directory, link.should(:ensure), "ensure was not set to directory") - assert_equal([File.join(link.title, "one")], ret.collect { |f| f.title }, - "Did not get linked file") - oneobj = @file[File.join(link.title, "one")] - assert_equal(one, oneobj.should(:target), "target was not set correctly") - - oneobj.remove - File.unlink(one) - - # Then make sure we get multiple files - returns = [] - 5.times do |i| - path = File.join(dest, i.to_s) - returns << File.join(link.title, i.to_s) - File.open(path, "w") { |f| f.puts "" } - end - assert_nothing_raised { ret = link.linkrecurse(true) } - - assert_equal(returns.sort, ret.collect { |f| f.title }.sort, - "Did not get links back") - - returns.each do |path| - obj = @file[path] - assert(path, "did not get obj for %s" % path) - sdest = File.join(dest, File.basename(path)) - assert_equal(sdest, obj.should(:target), - "target was not set correctly for %s" % path) - end - end - - def test_simplerecursivelinking - source = tempfile() - path = tempfile() - subdir = File.join(source, "subdir") - file = File.join(subdir, "file") - - system("mkdir -p %s" % subdir) - system("touch %s" % file) - - link = nil - assert_nothing_raised { - link = Puppet.type(:file).create( - :ensure => source, - :path => path, - :recurse => true - ) - } - - assert_apply(link) - - sublink = File.join(path, "subdir") - linkpath = File.join(sublink, "file") - assert(File.directory?(path), "dest is not a dir") - assert(File.directory?(sublink), "subdest is not a dir") - assert(File.symlink?(linkpath), "path is not a link") - assert_equal(file, File.readlink(linkpath)) - - assert_nil(@file[sublink], "objects were not removed") - assert_equal([], link.evaluate, "Link is not in sync") - end - - def test_recursivelinking - source = tempfile() - dest = tempfile() - - files = [] - dirs = [] - - # Make a bunch of files and dirs - Dir.mkdir(source) - Dir.chdir(source) do - system("mkdir -p %s" % "some/path/of/dirs") - system("mkdir -p %s" % "other/path/of/dirs") - system("touch %s" % "file") - system("touch %s" % "other/file") - system("touch %s" % "some/path/of/file") - system("touch %s" % "some/path/of/dirs/file") - system("touch %s" % "other/path/of/file") - - files = %x{find . -type f}.chomp.split(/\n/) - dirs = %x{find . -type d}.chomp.split(/\n/).reject{|d| d =~ /^\.+$/ } - end - - link = nil - assert_nothing_raised { - link = Puppet.type(:file).create( - :ensure => source, - :path => dest, - :recurse => true - ) - } - - assert_apply(link) - - files.each do |f| - f.sub!(/^\.#{File::SEPARATOR}/, '') - path = File.join(dest, f) - assert(FileTest.exists?(path), "Link %s was not created" % path) - assert(FileTest.symlink?(path), "%s is not a link" % f) - target = File.readlink(path) - assert_equal(File.join(source, f), target) - end - - dirs.each do |d| - d.sub!(/^\.#{File::SEPARATOR}/, '') - path = File.join(dest, d) - assert(FileTest.exists?(path), "Dir %s was not created" % path) - assert(FileTest.directory?(path), "%s is not a directory" % d) - end - end - - def test_localrelativelinks - dir = tempfile() - Dir.mkdir(dir) - source = File.join(dir, "source") - File.open(source, "w") { |f| f.puts "yay" } - dest = File.join(dir, "link") - - link = nil - assert_nothing_raised { - link = Puppet.type(:file).create( - :path => dest, - :ensure => "source" - ) - } - - assert_events([:link_created], link) - assert(FileTest.symlink?(dest), "Did not create link") - assert_equal("source", File.readlink(dest)) - assert_equal("yay\n", File.read(dest)) - end - - def test_recursivelinkingmissingtarget - source = tempfile() - dest = tempfile() - - objects = [] - objects << Puppet.type(:exec).create( - :command => "mkdir %s; touch %s/file" % [source, source], - :title => "yay", - :path => ENV["PATH"] - ) - objects << Puppet.type(:file).create( - :ensure => source, - :path => dest, - :recurse => true, - :require => objects[0] - ) - - assert_apply(*objects) - - link = File.join(dest, "file") - assert(FileTest.symlink?(link), "Did not make link") - assert_equal(File.join(source, "file"), File.readlink(link)) - end - - def test_insync? - source = tempfile() - dest = tempfile() - - obj = @file.create(:path => source, :target => dest) - - prop = obj.send(:property, :target) - prop.send(:instance_variable_set, "@should", [:nochange]) - assert(prop.insync?(prop.retrieve), - "Property not in sync with should == :nochange") - - prop = obj.send(:property, :target) - prop.send(:instance_variable_set, "@should", [:notlink]) - assert(prop.insync?(prop.retrieve), - "Property not in sync with should == :nochange") - - # Lastly, make sure that we don't try to do anything when we're - # recursing, since 'ensure' does the work. - obj[:recurse] = true - prop.should = dest - assert(prop.insync?(prop.retrieve), - "Still out of sync during recursion") - end - - def test_replacedirwithlink - Puppet[:trace] = false - path = tempfile() - link = tempfile() - - File.open(path, "w") { |f| f.puts "yay" } - Dir.mkdir(link) - File.open(File.join(link, "yay"), "w") do |f| f.puts "boo" end - - file = nil - assert_nothing_raised { - file = Puppet.type(:file).create( - :ensure => path, - :path => link, - :backup => false - ) - } - - # First run through without :force - assert_events([], file) - - assert(FileTest.directory?(link), "Link replaced dir without force") - - assert_nothing_raised { file[:force] = true } - - assert_events([:link_created], file) - - assert(FileTest.symlink?(link), "Link was not created") - - assert_equal(path, File.readlink(link), "Link was created incorrectly") - end - - def test_replace_links_with_files - base = tempfile() - - Dir.mkdir(base) - - file = File.join(base, "file") - link = File.join(base, "link") - File.open(file, "w") { |f| f.puts "yayness" } - File.symlink(file, link) - - obj = Puppet::Type.type(:file).create( - :path => link, - :ensure => "file" - ) - - assert_apply(obj) - - assert_equal("yayness\n", File.read(file), - "Original file got changed") - assert_equal("file", File.lstat(link).ftype, "File is still a link") - end - - def test_no_erase_linkedto_files - base = tempfile() - - Dir.mkdir(base) - - dirs = {} - %w{other source target}.each do |d| - dirs[d] = File.join(base, d) - Dir.mkdir(dirs[d]) - end - - file = File.join(dirs["other"], "file") - sourcefile = File.join(dirs["source"], "sourcefile") - link = File.join(dirs["target"], "sourcefile") - - File.open(file, "w") { |f| f.puts "other" } - File.open(sourcefile, "w") { |f| f.puts "source" } - File.symlink(file, link) - - obj = Puppet::Type.type(:file).create( - :path => dirs["target"], - :ensure => :file, - :source => dirs["source"], - :recurse => true - ) - config = mk_catalog obj - config.apply - - newfile = File.join(dirs["target"], "sourcefile") - - assert(File.directory?(dirs["target"]), "Dir did not get created") - assert(File.file?(newfile), "File did not get copied") - - assert_equal(File.read(sourcefile), File.read(newfile), - "File did not get copied correctly.") - - assert_equal("other\n", File.read(file), - "Original file got changed") - assert_equal("file", File.lstat(link).ftype, "File is still a link") - end - - def test_replace_links - dest = tempfile() - otherdest = tempfile() - link = tempfile() - - File.open(dest, "w") { |f| f.puts "boo" } - File.open(otherdest, "w") { |f| f.puts "yay" } - - obj = Puppet::Type.type(:file).create( - :path => link, - :ensure => otherdest - ) - - - assert_apply(obj) - - assert_equal(otherdest, File.readlink(link), "Link did not get created") - - obj[:ensure] = dest - - assert_apply(obj) - - assert_equal(dest, File.readlink(link), "Link did not get changed") - end -end - diff --git a/test/ral/types/filebucket.rb b/test/ral/types/filebucket.rb deleted file mode 100755 index f9706663b..000000000 --- a/test/ral/types/filebucket.rb +++ /dev/null @@ -1,157 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' -require 'puppettest/support/utils' -require 'fileutils' - -class TestFileBucket < Test::Unit::TestCase - include PuppetTest::Support::Utils - include PuppetTest::FileTesting - # hmmm - # this is complicated, because we store references to the created - # objects in a central store - def mkfile(hash) - file = nil - assert_nothing_raised { - file = Puppet.type(:file).create(hash) - } - return file - end - - def mkbucket(name,path) - bucket = nil - assert_nothing_raised { - bucket = Puppet.type(:filebucket).create( - :name => name, - :path => path - ) - } - - @@tmpfiles.push path - - return bucket - end - - def mktestfile - # because luke's home directory is on nfs, it can't be used for testing - # as root - tmpfile = tempfile() - File.open(tmpfile, "w") { |f| f.puts rand(100) } - @@tmpfiles.push tmpfile - mkfile(:name => tmpfile) - end - - def setup - super - begin - initstorage - rescue - system("rm -rf %s" % Puppet[:statefile]) - end - end - - def initstorage - Puppet::Util::Storage.init - Puppet::Util::Storage.load - end - - def clearstorage - Puppet::Util::Storage.store - Puppet::Util::Storage.clear - end - - def test_simplebucket - name = "yayness" - bucketpath = tempfile() - mkbucket(name, bucketpath) - - bucket = nil - assert_nothing_raised { - bucket = Puppet.type(:filebucket).bucket(name) - } - - assert_instance_of(Puppet::Network::Client.dipper, bucket) - - md5 = nil - newpath = tempfile() - @@tmpfiles << newpath - system("cp /etc/passwd %s" % newpath) - assert_nothing_raised { - md5 = bucket.backup(newpath) - } - - assert(md5) - - dir, file, pathfile = Puppet::Network::Handler.filebucket.paths(bucketpath, md5) - - assert(FileTest.directory?(dir), - "MD5 directory does not exist") - - newmd5 = nil - - # Just in case the file isn't writable - File.chmod(0644, newpath) - File.open(newpath, "w") { |f| f.puts ";lkjasdf;lkjasdflkjwerlkj134lkj" } - - assert_nothing_raised { - newmd5 = bucket.backup(newpath) - } - - assert(md5 != newmd5) - - assert_nothing_raised { - bucket.restore(newpath, md5) - } - - File.open(newpath) { |f| newmd5 = Digest::MD5.hexdigest(f.read) } - - assert_equal(md5, newmd5) - end - - def test_fileswithbuckets - name = "yayness" - mkbucket(name, tempfile()) - - bucket = nil - assert_nothing_raised { - bucket = Puppet.type(:filebucket).bucket(name) - } - - file = mktestfile() - assert_nothing_raised { - file[:backup] = name - } - - opath = tempfile() - @@tmpfiles << opath - File.open(opath, "w") { |f| f.puts "yaytest" } - - origmd5 = File.open(file.name) { |f| newmd5 = Digest::MD5.hexdigest(f.read) } - - file[:source] = opath - #assert_nothing_raised { - # file[:backup] = true - #} - - assert_apply(file) - - # so, we've now replaced the file with the opath file - assert_equal( - File.open(opath) { |f| newmd5 = Digest::MD5.hexdigest(f.read) }, - File.open(file.name) { |f| newmd5 = Digest::MD5.hexdigest(f.read) } - ) - - #File.chmod(0644, file.name) - assert_nothing_raised { - bucket.restore(file.name, origmd5) - } - - assert_equal( - origmd5, - File.open(file.name) { |f| newmd5 = Digest::MD5.hexdigest(f.read) } - ) - end -end - diff --git a/test/ral/types/fileignoresource.rb b/test/ral/types/fileignoresource.rb deleted file mode 100755 index ff867c879..000000000 --- a/test/ral/types/fileignoresource.rb +++ /dev/null @@ -1,245 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' -require 'puppettest/support/utils' -require 'cgi' -require 'fileutils' - -class TestFileIgnoreSources < Test::Unit::TestCase - include PuppetTest::Support::Utils - include PuppetTest::FileTesting - - def setup - super - begin - initstorage - rescue - system("rm -rf %s" % Puppet[:statefile]) - end - end - -#This is not needed unless using md5 (correct me if I'm wrong) - def initstorage - Puppet::Util::Storage.init - Puppet::Util::Storage.load - end - - def clearstorage - Puppet::Util::Storage.store - Puppet::Util::Storage.clear - end - - def test_ignore_simple_source - - #Temp directory to run tests in - path = tempfile() - @@tmpfiles.push path - - #source directory - sourcedir = "sourcedir" - sourcefile1 = "sourcefile1" - sourcefile2 = "sourcefile2" - - frompath = File.join(path,sourcedir) - FileUtils.mkdir_p frompath - - topath = File.join(path,"destdir") - FileUtils.mkdir topath - - #initialize variables before block - tofile = nil - trans = nil - - #create source files - - File.open(File.join(frompath,sourcefile1), - File::WRONLY|File::CREAT|File::APPEND) { |of| - of.puts "yayness" - } - - File.open(File.join(frompath,sourcefile2), - File::WRONLY|File::CREAT|File::APPEND) { |of| - of.puts "even yayer" - } - - - #makes Puppet file Object - assert_nothing_raised { - tofile = Puppet.type(:file).create( - :name => topath, - :source => frompath, - :recurse => true, - :ignore => "sourcefile2" - ) - } - - config = mk_catalog(tofile) - config.apply - - - #topath should exist as a directory with sourcedir as a directory - - #This file should exist - assert(FileTest.exists?(File.join(topath,sourcefile1))) - - #This file should not - assert(!(FileTest.exists?(File.join(topath,sourcefile2)))) - - Puppet::Type.allclear - end - - def test_ignore_with_wildcard - #Temp directory to run tests in - path = tempfile() - @@tmpfiles.push path - - #source directory - sourcedir = "sourcedir" - subdir = "subdir" - subdir2 = "subdir2" - sourcefile1 = "sourcefile1" - sourcefile2 = "sourcefile2" - - frompath = File.join(path,sourcedir) - FileUtils.mkdir_p frompath - - FileUtils.mkdir_p(File.join(frompath, subdir)) - FileUtils.mkdir_p(File.join(frompath, subdir2)) - dir = Dir.glob(File.join(path,"**/*")) - - topath = File.join(path,"destdir") - FileUtils.mkdir topath - - #initialize variables before block - tofile = nil - trans = nil - - #create source files - - dir.each { |dir| - File.open(File.join(dir,sourcefile1), - File::WRONLY|File::CREAT|File::APPEND) { |of| - of.puts "yayness" - } - - File.open(File.join(dir,sourcefile2), - File::WRONLY|File::CREAT|File::APPEND) { |of| - of.puts "even yayer" - } - - } - - #makes Puppet file Object - assert_nothing_raised { - tofile = Puppet.type(:file).create( - :name => topath, - :source => frompath, - :recurse => true, - :ignore => "*2" - ) - } - - config = mk_catalog(tofile) - config.apply - - #topath should exist as a directory with sourcedir as a directory - - #This file should exist - assert(FileTest.exists?(File.join(topath,sourcefile1))) - assert(FileTest.exists?(File.join(topath,subdir))) - assert(FileTest.exists?(File.join(File.join(topath,subdir),sourcefile1))) - - #This file should not - assert(!(FileTest.exists?(File.join(topath,sourcefile2)))) - assert(!(FileTest.exists?(File.join(topath,subdir2)))) - assert(!(FileTest.exists?(File.join(File.join(topath,subdir),sourcefile2)))) - Puppet::Type.allclear - - end - - def test_ignore_array - #Temp directory to run tests in - path = tempfile() - @@tmpfiles.push path - - #source directory - sourcedir = "sourcedir" - subdir = "subdir" - subdir2 = "subdir2" - subdir3 = "anotherdir" - sourcefile1 = "sourcefile1" - sourcefile2 = "sourcefile2" - - frompath = File.join(path,sourcedir) - FileUtils.mkdir_p frompath - - FileUtils.mkdir_p(File.join(frompath, subdir)) - FileUtils.mkdir_p(File.join(frompath, subdir2)) - FileUtils.mkdir_p(File.join(frompath, subdir3)) - sourcedir = Dir.glob(File.join(path,"**/*")) - - topath = File.join(path,"destdir") - FileUtils.mkdir topath - - #initialize variables before block - tofile = nil - trans = nil - - #create source files - - - - sourcedir.each { |dir| - File.open(File.join(dir,sourcefile1), - File::WRONLY|File::CREAT|File::APPEND) { |of| - of.puts "yayness" - } - - File.open(File.join(dir,sourcefile2), - File::WRONLY|File::CREAT|File::APPEND) { |of| - of.puts "even yayer" - } - - } - - - #makes Puppet file Object - assert_nothing_raised { - tofile = Puppet.type(:file).create( - :name => topath, - :source => frompath, - :recurse => true, - :ignore => ["*2", "an*"] - # :ignore => ["*2", "an*", "nomatch"] - ) - } - - config = mk_catalog(tofile) - config.apply - - #topath should exist as a directory with sourcedir as a directory - - # This file should exist - # proper files in destination - assert(FileTest.exists?(File.join(topath,sourcefile1)), "file1 not in destdir") - assert(FileTest.exists?(File.join(topath,subdir)), "subdir1 not in destdir") - assert(FileTest.exists?(File.join(File.join(topath,subdir),sourcefile1)), "file1 not in subdir") - # proper files in source - assert(FileTest.exists?(File.join(frompath,subdir)), "subdir not in source") - assert(FileTest.exists?(File.join(frompath,subdir2)), "subdir2 not in source") - assert(FileTest.exists?(File.join(frompath,subdir3)), "subdir3 not in source") - - # This file should not - assert(!(FileTest.exists?(File.join(topath,sourcefile2))), "file2 in dest") - assert(!(FileTest.exists?(File.join(topath,subdir2))), "subdir2 in dest") - assert(!(FileTest.exists?(File.join(topath,subdir3))), "anotherdir in dest") - assert(!(FileTest.exists?(File.join(File.join(topath,subdir),sourcefile2))), "file2 in dest/sub") - - - Puppet::Type.allclear - - end - -end diff --git a/test/ral/types/filesources.rb b/test/ral/types/filesources.rb deleted file mode 100755 index a7bb6fefa..000000000 --- a/test/ral/types/filesources.rb +++ /dev/null @@ -1,997 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' -require 'puppettest/support/utils' -require 'cgi' -require 'fileutils' -require 'mocha' - -class TestFileSources < Test::Unit::TestCase - include PuppetTest::Support::Utils - include PuppetTest::FileTesting - def setup - super - if defined? @port - @port += 1 - else - @port = 12345 - end - @file = Puppet::Type.type(:file) - Puppet[:filetimeout] = -1 - Puppet::Util::SUIDManager.stubs(:asuser).yields - end - - def teardown - super - Puppet::Network::HttpPool.clear_http_instances - end - - def use_storage - begin - initstorage - rescue - system("rm -rf %s" % Puppet[:statefile]) - end - end - - def initstorage - Puppet::Util::Storage.init - Puppet::Util::Storage.load - end - - # Make a simple recursive tree. - def mk_sourcetree - source = tempfile() - sourcefile = File.join(source, "file") - Dir.mkdir source - File.open(sourcefile, "w") { |f| f.puts "yay" } - - dest = tempfile() - destfile = File.join(dest, "file") - return source, dest, sourcefile, destfile - end - - def test_newchild - path = tempfile() - @@tmpfiles.push path - - FileUtils.mkdir_p path - File.open(File.join(path,"childtest"), "w") { |of| - of.puts "yayness" - } - file = nil - comp = nil - trans = nil - assert_nothing_raised { - file = Puppet.type(:file).create( - :name => path - ) - } - config = mk_catalog(file) - child = nil - assert_nothing_raised { - child = file.newchild("childtest", true) - } - assert(child) - assert_raise(Puppet::DevError) { - file.newchild(File.join(path,"childtest"), true) - } - end - - def test_describe - source = tempfile() - dest = tempfile() - - file = Puppet::Type.newfile :path => dest, :source => source, :title => "copier" - - property = file.property(:source) - - # First try describing with a normal source - result = nil - assert_nothing_raised do - result = property.describe(source) - end - assert_nil(result, "Got a result back when source is missing") - - # Now make a remote directory - Dir.mkdir(source) - assert_nothing_raised do - result = property.describe(source) - end - assert_equal("directory", result[:type]) - - # And as a file - Dir.rmdir(source) - File.open(source, "w") { |f| f.puts "yay" } - assert_nothing_raised do - result = property.describe(source) - end - assert_equal("file", result[:type]) - assert(result[:checksum], "did not get value for checksum") - if Puppet::Util::SUIDManager.uid == 0 - assert(result.has_key?(:owner), "Lost owner in describe") - else - assert(! result.has_key?(:owner), - "Kept owner in describe even tho not root") - end - - # Now let's do the various link things - File.unlink(source) - target = tempfile() - File.open(target, "w") { |f| f.puts "yay" } - File.symlink(target, source) - - file[:links] = :manage - assert_equal("link", property.describe(source)[:type]) - - # And then make sure links get followed - file[:links] = :follow - assert_equal("file", property.describe(source)[:type]) - end - - def test_source_retrieve - source = tempfile() - dest = tempfile() - - file = Puppet::Type.newfile :path => dest, :source => source, - :title => "copier" - - assert(file.property(:checksum), "source property did not create checksum property") - property = file.property(:source) - assert(property, "did not get source property") - - # Make sure the munge didn't actually change the source - assert_equal([source], property.should, "munging changed the source") - - # First try it with a missing source - currentvalue = nil - assert_nothing_raised do - currentvalue = property.retrieve - end - - # And make sure the property considers itself in sync, since there's nothing - # to do - assert(property.insync?(currentvalue), "source thinks there's work to do with no file or dest") - - # Now make the dest a directory, and make sure the object sets :ensure - # up to create a directory - Dir.mkdir(source) - assert_nothing_raised do - currentvalue = property.retrieve - end - assert_equal(:directory, file.should(:ensure), - "Did not set to create directory") - - # And make sure the source property won't try to do anything with a - # remote dir - assert(property.insync?(currentvalue), "Source was out of sync even tho remote is dir") - - # Now remove the source, and make sure :ensure was not modified - Dir.rmdir(source) - assert_nothing_raised do - property.retrieve - end - assert_equal(:directory, file.should(:ensure), - "Did not keep :ensure setting") - - # Now have a remote file and make sure things work correctly - File.open(source, "w") { |f| f.puts "yay" } - File.chmod(0755, source) - - assert_nothing_raised do - property.retrieve - end - assert_equal(:file, file.should(:ensure), - "Did not make correct :ensure setting") - assert_equal(0755, file.should(:mode), - "Mode was not copied over") - - # Now let's make sure that we get the first found source - fake = tempfile() - property.should = [fake, source] - assert_nothing_raised do - property.retrieve - end - assert_equal(Digest::MD5.hexdigest(File.read(source)), property.checksum.sub(/^\{\w+\}/, ''), - "Did not catch later source") - end - - def test_insync - source = tempfile() - dest = tempfile() - - file = Puppet::Type.newfile :path => dest, :source => source, - :title => "copier" - - property = file.property(:source) - assert(property, "did not get source property") - - # Try it with no source at all - currentvalues = file.retrieve - assert(property.insync?(currentvalues[property]), "source property not in sync with missing source") - - # with a directory - Dir.mkdir(source) - currentvalues = file.retrieve - assert(property.insync?(currentvalues[property]), "source property not in sync with directory as source") - Dir.rmdir(source) - - # with a file - File.open(source, "w") { |f| f.puts "yay" } - currentvalues = file.retrieve - assert(!property.insync?(currentvalues[property]), "source property was in sync when file was missing") - - # With a different file - File.open(dest, "w") { |f| f.puts "foo" } - currentvalues = file.retrieve - assert(!property.insync?(currentvalues[property]), "source property was in sync with different file") - - # with matching files - File.open(dest, "w") { |f| f.puts "yay" } - currentvalues = file.retrieve - assert(property.insync?(currentvalues[property]), "source property was not in sync with matching file") - end - - def test_source_sync - source = tempfile() - dest = tempfile() - - file = Puppet::Type.newfile :path => dest, :source => source, - :title => "copier" - property = file.property(:source) - - File.open(source, "w") { |f| f.puts "yay" } - - currentvalues = file.retrieve - assert(! property.insync?(currentvalues[property]), "source thinks it's in sync") - - event = nil - assert_nothing_raised do - event = property.sync - end - assert_equal(:file_created, event) - assert_equal(File.read(source), File.read(dest), - "File was not copied correctly") - - # Now write something different - File.open(source, "w") { |f| f.puts "rah" } - currentvalues = file.retrieve - assert(! property.insync?(currentvalues[property]), "source should be out of sync") - assert_nothing_raised do - event = property.sync - end - assert_equal(:file_changed, event) - assert_equal(File.read(source), File.read(dest), - "File was not copied correctly") - end - - # XXX This test doesn't cover everything. Specifically, - # it doesn't handle 'ignore' and 'links'. - def test_sourcerecurse - source, dest, sourcefile, destfile = mk_sourcetree - - # The sourcerecurse method will only ever get called when we're - # recursing, so we go ahead and set it. - obj = Puppet::Type.newfile :source => source, :path => dest, :recurse => true - config = mk_catalog(obj) - - result = nil - sourced = nil - assert_nothing_raised do - result, sourced = obj.sourcerecurse(true) - end - - assert_equal([destfile], sourced, "Did not get correct list of sourced objects") - dfileobj = @file[destfile] - assert(dfileobj, "Did not create destfile object") - assert_equal([dfileobj], result) - - # Clean this up so it can be recreated - config.remove_resource(dfileobj) - - # Make sure we correctly iterate over the sources - nosource = tempfile() - obj[:source] = [nosource, source] - - result = nil - assert_nothing_raised do - result, sourced = obj.sourcerecurse(true) - end - assert_equal([destfile], sourced, "Did not get correct list of sourced objects") - dfileobj = @file[destfile] - assert(dfileobj, "Did not create destfile object with a missing source") - assert_equal([dfileobj], result) - dfileobj.remove - - # Lastly, make sure we return an empty array when no sources are there - obj[:source] = [nosource, tempfile()] - - assert_nothing_raised do - result, sourced = obj.sourcerecurse(true) - end - assert_equal([], sourced, "Did not get correct list of sourced objects") - assert_equal([], result, "Sourcerecurse failed when all sources are missing") - end - - def test_simplelocalsource - path = tempfile() - FileUtils.mkdir_p path - frompath = File.join(path,"source") - topath = File.join(path,"dest") - fromfile = nil - tofile = nil - trans = nil - - File.open(frompath, File::WRONLY|File::CREAT|File::APPEND) { |of| - of.puts "yayness" - } - assert_nothing_raised { - tofile = Puppet.type(:file).create( - :name => topath, - :source => frompath - ) - } - - assert_apply(tofile) - - assert(FileTest.exists?(topath), "File #{topath} is missing") - from = File.open(frompath) { |o| o.read } - to = File.open(topath) { |o| o.read } - assert_equal(from,to) - end - - # Make sure a simple recursive copy works - def test_simple_recursive_source - source, dest, sourcefile, destfile = mk_sourcetree - - file = Puppet::Type.newfile :path => dest, :source => source, :recurse => true - - assert_events([:directory_created, :file_created], file) - - assert(FileTest.directory?(dest), "Dest dir was not created") - assert(FileTest.file?(destfile), "dest file was not created") - assert_equal("yay\n", File.read(destfile), "dest file was not copied correctly") - end - - def recursive_source_test(fromdir, todir) - Puppet::Type.allclear - initstorage - tofile = nil - trans = nil - - assert_nothing_raised { - tofile = Puppet.type(:file).create( - :path => todir, - :recurse => true, - :backup => false, - :source => fromdir - ) - } - assert_apply(tofile) - - assert(FileTest.exists?(todir), "Created dir %s does not exist" % todir) - Puppet::Type.allclear - end - - def run_complex_sources(networked = false) - path = tempfile() - - # first create the source directory - FileUtils.mkdir_p path - - # okay, let's create a directory structure - fromdir = File.join(path,"fromdir") - Dir.mkdir(fromdir) - FileUtils.cd(fromdir) { - File.open("one", "w") { |f| f.puts "onefile"} - File.open("two", "w") { |f| f.puts "twofile"} - } - - todir = File.join(path, "todir") - source = fromdir - if networked - source = "puppet://localhost/%s%s" % [networked, fromdir] - end - recursive_source_test(source, todir) - - return [fromdir,todir, File.join(todir, "one"), File.join(todir, "two")] - end - - def test_complex_sources_twice - fromdir, todir, one, two = run_complex_sources - assert_trees_equal(fromdir,todir) - recursive_source_test(fromdir, todir) - assert_trees_equal(fromdir,todir) - # Now remove the whole tree and try it again. - [one, two].each do |f| File.unlink(f) end - Dir.rmdir(todir) - recursive_source_test(fromdir, todir) - assert_trees_equal(fromdir,todir) - end - - def test_sources_with_deleted_destfiles - fromdir, todir, one, two = run_complex_sources - assert(FileTest.exists?(todir)) - - # We shouldn't have a 'two' file object in memory - assert_nil(@file[two], "object for 'two' is still in memory") - - # then delete a file - File.unlink(two) - - # and run - recursive_source_test(fromdir, todir) - - assert(FileTest.exists?(two), "Deleted file was not recopied") - - # and make sure they're still equal - assert_trees_equal(fromdir,todir) - end - - def test_sources_with_readonly_destfiles - fromdir, todir, one, two = run_complex_sources - assert(FileTest.exists?(todir)) - File.chmod(0600, one) - recursive_source_test(fromdir, todir) - - # and make sure they're still equal - assert_trees_equal(fromdir,todir) - - # Now try it with the directory being read-only - File.chmod(0111, todir) - recursive_source_test(fromdir, todir) - - # and make sure they're still equal - assert_trees_equal(fromdir,todir) - end - - def test_sources_with_modified_dest_files - fromdir, todir, one, two = run_complex_sources - - assert(FileTest.exists?(todir)) - - # Modify a dest file - File.open(two, "w") { |f| f.puts "something else" } - - recursive_source_test(fromdir, todir) - - # and make sure they're still equal - assert_trees_equal(fromdir,todir) - end - - def test_sources_with_added_destfiles - fromdir, todir = run_complex_sources - assert(FileTest.exists?(todir)) - # and finally, add some new files - add_random_files(todir) - - recursive_source_test(fromdir, todir) - - fromtree = file_list(fromdir) - totree = file_list(todir) - - assert(fromtree != totree, "Trees are incorrectly equal") - - # then remove our new files - FileUtils.cd(todir) { - %x{find . 2>/dev/null}.chomp.split(/\n/).each { |file| - if file =~ /file[0-9]+/ - File.unlink(file) - end - } - } - - # and make sure they're still equal - assert_trees_equal(fromdir,todir) - end - - # Make sure added files get correctly caught during recursion - def test_RecursionWithAddedFiles - basedir = tempfile() - Dir.mkdir(basedir) - @@tmpfiles << basedir - file1 = File.join(basedir, "file1") - file2 = File.join(basedir, "file2") - subdir1 = File.join(basedir, "subdir1") - file3 = File.join(subdir1, "file") - File.open(file1, "w") { |f| f.puts "yay" } - rootobj = nil - assert_nothing_raised { - rootobj = Puppet.type(:file).create( - :name => basedir, - :recurse => true, - :check => %w{type owner}, - :mode => 0755 - ) - } - - assert_apply(rootobj) - assert_equal(0755, filemode(file1)) - - File.open(file2, "w") { |f| f.puts "rah" } - assert_apply(rootobj) - assert_equal(0755, filemode(file2)) - - Dir.mkdir(subdir1) - File.open(file3, "w") { |f| f.puts "foo" } - assert_apply(rootobj) - assert_equal(0755, filemode(file3)) - end - - def mkfileserverconf(mounts) - file = tempfile() - File.open(file, "w") { |f| - mounts.each { |path, name| - f.puts "[#{name}]\n\tpath #{path}\n\tallow *\n" - } - } - - @@tmpfiles << file - return file - end - - def test_NetworkSources - server = nil - mounts = { - "/" => "root" - } - - fileserverconf = mkfileserverconf(mounts) - - Puppet[:autosign] = true - - Puppet[:masterport] = 8762 - Puppet[:name] = "puppetmasterd" - Puppet[:certdnsnames] = "localhost" - - serverpid = nil - assert_nothing_raised() { - server = Puppet::Network::HTTPServer::WEBrick.new( - :Handlers => { - :CA => {}, # so that certs autogenerate - :FileServer => { - :Config => fileserverconf - } - } - ) - - } - serverpid = fork { - assert_nothing_raised() { - #trap(:INT) { server.shutdown; Kernel.exit! } - trap(:INT) { server.shutdown } - server.start - } - } - @@tmppids << serverpid - - sleep(1) - - fromdir, todir = run_complex_sources("root") - assert_trees_equal(fromdir,todir) - recursive_source_test(fromdir, todir) - assert_trees_equal(fromdir,todir) - - assert_nothing_raised { - system("kill -INT %s" % serverpid) - } - end - - def test_unmountedNetworkSources - server = nil - mounts = { - "/" => "root", - "/noexistokay" => "noexist" - } - - fileserverconf = mkfileserverconf(mounts) - - Puppet[:autosign] = true - Puppet[:masterport] = @port - Puppet[:certdnsnames] = "localhost" - - serverpid = nil - assert_nothing_raised("Could not start on port %s" % @port) { - server = Puppet::Network::HTTPServer::WEBrick.new( - :Port => @port, - :Handlers => { - :CA => {}, # so that certs autogenerate - :FileServer => { - :Config => fileserverconf - } - } - ) - - } - - serverpid = fork { - assert_nothing_raised() { - #trap(:INT) { server.shutdown; Kernel.exit! } - trap(:INT) { server.shutdown } - server.start - } - } - @@tmppids << serverpid - - sleep(1) - - name = File.join(tmpdir(), "nosourcefile") - file = Puppet.type(:file).create( - :source => "puppet://localhost/noexist/file", - :name => name - ) - - assert_nothing_raised { - file.retrieve - } - - comp = mk_catalog(file) - comp.apply - - assert(!FileTest.exists?(name), "File with no source exists anyway") - end - - def test_alwayschecksum - from = tempfile() - to = tempfile() - - File.open(from, "w") { |f| f.puts "yayness" } - File.open(to, "w") { |f| f.puts "yayness" } - - file = nil - - # Now the files should be exactly the same, so we should not see attempts - # at copying - assert_nothing_raised { - file = Puppet.type(:file).create( - :path => to, - :source => from - ) - } - - currentvalue = file.retrieve - - assert(currentvalue[file.property(:checksum)], - "File does not have a checksum property") - - assert_equal(0, file.evaluate.length, "File produced changes") - end - - def test_sourcepaths - files = [] - 3.times { - files << tempfile() - } - - to = tempfile() - - File.open(files[-1], "w") { |f| f.puts "yee-haw" } - - file = nil - assert_nothing_raised { - file = Puppet.type(:file).create( - :name => to, - :source => files - ) - } - - comp = mk_catalog(file) - assert_events([:file_created], comp) - - assert(File.exists?(to), "File does not exist") - - txt = nil - File.open(to) { |f| txt = f.read.chomp } - - assert_equal("yee-haw", txt, "Contents do not match") - end - - # Make sure that source-copying updates the checksum on the same run - def test_checksumchange - source = tempfile() - dest = tempfile() - File.open(dest, "w") { |f| f.puts "boo" } - File.open(source, "w") { |f| f.puts "yay" } - - file = nil - assert_nothing_raised { - file = Puppet.type(:file).create( - :name => dest, - :source => source - ) - } - - file.retrieve - - assert_events([:file_changed], file) - file.retrieve - assert_events([], file) - end - - # Make sure that source-copying updates the checksum on the same run - def test_sourcebeatsensure - source = tempfile() - dest = tempfile() - File.open(source, "w") { |f| f.puts "yay" } - - file = nil - assert_nothing_raised { - file = Puppet.type(:file).create( - :name => dest, - :ensure => "file", - :source => source - ) - } - - file.retrieve - - assert_events([:file_created], file) - file.retrieve - assert_events([], file) - assert_events([], file) - end - - def test_sourcewithlinks - source = tempfile() - link = tempfile() - dest = tempfile() - - File.open(source, "w") { |f| f.puts "yay" } - File.symlink(source, link) - - file = nil - assert_nothing_raised { - file = Puppet.type(:file).create( - :name => dest, - :source => link, - :links => :follow - ) - } - - assert_events([:file_created], file) - assert(FileTest.file?(dest), "Destination is not a file") - - # Now copy the links - file[:links] = :manage - assert_events([:link_created], file) - assert(FileTest.symlink?(dest), "Destination is not a link") - end - - def test_changes - source = tempfile() - dest = tempfile() - - File.open(source, "w") { |f| f.puts "yay" } - - obj = nil - assert_nothing_raised { - obj = Puppet.type(:file).create( - :name => dest, - :source => source - ) - } - - assert_events([:file_created], obj) - assert_equal(File.read(source), File.read(dest), "Files are not equal") - assert_events([], obj) - - File.open(source, "w") { |f| f.puts "boo" } - - assert_events([:file_changed], obj) - assert_equal(File.read(source), File.read(dest), "Files are not equal") - assert_events([], obj) - - File.open(dest, "w") { |f| f.puts "kaboom" } - - # There are two changes, because first the checksum is noticed, and - # then the source causes a change - assert_events([:file_changed, :file_changed], obj) - assert_equal(File.read(source), File.read(dest), "Files are not equal") - assert_events([], obj) - end - - def test_file_source_with_space - dir = tempfile() - source = File.join(dir, "file with spaces") - Dir.mkdir(dir) - File.open(source, "w") { |f| f.puts "yayness" } - - newdir = tempfile() - newpath = File.join(newdir, "file with spaces") - - file = Puppet::Type.newfile( - :path => newdir, - :source => dir, - :recurse => true - ) - - - assert_apply(file) - - assert(FileTest.exists?(newpath), "Did not create file") - assert_equal("yayness\n", File.read(newpath)) - end - - # Make sure files aren't replaced when replace is false, but otherwise - # are. - def test_replace - source = tempfile() - File.open(source, "w") { |f| f.puts "yayness" } - - dest = tempfile() - file = Puppet::Type.newfile( - :path => dest, - :source => source, - :recurse => true - ) - - - assert_apply(file) - - assert(FileTest.exists?(dest), "Did not create file") - assert_equal("yayness\n", File.read(dest)) - - # Now set :replace - assert_nothing_raised { - file[:replace] = false - } - - File.open(source, "w") { |f| f.puts "funtest" } - assert_apply(file) - - # Make sure it doesn't change. - assert_equal("yayness\n", File.read(dest), - "File got replaced when :replace was false") - - # Now set it to true and make sure it does change. - assert_nothing_raised { - file[:replace] = true - } - assert_apply(file) - - # Make sure it doesn't change. - assert_equal("funtest\n", File.read(dest), - "File was not replaced when :replace was true") - end - - # Testing #285. This just makes sure that URI parsing works correctly. - def test_fileswithpoundsigns - dir = tstdir() - subdir = File.join(dir, "#dir") - Dir.mkdir(subdir) - file = File.join(subdir, "file") - File.open(file, "w") { |f| f.puts "yayness" } - - dest = tempfile() - source = "file://localhost#{dir}" - obj = Puppet::Type.newfile( - :path => dest, - :source => source, - :recurse => true - ) - - newfile = File.join(dest, "#dir", "file") - - poundsource = "file://localhost#{subdir}" - - sourceobj = path = nil - assert_nothing_raised { - sourceobj, path = obj.uri2obj(poundsource) - } - - assert_equal("/localhost" + URI.escape(subdir), path) - - assert_apply(obj) - - assert(FileTest.exists?(newfile), "File did not get created") - assert_equal("yayness\n", File.read(newfile)) - end - - def test_sourceselect - dest = tempfile() - sources = [] - 2.times { |i| - i = i + 1 - source = tempfile() - sources << source - file = File.join(source, "file%s" % i) - Dir.mkdir(source) - File.open(file, "w") { |f| f.print "yay" } - } - file1 = File.join(dest, "file1") - file2 = File.join(dest, "file2") - file3 = File.join(dest, "file3") - - # Now make different files with the same name in each source dir - sources.each_with_index do |source, i| - File.open(File.join(source, "file3"), "w") { |f| - f.print i.to_s - } - end - - obj = Puppet::Type.newfile(:path => dest, :recurse => true, - :source => sources) - - assert_equal(:first, obj[:sourceselect], "sourceselect has the wrong default") - # First, make sure we default to just copying file1 - assert_apply(obj) - - assert(FileTest.exists?(file1), "File from source 1 was not copied") - assert(! FileTest.exists?(file2), "File from source 2 was copied") - assert(FileTest.exists?(file3), "File from source 1 was not copied") - assert_equal("0", File.read(file3), "file3 got wrong contents") - - # Now reset sourceselect - assert_nothing_raised do - obj[:sourceselect] = :all - end - File.unlink(file1) - File.unlink(file3) - Puppet.err :yay - assert_apply(obj) - - assert(FileTest.exists?(file1), "File from source 1 was not copied") - assert(FileTest.exists?(file2), "File from source 2 was copied") - assert(FileTest.exists?(file3), "File from source 1 was not copied") - assert_equal("0", File.read(file3), "file3 got wrong contents") - end - - def test_recursive_sourceselect - dest = tempfile() - source1 = tempfile() - source2 = tempfile() - files = [] - [source1, source2, File.join(source1, "subdir"), File.join(source2, "subdir")].each_with_index do |dir, i| - Dir.mkdir(dir) - # Make a single file in each directory - file = File.join(dir, "file%s" % i) - File.open(file, "w") { |f| f.puts "yay%s" % i} - - # Now make a second one in each directory - file = File.join(dir, "second-file%s" % i) - File.open(file, "w") { |f| f.puts "yaysecond-%s" % i} - files << file - end - - obj = Puppet::Type.newfile(:path => dest, :source => [source1, source2], :sourceselect => :all, :recurse => true) - - assert_apply(obj) - - ["file0", "file1", "second-file0", "second-file1", "subdir/file2", "subdir/second-file2", "subdir/file3", "subdir/second-file3"].each do |file| - path = File.join(dest, file) - assert(FileTest.exists?(path), "did not create %s" % file) - - assert_equal("yay%s\n" % File.basename(file).sub("file", ''), File.read(path), "file was not copied correctly") - end - end - - # #594 - def test_purging_missing_remote_files - source = tempfile() - dest = tempfile() - s1 = File.join(source, "file1") - s2 = File.join(source, "file2") - d1 = File.join(dest, "file1") - d2 = File.join(dest, "file2") - Dir.mkdir(source) - [s1, s2].each { |name| File.open(name, "w") { |file| file.puts "something" } } - - # We have to add a second parameter, because that's the only way to expose the "bug". - file = Puppet::Type.newfile(:path => dest, :source => source, :recurse => true, :purge => true, :mode => "755") - - assert_apply(file) - - assert(FileTest.exists?(d1), "File1 was not copied") - assert(FileTest.exists?(d2), "File2 was not copied") - - File.unlink(s2) - - assert_apply(file) - - assert(FileTest.exists?(d1), "File1 was not kept") - assert(! FileTest.exists?(d2), "File2 was not purged") - end -end - diff --git a/test/ral/types/group.rb b/test/ral/types/group.rb deleted file mode 100755 index d28c8eea5..000000000 --- a/test/ral/types/group.rb +++ /dev/null @@ -1,171 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' -require 'etc' - -class TestGroup < Test::Unit::TestCase - include PuppetTest - - p = Puppet::Type.type(:group).provide :fake, :parent => PuppetTest::FakeProvider do - @name = :fake - apimethods :ensure, :gid - - def create - @ensure = :present - end - - def delete - @ensure = :absent - end - - def exists? - if defined? @ensure and @ensure == :present - true - else - false - end - end - end - - FakeGroupProvider = p - - @@fakeproviders[:group] = p - - def setup - super - Puppet::Type.type(:group).defaultprovider = FakeGroupProvider - end - - def teardown - Puppet.type(:group).clear - Puppet::Type.type(:group).defaultprovider = nil - super - end - - def mkgroup(name, hash = {}) - group = nil - hash[:name] = name - assert_nothing_raised { - group = Puppet.type(:group).create(hash) - } - - return group - end - - def groupnames - %x{groups}.chomp.split(/ /) - end - - def groupids - Process.groups - end - - def attrtest_ensure(group) - group[:ensure] = :absent - - comp = mk_catalog("ensuretest", group) - assert_apply(comp) - assert_equal(:absent, group.provider.ensure, "Group is still present") - group[:ensure] = :present - assert_events([:group_created], comp) - assert_equal(:present, group.provider.ensure, "Group is absent") - group[:ensure] = :absent - trans = assert_events([:group_removed], comp) - assert_equal(:absent, group.provider.ensure, "Group is present") - - assert_rollback_events(trans, [:group_created], "group") - assert_equal(:present, group.provider.ensure, "Group is absent") - end - - # This is a bit odd, since we're not actually doing anything on the machine. - # Just make sure we can set the gid and that it will work correctly. - def attrtest_gid(group) - - # Check the validation. - assert_nothing_raised { - group[:gid] = "15" - } - - assert_equal(15, group.should(:gid), - "Did not convert gid to number") - - comp = mk_catalog(group) - trans = assert_events([:group_modified], comp, "group") - assert_equal(15, group.provider.gid, "GID was not changed") - - assert_nothing_raised { - group[:gid] = 16 - } - - assert_equal(16, group.should(:gid), - "Did not keep gid as number") - - # Now switch to 16 - trans = assert_events([:group_modified], comp, "group") - assert_equal(16, group.provider.gid, "GID was not changed") - - # And then rollback - assert_rollback_events(trans, [:group_modified], "group") - assert_equal(15, group.provider.gid, "GID was not changed") - end - - def test_owngroups - groupnames().each { |group| - gobj = nil - comp = nil - assert_nothing_raised { - gobj = Puppet.type(:group).create( - :name => group, - :check => [:gid] - ) - } - - # Set a fake gid - gobj.provider.gid = rand(100) - - current_values = nil - assert_nothing_raised { - current_values = gobj.retrieve - } - - assert(current_values[gobj.property(:gid)], - "Failed to retrieve gid") - } - end - - def test_mkgroup - gobj = nil - name = "pptestgr" - - assert_nothing_raised { - gobj = Puppet.type(:group).create( - :name => name, - :gid => 123 - ) - } - gobj.finish - - trans = assert_events([:group_created], gobj, "group") - - assert(gobj.provider.exists?, - "Did not create group") - - tests = Puppet.type(:group).validproperties - - gobj.retrieve - tests.each { |test| - if self.respond_to?("attrtest_%s" % test) - self.send("attrtest_%s" % test, gobj) - else - #$stderr.puts "Not testing attr %s of group" % test - end - } - - assert_rollback_events(trans, [:group_removed], "group") - - assert(! gobj.provider.exists?, - "Did not delete group") - end -end diff --git a/test/ral/types/host.rb b/test/ral/types/host.rb deleted file mode 100755 index a5d645bd1..000000000 --- a/test/ral/types/host.rb +++ /dev/null @@ -1,181 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' -require 'test/unit' -require 'facter' - -class TestHost < Test::Unit::TestCase - include PuppetTest - - def setup - super - @hosttype = Puppet::Type.type(:host) - - @provider = @hosttype.defaultprovider - - # Make sure they aren't using something funky like netinfo - unless @provider.name == :parsed - @hosttype.defaultprovider = @hosttype.provider(:parsed) - end - - cleanup do @hosttype.defaultprovider = nil end - - if @provider.respond_to?(:default_target=) - @default_file = @provider.default_target - cleanup do - @provider.default_target = @default_file - end - @target = tempfile() - @provider.default_target = @target - end - end - - def mkhost - if defined? @hcount - @hcount += 1 - else - @hcount = 1 - end - - @catalog ||= mk_catalog - - host = nil - assert_nothing_raised { - host = Puppet.type(:host).create( - :name => "fakehost%s" % @hcount, - :ip => "192.168.27.%s" % @hcount, - :alias => "alias%s" % @hcount, - :catalog => @catalog - ) - } - - return host - end - - def test_list - assert_nothing_raised do - @hosttype.defaultprovider.prefetch - end - - count = 0 - @hosttype.each do |h| - count += 1 - end - - assert_equal(0, count, "Found hosts in empty file somehow") - end - - # Darwin will actually write to netinfo here. - if Facter.value(:operatingsystem) != "Darwin" or Process.uid == 0 - def test_simplehost - host = nil - # We want to actually use the netinfo provider on darwin - if Facter.value(:operatingsystem) == "Darwin" - Puppet::Type.type(:host).defaultprovider = nil - end - - assert_nothing_raised { - host = Puppet.type(:host).create( - :name => "culain", - :ip => "192.168.0.3" - ) - } - - current_values = nil - assert_nothing_raised { current_values = host.retrieve } - assert_events([:host_created], host) - - assert_nothing_raised { current_values = host.retrieve } - - assert_equal(:present, current_values[host.property(:ensure)]) - - host[:ensure] = :absent - - assert_events([:host_removed], host) - - assert_nothing_raised { current_values = host.retrieve } - - assert_equal(:absent, current_values[host.property(:ensure)]) - end - - def test_moddinghost - # We want to actually use the netinfo provider on darwin - if Facter.value(:operatingsystem) == "Darwin" - Puppet::Type.type(:host).defaultprovider = nil - end - host = mkhost() - if Facter.value(:operatingsystem) == "Darwin" - assert_equal(:netinfo, host[:provider], "Got incorrect provider") - end - cleanup do - host[:ensure] = :absent - assert_apply(host) - end - - assert_events([:host_created], host) - - current_values = nil - assert_nothing_raised { - current_values = host.retrieve - } - - # This was a hard bug to track down. - assert_instance_of(String, current_values[host.property(:ip)]) - - host[:alias] = %w{madstop kirby yayness} - - assert_events([:host_changed], host) - - assert_nothing_raised { - current_values = host.retrieve - } - - assert_equal(%w{madstop kirby yayness}, - current_values[host.property(:alias)]) - - host[:ensure] = :absent - assert_events([:host_removed], host) - end - - def test_invalid_ipaddress - host = mkhost() - - assert_raise(Puppet::Error) { - host[:ip] = "abc.def.ghi.jkl" - } - end - - def test_invalid_hostname - host = mkhost() - - assert_raise(Puppet::Error) { - host[:name] = "!invalid.hostname.$$$" - } - end - - end - def test_aliasisproperty - assert_equal(:property, @hosttype.attrtype(:alias)) - end - - def test_multivalues - host = mkhost - assert_raise(Puppet::Error) { - host[:alias] = "puppetmasterd yayness" - } - end - - def test_puppetalias - host = mkhost() - - assert_nothing_raised { - host[:alias] = "testing" - } - - same = host.class["testing"] - assert(same, "Could not retrieve by alias") - end -end - diff --git a/test/ral/types/mailalias.rb b/test/ral/types/mailalias.rb deleted file mode 100755 index ff1dd562a..000000000 --- a/test/ral/types/mailalias.rb +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' -require 'mocha' - -class TestMailAlias < Test::Unit::TestCase - include PuppetTest - - def setup - super - @type = Puppet::Type.type(:mailalias) - - @provider = @type.defaultprovider - - # Make sure they aren't using something funky like netinfo - unless @provider.name == :aliases - @type.defaultprovider = @type.provider(:aliases) - end - - cleanup do @type.defaultprovider = nil end - - if @provider.respond_to?(:default_target=) - @default_file = @provider.default_target - cleanup do - @provider.default_target = @default_file - end - @target = tempfile() - @provider.default_target = @target - end - end - - # This isn't much of a test, but then, it's not much of a type. - def test_recipient_arrays - resource = @type.create(:name => "luke", :recipient => "yay", :target => tempfile) - resource.provider.expects(:recipient).returns([:absent]) - values = nil - assert_nothing_raised("Could not retrieve mailalias") do - values = resource.retrieve.inject({}) { |hash, a| hash[a[0].name] = a[1]; hash } - end - assert_equal([:absent], values[:recipient]) - resource.property(:recipient).expects(:set).with(%w{yay}) - assert_nothing_raised("Could not sync mailalias") do - resource.property(:recipient).sync - end - end -end - diff --git a/test/ral/types/parameter.rb b/test/ral/types/parameter.rb deleted file mode 100755 index e1b8e00b3..000000000 --- a/test/ral/types/parameter.rb +++ /dev/null @@ -1,174 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' - -class TestParameter < Test::Unit::TestCase - include PuppetTest - - def newparam(name = :fakeparam) - assert_nothing_raised { - param = Class.new(Puppet::Parameter) do - @name = :fakeparam - end - param.initvars - - return param - } - end - - def newinst(param) - assert_nothing_raised { - return param.new(:resource => "yay") - } - end - - # Test the basic newvalue stuff. - def test_newvalue - param = newparam() - - # Try it with both symbols and strings. - assert_nothing_raised { - param.newvalues(:one, "two") - } - - inst = newinst(param) - - assert_nothing_raised { - inst.value = "one" - } - - assert_equal(:one, inst.value) - - assert_nothing_raised { - inst.value = :two - } - assert_equal(:two, inst.value) - - assert_raise(ArgumentError) { - inst.value = :three - } - assert_equal(:two, inst.value) - end - - # Test using regexes. - def test_regexvalues - param = newparam - - assert_nothing_raised { - param.newvalues(/^\d+$/) - } - assert(param.match?("14")) - assert(param.match?(14)) - - inst = newinst(param) - - assert_nothing_raised { - inst.value = 14 - } - - assert_nothing_raised { - inst.value = "14" - } - - assert_raise(ArgumentError) { - inst.value = "a14" - } - end - - # Test using both. Equality should beat matching. - def test_regexesandnormals - param = newparam - - assert_nothing_raised { - param.newvalues(:one, /^\w+$/) - } - - inst = newinst(param) - - assert_nothing_raised { - inst.value = "one" - } - - assert_equal(:one, inst.value, "Value used regex instead of equality") - - assert_nothing_raised { - inst.value = "two" - } - assert_equal("two", inst.value, "Matched value didn't take") - end - - def test_shadowing - type = Puppet::Type.newtype(:faketype) { newparam(:name) {} } - - cleanup { Puppet::Type.rmtype(:faketype) } - - param = nil - assert_nothing_raised do - param = type.newproperty(:alias) - end - - assert(param, "did not create param") - - inst = type.create(:name => "test") - - config = mk_catalog - inst.catalog = config - - assert_nothing_raised("Could not create shadowed param") { - inst[:alias] = "foo" - } - - # Get the parameter hash from the instance so we can check the shadow - params = inst.instance_variable_get("@parameters") - obj = params[:alias] - assert(obj, "did not get alias parameter") - assert(obj.shadow, "shadow was not created for alias param") - - assert(obj.is_a?(Puppet::Property), - "alias instance is not a property") - assert_instance_of(param, obj, "alias is an instance of the wrong class") - - # Make sure the alias got created - assert(type["foo"], "Did not retrieve object by its alias") - - # Now try it during initialization - other = nil - assert_nothing_raised("Could not create instance with shadow") do - other = type.create(:name => "rah", :alias => "one", :catalog => config) - end - params = other.instance_variable_get("@parameters") - obj = params[:alias] - assert(obj, "did not get alias parameter") - assert(obj.shadow, "shadow was not created for alias param") - - assert_instance_of(param, obj, "alias is an instance of the wrong class") - assert(obj.is_a?(Puppet::Property), - "alias instance is not a property") - - # Now change the alias and make sure it works out well - assert_nothing_raised("Could not modify shadowed alias") do - other[:alias] = "two" - end - - obj = params[:alias] - assert(obj, "did not get alias parameter") - assert_instance_of(param, obj, "alias is now an instance of the wrong class") - assert(obj.is_a?(Puppet::Property), - "alias instance is now not a property") - end - - # Make sure properties can correctly require features and behave appropriately when - # those features are missing. - def test_requires_features - param = newparam(:feature_tests) - - assert_nothing_raised("could not add feature requirements to property") do - param.required_features = "testing" - end - - assert_equal([:testing], param.required_features, "required features value was not arrayfied and interned") - end -end - diff --git a/test/ral/types/port.rb b/test/ral/types/port.rb deleted file mode 100755 index e28904d55..000000000 --- a/test/ral/types/port.rb +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' - -#require 'facter' -# -#class TestPort < Test::Unit::TestCase -# include PuppetTest -# -# def setup -# super -# @porttype = Puppet.type(:port) -# -# @provider = @porttype.defaultprovider -# -# # Make sure they aren't using something funky like netinfo -# unless @provider.name == :parsed -# @porttype.defaultprovider = @porttype.provider(:parsed) -# end -# -# cleanup do @porttype.defaultprovider = nil end -# -# if @provider.respond_to?(:default_target) -# oldpath = @provider.default_target -# cleanup do -# @provider.default_target = oldpath -# end -# @provider.default_target = tempfile() -# end -# end -# -# def mkport -# port = nil -# -# if defined? @pcount -# @pcount += 1 -# else -# @pcount = 1 -# end -# assert_nothing_raised { -# port = Puppet.type(:port).create( -# :name => "puppet%s" % @pcount, -# :number => "813%s" % @pcount, -# :protocols => "tcp", -# :description => "The port that Puppet runs on", -# :alias => "coolness%s" % @pcount -# ) -# } -# -# return port -# end -# -# def test_list -# assert_nothing_raised { -# Puppet.type(:port).list -# } -# -# count = 0 -# @porttype.each do |h| -# count += 1 -# end -# -# assert_equal(0, count, "Found hosts in empty file somehow") -# -# dns = @porttype["domain"] -# assert(dns, "Did not retrieve dns service") -# end -# -# def test_simpleport -# host = nil -# -# port = mkport -# -# assert_apply(port) -# assert_nothing_raised { -# port.retrieve -# } -# -# assert(port.provider.exists?, "Port did not get created") -# end -# -# def test_moddingport -# port = nil -# port = mkport -# -# assert_events([:port_created], port) -# -# port.retrieve -# -# port[:protocols] = %w{tcp udp} -# -# assert_events([:port_changed], port) -# end -# -# def test_multivalues -# port = mkport -# assert_raise(Puppet::Error) { -# port[:protocols] = "udp tcp" -# } -# assert_raise(Puppet::Error) { -# port[:alias] = "puppetmasterd yayness" -# } -# end -# -# def test_removal -# port = mkport() -# assert_nothing_raised { -# port[:ensure] = :present -# } -# assert_events([:port_created], port) -# assert_events([], port) -# -# assert(port.provider.exists?, "port was not created") -# assert_nothing_raised { -# port[:ensure] = :absent -# } -# -# assert_events([:port_removed], port) -# assert(! port.provider.exists?, "port was not removed") -# assert_events([], port) -# end -# -# def test_addingproperties -# port = mkport() -# assert_events([:port_created], port) -# -# port.delete(:alias) -# assert(! port.property(:alias)) -# assert_events([:port_changed], port) -# -# assert_nothing_raised { -# port.retrieve -# } -# -# assert_equal(:present, port.is(:ensure)) -# -# assert_equal(:absent, port.is(:alias)) -# -# port[:alias] = "yaytest" -# assert_events([:port_changed], port) -# port.retrieve -# assert(port.property(:alias).is == ["yaytest"]) -# end -#end - diff --git a/test/ral/types/property.rb b/test/ral/types/property.rb deleted file mode 100755 index 6a3370caa..000000000 --- a/test/ral/types/property.rb +++ /dev/null @@ -1,388 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' - -class TestProperty < Test::Unit::TestCase - include PuppetTest - - def newinst(property, resource = nil) - inst = nil - unless resource - resource = "fakeresource" - resource.meta_def(:pathbuilder) do [self.to_s] end - resource.meta_def(:provider) do nil end - resource.meta_def(:fakeproperty) do '' end - end - assert_nothing_raised { - newinst = property.new(:resource => resource) - def newinst.retrieve(); return @fakeprovidervalue; end; - return newinst - } - end - - def newproperty(name = :fakeproperty) - property = Class.new(Puppet::Property) do - @name = name - end - Object.const_set("FakeProperty", property) - property.initvars - cleanup do - Object.send(:remove_const, "FakeProperty") - end - - return property - end - - def newmodel(name) - # Create an object that responds to myproperty as an attr - provklass = Class.new { attr_accessor name - def pathbuilder - ["provklass"] - end - } - prov = provklass.new - - klass = Class.new { attr_accessor :provider, :path - def pathbuilder - ["instklass"] - end - } - klassinst = klass.new - klassinst.path = "instpath" - klassinst.provider = prov - - return prov, klassinst - end - - # Make sure we correctly look up names. - def test_value_name - property = newproperty() - - property.newvalue(:one) - property.newvalue(/\d+/) - - name = nil - ["one", :one].each do |value| - assert_nothing_raised do - name = property.value_name(value) - end - assert_equal(:one, name) - end - ["42"].each do |value| - assert_nothing_raised do - name = property.value_name(value) - end - assert_equal(/\d+/, name) - end - # these values should not have a name - ["two", :three, ''].each do |value| - assert_nothing_raised do - name = property.value_name(value) - end - assert_nil(name) - end - end - - # Test that we correctly look up options for values. - def test_value_option - property = newproperty() - - options = { - :one => {:event => :yay, :call => :before}, - /\d+/ => {:event => :fun, :call => :instead} - } - property.newvalue(:one, options[:one]) - property.newvalue(/\d+/, options[/\d+/]) - - options.each do |name, opts| - opts.each do |param, value| - assert_equal(value, property.value_option(name, param)) - end - end - end - - def test_newvalue - property = newproperty() - - # These are bogus because they don't define events. :/ - assert_nothing_raised { - property.newvalue(:one) do - @fakeprovidervalue = 1 - end - } - - assert_nothing_raised { - property.newvalue("two") do - @fakeprovidervalue = 2 - end - } - - # Make sure we default to using the block instead - assert_equal(:instead, property.value_option(:one, :call), - ":call was not set to :instead when a block was provided") - - inst = newinst(property) - - assert_nothing_raised { - inst.should = "one" - } - - assert_equal(:one, inst.should) - ret = nil - assert_nothing_raised { inst.set_one } - assert_equal(1, inst.retrieve) - - assert_nothing_raised { - inst.should = :two - } - - assert_equal(:two, inst.should) - assert_nothing_raised { inst.set_two } - assert_equal(2, inst.retrieve) - end - - def test_newpropertyvaluewithregexes - property = newproperty() - - assert_nothing_raised { - property.newvalue(/^\w+$/) do - return :regex_matched - end - } - - inst = newinst(property) - - assert_nothing_raised { - inst.should = "yayness" - } - - assert_equal("yayness", inst.should) - - assert_nothing_raised { - inst.sync - } - - assert_equal("yayness".upcase, inst.retrieve) - end - - def test_newvalue_event_option - property = newproperty() - - assert_nothing_raised do - property.newvalue(:myvalue, :event => :fake_valued) do - end - property.newvalue(:other, :event => "fake_other") do - end - end - inst = newinst(property) - - assert_nothing_raised { - inst.should = :myvalue - } - - ret = nil - assert_nothing_raised { - ret = inst.sync - } - - assert_equal(:fake_valued, ret, - "Event did not get returned correctly") - - assert_nothing_raised { - inst.should = :other - } - - assert_nothing_raised { - ret = inst.sync - } - - assert_equal(:fake_other, ret, - "Event did not get returned correctly") - end - - # We want to support values with no blocks, either regexes or strings. - # If there's no block provided, then we should call the provider mechanism - # like we would normally. - def test_newvalue_with_no_block - property = newproperty(:myproperty) - - assert_nothing_raised { - property.newvalue(:value, :event => :matched_value) - } - assert_nothing_raised { - property.newvalue(/^\d+$/, :event => :matched_number) - } - - assert_equal(:none, property.value_option(:value, :call), - ":call was not set to none when no block is provided") - - prov, klassinst = newmodel(:myproperty) - - inst = newinst(property, klassinst) - - # Now make sure we can set the values, they get validated as normal, - # and they set the values on the resource rather than trying to call - # a method - {:value => :matched_value, "27" => :matched_number}.each do |value, event| - assert_nothing_raised do - inst.should = value - end - ret = nil - assert_nothing_raised do - ret = inst.sync - end - assert_equal(event, ret, "Did not return correct event for %s" % value) - assert_equal(value, prov.myproperty, "%s was not set right" % value) - end - - # And make sure we still fail validations - assert_raise(ArgumentError) do - inst.should = "invalid" - end - end - - def test_tags - obj = "yay" - metaobj = class << obj; self; end - - metaobj.send(:attr_accessor, :tags) - - tags = [:some, :tags, :for, :testing] - obj.tags = tags - - propertyklass = newproperty - - inst = nil - assert_nothing_raised do - inst = propertyklass.new(:resource => obj) - end - - assert_nothing_raised do - assert_equal(tags + [inst.name], inst.tags) - end - end - - def test_failure - s = Struct.new(:line, :file, :path, :pathbuilder, :name) - p = s.new(1, "yay", "rah", "struct", "name") - - myprovider = Class.new(Puppet::Provider) - - def p.provider; nil; end; - myproperty = Class.new(Puppet::Property) do - @name = 'name' - end - myproperty.initvars - - myproperty.newvalue :mkfailure do - raise "It's all broken" - end - property = myproperty.new(:resource => p) - - assert_raise(Puppet::Error) do - property.set(:mkfailure) - end - end - - # Make sure 'set' behaves correctly WRT to call order. This tests that the - # :call value is handled correctly in all cases. - def test_set - property = newproperty(:myproperty) - - $setting = [] - - newval = proc do |name, call| - options = {} - if call - options[:call] = name - block = proc { $setting << name } - end - assert_nothing_raised("Could not create %s value" % name) { - if block - property.newvalue(name, options, &block) - else - property.newvalue(name, options) - end - } - end - - newval.call(:none, false) - - # Create a value with no block; it should default to :none - newval.call(:before, true) - - # One with a block but after - newval.call(:after, true) - - # One with an explicit instead - newval.call(:instead, true) - - # And one with an implicit instead - assert_nothing_raised do - property.newvalue(:implicit) do - $setting << :implicit - end - end - - # Now create a provider - prov, model = newmodel(:myproperty) - inst = newinst(property, model) - - # Mark when we're called - prov.meta_def(:myproperty=) do |value| $setting << :provider end - - # Now run through the list and make sure everything is correct - {:before => [:before, :provider], - :after => [:provider, :after], - :instead => [:instead], - :none => [:provider], - :implicit => [:implicit] - }.each do |name, result| - inst.set(name) - - assert_equal(result, $setting, "%s was not handled right" % name) - $setting.clear - end - end - - # Make sure we can specify that we want to use the whole array, rather - # than just individual values. - def test_array_handling - property = newproperty(:arraytests) - - prov, model = newmodel(:array_testing) - inst = newinst(property, model) - - # Make sure it defaults to first - assert_equal(:first, property.array_matching, "Property did not default to matching first value in an array") - assert(! inst.match_all?, "match_all? returned true when array_matching is :first") - - vals = %w{one two three} - inst.should = vals - - # Make sure we only get the first value back - assert_equal("one", inst.should, "Returned wrong value when array_matching == first") - - # And make sure any of these values is considered in sync - vals.each do |value| - assert(inst.insync?(value), "#{value} was not considered in sync when array_matching == first") - end - - # Now change it to all - property.array_matching = :all - assert_equal(:all, property.array_matching, "Property did not change value of array_matching") - assert(inst.match_all?, "match_all? returned false when array_matching is :all") - - # Make sure we only get the first value back - assert_equal(vals, inst.should, "Returned wrong value when array_matching == all") - - # And make sure any of these values is considered in sync - %w{one two three}.each do |value| - assert(! inst.insync?(value), "individual value #{value} was considered in sync when array_matching == all") - end - assert(inst.insync?(vals), "value array was not considered in sync when array_matching == all") - end -end - diff --git a/test/ral/types/resources.rb b/test/ral/types/resources.rb deleted file mode 100755 index 0663fe795..000000000 --- a/test/ral/types/resources.rb +++ /dev/null @@ -1,208 +0,0 @@ -#!/usr/bin/env ruby -# -# Created by Luke Kanies on 2006-12-12. -# Copyright (c) 2006. All rights reserved. - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' - -class TestResources < Test::Unit::TestCase - include PuppetTest - - def add_purge_lister - # Now define the list method - class << @purgetype - def instances - $purgemembers.values - end - end - end - - def mk_purger(managed = false) - @purgenum ||= 0 - @purgenum += 1 - obj = @purgetype.create :name => "purger%s" % @purgenum - $purgemembers[obj[:name]] = obj - if managed - obj[:fake] = "testing" - end - obj - end - - def mkpurgertype - # Create a purgeable type - $purgemembers = {} - @purgetype = Puppet::Type.newtype(:purgetest) do - newparam(:name, :namevar => true) {} - newproperty(:ensure) do - newvalue(:absent) do - $purgemembers[@parent[:name]] = @parent - end - newvalue(:present) do - $purgemembers.delete(@parent[:name]) - end - end - newproperty(:fake) do - def sync - :faked - end - end - end - cleanup do - Puppet::Type.rmtype(:purgetest) - end - end - - def setup - super - @type = Puppet::Type.type(:resources) - end - - def test_initialize - assert(@type, "Could not retrieve resources type") - # Make sure we can't create them for types that don't exist - assert_raise(Puppet::Error) do - @type.create :name => "thereisnotypewiththisname" - end - - # Now make sure it works for a normal type - usertype = nil - assert_nothing_raised do - usertype = @type.create :name => "user" - end - assert(usertype, "did not create user resource type") - assert_equal(Puppet::Type.type(:user), usertype.resource_type, - "resource_type was not set correctly") - end - - def test_purge - # Create a purgeable type - mkpurgertype - - purger = nil - assert_nothing_raised do - purger = @type.create :name => "purgetest", :noop => true, :loglevel => :warning - end - assert(purger, "did not get purger manager") - add_purge_lister() - - assert_equal($purgemembers.values.sort, @purgetype.instances.sort) - - # and it should now succeed - assert_nothing_raised do - purger[:purge] = true - end - assert(purger.purge?, "purge boolean was not enabled") - - # Okay, now let's try doing some purging, yo - managed = [] - unmanned = [] - 3.times { managed << mk_purger(true) } # 3 managed - 3.times { unmanned << mk_purger(false) } # 3 unmanaged - - managed.each do |m| - assert(m.managed?, "managed resource was not considered managed") - end - unmanned.each do |u| - assert(! u.managed?, "unmanaged resource was considered managed") - end - - # First make sure we get nothing back when purge is false - genned = nil - purger[:purge] = false - assert_nothing_raised do - genned = purger.generate - end - assert_equal([], genned, "Purged even when purge is false") - - # Now make sure we can purge - purger[:purge] = true - assert_nothing_raised do - genned = purger.generate - end - assert(genned, "Did not get any generated resources") - - genned.each do |res| - assert(res.purging, "did not mark resource for purging") - end - assert(! genned.empty?, "generated resource list was empty") - - # Now make sure the generate method only finds the unmanaged resources - assert_equal(unmanned.collect { |r| r.title }.sort, genned.collect { |r| r.title }, - "Did not return correct purge list") - - # Now make sure our metaparams carried over - genned.each do |res| - [:noop, :loglevel].each do |param| - assert_equal(purger[param], res[param], "metaparam %s did not carry over" % param) - end - end - end - - # Part of #408. - def test_check - # First check a non-user - res = Puppet::Type.type(:resources).create :name => :package - assert_nil(res[:unless_system_user], "got bad default for package") - - - assert_nothing_raised { - assert(res.check("A String"), "String failed check") - assert(res.check(Puppet::Type.newfile(:path => tempfile())), "File failed check") - assert(res.check(Puppet::Type.type(:user).create(:name => "yayness")), "User failed check in package") - } - - # Now create a user manager - res = Puppet::Type.type(:resources).create :name => :user - - # Make sure the default is 500 - assert_equal(500, res[:unless_system_user], "got bad default") - - # Now make sure root fails the test - @user = Puppet::Type.type(:user) - assert_nothing_raised { - assert(! res.check(@user.create(:name => "root")), "root passed check") - assert(! res.check(@user.create(:name => "nobody")), "nobody passed check") - } - - # Now find a user between 0 and the limit - low = high = nil - Etc.passwd { |entry| - if ! low and (entry.uid > 10 and entry.uid < 500) - low = entry.name - else - # We'll reset the limit, since we can't really guarantee that - # there are any users with uid > 500 - if ! high and entry.uid > 100 and ! res.system_users.include?(entry.name) - high = entry.name - break - end - end - } - - if low - assert(! res.check(@user.create(:name => low)), "low user %s passed check" % low) - end - if high - res[:unless_system_user] = 50 - assert(res.check(@user.create(:name => high)), "high user %s failed check" % high) - end - end - - # The other half of #408. - def test_check_is_called - res = Puppet::Type.type(:resources).create :name => :user, :purge => true - - list = nil - assert_nothing_raised { list = res.generate } - - assert(! list.empty?, "did not get any users") - - bad = list.find_all { |u| - %w{root bin nobody}.include?(u[:name]) or (cv = u.retrieve and cv[u.property(:uid)] < 500) - } - assert(bad.empty?, "incorrectly passed users %s" % bad.collect { |u| u[:name]}.join(", ")) - end -end - diff --git a/test/ral/types/service.rb b/test/ral/types/service.rb deleted file mode 100755 index 01533c63e..000000000 --- a/test/ral/types/service.rb +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' -require 'mocha' - -class TestServiceType < Test::Unit::TestCase - include PuppetTest - - # #199 - def test_no_refresh_when_starting - service = Puppet::Type.type(:service).create :name => "hopefully_this_isnt_in_the_process_table", - :ensure => :running, :provider => :base - - assert_equal :running, service.instance_eval('@parameters[:ensure]').should - assert_not_equal :running, service.instance_eval('@parameters[:ensure]').retrieve, "You have something called #{service.name} in your process table" - - # First make sure it does not refresh - service.provider.expects(:restart).never - - assert_nothing_raised do - service.refresh - end - end - - def test_refresh_normally - service = Puppet::Type.type(:service).create :name => "testing", - :ensure => :running, :provider => :base, :status => "cat /dev/null" - - service.provider.expects(:restart) - - assert_nothing_raised do - service.refresh - end - end -end - diff --git a/test/ral/types/sshkey.rb b/test/ral/types/sshkey.rb deleted file mode 100755 index b9aed20e8..000000000 --- a/test/ral/types/sshkey.rb +++ /dev/null @@ -1,194 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' -require 'puppet/type/sshkey' -require 'facter' - -class TestSSHKey < Test::Unit::TestCase - include PuppetTest - def setup - super - # god i'm lazy - @sshkeytype = Puppet.type(:sshkey) - - @provider = @sshkeytype.defaultprovider - - # Make sure they aren't using something funky like netinfo - unless @provider.name == :parsed - @sshkeytype.defaultprovider = @sshkeytype.provider(:parsed) - end - - cleanup do @sshkeytype.defaultprovider = nil end - - if @provider.respond_to?(:default_target) - oldpath = @provider.default_target - cleanup do - @provider.default_target = oldpath - end - @provider.default_target = tempfile() - end - end - - def teardown - super - if @provider.respond_to?(:clear) - @provider.clear - end - end - - def mkkey - key = nil - - if defined? @kcount - @kcount += 1 - else - @kcount = 1 - end - - @catalog ||= mk_catalog - - assert_nothing_raised { - key = @sshkeytype.create( - :name => "host%s.madstop.com" % @kcount, - :key => "%sAAAAB3NzaC1kc3MAAACBAMnhSiku76y3EGkNCDsUlvpO8tRgS9wL4Eh54WZfQ2lkxqfd2uT/RTT9igJYDtm/+UHuBRdNGpJYW1Nw2i2JUQgQEEuitx4QKALJrBotejGOAWxxVk6xsh9xA0OW8Q3ZfuX2DDitfeC8ZTCl4xodUMD8feLtP+zEf8hxaNamLlt/AAAAFQDYJyf3vMCWRLjTWnlxLtOyj/bFpwAAAIEAmRxxXb4jjbbui9GYlZAHK00689DZuX0EabHNTl2yGO5KKxGC6Esm7AtjBd+onfu4Rduxut3jdI8GyQCIW8WypwpJofCIyDbTUY4ql0AQUr3JpyVytpnMijlEyr41FfIb4tnDqnRWEsh2H7N7peW+8DWZHDFnYopYZJ9Yu4/jHRYAAACAERG50e6aRRb43biDr7Ab9NUCgM9bC0SQscI/xdlFjac0B/kSWJYTGVARWBDWug705hTnlitY9cLC5Ey/t/OYOjylTavTEfd/bh/8FkAYO+pWdW3hx6p97TBffK0b6nrc6OORT2uKySbbKOn0681nNQh4a6ueR3JRppNkRPnTk5c=" % @kcount, - :type => "ssh-dss", - :alias => ["192.168.0.%s" % @kcount], - :catalog => @catalog - ) - } - - return key - end - - def test_instances - assert_nothing_raised { - Puppet.type(:sshkey).instances - } - - count = 0 - @sshkeytype.each do |h| - count += 1 - end - - assert_equal(0, count, "Found sshkeys in empty file somehow") - end - - def test_simplekey - key = mkkey - file = tempfile() - key[:target] = file - key[:provider] = :parsed - - assert_apply(key) - - assert_events([], key, "created events on in-sync key") - - assert(key.provider.exists?, "Key did not get created") - - # Now create a new key object - name = key.name - key = nil - @sshkeytype.clear - - key = @sshkeytype.create :name => name, :target => file, :provider => :parsed - key.retrieve - - assert(key.provider.exists?, "key thinks it does not exist") - - end - - def test_moddingkey - key = mkkey() - - assert_events([:sshkey_created], key) - - key.retrieve - - aliases = %w{madstop kirby yayness} - key[:alias] = aliases - - params = key.instance_variable_get("@parameters") - assert_events([:sshkey_changed], key) - - aliases.each do |name| - assert_equal(key, key.class[name], - "alias was not set") - end - end - - def test_aliasisproperty - assert_equal(:property, @sshkeytype.attrtype(:alias)) - end - - def test_multivalues - key = mkkey - assert_raise(Puppet::Error) { - key[:alias] = "puppetmasterd yayness" - } - end - - def test_puppetalias - key = mkkey() - - assert_nothing_raised { - key[:alias] = "testing" - } - - same = key.class["testing"] - assert(same, "Could not retrieve by alias") - end - - def test_removal - sshkey = mkkey() - assert_nothing_raised { - sshkey[:ensure] = :present - } - assert_events([:sshkey_created], sshkey) - - assert(sshkey.provider.exists?, "key was not created") - assert_nothing_raised { - sshkey[:ensure] = :absent - } - - assert_events([:sshkey_removed], sshkey) - assert(! sshkey.provider.exists?, "Key was not deleted") - assert_events([], sshkey) - end - - # Make sure changes actually modify the file. - def test_modifyingfile - keys = [] - names = [] - 3.times { - k = mkkey() - #h[:ensure] = :present - #h.retrieve - keys << k - names << k.name - } - assert_apply(*keys) - keys.clear - Puppet.type(:sshkey).clear - newkey = mkkey() - #newkey[:ensure] = :present - names << newkey.name - assert_apply(newkey) - - # Verify we can retrieve that info - assert_nothing_raised("Could not retrieve after second write") { - newkey.provider.class.prefetch - newkey.retrieve - } - - # And verify that we have data for everything - names.each { |name| - key = Puppet.type(:sshkey)[name] || - Puppet.type(:sshkey).create(:name => name) - assert(key, "Could not retrieve key for %s" % name) - assert(key.provider.exists?, "key %s is missing" % name) - } - end -end - diff --git a/test/ral/types/tidy.rb b/test/ral/types/tidy.rb deleted file mode 100755 index 60fad6516..000000000 --- a/test/ral/types/tidy.rb +++ /dev/null @@ -1,291 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' -require 'puppettest/support/utils' - -class TestTidy < Test::Unit::TestCase - include PuppetTest::Support::Utils - include PuppetTest::FileTesting - def mktmpfile - # because luke's home directory is on nfs, it can't be used for testing - # as root - tmpfile = tempfile() - File.open(tmpfile, "w") { |f| f.puts rand(100) } - @@tmpfiles.push tmpfile - return tmpfile - end - - def mktmpdir - dir = File.join(tmpdir(), "puppetlinkdir") - unless FileTest.exists?(dir) - Dir.mkdir(dir) - end - @@tmpfiles.push dir - return dir - end - - def test_tidydirs - dir = mktmpdir - file = File.join(dir, "file") - File.open(file, "w") { |f| - f.puts "some stuff" - } - - tidy = Puppet.type(:tidy).create( - :name => dir, - :size => "1b", - :rmdirs => true, - :recurse => true - ) - - assert_events([:file_tidied, :file_tidied], tidy) - - assert(!FileTest.exists?(file), "Tidied %s still exists" % file) - assert(!FileTest.exists?(dir), "Tidied %s still exists" % dir) - - end - - def disabled_test_recursion - source = mktmpdir() - FileUtils.cd(source) { - mkranddirsandfiles() - } - - link = nil - assert_nothing_raised { - link = newlink(:target => source, :recurse => true) - } - comp = mk_catalog("linktest",link) - cycle(comp) - - path = link.name - list = file_list(path) - FileUtils.cd(path) { - list.each { |file| - unless FileTest.directory?(file) - assert(FileTest.symlink?(file)) - target = File.readlink(file) - assert_equal(target,File.join(source,file.sub(/^\.\//,''))) - end - } - } - end - - # Test the different age iterations. - def test_age_conversions - tidy = Puppet::Type.newtidy :path => tempfile(), :age => "1m" - - convertors = { - :second => 1, - :minute => 60 - } - - convertors[:hour] = convertors[:minute] * 60 - convertors[:day] = convertors[:hour] * 24 - convertors[:week] = convertors[:day] * 7 - - # First make sure we default to days - assert_nothing_raised do - tidy[:age] = "2" - end - - assert_equal(2 * convertors[:day], tidy.should(:age), - "Converted 2 wrong") - - convertors.each do |name, number| - init = name.to_s[0..0] # The first letter - [0, 1, 5].each do |multi| - [init, init.upcase].each do |letter| - age = multi.to_s + letter.to_s - assert_nothing_raised do - tidy[:age] = age - end - - assert_equal(multi * convertors[name], tidy.should(:age), - "Converted %s wrong" % age) - end - end - end - end - - def test_size_conversions - convertors = { - :b => 0, - :kb => 1, - :mb => 2, - :gb => 3 - } - - tidy = Puppet::Type.newtidy :path => tempfile(), :age => "1m" - - # First make sure we default to kb - assert_nothing_raised do - tidy[:size] = "2" - end - - assert_equal(2048, tidy.should(:size), - "Converted 2 wrong") - - convertors.each do |name, number| - init = name.to_s[0..0] # The first letter - [0, 1, 5].each do |multi| - [init, init.upcase].each do |letter| - size = multi.to_s + letter.to_s - assert_nothing_raised do - tidy[:size] = size - end - - total = multi - number.times do total *= 1024 end - - assert_equal(total, tidy.should(:size), - "Converted %s wrong" % size) - end - end - end - end - - def test_agetest - tidy = Puppet::Type.newtidy :path => tempfile(), :age => "1m" - - age = tidy.property(:age) - - # Set it to something that should be fine - assert(age.insync?(Time.now.to_i - 5), "Tried to tidy a low age") - - # Now to something that should fail - assert(! age.insync?(Time.now.to_i - 120), "Incorrectly skipped tidy") - end - - def test_sizetest - tidy = Puppet::Type.newtidy :path => tempfile(), :size => "1k" - - size = tidy.property(:size) - - # Set it to something that should be fine - assert(size.insync?(50), "Tried to tidy a low size") - - # Now to something that should fail - assert(! size.insync?(2048), "Incorrectly skipped tidy") - end - - # Make sure we can remove different types of files - def test_tidytypes - path = tempfile() - tidy = Puppet::Type.newtidy :path => path, :size => "1b", :age => "1s" - - # Start with a file - File.open(path, "w") { |f| f.puts "this is a test" } - assert_events([:file_tidied], tidy) - assert(! FileTest.exists?(path), "File was not removed") - - # Then a link - dest = tempfile - File.open(dest, "w") { |f| f.puts "this is a test" } - File.symlink(dest, path) - assert_events([:file_tidied], tidy) - assert(! FileTest.exists?(path), "Link was not removed") - assert(FileTest.exists?(dest), "Destination was removed") - - # And a directory - Dir.mkdir(path) - tidy[:rmdirs] = true - assert_events([:file_tidied], tidy) - assert(! FileTest.exists?(path), "File was not removed") - end - - # Make sure we can specify either attribute and get appropriate behaviour. - # I found that the original implementation of this did not work unless both - # size and age were specified. - def test_one_attribute - path = tempfile() - File.open(path, "w") { |f| 10.times { f.puts "yayness " } } - tidy = Puppet::Type.type(:tidy).create :path => path, :size => "1b" - - assert_apply(tidy) - assert(! FileTest.exists?(path), "file did not get tidied") - - tidy.class.clear - - # Now try one with just an age attribute. - time = Time.now - 10 - stat = stub 'stat', :mtime => time, :atime => time, :ftype => "file" - File.stubs(:lstat) - File.stubs(:lstat).with(path).returns(stat) - - File.open(path, "w") { |f| 10.times { f.puts "yayness " } } - tidy = Puppet::Type.type(:tidy).create :path => path, :age => "5s" - - - assert_apply(tidy) - assert(! FileTest.exists?(path), "file did not get tidied") - end - - # Testing #355. - def test_remove_dead_links - dir = tempfile() - link = File.join(dir, "link") - target = tempfile() - Dir.mkdir(dir) - File.symlink(target, link) - - tidy = Puppet::Type.newtidy :path => dir, :size => "1b", :recurse => true - assert_apply(tidy) - assert(! FileTest.symlink?(link), "link was not tidied") - end - - def test_glob_matches_single - dir = mktmpdir - files = { - :remove => File.join(dir, "01-foo"), - :keep => File.join(dir, "default") - } - files.each do |tag, file| - File.open(file, "w") { |f| - f.puts "some stuff" - } - end - - tidy = Puppet.type(:tidy).create( - :name => dir, - :size => "1b", - :rmdirs => true, - :recurse => true, - :matches => "01-*" - ) - assert_apply(tidy) - - assert(FileTest.exists?(files[:keep]), "%s was tidied" % files[:keep]) - assert(!FileTest.exists?(files[:remove]), "Tidied %s still exists" % files[:remove]) - end - - def test_glob_matches_multiple - dir = mktmpdir - files = { - :remove1 => File.join(dir, "01-foo"), - :remove2 => File.join(dir, "02-bar"), - :keep1 => File.join(dir, "default") - } - files.each do |tag, file| - File.open(file, "w") { |f| - f.puts "some stuff" - } - end - - tidy = Puppet.type(:tidy).create( - :name => dir, - :size => "1b", - :rmdirs => true, - :recurse => true, - :matches => ["01-*", "02-*"] - ) - assert_apply(tidy) - - assert(FileTest.exists?(files[:keep1]), "%s was tidied" % files[:keep1]) - assert(!FileTest.exists?(files[:remove1]), "Tidied %s still exists" % files[:remove1]) - assert(!FileTest.exists?(files[:remove2]), "Tidied %s still exists" % files[:remove2]) - end -end - diff --git a/test/ral/types/user.rb b/test/ral/types/user.rb deleted file mode 100755 index b280acfed..000000000 --- a/test/ral/types/user.rb +++ /dev/null @@ -1,492 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' -require 'etc' - -class TestUser < Test::Unit::TestCase - include PuppetTest - - p = Puppet::Type.type(:user).provide :fake, :parent => PuppetTest::FakeProvider do - @name = :fake - apimethods - def create - @ensure = :present - @resource.send(:properties).each do |property| - next if property.name == :ensure - property.sync - end - end - - def delete - @ensure = :absent - @resource.send(:properties).each do |property| - send(property.name.to_s + "=", :absent) - end - end - - def exists? - if defined? @ensure and @ensure == :present - true - else - false - end - end - end - - FakeUserProvider = p - - @@fakeproviders[:group] = p - - def findshell(old = nil) - %w{/bin/sh /bin/bash /sbin/sh /bin/ksh /bin/zsh /bin/csh /bin/tcsh - /usr/bin/sh /usr/bin/bash /usr/bin/ksh /usr/bin/zsh /usr/bin/csh - /usr/bin/tcsh}.find { |shell| - if old - FileTest.exists?(shell) and shell != old - else - FileTest.exists?(shell) - end - } - end - - def setup - super - Puppet::Type.type(:user).defaultprovider = FakeUserProvider - end - - def teardown - Puppet::Type.type(:user).defaultprovider = nil - super - end - - def mkuser(name) - user = nil - assert_nothing_raised { - user = Puppet.type(:user).create( - :name => name, - :comment => "Puppet Testing User", - :gid => Puppet::Util::SUIDManager.gid, - :shell => findshell(), - :home => "/home/%s" % name - ) - } - - assert(user, "Did not create user") - - return user - end - - def attrtest_ensure(user) - old = user.provider.ensure - user[:ensure] = :absent - - comp = mk_catalog("ensuretest", user) - assert_apply(user) - assert(!user.provider.exists?, "User is still present") - user[:ensure] = :present - assert_events([:user_created], comp) - assert(user.provider.exists?, "User is absent") - user[:ensure] = :absent - trans = assert_events([:user_removed], comp) - - assert_rollback_events(trans, [:user_created], "user") - - user[:ensure] = old - assert_apply(user) - end - - def attrtest_comment(user) - user.retrieve - old = user.provider.comment - user[:comment] = "A different comment" - - comp = mk_catalog("commenttest", user) - - trans = assert_events([:user_changed], comp, "user") - - assert_equal("A different comment", user.provider.comment, - "Comment was not changed") - - assert_rollback_events(trans, [:user_changed], "user") - - assert_equal(old, user.provider.comment, - "Comment was not reverted") - end - - def attrtest_home(user) - obj = nil - comp = mk_catalog("hometest", user) - - old = user.provider.home - user[:home] = old - - trans = assert_events([], comp, "user") - - user[:home] = "/tmp" - - trans = assert_events([:user_changed], comp, "user") - - assert_equal("/tmp", user.provider.home, "Home was not changed") - - assert_rollback_events(trans, [:user_changed], "user") - - assert_equal(old, user.provider.home, "Home was not reverted") - end - - def attrtest_shell(user) - old = user.provider.shell - comp = mk_catalog("shelltest", user) - - user[:shell] = old - - trans = assert_events([], comp, "user") - - newshell = findshell(old) - - unless newshell - $stderr.puts "Cannot find alternate shell; skipping shell test" - return - end - - user[:shell] = newshell - - trans = assert_events([:user_changed], comp, "user") - - user.retrieve - assert_equal(newshell, user.provider.shell, - "Shell was not changed") - - assert_rollback_events(trans, [:user_changed], "user") - user.retrieve - - assert_equal(old, user.provider.shell, "Shell was not reverted") - end - - def attrtest_gid(user) - obj = nil - old = user.provider.gid - comp = mk_catalog("gidtest", user) - - user.retrieve - - user[:gid] = old - - trans = assert_events([], comp, "user") - - newgid = %w{nogroup nobody staff users daemon}.find { |gid| - begin - group = Etc.getgrnam(gid) - rescue ArgumentError => detail - next - end - old != group.gid and group.gid > 0 - } - - unless newgid - $stderr.puts "Cannot find alternate group; skipping gid test" - return - end - - # first test by name - assert_nothing_raised("Failed to specify group by name") { - user[:gid] = newgid - } - - trans = assert_events([:user_changed], comp, "user") - - # then by id - newgid = Etc.getgrnam(newgid).gid - - assert_nothing_raised("Failed to specify group by id for %s" % newgid) { - user[:gid] = newgid - } - - user.retrieve - - assert_events([], comp, "user") - - assert_equal(newgid, user.provider.gid, "GID was not changed") - - assert_rollback_events(trans, [:user_changed], "user") - - assert_equal(old, user.provider.gid, "GID was not reverted") - end - - def attrtest_uid(user) - obj = nil - comp = mk_catalog("uidtest", user) - - user.provider.uid = 1 - - old = 1 - newuid = 1 - while true - newuid += 1 - - if newuid - old > 1000 - $stderr.puts "Could not find extra test UID" - return - end - begin - newuser = Etc.getpwuid(newuid) - rescue ArgumentError => detail - break - end - end - - assert_nothing_raised("Failed to change user id") { - user[:uid] = newuid - } - - trans = assert_events([:user_changed], comp, "user") - - assert_equal(newuid, user.provider.uid, "UID was not changed") - - assert_rollback_events(trans, [:user_changed], "user") - - assert_equal(old, user.provider.uid, "UID was not reverted") - end - - def attrtest_groups(user) - Etc.setgrent - max = 0 - while group = Etc.getgrent - if group.gid > max and group.gid < 5000 - max = group.gid - end - end - - groups = [] - main = [] - extra = [] - 5.times do |i| - i += 1 - name = "pptstgr%s" % i - groups << name - if i < 3 - main << name - else - extra << name - end - end - - assert(user[:membership] == :minimum, "Membership did not default correctly") - - assert_nothing_raised { - user.retrieve - } - - # Now add some of them to our user - assert_nothing_raised { - user[:groups] = extra - } - assert_nothing_raised { - user.retrieve - } - - assert_instance_of(String, user.property(:groups).should) - - # Some tests to verify that groups work correctly startig from nothing - # Remove our user - user[:ensure] = :absent - assert_apply(user) - - assert_nothing_raised do - user.retrieve - end - - # And add it again - user[:ensure] = :present - assert_apply(user) - - # Make sure that the groups are a string, not an array - assert(user.provider.groups.is_a?(String), - "Incorrectly passed an array to groups") - - currentvalue = user.retrieve - - assert(currentvalue[user.property(:groups)], "Did not retrieve group list") - - list = currentvalue[user.property(:groups)] - assert_equal(extra.sort, list.sort, "Group list is not equal") - - # Now set to our main list of groups - assert_nothing_raised { - user[:groups] = main - } - - assert_equal((main + extra).sort, user.property(:groups).should.split(",").sort) - - currentvalue = nil - assert_nothing_raised { - currentvalue = user.retrieve - } - - assert(!user.insync?(currentvalue), "User is incorrectly in sync") - - assert_apply(user) - - assert_nothing_raised { - currentvalue = user.retrieve - } - - # We're not managing inclusively, so it should keep the old group - # memberships and add the new ones - list = currentvalue[user.property(:groups)] - assert_equal((main + extra).sort, list.sort, "Group list is not equal") - - assert_nothing_raised { - user[:membership] = :inclusive - } - assert_nothing_raised { - currentvalue = user.retrieve - } - - assert(!user.insync?(currentvalue), "User is incorrectly in sync") - - assert_events([:user_changed], user) - assert_nothing_raised { - currentvalue = user.retrieve - } - - list = currentvalue[user.property(:groups)] - assert_equal(main.sort, list.sort, "Group list is not equal") - - # Set the values a bit differently. - user.property(:groups).should = list.sort { |a,b| b <=> a } - - assert(user.property(:groups).insync?(list.sort), "Groups property did not sort groups") - - user.delete(:groups) - end - - def test_autorequire - file = tempfile() - comp = nil - user = nil - group =nil - home = nil - ogroup = nil - assert_nothing_raised { - user = Puppet.type(:user).create( - :name => "pptestu", - :home => file, - :gid => "pptestg", - :groups => "yayness" - ) - home = Puppet.type(:file).create( - :path => file, - :owner => "pptestu", - :ensure => "directory" - ) - group = Puppet.type(:group).create( - :name => "pptestg" - ) - ogroup = Puppet.type(:group).create( - :name => "yayness" - ) - comp = mk_catalog(user, group, home, ogroup) - } - - rels = nil - assert_nothing_raised() { rels = user.autorequire } - - assert(rels.detect { |r| r.source == group }, "User did not require group") - assert(rels.detect { |r| r.source == ogroup }, "User did not require other groups") - assert_nothing_raised() { rels = home.autorequire } - assert(rels.detect { |r| r.source == user }, "Homedir did not require user") - end - - def test_simpleuser - name = "pptest" - - user = mkuser(name) - - comp = mk_catalog("usercomp", user) - - trans = assert_events([:user_created], comp, "user") - - assert_equal(user.should(:comment), user.provider.comment, - "Comment was not set correctly") - - assert_rollback_events(trans, [:user_removed], "user") - - assert(! user.provider.exists?, "User did not get deleted") - end - - def test_allusermodelproperties - user = nil - name = "pptest" - - user = mkuser(name) - - assert(! user.provider.exists?, "User %s is present" % name) - - comp = mk_catalog("usercomp", user) - - trans = assert_events([:user_created], comp, "user") - - user.retrieve - assert_equal("Puppet Testing User", user.provider.comment, - "Comment was not set") - - tests = Puppet.type(:user).validproperties - - tests.each { |test| - if self.respond_to?("attrtest_%s" % test) - self.send("attrtest_%s" % test, user) - else - Puppet.err "Not testing attr %s of user" % test - end - } - - user[:ensure] = :absent - assert_apply(user) - end - - # Testing #455 - def test_autorequire_with_no_group_should - user = Puppet::Type.type(:user).create(:name => "yaytest", :check => :all) - - assert_nothing_raised do - user.autorequire - end - - user[:ensure] = :absent - - assert_nothing_raised do - user.evaluate - end - - assert(user.send(:property, :groups).insync?(nil), - "Groups state considered out of sync with no :should value") - end - - # Make sure the 'managehome' param can only be set when the provider - # has that feature. Uses a patch from #432. - def test_managehome - user = Puppet::Type.type(:user).create(:name => "yaytest", :check => :all) - - prov = user.provider - - home = false - prov.class.meta_def(:manages_homedir?) { home } - - assert_nothing_raised("failed on false managehome") do - user[:managehome] = false - end - - assert_raise(ArgumentError, "did not fail when managehome? is false") do - user[:managehome] = true - end - - home = true - assert(prov.class.manages_homedir?, "provider did not enable homedir") - assert_nothing_raised("failed when managehome is true") do - user[:managehome] = true - end - end -end - diff --git a/test/ral/types/yumrepo.rb b/test/ral/types/yumrepo.rb deleted file mode 100755 index 899a02135..000000000 --- a/test/ral/types/yumrepo.rb +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' -require 'fileutils' - -class TestYumRepo < Test::Unit::TestCase - include PuppetTest - - def setup - super - @yumdir = tempfile() - Dir.mkdir(@yumdir) - @yumconf = File.join(@yumdir, "yum.conf") - File.open(@yumconf, "w") do |f| - f.print "[main]\nreposdir=#{@yumdir} /no/such/dir\n" - end - Puppet.type(:yumrepo).yumconf = @yumconf - end - - # Modify one existing section - def test_modify - copy_datafiles - devel = make_repo("development", { :descr => "New description" }) - current_values = devel.retrieve - assert_equal("development", devel[:name]) - assert_equal('Fedora Core $releasever - Development Tree', - current_values[devel.property(:descr)]) - assert_equal('New description', - devel.property(:descr).should) - assert_apply(devel) - inifile = Puppet.type(:yumrepo).read() - assert_equal('New description', inifile['development']['name']) - assert_equal('Fedora Core $releasever - $basearch - Base', - inifile['base']['name']) - assert_equal("foo\n bar\n baz", inifile['base']['exclude']) - assert_equal(['base', 'development', 'main'], - all_sections(inifile)) - end - - # Create a new section - def test_create - values = { - :descr => "Fedora Core $releasever - $basearch - Base", - :baseurl => "http://example.com/yum/$releasever/$basearch/os/", - :enabled => "1", - :gpgcheck => "1", - :includepkgs => "absent", - :gpgkey => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora" - } - repo = make_repo("base", values) - - assert_apply(repo) - inifile = Puppet.type(:yumrepo).read() - sections = all_sections(inifile) - assert_equal(['base', 'main'], sections) - text = inifile["base"].format - assert_equal(CREATE_EXP, text) - end - - # Delete mirrorlist by setting it to :absent and enable baseurl - def test_absent - copy_datafiles - baseurl = 'http://example.com/' - devel = make_repo("development", - { :mirrorlist => 'absent', - :baseurl => baseurl }) - devel.retrieve - assert_apply(devel) - inifile = Puppet.type(:yumrepo).read() - sec = inifile["development"] - assert_nil(sec["mirrorlist"]) - assert_equal(baseurl, sec["baseurl"]) - end - - def make_repo(name, hash={}) - hash[:name] = name - Puppet.type(:yumrepo).create(hash) - end - - def all_sections(inifile) - sections = [] - inifile.each_section { |section| sections << section.name } - return sections.sort - end - - def copy_datafiles - fakedata("data/types/yumrepos").select { |file| - file =~ /\.repo$/ - }.each { |src| - dst = File::join(@yumdir, File::basename(src)) - FileUtils::copy(src, dst) - } - end - - CREATE_EXP = <<'EOF' -[base] -name=Fedora Core $releasever - $basearch - Base -baseurl=http://example.com/yum/$releasever/$basearch/os/ -enabled=1 -gpgcheck=1 -gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora -EOF - -end diff --git a/test/ral/types/zone.rb b/test/ral/types/zone.rb deleted file mode 100755 index eb485b944..000000000 --- a/test/ral/types/zone.rb +++ /dev/null @@ -1,420 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' -require 'puppet/type/zone' - -class TestZone < PuppetTest::TestCase - confine "Zones are only functional on Solaris" => (Facter["operatingsystem"].value == "Solaris") - - def setup - super - @@zones = [] - end - - def mkzone(name) - zone = nil - - base = tempfile() - Dir.mkdir(base) - File.chmod(0700, base) - root = File.join(base, "zonebase") - assert_nothing_raised { - zone = Puppet::Type.type(:zone).create( - :name => name, - :path => root, - :ensure => "configured" # don't want to install zones automatically - ) - } - - @@zones << name - - return zone - end - - def test_instances - list = nil - assert_nothing_raised { - list = Puppet::Type.type(:zone).instances - } - - assert(! list.empty?, "Got no zones back") - - assert(list.find { |z| z[:name] == "global" }, "Could not find global zone") - end - - def test_state_sequence - zone = mkzone("slicetest") - - property = zone.property(:ensure) - - slice = nil - assert_nothing_raised { - slice = property.class.state_sequence(:absent, :installed).collect do |o| - o[:name] - end - } - - - assert_equal([:configured, :installed], slice) - - assert_nothing_raised { - slice = property.class.state_sequence(:running, :installed).collect do |o| - o[:name] - end - } - - - assert_equal(slice, [:installed]) - - end - - # Make sure the ensure stuff behaves as we expect - def test_zoneensure - zone = mkzone("ensurezone") - - property = zone.property(:ensure) - - assert(property, "Did not get ensure property") - - values = nil - assert_nothing_raised { - values = zone.retrieve - } - - assert(! property.insync?(values[property]), "Property is somehow in sync") - - assert(property.up?, "Property incorrectly thinks it is not moving up") - - zone[:ensure] = :installed - assert(property.up?, "Property incorrectly thinks it is not moving up") - zone[:ensure] = :absent - assert(! property.up?, "Property incorrectly thinks it is moving up") - end - - # Make sure all mentioned methods actually exist. - def test_zonemethods_exist - methods = [] - zone = mkzone("methodtest") - - property = zone.property(:ensure) - assert_nothing_raised { - property.class.state_sequence(:absent, :running).each do |st| - [:up, :down].each do |m| - if st[m] - methods << st[m] - end - end - end - } - - methods.each do |m| - Puppet::Type.type(:zone).suitableprovider.each do |prov| - assert(prov.method_defined?(m), - "Zone provider %s does not define method %s" % - [prov.name, m]) - end - end - - end - - # Make sure our property generates the correct text. - def test_inherit_property - zone = mkzone("configtesting") - zone[:ensure] = :configured - - assert_nothing_raised { - zone[:inherit] = "/usr" - } - property = zone.property(:inherit) - assert(zone, "Did not get 'inherit' property") - - assert_equal("add inherit-pkg-dir\nset dir=/usr\nend", property.configtext, - "Got incorrect config text") - - zone.provider.inherit = "/usr" - - assert_equal("", property.configtext, - "Got incorrect config text") - - # Now we want multiple directories - property.should = %w{/usr /sbin /lib} - - # The statements are sorted - text = "add inherit-pkg-dir -set dir=/lib -end -add inherit-pkg-dir -set dir=/sbin -end" - - assert_equal(text, property.configtext, - "Got incorrect config text") - - zone.provider.inherit = %w{/usr /sbin /lib} - property.should = %w{/usr /sbin} - - text = "remove inherit-pkg-dir dir=/lib" - - assert_equal(text, property.configtext, - "Got incorrect config text") - end -end - -class TestZoneAsRoot < TestZone - confine "Not running Zone creation tests" => Puppet.features.root? - confine "Zones are only functional on Solaris" => (Facter["operatingsystem"].value == "Solaris") - - def teardown - current = %x{zoneadm list -cp}.split("\n").inject({}) { |h, line| - ary = line.split(":") - h[ary[1]] = ary[2] - h - } - - Puppet::Type.type(:zone).clear - - # Get rid of any lingering zones - @@zones.each do |zone| - next unless current.include? zone - - obj = Puppet::Type.type(:zone).create(:name => zone) - obj[:ensure] = :absent - assert_apply(obj) - end - - # We can't delete the temp files until the zones are stopped and removed. - super - end - # Make sure our ensure process actually works. - def test_ensure_sync - zone = mkzone("ensuretesting") - - zone[:ensure] = :configured - - assert_apply(zone) - - assert(zone.insync?(zone.retrieve), "Zone is not insync") - end - - def test_getconfig - zone = mkzone("configtesting") - - base = tempfile() - zone[:path] = base - - ip = "192.168.0.1" - interface = "bge0" - zone[:ip] = "#{interface}:#{ip}" - - IO.popen("zonecfg -z configtesting -f -", "w") do |f| - f.puts %{create -b -set zonepath=#{tempfile()} -set autoboot=true -add inherit-pkg-dir -set dir=/lib -end -add inherit-pkg-dir -set dir=/platform -end -add inherit-pkg-dir -set dir=/sbin -end -add inherit-pkg-dir -set dir=/opt/csw -end -add inherit-pkg-dir -set dir=/usr -end -add net -set address=#{ip} -set physical=bge0 -end -} - end - - assert_equal(0, $?, "Did not successfully create zone") - - hash = nil - assert_nothing_raised { - hash = zone.provider.send(:getconfig) - } - - zone[:check] = [:inherit, :autoboot] - - values = nil - assert_nothing_raised("Could not retrieve zone values") do - values = zone.retrieve.inject({}) { |result, newvals| result[newvals[0].name] = newvals[1]; result } - end - - # And make sure it gets set correctly. - assert_equal(%w{/sbin /usr /opt/csw /lib /platform}.sort, - values[:inherit].sort, "Inherited dirs did not get collected correctly." - ) - - assert_equal(["#{interface}:#{ip}"], values[:ip], - "IP addresses did not get collected correctly.") - - assert_equal(:true, values[:autoboot], - "Autoboot did not get collected correctly.") - end - - # Make sure we can do all the various and sundry configuring things. - def test_configuring_zones - zone = mkzone("configtesting") - - assert_nothing_raised { - zone[:inherit] = "/usr" - } - - zone[:ensure] = :configured - - assert_apply(zone) - - assert(zone.insync?(zone.retrieve), "Zone is not insync") - - # Now add a new directory to inherit - assert_nothing_raised { - zone[:inherit] = ["/sbin", "/usr"] - } - assert_apply(zone) - - assert(zone.insync?(zone.retrieve), "Zone is not insync") - - assert(%x{/usr/sbin/zonecfg -z #{zone[:name]} info} =~ /dir: \/sbin/, - "sbin was not added") - - # And then remove it. - assert_nothing_raised { - zone[:inherit] = "/usr" - } - assert_apply(zone) - - assert(zone.insync?(zone.retrieve), "Zone is not insync") - - assert(%x{/usr/sbin/zonecfg -z #{zone[:name]} info} !~ /dir: \/sbin/, - "sbin was not removed") - - # Now add an ip adddress. Fortunately (or not), zonecfg doesn't verify - # that the interface exists. - zone[:ip] = "hme0:192.168.0.1" - - assert(! zone.insync?(zone.retrieve), "Zone is marked as in sync") - - assert_apply(zone) - assert(zone.insync?(zone.retrieve), "Zone is not in sync") - assert(%x{/usr/sbin/zonecfg -z #{zone[:name]} info} =~ /192.168.0.1/, - "ip was not added") - zone[:ip] = ["hme1:192.168.0.2", "hme0:192.168.0.1"] - assert_apply(zone) - assert(zone.insync?(zone.retrieve), "Zone is not in sync") - assert(%x{/usr/sbin/zonecfg -z #{zone[:name]} info} =~ /192.168.0.2/, - "ip was not added") - zone[:ip] = ["hme1:192.168.0.2"] - assert_apply(zone) - zone.retrieve - assert(%x{/usr/sbin/zonecfg -z #{zone[:name]} info} !~ /192.168.0.1/, - "ip was not removed") - end - - # Test creating and removing a zone, but only up to the configured property, - # so it's faster. - def test_smallcreate - zone = mkzone("smallcreate") - # Include a bunch of stuff so the zone isn't as large - dirs = %w{/usr /sbin /lib /platform} - - %w{/opt/csw}.each do |dir| - dirs << dir if FileTest.exists? dir - end - zone[:inherit] = dirs - - assert(zone, "Did not make zone") - - zone[:ensure] = :configured - - assert(! zone.insync?(zone.retrieve), "Zone is incorrectly in sync") - - assert_apply(zone) - - assert(zone.insync?(zone.retrieve), "Zone is incorrectly out of sync") - - zone[:ensure] = :absent - - assert_apply(zone) - - currentvalues = zone.retrieve - - assert_equal(:absent, currentvalues[zone.property(:ensure)], - "Zone is not absent") - end - - # Just go through each method linearly and make sure it works. - def test_each_method - zone = mkzone("methodtesting") - dirs = %w{/usr /sbin /lib /platform} - - %w{/opt/csw}.each do |dir| - dirs << dir if FileTest.exists? dir - end - zone[:inherit] = dirs - - [[:configure, :configured], - [:install, :installed], - [:start, :running], - [:stop, :installed], - [:uninstall, :configured], - [:unconfigure, :absent] - ].each do |method, property| - Puppet.info "Testing %s" % method - current_values = nil - assert_nothing_raised { - current_values = zone.retrieve - } - assert_nothing_raised { - zone.provider.send(method) - } - current_values = nil - assert_nothing_raised { - current_values = zone.retrieve - } - assert_equal(property, current_values[zone.property(:ensure)], - "Method %s did not correctly set property %s" % - [method, property]) - end - end - - def test_mkzone - zone = mkzone("testmaking") - # Include a bunch of stuff so the zone isn't as large - dirs = %w{/usr /sbin /lib /platform} - - %w{/opt/csw}.each do |dir| - dirs << dir if FileTest.exists? dir - end - zone[:inherit] = dirs - - assert(zone, "Did not make zone") - - - [:configured, :installed, :running, :installed, :absent].each do |value| - assert_nothing_raised { - zone[:ensure] = value - } - assert(! zone.insync?(zone.retrieve), "Zone is incorrectly in sync") - - assert_apply(zone) - - assert_nothing_raised { - assert(zone.insync?(zone.retrieve), "Zone is incorrectly out of sync") - } - end - - currentvalues = zone.retrieve - - assert_equal(:absent, currentvalues[zone.property(:ensure)], - "Zone is not absent") - end -end - -- cgit From 7ca0ad64f486c5dc50513e6d06c8e0725ce4f7f8 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Fri, 29 Feb 2008 11:50:17 -0600 Subject: Fixing a test that changed the environment for all later tests, thus breaking some of them. --- lib/puppet/network/client/master.rb | 11 ++++++----- test/network/client/master.rb | 10 +--------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/lib/puppet/network/client/master.rb b/lib/puppet/network/client/master.rb index 390f3d4e2..913c51b3d 100644 --- a/lib/puppet/network/client/master.rb +++ b/lib/puppet/network/client/master.rb @@ -26,14 +26,15 @@ class Puppet::Network::Client::Master < Puppet::Network::Client down = Puppet[:downcasefacts] - facts = {} - Facter.each { |name,fact| + facts = Facter.to_hash.inject({}) do |newhash, array| + name, fact = array if down - facts[name] = fact.to_s.downcase + newhash[name] = fact.to_s.downcase else - facts[name] = fact.to_s + newhash[name] = fact.to_s end - } + newhash + end # Add our client version to the list of facts, so people can use it # in their manifests diff --git a/test/network/client/master.rb b/test/network/client/master.rb index 67c47fa6d..41796575f 100755 --- a/test/network/client/master.rb +++ b/test/network/client/master.rb @@ -216,15 +216,7 @@ end name = "environment" value = "test_environment" - Puppet[:filetimeout] = -1 - Puppet[:factsource] = tempfile() - Dir.mkdir(Puppet[:factsource]) - file = File.join(Puppet[:factsource], "#{name}.rb") - File.open(file, "w") do |f| - f.puts %{Facter.add("#{name}") do setcode { "#{value}" } end } - end - - Puppet::Network::Client.master.getfacts + Facter.stubs(:to_hash).returns(name => value) assert_equal(value, Puppet::Network::Client.master.facts[name]) end -- cgit From 857814ac80cf4f0c9913ccb6d2d42355670ea64f Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Fri, 29 Feb 2008 11:51:15 -0600 Subject: Fixing tests that did not work with Rails 2. --- test/rails/railsparameter.rb | 2 ++ test/rails/railsresource.rb | 1 + 2 files changed, 3 insertions(+) diff --git a/test/rails/railsparameter.rb b/test/rails/railsparameter.rb index d83115b1a..7c99ac38d 100755 --- a/test/rails/railsparameter.rb +++ b/test/rails/railsparameter.rb @@ -25,6 +25,8 @@ class TestRailsParameter < Test::Unit::TestCase source = parser.newclass "myclass" host = Puppet::Rails::Host.new(:name => "myhost") + + host.save resource = host.resources.create( :title => "/tmp/to_resource", diff --git a/test/rails/railsresource.rb b/test/rails/railsresource.rb index 58058472d..3df5001be 100755 --- a/test/rails/railsresource.rb +++ b/test/rails/railsresource.rb @@ -29,6 +29,7 @@ class TestRailsResource < Test::Unit::TestCase def mktest_resource # We need a host for resources host = Puppet::Rails::Host.new(:name => "myhost") + host.save # Now build a resource resource = host.resources.create( -- cgit From 4c3fa7806d12f86fce01030aa5e3745e698cb3c0 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Fri, 29 Feb 2008 12:00:39 -0600 Subject: Fixing a few more loading order issues. --- bin/puppetmasterd | 1 + lib/puppet.rb | 1 + lib/puppet/network.rb | 3 +++ 3 files changed, 5 insertions(+) create mode 100644 lib/puppet/network.rb diff --git a/bin/puppetmasterd b/bin/puppetmasterd index a00186b68..33e4f436d 100755 --- a/bin/puppetmasterd +++ b/bin/puppetmasterd @@ -81,6 +81,7 @@ end require 'getoptlong' require 'puppet' +require 'puppet/network/handler' require 'puppet/sslcertificates' options = [ diff --git a/lib/puppet.rb b/lib/puppet.rb index 18037cdc1..57f84d5f7 100644 --- a/lib/puppet.rb +++ b/lib/puppet.rb @@ -423,6 +423,7 @@ module Puppet end require 'puppet/type' +require 'puppet/network' require 'puppet/module' require 'puppet/util/storage' require 'puppet/parser/interpreter' diff --git a/lib/puppet/network.rb b/lib/puppet/network.rb new file mode 100644 index 000000000..8993b8869 --- /dev/null +++ b/lib/puppet/network.rb @@ -0,0 +1,3 @@ +# Just a stub, so we can correctly scope other classes. +module Puppet::Network # :nodoc: +end -- cgit From 65b72676aef2d58314f546eb31780d1b9925b9b3 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Fri, 29 Feb 2008 12:04:42 -0600 Subject: Fixing the fact that resources that model defined resources were getting finished multiple times, which meant they got multiple copies of metaparams. --- lib/puppet/parser/resource.rb | 7 +++++++ spec/unit/parser/resource.rb | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/lib/puppet/parser/resource.rb b/lib/puppet/parser/resource.rb index 46be89ca2..b001e165b 100644 --- a/lib/puppet/parser/resource.rb +++ b/lib/puppet/parser/resource.rb @@ -82,12 +82,19 @@ class Puppet::Parser::Resource # Do any finishing work on this object, called before evaluation or # before storage/translation. def finish + return if finished? + @finished = true add_defaults() add_metaparams() add_scope_tags() validate() end + # Has this resource already been finished? + def finished? + defined?(@finished) and @finished + end + def initialize(options) # Set all of the options we can. options.each do |option, value| diff --git a/spec/unit/parser/resource.rb b/spec/unit/parser/resource.rb index 035590341..9ce7b391b 100755 --- a/spec/unit/parser/resource.rb +++ b/spec/unit/parser/resource.rb @@ -67,6 +67,12 @@ describe Puppet::Parser::Resource do @resource = Puppet::Parser::Resource.new(:type => "mydefine", :title => "whatever", :scope => @scope, :source => @source) end + it "should do nothing if it has already been finished" do + @resource.finish + @resource.expects(:add_metaparams).never + @resource.finish + end + it "should copy metaparams from its scope" do @scope.setvar("noop", "true") -- cgit