ansible_local: Add the :pip_args_only install mode

With the introduction of `pip_args` option, you can easily extend the
`:pip` installation mode behaviour. But some interesting/advanced usages
are still not possible because of the auto-generated parts ("ansible"
package, version selection, and the `--upgrade` flag).

By adding this "pip_args_only" install mode, it will be for instance
possible to:
- install unofficial releases, like release candidates published at
  https://releases.ansible.com/
- install more pip packages (e.g. via a `requirements.txt` file), with
  hash validation, etc.

Note that there is no config validation that requires `pip_args` option
to be defined when the :pip_args_only mode is selected. This would be
more elegant, and user friendly to raise a configuration error, but this
can wait. At least, running with an empty `pip_args` won't lead to any
command crash, since the rather dummy "pip install" shows an helper
notice and terminates with a zero (0) exit code.

This change is thought as a complement to the changes originally
proposed in pull request GH-8170.
This commit is contained in:
Gilles Cornu 2017-03-23 23:10:56 +01:00
parent b40d347944
commit 80d105cf8c
No known key found for this signature in database
GPG Key ID: F6BC2CF7E1FE8FFF
11 changed files with 91 additions and 23 deletions

View File

@ -8,7 +8,7 @@ module VagrantPlugins
module AnsibleInstall
def self.ansible_install(machine, install_mode, ansible_version, pip_args)
if install_mode == :pip
if install_mode != :default
raise Ansible::Errors::AnsiblePipInstallIsNotSupported
else
machine.communicate.sudo "pacman -Syy --noconfirm"

View File

@ -9,18 +9,18 @@ module VagrantPlugins
def self.ansible_install(machine, install_mode, ansible_version, pip_args)
if (install_mode == :pip)
ansible_pip_install machine, ansible_version, pip_args
case install_mode
when :pip
pip_setup machine
Pip::pip_install machine, "ansible", ansible_version, pip_args, true
when :pip_args_only
pip_setup machine
Pip::pip_install machine, "", "", pip_args, false
else
ansible_apt_install machine
end
end
def self.ansible_pip_install(machine, ansible_version, pip_args)
pip_setup machine
Pip::pip_install machine, "ansible", ansible_version, pip_args
end
private
def self.ansible_apt_install(machine)

View File

@ -9,12 +9,16 @@ module VagrantPlugins
module AnsibleInstall
def self.ansible_install(machine, install_mode, ansible_version, pip_args)
rpm_package_manager = Facts::rpm_package_manager(machine)
if install_mode == :pip
case install_mode
when :pip
pip_setup machine
Pip::pip_install machine, "ansible", ansible_version, pip_args
Pip::pip_install machine, "ansible", ansible_version, pip_args, true
when :pip_args_only
pip_setup machine
Pip::pip_install machine, "", "", pip_args, false
else
rpm_package_manager = Facts::rpm_package_manager(machine)
machine.communicate.sudo "#{rpm_package_manager} -y install ansible"
end
end

View File

@ -8,7 +8,7 @@ module VagrantPlugins
module AnsibleInstall
def self.ansible_install(machine, install_mode, ansible_version)
if install_mode == :pip
if install_mode != :default
raise Ansible::Errors::AnsiblePipInstallIsNotSupported
else
machine.communicate.sudo "yes | pkg install ansible"

View File

@ -5,7 +5,7 @@ module VagrantPlugins
module Guest
module Pip
def self.pip_install(machine, package, version = "", pip_args = "", upgrade = true)
def self.pip_install(machine, package = "", version = "", pip_args = "", upgrade = true)
upgrade_arg = "--upgrade" if upgrade
version_arg = ""

View File

@ -9,9 +9,13 @@ module VagrantPlugins
module AnsibleInstall
def self.ansible_install(machine, install_mode, ansible_version, pip_args)
if install_mode == :pip
case install_mode
when :pip
pip_setup machine
Pip::pip_install machine, "ansible", ansible_version, pip_args
Pip::pip_install machine, "ansible", ansible_version, pip_args, true
when :pip_args_only
pip_setup machine
Pip::pip_install machine, "", "", pip_args, false
else
ansible_rpm_install machine
end

View File

