diff --git a/config/default.rb b/config/default.rb index 304ada189..c7405eea5 100644 --- a/config/default.rb +++ b/config/default.rb @@ -18,6 +18,7 @@ Vagrant::Config.run do |config| config.vm.disk_image_format = 'VMDK' config.package.name = 'vagrant' + config.package.extension = '.box' config.package.delimiter = 'VAGRANT' config.package.delimiter_regex = /(.*)#{config.package.delimiter}(.+)#{config.package.delimiter}(.*[\n\r])/ diff --git a/lib/vagrant/actions/export.rb b/lib/vagrant/actions/export.rb new file mode 100644 index 000000000..aa42f25e7 --- /dev/null +++ b/lib/vagrant/actions/export.rb @@ -0,0 +1,15 @@ +module Vagrant + module Actions + class Export < Base + def execute!(name=Vagrant.config.package.name, to=FileUtils.pwd) + folder = FileUtils.mkpath(File.join(to, name)) + + logger.info "Creating export directory: #{folder} ..." + ovf_path = File.join(folder, "#{name}.ovf") + + logger.info "Exporting required VM files to directory: #{folder} ..." + @vm.export(ovf_path) + end + end + end +end diff --git a/lib/vagrant/actions/package.rb b/lib/vagrant/actions/package.rb new file mode 100644 index 000000000..54461896d --- /dev/null +++ b/lib/vagrant/actions/package.rb @@ -0,0 +1,29 @@ +module Vagrant + module Actions + class Package < Base + def execute!(name=Vagrant.config.package.name, to=FileUtils.pwd) + folder = FileUtils.mkpath(File.join(to, name)) + tar_path = "#{folder}#{Vagrant.config.package.extension}" + + logger.info "Packaging VM into #{tar_path} ..." + compress(Dir["#{folder}/*.*"], tar_path) + + logger.info "Removing working directory ..." + FileUtils.rm_r(folder) + + tar_path + end + + def compress(files_to_compress, compressed_file_name) + delimiter = Vagrant.config.package.delimiter + Zlib::GzipWriter.open(compressed_file_name) do |gz| + files_to_compress.each do |file| + # Delimit the files, and guarantee new line for next file if not the first + gz.write "#{delimiter}#{file}#{delimiter}" + File.open(file).each { |line| gz.write(line) } + end + end + end + end + end +end diff --git a/lib/vagrant/commands.rb b/lib/vagrant/commands.rb index f5b0b6827..b0f5f4721 100644 --- a/lib/vagrant/commands.rb +++ b/lib/vagrant/commands.rb @@ -107,7 +107,11 @@ error error_and_exit(<<-error) unless Env.persisted_vm.powered_off? The vagrant virtual environment you are trying to package must be powered off error - Env.persisted_vm.package(name || Vagrant.config[:package][:name], FileUtils.pwd) + # TODO allow directory specification + act_on_vm do |vm| + vm.add_action(Actions::Export) + vm.add_action(Actions::Package)# (name || Vagrant.config[:package][:name], FileUtils.pwd) + end end def unpackage(name) @@ -117,6 +121,14 @@ Please specify a target package to unpack and import error VM.up(VM.unpackage(name)) end + + + private + + def act_on_vm(&block) + yield Env.persisted_vm + Env.persisted_vm.execute! + end end end end diff --git a/lib/vagrant/config.rb b/lib/vagrant/config.rb index a05aa71d9..9dcb94043 100644 --- a/lib/vagrant/config.rb +++ b/lib/vagrant/config.rb @@ -78,6 +78,7 @@ module Vagrant class PackageConfig < Base attr_accessor :name + attr_accessor :extension attr_accessor :delimiter attr_accessor :delimiter_regex end diff --git a/lib/vagrant/vm.rb b/lib/vagrant/vm.rb index 5561558aa..733862569 100644 --- a/lib/vagrant/vm.rb +++ b/lib/vagrant/vm.rb @@ -136,34 +136,6 @@ error @vm.save_state(true) end - # TODO the longest method, needs to be split up - def package(name, to) - delimiter = Vagrant.config[:package][:delimiter] - folder = FileUtils.mkpath(File.join(to, name)) - logger.info "Creating working directory: #{folder} ..." - - ovf_path = File.join(folder, "#{name}.ovf") - tar_path = "#{folder}.box" - - logger.info "Exporting required VM files to working directory ..." - @vm.export(ovf_path) - - logger.info "Packaging VM into #{tar_path} ..." - Zlib::GzipWriter.open(tar_path) do |gz| - Dir.new(folder).each do |file| - next if File.directory?(file) - # Delimit the files, and guarantee new line for next file if not the first - gz.write "#{delimiter}#{file}#{delimiter}" - File.open(File.join(folder, file)).each { |line| gz.write(line) } - end - end - - logger.info "Removing working directory ..." - FileUtils.rm_r(folder) - - tar_path - end - def powered_off?; @vm.powered_off? end def export(filename); @vm.export(filename, {}, true) end diff --git a/test/test_helper.rb b/test/test_helper.rb index bfc49aa7e..9d59395c7 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -38,6 +38,8 @@ class Test::Unit::TestCase config.vm.disk_image_format = 'VMDK' config.vm.forward_port("ssh", 22, 2222) + config.package.name = 'vagrant' + config.package.extension = '.box' config.package.delimiter = 'V' config.package.delimiter_regex = /'V(.+)V'/ diff --git a/test/vagrant/actions/.#export_test.rb b/test/vagrant/actions/.#export_test.rb new file mode 120000 index 000000000..d9b5b59f5 --- /dev/null +++ b/test/vagrant/actions/.#export_test.rb @@ -0,0 +1 @@ +johnbender@john-benders-macbook-pro-2.local.460 \ No newline at end of file diff --git a/test/vagrant/actions/.#package_test.rb b/test/vagrant/actions/.#package_test.rb new file mode 120000 index 000000000..d9b5b59f5 --- /dev/null +++ b/test/vagrant/actions/.#package_test.rb @@ -0,0 +1 @@ +johnbender@john-benders-macbook-pro-2.local.460 \ No newline at end of file diff --git a/test/vagrant/actions/export_test.rb b/test/vagrant/actions/export_test.rb new file mode 100644 index 000000000..f44eeda55 --- /dev/null +++ b/test/vagrant/actions/export_test.rb @@ -0,0 +1,21 @@ +require File.join(File.dirname(__FILE__), '..', '..', 'test_helper') + +class ExportActionTest < Test::Unit::TestCase + setup do + @wrapper_vm, @vm, @action = mock_action(Vagrant::Actions::Export) + mock_config + end + + should "setup and correct working directory and export to it" do + new_dir = File.join(FileUtils.pwd, Vagrant.config.package.name) + FileUtils.expects(:mkpath).with(new_dir).returns(new_dir) + @wrapper_vm.expects(:export).with(File.join(new_dir, "#{Vagrant.config.package.name}.ovf")) + @action.execute! + + +#FileUtils.expects(:rm_r).with(new_dir) + + + # assert_equal Vagrant::VM.new(@mock_vm).package(name, location), "#{new_dir}.box" + end +end diff --git a/test/vagrant/actions/package_test.rb b/test/vagrant/actions/package_test.rb new file mode 100644 index 000000000..119142879 --- /dev/null +++ b/test/vagrant/actions/package_test.rb @@ -0,0 +1,17 @@ +require File.join(File.dirname(__FILE__), '..', '..', 'test_helper') + +class PackageActionTest < Test::Unit::TestCase + setup do + @wrapper_vm, @vm, @action = mock_action(Vagrant::Actions::Package) + mock_config + end + + should "setup and correct working directory and export to it" do + working_dir = File.join(FileUtils.pwd, Vagrant.config.package.name) + FileUtils.expects(:rm_r).with(working_dir) + @action.expects(:compress) + assert_equal @action.execute!, "#{working_dir}.box" + end + + # TODO test compression once its finished +end diff --git a/test/vagrant/commands_test.rb b/test/vagrant/commands_test.rb index 1785b1197..4ee0fd888 100644 --- a/test/vagrant/commands_test.rb +++ b/test/vagrant/commands_test.rb @@ -136,6 +136,8 @@ class CommandsTest < Test::Unit::TestCase setup do @persisted_vm.stubs(:package) @persisted_vm.stubs(:powered_off?).returns(true) + @persisted_vm.expects(:add_action).twice + @persisted_vm.expects(:execute!) end should "require a persisted vm" do @@ -149,15 +151,5 @@ class CommandsTest < Test::Unit::TestCase @persisted_vm.expects(:package).never Vagrant::Commands.package end - - should "package the vm with the default name and the current directory" do - @persisted_vm.expects(:package).with(Vagrant.config[:package][:name], FileUtils.pwd).once - Vagrant::Commands.package - end - - should "package the vm with the specified name" do - @persisted_vm.expects(:package).with('foo', FileUtils.pwd).once - Vagrant::Commands.package('foo') - end end end diff --git a/test/vagrant/vm_test.rb b/test/vagrant/vm_test.rb index a4bd1c238..e5467383c 100644 --- a/test/vagrant/vm_test.rb +++ b/test/vagrant/vm_test.rb @@ -182,22 +182,6 @@ class VMTest < Test::Unit::TestCase end end - # TODO more comprehensive testing - context "packaging a vm" do - should "dump the three necessary files to a tar in the current working dir" do - location = FileUtils.pwd - name = 'vagrant' - new_dir = File.join(location, name) - @mock_vm.expects(:export).with(File.join(new_dir, "#{name}.ovf")) - FileUtils.expects(:mkpath).with(new_dir).returns(new_dir) - FileUtils.expects(:rm_r).with(new_dir) - Zlib::GzipWriter.expects(:open).with("#{location}/#{name}.box") - - # TODO test whats passed to the open tar.append_tree - assert_equal Vagrant::VM.new(@mock_vm).package(name, location), "#{new_dir}.box" - end - end - context "unpackaging a vm" do # TODO test actual decompression