provisioners/ansible_local: add "pip" install_mode
These changes have been validated against the following guest systems: - Debian 7 and 8 - Ubuntu 12.04, 14.04 and 16.04 - Fedora 21 and 23 - CentOS 7 - OracleLinux 7 - Scientific Linux 7 At the moment, the pip setup (via get-pip.py script) is not working for RHEL6-like systems (CentOS 6.6, OracleLinux 6.5, Scientific Linux 6), because Python 2.6 has been deprecated and is no longer supported by Python core team. I consider this limitation with low priority in Vagrant context. The `:pip` install_mode is currently not implemented for the following platforms: - OpenSUSE - ArchLinux - FreeBSD Known Issue: By using get-pip.py script, any previous pip installation will be most probably overrided. This could be an issue for Python developers who would prefer to keep their base box setup untouched. In future iteration, it could be possible to choose to reinstall/upgrade pip or not. issue for Python developers who would prefer to keep their base box setup untouched. In future iteration, it could be possible to choose to reinstall/upgrade pip or not. Resolve GH-6654 Resolve GH-7167 as the `version` option is now considered to select the version of Ansible to be installed.
This commit is contained in:
parent
08cf08a110
commit
bb9dba56ac
|
@ -45,6 +45,8 @@ IMPROVEMENTS:
|
|||
- commands/login: Print a warning with both the environment variable and
|
||||
local login token are present [GH-7206, GH-7219]
|
||||
- communicators/winrm: Upgrade to latest WinRM gems [GH-6922]
|
||||
- provisioners/ansible_local: Allow to install Ansible from pip,
|
||||
with version selection capability [GH-6654, GH-7167]
|
||||
- provisioners/ansible_local: Use `provisioning_path` as working directory
|
||||
for `ansible-galaxy` execution
|
||||
- provisioners/ansible(both provisioners): Add basic config
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
require_relative "../../../errors"
|
||||
|
||||
module VagrantPlugins
|
||||
module Ansible
|
||||
|
@ -6,10 +7,14 @@ module VagrantPlugins
|
|||
module Arch
|
||||
module AnsibleInstall
|
||||
|
||||
def self.ansible_install(machine)
|
||||
def self.ansible_install(machine, install_mode, ansible_version)
|
||||
if install_mode == :pip
|
||||
raise Ansible::Errors::AnsiblePipInstallIsNotSupported
|
||||
else
|
||||
machine.communicate.sudo("pacman -Syy --noconfirm")
|
||||
machine.communicate.sudo("pacman -S --noconfirm ansible")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
require_relative "../pip/pip"
|
||||
|
||||
module VagrantPlugins
|
||||
module Ansible
|
||||
|
@ -6,8 +7,23 @@ module VagrantPlugins
|
|||
module Debian
|
||||
module AnsibleInstall
|
||||
|
||||
def self.ansible_install(machine)
|
||||
|
||||
def self.ansible_install(machine, install_mode, ansible_version)
|
||||
if (install_mode == :pip)
|
||||
ansible_pip_install machine, ansible_version
|
||||
else
|
||||
ansible_apt_install machine
|
||||
end
|
||||
end
|
||||
|
||||
def self.ansible_pip_install(machine, ansible_version)
|
||||
pip_setup machine
|
||||
Pip::pip_install machine, "ansible", ansible_version
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.ansible_apt_install(machine)
|
||||
install_backports_if_wheezy_release = <<INLINE_CRIPT
|
||||
CODENAME=`lsb_release -cs`
|
||||
if [ x$CODENAME == 'xwheezy' ]; then
|
||||
|
@ -20,6 +36,12 @@ INLINE_CRIPT
|
|||
machine.communicate.sudo("apt-get install -y -qq ansible")
|
||||
end
|
||||
|
||||
def self.pip_setup(machine)
|
||||
machine.communicate.sudo "apt-get update -y -qq"
|
||||
machine.communicate.sudo "apt-get install -y -qq build-essential curl git libssl-dev libffi-dev python-dev"
|
||||
Pip::get_pip machine
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
|
||||
module VagrantPlugins
|
||||
module Ansible
|
||||
module Cap
|
||||
module Guest
|
||||
module Facts
|
||||
|
||||
def self.dnf?(machine)
|
||||
machine.communicate.test "/usr/bin/which -s dnf"
|
||||
end
|
||||
|
||||
def self.yum?(machine)
|
||||
machine.communicate.test "/usr/bin/which -s yum"
|
||||
end
|
||||
|
||||
def self.rpm_package_manager(machine)
|
||||
dnf?(machine) ? "dnf" : "yum"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,3 +1,5 @@
|
|||
require_relative "../facts"
|
||||
require_relative "../pip/pip"
|
||||
|
||||
module VagrantPlugins
|
||||
module Ansible
|
||||
|
@ -6,16 +8,20 @@ module VagrantPlugins
|
|||
module Fedora
|
||||
module AnsibleInstall
|
||||
|
||||
def self.ansible_install(machine)
|
||||
if dnf?(machine)
|
||||
machine.communicate.sudo("dnf -y install ansible")
|
||||
def self.ansible_install(machine, install_mode, ansible_version)
|
||||
if install_mode == :pip
|
||||
pip_setup machine
|
||||
Pip::pip_install machine, "ansible", ansible_version
|
||||
else
|
||||
machine.communicate.sudo("yum -y install ansible")
|
||||
machine.communicate.sudo "#{Facts::rpm_package_manager} -y install ansible"
|
||||
end
|
||||
end
|
||||
|
||||
def self.dnf?(machine)
|
||||
machine.communicate.test("/usr/bin/which -s dnf")
|
||||
private
|
||||
|
||||
def self.pip_setup(machine)
|
||||
machine.communicate.sudo "#{Facts::rpm_package_manager(machine)} install -y curl gcc gmp-devel libffi-devel openssl-devel python-crypto python-devel python-dnf python-setuptools redhat-rpm-config"
|
||||
Pip::get_pip machine
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
require_relative "../../../errors"
|
||||
|
||||
module VagrantPlugins
|
||||
module Ansible
|
||||
|
@ -6,9 +7,13 @@ module VagrantPlugins
|
|||
module FreeBSD
|
||||
module AnsibleInstall
|
||||
|
||||
def self.ansible_install(machine)
|
||||
def self.ansible_install(machine, install_mode, ansible_version)
|
||||
if install_mode == :pip
|
||||
raise Ansible::Errors::AnsiblePipInstallIsNotSupported
|
||||
else
|
||||
machine.communicate.sudo("yes | pkg install ansible")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
module VagrantPlugins
|
||||
module Ansible
|
||||
module Cap
|
||||
module Guest
|
||||
module Pip
|
||||
|
||||
def self.pip_install(machine, package, version = "", upgrade = true)
|
||||
upgrade_arg = "--upgrade " if upgrade
|
||||
version_arg = ""
|
||||
|
||||
if !version.to_s.empty? && version.to_s.to_sym != :latest
|
||||
version_arg = "==#{version}"
|
||||
end
|
||||
|
||||
machine.communicate.sudo "pip install #{upgrade_arg}#{package}#{version_arg}"
|
||||
end
|
||||
|
||||
def self.get_pip(machine)
|
||||
machine.ui.detail I18n.t("vagrant.provisioners.ansible.installing_pip")
|
||||
machine.communicate.execute "curl https://bootstrap.pypa.io/get-pip.py | sudo python"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,3 +1,5 @@
|
|||
require_relative "../facts"
|
||||
require_relative "../pip/pip"
|
||||
|
||||
module VagrantPlugins
|
||||
module Ansible
|
||||
|
@ -6,17 +8,29 @@ module VagrantPlugins
|
|||
module RedHat
|
||||
module AnsibleInstall
|
||||
|
||||
def self.ansible_install(machine)
|
||||
epel = machine.communicate.execute("#{yum_dnf(machine)} repolist epel | grep -q epel", :error_check => false)
|
||||
def self.ansible_install(machine, install_mode, ansible_version)
|
||||
if install_mode == :pip
|
||||
pip_setup machine
|
||||
Pip::pip_install machine, "ansible", ansible_version
|
||||
else
|
||||
ansible_rpm_install machine
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.ansible_rpm_install(machine)
|
||||
epel = machine.communicate.execute "#{yum_dnf(machine)} repolist epel | grep -q epel", error_check: false
|
||||
if epel != 0
|
||||
machine.communicate.sudo('sudo rpm -i https://dl.fedoraproject.org/pub/epel/epel-release-latest-`rpm -E %dist | sed -n \'s/.*el\([0-9]\).*/\1/p\'`.noarch.rpm')
|
||||
machine.communicate.sudo 'sudo rpm -i https://dl.fedoraproject.org/pub/epel/epel-release-latest-`rpm -E %dist | sed -n \'s/.*el\([0-9]\).*/\1/p\'`.noarch.rpm'
|
||||
end
|
||||
|
||||
machine.communicate.sudo("#{yum_dnf(machine)} -y --enablerepo=epel install ansible")
|
||||
machine.communicate.sudo "#{Facts::rpm_package_manager} -y --enablerepo=epel install ansible"
|
||||
end
|
||||
|
||||
def self.yum_dnf(machine)
|
||||
machine.communicate.test("/usr/bin/which -s dnf") ? "dnf" : "yum"
|
||||
def self.pip_setup(machine)
|
||||
machine.communicate.sudo("#{Facts::rpm_package_manager(machine)} install -y curl gcc libffi-devel openssl-devel python-crypto python-devel python-setuptools")
|
||||
Pip::get_pip machine
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -6,9 +6,13 @@ module VagrantPlugins
|
|||
module SUSE
|
||||
module AnsibleInstall
|
||||
|
||||
def self.ansible_install(machine)
|
||||
def self.ansible_install(machine, install_mode, ansible_version)
|
||||
if install_mode == :pip
|
||||
raise Ansible::Errors::AnsiblePipInstallIsNotSupported
|
||||
else
|
||||
machine.communicate.sudo("zypper --non-interactive --quiet install ansible")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
require_relative "../debian/ansible_install"
|
||||
|
||||
module VagrantPlugins
|
||||
module Ansible
|
||||
|
@ -6,12 +7,22 @@ module VagrantPlugins
|
|||
module Ubuntu
|
||||
module AnsibleInstall
|
||||
|
||||
def self.ansible_install(machine)
|
||||
machine.communicate.sudo("apt-get update -y -qq")
|
||||
machine.communicate.sudo("apt-get install -y -qq software-properties-common python-software-properties")
|
||||
machine.communicate.sudo("add-apt-repository ppa:ansible/ansible -y")
|
||||
machine.communicate.sudo("apt-get update -y -qq")
|
||||
machine.communicate.sudo("apt-get install -y -qq ansible")
|
||||
def self.ansible_install(machine, install_mode, ansible_version)
|
||||
if install_mode == :pip
|
||||
Debian::AnsibleInstall::ansible_pip_install machine, ansible_version
|
||||
else
|
||||
ansible_apt_install machine
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.ansible_apt_install(machine)
|
||||
machine.communicate.sudo "apt-get update -y -qq"
|
||||
machine.communicate.sudo "apt-get install -y -qq software-properties-common python-software-properties"
|
||||
machine.communicate.sudo "add-apt-repository ppa:ansible/ansible -y"
|
||||
machine.communicate.sudo "apt-get update -y -qq"
|
||||
machine.communicate.sudo "apt-get install -y -qq ansible"
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -9,12 +9,14 @@ module VagrantPlugins
|
|||
attr_accessor :provisioning_path
|
||||
attr_accessor :tmp_path
|
||||
attr_accessor :install
|
||||
attr_accessor :install_mode
|
||||
attr_accessor :version
|
||||
|
||||
def initialize
|
||||
super
|
||||
|
||||
@install = UNSET_VALUE
|
||||
@install_mode = UNSET_VALUE
|
||||
@provisioning_path = UNSET_VALUE
|
||||
@tmp_path = UNSET_VALUE
|
||||
@version = UNSET_VALUE
|
||||
|
@ -24,6 +26,7 @@ module VagrantPlugins
|
|||
super
|
||||
|
||||
@install = true if @install == UNSET_VALUE
|
||||
@install_mode = :default if @install_mode == UNSET_VALUE
|
||||
@provisioning_path = "/vagrant" if provisioning_path == UNSET_VALUE
|
||||
@tmp_path = "/tmp/vagrant-ansible" if tmp_path == UNSET_VALUE
|
||||
@version = "" if @version == UNSET_VALUE
|
||||
|
@ -32,6 +35,12 @@ module VagrantPlugins
|
|||
def validate(machine)
|
||||
super
|
||||
|
||||
if @install_mode.to_s.to_sym == :pip
|
||||
@install_mode = :pip
|
||||
else
|
||||
@install_mode = :default
|
||||
end
|
||||
|
||||
{ "ansible local provisioner" => @errors }
|
||||
end
|
||||
|
||||
|
|
|
@ -19,6 +19,10 @@ module VagrantPlugins
|
|||
error_key(:ansible_not_found_on_guest)
|
||||
end
|
||||
|
||||
class AnsiblePipInstallIsNotSupported < AnsibleError
|
||||
error_key(:cannot_support_pip_install)
|
||||
end
|
||||
|
||||
class AnsibleVersionNotFoundOnGuest < AnsibleError
|
||||
error_key(:ansible_version_not_found_on_guest)
|
||||
end
|
||||
|
|
|
@ -49,7 +49,7 @@ module VagrantPlugins
|
|||
(config.version.to_s.to_sym == :latest ||
|
||||
!@machine.guest.capability(:ansible_installed, config.version))
|
||||
@machine.ui.detail I18n.t("vagrant.provisioners.ansible.installing")
|
||||
@machine.guest.capability(:ansible_install)
|
||||
@machine.guest.capability(:ansible_install, config.install_mode, config.version)
|
||||
end
|
||||
|
||||
# Check that ansible binaries are well installed on the guest,
|
||||
|
|
|
@ -2122,6 +2122,15 @@ en:
|
|||
on your host system. Vagrant can't do this for you in a safe and
|
||||
automated way.
|
||||
Please check https://docs.ansible.com for more information.
|
||||
cannot_support_pip_install: |-
|
||||
Unfortunately Vagrant does not support yet installing Ansible
|
||||
from pip for the guest OS running in the machine.
|
||||
|
||||
If you'd like this provisioner to be improved, please
|
||||
take a look at the Vagrant source code linked below and try
|
||||
to contribute back support. Thank you!
|
||||
|
||||
https://github.com/mitchellh/vagrant
|
||||
ansible_version_not_found_on_guest: |-
|
||||
The requested Ansible version (%{required_version}) was not found on the guest.
|
||||
Please check the ansible installation on your guest system,
|
||||
|
@ -2139,6 +2148,7 @@ en:
|
|||
raw_ssh_args_invalid: |-
|
||||
`raw_ssh_args` must be an array of strings. Received: %{value} (as %{type})
|
||||
installing: "Installing Ansible..."
|
||||
installing_pip: "Installing pip... (for Ansible installation)"
|
||||
running_galaxy: "Running ansible-galaxy..."
|
||||
running_playbook: "Running ansible-playbook..."
|
||||
windows_not_supported_for_control_machine: |-
|
||||
|
|
|
@ -23,6 +23,7 @@ describe VagrantPlugins::Ansible::Config::Guest do
|
|||
groups
|
||||
host_vars
|
||||
install
|
||||
install_mode
|
||||
inventory_path
|
||||
limit
|
||||
playbook
|
||||
|
@ -48,6 +49,7 @@ describe VagrantPlugins::Ansible::Config::Guest do
|
|||
subject.finalize!
|
||||
|
||||
expect(subject.install).to be_true
|
||||
expect(subject.install_mode).to eql(:default)
|
||||
expect(subject.provisioning_path).to eql("/vagrant")
|
||||
expect(subject.tmp_path).to eql("/tmp/vagrant-ansible")
|
||||
expect(subject.version).to be_empty
|
||||
|
@ -60,6 +62,22 @@ describe VagrantPlugins::Ansible::Config::Guest do
|
|||
end
|
||||
|
||||
it_behaves_like "an Ansible provisioner", "/vagrant", "local"
|
||||
|
||||
it "falls back to :default install_mode for any invalid setting" do
|
||||
subject.install_mode = "from_source"
|
||||
subject.finalize!
|
||||
|
||||
result = subject.validate(machine)
|
||||
expect(subject.install_mode).to eql(:default)
|
||||
end
|
||||
|
||||
it "supports :pip install_mode" do
|
||||
subject.install_mode = "pip"
|
||||
subject.finalize!
|
||||
|
||||
result = subject.validate(machine)
|
||||
expect(subject.install_mode).to eql(:pip)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -71,6 +71,16 @@ This section lists the specific options for the Ansible Local provisioner. In ad
|
|||
|
||||
**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.
|
||||
|
||||
- `: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.
|
||||
|
||||
The default value is `:default`, and any invalid value for this option will silently fall back to the default value.
|
||||
|
||||
- `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`.
|
||||
|
|
Loading…
Reference in New Issue