summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorLuke Kanies <luke@reductivelabs.com>2010-03-19 22:02:14 -0700
committertest branch <puppet-dev@googlegroups.com>2010-02-17 06:50:53 -0800
commit47c3ca18272e38f16d0e5690c2c9a0e0dbac3285 (patch)
treeb0419940aa95b1e4ce159f3e968364e57a426b33 /lib
parent44cba9cfb85a43f758c457bf3a5e661706f1e8f3 (diff)
downloadpuppet-47c3ca18272e38f16d0e5690c2c9a0e0dbac3285.tar.gz
puppet-47c3ca18272e38f16d0e5690c2c9a0e0dbac3285.tar.xz
puppet-47c3ca18272e38f16d0e5690c2c9a0e0dbac3285.zip
Converted File[checksum] to a parameter not property
At the same time I removed all of the code in checksum that managed tracking changes to the checksum over time. I'll add it back in as I fix the fact that changes aren't being tracked like the should at the moment. Signed-off-by: Luke Kanies <luke@reductivelabs.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/puppet/type/file.rb33
-rwxr-xr-xlib/puppet/type/file/checksum.rb250
-rwxr-xr-xlib/puppet/type/file/content.rb18
-rwxr-xr-xlib/puppet/type/file/ensure.rb1
4 files changed, 29 insertions, 273 deletions
diff --git a/lib/puppet/type/file.rb b/lib/puppet/type/file.rb
index 895c0b207..efac1c835 100644
--- a/lib/puppet/type/file.rb
+++ b/lib/puppet/type/file.rb
@@ -722,12 +722,6 @@ Puppet::Type.newtype(:file) do
# Write out the file. Requires the content to be written,
# the property name for logging, and the checksum for validation.
def write(content, property, checksum = nil)
- if validate = validate_checksum?
- # Use the appropriate checksum type -- md5, md5lite, etc.
- sumtype = property(:checksum).checktype
- checksum ||= "{#{sumtype}}" + property(:checksum).send(sumtype, content)
- end
-
remove_existing(:file)
use_temporary_file = (content.length != 0)
@@ -750,7 +744,7 @@ Puppet::Type.newtype(:file) do
# And put our new file in place
if use_temporary_file # This is only not true when our file is empty.
begin
- fail_if_checksum_is_wrong(path, checksum) if validate
+ fail_if_checksum_is_wrong(path, content) if validate
File.rename(path, self[:path])
rescue => detail
fail "Could not rename temporary file %s to %s : %s" % [path, self[:path], detail]
@@ -763,32 +757,17 @@ Puppet::Type.newtype(:file) do
# make sure all of the modes are actually correct
property_fix
- # And then update our checksum, so the next run doesn't find it.
- self.setchecksum(checksum)
- end
-
- # Should we validate the checksum of the file we're writing?
- def validate_checksum?
- if sumparam = @parameters[:checksum]
- return sumparam.checktype.to_s !~ /time/
- else
- return false
- end
end
private
# Make sure the file we wrote out is what we think it is.
def fail_if_checksum_is_wrong(path, checksum)
- if checksum =~ /^\{(\w+)\}.+/
- sumtype = $1
- else
- # This shouldn't happen, but if it happens to, it's nicer
- # to just use a default sumtype than fail.
- sumtype = "md5"
- end
- newsum = property(:checksum).getsum(sumtype, path)
- return if newsum == checksum
+ # Use the appropriate checksum type -- md5, md5lite, etc.
+ checksum = parameter(:checksum).sum(content)
+
+ newsum = parameter(:checksum).sum_file(path)
+ return if [:absent, nil, checksum].include?(newsum)
self.fail "File written to disk did not match checksum; discarding changes (%s vs %s)" % [checksum, newsum]
end
diff --git a/lib/puppet/type/file/checksum.rb b/lib/puppet/type/file/checksum.rb
index 0c45aad32..d4c24886c 100755
--- a/lib/puppet/type/file/checksum.rb
+++ b/lib/puppet/type/file/checksum.rb
@@ -1,250 +1,26 @@
require 'puppet/util/checksums'
-# Keep a copy of the file checksums, and notify when they change. This
-# property never actually modifies the system, it only notices when the system
-# changes on its own.
-Puppet::Type.type(:file).newproperty(:checksum) do
+# Specify which checksum algorithm to use when checksumming
+# files.
+Puppet::Type.type(:file).newparam(:checksum) do
include Puppet::Util::Checksums
- desc "How to check whether a file has changed. This state is used internally
- for file copying, but it can also be used to monitor files somewhat
- like Tripwire without managing the file contents in any way. You can
- specify that a file's checksum should be monitored and then subscribe to
- the file from another object and receive events to signify
- checksum changes, for instance.
-
- There are a number of checksum types available including MD5 hashing (and
- an md5lite variation that only hashes the first 500 characters of the
- file.
+ desc "The checksum type to use when checksumming a file.
The default checksum parameter, if checksums are enabled, is md5."
- @event = :file_changed
-
- @unmanaged = true
-
- @validtypes = %w{md5 md5lite timestamp mtime time none}
-
- def self.validtype?(type)
- @validtypes.include?(type)
- end
-
- @validtypes.each do |ctype|
- newvalue(ctype) do
- handlesum()
- end
- end
-
- str = @validtypes.join("|")
+ newvalues "md5", "md5lite", "timestamp", "mtime", "time", "none"
- # This is here because Puppet sets this internally, using
- # {md5}......
- newvalue(/^\{#{str}\}/) do
- handlesum()
- end
+ defaultto :md5
- # If they pass us a sum type, behave normally, but if they pass
- # us a sum type + sum, stick the sum in the cache.
- munge do |value|
- if value =~ /^\{(\w+)\}(.+)$/
- type = symbolize($1)
- sum = $2
- cache(type, sum)
- return type
- else
- return :none if value.nil? or value.to_s == "" or value.to_s == "none"
- if FileTest.directory?(@resource[:path])
- return :time
- elsif @resource[:source] and value.to_s != "md5"
- self.warning("Files with source set must use md5 as checksum. Forcing to md5 from %s for %s" % [ value, @resource[:path] ])
- return :md5
- else
- return symbolize(value)
- end
- end
+ def sum(content)
+ type = value || :md5 # because this might be called before defaults are set
+ "{#{type}}" + send(type, content)
end
- # Store the checksum in the data cache, or retrieve it if only the
- # sum type is provided.
- def cache(type, sum = nil)
- return unless c = resource.catalog and c.host_config?
- unless type
- raise ArgumentError, "A type must be specified to cache a checksum"
- end
- type = symbolize(type)
- type = :mtime if type == :timestamp
- type = :ctime if type == :time
-
- unless state = @resource.cached(:checksums)
- self.debug "Initializing checksum hash"
- state = {}
- @resource.cache(:checksums, state)
- end
-
- if sum
- unless sum =~ /\{\w+\}/
- sum = "{%s}%s" % [type, sum]
- end
- state[type] = sum
- else
- return state[type]
- end
- end
-
- # Because source and content and whomever else need to set the checksum
- # and do the updating, we provide a simple mechanism for doing so.
- def checksum=(value)
- munge(@should)
- self.updatesum(value)
- end
-
- def checktype
- self.should || :md5
- end
-
- # Checksums need to invert how changes are printed.
- def change_to_s(currentvalue, newvalue)
- begin
- if currentvalue == :absent
- return "defined '%s' as '%s'" %
- [self.name, self.currentsum]
- elsif newvalue == :absent
- return "undefined %s from '%s'" %
- [self.name, self.is_to_s(currentvalue)]
- else
- if defined? @cached and @cached
- return "%s changed '%s' to '%s'" %
- [self.name, @cached, self.is_to_s(currentvalue)]
- else
- return "%s changed '%s' to '%s'" %
- [self.name, self.currentsum, self.is_to_s(currentvalue)]
- end
- end
- rescue Puppet::Error, Puppet::DevError
- raise
- rescue => detail
- raise Puppet::DevError, "Could not convert change %s to string: %s" %
- [self.name, detail]
- end
- end
-
- def currentsum
- cache(checktype())
- end
-
- # Calculate the sum from disk.
- def getsum(checktype, file = nil)
- sum = ""
-
- checktype = :mtime if checktype == :timestamp
- checktype = :ctime if checktype == :time
- self.should = checktype = :md5 if @resource.property(:source)
-
- file ||= @resource[:path]
-
- return nil unless FileTest.exist?(file)
-
- if ! FileTest.file?(file)
- checktype = :mtime
- end
- method = checktype.to_s + "_file"
-
- self.fail("Invalid checksum type %s" % checktype) unless respond_to?(method)
-
- return "{%s}%s" % [checktype, send(method, file)]
- end
-
- # At this point, we don't actually modify the system, we modify
- # the stored state to reflect the current state, and then kick
- # off an event to mark any changes.
- def handlesum
- currentvalue = self.retrieve
- if currentvalue.nil?
- raise Puppet::Error, "Checksum state for %s is somehow nil" %
- @resource.title
- end
-
- if self.insync?(currentvalue)
- self.debug "Checksum is already in sync"
- return nil
- end
- # If we still can't retrieve a checksum, it means that
- # the file still doesn't exist
- if currentvalue == :absent
- # if they're copying, then we won't worry about the file
- # not existing yet
- return nil unless @resource.property(:source)
- end
-
- # If the sums are different, then return an event.
- if self.updatesum(currentvalue)
- return :file_changed
- else
- return nil
- end
- end
-
- def insync?(currentvalue)
- @should = [checktype()]
- if cache(checktype())
- return currentvalue == currentsum()
- else
- # If there's no cached sum, then we don't want to generate
- # an event.
- return true
- end
- end
-
- # Even though they can specify multiple checksums, the insync?
- # mechanism can really only test against one, so we'll just retrieve
- # the first specified sum type.
- def retrieve(usecache = false)
- # When the 'source' is retrieving, it passes "true" here so
- # that we aren't reading the file twice in quick succession, yo.
- currentvalue = currentsum()
- return currentvalue if usecache and currentvalue
-
- stat = nil
- return :absent unless stat = @resource.stat
-
- if stat.ftype == "link" and @resource[:links] != :follow
- self.debug "Not checksumming symlink"
- # @resource.delete(:checksum)
- return currentvalue
- end
-
- # Just use the first allowed check type
- currentvalue = getsum(checktype())
-
- # If there is no sum defined, then store the current value
- # into the cache, so that we're not marked as being
- # out of sync. We don't want to generate an event the first
- # time we get a sum.
- self.updatesum(currentvalue) unless cache(checktype())
-
- # @resource.debug "checksum state is %s" % self.is
- return currentvalue
- end
-
- # Store the new sum to the state db.
- def updatesum(newvalue)
- return unless c = resource.catalog and c.host_config?
- result = false
-
- # if we're replacing, vs. updating
- if sum = cache(checktype())
- return false if newvalue == sum
-
- self.debug "Replacing %s checksum %s with %s" % [@resource.title, sum, newvalue]
- result = true
- else
- @resource.debug "Creating checksum %s" % newvalue
- result = false
- end
-
- # Cache the sum so the log message can be right if possible.
- @cached = sum
- cache(checktype(), newvalue)
- return result
+ def sum_file(path)
+ type = value || :md5 # because this might be called before defaults are set
+ method = type.to_s + "_file"
+ "{#{type}}" + send(method, path).to_s
end
end
diff --git a/lib/puppet/type/file/content.rb b/lib/puppet/type/file/content.rb
index 0f26a8561..a8a5e7c73 100755
--- a/lib/puppet/type/file/content.rb
+++ b/lib/puppet/type/file/content.rb
@@ -30,9 +30,13 @@ module Puppet
munge do |value|
if value == :absent
value
+ elsif checksum?(value)
+ # XXX This is potentially dangerous because it means users can't write a file whose
+ # entire contents are a plain checksum
+ value
else
@actual_content = value
- "{#{checksum_type}}" + send(self.checksum_type, value)
+ resource.parameter(:checksum).sum(value)
end
end
@@ -54,10 +58,8 @@ module Puppet
def checksum_type
if source = resource.parameter(:source)
result = source.checksum
- elsif checksum = resource.parameter(:checksum)
- result = checksum.checktype
- else
- return :md5
+ else checksum = resource.parameter(:checksum)
+ result = resource[:checksum]
end
if result =~ /^\{(\w+)\}.+/
return $1.to_sym
@@ -76,7 +78,7 @@ module Puppet
if s = resource.parameter(:source)
return s.content
end
- return nil
+ fail "Could not find actual content from checksum"
end
def content
@@ -116,10 +118,10 @@ module Puppet
return :absent unless stat = @resource.stat
ftype = stat.ftype
# Don't even try to manage the content on directories or links
- return nil if ["directory","link"].include? ftype or checksum_type.nil?
+ return nil if ["directory","link"].include?(ftype)
begin
- "{#{checksum_type}}" + send(checksum_type.to_s + "_file", resource[:path]).to_s
+ resource.parameter(:checksum).sum_file(resource[:path])
rescue => detail
raise Puppet::Error, "Could not read #{ftype} #{@resource.title}: #{detail}"
end
diff --git a/lib/puppet/type/file/ensure.rb b/lib/puppet/type/file/ensure.rb
index 96369f6b3..fc4bbea3c 100755
--- a/lib/puppet/type/file/ensure.rb
+++ b/lib/puppet/type/file/ensure.rb
@@ -73,7 +73,6 @@ module Puppet
Dir.mkdir(@resource[:path])
end
@resource.send(:property_fix)
- @resource.setchecksum
return :directory_created
end