Reworked `vagrant package` to use the new tmp directory.

This commit is contained in:
Mitchell Hashimoto 2010-02-24 00:30:58 -08:00
parent 2ee850011b
commit 26f9eca141
9 changed files with 143 additions and 64 deletions

View File

@ -18,7 +18,7 @@ GitStyleBinary.command do
banner <<-EOS banner <<-EOS
Usage: #{command.full_name} #{all_options_string} Usage: #{command.full_name} #{all_options_string}
Package the current vagrant environment Package the current vagrant environment into a box.
EOS EOS
run do |command| run do |command|

View File

@ -2,13 +2,28 @@ module Vagrant
module Actions module Actions
module VM module VM
class Export < Base class Export < Base
def execute!(name=Vagrant.config.package.name, to=FileUtils.pwd) attr_reader :temp_dir
folder = FileUtils.mkpath(File.join(to, name))
logger.info "Creating export directory: #{folder} ..." def execute!
ovf_path = File.join(folder, "#{name}.ovf") setup_temp_dir
export
end
logger.info "Exporting required VM files to directory: #{folder} ..." def setup_temp_dir
@temp_dir = File.join(Env.tmp_path, Time.now.to_i.to_s)
logger.info "Creating temporary directory for export..."
FileUtils.mkpath(temp_dir)
@runner.invoke_callback(:set_export_temp_path, @temp_dir)
end
def ovf_path
File.join(temp_dir, Vagrant.config.vm.box_ovf)
end
def export
logger.info "Exporting VM to #{ovf_path} ..."
@runner.export(ovf_path) @runner.export(ovf_path)
end end
end end

View File

@ -2,48 +2,47 @@ module Vagrant
module Actions module Actions
module VM module VM
class Package < Base class Package < Base
attr_accessor :name, :to attr_accessor :out_path
attr_accessor :temp_path
def initialize(vm, *args) def initialize(vm, out_path = nil, *args)
super vm super
@name = args[0] @out_path = out_path || "package"
@to = args[1] @temp_path = nil
end end
def execute! def execute!
logger.info "Packaging VM into #{tar_path} ..."
compress compress
logger.info "Removing working directory ..."
clean clean
tar_path
end end
def clean def clean
FileUtils.rm_r(working_dir) logger.info "Removing temporary directory ..."
end FileUtils.rm_r(temp_path)
def working_dir
FileUtils.mkpath(File.join(@to, @name))
end end
def tar_path def tar_path
"#{working_dir}#{Vagrant.config.package.extension}" File.join(FileUtils.pwd, "#{out_path}#{Vagrant.config.package.extension}")
end end
def compress def compress
logger.info "Packaging VM into #{tar_path} ..."
Tar.open(tar_path, File::CREAT | File::WRONLY, 0644, Tar::GNU) do |tar| Tar.open(tar_path, File::CREAT | File::WRONLY, 0644, Tar::GNU) do |tar|
begin begin
# Append tree will append the entire directory tree unless a relative folder reference is used # Append tree will append the entire directory tree unless a relative folder reference is used
current_dir = FileUtils.pwd current_dir = FileUtils.pwd
FileUtils.cd(@to) FileUtils.cd(temp_path)
tar.append_tree(@name) tar.append_tree(".")
ensure ensure
FileUtils.cd(current_dir) FileUtils.cd(current_dir)
end end
end end
end end
# This is a callback by Actions::VM::Export
def set_export_temp_path(temp_path)
@temp_path = temp_path
end
end end
end end
end end

View File

@ -113,17 +113,14 @@ error
# Export and package the current vm # Export and package the current vm
# #
# This command requires that an instance be powered off # This command requires that an instance be powered off
def package(name=nil) def package(out_path=nil)
Env.load! Env.load!
Env.require_persisted_vm Env.require_persisted_vm
error_and_exit(<<-error) unless Env.persisted_vm.powered_off? error_and_exit(<<-error) unless Env.persisted_vm.powered_off?
The vagrant virtual environment you are trying to package must be powered off The vagrant virtual environment you are trying to package must be powered off
error error
# TODO allow directory specification
act_on_vm do |vm| Env.persisted_vm.package(out_path)
vm.add_action(Actions::VM::Export)
vm.add_action(Actions::VM::Package, name || Vagrant.config[:package][:name], FileUtils.pwd)
end
end end
# Manages the `vagrant box` command, allowing the user to add # Manages the `vagrant box` command, allowing the user to add

