Shared folder task

This commit is contained in:
Mitchell Hashimoto 2010-07-05 02:31:30 +02:00
parent 05a01f5953
commit 73a3723608
3 changed files with 323 additions and 0 deletions

View File

@ -9,6 +9,7 @@ module Vagrant
use VM::Import
use VM::Customize
use VM::ForwardPorts
use VM::ShareFolders
end
register :up, up

View File

@ -0,0 +1,105 @@
module Vagrant
class Action
module VM
class ShareFolders
def initialize(app, env)
@app = app
@env = env
end
def call(env)
@env = env
clear_shared_folders
create_metadata
@app.call(env)
mount_shared_folders
setup_unison
end
# This method returns an actual list of VirtualBox shared
# folders to create and their proper path.
def shared_folders
@env.env.config.vm.shared_folders.inject({}) do |acc, data|
key, value = data
# This to prevent overwriting the actual shared folders data
value = value.dup
if value[:sync]
# Syncing this folder. Change the guestpath to reflect
# what we're actually mounting.
value[:original] = value.dup
value[:guestpath] = "#{value[:guestpath]}#{@env.env.config.unison.folder_suffix}"
end
acc[key] = value
acc
end
end
# This method returns the list of shared folders which are to
# be synced via unison.
def unison_folders
shared_folders.inject({}) do |acc, data|
key, value = data
acc[key] = value if !!value[:sync]
acc
end
end
def clear_shared_folders
if @env["vm"].vm.shared_folders.length > 0
@env.logger.info "Clearing previously set shared folders..."
folders = @env["vm"].vm.shared_folders.dup
folders.each do |shared_folder|
shared_folder.destroy
end
@env["vm"].reload!
end
end
def create_metadata
@env.logger.info "Creating shared folders metadata..."
shared_folders.each do |name, data|
folder = VirtualBox::SharedFolder.new
folder.name = name
folder.host_path = File.expand_path(data[:hostpath], @env.env.root_path)
@env["vm"].vm.shared_folders << folder
end
@env["vm"].vm.save
end
def mount_shared_folders
@env.logger.info "Mounting shared folders..."
@env["vm"].ssh.execute do |ssh|
shared_folders.each do |name, data|
@env.logger.info "-- #{name}: #{data[:guestpath]}"
@env["vm"].system.mount_shared_folder(ssh, name, data[:guestpath])
end
end
end
def setup_unison
return if unison_folders.empty?
@env["vm"].ssh.execute do |ssh|
@env["vm"].system.prepare_unison(ssh)
@env.logger.info "Creating unison crontab entries..."
unison_folders.each do |name, data|
@env["vm"].system.create_unison(ssh, data)
end
end
end
end
end
end
end

View File