@ -7,7 +7,7 @@ module VagrantPlugins
module AnsibleInstall
def self.ansible_install(machine, install_mode, ansible_version)
if install_mode == :pip
if install_mode != :default
raise Ansible::Errors::AnsiblePipInstallIsNotSupported
else
machine.communicate.sudo("zypper --non-interactive --quiet install ansible")

View File

@ -8,8 +8,8 @@ module VagrantPlugins
module AnsibleInstall
def self.ansible_install(machine, install_mode, ansible_version, pip_args)
if install_mode == :pip
Debian::AnsibleInstall::ansible_pip_install machine, ansible_version, pip_args
if install_mode != :default
Debian::AnsibleInstall::ansible_install machine, install_mode, ansible_version, pip_args
else
ansible_apt_install machine
end

View File

@ -38,8 +38,11 @@ module VagrantPlugins
def validate(machine)
super
if @install_mode.to_s.to_sym == :pip
case @install_mode.to_s.to_sym
when :pip
@install_mode = :pip
when :pip_args_only
@install_mode = :pip_args_only
else
@install_mode = :default
end

View File

@ -81,6 +81,14 @@ describe VagrantPlugins::Ansible::Config::Guest do
result = subject.validate(machine)
expect(subject.install_mode).to eql(:pip)
end
it "supports :pip_args_only install_mode" do
subject.install_mode = "pip_args_only"
subject.finalize!
result = subject.validate(machine)
expect(subject.install_mode).to eql(:pip_args_only)
end
end
end

View File

@ -69,20 +69,69 @@ This section lists the _specific_ options for the Ansible Local provisioner. In
**Attention:** There is no guarantee that this automated installation will replace a custom Ansible setup, that might be already present on the Vagrant box.
- `install_mode` (`:default` or `:pip`) - Select the way to automatically install Ansible on the guest system.
- `install_mode` (`:default`, `:pip`, or `:pip_args_only`) - Select the way to automatically install Ansible on the guest system.
- `:default`: Ansible is installed from the operating system package manager. This mode doesn't support `version` selection. For many platforms (e.g Debian, FreeBSD, OpenSUSE) the official package repository is used, except for the following Linux distributions:
- 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.
- `: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). The `:pip` mode can install a specific version of Ansible if such information is specified with the `version` option described below.
- `: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.
The default value is `:default`, and any invalid value for this option will silently fall back to the default value.
Example:
```ruby
config.vm.provision "ansible_local" do |ansible|
ansible.playbook = "playbook.yml"
ansible.install_mode = "pip"
ansible.version = "2.2.1.0"
end
```
With this configuration, Vagrant will install `pip` and then execute the command
```shell
sudo pip install --upgrade ansible==2.2.1.0
```
- `:pip_args_only`: This mode is very similar to the `:pip` mode, with the difference that in this case no pip arguments will be automatically set by Vagrant.
Example:
```ruby
config.vm.provision "ansible_local" do |ansible|
ansible.playbook = "playbook.yml"
ansible.install_mode = "pip_args_only"
ansible.pip_args = "-r /vagrant/requirements.txt"
end
```
With this configuration, Vagrant will install `pip` and then execute the command
```shell
sudo pip install -r /vagrant/requirements.txt
```
The default value of `install_mode` is `:default`, and any invalid value for this option will silently fall back to the default value.
- `pip_args` (string) - When Ansible is installed via pip, this option allows the definition of additional pip arguments to be passed along on the command line (for example, [`--index-url`](https://pip.pypa.io/en/stable/reference/pip_install/#cmdoption-i)).
By default, this option is not set.
Example:
```ruby
config.vm.provision "ansible_local" do |ansible|
ansible.playbook = "playbook.yml"
ansible.install_mode = :pip
ansible.pip_args = "--install-url https://pypi.internal"
end
```
With this configuration, Vagrant will install `pip` and then execute the command
```shell
sudo pip install --index-url https://pypi.internal --upgrade ansible
```
- `provisioning_path` (string) - An absolute path on the guest machine where the Ansible files are stored. The `ansible-galaxy` and `ansible-playbook` commands are executed from this directory. This is the location to place an [ansible.cfg](http://docs.ansible.com/ansible/intro_configuration.html) file, in case you need it.
The default value is `/vagrant`.