diff options
| -rw-r--r-- | lib/puppet.rb | 29 | ||||
| -rw-r--r-- | lib/puppet/transportable.rb | 18 | ||||
| -rw-r--r-- | lib/puppet/type.rb | 32 | ||||
| -rw-r--r-- | lib/puppet/type/component.rb | 9 | ||||
| -rwxr-xr-x | lib/puppet/type/cron.rb | 310 | ||||
| -rw-r--r-- | lib/puppet/type/service.rb | 6 | ||||
| -rwxr-xr-x | test/types/tc_cron.rb | 135 | ||||
| -rwxr-xr-x | test/types/tc_exec.rb | 3 | ||||
| -rw-r--r-- | test/types/tc_service.rb | 73 | ||||
| -rw-r--r-- | test/types/tc_type.rb | 5 |
10 files changed, 460 insertions, 160 deletions
diff --git a/lib/puppet.rb b/lib/puppet.rb index bb1f0079a..8cd639eb3 100644 --- a/lib/puppet.rb +++ b/lib/puppet.rb @@ -160,6 +160,35 @@ module Puppet end end + def self.asuser(user) + # FIXME this should use our user object, since it already knows how + # to find users and such + require 'etc' + + begin + obj = Etc.getpwnam(user) + rescue ArgumentError + raise Puppet::Error, "User %s not found" + end + + uid = obj.uid + + olduid = nil + if Process.uid == uid + olduid = Process.uid + Process.euid = uid + end + + retval = yield + + + if olduid + Process.euid = olduid + end + + return retval + end + def self.setdefault(param,value) if value.is_a?(Array) if value[0].is_a?(Symbol) diff --git a/lib/puppet/transportable.rb b/lib/puppet/transportable.rb index 57e5f8377..9d1e85147 100644 --- a/lib/puppet/transportable.rb +++ b/lib/puppet/transportable.rb @@ -52,23 +52,7 @@ module Puppet def to_type retobj = nil if type = Puppet::Type.type(self.type) - begin - retobj = type.create(self) - rescue => detail - # FIXME TransObject should be handling what happens when there's an error - if Puppet[:debug] - if detail.respond_to?(:stack) - puts detail.stack - end - end - Puppet.err "Could not create %s: %s" % [self[:name], detail.to_s] - if retobj - retobj.destroy() - else - if obj = type[self[:name]] - obj.destroy() - end - end + unless retobj = type.create(self) return nil end retobj.file = @file diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb index 4826686b4..49190596a 100644 --- a/lib/puppet/type.rb +++ b/lib/puppet/type.rb @@ -499,6 +499,10 @@ class Type < Puppet::Element @dependencies.each { |dep| dep.unsubscribe(self) } + + if defined? @parent and @parent + @parent.delete(self) + end end #--------------------------------------------------------------- @@ -681,18 +685,38 @@ class Type < Puppet::Element public #--------------------------------------------------------------- - # force users to call this, so that we can merge objects if - # necessary + # Force users to call this, so that we can merge objects if + # necessary. FIXME This method should be responsible for most of the + # error handling. def self.create(hash) if name = hash["name"] || hash[:name] || hash[self.namevar] || hash[self.namevar.to_s] # if the object already exists if retobj = self[name] + # merge the new data retobj.merge(hash) return retobj else - return new(hash) + # create it anew + # if there's a failure, destroy the object if it got that far + begin + obj = new(hash) + rescue => detail + if Puppet[:debug] + if detail.respond_to?(:stack) + puts detail.stack + end + end + Puppet.err "Could not create %s: %s" % [name, detail.to_s] + if obj + Puppet.err obj + obj.destroy + elsif obj = self[name] + obj.destroy + end + return nil + end end else raise Puppet::Error, "You must specify a name for objects of type %s" % @@ -1308,7 +1332,7 @@ end require 'puppet/statechange' require 'puppet/type/component' -#require 'puppet/type/cron' +require 'puppet/type/cron' require 'puppet/type/exec' require 'puppet/type/group' require 'puppet/type/package' diff --git a/lib/puppet/type/component.rb b/lib/puppet/type/component.rb index 345afb75b..a81f62deb 100644 --- a/lib/puppet/type/component.rb +++ b/lib/puppet/type/component.rb @@ -52,6 +52,15 @@ module Puppet end end + def delete(child) + if @children.include?(child) + @children.delete(child) + return true + else + return false + end + end + def each @children.each { |child| yield child } end diff --git a/lib/puppet/type/cron.rb b/lib/puppet/type/cron.rb index 09d50c813..6f8b98367 100755 --- a/lib/puppet/type/cron.rb +++ b/lib/puppet/type/cron.rb @@ -1,72 +1,84 @@ -#!/usr/local/bin/ruby -w - -# $Id$ +# A Puppet::Type class to manage cron jobs. Some abstraction is done, +# so that different platforms' versions of +crontab+ all work equivalently. +require 'etc' require 'facter' require 'puppet/type/state' module Puppet + # The Puppet::CronType modules are responsible for the actual abstraction. + # They must implement three module functions: +read+, +write+, and +remove+, + # analogous to the three flags accepted by most implementations of +crontab+. + # All of these methods require the user name to be passed in. + # + # These modules operate on the strings that are ore become the cron tabs -- + # they do not have any semantic understanding of what they are reading or + # writing. module CronType + # Retrieve the uid of a user. This is duplication of code, but the unless + # I start using Puppet::Type::User objects here, it's a much better design. + def self.uid(user) + begin + return Etc.getpwnam(user).uid + rescue ArgumentError + raise Puppet::Error, "User %s not found" % user + end + end + + # This module covers nearly everyone; SunOS is only known exception so far. module Default + # Only add the -u flag when the user is different. Fedora apparently + # does not think I should be allowed to set the user to myself. + def self.cmdbase(user) + uid = CronType.uid(user) + cmd = nil + if uid == Process.uid + return "crontab" + else + return "crontab -u #{user}" + end + end + + # Read a specific user's cron tab. def self.read(user) - tab = %x{crontab -u #{user} -l 2>/dev/null} + tab = %x{#{self.cmdbase(user)} -l 2>/dev/null} end + # Remove a specific user's cron tab. def self.remove(user) - %x{crontab -u #{user} -r 2>/dev/null} + %x{#{self.cmdbase(user)} -r 2>/dev/null} end + # Overwrite a specific user's cron tab; must be passed the user name + # and the text with which to create the cron tab. def self.write(user, text) - IO.popen("crontab -u #{user} -", "w") { |p| + IO.popen("#{self.cmdbase(user)} -", "w") { |p| p.print text } end end + # SunOS has completely different cron commands; this module implements + # its versions. module SunOS - def self.asuser(user) - # FIXME this should use our user object, since it already does - # this for us - require 'etc' - - begin - obj = Etc.getpwnam(user) - rescue ArgumentError - raise Puppet::Error, "User %s not found" - end - - uid = obj.uid - - olduid = nil - if Process.uid == uid - olduid = Process.uid - Process.euid = uid - end - - retval = yield - - - if olduid - Process.euid = olduid - end - - return retval - end - + # Read a specific user's cron tab. def self.read(user) - self.asuser(user) { + Puppet.asuser(user) { %x{crontab -l 2>/dev/null} } end + # Remove a specific user's cron tab. def self.remove(user) - self.asuser(user) { + Puppet.asuser(user) { %x{crontab -r 2>/dev/null} } end + # Overwrite a specific user's cron tab; must be passed the user name + # and the text with which to create the cron tab. def self.write(user, text) - self.asuser(user) { + Puppet.asuser(user) { IO.popen("crontab", "w") { |p| p.print text } @@ -76,6 +88,13 @@ module Puppet end class State + # This is Cron's single state. Somewhat uniquely, this state does not + # actually change anything -- it just calls +@parent.sync+, which writes + # out the whole cron tab for the user in question. There is no real way + # to change individual cron jobs without rewriting the entire cron file. + # + # Note that this means that managing many cron jobs for a given user + # could currently result in multiple write sessions for that user. class CronCommand < Puppet::State @name = :command @doc = "The command to execute in the cron job. The environment @@ -84,12 +103,18 @@ module Puppet profile is not sourced when the command is run, so if the user's environment is desired it should be sourced manually." + # Normally this would retrieve the current value, but our state is not + # actually capable of doing so. The Cron class does the actual tab + # retrieval, so all this method does is default to :notfound for @is. def retrieve unless defined? @is and ! @is.nil? @is = :notfound end end + # Determine whether the cron job should be destroyed, and figure + # out which event to return. Finally, call @parent.sync to write the + # cron tab. def sync @parent.store @@ -99,6 +124,7 @@ module Puppet event = :cron_created elsif @should == :notfound # FIXME I need to actually delete the cronjob... + @parent.destroy event = :cron_deleted elsif @should == @is Puppet.err "Uh, they're both %s" % @should @@ -117,6 +143,10 @@ module Puppet end class Type + # Model the actual cron jobs. Supports all of the normal cron job fields + # as parameters, with the 'command' as the single state. Also requires a + # completely symbolic 'name' paremeter, which gets written to the file + # and is used to manage the job. class Cron < Type @states = [ Puppet::State::CronCommand @@ -149,10 +179,15 @@ module Puppet @paramdoc[:monthday] = "The day of the month on which to run the command. Optional; if specified, must be between 1 and 31." - @doc = "Installs cron jobs. All fields except the command + @doc = "Installs and manages cron jobs. All fields except the command and the user are optional, although specifying no periodic fields would result in the command being executed every - minute." + minute. While the name of the cron job is not part of the actual + job, it is used by Puppet to store and retrieve it. If you specify + a cron job that matches an existing job in every way except name, + then the jobs will be considered equivalent and the new name will + be permanently associated with that job. Once this association is + made and synced to disk, you can then manage the job normally." @name = :cron @namevar = :name @@ -174,9 +209,21 @@ module Puppet @crontype = Puppet::CronType::Default end - # FIXME so the fundamental problem is, what if the object - # already exists? + class << self + attr_accessor :crontype + end + + attr_accessor :uid + + # Override the Puppet::Type#[]= method so that we can store the instances + # in per-user arrays. Then just call +super+. + def self.[]=(name, object) + self.instance(object) + super + end + # In addition to removing the instances in @objects, Cron has to remove + # per-user cron tab information. def self.clear @instances = {} @loaded = {} @@ -184,14 +231,32 @@ module Puppet super end - def self.crontype - return @crontype + # Override the default Puppet::Type method, because instances + # also need to be deleted from the @instances hash + def self.delete(child) + if @instances.include?(child[:user]) + if @instances[child[:user]].include?(child) + @instances[child[:user]].delete(child) + end + end + super end + # Return the fields found in the cron tab. def self.fields return [:minute, :hour, :monthday, :month, :weekday, :command] end + # Return the header placed at the top of each generated file, warning + # users that modifying this file manually is probably a bad idea. + def self.header +%{#This file was autogenerated at #{Time.now} by puppet. While it +# can still be managed manually, it is definitely not recommended. +# Note particularly that the comments starting with 'Puppet Name' should +# not be deleted, as doing so could cause duplicate cron jobs.\n} + end + + # Store a new instance of a cron job. Called from Cron#initialize. def self.instance(obj) user = obj[:user] if @instances.include?(user) @@ -203,14 +268,22 @@ module Puppet end end - def self.retrieve(user) + # Parse a user's cron job into individual cron objects. + # + # Autogenerates names for any jobs that don't already have one; these + # names will get written back to the file. + # + # This method also stores existing comments, and it stores all cron + # jobs in order, mostly so that comments are retained in the order + # they were written and in proximity to the same jobs. + def self.parse(user, text) + count = 0 hash = {} name = nil unless @instances.include?(user) @instances[user] = [] end - #%x{crontab -u #{user} -l 2>/dev/null}.split("\n").each { |line| - @crontype.read(user).split("\n").each { |line| + text.chomp.split("\n").each { |line| case line when /^# Puppet Name: (\w+)$/: name = $1 when /^#/: @@ -237,7 +310,26 @@ module Puppet unless hash.include?(:command) raise Puppet::DevError, "No command for %s" % name end - unless cron = Puppet::Type::Cron[hash[:command]] + # if the cron already exists with that name... + if cron = Puppet::Type::Cron[hash[:command]] + # do nothing... + elsif tmp = @instances[user].reject { |obj| + ! obj.is_a?(Cron) + }.find { |obj| + obj.should(:command) == hash[:command] + } + # if we can find a cron whose spec exactly matches + + # we now have a cron job whose command exactly matches + # let's see if the other fields match + txt = tmp.to_cron.sub(/#.+\n/,'') + + if txt == line + cron = tmp + end + else + # create a new cron job, since no existing one + # seems to match cron = Puppet::Type::Cron.create( :name => name ) @@ -248,34 +340,57 @@ module Puppet } hash.clear name = nil + count += 1 end } - if $? == 0 - #return tab + end + + # Retrieve a given user's cron job, using the @crontype's +retrieve+ + # method. Returns nil if there was no cron job; else, returns the + # number of cron instances found. + def self.retrieve(user) + #%x{crontab -u #{user} -l 2>/dev/null}.split("\n").each { |line| + text = @crontype.read(user) + if $? != 0 + # there is no cron file + return nil else - #return nil + self.parse(user, text) end @loaded[user] = Time.now end + # Store the user's cron tab. Collects the text of the new tab and + # sends it to the +@crontype+ module's +write+ function. Also adds + # header warning users not to modify the file directly. def self.store(user) if @instances.include?(user) - @crontype.write(user, - @instances[user].collect { |obj| - if obj.is_a?(Cron) - obj.to_cron - else - obj.to_s - end - }.join("\n") - ) + @crontype.write(user, self.header + self.tab(user)) @synced[user] = Time.now else Puppet.notice "No cron instances for %s" % user end end + # Collect all Cron instances for a given user and convert them + # into literal text. + def self.tab(user) + if @instances.include?(user) + return @instances[user].collect { |obj| + if obj.is_a?(Cron) + obj.to_cron + else + obj.to_s + end + }.join("\n") + "\n" + else + Puppet.notice "No cron instances for %s" % user + end + end + + # Return the last time a given user's cron tab was loaded. Could + # be used for reducing writes, but currently is not. def self.loaded?(user) if @loaded.include?(user) return @loaded[user] @@ -284,11 +399,10 @@ module Puppet end end - def initialize(hash) - super - self.class.instance(self) - end - + # Because the current value is retrieved by the +@crontype+ module, + # the +is+ value on the state is set by an outside party. Cron is + # currently the only class that needs this, so this method is provided + # specifically for it. def is=(ary) param, value = ary if param.is_a?(String) @@ -302,6 +416,9 @@ module Puppet end end + # A method used to do parameter input handling. Converts integers in + # string form to actual integers, and returns the value if it's an integer + # or false if it's just a normal string. def numfix(num) if num =~ /^\d+$/ return num.to_i @@ -312,7 +429,9 @@ module Puppet end end - def limitcheck(num, lower, upper, type) + # Verify that a number is within the specified limits. Return the + # number if it is, or false if it is not. + def limitcheck(num, lower, upper) if num >= lower and num <= upper return num else @@ -320,7 +439,10 @@ module Puppet end end - def alphacheck(value, type, ary) + # Verify that a value falls within the specified array. Does case + # insensitive matching, and supports matching either the entire word + # or the first three letters of the word. + def alphacheck(value, ary) tmp = value.downcase if tmp.length == 3 ary.each_with_index { |name, index| @@ -337,20 +459,34 @@ module Puppet return false end - def parameter(value, type, lower, upper, alpha = nil, ary = nil) - retval = nil - if num = numfix(value) - retval = limitcheck(num, lower, upper, type) - elsif alpha - retval = alphacheck(value, type, ary) + # The method that does all of the actual parameter value checking; called + # by all of the +param<name>=+ methods. Requires the value, type, and + # bounds, and optionally supports a boolean of whether to do alpha + # checking, and if so requires the ary against which to do the checking. + def parameter(values, type, lower, upper, alpha = nil, ary = nil) + unless values.is_a?(Array) + if values =~ /,/ + values = values.split(/,/) + else + values = [values] + end end - if retval - @parameters[type] = retval - else - raise Puppet::Error, "%s is not a valid %s" % - [value, type] - end + @parameters[type] = values.collect { |value| + retval = nil + if num = numfix(value) + retval = limitcheck(num, lower, upper) + elsif alpha + retval = alphacheck(value, ary) + end + + if retval + @parameters[type] = retval + else + raise Puppet::Error, "%s is not a valid %s" % + [value, type] + end + } end def paramminute=(value) @@ -378,12 +514,15 @@ module Puppet begin obj = Etc.getpwnam(user) + @uid = obj.uid rescue ArgumentError - raise Puppet::Error, "User %s not found" + raise Puppet::Error, "User %s not found" % user end @parameters[:user] = user end + # Override the default Puppet::Type method because we need to call + # the +@crontype+ retrieve method. def retrieve unless @parameters.include?(:user) raise Puppet::Error, "You must specify the cron user" @@ -393,10 +532,13 @@ module Puppet @states[:command].retrieve end + # Write the entire user's cron tab out. def store self.class.store(@parameters[:user]) end + # Convert the current object a cron-style string. Adds the cron name + # as a comment above the cron job, in the form '# Puppet Name: <name>'. def to_cron hash = {:command => @states[:command].should || @states[:command].is } self.class.fields().reject { |f| f == :command }.each { |param| @@ -405,9 +547,15 @@ module Puppet return "# Puppet Name: %s\n" % self.name + self.class.fields.collect { |f| - hash[f] + if hash[f].is_a?(Array) + hash[f].join(",") + else + hash[f] + end }.join(" ") end end end end + +# $Id$ diff --git a/lib/puppet/type/service.rb b/lib/puppet/type/service.rb index a50af8ead..ff5fd779b 100644 --- a/lib/puppet/type/service.rb +++ b/lib/puppet/type/service.rb @@ -128,9 +128,10 @@ module Puppet @allowedmethods = [:setpath] def initialize(hash) + @searchpaths = [] super - unless defined? @searchpaths and @searchpaths.length >= 0 + unless defined? @searchpaths and @searchpaths.length > 0 raise Puppet::Error.new( "You must specify a valid search path for service %s" % self.name @@ -152,10 +153,11 @@ module Puppet # if we've gotten this far, we found a valid script return fqname } - raise "Could not find init script for '%s'" % name + raise Puppet::Error, "Could not find init script for '%s'" % name end def parampath=(ary) + @parameters[:path] = ary # verify each of the paths exists @searchpaths = ary.find_all { |dir| FileTest.directory?(dir) diff --git a/test/types/tc_cron.rb b/test/types/tc_cron.rb index a33ee992d..4389e80ae 100755 --- a/test/types/tc_cron.rb +++ b/test/types/tc_cron.rb @@ -1,3 +1,5 @@ +# Test cron job creation, modification, and destruction + if __FILE__ == $0 $:.unshift '..' $:.unshift '../../lib' @@ -10,10 +12,9 @@ require 'puppet/type/cron' require 'test/unit' require 'facter' -# $Id$ - class TestExec < TestPuppet def setup + # retrieve the user name id = %x{id}.chomp if id =~ /uid=\d+\(([^\)]+)\)/ @me = $1 @@ -23,36 +24,42 @@ class TestExec < TestPuppet unless defined? @me raise "Could not retrieve user name; 'id' did not work" end - tab = Puppet::Type::Cron.crontype.read(@me) - - if $? == 0 - @currenttab = tab - else - @currenttab = nil - end + # god i'm lazy + @crontype = Puppet::Type::Cron super end - def teardown - if @currenttab - Puppet::Type::Cron.crontype.write(@me, @currenttab) + # Back up the user's existing cron tab if they have one. + def cronback + tab = nil + assert_nothing_raised { + tab = Puppet::Type::Cron.crontype.read(@me) + } + + if $? == 0 + @currenttab = tab else - Puppet::Type::Cron.crontype.remove(@me) + @currenttab = nil end - super end - def test_load + # Restore the cron tab to its original form. + def cronrestore assert_nothing_raised { - Puppet::Type::Cron.retrieve(@me) + if @currenttab + @crontype.crontype.write(@me, @currenttab) + else + @crontype.crontype.remove(@me) + end } end + # Create a cron job with all fields filled in. def mkcron(name) cron = nil assert_nothing_raised { - cron = Puppet::Type::Cron.create( + cron = @crontype.create( :command => "date > %s/crontest%s" % [tmpdir(), name], :name => name, :user => @me, @@ -66,6 +73,7 @@ class TestExec < TestPuppet return cron end + # Run the cron through its paces -- install it then remove it. def cyclecron(cron) name = cron.name comp = newcomp(name, cron) @@ -76,16 +84,94 @@ class TestExec < TestPuppet trans = assert_events(comp, [], name) cron[:command] = :notfound trans = assert_events(comp, [:cron_deleted], name) + # the cron should no longer exist, not even in the comp + trans = assert_events(comp, [], name) + + assert(!comp.include?(cron), + "Cron is still a member of comp, after being deleted") + end + + # A simple test to see if we can load the cron from disk. + def test_load + assert_nothing_raised { + @crontype.retrieve(@me) + } + end + + # Test that a cron job turns out as expected, by creating one and generating + # it directly + def test_simple_to_cron + cron = nil + # make the cron + name = "yaytest" + assert_nothing_raised { + cron = @crontype.create( + :name => name, + :command => "date", + :user => @me + ) + } + str = nil + # generate the text + assert_nothing_raised { + str = cron.to_cron + } + assert_equal(str, "# Puppet Name: #{name}\n* * * * * date", + "Cron did not generate correctly") + end + + # Test that comments are correctly retained + def test_retain_comments + str = "# this is a comment\n#and another comment\n" + user = "fakeuser" + assert_nothing_raised { + @crontype.parse(user, str) + } + + assert_nothing_raised { + newstr = @crontype.tab(user) + assert_equal(str, newstr, "Cron comments were changed or lost") + } end + # Test that a specified cron job will be matched against an existing job + # with no name, as long as all fields match + def test_matchcron + str = "0,30 * * * * date\n" + + assert_nothing_raised { + @crontype.parse(@me, str) + } + + assert_nothing_raised { + cron = @crontype.create( + :name => "yaycron", + :minute => [0, 30], + :command => "date", + :user => @me + ) + } + + modstr = "# Puppet Name: yaycron\n%s" % str + + assert_nothing_raised { + newstr = @crontype.tab(@me) + assert_equal(modstr, newstr, "Cron was not correctly matched") + } + end + + # Test adding a cron when there is currently no file. def test_mkcronwithnotab + cronback Puppet::Type::Cron.crontype.remove(@me) cron = mkcron("crontest") cyclecron(cron) + cronrestore end def test_mkcronwithtab + cronback Puppet::Type::Cron.crontype.remove(@me) Puppet::Type::Cron.crontype.write(@me, "1 1 1 1 * date > %s/crontesting\n" % testdir() @@ -93,9 +179,11 @@ class TestExec < TestPuppet cron = mkcron("crontest") cyclecron(cron) + cronrestore end def test_makeandretrievecron + cronback Puppet::Type::Cron.crontype.remove(@me) name = "storeandretrieve" @@ -110,17 +198,20 @@ class TestExec < TestPuppet assert(cron = Puppet::Type::Cron[name], "Could not retrieve named cron") assert_instance_of(Puppet::Type::Cron, cron) + cronrestore end + # Do input validation testing on all of the parameters. def test_arguments values = { :monthday => { - :valid => [ 1, 13, ], + :valid => [ 1, 13, "1,30" ], :invalid => [ -1, 0, 32 ] }, :weekday => { - :valid => [ 0, 3, 6, "tue", "wed", "Wed", "MOnday", "SaTurday" ], - :invalid => [ -1, 7, "tues", "teusday", "thurs" ] + :valid => [ 0, 3, 6, "1,2", "tue", "wed", + "Wed", "MOnday", "SaTurday" ], + :invalid => [ -1, 7, "1, 3", "tues", "teusday", "thurs" ] }, :hour => { :valid => [ 0, 21, 23 ], @@ -147,7 +238,7 @@ class TestExec < TestPuppet } if value.is_a?(Integer) - assert_equal(value, cron[param], + assert_equal([value], cron[param], "Cron value was not set correctly") end when :invalid: @@ -166,3 +257,5 @@ class TestExec < TestPuppet } end end + +# $Id$ diff --git a/test/types/tc_exec.rb b/test/types/tc_exec.rb index 7e1f5f161..0e4de4d9d 100755 --- a/test/types/tc_exec.rb +++ b/test/types/tc_exec.rb @@ -62,10 +62,11 @@ class TestExec < TestPuppet def test_path_or_qualified command = nil output = nil - assert_raise(TypeError) { + assert_nothing_raised { command = Puppet::Type::Exec.create( :command => "echo" ) + assert_nil(command) } Puppet::Type::Exec.clear assert_nothing_raised { diff --git a/test/types/tc_service.rb b/test/types/tc_service.rb index a1633aec7..ecacc77d7 100644 --- a/test/types/tc_service.rb +++ b/test/types/tc_service.rb @@ -1,87 +1,94 @@ if __FILE__ == $0 $:.unshift '..' $:.unshift '../../lib' - $puppetbase = "../../../../language/trunk" + $puppetbase = "../.." end require 'puppet' +require 'puppettest' require 'test/unit' # $Id$ -class TestService < Test::Unit::TestCase +class TestService < TestPuppet # hmmm # this is complicated, because we store references to the created # objects in a central store def setup - @sleeper = nil + sleeper = nil script = File.join($puppetbase,"examples/root/etc/init.d/sleeper") @status = script + " status" - Puppet[:loglevel] = :debug if __FILE__ == $0 - assert_nothing_raised() { - unless Puppet::Type::Service.has_key?("sleeper") - Puppet::Type::Service.create( - :name => "sleeper", - :path => File.join($puppetbase,"examples/root/etc/init.d"), - :running => 1 - ) - end - @sleeper = Puppet::Type::Service["sleeper"] - } + + super end def teardown - Puppet::Type.allclear - Kernel.system("pkill sleeper") + stopservices + super + end + + def mksleeper + assert_nothing_raised() { + return Puppet::Type::Service.create( + :name => "sleeper", + :path => File.join($puppetbase,"examples/root/etc/init.d"), + :running => 1 + ) + } end def test_process_start + sleeper = mksleeper # start it assert_nothing_raised() { - @sleeper[:running] = 1 + sleeper[:running] = 1 } assert_nothing_raised() { - @sleeper.retrieve + sleeper.retrieve } - assert(!@sleeper.insync?()) + assert(!sleeper.insync?()) assert_nothing_raised() { - @sleeper.sync + sleeper.sync } assert_nothing_raised() { - @sleeper.retrieve + sleeper.retrieve } - assert(@sleeper.insync?) + assert(sleeper.insync?) # test refreshing it assert_nothing_raised() { - @sleeper.refresh + sleeper.refresh } - assert(@sleeper.respond_to?(:refresh)) + assert(sleeper.respond_to?(:refresh)) # now stop it assert_nothing_raised() { - @sleeper[:running] = 0 + sleeper[:running] = 0 } assert_nothing_raised() { - @sleeper.retrieve + sleeper.retrieve } - assert(!@sleeper.insync?()) + assert(!sleeper.insync?()) assert_nothing_raised() { - @sleeper.sync + sleeper.sync } assert_nothing_raised() { - @sleeper.retrieve + sleeper.retrieve } - assert(@sleeper.insync?) + assert(sleeper.insync?) end - def testFailOnNoPath - assert_raise(Puppet::Error) { - Puppet::Type::Service.create( + def test_FailOnNoPath + serv = nil + assert_nothing_raised { + serv = Puppet::Type::Service.create( :name => "sleeper" ) } + + assert_nil(serv) + assert_nil(Puppet::Type::Service["sleeper"]) end end diff --git a/test/types/tc_type.rb b/test/types/tc_type.rb index 56eb7071b..f746f287b 100644 --- a/test/types/tc_type.rb +++ b/test/types/tc_type.rb @@ -96,7 +96,10 @@ class TestType < TestPuppet } end - def test_nameasstate + # This was supposed to test objects whose name was a state, but that + # fundamentally doesn't make much sense, and we now don't have any such + # types. + def disabled_test_nameasstate # currently groups are the only objects with the namevar as a state group = nil assert_nothing_raised { |
