package and unpackage moved to tar, tarruby added

This commit is contained in:
John Bender 2010-02-19 00:54:49 -08:00
parent a690b13f78
commit c644cfad1a
13 changed files with 105 additions and 64 deletions

View File

@ -7,6 +7,7 @@ gem "net-ssh", ">= 2.0.19"
gem "net-scp", ">= 1.0.2" gem "net-scp", ">= 1.0.2"
gem "jashmenn-git-style-binaries", ">= 0.1.10" gem "jashmenn-git-style-binaries", ">= 0.1.10"
gem "json", ">= 1.2.0" gem "json", ">= 1.2.0"
gem "tarruby", ">= 0.1.5"
# Gems required for testing only. To install run # Gems required for testing only. To install run
# gem bundle test # gem bundle test
@ -14,4 +15,4 @@ group :test do
gem "contest", ">= 0.1.2" gem "contest", ">= 0.1.2"
gem "mocha" gem "mocha"
gem "ruby-debug", ">= 0.10.3" if RUBY_VERSION < '1.9' gem "ruby-debug", ">= 0.10.3" if RUBY_VERSION < '1.9'
end end

View File

@ -19,8 +19,6 @@ Vagrant::Config.run do |config|
config.package.name = 'vagrant' config.package.name = 'vagrant'
config.package.extension = '.box' config.package.extension = '.box'
config.package.delimiter = 'VAGRANT'
config.package.delimiter_regex = /(.*)#{config.package.delimiter}(.+)#{config.package.delimiter}(.*[\n\r])/
config.chef.enabled = false config.chef.enabled = false
config.chef.cookbooks_path = "cookbooks" config.chef.cookbooks_path = "cookbooks"

View File

@ -3,7 +3,7 @@ $:.unshift(libdir)
PROJECT_ROOT = File.join(libdir, '..') unless defined?(PROJECT_ROOT) PROJECT_ROOT = File.join(libdir, '..') unless defined?(PROJECT_ROOT)
# The libs which must be loaded prior to the rest # The libs which must be loaded prior to the rest
%w{ftools json pathname logger virtualbox net/ssh %w{ftools json pathname logger virtualbox net/ssh tarruby
net/scp fileutils vagrant/util vagrant/actions/base}.each do |f| net/scp fileutils vagrant/util vagrant/actions/base}.each do |f|
require f require f
end end

View File

@ -1,18 +1,19 @@
module Vagrant module Vagrant
module Actions module Actions
class Import < Base class Import < Base
attr_accessor :ovf_file
#First arg should be the ovf_file location for import #First arg should be the ovf_file location for import
def initialize(vm, *args) def initialize(vm, *args)
super vm super vm
@ovf_file = args[0] @ovf_file = File.expand_path(args[0] || Vagrant.config[:vm][:base])
end end
def execute! def execute!
@vm.invoke_around_callback(:import) do @vm.invoke_around_callback(:import) do
Busy.busy do Busy.busy do
logger.info "Importing base VM (#{Vagrant.config[:vm][:base]})..." logger.info "Importing base VM (#{@ovf_file})..."
# Use the first argument passed to the action # Use the first argument passed to the action
@vm.vm = VirtualBox::VM.import(@ovf_file || File.expand_path(Vagrant.config[:vm][:base])) @vm.vm = VirtualBox::VM.import(@ovf_file)
end end
end end
end end

View File

@ -1,26 +1,41 @@
module Vagrant module Vagrant
module Actions module Actions
class Package < Base class Package < Base
def execute!(name=Vagrant.config.package.name, to=FileUtils.pwd) attr_accessor :name, :to
folder = FileUtils.mkpath(File.join(to, name))
tar_path = "#{folder}#{Vagrant.config.package.extension}"
def initialize(vm, *args)
super vm
@name = args[0]
@to = args[1]
end
def execute!
logger.info "Packaging VM into #{tar_path} ..." logger.info "Packaging VM into #{tar_path} ..."
compress(Dir["#{folder}/*.*"], tar_path) compress
logger.info "Removing working directory ..." logger.info "Removing working directory ..."
FileUtils.rm_r(folder) FileUtils.rm_r(working_dir)
tar_path tar_path
end end
def compress(files_to_compress, compressed_file_name) def working_dir
delimiter = Vagrant.config.package.delimiter FileUtils.mkpath(File.join(@to, @name))
Zlib::GzipWriter.open(compressed_file_name) do |gz| end
files_to_compress.each do |file|
# Delimit the files, and guarantee new line for next file if not the first def tar_path
gz.write "#{delimiter}#{File.basename(file)}#{delimiter}" "#{working_dir}#{Vagrant.config.package.extension}"
File.open(file).each { |line| gz.write(line) } end
def compress
Tar.open(tar_path, File::CREAT | File::WRONLY, 0644, Tar::GNU) do |tar|
begin
# Append tree will append the entire directory tree unless a relative folder reference is used
current_dir = FileUtils.pwd
FileUtils.cd(@to)
tar.append_tree(@name)
ensure
FileUtils.cd(current_dir)
end end
end end
end end

