summaryrefslogtreecommitdiffstats
path: root/lib/puppet/indirector
diff options
context:
space:
mode:
Diffstat (limited to 'lib/puppet/indirector')
-rw-r--r--lib/puppet/indirector/file_bucket_file/file.rb142
-rw-r--r--lib/puppet/indirector/file_bucket_file/rest.rb8
-rw-r--r--lib/puppet/indirector/indirection.rb14
-rw-r--r--lib/puppet/indirector/request.rb10
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