From b1d1c20ff78764a8a2b7674c83988270b7e261b0 Mon Sep 17 00:00:00 2001 From: sophia Date: Tue, 7 Jul 2020 14:43:35 -0500 Subject: [PATCH] Refactor building iso --- lib/vagrant/util/caps.rb | 30 +++++++++--- plugins/hosts/darwin/cap/fs_iso.rb | 34 ++++---------- plugins/hosts/linux/cap/fs_iso.rb | 29 ++++-------- .../plugins/hosts/darwin/cap/fs_iso_test.rb | 5 -- .../plugins/hosts/linux/cap/fs_iso_test.rb | 5 -- test/unit/vagrant/util/caps_test.rb | 47 +++++++++++++++++++ 6 files changed, 89 insertions(+), 61 deletions(-) create mode 100644 test/unit/vagrant/util/caps_test.rb diff --git a/lib/vagrant/util/caps.rb b/lib/vagrant/util/caps.rb index aed82aeb1..b7c02d79c 100644 --- a/lib/vagrant/util/caps.rb +++ b/lib/vagrant/util/caps.rb @@ -1,3 +1,6 @@ +require "tempfile" +require "fileutils" +require "pathname" require "vagrant/util/directory" require "vagrant/util/subprocess" @@ -6,17 +9,35 @@ module Vagrant module Caps module BuildISO - BUILD_ISO_CMD = "".freeze - # Check that the host has the ability to generate ISOs # # @param [Vagrant::Environment] env # @return [Boolean] def isofs_available(env) + if !self.const_defined?(:BUILD_ISO_CMD) + raise NotImplementedError + end !!Vagrant::Util::Which.which(self::BUILD_ISO_CMD) end - def ensure_file_destination(file_destination) + # Builds an iso given a compatible iso_command + # + # @param [List] command to build iso + # @param [Pathname] input directory for iso build + # @param [Pathname] output file for iso build + def build_iso(iso_command, source_directory, file_destination) + FileUtils.mkdir_p(file_destination.dirname) + if !file_destination.exist? || Vagrant::Util::Directory.directory_changed?(source_directory, file_destination.mtime) + result = Vagrant::Util::Subprocess.execute(*iso_command) + if result.exit_code != 0 + raise Vagrant::Errors::ISOBuildFailed, cmd: iso_command.join(" "), stdout: result.stdout, stderr: result.stderr + end + end + end + + protected + + def ensure_output_iso(file_destination) if file_destination.nil? tmpfile = Tempfile.new(["vagrant", ".iso"]) file_destination = Pathname.new(tmpfile.path) @@ -29,11 +50,8 @@ module Vagrant file_destination = file_destination.join("#{SecureRandom.hex(3)}_vagrant.iso") end end - # Ensure destination directory is available - FileUtils.mkdir_p(file_destination.dirname) file_destination end - end end end diff --git a/plugins/hosts/darwin/cap/fs_iso.rb b/plugins/hosts/darwin/cap/fs_iso.rb index f3cb58b00..742074239 100644 --- a/plugins/hosts/darwin/cap/fs_iso.rb +++ b/plugins/hosts/darwin/cap/fs_iso.rb @@ -1,8 +1,4 @@ -require "tempfile" -require 'fileutils' -require 'pathname' -require "vagrant/util/subprocess" -require "vagrant/util/directory" +require "pathname" require "vagrant/util/caps" module VagrantPlugins @@ -27,25 +23,15 @@ module VagrantPlugins # for recent modifications and a new ISO will be generated if requried. def self.create_iso(env, source_directory, **extra_opts) source_directory = Pathname.new(source_directory) - file_destination = self.ensure_file_destination(extra_opts[:file_destination]) - - # If the destrination does not exist or there have been changes in the source directory since the last build, then build - if !file_destination.exist? || Vagrant::Util::Directory.directory_changed?(source_directory, file_destination.mtime) - @@logger.info("Building ISO from source #{source_directory}") - iso_command = [BUILD_ISO_CMD, "makehybrid"] - iso_command << "-hfs" - iso_command << "-iso" - iso_command << "-joliet" - iso_command << "-ov" - iso_command.concat(["-default-volume-name", extra_opts[:volume_id]]) if extra_opts[:volume_id] - iso_command << "-o" - iso_command << file_destination.to_s - iso_command << source_directory.to_s - result = Vagrant::Util::Subprocess.execute(*iso_command) - if result.exit_code != 0 - raise Vagrant::Errors::ISOBuildFailed, cmd: iso_command.join(" "), stdout: result.stdout, stderr: result.stderr - end - end + file_destination = self.ensure_output_iso(extra_opts[:file_destination]) + + iso_command = [BUILD_ISO_CMD, "makehybrid", "-hfs", "-iso", "-joliet", "-ov"] + iso_command.concat(["-default-volume-name", extra_opts[:volume_id]]) if extra_opts[:volume_id] + iso_command << "-o" + iso_command << file_destination.to_s + iso_command << source_directory.to_s + self.build_iso(iso_command, source_directory, file_destination) + @@logger.info("ISO available at #{file_destination}") file_destination end diff --git a/plugins/hosts/linux/cap/fs_iso.rb b/plugins/hosts/linux/cap/fs_iso.rb index fc18cef1f..c4973c1dc 100644 --- a/plugins/hosts/linux/cap/fs_iso.rb +++ b/plugins/hosts/linux/cap/fs_iso.rb @@ -1,8 +1,4 @@ -require "tempfile" -require 'fileutils' -require 'pathname' -require "vagrant/util/subprocess" -require "vagrant/util/directory" +require "pathname" require "vagrant/util/caps" module VagrantPlugins @@ -27,23 +23,14 @@ module VagrantPlugins # for recent modifications and a new ISO will be generated if requried. def self.create_iso(env, source_directory, **extra_opts) source_directory = Pathname.new(source_directory) - file_destination = self.ensure_file_destination(extra_opts[:file_destination]) + file_destination = self.ensure_output_iso(extra_opts[:file_destination]) - # If the destrination does not exist or there have been changes in the source directory since the last build, then build - if !file_destination.exist? || Vagrant::Util::Directory.directory_changed?(source_directory, file_destination.mtime) - @@logger.info("Building ISO from source #{source_directory}") - iso_command = [BUILD_ISO_CMD] - iso_command << "-joliet" - iso_command.concat(["-volid", extra_opts[:volume_id]]) if extra_opts[:volume_id] - iso_command << "-o" - iso_command << file_destination.to_s - iso_command << source_directory.to_s - result = Vagrant::Util::Subprocess.execute(*iso_command) - - if result.exit_code != 0 - raise Vagrant::Errors::ISOBuildFailed, cmd: iso_command.join(" "), stdout: result.stdout, stderr: result.stderr - end - end + iso_command = [BUILD_ISO_CMD, "-joliet"] + iso_command.concat(["-volid", extra_opts[:volume_id]]) if extra_opts[:volume_id] + iso_command << "-o" + iso_command << file_destination.to_s + iso_command << source_directory.to_s + self.build_iso(iso_command, source_directory, file_destination) @@logger.info("ISO available at #{file_destination}") file_destination diff --git a/test/unit/plugins/hosts/darwin/cap/fs_iso_test.rb b/test/unit/plugins/hosts/darwin/cap/fs_iso_test.rb index d44a7747c..f16bc1758 100644 --- a/test/unit/plugins/hosts/darwin/cap/fs_iso_test.rb +++ b/test/unit/plugins/hosts/darwin/cap/fs_iso_test.rb @@ -13,11 +13,6 @@ describe VagrantPlugins::HostDarwin::Cap::FsISO do expect(Vagrant::Util::Which).to receive(:which).and_return(true) expect(subject.isofs_available(env)).to eq(true) end - - it "does not find iso building utility when not available" do - expect(Vagrant::Util::Which).to receive(:which).and_return(false) - expect(subject.isofs_available(env)).to eq(false) - end end describe ".create_iso" do diff --git a/test/unit/plugins/hosts/linux/cap/fs_iso_test.rb b/test/unit/plugins/hosts/linux/cap/fs_iso_test.rb index d44c19b8c..89014ad23 100644 --- a/test/unit/plugins/hosts/linux/cap/fs_iso_test.rb +++ b/test/unit/plugins/hosts/linux/cap/fs_iso_test.rb @@ -13,11 +13,6 @@ describe VagrantPlugins::HostLinux::Cap::FsISO do expect(Vagrant::Util::Which).to receive(:which).and_return(true) expect(subject.isofs_available(env)).to eq(true) end - - it "does not find iso building utility when not available" do - expect(Vagrant::Util::Which).to receive(:which).and_return(false) - expect(subject.isofs_available(env)).to eq(false) - end end describe ".create_iso" do diff --git a/test/unit/vagrant/util/caps_test.rb b/test/unit/vagrant/util/caps_test.rb new file mode 100644 index 000000000..bccc5e9fc --- /dev/null +++ b/test/unit/vagrant/util/caps_test.rb @@ -0,0 +1,47 @@ +require File.expand_path("../../../base", __FILE__) + +require "vagrant/util/caps" + +describe Vagrant::Util::Caps do + describe "BuildISO" do + + class TestSubject + extend Vagrant::Util::Caps::BuildISO + BUILD_ISO_CMD = "test".freeze + end + + let(:subject) { TestSubject } + let(:env) { double("env") } + + describe ".isofs_available" do + it "finds iso building utility when available" do + expect(Vagrant::Util::Which).to receive(:which).and_return(true) + expect(subject.isofs_available(env)).to eq(true) + end + + it "does not find iso building utility when not available" do + expect(Vagrant::Util::Which).to receive(:which).and_return(false) + expect(subject.isofs_available(env)).to eq(false) + end + end + + describe ".build_iso" do + let(:file_destination) { Pathname.new("/woo/out.iso") } + + before do + allow(file_destination).to receive(:exists?).and_return(false) + allow(FileUtils).to receive(:mkdir_p) + end + + it "should run command" do + expect(Vagrant::Util::Subprocess).to receive(:execute).with("test", "cmd").and_return(double(exit_code: 0)) + subject.build_iso(["test", "cmd"], "/src/dir", file_destination) + end + + it "raise an error if command fails" do + expect(Vagrant::Util::Subprocess).to receive(:execute).with("test", "cmd").and_return(double(exit_code: 1, stdout: "oh no", stderr: "oh no")) + expect{ subject.build_iso(["test", "cmd"], "/src/dir", file_destination) }.to raise_error(Vagrant::Errors::ISOBuildFailed) + end + end + end +end \ No newline at end of file