summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/puppet.rb29
-rw-r--r--lib/puppet/transportable.rb18
-rw-r--r--lib/puppet/type.rb32
-rw-r--r--lib/puppet/type/component.rb9
-rwxr-xr-xlib/puppet/type/cron.rb310
-rw-r--r--lib/puppet/type/service.rb6
-rwxr-xr-xtest/types/tc_cron.rb135
-rwxr-xr-xtest/types/tc_exec.rb3
-rw-r--r--test/types/tc_service.rb73
-rw-r--r--test/types/tc_type.rb5
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 {