Add darwin version cap

This commit is contained in:
sophia 2020-11-17 17:45:39 -06:00
parent 8eea6a2301
commit fffe6ea4a5
7 changed files with 126 additions and 78 deletions

View File

@ -0,0 +1,40 @@
module VagrantPlugins
module GuestDarwin
module Cap
class DarwinVersion
VERSION_REGEX = /\d+.\d+.?\d*/.freeze
# Get the darwin version
#
# @param [Machine]
# @return [String] version of drawin
def self.darwin_version(machine)
output = ""
machine.communicate.sudo("sysctl kern.osrelease") do |_, data|
output = data
end
output.scan(VERSION_REGEX).first
end
# Get the darwin major version
#
# @param [Machine]
# @return [int] major version of drawin (nil if version is not detected)
def self.darwin_major_version(machine)
output = ""
machine.communicate.sudo("sysctl kern.osrelease") do |_, data|
output = data
end
version_string = output.scan(VERSION_REGEX).first
if version_string
major_version = version_string.split(".").first.to_i
else
major_version = nil
end
major_version
end
end
end
end
end

View File

@ -1,24 +0,0 @@
module VagrantPlugins
module GuestDarwin
module Cap
class Flavor
def self.flavor(machine)
# Read the version file
output = ""
machine.communicate.sudo("sw_vers -productVersion", error_check: false) do |_, data|
output = data
end
# Detect various flavors we care about
if output =~ /10.15.\d+/
return :catalina
elsif output =~ /11.0.?\d*/
return :big_sur
else
return :darwin
end
end
end
end
end
end

View File

@ -4,6 +4,9 @@ module VagrantPlugins
module GuestDarwin
module Cap
class MountVmwareSharedFolder
MACOS_BIGSUR_DARWIN_VERSION = 20.freeze
# Entry point for hook to called delayed actions
# which finalizing the synced folders setup on
# the guest
@ -82,14 +85,15 @@ module VagrantPlugins
# Write out the synthetic file
comm.sudo("echo -e #{content.inspect} > /etc/synthetic.conf")
if @apply_firmlinks[machine.id][:bootstrap]
case machine.guest.capability("flavor")
when :big_sur
apfs_bootstrap_flag = "-t"
else
if machine.guest.capability("darwin_major_version").to_i < MACOS_BIGSUR_DARWIN_VERSION
apfs_bootstrap_flag = "-B"
expected_rc = 0
else
apfs_bootstrap_flag = "-t"
expected_rc = 253
end
# Re-bootstrap the root container to pick up firmlink updates
comm.sudo("/System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util #{apfs_bootstrap_flag}", good_exit: [0, 253])
comm.sudo("/System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util #{apfs_bootstrap_flag}", good_exit: [expected_rc])
end
end
end

View File

@ -31,9 +31,14 @@ module VagrantPlugins
Cap::ConfigureNetworks
end
guest_capability(:darwin, :flavor) do
require_relative "cap/flavor"
Cap::Flavor
guest_capability(:darwin, :darwin_version) do
require_relative "cap/darwin_version"
Cap::DarwinVersion
end
guest_capability(:darwin, :darwin_major_version) do
require_relative "cap/darwin_version"
Cap::DarwinVersion
end
guest_capability(:darwin, :halt) do

View File

@ -0,0 +1,49 @@
require_relative "../../../../base"
describe "VagrantPlugins::GuestDarwin::Cap::DarwinVersion" do
let(:caps) do
VagrantPlugins::GuestDarwin::Plugin
.components
.guest_capabilities[:darwin]
end
let(:machine) { double("machine") }
let(:comm) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
before do
allow(machine).to receive(:communicate).and_return(comm)
end
after do
comm.verify_expectations!
end
describe ".darwin_version" do
let(:cap) { caps.get(:darwin_version) }
{
"kern.osrelease: 19.6.0" => "19.6.0",
"kern.osrelease: 20.1.10" => "20.1.10",
}.each do |str, expected|
it "returns #{expected} for #{str}" do
comm.stub_command("sysctl kern.osrelease", stdout: str)
expect(cap.darwin_version(machine)).to eq(expected)
end
end
end
describe ".darwin_major_version" do
let(:cap) { caps.get(:darwin_major_version) }
{
"kern.osrelease: 19.6.0" => 19,
"kern.osrelease: 20.1.10" => 20,
"" => nil
}.each do |str, expected|
it "returns #{expected} for #{str}" do
comm.stub_command("sysctl kern.osrelease", stdout: str)
expect(cap.darwin_major_version(machine)).to eq(expected)
end
end
end
end

View File

@ -1,43 +0,0 @@
require_relative "../../../../base"
describe "VagrantPlugins::GuestDarwin::Cap::Flavor" do
let(:caps) do
VagrantPlugins::GuestDarwin::Plugin
.components
.guest_capabilities[:darwin]
end
let(:machine) { double("machine") }
let(:comm) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
before do
allow(machine).to receive(:communicate).and_return(comm)
end
after do
comm.verify_expectations!
end
describe ".flavor" do
let(:cap) { caps.get(:flavor) }
{
"11.0.1" => :big_sur,
"11.0.11" => :big_sur,
"11.0" => :big_sur,
"10.15.123" => :catalina,
"" => :darwin,
"10.14.1" => :darwin,
}.each do |str, expected|
it "returns #{expected} for #{str}" do
comm.stub_command("sw_vers -productVersion", stdout: str)
expect(cap.flavor(machine)).to be(expected)
end
end
it "contines if sw_vers is not available" do
comm.stub_command("sw_vers -productVersion", stdout: "something!")
expect(cap.flavor(machine)).to be(:darwin)
end
end
end

View File

@ -8,7 +8,8 @@ describe "VagrantPlugins::GuestDarwin::Cap::MountVmwareSharedFolder" do
.get(:mount_vmware_shared_folder)
end
let(:machine) { double("machine", communicate: communicator, id: "MACHINE_ID") }
let(:machine) { double("machine", communicate: communicator, id: "MACHINE_ID", guest: guest) }
let(:guest) {double("guest")}
let(:communicator) { double("communicator") }
before do
@ -27,8 +28,9 @@ describe "VagrantPlugins::GuestDarwin::Cap::MountVmwareSharedFolder" do
described_class.reset!
end
after { described_class.
mount_vmware_shared_folder(machine, name, guestpath, options) }
after {
described_class.mount_vmware_shared_folder(machine, name, guestpath, options)
}
context "with APFS root container" do
before do
@ -73,6 +75,21 @@ describe "VagrantPlugins::GuestDarwin::Cap::MountVmwareSharedFolder" do
expect(communicator).to receive(:sudo).with(%r{ln -s .+/System/Volumes/Data.+})
end
{
19 => "-B",
20 => "-t",
21 => "-t",
nil => "-B"
}.each do |version, expected_flag|
it "should re-bootstrap root dir for darwin version #{version}" do
expect(communicator).to receive(:sudo).with(/apfs.util #{expected_flag}/, any_args)
expect(guest).to receive(:capability).with("darwin_major_version").and_return(version)
described_class.mount_vmware_shared_folder(machine, name, guestpath, options)
described_class.apfs_firmlinks_delayed[machine.id].call
end
end
context "when firmlink is provided by the system" do
before { expect(described_class).to receive(:system_firmlink?).and_return(true) }