Fixes #10224: Allow validation of config while ignoring provider
This commit adds a new flag to the `vagrant validate` command which allows users to completely ignore the provider block of a config file. This is useful for when you are running `vagrant validate` in CI and don't want to install a valid provider to check the syntax of your Vagratnfile. When the flag is invoked, a warning will be displayed saying that the provider block will be ignored and not validated.
This commit is contained in:
parent
716a5f1501
commit
6051f3598e
|
@ -12,7 +12,7 @@ module Vagrant
|
|||
|
||||
def call(env)
|
||||
if !env.key?(:config_validate) || env[:config_validate]
|
||||
errors = env[:machine].config.validate(env[:machine])
|
||||
errors = env[:machine].config.validate(env[:machine], env[:ignore_provider])
|
||||
|
||||
if errors && !errors.empty?
|
||||
raise Errors::ConfigInvalid,
|
||||
|
|
|
@ -60,14 +60,18 @@ module Vagrant
|
|||
#
|
||||
# @param [Environment] env
|
||||
# @return [Hash]
|
||||
def validate(machine)
|
||||
def validate(machine, ignore_provider=nil)
|
||||
# Go through each of the configuration keys and validate
|
||||
errors = {}
|
||||
@keys.each do |_key, instance|
|
||||
if instance.respond_to?(:validate)
|
||||
# Validate this single item, and if we have errors then
|
||||
# we merge them into our total errors list.
|
||||
if _key == :vm
|
||||
result = instance.validate(machine, ignore_provider)
|
||||
else
|
||||
result = instance.validate(machine)
|
||||
end
|
||||
if result && !result.empty?
|
||||
errors = Util.merge_errors(errors, result)
|
||||
end
|
||||
|
|
|
@ -8,17 +8,32 @@ module VagrantPlugins
|
|||
end
|
||||
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant validate"
|
||||
o.banner = "Usage: vagrant validate [options]"
|
||||
o.separator ""
|
||||
o.separator "Validates a Vagrantfile config"
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
|
||||
o.on("-p", "--ignore-provider", "Ignores provider config options") do |p|
|
||||
options[:ignore_provider] = p
|
||||
end
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
|
||||
action_env = {}
|
||||
if options[:ignore_provider]
|
||||
action_env[:ignore_provider] = true
|
||||
end
|
||||
# Validate the configuration of all machines
|
||||
with_target_vms() do |machine|
|
||||
machine.action_raw(:config_validate, Vagrant::Action::Builtin::ConfigValidate)
|
||||
machine.action_raw(:config_validate, Vagrant::Action::Builtin::ConfigValidate, action_env)
|
||||
end
|
||||
|
||||
@env.ui.info(I18n.t("vagrant.commands.validate.success"))
|
||||
|
|
|
@ -582,7 +582,7 @@ module VagrantPlugins
|
|||
@__synced_folders
|
||||
end
|
||||
|
||||
def validate(machine)
|
||||
def validate(machine, ignore_provider=nil)
|
||||
errors = _detected_errors
|
||||
|
||||
if !box && !clone && !machine.provider_options[:box_optional]
|
||||
|
@ -737,10 +737,14 @@ module VagrantPlugins
|
|||
|
||||
# Validate only the _active_ provider
|
||||
if machine.provider_config
|
||||
if !ignore_provider
|
||||
provider_errors = machine.provider_config.validate(machine)
|
||||
if provider_errors
|
||||
errors = Vagrant::Config::V2::Util.merge_errors(errors, provider_errors)
|
||||
end
|
||||
else
|
||||
machine.ui.warn(I18n.t("vagrant.config.vm.ignore_provider_config"))
|
||||
end
|
||||
end
|
||||
|
||||
# Validate provisioners
|
||||
|
|
|
@ -1845,6 +1845,8 @@ en:
|
|||
hostname_invalid_characters: |-
|
||||
The hostname set for the VM should only contain letters, numbers,
|
||||
hyphens or dots. It cannot start with a hyphen or dot.
|
||||
ignore_provider_config: |-
|
||||
Ignoring provider config for validation...
|
||||
name_invalid: |-
|
||||
The sub-VM name '%{name}' is invalid. Please don't use special characters.
|
||||
network_ip_ends_in_one: |-
|
||||
|
|
|
@ -5,13 +5,15 @@ describe VagrantPlugins::CommandValidate::Command do
|
|||
include_context "unit"
|
||||
include_context "command plugin helpers"
|
||||
|
||||
let(:vagrantfile_content){ "" }
|
||||
let(:iso_env) do
|
||||
isolated_environment
|
||||
env = isolated_environment
|
||||
env.vagrantfile(vagrantfile_content)
|
||||
env.create_vagrant_env
|
||||
end
|
||||
|
||||
let(:env) do
|
||||
iso_env.create_vagrant_env
|
||||
end
|
||||
let(:action_runner) { double("action_runner") }
|
||||
let(:machine) { iso_env.machine(iso_env.machine_names[0], :dummy) }
|
||||
|
||||
let(:argv) { [] }
|
||||
|
||||
|
@ -20,37 +22,49 @@ describe VagrantPlugins::CommandValidate::Command do
|
|||
I18n.reload!
|
||||
end
|
||||
|
||||
subject { described_class.new(argv, env) }
|
||||
subject { described_class.new(argv, iso_env) }
|
||||
|
||||
describe "#execute" do
|
||||
it "validates correct Vagrantfile" do
|
||||
iso_env.vagrantfile(<<-EOH)
|
||||
context "validating configs" do
|
||||
let(:vagrantfile_content) do
|
||||
<<-VF
|
||||
Vagrant.configure("2") do |config|
|
||||
config.vm.box = "hashicorp/precise64"
|
||||
end
|
||||
EOH
|
||||
|
||||
expect(env.ui).to receive(:info).with(any_args) { |message, _|
|
||||
VF
|
||||
end
|
||||
it "validates correct Vagrantfile" do
|
||||
expect(machine).to receive(:action_raw) do |name, action, env|
|
||||
expect(name).to eq(:config_validate)
|
||||
expect(action).to eq(Vagrant::Action::Builtin::ConfigValidate)
|
||||
expect(env).to eq({})
|
||||
end
|
||||
expect(iso_env.ui).to receive(:info).with(any_args) { |message, _|
|
||||
expect(message).to include("Vagrantfile validated successfully.")
|
||||
}
|
||||
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
it "validates the configuration" do
|
||||
iso_env.vagrantfile <<-EOH
|
||||
context "invalid configs" do
|
||||
let(:vagrantfile_content) do
|
||||
<<-VF
|
||||
Vagrant.configure("2") do |config|
|
||||
config.vm.bix = "hashicorp/precise64"
|
||||
end
|
||||
EOH
|
||||
|
||||
VF
|
||||
end
|
||||
it "validates the configuration" do
|
||||
expect { subject.execute }.to raise_error(Vagrant::Errors::ConfigInvalid) { |err|
|
||||
expect(err.message).to include("The following settings shouldn't exist: bix")
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
it "validates correct Vagrantfile of all vms" do
|
||||
iso_env.vagrantfile <<-EOH
|
||||
context "valid configs for multiple vms" do
|
||||
let(:vagrantfile_content) do
|
||||
<<-VF
|
||||
Vagrant.configure("2") do |config|
|
||||
config.vm.box = "hashicorp/precise64"
|
||||
|
||||
|
@ -62,17 +76,25 @@ describe VagrantPlugins::CommandValidate::Command do
|
|||
vm.vm.provider :virtualbox
|
||||
end
|
||||
end
|
||||
EOH
|
||||
|
||||
expect(env.ui).to receive(:info).with(any_args) { |message, _|
|
||||
VF
|
||||
end
|
||||
it "validates correct Vagrantfile of all vms" do
|
||||
expect(machine).to receive(:action_raw) do |name, action, env|
|
||||
expect(name).to eq(:config_validate)
|
||||
expect(action).to eq(Vagrant::Action::Builtin::ConfigValidate)
|
||||
expect(env).to eq({})
|
||||
end
|
||||
expect(iso_env.ui).to receive(:info).with(any_args) { |message, _|
|
||||
expect(message).to include("Vagrantfile validated successfully.")
|
||||
}
|
||||
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
it "validates the configuration of all vms" do
|
||||
iso_env.vagrantfile <<-EOH
|
||||
context "an invalid config for some vms" do
|
||||
let(:vagrantfile_content) do
|
||||
<<-VF
|
||||
Vagrant.configure("2") do |config|
|
||||
config.vm.box = "hashicorp/precise64"
|
||||
|
||||
|
@ -84,15 +106,59 @@ describe VagrantPlugins::CommandValidate::Command do
|
|||
vm.vm.not_provider :virtualbox
|
||||
end
|
||||
end
|
||||
EOH
|
||||
VF
|
||||
end
|
||||
it "validates the configuration of all vms" do
|
||||
expect(machine).to receive(:action_raw) do |name, action, env|
|
||||
expect(name).to eq(:config_validate)
|
||||
expect(action).to eq(Vagrant::Action::Builtin::ConfigValidate)
|
||||
expect(env).to eq({})
|
||||
end
|
||||
|
||||
expect { subject.execute }.to raise_error(Vagrant::Errors::ConfigInvalid) { |err|
|
||||
expect(err.message).to include("The following settings shouldn't exist: not_provider")
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
context "with the ignore provider flag" do
|
||||
let(:argv) { ["--ignore-provider"]}
|
||||
let(:vagrantfile_content) do
|
||||
<<-VF
|
||||
Vagrant.configure("2") do |config|
|
||||
config.vm.box = "hashicorp/precise64"
|
||||
|
||||
config.vm.define "test" do |vm|
|
||||
vm.vm.hostname = "test"
|
||||
vm.vm.provider :virtualbox do |v|
|
||||
v.not_a_real_option = true
|
||||
end
|
||||
end
|
||||
end
|
||||
VF
|
||||
end
|
||||
it "ignores provider specific configurations with the flag" do
|
||||
expect(iso_env.ui).to receive(:info).with(any_args) { |message, _|
|
||||
expect(message).to include("Vagrantfile validated successfully.")
|
||||
}
|
||||
|
||||
expect(machine).to receive(:action_raw) do |name, action, env|
|
||||
expect(name).to eq(:config_validate)
|
||||
expect(action).to eq(Vagrant::Action::Builtin::ConfigValidate)
|
||||
expect(env).to eq({:ignore_provider=>true})
|
||||
end
|
||||
|
||||
expect(subject.execute).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
context "no vagrantfile" do
|
||||
let(:vagrantfile_content){ "" }
|
||||
let(:env) { isolated_environment.create_vagrant_env }
|
||||
subject { described_class.new(argv, env) }
|
||||
it "throws an exception if there's no Vagrantfile" do
|
||||
expect { subject.execute }.to raise_error(Vagrant::Errors::NoEnvironmentError)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -368,6 +368,20 @@ describe VagrantPlugins::Kernel_V2::VMConfig do
|
|||
expect { subject.finalize! }.
|
||||
to raise_error(Vagrant::Errors::VagrantfileLoadError)
|
||||
end
|
||||
|
||||
it "ignores providers entirely if flag is provided" do
|
||||
subject.provider "virtualbox" do |vb|
|
||||
vb.nope = true
|
||||
end
|
||||
|
||||
subject.provider "virtualbox" do |vb|
|
||||
vb.not_real = "foo"
|
||||
end
|
||||
|
||||
subject.finalize!
|
||||
errors = subject.validate(machine, true)
|
||||
expect(errors).to eq({"vm"=>[]})
|
||||
end
|
||||
end
|
||||
|
||||
describe "#provision" do
|
||||
|
|
|
@ -91,6 +91,24 @@ describe Vagrant::Config::V2::Root do
|
|||
expect(instance.validate(env)).to eq(errors)
|
||||
end
|
||||
|
||||
context "with vms and ignoring provider validations" do
|
||||
let(:instance) do
|
||||
map = { vm: Object, bar: Object }
|
||||
described_class.new(map)
|
||||
end
|
||||
|
||||
it "should pass along the ignore_provider flag for ignoring validations" do
|
||||
errors = { "vm" => ["errors!"] }
|
||||
env = { "errors" => errors }
|
||||
vm = instance.vm
|
||||
def vm.validate(env, param)
|
||||
env["errors"]
|
||||
end
|
||||
|
||||
expect(instance.validate({}, true)).to eq({})
|
||||
end
|
||||
end
|
||||
|
||||
it "should merge errors via array concat if matching keys" do
|
||||
errors = { "foo" => ["errors!"] }
|
||||
env = { "errors" => errors }
|
||||
|
|
Loading…
Reference in New Issue