From 780673c6fe01cda76d898ef5648f36a51b885d0d Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Sat, 20 Jan 2018 06:51:59 -0800 Subject: [PATCH] Add warning message for VirtualBox shared folders option. Display warning to user about the VirtualBox SharedFoldersEnableSymlinksCreate option with link to VirtualBox documentation and instructions on how the setting can be disabled. --- plugins/providers/virtualbox/synced_folder.rb | 25 ++++- templates/locales/en.yml | 15 +++ .../virtualbox/synced_folder_test.rb | 93 ++++++++++++++++++- 3 files changed, 126 insertions(+), 7 deletions(-) diff --git a/plugins/providers/virtualbox/synced_folder.rb b/plugins/providers/virtualbox/synced_folder.rb index 695b41ee5..5b8a9799b 100644 --- a/plugins/providers/virtualbox/synced_folder.rb +++ b/plugins/providers/virtualbox/synced_folder.rb @@ -1,3 +1,4 @@ +require "fileutils" require "vagrant/util/platform" module VagrantPlugins @@ -97,35 +98,51 @@ module VagrantPlugins # transient. def share_folders(machine, folders, transient) defs = [] + warn_user_symlink = false + folders.each do |id, data| hostpath = data[:hostpath] if !data[:hostpath_exact] hostpath = Vagrant::Util::Platform.cygwin_windows_path(hostpath) end - sharefoldersenablesymlinkscreate = true + enable_symlink_create = true if ENV['VAGRANT_DISABLE_VBOXSYMLINKCREATE'] - sharefoldersenablesymlinkscreate = false + enable_symlink_create = false end unless data[:SharedFoldersEnableSymlinksCreate].nil? - sharefoldersenablesymlinkscreate = data[:SharedFoldersEnableSymlinksCreate] + enable_symlink_create = data[:SharedFoldersEnableSymlinksCreate] end + warn_user_symlink ||= enable_symlink_create + # Only setup the shared folders that match our transient level if (!!data[:transient]) == transient defs << { name: os_friendly_id(id), hostpath: hostpath.to_s, transient: transient, - SharedFoldersEnableSymlinksCreate: sharefoldersenablesymlinkscreate + SharedFoldersEnableSymlinksCreate: enable_symlink_create } end end + if warn_user_symlink + display_symlink_create_warning(machine.env) + end + driver(machine).share_folders(defs) end + + def display_symlink_create_warning(env) + d_file = env.data_dir.join("vbox_symlink_create_warning") + if !d_file.exist? + FileUtils.touch(d_file.to_path) + env.ui.warn(I18n.t("vagrant.virtualbox.warning.shared_folder_symlink_create")) + end + end end end end diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 0f591b94c..f205fd819 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -329,7 +329,22 @@ en: invalid_event: |- %{event} is not a valid event for customization. Valid events are: %{valid_events} + warning: + shared_folder_symlink_create: |- + Vagrant is currently configured to create VirtualBox synced folders with + the `SharedFoldersEnableSymlinksCreate` option enabled. If the Vagrant + guest is not trusted, you may want to disable this option. For more + information on this option, please refer to the VirtualBox manual: + https://www.virtualbox.org/manual/ch04.html#sharedfolders + + This option can be disabled globally with an environment variable: + + VAGRANT_DISABLE_VBOXSYMLINKCREATE=1 + + or on a per folder basis within the Vagrantfile: + + config.vm.synced_folder '/host/path', '/guest/path', SharedFoldersEnableSymlinksCreate: false general: batch_notify_error: |- An error occurred. The error will be shown after all tasks complete. diff --git a/test/unit/plugins/providers/virtualbox/synced_folder_test.rb b/test/unit/plugins/providers/virtualbox/synced_folder_test.rb index 683fd9dee..1eb3d77c3 100644 --- a/test/unit/plugins/providers/virtualbox/synced_folder_test.rb +++ b/test/unit/plugins/providers/virtualbox/synced_folder_test.rb @@ -19,7 +19,7 @@ describe VagrantPlugins::ProviderVirtualBox::SyncedFolder do machine.provider_config.finalize! end - describe "usable" do + describe "#usable?" do it "should be with virtualbox provider" do allow(machine).to receive(:provider_name).and_return(:virtualbox) expect(subject).to be_usable(machine) @@ -36,7 +36,7 @@ describe VagrantPlugins::ProviderVirtualBox::SyncedFolder do end end - describe "prepare" do + describe "#prepare" do let(:driver) { double("driver") } let(:provider) { double("driver", driver: driver) } let(:folders) { {"/folder"=> @@ -61,6 +61,8 @@ describe VagrantPlugins::ProviderVirtualBox::SyncedFolder do before do allow(machine).to receive(:provider).and_return(provider) + allow(machine).to receive(:env) + allow(subject).to receive(:display_symlink_create_warning) end it "should prepare and share the folders" do @@ -88,7 +90,7 @@ describe VagrantPlugins::ProviderVirtualBox::SyncedFolder do end end - describe "os_friendly_id" do + describe "#os_friendly_id" do it "should not replace normal chars" do expect(subject.send(:os_friendly_id, 'perfectly_valid0_name')).to eq('perfectly_valid0_name') end @@ -113,4 +115,89 @@ describe VagrantPlugins::ProviderVirtualBox::SyncedFolder do expect(subject.send(:os_friendly_id, 'foo\\bar')).to eq('foo_bar') end end + + describe "#share_folders" do + let(:folders){ {'folder1' => {hostpath: '/vagrant', transient: true}, + 'folder2' => {hostpath: '/vagrant2', transient: false}} } + let(:symlink_create_disable){ nil } + let(:driver){ double("driver") } + + before do + allow(subject).to receive(:display_symlink_create_warning) + allow(machine).to receive(:env) + allow(subject).to receive(:driver).and_return(driver) + allow(driver).to receive(:share_folders) + allow(ENV).to receive(:[]).with("VAGRANT_DISABLE_VBOXSYMLINKCREATE").and_return(symlink_create_disable) + end + + it "should only add transient folder" do + expect(driver).to receive(:share_folders).with(any_args) do |defs| + expect(defs.size).to eq(1) + end + subject.send(:share_folders, machine, folders, true) + end + + it "should display symlink create warning" do + expect(subject).to receive(:display_symlink_create_warning) + subject.send(:share_folders, machine, folders, true) + end + + context "with create symlink globally disabled" do + let(:symlink_create_disable){ "1" } + + it "should not enable option within definitions" do + expect(driver).to receive(:share_folders).with(any_args) do |defs| + expect(defs.first[:SharedFoldersEnableSymlinksCreate]).to be(false) + end + subject.send(:share_folders, machine, folders, true) + end + + it "should not display symlink warning" do + expect(subject).not_to receive(:display_symlink_create_warning) + subject.send(:share_folders, machine, folders, true) + end + end + end + + describe "#display_symlink_create_warning" do + let(:env){ double("env", ui: double("ui"), data_dir: double("data_dir")) } + let(:gate_file){ double("gate") } + + before{ allow(gate_file).to receive(:to_path).and_return("PATH") } + after{ subject.send(:display_symlink_create_warning, env) } + + context "gate file does not exist" do + before do + allow(env.data_dir).to receive(:join).and_return(gate_file) + allow(gate_file).to receive(:exist?).and_return(false) + allow(FileUtils).to receive(:touch) + allow(env.ui).to receive(:warn) + end + + it "should create file" do + expect(FileUtils).to receive(:touch).with("PATH") + end + + it "should output warning to user" do + expect(env.ui).to receive(:warn) + end + end + + context "gate file does exist" do + before do + allow(env.data_dir).to receive(:join).and_return(gate_file) + allow(gate_file).to receive(:exist?).and_return(true) + allow(FileUtils).to receive(:touch) + allow(env.ui).to receive(:warn) + end + + it "should not create/update file" do + expect(FileUtils).not_to receive(:touch).with("PATH") + end + + it "should not output warning to user" do + expect(env.ui).not_to receive(:warn) + end + end + end end