Merge pull request #10625 from vdebroy/fix-issue-9584

Fix issue 9584
This commit is contained in:
Brian Cain 2019-04-09 15:12:02 -07:00 committed by GitHub
commit 139ae4397f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 118 additions and 21 deletions

View File

@ -8,13 +8,13 @@ module VagrantPlugins
module AnsibleInstall
def self.ansible_install(machine, install_mode, ansible_version, pip_args)
def self.ansible_install(machine, install_mode, ansible_version, pip_args, pip_install_cmd="")
case install_mode
when :pip
pip_setup machine
pip_setup machine, pip_install_cmd
Pip::pip_install machine, "ansible", ansible_version, pip_args, true
when :pip_args_only
pip_setup machine
pip_setup machine, pip_install_cmd
Pip::pip_install machine, "", "", pip_args, false
else
ansible_apt_install machine
@ -36,10 +36,10 @@ INLINE_CRIPT
machine.communicate.sudo "apt-get install -y -qq ansible"
end
def self.pip_setup(machine)
def self.pip_setup(machine, pip_install_cmd="")
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
Pip::get_pip machine, pip_install_cmd
end
end

View File

@ -8,13 +8,13 @@ module VagrantPlugins
module Fedora
module AnsibleInstall
def self.ansible_install(machine, install_mode, ansible_version, pip_args)
def self.ansible_install(machine, install_mode, ansible_version, pip_args, pip_install_cmd="")
case install_mode
when :pip
pip_setup machine
pip_setup machine, pip_install_cmd
Pip::pip_install machine, "ansible", ansible_version, pip_args, true
when :pip_args_only
pip_setup machine
pip_setup machine, pip_install_cmd
Pip::pip_install machine, "", "", pip_args, false
else
rpm_package_manager = Facts::rpm_package_manager(machine)
@ -25,11 +25,11 @@ module VagrantPlugins
private
def self.pip_setup(machine)
def self.pip_setup(machine, pip_install_cmd="")
rpm_package_manager = Facts::rpm_package_manager(machine)
machine.communicate.sudo "#{rpm_package_manager} 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
Pip::get_pip machine, pip_install_cmd
end
end

View File

@ -5,6 +5,8 @@ module VagrantPlugins
module Guest
module Pip
DEFAULT_PIP_INSTALL_CMD = "curl https://bootstrap.pypa.io/get-pip.py | sudo python".freeze
def self.pip_install(machine, package = "", version = "", pip_args = "", upgrade = true)
upgrade_arg = "--upgrade" if upgrade
version_arg = ""
@ -18,9 +20,20 @@ module VagrantPlugins
machine.communicate.sudo "pip install #{args_array.join(' ')}"
end
def self.get_pip(machine)
def self.get_pip(machine, pip_install_cmd=DEFAULT_PIP_INSTALL_CMD)
# The objective here is to get pip either by default
# or by the argument passed in. The objective is not
# to circumvent the pip setup by passing in nothing.
# Thus, we stick with the default on an empty string.
# Typecast added in the check for safety.
if pip_install_cmd.to_s.empty?
pip_install_cmd=DEFAULT_PIP_INSTALL_CMD
end
machine.ui.detail I18n.t("vagrant.provisioners.ansible.installing_pip")
machine.communicate.execute "curl https://bootstrap.pypa.io/get-pip.py | sudo python"
machine.communicate.execute pip_install_cmd
end
end

View File

@ -8,13 +8,13 @@ module VagrantPlugins
module RedHat
module AnsibleInstall
def self.ansible_install(machine, install_mode, ansible_version, pip_args)
def self.ansible_install(machine, install_mode, ansible_version, pip_args, pip_install_cmd="")
case install_mode
when :pip
pip_setup machine
pip_setup machine, pip_install_cmd
Pip::pip_install machine, "ansible", ansible_version, pip_args, true
when :pip_args_only
pip_setup machine
pip_setup machine, pip_install_cmd
Pip::pip_install machine, "", "", pip_args, false
else
ansible_rpm_install machine
@ -33,11 +33,11 @@ module VagrantPlugins
machine.communicate.sudo "#{rpm_package_manager} -y --enablerepo=epel install ansible"
end
def self.pip_setup(machine)
def self.pip_setup(machine, pip_install_cmd="")
rpm_package_manager = Facts::rpm_package_manager(machine)
machine.communicate.sudo("#{rpm_package_manager} -y install curl gcc libffi-devel openssl-devel python-crypto python-devel python-setuptools")
Pip::get_pip machine
Pip::get_pip machine, pip_install_cmd
end
end

View File

@ -7,9 +7,9 @@ module VagrantPlugins
module Ubuntu
module AnsibleInstall
def self.ansible_install(machine, install_mode, ansible_version, pip_args)
def self.ansible_install(machine, install_mode, ansible_version, pip_args, pip_install_cmd="")
if install_mode != :default
Debian::AnsibleInstall::ansible_install machine, install_mode, ansible_version, pip_args
Debian::AnsibleInstall::ansible_install machine, install_mode, ansible_version, pip_args, pip_install_cmd
else
ansible_apt_install machine
end

