I have this scenario in Vagrant where I wanted to patch how the ansible is being installed on RHEL 8 (because of certain issues with absence of packages missing due to repository setup) using ansible_local plugin. So here's the thing. Instead, I wanted to use pip3 (though I know I can use pip using ansible_local module but still it errs after that due to absence of certain repository so I figure out a way to fix it).
In my Vagrantfile, I have these lines as such,
.....
node.vm.provision "ansible_local" do |ansible|
ansible.playbook = ansible_playbook
ansible.verbose = true
ansible.install = true
## Actually this line doesn't suffice my problem since it still errs as pip requires other packages. Please check the *.rb file below
if i == 100
ansible.install_mode = "pip"
ansible.version = "2.9"
#ansible.ansible_rpm_install = Foo
end
end
...
.....
But because using pip still fails, so I end up changing the file /opt/vagrant/embedded/gems/2.2.9/gems/vagrant-2.2.9/plugins/provisioners/ansible/cap/guest/redhat/ansible_install.rb
and what I did is this way,
cap/guest/redhat/ansible_install.rb
require_relative "../facts"
require_relative "../pip/pip"
module VagrantPlugins
module Ansible
module Cap
module Guest
module RedHat
module AnsibleInstall
def self.ansible_install(machine, install_mode, ansible_version, pip_args, pip_install_cmd = "")
case install_mode
when :pip
pip_setup machine, pip_install_cmd
Pip::pip_install machine, "ansible", ansible_version, pip_args, true
when :pip_args_only
pip_setup machine, pip_install_cmd
Pip::pip_install machine, "", "", pip_args, false
else
// My added part as a quick fix/solution
if machine.config.vm.box == "generic/rhel8"
ansible_rpm_install_rhel8 machine
elsif
ansible_rpm_install machine
end
end
end
private
def self.ansible_rpm_install(machine)
rpm_package_manager = Facts::rpm_package_manager(machine)
epel = machine.communicate.execute "#{rpm_package_manager} 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'
end
machine.communicate.sudo "#{rpm_package_manager} -y --enablerepo=epel install ansible"
end
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_install_cmd
end
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_install_cmd
end
// My added part as a quick fix/solution
def self.ansible_rpm_install_rhel8(machine)
rpm_package_manager = Facts::rpm_package_manager(machine)
epel = machine.communicate.execute "#{rpm_package_manager} 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'
end
machine.communicate.sudo "dnf -y update; dnf -y install python3 python3-pip; pip3 install ansible"
end
end
end
end
end
end
end
So I added a method self.ansible_rpm_install_rhel8(machine)
and did an if..elsif
as a solution when box name is "generic/rhel8"
. This works perfect actually on my end. However, I don't like this approach i.e. changing the file /opt/vagrant/embedded/gems/2.2.9/gems/vagrant-2.2.9/plugins/provisioners/ansible/cap/guest/redhat/ansible_install.rb
because once it changes or version upgrades, this will be gone. Is there any better way that I can just do this only inside Vagrantfile such that perhaps overriding or extending the class itself? I have no idea how to do this.
Any ideas are welcome.
Thank you!
You can use multiple provisioning sections next one another which will be executed in the order as you defined them in your Vagrantfile
.
Instead of patching a plugin, try to prepare your ansible execution accordingly.
Before executing the provisioning part for ansible, execute a shell provisioning as follows:
Vagrant.configure("2") do |node|
# ...
node.vm.provision :shell, path: "fix_repo_and_add_packages.sh"
node.vm.provision "ansible_local" do |ansible|
ansible.playbook = ansible_playbook
ansible.verbose = true
ansible.install = true
## Actually this line doesn't suffice my problem since it still errs as pip requires other packages. Please check the *.rb file below
if i == 100
ansible.install_mode = "pip"
ansible.version = "2.9"
#ansible.ansible_rpm_install = Foo
end
end
end
Your fix_repo_and_add_packages.sh
contains the setup of the missing repos and here you can add packages as well.
For more information about shell provisioning, you can find in the doc