summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2005-09-06 04:21:55 +0000
committerluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2005-09-06 04:21:55 +0000
commit795a5a0551ba8c2fcf4dcbdb6a3e9ab3fb57bf86 (patch)
tree59c19c3485f93c66e07018667c176f6d0285c2c6 /lib
parentf7a5f87cbbbb2a0895e2174ad5d25e6f3f7aad46 (diff)
downloadpuppet-795a5a0551ba8c2fcf4dcbdb6a3e9ab3fb57bf86.tar.gz
puppet-795a5a0551ba8c2fcf4dcbdb6a3e9ab3fb57bf86.tar.xz
puppet-795a5a0551ba8c2fcf4dcbdb6a3e9ab3fb57bf86.zip
adding all of the work necessary for tidying
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@627 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'lib')
-rw-r--r--lib/puppet/type.rb27
-rw-r--r--lib/puppet/type/pfile.rb261
-rwxr-xr-xlib/puppet/type/tidy.rb163
3 files changed, 240 insertions, 211 deletions
diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb
index e2080d5cb..509a10333 100644
--- a/lib/puppet/type.rb
+++ b/lib/puppet/type.rb
@@ -815,13 +815,18 @@ class Type < Puppet::Element
#---------------------------------------------------------------
# sync the changes to disk, and return the events generated by the changes
+ # FIXME this method is essentially obviated, but it's still used by tests
+ # and i don't feel like fixing it yet
def sync
+ #raise Puppet::DevError, "Type#sync called"
events = self.collect { |child|
child.sync
}.reject { |event|
! (event.is_a?(Symbol) or event.is_a?(String))
}.flatten
+ Puppet.notice "got events %s" % events.inspect
+
Puppet::Metric.addevents(self.class,self,events)
return events
end
@@ -849,7 +854,7 @@ class Type < Puppet::Element
if defined? @depthfirst
return @depthfirst
else
- return true
+ return false
end
end
#---------------------------------------------------------------
@@ -893,11 +898,13 @@ class Type < Puppet::Element
self.retrieve
# states() is a private method, returning an ordered list
- changes << states().find_all { |state|
- ! state.insync?
- }.collect { |state|
- Puppet::StateChange.new(state)
- }
+ unless self.class.depthfirst?
+ changes << states().find_all { |state|
+ ! state.insync?
+ }.collect { |state|
+ Puppet::StateChange.new(state)
+ }
+ end
if changes.length > 0
# add one to the number of out-of-sync instances
@@ -919,6 +926,14 @@ class Type < Puppet::Element
# child.evaluate
#}
+ if self.class.depthfirst?
+ changes << states().find_all { |state|
+ ! state.insync?
+ }.collect { |state|
+ Puppet::StateChange.new(state)
+ }
+ end
+
changes.flatten!
# now record how many changes we've resulted in
diff --git a/lib/puppet/type/pfile.rb b/lib/puppet/type/pfile.rb
index e46d6fdb6..9a0798581 100644
--- a/lib/puppet/type/pfile.rb
+++ b/lib/puppet/type/pfile.rb
@@ -743,33 +743,7 @@ module Puppet
return nil
end
end
- @backed = false
- bak = @parent[:backup] || ".puppet-bak"
-
- # try backing ourself up before we overwrite
- if FileTest.file?(@parent.name)
- if bucket = @parent[:filebucket]
- bucket.backup(@parent.name)
- @backed = true
- elsif @parent[:backup]
- # back the file up
- begin
- FileUtils.cp(@parent.name,
- @parent.name + bak)
- @backed = true
- rescue => detail
- # since they said they want a backup, let's error out
- # if we couldn't make one
- error = Puppet::Error.new("Could not back %s up: %s" %
- [@parent.name, detail.message])
- raise error
- end
- end
- end
-
- unless @parent[:backup]
- @backed = true
- end
+ @backed = @parent.handlebackup
unless @stats[:type] == "file"
raise Puppet::DevError, "Got told to copy non-file %s" %
@@ -789,123 +763,48 @@ module Puppet
@source
end
- begin
- if FileTest.exists?(@parent.name)
- if FileTest.exists?(@parent.name + bak)
- Puppet.warning "Deleting backup of %s" %
- @parent.name
- File.unlink(@parent.name + bak)
- end
+ if FileTest.exists?(@parent.name)
+ # this makes sure we have a copy for posterity
+ @backed = @parent.handlebackup
+ end
- # rename the existing one
- File.rename(
- @parent.name,
- @parent.name + ".puppet-bak"
- )
- # move the new file into place
- args = [@parent.name,
- File::CREAT | File::WRONLY | File::TRUNC]
-
- # try to create it with the correct modes to start
- # we should also be changing our effective uid/gid, but...
- if @parent[:mode]
- args.push @parent[:mode]
- end
- File.open(*args) { |f|
- f.print contents
- }
- # if we've made a backup, then delete the old file
- if @backed
- #Puppet.err "Unlinking backup"
- File.unlink(@parent.name + bak)
- #else
- #Puppet.err "Not unlinking backup"
- end
- else
- # the easy case
- args = [@parent.name,
- File::CREAT | File::WRONLY | File::TRUNC]
-
- # try to create it with the correct modes to start
- # we should also be changing our effective uid/gid, but...
- if @parent[:mode]
- args.push @parent[:mode]
- end
- File.open(*args) { |f|
- f.print contents
- }
- end
+ # create the file in a tmp location
+ args = [@parent.name + ".puppettmp",
+ File::CREAT | File::WRONLY | File::TRUNC]
+
+ # try to create it with the correct modes to start
+ # we should also be changing our effective uid/gid, but...
+ if @parent[:mode]
+ args.push @parent[:mode]
+ end
+
+ begin
+ File.open(*args) { |f|
+ f.print contents
+ }
rescue => detail
# since they said they want a backup, let's error out
# if we couldn't make one
- error = Puppet::Error.new("Could not copy %s to %s: %s" %
- [@source, @parent.name, detail.message])
- raise error
+ raise Puppet::Error, "Could not create %s to %s: %s" %
+ [@source, @parent.name, detail.message]
end
- #Puppet.notice "@is: %s; @should: %s" % [@is,@should]
- #Puppet.err "@is: %s; @should: %s" % [@is,@should]
- # okay, we've now got whatever backing up done we might need
- # so just copy the files over
-
- f = false
- if f
- if @local
- stat = File.stat(@source)
- case stat.ftype
- when "file":
- begin
- if FileTest.exists?(@parent.name)
- # get the file here
- FileUtils.cp(@source, @parent.name + ".tmp")
- if FileTest.exists?(@parent.name + bak)
- Puppet.warning "Deleting backup of %s" %
- @parent.name
- File.unlink(@parent.name + bak)
- end
- # rename the existing one
- File.rename(
- @parent.name,
- @parent.name + ".puppet-bak"
- )
- # move the new file into place
- File.rename(
- @parent.name + ".tmp",
- @parent.name
- )
- # if we've made a backup, then delete the old file
- if @backed
- #Puppet.err "Unlinking backup"
- File.unlink(@parent.name + bak)
- #else
- #Puppet.err "Not unlinking backup"
- end
- else
- # the easy case
- FileUtils.cp(@source, @parent.name)
- end
- rescue => detail
- # since they said they want a backup, let's error out
- # if we couldn't make one
- error = Puppet::Error.new("Could not copy %s to %s: %s" %
- [@source, @parent.name, detail.message])
- raise error
- end
- when "directory":
- raise Puppet::Error.new(
- "Somehow got told to copy directory %s" %
- @parent.name)
- when "link":
- dest = File.readlink(@source)
- Puppet::State::PFileLink.create(@dest,@parent.path)
- else
- raise Puppet::Error.new(
- "Cannot use files of type %s as source" % stat.ftype)
- end
- else
- raise Puppet::Error.new("Somehow got a non-local source")
+ if FileTest.exists?(@parent.name)
+ begin
+ File.unlink(@parent.name)
+ rescue => detail
+ Puppet.err "Could not remove %s for replacing: %s" %
+ [@parent.name, detail]
end
end
+
+ begin
+ File.rename(@parent.name + ".puppettmp", @parent.name)
+ rescue => detail
+ Puppet.err "Could not rename tmp %s for replacing: %s" %
+ [@parent.name, detail]
+ end
+
return :file_changed
end
end
@@ -972,6 +871,63 @@ module Puppet
@arghash.include?(arg)
end
+ def handlebackup(file = nil)
+ # let the path be specified
+ file ||= self[:path]
+ # if they specifically don't want a backup, then just say
+ # we're good
+ unless FileTest.exists?(file)
+ return true
+ end
+
+ unless self[:backup]
+ return true
+ end
+
+ case File.stat(file).ftype
+ when "directory":
+ # we don't need to backup directories
+ return true
+ when "file":
+ backup = self[:backup]
+ case backup
+ when Puppet::Client::Dipper:
+ sum = backup.backup(file)
+ Puppet.info "Filebucketed %s with sum %s" %
+ [file, sum]
+ return true
+ when String:
+ newfile = file + backup
+ if FileTest.exists?(newfile)
+ begin
+ File.unlink(newfile)
+ rescue => detail
+ Puppet.err "Could not remove old backup: %s" %
+ detail
+ return false
+ end
+ end
+ begin
+ FileUtils.cp(file,
+ file + backup)
+ return true
+ rescue => detail
+ # since they said they want a backup, let's error out
+ # if we couldn't make one
+ raise Puppet::Error.new("Could not back %s up: %s" %
+ [file, detail.message])
+ end
+ else
+ Puppet.err "Invalid backup type %s" % backup
+ return false
+ end
+ else
+ Puppet.notice "Cannot backup files of type %s" %
+ File.stat(file).ftype
+ return false
+ end
+ end
+
def initialize(hash)
@arghash = self.argclean(hash)
@arghash.delete(self.class.namevar)
@@ -1002,20 +958,29 @@ module Puppet
end
def parambackup=(value)
- if value == false or value == "false"
+ case value
+ when false, "false":
@parameters[:backup] = false
- elsif value == true or value == "true"
+ when true, "true":
@parameters[:backup] = ".puppet-bak"
+ when Array:
+ case value[0]
+ when "filebucket":
+ if bucket = Puppet::Type::PFileBucket.bucket(value[1])
+ @parameters[:backup] = bucket
+ else
+ @parameters[:backup] = ".puppet-bak"
+ raise Puppet::Error,
+ "Could not retrieve filebucket %s" %
+ value[1]
+ end
+ else
+ raise Puppet::Error, "Invalid backup object type %s" %
+ value[0].inspect
+ end
else
- @parameters[:backup] = value
- end
- end
-
- def paramfilebucket=(name)
- if bucket = Puppet::Type::PFileBucket.bucket(name)
- @parameters[:filebucket] = bucket
- else
- raise Puppet::Error.new("Could not find filebucket %s" % name)
+ raise Puppet::Error, "Invalid backup type %s" %
+ value.inspect
end
end
@@ -1081,7 +1046,7 @@ module Puppet
:path => path
}
else
- klass = Puppet::Type::PFile
+ klass = self.class
end
if child = klass[path]
unless @children.include?(child)
diff --git a/lib/puppet/type/tidy.rb b/lib/puppet/type/tidy.rb
index cf9b3c939..833f4444b 100755
--- a/lib/puppet/type/tidy.rb
+++ b/lib/puppet/type/tidy.rb
@@ -12,80 +12,68 @@ module Puppet
class State
class TidyUp < Puppet::State
require 'etc'
- attr_accessor :file
-
- @doc = "Create a link to another file. Currently only symlinks
- are supported, and attempts to replace normal files with
- links will currently fail, while existing but incorrect symlinks
- will be removed."
- @name = :target
-
- def create
- begin
- debug("Creating symlink '%s' to '%s'" %
- [self.parent[:path],self.should])
- unless File.symlink(self.should,self.parent[:path])
- raise TypeError.new("Could not create symlink '%s'" %
- self.parent[:path])
- end
- rescue => detail
- raise TypeError.new("Cannot create symlink '%s': %s" %
- [self.parent[:path],detail])
- end
- end
- def remove
- if FileTest.symlink?(self.parent[:path])
- debug("Removing symlink '%s'" % self.parent[:path])
- begin
- File.unlink(self.parent[:path])
- rescue
- raise TypeError.new("Failed to remove symlink '%s'" %
- self.parent[:path])
- end
- elsif FileTest.exists?(self.parent[:path])
- raise TypeError.new("Cannot remove normal file '%s'" %
- self.parent[:path])
+ @nodoc = true
+ @name = :tidyup
+
+ def age(stat)
+ type = nil
+ if stat.ftype == "directory"
+ type = :mtime
else
- debug("Symlink '%s' does not exist" %
- self.parent[:path])
+ type = @parent[:type] || :atime
end
+
+ return Integer(Time.now - stat.send(type))
end
def retrieve
stat = nil
-
- if FileTest.symlink?(self.parent[:path])
- self.is = File.readlink(self.parent[:path])
- debug("link value is '%s'" % self.is)
- return
- else
- self.is = nil
+ unless stat = @parent.stat
+ @is = :unknown
return
end
+
+ @is = [:age, :size].collect { |param|
+ if @parent[param]
+ self.send(param, stat)
+ end
+ }.reject { |p| p == false or p.nil? }
+ end
+
+ def size(stat)
+ return stat.size
end
- # this is somewhat complicated, because it could exist and be
- # a file
def sync
- if self.should.nil?
- self.remove()
- else # it should exist and be a symlink
- if FileTest.symlink?(self.parent[:path])
- path = File.readlink(self.parent[:path])
- if path != self.should
- self.remove()
- self.create()
+ file = @parent[:path]
+ case File.lstat(file).ftype
+ when "directory":
+ if @parent[:rmdirs]
+ subs = Dir.entries(@parent[:path]).reject { |d|
+ d == "." or d == ".."
+ }.length
+ if subs > 0
+ Puppet.info "%s has %s children; not tidying" %
+ [@parent[:path], subs]
+ Puppet.info Dir.entries(@parent[:path]).inspect
+ else
+ Dir.rmdir(@parent[:path])
end
- elsif FileTest.exists?(self.parent[:path])
- raise TypeError.new("Cannot replace normal file '%s'" %
- self.parent[:path])
else
- self.create()
+ Puppet.debug "Not tidying directories"
+ return nil
end
+ when "file":
+ @parent.handlebackup(file)
+ File.unlink(file)
+ when "symlink": File.unlink(file)
+ else
+ raise Puppet::Error, "Cannot tidy files of type %s" %
+ File.lstat(file).ftype
end
- #self.parent.newevent(:event => :inode_changed)
+ return :file_tidied
end
end
end
@@ -99,10 +87,12 @@ module Puppet
]
@parameters = [
+ :path,
:age,
:size,
:type,
:backup,
+ :rmdirs,
:recurse
]
@@ -117,16 +107,75 @@ module Puppet
time is the default mechanism, but modification."
@paramdoc[:recurse] = "If target is a directory, recursively descend
into the directory looking for files to tidy."
+ @paramdoc[:rmdirs] = "Tidy directories in addition to files."
@doc = "Remove unwanted files based on specific criteria."
@name = :tidy
@namevar = :path
+ @depthfirst = true
+
def initialize(hash)
super
+
+ unless @parameters.include?(:age) or
+ @parameters.include?(:size)
+ unless FileTest.directory?(self[:path])
+ # don't do size comparisons for directories
+ raise Puppet::Error, "Tidy must specify size, age, or both"
+ end
+ end
+
+ # only allow backing up into filebuckets
+ unless self[:backup].is_a? Puppet::Client::Dipper
+ self[:backup] = false
+ end
+ self[:tidyup] = [:age, :size].collect { |param|
+ @parameters[param]
+ }.reject { |p| p == false }
end
def paramage=(age)
@parameters[:age] = age
+ case age
+ when /^[0-9]+$/, /^[0-9]+[dD]/:
+ @parameters[:age] = Integer(age.gsub(/[^0-9]+/,'')) *
+ 60 * 60 * 24
+ when /^[0-9]+$/, /^[0-9]+[hH]/:
+ @parameters[:age] = Integer(age.gsub(/[^0-9]+/,'')) * 60 * 60
+ when /^[0-9]+[mM]/:
+ @parameters[:age] = Integer(age.gsub(/[^0-9]+/,'')) * 60
+ when /^[0-9]+[sS]/:
+ @parameters[:age] = Integer(age.gsub(/[^0-9]+/,''))
+ else
+ raise Puppet::Error.new("Invalid tidy age %s" % age)
+ end
+ end
+
+ def paramsize=(size)
+ if FileTest.directory?(self[:path])
+ # don't do size comparisons for directories
+ return
+ end
+ case size
+ when /^[0-9]+$/, /^[0-9]+[kK]/:
+ @parameters[:size] = Integer(size.gsub(/[^0-9]+/,'')) * 1024
+ when /^[0-9]+[bB]/:
+ @parameters[:size] = Integer(size.gsub(/[^0-9]+/,''))
+ when /^[0-9]+[mM]/:
+ @parameters[:size] = Integer(size.gsub(/[^0-9]+/,'')) *
+ 1024 * 1024
+ else
+ raise Puppet::Error.new("Invalid tidy size %s" % size)
+ end
+ end
+
+ def paramtype=(type)
+ case type
+ when "atime", "mtime", "ctime":
+ @parameters[:type] = type.intern
+ else
+ raise Puppet::Error.new("Invalid tidy type %s" % type)
+ end
end
end # Puppet::Type::Symlink