From 68dda8f853df3666c3d70c40fab03707497eb352 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Thu, 29 Nov 2018 13:29:46 -0800 Subject: [PATCH 1/3] Fixes #10224: Clear our registered providers when validating configs with no provider Prior to this commit, if you went to validate your Vagrantfile and wanted to ignore the provider, Vagrant would still fail as it checks if there are any registered providers that are installed and usable. This commit mocks out all registered providers to bypass that for the validate command so that Vagrant can just validate the config and ignore any provider config blocks. --- plugins/commands/validate/command.rb | 54 +++++++++++++++++++ .../plugins/commands/validate/command_test.rb | 1 + 2 files changed, 55 insertions(+) diff --git a/plugins/commands/validate/command.rb b/plugins/commands/validate/command.rb index fe90493bc..ace01d601 100644 --- a/plugins/commands/validate/command.rb +++ b/plugins/commands/validate/command.rb @@ -30,7 +30,9 @@ module VagrantPlugins action_env = {} if options[:ignore_provider] action_env[:ignore_provider] = true + mockup_providers! end + # Validate the configuration of all machines with_target_vms() do |machine| machine.action_raw(:config_validate, Vagrant::Action::Builtin::ConfigValidate, action_env) @@ -41,6 +43,58 @@ module VagrantPlugins # Success, exit status 0 0 end + + protected + + # This method is required to bypass some of the provider checks that would + # otherwise raise exceptions before Vagrant could load and validate a config. + # It essentially ignores that there are no installed or usable prodivers so + # that Vagrant can go along and validate the rest of the Vagrantfile and ignore + # any provider blocks. + def mockup_providers! + require 'log4r' + logger = Log4r::Logger.new("vagrant::validate") + logger.debug("Overriding all registered provider classes for validate") + + # Without setting up a tmp Environment, Vagrant will completely + # erase the local data dotfile and you can lose state after the + # validate command completes. + tmp_data_dir = Dir.mktmpdir("vagrant-validate-") + @env = Vagrant::Environment.new( + cwd: @env.cwd, + home_path: @env.home_path, + ui_class: @env.ui_class, + vagrantfile_name: @env.vagrantfile_name, + local_data_path: tmp_data_dir, + data_dir: tmp_data_dir + ) + + Vagrant.plugin("2").manager.providers.each do |key, data| + data[0].class_eval do + def initialize(machine) + @machine = machine + end + + def machine_id_changed + end + + def self.installed? + true + end + + def self.usable?(raise_error=false) + true + end + + def state + state_id = Vagrant::MachineState::NOT_CREATED_ID + short = :not_created + long = :not_created + Vagrant::MachineState.new(state_id, short, long) + end + end + end + end end end end diff --git a/test/unit/plugins/commands/validate/command_test.rb b/test/unit/plugins/commands/validate/command_test.rb index 591a3bfe6..98443a0d2 100644 --- a/test/unit/plugins/commands/validate/command_test.rb +++ b/test/unit/plugins/commands/validate/command_test.rb @@ -138,6 +138,7 @@ describe VagrantPlugins::CommandValidate::Command do VF end it "ignores provider specific configurations with the flag" do + allow(subject).to receive(:mockup_providers!).and_return(true) expect(iso_env.ui).to receive(:info).with(any_args) { |message, _| expect(message).to include("Vagrantfile validated successfully.") } From 69eacd2b73a0ff0b268b612d02e6c9206b30f47b Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Fri, 30 Nov 2018 11:03:05 -0800 Subject: [PATCH 2/3] Remove machine from initialize method --- plugins/commands/validate/command.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/commands/validate/command.rb b/plugins/commands/validate/command.rb index ace01d601..ab2b9740f 100644 --- a/plugins/commands/validate/command.rb +++ b/plugins/commands/validate/command.rb @@ -72,7 +72,6 @@ module VagrantPlugins Vagrant.plugin("2").manager.providers.each do |key, data| data[0].class_eval do def initialize(machine) - @machine = machine end def machine_id_changed From 5fa3c5866ca794af821ef84f95c86810af39e2a7 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 3 Dec 2018 14:45:26 -0800 Subject: [PATCH 3/3] Ensure tmp dir for validate is removed once command exits --- plugins/commands/validate/command.rb | 7 ++++++- test/unit/plugins/commands/validate/command_test.rb | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/plugins/commands/validate/command.rb b/plugins/commands/validate/command.rb index ab2b9740f..a68deb87a 100644 --- a/plugins/commands/validate/command.rb +++ b/plugins/commands/validate/command.rb @@ -30,7 +30,7 @@ module VagrantPlugins action_env = {} if options[:ignore_provider] action_env[:ignore_provider] = true - mockup_providers! + tmp_data_dir = mockup_providers! end # Validate the configuration of all machines @@ -42,6 +42,8 @@ module VagrantPlugins # Success, exit status 0 0 + ensure + FileUtils.remove_entry tmp_data_dir if tmp_data_dir end protected @@ -51,6 +53,8 @@ module VagrantPlugins # It essentially ignores that there are no installed or usable prodivers so # that Vagrant can go along and validate the rest of the Vagrantfile and ignore # any provider blocks. + # + # return [String] tmp_data_dir - Temporary dir used to store guest metadata during validation def mockup_providers! require 'log4r' logger = Log4r::Logger.new("vagrant::validate") @@ -93,6 +97,7 @@ module VagrantPlugins end end end + tmp_data_dir end end end diff --git a/test/unit/plugins/commands/validate/command_test.rb b/test/unit/plugins/commands/validate/command_test.rb index 98443a0d2..0bcd45cbc 100644 --- a/test/unit/plugins/commands/validate/command_test.rb +++ b/test/unit/plugins/commands/validate/command_test.rb @@ -138,7 +138,8 @@ describe VagrantPlugins::CommandValidate::Command do VF end it "ignores provider specific configurations with the flag" do - allow(subject).to receive(:mockup_providers!).and_return(true) + allow(subject).to receive(:mockup_providers!).and_return("") + allow(FileUtils).to receive(:remove_entry).and_return(true) expect(iso_env.ui).to receive(:info).with(any_args) { |message, _| expect(message).to include("Vagrantfile validated successfully.") }