@ -0,0 +1,217 @@
require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
class ShareFoldersVMActionTest < Test::Unit::TestCase
setup do
@klass = Vagrant::Action::VM::ShareFolders
@app, @env = mock_action_data
@vm = mock("vm")
@vm.stubs(:name).returns("foo")
@vm.stubs(:ssh).returns(mock("ssh"))
@vm.stubs(:system).returns(mock("system"))
@env["vm"] = @vm
@internal_vm = mock("internal")
@vm.stubs(:vm).returns(@internal_vm)
@instance = @klass.new(@app, @env)
end
def stub_shared_folders
env = mock_environment do |config|
config.vm.shared_folders.clear
if block_given?
yield config
else
folders = [%w{foo fooguest foohost}, %w{bar barguest barhost}]
folders.each do |data|
config.vm.share_folder(*data)
end
end
end
@env.stubs(:env).returns(env)
env.config.vm.shared_folders
end
context "calling" do
should "run the methods in the proper order" do
before_seq = sequence("before")
@instance.expects(:clear_shared_folders).once.in_sequence(before_seq)
@instance.expects(:create_metadata).once.in_sequence(before_seq)
@app.expects(:call).with(@env).in_sequence(before_seq)
@instance.expects(:mount_shared_folders).once.in_sequence(before_seq)
@instance.expects(:setup_unison).once.in_sequence(before_seq)
@instance.call(@env)
end
end
context "collecting shared folders" do
setup do
File.stubs(:expand_path).returns("baz")
end
should "return a hash of the shared folders" do
data = {
"foo" => %W[bar baz],
"bar" => %W[foo baz]
}
stub_shared_folders do |config|
data.each do |name, value|
config.vm.share_folder(name, *value)
end
end
result = @instance.shared_folders
assert_equal data.length, result.length
data.each do |name, value|
guest, host = value
assert_equal guest, result[name][:guestpath]
assert_equal host, result[name][:hostpath]
end
end
should "append sync suffix if sync enabled to a folder" do
name = "foo"
guest = "bar"
host = "baz"
stub_shared_folders do |config|
config.vm.share_folder(name, guest, host, :sync => true)
end
result = @instance.shared_folders
assert_equal "#{guest}#{@env.env.config.unison.folder_suffix}", result[name][:guestpath]
assert_equal guest, result[name][:original][:guestpath]
end
should "not destroy original hash" do
@folders = stub_shared_folders do |config|
config.vm.share_folder("foo", "bar", "baz", :sync => true)
end
folder = @folders["foo"].dup
@instance.shared_folders
assert_equal folder, @env.env.config.vm.shared_folders["foo"]
end
end
context "unison shared folders" do
setup do
@folders = stub_shared_folders do |config|
config.vm.share_folder("foo", "bar", "baz", :sync => true)
config.vm.share_folder("bar", "foo", "baz")
end
end
should "only return the folders marked for syncing" do
result = @instance.unison_folders
assert_equal 1, result.length
assert result.has_key?("foo")
assert !result.has_key?("bar")
end
end
context "clearing shared folders" do
setup do
@shared_folder = mock("shared_folder")
@shared_folders = [@shared_folder]
@internal_vm.stubs(:shared_folders).returns(@shared_folders)
end
should "call destroy on each shared folder then reload" do
destroy_seq = sequence("destroy")
@shared_folders.each do |sf|
sf.expects(:destroy).once.in_sequence(destroy_seq)
end
@vm.expects(:reload!).once.in_sequence(destroy_seq)
@instance.clear_shared_folders
end
should "do nothing if no shared folders existed" do
@shared_folders.clear
@vm.expects(:reload!).never
@instance.clear_shared_folders
end
end
context "setting up shared folder metadata" do
setup do
stub_shared_folders
end
should "add all shared folders to the VM" do
shared_folders = []
data = %W[foo bar]
shared_folders.expects(:<<).times(data.length).with() do |sf|
hostpath = File.expand_path("#{sf.name}host", @env.env.root_path)
assert data.include?(sf.name)
assert_equal hostpath, sf.host_path
true
end
@internal_vm.stubs(:shared_folders).returns(shared_folders)
@internal_vm.expects(:save).once
@instance.create_metadata
end
end
context "mounting the shared folders" do
setup do
@folders = stub_shared_folders
@ssh = mock("ssh")
@vm.ssh.stubs(:execute).yields(@ssh)
@vm.system.stubs(:mount_shared_folder)
end
should "mount all shared folders to the VM" do
mount_seq = sequence("mount_seq")
@folders.each do |name, data|
@vm.system.expects(:mount_shared_folder).with(@ssh, name, data[:guestpath]).in_sequence(mount_seq)
end
@instance.mount_shared_folders
end
end
context "setting up unison" do
setup do
@ssh = mock("ssh")
@vm.ssh.stubs(:execute).yields(@ssh)
@folders = stub_shared_folders do |config|
config.vm.share_folder("foo", "bar", "baz", :sync => true)
config.vm.share_folder("bar", "foo", "baz")
end
end
should "do nothing if unison folders is empty" do
@instance.stubs(:unison_folders).returns({})
@vm.ssh.expects(:execute).never
@instance.setup_unison
end
should "prepare unison then create for each folder" do
seq = sequence("unison seq")
@vm.system.expects(:prepare_unison).with(@ssh).once.in_sequence(seq)
@instance.unison_folders.each do |name, data|
if data[:sync]
@vm.system.expects(:create_unison).with do |ssh, opts|
assert_equal @ssh, ssh
assert_equal data, opts
true
end
end
end
@instance.setup_unison
end
end
end