diff --git a/lib/vagrant/action/builtin.rb b/lib/vagrant/action/builtin.rb index 3e3b7e820..e5d852c20 100644 --- a/lib/vagrant/action/builtin.rb +++ b/lib/vagrant/action/builtin.rb @@ -89,6 +89,7 @@ module Vagrant use VM::ClearForwardedPorts use VM::ClearSharedFolders use VM::Export + use VM::PackageVagrantfile use VM::Package end diff --git a/lib/vagrant/action/vm/export.rb b/lib/vagrant/action/vm/export.rb index e4c7e0909..cf8ba1ce3 100644 --- a/lib/vagrant/action/vm/export.rb +++ b/lib/vagrant/action/vm/export.rb @@ -32,6 +32,7 @@ module Vagrant def setup_temp_dir @env.logger.info "Creating temporary directory for export..." @temp_dir = @env["export.temp_dir"] = File.join(@env.env.tmp_path, Time.now.to_i.to_s) + @env["package.directory"] = @temp_dir # TODO temporary FileUtils.mkpath(@env["export.temp_dir"]) end diff --git a/lib/vagrant/action/vm/package.rb b/lib/vagrant/action/vm/package.rb index c7e951b77..db75dc8f4 100644 --- a/lib/vagrant/action/vm/package.rb +++ b/lib/vagrant/action/vm/package.rb @@ -16,7 +16,7 @@ module Vagrant def call(env) @env = env - return env.error!(:package_requires_export) if !@env["export.temp_dir"] + return env.error!(:package_requires_export) if !@env["package.directory"] return if !verify_included_files compress @@ -46,7 +46,7 @@ module Vagrant # the actual box def copy_include_files if @env["package.include"].length > 0 - include_dir = File.join(@env["export.temp_dir"], "include") + include_dir = File.join(@env["package.directory"], "include") FileUtils.mkdir_p(include_dir) @env["package.include"].each do |f| @@ -60,7 +60,7 @@ module Vagrant # box. This Vagrantfile contains the MAC address so that the user doesn't # have to worry about it. def create_vagrantfile - File.open(File.join(@env["export.temp_dir"], "Vagrantfile"), "w") do |f| + File.open(File.join(@env["package.directory"], "Vagrantfile"), "w") do |f| f.write(TemplateRenderer.render("package_Vagrantfile", { :base_mac => @env["vm"].vm.network_adapters.first.mac_address })) @@ -76,9 +76,8 @@ module Vagrant current_dir = FileUtils.pwd copy_include_files - create_vagrantfile - FileUtils.cd(@env["export.temp_dir"]) + FileUtils.cd(@env["package.directory"]) Dir.glob(File.join(".", "**", "*")).each do |entry| Archive::Tar::Minitar.pack_file(entry, output) end diff --git a/lib/vagrant/action/vm/package_vagrantfile.rb b/lib/vagrant/action/vm/package_vagrantfile.rb new file mode 100644 index 000000000..4bd1ce0d7 --- /dev/null +++ b/lib/vagrant/action/vm/package_vagrantfile.rb @@ -0,0 +1,33 @@ +module Vagrant + class Action + module VM + # Puts a generated Vagrantfile into the package directory so that + # it can be included in the package. + class PackageVagrantfile + include Util + + def initialize(app, env) + @app = app + @env = env + end + + def call(env) + @env = env + create_vagrantfile + @app.call(env) + end + + # This method creates the auto-generated Vagrantfile at the root of the + # box. This Vagrantfile contains the MAC address so that the user doesn't + # have to worry about it. + def create_vagrantfile + File.open(File.join(@env["package.directory"], "Vagrantfile"), "w") do |f| + f.write(TemplateRenderer.render("package_Vagrantfile", { + :base_mac => @env["vm"].vm.network_adapters.first.mac_address + })) + end + end + end + end + end +end diff --git a/lib/vagrant/box.rb b/lib/vagrant/box.rb index f41c111fe..fcaf4a2a0 100644 --- a/lib/vagrant/box.rb +++ b/lib/vagrant/box.rb @@ -132,11 +132,16 @@ module Vagrant env.actions.run(:box_add, { "box" => self }) end - # Beings the process of destroying this box. + # Begins the process of destroying this box. def destroy env.actions.run(:box_remove, { "box" => self }) end + # Begins sequence to repackage this box. + def repackage + env.actions.run(:box_repackage, { "box" => self }) + end + # Returns the directory to the location of this boxes content in the local # filesystem. # diff --git a/lib/vagrant/commands/box/list.rb b/lib/vagrant/commands/box/list.rb index a33b76c0d..23e1175e9 100644 --- a/lib/vagrant/commands/box/list.rb +++ b/lib/vagrant/commands/box/list.rb @@ -27,4 +27,4 @@ module Vagrant end end end -end \ No newline at end of file +end diff --git a/lib/vagrant/commands/box/repackage.rb b/lib/vagrant/commands/box/repackage.rb new file mode 100644 index 000000000..7baeeed38 --- /dev/null +++ b/lib/vagrant/commands/box/repackage.rb @@ -0,0 +1,23 @@ +module Vagrant + class Commands + module Box + # Repackage a box which has been added. + class Repackage < BoxCommand + BoxCommand.subcommand "repackage", self + description "Repackages a box which has already been added." + + def execute(args=[]) + return show_help if args.length != 1 + + box = Vagrant::Box.find(env, args.first) + return error_and_exit(:box_repackage_doesnt_exist) if box.nil? + box.repackage + end + + def options_spec(opts) + opts.banner = "Usage: vagrant box repackage NAME" + end + end + end + end +end diff --git a/templates/strings.yml b/templates/strings.yml index a2e313809..5d5176cbf 100644 --- a/templates/strings.yml +++ b/templates/strings.yml @@ -84,6 +84,11 @@ Specified output file: <%= output_file %> :box_remove_doesnt_exist: |- The box you're attempting to remove does not exist! +:box_repackage_doesnt_exist: |- + The box you're attempting to repackage does not exist. Please check the + name you specified and try again. As a reminder, the repackage + command is for repackaging boxes which have been added through `vagrant box add` + but the box has been lost. :box_specified_doesnt_exist: |- Specified box `<%= box_name %>` does not exist! diff --git a/test/vagrant/action/vm/export_test.rb b/test/vagrant/action/vm/export_test.rb index 9efebded9..dc06384ed 100644 --- a/test/vagrant/action/vm/export_test.rb +++ b/test/vagrant/action/vm/export_test.rb @@ -106,6 +106,7 @@ class ExportVMActionTest < Test::Unit::TestCase should "set to the environment" do @instance.setup_temp_dir assert_equal @temp_dir, @env["export.temp_dir"] + assert_equal @temp_dir, @env["package.directory"] assert_equal @temp_dir, @instance.temp_dir end end diff --git a/test/vagrant/action/vm/package_test.rb b/test/vagrant/action/vm/package_test.rb index 97b3ff52c..53d243b99 100644 --- a/test/vagrant/action/vm/package_test.rb +++ b/test/vagrant/action/vm/package_test.rb @@ -59,7 +59,7 @@ class PackageVMActionTest < Test::Unit::TestCase File.stubs(:exist?).returns(false) @instance = @klass.new(@app, @env) - @env["export.temp_dir"] = "foo" + @env["package.directory"] = "foo" end context "calling" do @@ -82,7 +82,7 @@ class PackageVMActionTest < Test::Unit::TestCase end should "halt the chain if export didn't run" do - @env["export.temp_dir"] = nil + @env["package.directory"] = nil @app.expects(:call).never @instance.call(@env) @@ -157,7 +157,7 @@ class PackageVMActionTest < Test::Unit::TestCase end should "create the include directory and copy files to it" do - include_dir = File.join(@env["export.temp_dir"], "include") + include_dir = File.join(@env["package.directory"], "include") copy_seq = sequence("copy_seq") FileUtils.expects(:mkdir_p).with(include_dir).once.in_sequence(copy_seq) @@ -171,26 +171,6 @@ class PackageVMActionTest < Test::Unit::TestCase end end - context "creating vagrantfile" do - setup do - @network_adapter = mock("nic") - @network_adapter.stubs(:mac_address).returns("mac_address") - @internal_vm.stubs(:network_adapters).returns([@network_adapter]) - end - - should "write the rendered vagrantfile to temp_path Vagrantfile" do - f = mock("file") - rendered = mock("rendered") - File.expects(:open).with(File.join(@env["export.temp_dir"], "Vagrantfile"), "w").yields(f) - Vagrant::Util::TemplateRenderer.expects(:render).returns(rendered).with("package_Vagrantfile", { - :base_mac => @internal_vm.network_adapters.first.mac_address - }) - f.expects(:write).with(rendered) - - @instance.create_vagrantfile - end - end - context "compression" do setup do @env["package.include"] = [] @@ -211,7 +191,6 @@ class PackageVMActionTest < Test::Unit::TestCase @tar.stubs(:pack_file) @instance.stubs(:copy_include_files) - @instance.stubs(:create_vagrantfile) end should "open the tar file with the tar path properly" do @@ -233,8 +212,7 @@ class PackageVMActionTest < Test::Unit::TestCase FileUtils.expects(:pwd).once.returns(@pwd).in_sequence(compress_seq) @instance.expects(:copy_include_files).once.in_sequence(compress_seq) - @instance.expects(:create_vagrantfile).once.in_sequence(compress_seq) - FileUtils.expects(:cd).with(@env["export.temp_dir"]).in_sequence(compress_seq) + FileUtils.expects(:cd).with(@env["package.directory"]).in_sequence(compress_seq) Dir.expects(:glob).returns(@files).in_sequence(compress_seq) 5.times do |i| @@ -249,7 +227,7 @@ class PackageVMActionTest < Test::Unit::TestCase should "pop back to the current directory even if an exception is raised" do cd_seq = sequence("cd_seq") - FileUtils.expects(:cd).with(@env["export.temp_dir"]).raises(Exception).in_sequence(cd_seq) + FileUtils.expects(:cd).with(@env["package.directory"]).raises(Exception).in_sequence(cd_seq) FileUtils.expects(:cd).with(@pwd).in_sequence(cd_seq) assert_raises(Exception) { diff --git a/test/vagrant/action/vm/package_vagrantfile_test.rb b/test/vagrant/action/vm/package_vagrantfile_test.rb new file mode 100644 index 000000000..96cfaf9ec --- /dev/null +++ b/test/vagrant/action/vm/package_vagrantfile_test.rb @@ -0,0 +1,46 @@ +require "test_helper" + +class PackageVagrantfileVMActionTest < Test::Unit::TestCase + setup do + @klass = Vagrant::Action::VM::PackageVagrantfile + @app, @env = mock_action_data + + @vm = mock("vm") + @env["vm"] = @vm + @env["package.directory"] = "foo" + + @internal_vm = mock("internal") + @vm.stubs(:vm).returns(@internal_vm) + @instance = @klass.new(@app, @env) + end + + context "calling" do + should "create the vagrantfile then continue chain" do + seq = sequence("sequence") + @instance.expects(:create_vagrantfile).in_sequence(seq) + @app.expects(:call).with(@env).in_sequence(seq) + + @instance.call(@env) + end + end + + context "creating vagrantfile" do + setup do + @network_adapter = mock("nic") + @network_adapter.stubs(:mac_address).returns("mac_address") + @internal_vm.stubs(:network_adapters).returns([@network_adapter]) + end + + should "write the rendered vagrantfile to temp_path Vagrantfile" do + f = mock("file") + rendered = mock("rendered") + File.expects(:open).with(File.join(@env["package.directory"], "Vagrantfile"), "w").yields(f) + Vagrant::Util::TemplateRenderer.expects(:render).returns(rendered).with("package_Vagrantfile", { + :base_mac => @internal_vm.network_adapters.first.mac_address + }) + f.expects(:write).with(rendered) + + @instance.create_vagrantfile + end + end +end diff --git a/test/vagrant/commands/box/repackage_test.rb b/test/vagrant/commands/box/repackage_test.rb new file mode 100644 index 000000000..d10744732 --- /dev/null +++ b/test/vagrant/commands/box/repackage_test.rb @@ -0,0 +1,41 @@ +require "test_helper" + +class CommandsBoxRepackageTest < Test::Unit::TestCase + setup do + @klass = Vagrant::Commands::Box::Repackage + + @persisted_vm = mock("persisted_vm") + @persisted_vm.stubs(:execute!) + + @env = mock_environment + @env.stubs(:require_persisted_vm) + @env.stubs(:vm).returns(@persisted_vm) + + @instance = @klass.new(@env) + end + + context "executing" do + setup do + @name = "foo" + end + + should "show help if not enough arguments" do + Vagrant::Box.expects(:find).never + @instance.expects(:show_help).once + @instance.execute([]) + end + + should "error and exit if the box doesn't exist" do + Vagrant::Box.expects(:find).returns(nil) + @instance.expects(:error_and_exit).with(:box_repackage_doesnt_exist).once + @instance.execute([@name]) + end + + should "call destroy on the box if it exists" do + @box = mock("box") + Vagrant::Box.expects(:find).with(@env, @name).returns(@box) + @box.expects(:repackage).once + @instance.execute([@name]) + end + end +end