From 1cff8c7495d780b0e1def78533ec7c7c737a047e Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Tue, 2 Nov 2021 16:42:11 -0700 Subject: [PATCH 1/3] Pass values to exception and define exception message content --- .../guests/darwin/cap/mount_smb_shared_folder.rb | 9 ++++++--- templates/locales/en.yml | 13 +++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/plugins/guests/darwin/cap/mount_smb_shared_folder.rb b/plugins/guests/darwin/cap/mount_smb_shared_folder.rb index 818aec2ed..95c1ff15f 100644 --- a/plugins/guests/darwin/cap/mount_smb_shared_folder.rb +++ b/plugins/guests/darwin/cap/mount_smb_shared_folder.rb @@ -29,9 +29,12 @@ module VagrantPlugins "//#{options[:smb_username]}:#{smb_password}@#{options[:smb_host]}/#{name} " + "#{expanded_guest_path}" retryable(on: Vagrant::Errors::DarwinMountFailed, tries: 10, sleep: 2) do - machine.communicate.execute( - mount_command, - error_class: Vagrant::Errors::DarwinMountFailed) + result = machine.communicate.execute(mount_command) + if result.exit_code != 0 + raise Vagrant::Errors::DarwinMountFailed, + command: mount_command, + output: result.stderr + end end end end diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 10ec97d31..800a1d04e 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -845,6 +845,19 @@ en: create_iso_host_cap_not_found: |- Vagrant cannot create an iso due to the host capability for creating isos not existing. Vagrant will now exit. + darwin_mount_failed: |- + Failed to mount folders in Darwin guest. The command attempted was: + + %{command} + + The error output from the last command was: + + %{output} + darwin_version_failed: |- + Failed to determine macOS version. + + Version string: %{version} + Error information: %{error} destroy_requires_force: |- Destroy doesn't have a TTY to ask for confirmation. Please pass the `--force` flag to force a destroy, otherwise attach a TTY so that From 6810c7b4bb1b5f7982234ae80dc8b9e5dbcb1eb2 Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Tue, 2 Nov 2021 16:43:26 -0700 Subject: [PATCH 2/3] Add version capability to darwin host plugin --- lib/vagrant/errors.rb | 4 ++ plugins/hosts/darwin/cap/version.rb | 23 +++++++++ plugins/hosts/darwin/plugin.rb | 5 ++ .../plugins/hosts/darwin/cap/version_test.rb | 47 +++++++++++++++++++ 4 files changed, 79 insertions(+) create mode 100644 plugins/hosts/darwin/cap/version.rb create mode 100644 test/unit/plugins/hosts/darwin/cap/version_test.rb diff --git a/lib/vagrant/errors.rb b/lib/vagrant/errors.rb index 6d27f3d5d..2ac521a1b 100644 --- a/lib/vagrant/errors.rb +++ b/lib/vagrant/errors.rb @@ -356,6 +356,10 @@ module Vagrant error_key(:darwin_mount_failed) end + class DarwinVersionFailed < VagrantError + error_key(:darwin_version_failed) + end + class DestroyRequiresForce < VagrantError error_key(:destroy_requires_force) end diff --git a/plugins/hosts/darwin/cap/version.rb b/plugins/hosts/darwin/cap/version.rb new file mode 100644 index 000000000..0b655294a --- /dev/null +++ b/plugins/hosts/darwin/cap/version.rb @@ -0,0 +1,23 @@ +module VagrantPlugins + module HostDarwin + module Cap + class Version + def self.version(env) + r = Vagrant::Util::Subprocess.execute("sw_vers", "-productVersion") + if r.exit_code != 0 + raise Vagrant::Errors::DarwinVersionFailed, + version: r.stdout, + error: r.stderr + end + begin + Gem::Version.new(r.stdout) + rescue => err + raise Vagrant::Errors::DarwinVersionFailed, + version: r.stdout, + error: err.message + end + end + end + end + end +end diff --git a/plugins/hosts/darwin/plugin.rb b/plugins/hosts/darwin/plugin.rb index f3a7e6a55..f8d57cfdf 100644 --- a/plugins/hosts/darwin/plugin.rb +++ b/plugins/hosts/darwin/plugin.rb @@ -70,6 +70,11 @@ module VagrantPlugins require_relative "cap/nfs" Cap::NFS end + + host_capability("darwin", "version") do + require_relative "cap/version" + Cap::Version + end end end end diff --git a/test/unit/plugins/hosts/darwin/cap/version_test.rb b/test/unit/plugins/hosts/darwin/cap/version_test.rb new file mode 100644 index 000000000..d961efb59 --- /dev/null +++ b/test/unit/plugins/hosts/darwin/cap/version_test.rb @@ -0,0 +1,47 @@ +require_relative "../../../../base" +require_relative "../../../../../../plugins/hosts/darwin/cap/version" + +describe VagrantPlugins::HostDarwin::Cap::Version do + describe ".version" do + let(:product_version) { "10.5.1" } + let(:env) { double(:env) } + let(:exit_code) { 0 } + let(:stderr) { "" } + let(:stdout) { product_version } + let(:result) { + Vagrant::Util::Subprocess::Result.new(exit_code, stdout, stderr) + } + + before do + allow(Vagrant::Util::Subprocess).to receive(:execute). + with("sw_vers", "-productVersion"). + and_return(result) + end + + it "should return a Gem::Version" do + expect(described_class.version(env)).to be_a(Gem::Version) + end + + it "should equal the defined version" do + expect(described_class.version(env)).to eq(Gem::Version.new(product_version)) + end + + context "when version cannot be parsed" do + let(:product_version) { "invalid" } + + it "should raise a failure error" do + expect { described_class.version(env) }. + to raise_error(Vagrant::Errors::DarwinVersionFailed) + end + end + + context "when command execution fails" do + let(:exit_code) { 1 } + + it "should raise a failure error" do + expect { described_class.version(env) }. + to raise_error(Vagrant::Errors::DarwinVersionFailed) + end + end + end +end From 5f0e5652b1e0643a4d5c00b37cd956c68eb190f6 Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Tue, 2 Nov 2021 16:44:06 -0700 Subject: [PATCH 3/3] Only resolve path with firmlink prefix on Catalina --- plugins/hosts/darwin/cap/path.rb | 4 ++++ .../plugins/hosts/darwin/cap/path_test.rb | 22 ++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/plugins/hosts/darwin/cap/path.rb b/plugins/hosts/darwin/cap/path.rb index c39d63319..babc1bb33 100644 --- a/plugins/hosts/darwin/cap/path.rb +++ b/plugins/hosts/darwin/cap/path.rb @@ -6,6 +6,7 @@ module VagrantPlugins FIRMLINK_DEFS = "/usr/share/firmlinks".freeze FIRMLINK_DATA_PATH = "/System/Volumes/Data".freeze + CATALINA_CONSTRAINT = Gem::Requirement.new("~> 10.15") # Resolve the given host path to the actual # usable system path by detecting firmlinks @@ -15,6 +16,9 @@ module VagrantPlugins # @return [String] resolved path def self.resolve_host_path(env, path) path = File.expand_path(path) + # Only expand firmlink paths on Catalina + return path if !CATALINA_CONSTRAINT.satisfied_by?(Cap::Version.version(env)) + firmlink = firmlink_map.detect do |mount_path, data_path| path.start_with?(mount_path) end diff --git a/test/unit/plugins/hosts/darwin/cap/path_test.rb b/test/unit/plugins/hosts/darwin/cap/path_test.rb index f7e799e6c..8ff62039e 100644 --- a/test/unit/plugins/hosts/darwin/cap/path_test.rb +++ b/test/unit/plugins/hosts/darwin/cap/path_test.rb @@ -1,13 +1,21 @@ require_relative "../../../../base" require_relative "../../../../../../plugins/hosts/darwin/cap/path" +require_relative "../../../../../../plugins/hosts/darwin/cap/version" describe VagrantPlugins::HostDarwin::Cap::Path do describe ".resolve_host_path" do let(:env) { double("environment") } let(:path) { "/test/vagrant/path" } let(:firmlink_map) { {} } + let(:macos_version) { Gem::Version.new("10.15.1") } - before { allow(described_class).to receive(:firmlink_map).and_return(firmlink_map) } + before do + allow(VagrantPlugins::HostDarwin::Cap::Version).to receive(:version). + with(anything). + and_return(macos_version) + allow(described_class).to receive(:firmlink_map). + and_return(firmlink_map) + end it "should not change the path when no firmlinks are defined" do expect(described_class.resolve_host_path(env, path)).to eq(path) @@ -48,6 +56,18 @@ describe VagrantPlugins::HostDarwin::Cap::Path do expect(described_class.resolve_host_path(env, path)).to include("other") end end + + context "when macos version is later than catalina" do + let(:macos_version) { Gem::Version.new("10.16.1") } + + it "should not update the path" do + expect(described_class.resolve_host_path(env, path)).to eq(path) + end + + it "should not prefix the path with the defined data path" do + expect(described_class.resolve_host_path(env, path)).not_to start_with(described_class.const_get(:FIRMLINK_DATA_PATH)) + end + end end describe ".firmlink_map" do