Shared folder task
This commit is contained in:
parent
05a01f5953
commit
73a3723608
|
@ -9,6 +9,7 @@ module Vagrant
|
||||||
use VM::Import
|
use VM::Import
|
||||||
use VM::Customize
|
use VM::Customize
|
||||||
use VM::ForwardPorts
|
use VM::ForwardPorts
|
||||||
|
use VM::ShareFolders
|
||||||
end
|
end
|
||||||
|
|
||||||
register :up, up
|
register :up, up
|
||||||
|
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue