diff options
-rwxr-xr-x | bin/pbucket | 52 | ||||
-rw-r--r-- | lib/puppet/network/client/dipper.rb | 20 | ||||
-rwxr-xr-x | lib/puppet/network/handler/filebucket.rb | 2 | ||||
-rwxr-xr-x | test/executables/filebucket.rb | 49 | ||||
-rwxr-xr-x | test/network/client/dipper.rb | 35 | ||||
-rwxr-xr-x | test/network/handler/bucket.rb | 2 |
6 files changed, 145 insertions, 15 deletions
diff --git a/bin/pbucket b/bin/pbucket index bc4c994cb..21d92cf4b 100755 --- a/bin/pbucket +++ b/bin/pbucket @@ -16,6 +16,36 @@ # This is a stand-alone filebucket client for sending files to a local # or central filebucket. # +# = Usage +# +# This client can operate in three modes, with only one mode per call: +# +# backup:: +# Send one or more files to the specified file bucket. Each sent file +# is printed with its resulting md5 sum. +# +# get:: +# Return the text associated with an md5 sum. The text is printed to +# stdout, and only one file can be retrieved at a time. +# +# restore:: +# Given a file path and an md5 sum, store the content associated with the +# sum into the specified file path. You can specify an entirely new path +# to this argument; you are not restricted to restoring the content to its +# original location. +# +# Note that +pbucket+ defaults to using a network-based filebucket available on +# the server named +puppet+. To use this, you'll have to be running as a user +# with valid Puppet certificates. Alternatively, you can use your local file bucket +# by specifying +--local+. +# +# = Example +# +# $ pbucket backup /etc/passwd +# /etc/passwd: 429b225650b912a2ee067b0a4cf1e949 +# $ pbucket restore /tmp/passwd 429b225650b912a2ee067b0a4cf1e949 +# $ +# # = Options # # Note that any configuration parameter that's valid in the configuration file @@ -65,8 +95,7 @@ # Licensed under the GNU Public License require 'puppet' -require 'puppet/server' -require 'puppet/client' +require 'puppet/network/client' require 'getoptlong' options = [ @@ -140,11 +169,12 @@ Puppet.genconfig Puppet.genmanifest begin - if options[:local] + if options[:local] or options[:bucket] path = options[:bucket] || Puppet[:bucketdir] - client = Puppet::Client::Dipper.new(:Path => path) + client = Puppet::Network::Client.dipper.new(:Path => path) else - client = Puppet::Client::Dipper.new(:Server => Puppet[:server]) + require 'puppet/network/handler' + client = Puppet::Network::Client.dipper.new(:Server => Puppet[:server]) end rescue => detail $stderr.puts detail @@ -157,7 +187,10 @@ end mode = ARGV.shift case mode when "get": -when "send": + md5 = ARGV.shift + out = client.getfile(md5) + print out +when "backup": ARGV.each do |file| unless FileTest.exists?(file) $stderr.puts "%s: no such file" % file @@ -167,8 +200,13 @@ when "send": $stderr.puts "%s: cannot read file" % file next end - client.backup(file) + md5 = client.backup(file) + puts "%s: %s" % [file, md5] end +when "restore": + file = ARGV.shift + md5 = ARGV.shift + client.restore(file, md5) else raise "Invalid mode %s" % mode end diff --git a/lib/puppet/network/client/dipper.rb b/lib/puppet/network/client/dipper.rb index 2084e09f6..5ddb67db1 100644 --- a/lib/puppet/network/client/dipper.rb +++ b/lib/puppet/network/client/dipper.rb @@ -28,6 +28,17 @@ class Puppet::Network::Client::Dipper < Puppet::Network::Client return @driver.addfile(contents,file) end + # Retrieve a file by sum. + def getfile(sum) + if newcontents = @driver.getfile(sum) + unless local? + newcontents = Base64.decode64(newcontents) + end + return newcontents + end + return nil + end + # Restore the file def restore(file,sum) restore = true @@ -42,18 +53,15 @@ class Puppet::Network::Client::Dipper < Puppet::Network::Client end if restore - if newcontents = @driver.getfile(sum) - unless local? - newcontents = Base64.decode64(newcontents) - end + if newcontents = getfile(sum) tmp = "" newsum = Digest::MD5.hexdigest(newcontents) changed = nil - unless FileTest.writable?(file) + if FileTest.exists?(file) and ! FileTest.writable?(file) changed = ::File.stat(file).mode ::File.chmod(changed | 0200, file) end - ::File.open(file,::File::WRONLY|::File::TRUNC) { |of| + ::File.open(file, ::File::WRONLY|::File::TRUNC|::File::CREAT) { |of| of.print(newcontents) } if changed diff --git a/lib/puppet/network/handler/filebucket.rb b/lib/puppet/network/handler/filebucket.rb index f0d389aea..705a4eee9 100755 --- a/lib/puppet/network/handler/filebucket.rb +++ b/lib/puppet/network/handler/filebucket.rb @@ -28,7 +28,7 @@ class Puppet::Network::Handler # :nodoc: # this doesn't work for relative paths def self.paths(base,md5) dir = File.join(md5[0..7].split("")) - basedir = File.join(base, dir) + basedir = File.join(base, dir, md5) return [ basedir, File.join(basedir, "contents"), diff --git a/test/executables/filebucket.rb b/test/executables/filebucket.rb new file mode 100755 index 000000000..dbd5fed76 --- /dev/null +++ b/test/executables/filebucket.rb @@ -0,0 +1,49 @@ +#!/usr/bin/env ruby + +$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppet' +require 'puppet/network/client' +require 'puppettest' +require 'socket' +require 'facter' + +class TestPBucket < Test::Unit::TestCase + include PuppetTest::ExeTest + + def test_local + bucket = tempfile + file = tempfile + text = "somet ext" + md5 = Digest::MD5.hexdigest(text) + File.open(file, "w") { |f| f.print text } + out = %x{pbucket --bucket #{bucket} backup #{file}} + + outfile, outmd5 = out.chomp.split(": ") + + assert_equal(0, $?, "pbucket did not run successfully") + + assert_equal(file, outfile, "did not output correct file name") + assert_equal(md5, outmd5, "did not output correct md5 sum") + + dipper = Puppet::Network::Client.dipper.new(:Path => bucket) + + newtext = nil + assert_nothing_raised("Could not get file from bucket") do + newtext = dipper.getfile(md5) + end + + assert_equal(text, newtext, "did not get correct file from md5 sum") + + out = %x{pbucket --bucket #{bucket} get #{md5}} + assert_equal(0, $?, "pbucket did not run successfully") + assert_equal(text, out, "did not get correct text back from pbucket") + + File.open(file, "w") { |f| f.puts "some other txt" } + out = %x{pbucket --bucket #{bucket} restore #{file} #{md5}} + assert_equal(0, $?, "pbucket did not run successfully") + assert_equal(text, File.read(file), "file was not restored") + end +end + +# $Id$ diff --git a/test/network/client/dipper.rb b/test/network/client/dipper.rb new file mode 100755 index 000000000..e91dea2a7 --- /dev/null +++ b/test/network/client/dipper.rb @@ -0,0 +1,35 @@ +#!/usr/bin/env ruby + +$:.unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppettest' +require 'puppet/network/client/resource' + +class TestDipperClient < Test::Unit::TestCase + include PuppetTest::ServerTest + + def setup + super + @dipper = Puppet::Network::Client.dipper.new(:Path => tempfile) + end + + # Make sure we can create a new file with 'restore'. + def test_restore_to_new_file + file = tempfile + text = "asdf;lkajseofiqwekj" + File.open(file, "w") { |f| f.puts text } + md5 = nil + assert_nothing_raised("Could not send file") do + md5 = @dipper.backup(file) + end + + newfile = tempfile + assert_nothing_raised("could not restore to new path") do + @dipper.restore(newfile, md5) + end + + assert_equal(File.read(file), File.read(newfile), "did not restore correctly") + end +end + +# $Id$ diff --git a/test/network/handler/bucket.rb b/test/network/handler/bucket.rb index 9c68afd29..eb488dd33 100755 --- a/test/network/handler/bucket.rb +++ b/test/network/handler/bucket.rb @@ -276,7 +276,7 @@ class TestBucket < Test::Unit::TestCase md5 = Digest::MD5.hexdigest(text) dirs = File.join(md5[0..7].split("")) - dir = File.join(@bucket, dirs) + dir = File.join(@bucket, dirs, md5) filedir, contents, paths = bucket.class.paths(@bucket, md5) assert_equal(dir, filedir, "did not use a deeper file structure") |