From c39b3fbb76ddd1e751976de4cf2e514c89a5ef19 Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Tue, 25 Oct 2016 12:16:52 -0700 Subject: [PATCH] guests/openbsd: Check package installation after installing package The `pkg_add` command will return `0` when a package requested for installation is not found. This adds a validation check to ensure the rsync package is actually installed on the guest. --- lib/vagrant/errors.rb | 4 ++ plugins/guests/openbsd/cap/rsync.rb | 17 +++++- templates/locales/en.yml | 9 +++ .../plugins/guests/openbsd/cap/rsync_test.rb | 59 +++++++++++++++++++ 4 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 test/unit/plugins/guests/openbsd/cap/rsync_test.rb diff --git a/lib/vagrant/errors.rb b/lib/vagrant/errors.rb index a557f88d8..fd289eef6 100644 --- a/lib/vagrant/errors.rb +++ b/lib/vagrant/errors.rb @@ -608,6 +608,10 @@ module Vagrant error_key(:rsync_not_installed_in_guest) end + class RSyncGuestInstallError < VagrantError + error_key(:rsync_guest_install_error) + end + class SCPPermissionDenied < VagrantError error_key(:scp_permission_denied) end diff --git a/plugins/guests/openbsd/cap/rsync.rb b/plugins/guests/openbsd/cap/rsync.rb index 54663ef6a..ac1e17a1a 100644 --- a/plugins/guests/openbsd/cap/rsync.rb +++ b/plugins/guests/openbsd/cap/rsync.rb @@ -7,10 +7,21 @@ module VagrantPlugins extend VagrantPlugins::SyncedFolderRSync::DefaultUnixCap def self.rsync_install(machine) - machine.communicate.sudo( - 'PKG_PATH="http://ftp.openbsd.org/pub/OpenBSD/' \ + install_output = {:stderr => '', :stdout => ''} + command = 'PKG_PATH="http://ftp.openbsd.org/pub/OpenBSD/' \ '`uname -r`/packages/`arch -s`/" ' \ - 'pkg_add -I rsync--') + 'pkg_add -I rsync--' + machine.communicate.sudo(command) do |type, data| + install_output[type] << data if install_output.key?(type) + end + # pkg_add returns 0 even if package was not found, so + # validate package is actually installed + machine.communicate.sudo('pkg_info -cA | grep inst:rsync-[[:digit:]]', + error_class: Vagrant::Errors::RSyncNotInstalledInGuest, + command: command, + stderr: install_output[:stderr], + stdout: install_output[:stdout] + ) end end end diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 75db2d500..cfb067cc5 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -1065,6 +1065,15 @@ en: Guest path: %{guestpath} Command: %{command} Error: %{stderr} + rsync_guest_install_error: |- + Installation of rsync into the guest has failed! The stdout + and stderr are shown below. Please read the error output, resolve + it and try again. If the problem persists, please install rsync + manually within the guest. + + Command: %{command} + Stdout: %{stdout} + Stderr: %{stderr} rsync_not_found: |- "rsync" could not be found on your PATH. Make sure that rsync is properly installed on your system and available on the PATH. diff --git a/test/unit/plugins/guests/openbsd/cap/rsync_test.rb b/test/unit/plugins/guests/openbsd/cap/rsync_test.rb new file mode 100644 index 000000000..68874b18f --- /dev/null +++ b/test/unit/plugins/guests/openbsd/cap/rsync_test.rb @@ -0,0 +1,59 @@ +require_relative "../../../../base" + +describe "VagrantPlugins::GuestOpenBSD::Cap::RSync" do + let(:caps) do + VagrantPlugins::GuestOpenBSD::Plugin + .components + .guest_capabilities[:openbsd] + 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 ".rsync_install" do + let(:cap) { caps.get(:rsync_install) } + + describe "successful installation" do + it "installs rsync" do + cap.rsync_install(machine) + expect(comm.received_commands[0]).to match(/pkg_add -I rsync/) + expect(comm.received_commands[1]).to match(/pkg_info/) + end + end + + describe "failure installation" do + before do + expect(comm).to receive(:execute).and_raise(Vagrant::Errors::RSyncNotInstalledInGuest, {command: '', output: ''}) + end + + it "raises custom exception" do + expect{ cap.rsync_install(machine) }.to raise_error(Vagrant::Errors::RSyncNotInstalledInGuest) + end + end + end + + describe ".rsync_installed" do + let(:cap) { caps.get(:rsync_installed) } + + it "checks if rsync is installed" do + comm.expect_command("which rsync") + cap.rsync_installed(machine) + end + end + + describe ".rsync_command" do + let(:cap) { caps.get(:rsync_command) } + + it "defaults to 'sudo rsync'" do + expect(cap.rsync_command(machine)).to eq("sudo rsync") + end + end +end