View File

@ -1,6 +1,9 @@
module Vagrant module Vagrant
module Actions module Actions
class Unpackage < Base class Unpackage < Base
TAR_OPTIONS = [File::RDONLY, 0644, Tar::GNU]
attr_accessor :package_file_path
def initialize(vm, *args) def initialize(vm, *args)
super vm super vm
@package_file_path = args[0] @package_file_path = args[0]
@ -15,55 +18,35 @@ remove it, rename your packaged VM file, or (TODO) specifiy an
alternate directory alternate directory
error error
logger.info "Creating working new base directory: #{new_base_dir} ..." logger.info "Decompressing the packaged VM: #{package_file_path} to: #{working_dir}..."
FileUtils.mkpath(new_base_dir) decompress
logger.info "Decompressing the packaged VM: #{package_file_path} to: #{new_base_dir}..." logger.info "Moving decompressed files in: #{working_dir} to: #{new_base_dir} ..."
decompress_to new_base_dir FileUtils.mv(working_dir, new_base_dir)
#Return the ovf file for importation #Return the ovf file for importation
Dir["#{new_base_dir}/*.ovf"].first Dir["#{new_base_dir}/*.ovf"].first
end end
def new_base_dir def new_base_dir
File.join(Vagrant.config[:vagrant][:home], file_name_without_extension) File.join(Vagrant.config.vagrant.home, file_name_without_extension)
end end
def file_name_without_extension def file_name_without_extension
File.basename(package_file_path, '.*') File.basename(package_file_path, '.*')
end end
def working_dir
package_file_path.chomp(File.extname(package_file_path))
end
def package_file_path def package_file_path
File.expand_path(@package_file_path) File.expand_path(@package_file_path)
end end
def decompress_to(dir, file_delimeter=Vagrant.config[:package][:delimiter_regex]) def decompress
file = nil Tar.open(package_file_path, *TAR_OPTIONS) do |tar|
Zlib::GzipReader.open(package_file_path) do |gz| tar.extract_all
begin
gz.each_line do |line|
# If the line is a file delimiter create new file and write to it
if line =~ file_delimeter
#Write the the part of the line belonging to the previous file
if file
file.write $1
file.close
end
#Open a new file with the name contained in the delimiter
file = File.open(File.join(dir, $2), 'w')
#Write the rest of the line to the new file
file.write $3
else
file.write line
end
end
ensure
file.close if file
end
end end
end end
end end

View File

@ -121,7 +121,7 @@ error
# TODO allow directory specification # TODO allow directory specification
act_on_vm do |vm| act_on_vm do |vm|
vm.add_action(Actions::Export) vm.add_action(Actions::Export)
vm.add_action(Actions::Package)# (name || Vagrant.config[:package][:name], FileUtils.pwd) vm.add_action(Actions::Package, name || Vagrant.config[:package][:name], FileUtils.pwd)
end end
end end
@ -130,7 +130,7 @@ error
error_and_exit(<<-error) unless name error_and_exit(<<-error) unless name
Please specify a target package to unpack and import Please specify a target package to unpack and import
error error
VM.execute!(Actions::Up, VM.execute!(Actions::Unpackage, name)) VM.execute!(Actions::Up, VM.execute!(Actions::Unpackage, name))
end end

View File

@ -79,8 +79,6 @@ module Vagrant
class PackageConfig < Base class PackageConfig < Base
attr_accessor :name attr_accessor :name
attr_accessor :extension attr_accessor :extension
attr_accessor :delimiter
attr_accessor :delimiter_regex
end end
class ChefConfig < Base class ChefConfig < Base

View File

@ -40,8 +40,6 @@ class Test::Unit::TestCase
config.package.name = 'vagrant' config.package.name = 'vagrant'
config.package.extension = '.box' config.package.extension = '.box'
config.package.delimiter = 'V'
config.package.delimiter_regex = /'V(.+)V'/
config.chef.cookbooks_path = "cookbooks" config.chef.cookbooks_path = "cookbooks"
config.chef.provisioning_path = "/tmp/hobo-chef" config.chef.provisioning_path = "/tmp/hobo-chef"

