diff --git a/plugins/commands/validate/command.rb b/plugins/commands/validate/command.rb index fe90493bc..a68deb87a 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 + tmp_data_dir = 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) @@ -40,6 +42,62 @@ module VagrantPlugins # Success, exit status 0 0 + ensure + FileUtils.remove_entry tmp_data_dir if tmp_data_dir + 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. + # + # 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") + 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) + 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 + 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 591a3bfe6..0bcd45cbc 100644 --- a/test/unit/plugins/commands/validate/command_test.rb +++ b/test/unit/plugins/commands/validate/command_test.rb @@ -138,6 +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("") + 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.") }