On Jul 24, 2009, at 9:43 AM, Steven Jenkins wrote:
>
> This changes the condition checking of handlebucket, as well as
> moves it (and remove_backup) into a separate module. It
> additionally refactors common code out of handlebucket into
> a separate (now private) method.
>
> All spec tests still pass; however, test/ral/type/file.rb:696 fails.
>
> Signed-off-by: Steven Jenkins <[email protected]>
> ---
> lib/puppet/type/file.rb | 126
> +-------------------------------------------
> lib/puppet/util/backups.rb | 110 +++++++++++++++++++++++++++++++++++
> +++
> 2 files changed, 112 insertions(+), 124 deletions(-)
> create mode 100644 lib/puppet/util/backups.rb
>
> diff --git a/lib/puppet/type/file.rb b/lib/puppet/type/file.rb
> index 55d4ec7..657c7ab 100644
> --- a/lib/puppet/type/file.rb
> +++ b/lib/puppet/type/file.rb
> @@ -7,11 +7,13 @@ require 'puppet/network/handler'
> require 'puppet/util/diff'
> require 'puppet/util/checksums'
> require 'puppet/network/client'
> +require 'puppet/util/backups'
>
> module Puppet
> newtype(:file) do
> include Puppet::Util::MethodHelper
> include Puppet::Util::Checksums
> + include Puppet::Util::Backups
> @doc = "Manages local files, including setting ownership and
> permissions, creation of both files and directories, and
> retrieving entire files from remote servers. As Puppet
> matures, it
> @@ -391,103 +393,6 @@ module Puppet
> @stat = nil
> end
>
> - # Deal with backups.
> - 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"
> - if self[:recurse]
> - # we don't need to backup directories when
> recurse is on
> - return true
> - else
> - backup = self.bucket || self[:backup]
> - case backup
> - when Puppet::Network::Client.client(:Dipper)
> - notice "Recursively backing up to filebucket"
> - require 'find'
> - Find.find(self[:path]) do |f|
> - if File.file?(f)
> - sum = backup.backup(f)
> - self.notice "Filebucketed %s to %s
> with sum %s" %
> - [f, backup.name, sum]
> - end
> - end
> -
> - return true
> - when String
> - newfile = file + backup
> - # Just move it, since it's a directory.
> - if FileTest.exists?(newfile)
> - remove_backup(newfile)
> - end
> - begin
> - bfile = file + backup
> -
> - # Ruby 1.8.1 requires the 'preserve'
> addition, but
> - # later versions do not appear to
> require it.
> - FileUtils.cp_r(file, bfile, :preserve
> => true)
> - return true
> - rescue => detail
> - # since they said they want a backup,
> let's error out
> - # if we couldn't make one
> - self.fail "Could not back %s up: %s" %
> - [file, detail.message]
> - end
> - else
> - self.err "Invalid backup type %s" %
> backup.inspect
> - return false
> - end
> - end
> - when "file"
> - backup = self.bucket || self[:backup]
> - case backup
> - when Puppet::Network::Client.client(:Dipper)
> - sum = backup.backup(file)
> - self.notice "Filebucketed to %s with sum %s" %
> - [backup.name, sum]
> - return true
> - when String
> - newfile = file + backup
> - if FileTest.exists?(newfile)
> - remove_backup(newfile)
> - end
> - begin
> - # FIXME Shouldn't this just use a Puppet
> object with
> - # 'source' specified?
> - bfile = file + backup
> -
> - # Ruby 1.8.1 requires the 'preserve'
> addition, but
> - # later versions do not appear to require it.
> - FileUtils.cp(file, bfile, :preserve => true)
> - return true
> - rescue => detail
> - # since they said they want a backup, let's
> error out
> - # if we couldn't make one
> - self.fail "Could not back %s up: %s" %
> - [file, detail.message]
> - end
> - else
> - self.err "Invalid backup type %s" %
> backup.inspect
> - return false
> - end
> - when "link"; return true
> - else
> - self.notice "Cannot backup files of type %s" %
> File.stat(file).ftype
> - return false
> - end
> - end
> -
> def initialize(hash)
> # Used for caching clients
> @clients = {}
> @@ -668,33 +573,6 @@ module Puppet
> Puppet::FileServing::Metadata.search(path, :links =>
> self[:links], :recurse => (self[:recurse] == :remote ? true :
> self[:recurse]), :recurselimit => self[:recurselimit], :ignore =>
> self[:ignore])
> end
>
> - # Remove the old backup.
> - def remove_backup(newfile)
> - if self.class.name == :file and self[:links] != :follow
> - method = :lstat
> - else
> - method = :stat
> - end
> - old = File.send(method, newfile).ftype
> -
> - if old == "directory"
> - raise Puppet::Error,
> - "Will not remove directory backup %s; use a
> filebucket" %
> - newfile
> - end
> -
> - info "Removing old backup of type %s" %
> - File.send(method, newfile).ftype
> -
> - begin
> - File.unlink(newfile)
> - rescue => detail
> - puts detail.backtrace if Puppet[:trace]
> - self.err "Could not remove old backup: %s" % detail
> - return false
> - end
> - end
> -
It's great to see all of that code removed.
>
> # Remove any existing data. This is only used when dealing
> with
> # links or directories.
> def remove_existing(should)
> diff --git a/lib/puppet/util/backups.rb b/lib/puppet/util/backups.rb
> new file mode 100644
> index 0000000..89b0505
> --- /dev/null
> +++ b/lib/puppet/util/backups.rb
> @@ -0,0 +1,110 @@
> +module Puppet::Util::Backups
> +
> + # Deal with backups.
> + 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
Both of these can be trimmed up a bit using this idiom:
return true unless FileTest.exists?(file)
>
> + backup = self.bucket || self[:backup]
This line should be removed; I'm pretty sure this value isn't used
anywhere.
>
> + case File.stat(file).ftype
> + when "directory"
> + # we don't need to backup directories when recurse
> is on
> + return true if self[:recurse]
> +
> + if self.bucket
> + notice "Recursively backing up to filebucket"
> + require 'find'
> + Find.find(self[:path]) do |f|
> + if File.file?(f)
> + sum = backup.backup(f)
> + self.notice "Filebucketed %s to %s with
> sum %s" %
> + [f, backup.name, sum]
Can you change all of the notice logs here to info? They really
shouldn't be at the normal log level; I've had a customer complain
about that. It's an unrelated problem, but this method seems to be
the main culprit.
>
> + end
> + end
> +
> + return true
> + elsif self[:backup]
> + handlebackuplocal(file)
> + else
> + self.err "Invalid backup type %s" %
> backup.inspect
> + return false
This branch can be removed because we're doing the validation in the
parameter - we know we'll only ever have valid values here.
>
> + end
> + when "file"
> + if self.bucket
> + sum = backup.backup(file)
> + self.notice "Filebucketed to %s with sum %s" %
> + [backup.name, sum]
> + return true
> + elsif self[:backup]
> + handlebackuplocal(file)
> + else
> + self.err "Invalid backup type %s" %
> backup.inspect
> + return false
This validation is also unnecessary.
>
> + end
> + when "link"; return true
> + else
> + self.notice "Cannot backup files of type %s" %
> File.stat(file).ftype
> + return false
> + end
> + end
I think this whole method would be better off refactored into a
dispatch-based structure instead of the case statements. Something
like:
return backup_with_filebucket if self.bucket
return backup_with_file
Each of these would then handle the file/dir differences. Well,
really, you'd need something like:
def backup_with_filebucket
ftype = stat().ftype # this is part of the file type already
case ftype
when "directory"
Find.find(self[:path]) { |f| backup_file_with_filebucket(f) if
File.file?(f) }
when "file"; backup_file_with_filebucket(f)
when "link"; return true
end
end
This should allow all of the methods to be very short and easily
testable.
Speaking of tests, there, um, don't appear to be any. :)
> +private
> +
> + def remove_backup(newfile)
> + if self.class.name == :file and self[:links] != :follow
> + method = :lstat
> + else
> + method = :stat
> + end
> + old = File.send(method, newfile).ftype
> +
> + if old == "directory"
> + raise Puppet::Error,
> + "Will not remove directory backup %s; use a
> filebucket" %
> + newfile
> + end
> +
> + info "Removing old backup of type %s" %
> + File.send(method, newfile).ftype
> +
> + begin
> + File.unlink(newfile)
> + rescue => detail
> + puts detail.backtrace if Puppet[:trace]
> + self.err "Could not remove old backup: %s" % detail
> + return false
> + end
> + end
> +
> + def handlelocalbackup(file)
> + newfile = file + backup
> + if FileTest.exists?(newfile)
> + remove_backup(newfile)
> + end
> +
> + begin
> + bfile = file + backup
> +
> + # Ruby 1.8.1 requires the 'preserve' addition, but
> + # later versions do not appear to require it.
> + # N.B. cp_r works on both files and directories
> + FileUtils.cp_r(file, bfile, :preserve => true)
> + return true
> + rescue => detail
> + # since they said they want a backup, let's error out
> + # if we couldn't make one
> + self.fail "Could not back %s up: %s" %
> + [file, detail.message]
> + end
There seem to be some weird indentation issues here -- are you using 4
spaces throughout?
>
> + end
> +
> +end
> --
> 1.6.3.3
>
>
> >
--
A cult is a religion with no political power. -- Tom Wolfe
---------------------------------------------------------------------
Luke Kanies | http://reductivelabs.com | http://madstop.com
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Puppet Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/puppet-dev?hl=en
-~----------~----~----~----~------~----~------~--~---