provisioners/ansible: Move `version` to common options
Before this change, only the ansible_local provisioner supported this option (for ansible version requirement, and pip installation). Now, the ansible host-based provisioner can also require a exact ansible version. Resolve #8914 Note: this has been added as part of #6570 resolution, since the introduction of the `compatibility_mode` auto-detection made both provisioners made capable to detect ansible version. Pending: optimize the code to avoid duplicated executions of "ansible --version" command.
This commit is contained in:
parent
15e74e264d
commit
8c0df3d046
|
@ -28,6 +28,7 @@ module VagrantPlugins
|
||||||
attr_accessor :tags
|
attr_accessor :tags
|
||||||
attr_accessor :vault_password_file
|
attr_accessor :vault_password_file
|
||||||
attr_accessor :verbose
|
attr_accessor :verbose
|
||||||
|
attr_accessor :version
|
||||||
|
|
||||||
#
|
#
|
||||||
# Deprecated options
|
# Deprecated options
|
||||||
|
@ -64,6 +65,7 @@ module VagrantPlugins
|
||||||
@tags = UNSET_VALUE
|
@tags = UNSET_VALUE
|
||||||
@vault_password_file = UNSET_VALUE
|
@vault_password_file = UNSET_VALUE
|
||||||
@verbose = UNSET_VALUE
|
@verbose = UNSET_VALUE
|
||||||
|
@version = UNSET_VALUE
|
||||||
end
|
end
|
||||||
|
|
||||||
def finalize!
|
def finalize!
|
||||||
|
@ -87,6 +89,7 @@ module VagrantPlugins
|
||||||
@tags = nil if @tags == UNSET_VALUE
|
@tags = nil if @tags == UNSET_VALUE
|
||||||
@vault_password_file = nil if @vault_password_file == UNSET_VALUE
|
@vault_password_file = nil if @vault_password_file == UNSET_VALUE
|
||||||
@verbose = false if @verbose == UNSET_VALUE
|
@verbose = false if @verbose == UNSET_VALUE
|
||||||
|
@version = "" if @version == UNSET_VALUE
|
||||||
end
|
end
|
||||||
|
|
||||||
# Just like the normal configuration "validate" method except that
|
# Just like the normal configuration "validate" method except that
|
||||||
|
|
|
@ -11,7 +11,6 @@ module VagrantPlugins
|
||||||
attr_accessor :install
|
attr_accessor :install
|
||||||
attr_accessor :install_mode
|
attr_accessor :install_mode
|
||||||
attr_accessor :pip_args
|
attr_accessor :pip_args
|
||||||
attr_accessor :version
|
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
super
|
super
|
||||||
|
@ -21,7 +20,6 @@ module VagrantPlugins
|
||||||
@pip_args = UNSET_VALUE
|
@pip_args = UNSET_VALUE
|
||||||
@provisioning_path = UNSET_VALUE
|
@provisioning_path = UNSET_VALUE
|
||||||
@tmp_path = UNSET_VALUE
|
@tmp_path = UNSET_VALUE
|
||||||
@version = UNSET_VALUE
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def finalize!
|
def finalize!
|
||||||
|
@ -32,7 +30,6 @@ module VagrantPlugins
|
||||||
@pip_args = "" if @pip_args == UNSET_VALUE
|
@pip_args = "" if @pip_args == UNSET_VALUE
|
||||||
@provisioning_path = "/vagrant" if provisioning_path == UNSET_VALUE
|
@provisioning_path = "/vagrant" if provisioning_path == UNSET_VALUE
|
||||||
@tmp_path = "/tmp/vagrant-ansible" if tmp_path == UNSET_VALUE
|
@tmp_path = "/tmp/vagrant-ansible" if tmp_path == UNSET_VALUE
|
||||||
@version = "" if @version == UNSET_VALUE
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate(machine)
|
def validate(machine)
|
||||||
|
|
|
@ -23,8 +23,8 @@ module VagrantPlugins
|
||||||
error_key(:cannot_support_pip_install)
|
error_key(:cannot_support_pip_install)
|
||||||
end
|
end
|
||||||
|
|
||||||
class AnsibleVersionNotFoundOnGuest < AnsibleError
|
class AnsibleVersionMismatch < AnsibleError
|
||||||
error_key(:ansible_version_not_found_on_guest)
|
error_key(:ansible_version_mismatch)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -65,7 +65,7 @@ module VagrantPlugins
|
||||||
if (!config.version.empty? &&
|
if (!config.version.empty? &&
|
||||||
config.version.to_s.to_sym != :latest &&
|
config.version.to_s.to_sym != :latest &&
|
||||||
!@machine.guest.capability(:ansible_installed, config.version))
|
!@machine.guest.capability(:ansible_installed, config.version))
|
||||||
raise Ansible::Errors::AnsibleVersionNotFoundOnGuest, required_version: config.version.to_s
|
raise Ansible::Errors::AnsibleVersionMismatch, system: "guest", required_version: config.version.to_s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ module VagrantPlugins
|
||||||
@ssh_info = @machine.ssh_info
|
@ssh_info = @machine.ssh_info
|
||||||
|
|
||||||
warn_for_unsupported_platform
|
warn_for_unsupported_platform
|
||||||
|
check_required_ansible_version unless config.version.empty?
|
||||||
check_files_existence
|
check_files_existence
|
||||||
set_compatibility_mode
|
set_compatibility_mode
|
||||||
|
|
||||||
|
@ -36,6 +37,19 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def check_required_ansible_version
|
||||||
|
if config.version.to_s.to_sym == :latest
|
||||||
|
@logger.debug("The :latest version requirement is not supported (yet) by the host-based provisioner")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
@logger.info("Checking for Ansible version on Vagrant host...")
|
||||||
|
found_version = gather_ansible_version
|
||||||
|
if (!found_version || "ansible #{config.version}\n" != found_version.lines[0])
|
||||||
|
raise Ansible::Errors::AnsibleVersionMismatch, system: "host", required_version: config.version.to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def prepare_command_arguments
|
def prepare_command_arguments
|
||||||
# Connect with native OpenSSH client
|
# Connect with native OpenSSH client
|
||||||
# Other modes (e.g. paramiko) are not officially supported,
|
# Other modes (e.g. paramiko) are not officially supported,
|
||||||
|
|
|
@ -2364,11 +2364,11 @@ en:
|
||||||
to contribute back support. Thank you!
|
to contribute back support. Thank you!
|
||||||
|
|
||||||
https://github.com/mitchellh/vagrant
|
https://github.com/mitchellh/vagrant
|
||||||
ansible_version_not_found_on_guest: |-
|
ansible_version_mismatch: |-
|
||||||
The requested Ansible version (%{required_version}) was not found on the guest.
|
The requested Ansible version (%{required_version}) was not found on the %{system}.
|
||||||
Please check the ansible installation on your guest system,
|
Please check the Ansible installation on your Vagrant %{system} system,
|
||||||
or adapt the `version` option of this provisioner in your Vagrantfile.
|
or adapt the `version` option of this provisioner in your Vagrantfile.
|
||||||
See https://docs.vagrantup.com/v2/provisioning/ansible_local.html
|
See https://docs.vagrantup.com/v2/provisioning/ansible_common.html#version
|
||||||
for more information.
|
for more information.
|
||||||
config_file_not_found: |-
|
config_file_not_found: |-
|
||||||
`%{config_option}` does not exist on the %{system}: %{path}
|
`%{config_option}` does not exist on the %{system}: %{path}
|
||||||
|
|
|
@ -16,7 +16,8 @@ describe VagrantPlugins::Ansible::Config::Guest do
|
||||||
let(:existing_file) { "this/path/is/a/stub" }
|
let(:existing_file) { "this/path/is/a/stub" }
|
||||||
|
|
||||||
it "supports a list of options" do
|
it "supports a list of options" do
|
||||||
supported_options = %w( become
|
supported_options = %w(
|
||||||
|
become
|
||||||
become_user
|
become_user
|
||||||
compatibility_mode
|
compatibility_mode
|
||||||
config_file
|
config_file
|
||||||
|
@ -43,7 +44,8 @@ describe VagrantPlugins::Ansible::Config::Guest do
|
||||||
tmp_path
|
tmp_path
|
||||||
vault_password_file
|
vault_password_file
|
||||||
verbose
|
verbose
|
||||||
version )
|
version
|
||||||
|
)
|
||||||
|
|
||||||
expect(get_provisioner_option_names(described_class)).to eql(supported_options)
|
expect(get_provisioner_option_names(described_class)).to eql(supported_options)
|
||||||
end
|
end
|
||||||
|
@ -58,7 +60,6 @@ describe VagrantPlugins::Ansible::Config::Guest do
|
||||||
expect(subject.install_mode).to eql(:default)
|
expect(subject.install_mode).to eql(:default)
|
||||||
expect(subject.provisioning_path).to eql("/vagrant")
|
expect(subject.provisioning_path).to eql("/vagrant")
|
||||||
expect(subject.tmp_path).to eql("/tmp/vagrant-ansible")
|
expect(subject.tmp_path).to eql("/tmp/vagrant-ansible")
|
||||||
expect(subject.version).to be_empty
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,8 @@ describe VagrantPlugins::Ansible::Config::Host, :skip_windows => true do
|
||||||
let(:existing_file) { File.expand_path(__FILE__) }
|
let(:existing_file) { File.expand_path(__FILE__) }
|
||||||
|
|
||||||
it "supports a list of options" do
|
it "supports a list of options" do
|
||||||
supported_options = %w( ask_become_pass
|
supported_options = %w(
|
||||||
|
ask_become_pass
|
||||||
ask_sudo_pass
|
ask_sudo_pass
|
||||||
ask_vault_pass
|
ask_vault_pass
|
||||||
become
|
become
|
||||||
|
@ -40,7 +41,9 @@ describe VagrantPlugins::Ansible::Config::Host, :skip_windows => true do
|
||||||
sudo_user
|
sudo_user
|
||||||
tags
|
tags
|
||||||
vault_password_file
|
vault_password_file
|
||||||
verbose )
|
verbose
|
||||||
|
version
|
||||||
|
)
|
||||||
|
|
||||||
expect(get_provisioner_option_names(described_class)).to eql(supported_options)
|
expect(get_provisioner_option_names(described_class)).to eql(supported_options)
|
||||||
end
|
end
|
||||||
|
|
|
@ -25,6 +25,7 @@ shared_examples_for 'options shared by both Ansible provisioners' do
|
||||||
expect(subject.tags).to be_nil
|
expect(subject.tags).to be_nil
|
||||||
expect(subject.vault_password_file).to be_nil
|
expect(subject.vault_password_file).to be_nil
|
||||||
expect(subject.verbose).to be(false)
|
expect(subject.verbose).to be(false)
|
||||||
|
expect(subject.version).to be_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -947,6 +947,46 @@ VF
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
context "with version option set" do
|
||||||
|
before do
|
||||||
|
config.version = "2.3.4.5"
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "and the installed ansible version is correct" do
|
||||||
|
before do
|
||||||
|
allow(subject).to receive(:gather_ansible_version).and_return("ansible #{config.version}\n...\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "executes ansible-playbook command" do
|
||||||
|
expect(Vagrant::Util::Subprocess).to receive(:execute).with('ansible-playbook', any_args).and_return(default_execute_result)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "and there is an ansible version mismatch" do
|
||||||
|
before do
|
||||||
|
allow(subject).to receive(:gather_ansible_version).and_return("ansible 1.9.6\n...\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises an error about the ansible version mismatch", skip_before: true, skip_after: true do
|
||||||
|
config.finalize!
|
||||||
|
expect {subject.provision}.to raise_error(VagrantPlugins::Ansible::Errors::AnsibleVersionMismatch)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "and the installed ansible version cannot be detected" do
|
||||||
|
before do
|
||||||
|
allow(subject).to receive(:gather_ansible_version).and_return(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises an error about the ansible version mismatch", skip_before: true, skip_after: true do
|
||||||
|
config.finalize!
|
||||||
|
expect {subject.provision}.to raise_error(VagrantPlugins::Ansible::Errors::AnsibleVersionMismatch)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# TODO: add more tests, now that we know how to deal with multiple Subprocess stub executions
|
||||||
describe "with galaxy support" do
|
describe "with galaxy support" do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
|
|
|
@ -42,7 +42,7 @@ Some of these options are for advanced usage only and should not be used unless
|
||||||
|
|
||||||
<div class="alert alert-warning">
|
<div class="alert alert-warning">
|
||||||
<strong>Attention:</strong>
|
<strong>Attention:</strong>
|
||||||
Vagrant doesn't perform any validation between the `compatibility_mode` value and the value of the ansible_local [`version`](/docs/provisioning/ansible_local.html#version) option.
|
Vagrant doesn't perform any validation between the `compatibility_mode` value and the value of the [`version`](#version) option.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
- `config_file` (string) - The path to an [Ansible Configuration file](https://docs.ansible.com/intro_configuration.html).
|
- `config_file` (string) - The path to an [Ansible Configuration file](https://docs.ansible.com/intro_configuration.html).
|
||||||
|
@ -185,3 +185,16 @@ Some of these options are for advanced usage only and should not be used unless
|
||||||
Examples: `true` (equivalent to `v`), `-vvv` (equivalent to `vvv`), `vvvv`.
|
Examples: `true` (equivalent to `v`), `-vvv` (equivalent to `vvv`), `vvvv`.
|
||||||
|
|
||||||
Note that when the `verbose` option is enabled, the `ansible-playbook` command used by Vagrant will be displayed.
|
Note that when the `verbose` option is enabled, the `ansible-playbook` command used by Vagrant will be displayed.
|
||||||
|
|
||||||
|
- `version` (string) - The expected Ansible version.
|
||||||
|
|
||||||
|
This option is disabled by default.
|
||||||
|
|
||||||
|
When an Ansible version is defined (e.g. `"2.1.6.0"`), the Ansible provisioner will be executed only if Ansible is installed at the requested version.
|
||||||
|
|
||||||
|
When this option is set to `"latest"`, no version check is applied.
|
||||||
|
|
||||||
|
<div class="alert alert-info">
|
||||||
|
<strong>Tip:</strong>
|
||||||
|
With the `ansible_local` provisioner, it is currently possible to use this option to specify which version of Ansible must be automatically installed, but <strong>only</strong> in combination with the [**`install_mode`**](ansible_local.html#install_mode) set to <strong>`:pip`</strong>.
|
||||||
|
</div>
|
||||||
|
|
|
@ -62,8 +62,8 @@ This section lists the _specific_ options for the Ansible Local provisioner. In
|
||||||
Vagrant will try to install (or upgrade) Ansible when one of these conditions are met:
|
Vagrant will try to install (or upgrade) Ansible when one of these conditions are met:
|
||||||
|
|
||||||
- Ansible is not installed (or cannot be found).
|
- Ansible is not installed (or cannot be found).
|
||||||
- The `version` option is set to `"latest"`.
|
- The [`version`](/docs/provisioning/ansible_common.html#version) option is set to `"latest"`.
|
||||||
- The current Ansible version does not correspond to the `version` option.
|
- The current Ansible version does not correspond to the [`version`](/docs/provisioning/ansible_common.html#version) option.
|
||||||
|
|
||||||
<div class="alert alert-warning">
|
<div class="alert alert-warning">
|
||||||
<strong>Attention:</strong>
|
<strong>Attention:</strong>
|
||||||
|
@ -76,7 +76,7 @@ This section lists the _specific_ options for the Ansible Local provisioner. In
|
||||||
- On Ubuntu-like systems, the latest Ansible release is installed from the `ppa:ansible/ansible` repository.
|
- On Ubuntu-like systems, the latest Ansible release is installed from the `ppa:ansible/ansible` repository.
|
||||||
- On RedHat-like systems, the latest Ansible release is installed from the [EPEL](http://fedoraproject.org/wiki/EPEL) repository.
|
- On RedHat-like systems, the latest Ansible release is installed from the [EPEL](http://fedoraproject.org/wiki/EPEL) repository.
|
||||||
|
|
||||||
- `:pip`: Ansible is installed from [PyPI](https://pypi.python.org/pypi) with [pip](https://pip.pypa.io) package installer. With this mode, Vagrant will systematically try to [install the latest pip version](https://pip.pypa.io/en/stable/installing/#installing-with-get-pip-py). With the `:pip` mode you can optionally install a specific Ansible release by setting the [`version`](#version) option.
|
- `:pip`: Ansible is installed from [PyPI](https://pypi.python.org/pypi) with [pip](https://pip.pypa.io) package installer. With this mode, Vagrant will systematically try to [install the latest pip version](https://pip.pypa.io/en/stable/installing/#installing-with-get-pip-py). With the `:pip` mode you can optionally install a specific Ansible release by setting the [`version`](/docs/provisioning/ansible_common.html#version) option.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
@ -141,19 +141,6 @@ This section lists the _specific_ options for the Ansible Local provisioner. In
|
||||||
|
|
||||||
The default value is `/tmp/vagrant-ansible`
|
The default value is `/tmp/vagrant-ansible`
|
||||||
|
|
||||||
- `version` (string) - The expected Ansible version.
|
|
||||||
|
|
||||||
This option is disabled by default.
|
|
||||||
|
|
||||||
When an Ansible version is defined (e.g. `"1.8.2"`), the Ansible local provisioner will be executed only if Ansible is installed at the requested version.
|
|
||||||
|
|
||||||
When this option is set to `"latest"`, no version check is applied.
|
|
||||||
|
|
||||||
<div class="alert alert-info">
|
|
||||||
<strong>Tip:</strong>
|
|
||||||
It is currently possible to use this option to specify which version of Ansible must be automatically installed, but <strong>only</strong> in combination with the `install_mode` set to <strong>`:pip`</strong>.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## Tips and Tricks
|
## Tips and Tricks
|
||||||
|
|
||||||
### Ansible Parallel Execution from a Guest
|
### Ansible Parallel Execution from a Guest
|
||||||
|
|
Loading…
Reference in New Issue