View File

@ -19,6 +19,12 @@ module Vagrant
@vm = vm @vm = vm
end end
def package(out_path)
add_action(Actions::VM::Export)
add_action(Actions::VM::Package, out_path)
execute!
end
def destroy def destroy
execute!(Actions::VM::Stop) if @vm.running? execute!(Actions::VM::Stop) if @vm.running?

View File

@ -2,20 +2,66 @@ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
class ExportActionTest < Test::Unit::TestCase class ExportActionTest < Test::Unit::TestCase
setup do setup do
@wrapper_vm, @vm, @action = mock_action(Vagrant::Actions::VM::Export) @runner, @vm, @action = mock_action(Vagrant::Actions::VM::Export)
mock_config mock_config
end end
should "setup and correct working directory and export to it" do context "executing" do
new_dir = File.join(FileUtils.pwd, Vagrant.config.package.name) should "setup the temp dir then export" do
FileUtils.expects(:mkpath).with(new_dir).returns(new_dir) exec_seq = sequence('execute')
@wrapper_vm.expects(:export).with(File.join(new_dir, "#{Vagrant.config.package.name}.ovf")) @action.expects(:setup_temp_dir).once.in_sequence(exec_seq)
@action.execute! @action.expects(:export).once.in_sequence(exec_seq)
@action.execute!
end
end
context "setting up the temporary directory" do
setup do
@time_now = Time.now.to_i.to_s
Time.stubs(:now).returns(@time_now)
#FileUtils.expects(:rm_r).with(new_dir) @tmp_path = "foo"
Vagrant::Env.stubs(:tmp_path).returns(@tmp_path)
@temp_dir = File.join(Vagrant::Env.tmp_path, @time_now)
end
# assert_equal Vagrant::VM.new(@mock_vm).package(name, location), "#{new_dir}.box" should "create the temporary directory using the current time" do
FileUtils.expects(:mkpath).with(@temp_dir).once
@action.setup_temp_dir
end
should "set the temporary directory to the temp_dir variable" do
@action.setup_temp_dir
assert_equal @temp_dir, @action.temp_dir
end
should "call the set_export_temp_path callback" do
@runner.expects(:invoke_callback).with(:set_export_temp_path, @temp_dir).once
@action.setup_temp_dir
end
end
context "path to OVF file" do
setup do
@temp_dir = "foo"
@action.stubs(:temp_dir).returns(@temp_dir)
end
should "be the temporary directory joined with the OVF filename" do
assert_equal File.join(@temp_dir, Vagrant.config.vm.box_ovf), @action.ovf_path
end
end
context "exporting" do
setup do
@ovf_path = mock("ovf_path")
@action.stubs(:ovf_path).returns(@ovf_path)
end
should "call export on the runner with the ovf path" do
@runner.expects(:export).with(@ovf_path).once
@action.export
end
end end
end end

View File

