provisioners/ansible: Validate compatibility_mode
- Use `'auto'` instead of `nil` for the auto-detection mode - Add strict validation and related error message
This commit is contained in:
parent
e2621a42fc
commit
a327e34861
|
@ -46,7 +46,7 @@ module VagrantPlugins
|
||||||
def initialize
|
def initialize
|
||||||
@become = UNSET_VALUE
|
@become = UNSET_VALUE
|
||||||
@become_user = UNSET_VALUE
|
@become_user = UNSET_VALUE
|
||||||
@compatibility_mode = UNSET_VALUE
|
@compatibility_mode = Ansible::COMPATIBILITY_MODE_AUTO
|
||||||
@config_file = UNSET_VALUE
|
@config_file = UNSET_VALUE
|
||||||
@extra_vars = UNSET_VALUE
|
@extra_vars = UNSET_VALUE
|
||||||
@galaxy_role_file = UNSET_VALUE
|
@galaxy_role_file = UNSET_VALUE
|
||||||
|
@ -95,6 +95,12 @@ module VagrantPlugins
|
||||||
def validate(machine)
|
def validate(machine)
|
||||||
@errors = _detected_errors
|
@errors = _detected_errors
|
||||||
|
|
||||||
|
# Validate that a compatibility mode was provided
|
||||||
|
if !compatibility_mode
|
||||||
|
@errors << I18n.t("vagrant.provisioners.ansible.errors.no_compatibility_mode",
|
||||||
|
valid_modes: Ansible::COMPATIBILITY_MODES.map { |s| "'#{s}'" }.join(', '))
|
||||||
|
end
|
||||||
|
|
||||||
# Validate that a playbook path was provided
|
# Validate that a playbook path was provided
|
||||||
if !playbook
|
if !playbook
|
||||||
@errors << I18n.t("vagrant.provisioners.ansible.errors.no_playbook")
|
@errors << I18n.t("vagrant.provisioners.ansible.errors.no_playbook")
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module Ansible
|
module Ansible
|
||||||
|
COMPATIBILITY_MODE_AUTO = "auto".freeze
|
||||||
COMPATIBILITY_MODE_V1_8 = "1.8".freeze
|
COMPATIBILITY_MODE_V1_8 = "1.8".freeze
|
||||||
COMPATIBILITY_MODE_V2_0 = "2.0".freeze
|
COMPATIBILITY_MODE_V2_0 = "2.0".freeze
|
||||||
DEFAULT_COMPATIBILITY_MODE = COMPATIBILITY_MODE_V1_8
|
SAFE_COMPATIBILITY_MODE = COMPATIBILITY_MODE_V1_8
|
||||||
COMPATIBILITY_MODES = [COMPATIBILITY_MODE_V1_8, COMPATIBILITY_MODE_V2_0].freeze
|
COMPATIBILITY_MODES = [
|
||||||
|
COMPATIBILITY_MODE_AUTO,
|
||||||
|
COMPATIBILITY_MODE_V1_8,
|
||||||
|
COMPATIBILITY_MODE_V2_0,
|
||||||
|
].freeze
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -48,11 +48,11 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_compatibility_mode
|
def set_compatibility_mode
|
||||||
unless config.compatibility_mode
|
if config.compatibility_mode == Ansible::COMPATIBILITY_MODE_AUTO
|
||||||
detect_compatibility_mode(gather_ansible_version)
|
detect_compatibility_mode(gather_ansible_version)
|
||||||
end
|
end
|
||||||
|
|
||||||
unless Ansible::COMPATIBILITY_MODES.include?(config.compatibility_mode)
|
unless Ansible::COMPATIBILITY_MODES.slice(1..-1).include?(config.compatibility_mode)
|
||||||
raise "Programming Error: compatibility_mode must correctly set at this stage!"
|
raise "Programming Error: compatibility_mode must correctly set at this stage!"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
def detect_compatibility_mode(ansible_version_stdoutput)
|
def detect_compatibility_mode(ansible_version_stdoutput)
|
||||||
if config.compatibility_mode
|
if config.compatibility_mode != Ansible::COMPATIBILITY_MODE_AUTO
|
||||||
raise "Programming Error: detect_compatibility_mode() shouldn't have been called."
|
raise "Programming Error: detect_compatibility_mode() shouldn't have been called."
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -86,8 +86,8 @@ module VagrantPlugins
|
||||||
# Nothing to do here, the fallback to default compatibility_mode is done below
|
# Nothing to do here, the fallback to default compatibility_mode is done below
|
||||||
end
|
end
|
||||||
|
|
||||||
unless config.compatibility_mode
|
if config.compatibility_mode == Ansible::COMPATIBILITY_MODE_AUTO
|
||||||
config.compatibility_mode = Ansible::DEFAULT_COMPATIBILITY_MODE
|
config.compatibility_mode = Ansible::SAFE_COMPATIBILITY_MODE
|
||||||
|
|
||||||
@machine.env.ui.warn(I18n.t("vagrant.provisioners.ansible.compatibility_mode_not_detected",
|
@machine.env.ui.warn(I18n.t("vagrant.provisioners.ansible.compatibility_mode_not_detected",
|
||||||
compatibility_mode: config.compatibility_mode,
|
compatibility_mode: config.compatibility_mode,
|
||||||
|
|
|
@ -2374,6 +2374,8 @@ en:
|
||||||
`%{config_option}` does not exist on the %{system}: %{path}
|
`%{config_option}` does not exist on the %{system}: %{path}
|
||||||
extra_vars_invalid: |-
|
extra_vars_invalid: |-
|
||||||
`extra_vars` must be a hash or a path to an existing file. Received: %{value} (as %{type})
|
`extra_vars` must be a hash or a path to an existing file. Received: %{value} (as %{type})
|
||||||
|
no_compatibility_mode: |-
|
||||||
|
`compatibility_mode` must be correctly set (possible values: %{valid_modes}).
|
||||||
no_playbook: |-
|
no_playbook: |-
|
||||||
`playbook` file path must be set.
|
`playbook` file path must be set.
|
||||||
raw_arguments_invalid: |-
|
raw_arguments_invalid: |-
|
||||||
|
|
|
@ -5,7 +5,7 @@ shared_examples_for 'options shared by both Ansible provisioners' do
|
||||||
|
|
||||||
expect(subject.become).to be(false)
|
expect(subject.become).to be(false)
|
||||||
expect(subject.become_user).to be_nil
|
expect(subject.become_user).to be_nil
|
||||||
expect(subject.compatibility_mode).to be_nil
|
expect(subject.compatibility_mode).to eql(VagrantPlugins::Ansible::COMPATIBILITY_MODE_AUTO)
|
||||||
expect(subject.config_file).to be_nil
|
expect(subject.config_file).to be_nil
|
||||||
expect(subject.extra_vars).to be_nil
|
expect(subject.extra_vars).to be_nil
|
||||||
expect(subject.galaxy_command).to eql("ansible-galaxy install --role-file=%{role_file} --roles-path=%{roles_path} --force")
|
expect(subject.galaxy_command).to eql("ansible-galaxy install --role-file=%{role_file} --roles-path=%{roles_path} --force")
|
||||||
|
@ -46,23 +46,37 @@ shared_examples_for 'an Ansible provisioner' do | path_prefix, ansible_setup |
|
||||||
|
|
||||||
describe "compatibility_mode option" do
|
describe "compatibility_mode option" do
|
||||||
|
|
||||||
%w(1.8 2.0).each do |minimal_version|
|
VagrantPlugins::Ansible::COMPATIBILITY_MODES.each do |valid_mode|
|
||||||
it "supports compatibility mode '#{minimal_version}'" do
|
it "supports compatibility mode '#{valid_mode}'" do
|
||||||
subject.compatibility_mode = minimal_version
|
subject.compatibility_mode = valid_mode
|
||||||
subject.finalize!
|
subject.finalize!
|
||||||
|
|
||||||
result = subject.validate(machine)
|
result = subject.validate(machine)
|
||||||
expect(subject.compatibility_mode).to eql(minimal_version)
|
expect(subject.compatibility_mode).to eql(valid_mode)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "returns an error if the compatibility mode is not set" do
|
||||||
|
subject.compatibility_mode = nil
|
||||||
|
subject.finalize!
|
||||||
|
|
||||||
|
result = subject.validate(machine)
|
||||||
|
expect(result[provisioner_label]).to eql([
|
||||||
|
I18n.t("vagrant.provisioners.ansible.errors.no_compatibility_mode",
|
||||||
|
valid_modes: "'auto', '1.8', '2.0'")
|
||||||
|
])
|
||||||
|
end
|
||||||
|
|
||||||
%w(invalid 1.9 2.3).each do |invalid_mode|
|
%w(invalid 1.9 2.3).each do |invalid_mode|
|
||||||
it "silently forces the compatibility mode detection for invalid mode '#{invalid_mode}'" do
|
it "returns an error if the compatibility mode is invalid (e.g. '#{invalid_mode}')" do
|
||||||
subject.compatibility_mode = invalid_mode
|
subject.compatibility_mode = invalid_mode
|
||||||
subject.finalize!
|
subject.finalize!
|
||||||
|
|
||||||
result = subject.validate(machine)
|
result = subject.validate(machine)
|
||||||
expect(subject.compatibility_mode).to be_nil
|
expect(result[provisioner_label]).to eql([
|
||||||
|
I18n.t("vagrant.provisioners.ansible.errors.no_compatibility_mode",
|
||||||
|
valid_modes: "'auto', '1.8', '2.0'")
|
||||||
|
])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -109,6 +123,7 @@ shared_examples_for 'an Ansible provisioner' do | path_prefix, ansible_setup |
|
||||||
end
|
end
|
||||||
|
|
||||||
it "it collects and returns all detected errors" do
|
it "it collects and returns all detected errors" do
|
||||||
|
subject.compatibility_mode = nil
|
||||||
subject.playbook = nil
|
subject.playbook = nil
|
||||||
subject.extra_vars = ["var1", 3, "var2", 5]
|
subject.extra_vars = ["var1", 3, "var2", 5]
|
||||||
subject.raw_arguments = { arg1: 1, arg2: "foo" }
|
subject.raw_arguments = { arg1: 1, arg2: "foo" }
|
||||||
|
@ -116,7 +131,10 @@ shared_examples_for 'an Ansible provisioner' do | path_prefix, ansible_setup |
|
||||||
|
|
||||||
result = subject.validate(machine)
|
result = subject.validate(machine)
|
||||||
|
|
||||||
expect(result[provisioner_label].size).to eql(3)
|
expect(result[provisioner_label].size).to eql(4)
|
||||||
|
expect(result[provisioner_label]).to include(
|
||||||
|
I18n.t("vagrant.provisioners.ansible.errors.no_compatibility_mode",
|
||||||
|
valid_modes: "'auto', '1.8', '2.0'"))
|
||||||
expect(result[provisioner_label]).to include(
|
expect(result[provisioner_label]).to include(
|
||||||
I18n.t("vagrant.provisioners.ansible.errors.no_playbook"))
|
I18n.t("vagrant.provisioners.ansible.errors.no_playbook"))
|
||||||
expect(result[provisioner_label]).to include(
|
expect(result[provisioner_label]).to include(
|
||||||
|
|
|
@ -305,9 +305,9 @@ VF
|
||||||
"ask_become_pass" => "--ask-sudo-pass"})
|
"ask_become_pass" => "--ask-sudo-pass"})
|
||||||
end
|
end
|
||||||
|
|
||||||
context "with no compatibility_mode defined" do
|
context "with compatibility_mode 'auto'" do
|
||||||
before do
|
before do
|
||||||
config.compatibility_mode = nil
|
config.compatibility_mode = VagrantPlugins::Ansible::COMPATIBILITY_MODE_AUTO
|
||||||
end
|
end
|
||||||
|
|
||||||
valid_versions = {
|
valid_versions = {
|
||||||
|
@ -348,16 +348,16 @@ VF
|
||||||
allow(subject).to receive(:gather_ansible_version).and_return(unknown_ansible_version)
|
allow(subject).to receive(:gather_ansible_version).and_return(unknown_ansible_version)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "applies the default compatibility mode ('#{VagrantPlugins::Ansible::DEFAULT_COMPATIBILITY_MODE}')" do
|
it "applies the safest compatibility mode ('#{VagrantPlugins::Ansible::SAFE_COMPATIBILITY_MODE}')" do
|
||||||
expect(Vagrant::Util::Subprocess).to receive(:execute).with('ansible-playbook', any_args) { |*args|
|
expect(Vagrant::Util::Subprocess).to receive(:execute).with('ansible-playbook', any_args) { |*args|
|
||||||
expect(config.compatibility_mode).to eq(VagrantPlugins::Ansible::DEFAULT_COMPATIBILITY_MODE)
|
expect(config.compatibility_mode).to eq(VagrantPlugins::Ansible::SAFE_COMPATIBILITY_MODE)
|
||||||
}.and_return(default_execute_result)
|
}.and_return(default_execute_result)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "warns about not being able to detect the best compatibility mode" do
|
it "warns about not being able to detect the best compatibility mode" do
|
||||||
expect(machine.env.ui).to receive(:warn).with(
|
expect(machine.env.ui).to receive(:warn).with(
|
||||||
I18n.t("vagrant.provisioners.ansible.compatibility_mode_not_detected",
|
I18n.t("vagrant.provisioners.ansible.compatibility_mode_not_detected",
|
||||||
compatibility_mode: VagrantPlugins::Ansible::DEFAULT_COMPATIBILITY_MODE,
|
compatibility_mode: VagrantPlugins::Ansible::SAFE_COMPATIBILITY_MODE,
|
||||||
gathered_version: unknown_ansible_version) +
|
gathered_version: unknown_ansible_version) +
|
||||||
"\n")
|
"\n")
|
||||||
end
|
end
|
||||||
|
|
|
@ -29,10 +29,11 @@ Some of these options are for advanced usage only and should not be used unless
|
||||||
|
|
||||||
Possible values:
|
Possible values:
|
||||||
|
|
||||||
- `"1.8"` (Ansible versions prior to 1.8 should mostly work well, but some options might not be supported)
|
- `"auto"` _(Vagrant will automatically select the optimal compatibilty mode by checking the Ansible version currently available)_
|
||||||
- `"2.0"` (The generated Ansible inventory will be incompatible with Ansible 1.x)
|
- `"1.8"` _(Ansible versions prior to 1.8 should mostly work well, but some options might not be supported)_
|
||||||
|
- `"2.0"` _(The generated Ansible inventory will be incompatible with Ansible 1.x)_
|
||||||
|
|
||||||
By default this option is not set, and Vagrant will try to automatically set the optimal compatibilty mode by checking the Ansible version currently available. Note that Vagrant doesn't validate this option, and any unsupported value (e.g. "2.3") will also lead Vagrant to auto-detect the compatibility mode.
|
By default this option is set to `"auto"`. If Vagrant is not able to detect any supported Ansible version, it will falls back on the compatibility mode `"1.8"` with a warning.
|
||||||
|
|
||||||
<div class="alert alert-info">
|
<div class="alert alert-info">
|
||||||
<strong>Compatibility Note:</strong>
|
<strong>Compatibility Note:</strong>
|
||||||
|
|
Loading…
Reference in New Issue