diff options
Diffstat (limited to 'lib/puppet/indirector')
| -rw-r--r-- | lib/puppet/indirector/file_bucket_file/file.rb | 142 | ||||
| -rw-r--r-- | lib/puppet/indirector/file_bucket_file/rest.rb | 8 | ||||
| -rw-r--r-- | lib/puppet/indirector/indirection.rb | 14 | ||||
| -rw-r--r-- | lib/puppet/indirector/request.rb | 10 |
4 files changed, 169 insertions, 5 deletions
diff --git a/lib/puppet/indirector/file_bucket_file/file.rb b/lib/puppet/indirector/file_bucket_file/file.rb new file mode 100644 index 000000000..ec02ca0bd --- /dev/null +++ b/lib/puppet/indirector/file_bucket_file/file.rb @@ -0,0 +1,142 @@ +require 'puppet/indirector/code' +require 'puppet/file_bucket/file' + +module Puppet::FileBucketFile + class File < Puppet::Indirector::Code + desc "Store files in a directory set based on their checksums." + + def initialize + Puppet.settings.use(:filebucket) + end + + def find( request ) + checksum, path = request_to_checksum_and_path( request ) + return find_by_checksum( checksum ) + end + + def save( request ) + checksum, path = request_to_checksum_and_path( request ) + + instance = request.instance + instance.checksum = checksum if checksum + instance.path = path if path + + save_to_disk(instance) + instance.to_s + end + + private + + def find_by_checksum( checksum ) + model.new( nil, :checksum => checksum ) do |bucket_file| + filename = contents_path_for bucket_file + + if ! ::File.exist? filename + return nil + end + + begin + contents = ::File.read filename + Puppet.info "FileBucket read #{bucket_file.checksum}" + rescue RuntimeError => e + raise Puppet::Error, "file could not be read: #{e.message}" + end + + if ::File.exist?(paths_path_for bucket_file) + ::File.open(paths_path_for bucket_file) do |f| + bucket_file.paths = f.readlines.map { |l| l.chomp } + end + end + + bucket_file.contents = contents + end + end + + def save_to_disk( bucket_file ) + # If the file already exists, just return the md5 sum. + if ::File.exist?(contents_path_for bucket_file) + verify_identical_file!(bucket_file) + else + # Make the directories if necessary. + unless ::File.directory?(path_for bucket_file) + Puppet::Util.withumask(0007) do + ::FileUtils.mkdir_p(path_for bucket_file) + end + end + + Puppet.info "FileBucket adding #{bucket_file.path} (#{bucket_file.checksum_data})" + + # Write the file to disk. + Puppet::Util.withumask(0007) do + ::File.open(contents_path_for(bucket_file), ::File::WRONLY|::File::CREAT, 0440) do |of| + of.print bucket_file.contents + end + end + end + + save_path_to_paths_file(bucket_file) + return bucket_file.checksum_data + end + + def request_to_checksum_and_path( request ) + checksum_type, checksum, path = request.key.split(/[:\/]/, 3) + return nil if checksum_type.to_s == "" + return [ checksum_type + ":" + checksum, path ] + end + + def path_for(bucket_file, subfile = nil) + bucket_path = bucket_file.bucket_path || Puppet[:bucketdir] + digest = bucket_file.checksum_data + + dir = ::File.join(digest[0..7].split("")) + basedir = ::File.join(bucket_path, dir, digest) + + return basedir unless subfile + return ::File.join(basedir, subfile) + end + + def contents_path_for(bucket_file) + path_for(bucket_file, "contents") + end + + def paths_path_for(bucket_file) + path_for(bucket_file, "paths") + end + + def content_check? + true + end + + # If conflict_check is enabled, verify that the passed text is + # the same as the text in our file. + def verify_identical_file!(bucket_file) + return unless content_check? + disk_contents = ::File.read(contents_path_for(bucket_file)) + + # If the contents don't match, then we've found a conflict. + # Unlikely, but quite bad. + if disk_contents != bucket_file.contents + raise Puppet::FileBucket::BucketError, "Got passed new contents for sum #{bucket_file.checksum}", caller + else + Puppet.info "FileBucket got a duplicate file #{bucket_file.path} (#{bucket_file.checksum})" + end + end + + def save_path_to_paths_file(bucket_file) + return unless bucket_file.path + + # check for dupes + if ::File.exist?(paths_path_for bucket_file) + ::File.open(paths_path_for bucket_file) do |f| + return if f.readlines.collect { |l| l.chomp }.include?(bucket_file.path) + end + end + + # if it's a new file, or if our path isn't in the file yet, add it + ::File.open(paths_path_for(bucket_file), ::File::WRONLY|::File::CREAT|::File::APPEND) do |of| + of.puts bucket_file.path + end + end + + end +end diff --git a/lib/puppet/indirector/file_bucket_file/rest.rb b/lib/puppet/indirector/file_bucket_file/rest.rb new file mode 100644 index 000000000..15e4f331d --- /dev/null +++ b/lib/puppet/indirector/file_bucket_file/rest.rb @@ -0,0 +1,8 @@ +require 'puppet/indirector/rest' +require 'puppet/file_bucket/file' + +module Puppet::FileBucketFile + class Rest < Puppet::Indirector::REST + desc "This is a REST based mechanism to send/retrieve file to/from the filebucket" + end +end diff --git a/lib/puppet/indirector/indirection.rb b/lib/puppet/indirector/indirection.rb index d762701f5..3c6414624 100644 --- a/lib/puppet/indirector/indirection.rb +++ b/lib/puppet/indirector/indirection.rb @@ -116,8 +116,14 @@ class Puppet::Indirector::Indirection end # Set up our request object. - def request(method, key, arguments = nil) - Puppet::Indirector::Request.new(self.name, method, key, arguments) + def request(method, instance_or_key, request_or_options = {}) + if request_or_options.is_a? Puppet::Indirector::Request + request = request_or_options + request.instance = instance_or_key + request.method = method + return request + end + Puppet::Indirector::Request.new(self.name, method, instance_or_key, request_or_options) end # Return the singleton terminus for this indirection. @@ -248,8 +254,8 @@ class Puppet::Indirector::Indirection # Save the instance in the appropriate terminus. This method is # normally an instance method on the indirected class. - def save(instance, *args) - request = request(:save, instance, *args) + def save(instance, request_or_options = nil) + request = request(:save, instance, request_or_options) terminus = prepare(request) result = terminus.save(request) diff --git a/lib/puppet/indirector/request.rb b/lib/puppet/indirector/request.rb index d9e66cb5b..14608d0dc 100644 --- a/lib/puppet/indirector/request.rb +++ b/lib/puppet/indirector/request.rb @@ -180,6 +180,14 @@ class Puppet::Indirector::Request end @protocol = uri.scheme - @key = URI.unescape(uri.path.sub(/^\//, '')) + + if uri.scheme == 'puppet' + @key = URI.unescape(uri.path.sub(/^\//, '')) + return + end + + env, indirector, @key = URI.unescape(uri.path.sub(/^\//, '')).split('/',3) + @key ||= '' + self.environment = env unless env == '' end end |