View File

@ -1 +0,0 @@
johnbender@john-benders-macbook-pro-2.local.460

View File

@ -28,4 +28,24 @@ class ImportActionTest < Test::Unit::TestCase
VirtualBox::VM.expects(:import).returns(new_vm) VirtualBox::VM.expects(:import).returns(new_vm)
@import.execute! @import.execute!
end end
context "when importing with or without an ovf file as an argument" do
# NOTE for both tests File.expects(:expand_path) makes mocha recurse and vomit
should "default the ovf_file value to the vagrant base when not passed as an init argument" do\
File.stubs(:expand_path)
File.expand_path do |n|
assert_equal n, Vagrant.config.vm.base
end
Vagrant::Actions::Import.new(@vm)
end
should "expand the ovf path and assign it when passed as a parameter" do
File.stubs(:expand_path)
File.expand_path do |n|
assert_equal n, 'foo'
end
Vagrant::Actions::Import.new(@vm, 'foo')
end
end
end end

View File

@ -3,15 +3,25 @@ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class PackageActionTest < Test::Unit::TestCase class PackageActionTest < Test::Unit::TestCase
setup do setup do
@wrapper_vm, @vm, @action = mock_action(Vagrant::Actions::Package) @wrapper_vm, @vm, @action = mock_action(Vagrant::Actions::Package)
@action.to = '/foo/bar/baz'
@action.name = 'bing'
mock_config mock_config
end end
should "setup and correct working directory and export to it" do should "setup and correct working directory and export to it" do
working_dir = File.join(FileUtils.pwd, Vagrant.config.package.name) working_dir = File.join(@action.to, @action.name)
FileUtils.expects(:rm_r).with(working_dir) FileUtils.expects(:rm_r).with(working_dir)
@action.expects(:compress) @action.expects(:compress)
assert_equal @action.execute!, "#{working_dir}.box" assert_equal @action.execute!, "#{working_dir}.box"
end end
should "return the target file and the proper extension for tar_path" do
assert_equal File.join(@action.to, @action.name + Vagrant.config.package.extension), @action.tar_path
end
should "return the target working dir" do
assert_equal File.join(@action.to, @action.name), @action.working_dir
end
# TODO test compression once its finished # TODO test compression once its finished
end end

View File

@ -3,17 +3,35 @@ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class UnpackageActionTest < Test::Unit::TestCase class UnpackageActionTest < Test::Unit::TestCase
setup do setup do
@wrapper_vm, @vm, @action = mock_action(Vagrant::Actions::Unpackage) @wrapper_vm, @vm, @action = mock_action(Vagrant::Actions::Unpackage)
@expanded_path = File.join(FileUtils.pwd, 'foo.box')
File.stubs(:expand_path).returns(@expanded_path)
@action.package_file_path = 'foo.box'
mock_config mock_config
end end
# TODO test actual decompression # TODO test actual decompression
should "call decompress with the path to the file and the directory to decompress to" do should "call decompress with the path to the file and the directory to decompress to" do
new_base_dir = File.join Vagrant.config[:vagrant][:home], 'something' new_base_dir = File.join Vagrant.config[:vagrant][:home], 'foo'
file = File.join(FileUtils.pwd, 'something.box') FileUtils.expects(:mv).with(@action.working_dir, new_base_dir).once
FileUtils.expects(:mkpath).with(new_base_dir).once
Dir.expects(:[]).returns(File.join new_base_dir, 'something.ovf') Dir.expects(:[]).returns(File.join new_base_dir, 'something.ovf')
@action.expects(:decompress_to).with(new_base_dir).once @action.expects(:decompress)
@action.stubs(:package_file_path).returns(file)
@action.execute! @action.execute!
end end
should "return the full package file path without extension for the working directory" do
assert_equal @action.working_dir, @action.package_file_path.gsub(/\.box/, '')
end
should "return base name without extension" do
assert_equal @action.file_name_without_extension, 'foo'
end
should "call decompress with the defined options and the correct package path" do
Tar.expects(:open).with(@expanded_path, *Vagrant::Actions::Unpackage::TAR_OPTIONS)
@action.decompress
end
should "return a new base dir under the home dir with the same name as the file without the extension" do
assert_equal @action.new_base_dir, File.join(Vagrant.config.vagrant.home, 'foo')
end
end end