@ -2,19 +2,17 @@ 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::VM::Package) @wrapper_vm, @vm, @action = mock_action(Vagrant::Actions::VM::Package, "bing")
@action.to = '/foo/bar/baz'
@action.name = 'bing'
mock_config mock_config
@temp_path = "temp_path"
@action.temp_path = @temp_path
end end
context "executing" do context "executing" do
setup do setup do
@tar_path = "foo"
@action.stubs(:compress) @action.stubs(:compress)
@action.stubs(:clean) @action.stubs(:clean)
@action.stubs(:tar_path).returns(@tar_path)
end end
should "compress and remove the working directory" do should "compress and remove the working directory" do
@ -23,10 +21,6 @@ class PackageActionTest < Test::Unit::TestCase
@action.expects(:clean).in_sequence(package_seq) @action.expects(:clean).in_sequence(package_seq)
@action.execute! @action.execute!
end end
should "return the tar path" do
assert_equal @tar_path, @action.execute!
end
end end
context "cleaning up" do context "cleaning up" do
@ -36,22 +30,16 @@ class PackageActionTest < Test::Unit::TestCase
end end
should "remove the working directory" do should "remove the working directory" do
FileUtils.expects(:rm_r).with(@working_dir).once FileUtils.expects(:rm_r).with(@temp_path).once
@action.clean @action.clean
end end
end end
context "working directory" do
should "create the directory" do
FileUtils.expects(:mkpath).with(File.join(@action.to, @action.name))
@action.working_dir
end
end
context "tar path" do context "tar path" do
should "be the working directory with the extension attached" do should "be the temporary directory with the name and extension attached" do
@action.expects(:working_dir).returns("foo") pwd = "foo"
assert_equal "foo#{Vagrant.config.package.extension}", @action.tar_path FileUtils.stubs(:pwd).returns(pwd)
assert_equal File.join(pwd, "#{@action.out_path}#{Vagrant.config.package.extension}"), @action.tar_path
end end
end end
@ -79,15 +67,15 @@ class PackageActionTest < Test::Unit::TestCase
should "cd to the directory and append the directory" do should "cd to the directory and append the directory" do
compress_seq = sequence("compress_seq") compress_seq = sequence("compress_seq")
FileUtils.expects(:pwd).once.returns(@pwd).in_sequence(compress_seq) FileUtils.expects(:pwd).once.returns(@pwd).in_sequence(compress_seq)
FileUtils.expects(:cd).with(@action.to).in_sequence(compress_seq) FileUtils.expects(:cd).with(@temp_path).in_sequence(compress_seq)
@tar.expects(:append_tree).with(@action.name).in_sequence(compress_seq) @tar.expects(:append_tree).with(".").in_sequence(compress_seq)
FileUtils.expects(:cd).with(@pwd).in_sequence(compress_seq) FileUtils.expects(:cd).with(@pwd).in_sequence(compress_seq)
@action.compress @action.compress
end end
should "pop back to the current directory even if an exception is raised" do should "pop back to the current directory even if an exception is raised" do
cd_seq = sequence("cd_seq") cd_seq = sequence("cd_seq")
FileUtils.expects(:cd).with(@action.to).raises(Exception).in_sequence(cd_seq) FileUtils.expects(:cd).with(@temp_path).raises(Exception).in_sequence(cd_seq)
FileUtils.expects(:cd).with(@pwd).in_sequence(cd_seq) FileUtils.expects(:cd).with(@pwd).in_sequence(cd_seq)
assert_raises(Exception) { assert_raises(Exception) {
@ -95,4 +83,12 @@ class PackageActionTest < Test::Unit::TestCase
} }
end end
end end
context "export callback to set temp path" do
should "save to the temp_path directory" do
foo = mock("foo")
@action.set_export_temp_path(foo)
assert foo.equal?(@action.temp_path)
end
end
end end

View File

@ -155,8 +155,6 @@ class CommandsTest < Test::Unit::TestCase
setup do setup do
@persisted_vm.stubs(:package) @persisted_vm.stubs(:package)
@persisted_vm.stubs(:powered_off?).returns(true) @persisted_vm.stubs(:powered_off?).returns(true)
@persisted_vm.expects(:add_action).twice
@persisted_vm.expects(:execute!)
end end
should "require a persisted vm" do should "require a persisted vm" do
@ -170,6 +168,17 @@ class CommandsTest < Test::Unit::TestCase
@persisted_vm.expects(:package).never @persisted_vm.expects(:package).never
Vagrant::Commands.package Vagrant::Commands.package
end end
should "call package on the persisted VM" do
@persisted_vm.expects(:package).once
Vagrant::Commands.package
end
should "pass in the out path to the package method" do
out_path = mock("out_path")
@persisted_vm.expects(:package).with(out_path).once
Vagrant::Commands.package(out_path)
end
end end
context "box" do context "box" do

View File

@ -37,6 +37,17 @@ class VMTest < Test::Unit::TestCase
@vm = Vagrant::VM.new(@mock_vm) @vm = Vagrant::VM.new(@mock_vm)
end end
context "packaging" do
should "queue up the actions and execute" do
out_path = mock("out_path")
action_seq = sequence("actions")
@vm.expects(:add_action).with(Vagrant::Actions::VM::Export).once.in_sequence(action_seq)
@vm.expects(:add_action).with(Vagrant::Actions::VM::Package, out_path).once.in_sequence(action_seq)
@vm.expects(:execute!).in_sequence(action_seq)
@vm.package(out_path)
end
end
context "destroying" do context "destroying" do
setup do setup do
@mock_vm.stubs(:running?).returns(false) @mock_vm.stubs(:running?).returns(false)