View File

@ -11,6 +11,7 @@ module VagrantPlugins
attr_accessor :install
attr_accessor :install_mode
attr_accessor :pip_args
attr_accessor :pip_install_cmd
def initialize
super
@ -18,6 +19,7 @@ module VagrantPlugins
@install = UNSET_VALUE
@install_mode = UNSET_VALUE
@pip_args = UNSET_VALUE
@pip_install_cmd = UNSET_VALUE
@provisioning_path = UNSET_VALUE
@tmp_path = UNSET_VALUE
end
@ -28,6 +30,7 @@ module VagrantPlugins
@install = true if @install == UNSET_VALUE
@install_mode = :default if @install_mode == UNSET_VALUE
@pip_args = "" if @pip_args == UNSET_VALUE
@pip_install_cmd = "" if @pip_args == UNSET_VALUE
@provisioning_path = "/vagrant" if provisioning_path == UNSET_VALUE
@tmp_path = "/tmp/vagrant-ansible" if tmp_path == UNSET_VALUE
end

View File

@ -32,7 +32,10 @@ module VagrantPlugins
#
# Current limitations:
# - The installation of a specific Ansible version is only supported by
# the "pip" install_mode.
# the "pip" install_mode. Note that "pip" installation also takes place
# via a default command. If pip needs to be installed differently then
# the command can be overwritten by supplying "pip_install_cmd" in the
# config settings.
# - There is no absolute guarantee that the automated installation will replace
# a previous Ansible installation (although it works fine in many cases)
#
@ -51,7 +54,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, config.install_mode, config.version, config.pip_args)
@machine.guest.capability(:ansible_install, config.install_mode, config.version, config.pip_args, config.pip_install_cmd)
end
# This step will also fetch the Ansible version data into related instance variables

View File

@ -0,0 +1,52 @@
require_relative "../../../../../../base"
require Vagrant.source_root.join("plugins/provisioners/ansible/cap/guest/pip/pip")
describe VagrantPlugins::Ansible::Cap::Guest::Pip do
include_context "unit"
subject { VagrantPlugins::Ansible::Cap::Guest::Pip }
let(:iso_env) do
# We have to create a Vagrantfile so there is a root path
env = isolated_environment
env.vagrantfile("")
env.create_vagrant_env
end
let(:machine) { iso_env.machine(iso_env.machine_names[0], :dummy) }
let(:communicator) { double("comm") }
before do
allow(machine).to receive(:communicate).and_return(communicator)
allow(communicator).to receive(:execute).and_return(true)
end
describe "#get_pip" do
describe 'when no pip_install_command argument is provided' do
it "installs pip using the default command" do
expect(communicator).to receive(:execute).with("curl https://bootstrap.pypa.io/get-pip.py | sudo python")
subject.get_pip(machine)
end
end
describe 'when pip_install_command argument is provided' do
it "runs the supplied argument instead of default" do
pip_install_command = "foo"
expect(communicator).to receive(:execute).with(pip_install_command)
subject.get_pip(machine,pip_install_command)
end
it "installs pip using the default command if the argument is empty" do
pip_install_command = ""
expect(communicator).to receive(:execute).with("curl https://bootstrap.pypa.io/get-pip.py | sudo python")
subject.get_pip(machine,pip_install_command)
end
it "installs pip using the default command if the argument is nil" do
expect(communicator).to receive(:execute).with("curl https://bootstrap.pypa.io/get-pip.py | sudo python")
subject.get_pip(machine, nil)
end
end
end
end

View File

@ -32,6 +32,7 @@ describe VagrantPlugins::Ansible::Config::Guest do
inventory_path
limit
pip_args
pip_install_cmd
playbook
playbook_command
provisioning_path

View File

@ -93,6 +93,31 @@ This section lists the _specific_ options for the Ansible Local provisioner. In
sudo pip install --upgrade ansible==2.2.1.0
```
As-is `pip` is installed if needed via a default command which looks like
```shell
curl https://bootstrap.pypa.io/get-pip.py | sudo python
```
This can be problematic in certain scenarios, for example, when behind a proxy. It is possible to override this default command by providing an explicit command to run as part of the config using `pip_install_cmd`. For example:
```ruby
config.vm.provision "ansible_local" do |ansible|
ansible.playbook = "playbook.yml"
ansible.install_mode = "pip"
ansible.pip_install_cmd = "https_proxy=http://your.proxy.server:port curl -s https://bootstrap.pypa.io/get-pip.py | sudo https_proxy=http://your.proxy.server:port python"
ansible.version = "2.2.1.0"
end
```
In this case case `pip` will be installed via the command:
```shell
https_proxy=http://your.proxy.server:port curl -s https://bootstrap.pypa.io/get-pip.py | sudo https_proxy=http://your.proxy.server:port python
```
If `pip_install_cmd` is not provided in the config, then `pip` is installed via the default command.
- `: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: