Separate vagrantfile creation in packaging and actual packaging

This commit is contained in:
Mitchell Hashimoto 2010-07-27 23:22:10 -07:00
parent d9331c9406
commit 9895f93e1d
12 changed files with 167 additions and 34 deletions

View File

@ -89,6 +89,7 @@ module Vagrant
use VM::ClearForwardedPorts use VM::ClearForwardedPorts
use VM::ClearSharedFolders use VM::ClearSharedFolders
use VM::Export use VM::Export
use VM::PackageVagrantfile
use VM::Package use VM::Package
end end

View File

@ -32,6 +32,7 @@ module Vagrant
def setup_temp_dir def setup_temp_dir
@env.logger.info "Creating temporary directory for export..." @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) @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"]) FileUtils.mkpath(@env["export.temp_dir"])
end end

View File

@ -16,7 +16,7 @@ module Vagrant
def call(env) def call(env)
@env = 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 return if !verify_included_files
compress compress
@ -46,7 +46,7 @@ module Vagrant
# the actual box # the actual box
def copy_include_files def copy_include_files
if @env["package.include"].length > 0 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) FileUtils.mkdir_p(include_dir)
@env["package.include"].each do |f| @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 # box. This Vagrantfile contains the MAC address so that the user doesn't
# have to worry about it. # have to worry about it.
def create_vagrantfile 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", { f.write(TemplateRenderer.render("package_Vagrantfile", {
:base_mac => @env["vm"].vm.network_adapters.first.mac_address :base_mac => @env["vm"].vm.network_adapters.first.mac_address
})) }))
@ -76,9 +76,8 @@ module Vagrant
current_dir = FileUtils.pwd current_dir = FileUtils.pwd
copy_include_files copy_include_files
create_vagrantfile
FileUtils.cd(@env["export.temp_dir"]) FileUtils.cd(@env["package.directory"])
Dir.glob(File.join(".", "**", "*")).each do |entry| Dir.glob(File.join(".", "**", "*")).each do |entry|
Archive::Tar::Minitar.pack_file(entry, output) Archive::Tar::Minitar.pack_file(entry, output)
end end

View File

@ -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

View File

@ -132,11 +132,16 @@ module Vagrant
env.actions.run(:box_add, { "box" => self }) env.actions.run(:box_add, { "box" => self })
end end
# Beings the process of destroying this box. # Begins the process of destroying this box.
def destroy def destroy
env.actions.run(:box_remove, { "box" => self }) env.actions.run(:box_remove, { "box" => self })
end 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 # Returns the directory to the location of this boxes content in the local
# filesystem. # filesystem.
# #

View File

@ -27,4 +27,4 @@ module Vagrant
end end
end end
end end
end end

View File

@ -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

View File

@ -84,6 +84,11 @@
Specified output file: <%= output_file %> Specified output file: <%= output_file %>
:box_remove_doesnt_exist: |- :box_remove_doesnt_exist: |-
The box you're attempting to remove does not 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: |- :box_specified_doesnt_exist: |-
Specified box `<%= box_name %>` does not exist! Specified box `<%= box_name %>` does not exist!

View File

@ -106,6 +106,7 @@ class ExportVMActionTest < Test::Unit::TestCase
should "set to the environment" do should "set to the environment" do
@instance.setup_temp_dir @instance.setup_temp_dir
assert_equal @temp_dir, @env["export.temp_dir"] assert_equal @temp_dir, @env["export.temp_dir"]
assert_equal @temp_dir, @env["package.directory"]
assert_equal @temp_dir, @instance.temp_dir assert_equal @temp_dir, @instance.temp_dir
end end
end end

View File

@ -59,7 +59,7 @@ class PackageVMActionTest < Test::Unit::TestCase
File.stubs(:exist?).returns(false) File.stubs(:exist?).returns(false)
@instance = @klass.new(@app, @env) @instance = @klass.new(@app, @env)
@env["export.temp_dir"] = "foo" @env["package.directory"] = "foo"
end end
context "calling" do context "calling" do
@ -82,7 +82,7 @@ class PackageVMActionTest < Test::Unit::TestCase
end end
should "halt the chain if export didn't run" do should "halt the chain if export didn't run" do
@env["export.temp_dir"] = nil @env["package.directory"] = nil
@app.expects(:call).never @app.expects(:call).never
@instance.call(@env) @instance.call(@env)
@ -157,7 +157,7 @@ class PackageVMActionTest < Test::Unit::TestCase
end end
should "create the include directory and copy files to it" do 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") copy_seq = sequence("copy_seq")
FileUtils.expects(:mkdir_p).with(include_dir).once.in_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
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 context "compression" do
setup do setup do
@env["package.include"] = [] @env["package.include"] = []
@ -211,7 +191,6 @@ class PackageVMActionTest < Test::Unit::TestCase
@tar.stubs(:pack_file) @tar.stubs(:pack_file)
@instance.stubs(:copy_include_files) @instance.stubs(:copy_include_files)
@instance.stubs(:create_vagrantfile)
end end
should "open the tar file with the tar path properly" do 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) FileUtils.expects(:pwd).once.returns(@pwd).in_sequence(compress_seq)
@instance.expects(:copy_include_files).once.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["package.directory"]).in_sequence(compress_seq)
FileUtils.expects(:cd).with(@env["export.temp_dir"]).in_sequence(compress_seq)
Dir.expects(:glob).returns(@files).in_sequence(compress_seq) Dir.expects(:glob).returns(@files).in_sequence(compress_seq)
5.times do |i| 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 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(@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) FileUtils.expects(:cd).with(@pwd).in_sequence(cd_seq)
assert_raises(Exception) { assert_raises(Exception) {

View File

@ -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

View File

@ -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