diff options
| author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2005-09-06 04:21:55 +0000 |
|---|---|---|
| committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2005-09-06 04:21:55 +0000 |
| commit | 795a5a0551ba8c2fcf4dcbdb6a3e9ab3fb57bf86 (patch) | |
| tree | 59c19c3485f93c66e07018667c176f6d0285c2c6 /lib | |
| parent | f7a5f87cbbbb2a0895e2174ad5d25e6f3f7aad46 (diff) | |
| download | puppet-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.rb | 27 | ||||
| -rw-r--r-- | lib/puppet/type/pfile.rb | 261 | ||||
| -rwxr-xr-x | lib/puppet/type/tidy.rb | 163 |
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 |
