Automatically Installing and running Ansible Local via Vagrant - vagrant

I am using Vagrant and trying to enable Ansible to work with it. Because I am working in a virtualenv with Python 3.5.0, I have to use Ansible-Local – the "main" Ansible will not run on my host because I am not running Python 2.x.
Regardless, everything mostly works, except that vagrant up does not find Ansible. Here is the output from the call:
==> default: Running provisioner: ansible_local...
default: Installing Ansible...
The Ansible software could not be found! Please verify
that Ansible is correctly installed on your guest system.
If you haven't installed Ansible yet, please install Ansible
on your Vagrant basebox, or enable the automated setup with the
`install` option of this provisioner. Please check
https://docs.vagrantup.com/v2/provisioning/ansible_local.html
for more information.
However, if I use vagrant ssh to access the VM, Ansible is clearly installed:
vagrant#vagrant-ubuntu-trusty-64:~$ ansible --version
ansible 2.0.0.2
config file = /etc/ansible/ansible.cfg
configured module search path = Default w/o overrides
I'm at a loss of what to do. I can run ansible-playbook server.yml, while SSH'd into the server, and it works correctly. However, the whole point of me using Ansible is that I could automatically run it via Vagrant. Here's the relevant portion of my Vagrantfile:
config.vm.provision "ansible_local" do |ansible|
ansible.install = true
ansible.version = "latest"
ansible.sudo = true
ansible.playbook = "server.yml"
end
Any suggestions are greatly appreciated. Thank you!

By bringing the box up in debug mode:
VAGRANT_LOG=debug vagrant up
Shows:
DEBUG ssh: Re-using SSH connection.
INFO ssh: Execute: ansible-galaxy --help && ansible-playbook --help (sudo=false)
DEBUG ssh: stderr: ERROR! Missing required action
DEBUG ssh: stdout: Usage: ansible-galaxy [delete|import|info|init|install|list|login|remove|search|setup] [--help] [options] ...
Options:
-h, --help show this help message and exit
-v, --verbose verbose mode (-vvv for more, -vvvv to enable connection
debugging)
--version show program's version number and exit
DEBUG ssh: Exit status: 5
ansible-galaxy --help is the problem as it expected an action. Because that failed, vagrant thinks that there was a problem with the install.
It looks like this has been fixed on the master branch and will be in the next version.
What you could try is:
# -*- mode: ruby -*-
# vi: set ft=ruby :
$install_ansible = <<SCRIPT
apt-get -y install software-properties-common
apt-add-repository ppa:ansible/ansible
apt-get -y update
apt-get -y install ansible
SCRIPT
Vagrant.configure(2) do |config|
config.vm.box = 'ubuntu/trusty64'
config.vm.provision 'shell', inline: $install_ansible
# Patch for https://github.com/mitchellh/vagrant/issues/6793
config.vm.provision "shell" do |s|
s.inline = '[[ ! -f $1 ]] || grep -F -q "$2" $1 || sed -i "/__main__/a \\ $2" $1'
s.args = ['/usr/bin/ansible-galaxy', "if sys.argv == ['/usr/bin/ansible-galaxy', '--help']: sys.argv.insert(1, 'info')"]
end
config.vm.provision :ansible_local do |ansible|
ansible.sudo = true
ansible.playbook = 'server.yml'
end
end
note: Credit to MasonM for the
following snippet:
# Patch for https://github.com/mitchellh/vagrant/issues/6793
config.vm.provision "shell" do |s|
s.inline = '[[ ! -f $1 ]] || grep -F -q "$2" $1 || sed -i "/__main__/a \\ $2" $1'
s.args = ['/usr/bin/ansible-galaxy', "if sys.argv == ['/usr/bin/ansible-galaxy', '--help']: sys.argv.insert(1, 'info')"]
end
Or another option while waiting for the fix to be released is building vagrant from source.

Related

Vagrant: how to have shell scripts run prior to ansible provisioning?

We are currently running into an issue, with Vagrant, where certain CLI commands need to be run before Ansible provisionning:
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!
curl https://bootstrap.pypa.io/get-pip.py | sudo python
Stdout from the command:
ERROR: This script does not work on Python 2.7 The minimum supported
Python version is 3.7. Please use
https://bootstrap.pypa.io/pip/2.7/get-pip.py instead.
In our Vagrantfile we have added the following, but when we go to provision the shell block does not appear to be called before the Ansible block, so we end up having to vagrant ssh into the container and then run them manually:
config.vm.provision "shell" do |s|
s.inline = "update-alternatives --install /usr/bin/python python /usr/bin/python2 1"
s.inline = "update-alternatives --install /usr/bin/python python /usr/bin/python3 2"
s.inline = "apt install -y python3-setuptools"
end
config.vm.provision "ansible_local" do |ansible|
ansible.compatibility_mode = "2.0"
ansible.install = true
ansible.install_mode = "pip_args_only"
ansible.pip_args = "ansible==#{ANSIBLE_VERSION}"
ansible.playbook = "deploy-local.yml"
ansible.galaxy_role_file = "roles.yml"
ansible.galaxy_roles_path = "/tmp/galaxy_roles"
end
Can anyone suggest how to force sequence of provisioning block?
By default, some debian like distributions, for example Ubuntu 20.04, have a python link to python2. Although version python3 is also present. You need to change this behavior, add a pip3 version if there isn't one and the most important thing is to use ansible.install_mode = "pip3". For example provisioning block will look like this:
# Change link to python3 and install pip3
config.vm.provision "Python version change", before: :all, type: "shell", inline: <<-SHELL
apt update
apt install -y python3-pip && echo Pip3 installation complete.
ln -f /usr/bin/python3 /usr/bin/python && echo Python default version was changed to 3.
SHELL
# Run Ansible from the Vagrant Host
config.vm.provision "ansible_install", after: :all, type: "ansible_local" do |ansible|
ansible.become = true
ansible.playbook = "./stack/ansible/playbook.yml"
ansible.install_mode = "pip3"
ansible.galaxy_role_file = "./stack/ansible/requirements.yml"
ansible.galaxy_roles_path = "/etc/ansible/roles"
ansible.galaxy_command = "sudo ansible-galaxy install --role-file=%{role_file} --roles-path=%{roles_path} --force"
end

Start Vagrant VM and start Node.js script by shell script

I installed StackEdit on Vagrant. I would like to start Vagrant and StackEdit by one click.
I created bash script:
#!/bin/bash
vagrant up
#ssh -p 2222 -i /d/stackedit/.vagrant/machines/default/virtualbox/private_key vagrant#127.0.0.1 -t '/home/vagrant/Code/start_server.sh'
start "C:\Program Files\Mozilla Firefox\firefox.exe" http://stackedit.app:5000
and start_server.sh in VM
if [ $(ps -e|grep node|wc -l) = "0" ] ; then
(export PORT=5000 && node Code/Project/public/stackedit/server.js) &
fi
sleep 5
exit 0
If I run start_server.sh via ssh manualy everything works, but when I try it with ssh in start script - now commented line - server doesn't run.
I tried copy this script to /ect/rc.local, but the result is same.
I tried add #reboot /home/vagrant/Code/start_server.sh to crontab -e too, but without success.
Can anyone help me?
My system is Windows 10. I use Git Bash.
you should put everything in your Vagrantfile
#Run provisioning
You can run your script from Vagrantfile using a shell provisioner
Vagrant.configure("2") do |config|
config.vm.provision "shell", path: "Code/start_server.sh"
end
check, you have some options by default it will run as root so you can change if you want to run your script as vagrant user
Vagrant.configure("2") do |config|
config.vm.provision "shell", path: "Code/start_server.sh", privileged: false
end
and also you can make sure you run your script everytime you boot the VM (by default it runs only once or when calling specifically the provision parameter)
Vagrant.configure("2") do |config|
config.vm.provision "shell", path: "Code/start_server.sh", run: "always"
end
#opening the website after the system is running
Vagrantfile is a ruby script so you can call any command from the file, but it will run the command immediately and in any occasion.
Then, if you want to run after the box is started, you can use the vagrant trigger and do something like
Vagrant.configure(2) do |config|
.....
config.trigger.after :up do |trigger|
trigger.run = {inline: 'system("open", "http://stackedit.app:5000"')
end
end

debugging a vagrant setup bash script

I have a Vagrantfile with a setup script as below. I've run it several times with vagrant up and I know the first few commands work, but later ones I know did not succeed.
Vagrantfile:
# -*- mode: ruby -*-
VAGRANTFILE_API_VERSION = "2"
$setup = <<END
# some bash code
# ...
# something that somehow never runs
sudo chown -R vagrant:vagrant /some/path
END
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "puppetlabs/centos-7.0-64-nocm"
config.vm.define "client", primary: true do |client|
client.vm.hostname = "client.example.com"
client.vm.network :private_network, ip: "192.168.250.10"
client.vm.provision "shell", inline: $setup
end
end
Is there any way to see what errors happen when scripts are run on vagrant up?
I tried vagrant up --debug &> vagrant.log but the output was literally thousands of lines and I couldn't find anything useful (or didn't know what to look for, which is more likely).
echo should do the trick and display messages from your shell file.
echo "running update ..."
sudo apt-get update
echo "running install lib ..."
sudo apt-get install --yes git-all libreadline-dev build-essential curl git m4 python-setuptools ruby texinfo libbz2-dev libcurl4-openssl-dev libexpat-dev libncurses-dev zlib1g-dev
echo "install rvm ..."
curl -L https://get.rvm.io | bash -s stable --ruby=2.0.0
all echo messages will be displayed in the output when running the shell provisioning
If you need to redirect stderr to stdout you can do something like grep * 2>&1 -
ref: http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-3.html
While Frédéric Henri's answer is definitely recommended and helpful, vagrant also comes with some built in debugging help which you can read more about here, but basically you can vagrant up with a debug flag for more information:
vagrant up --debug

vagrant provisioning with ansible error

I'm getting the following error on
==> default: Configuring cache buckets...
==> default: Running provisioner: ansible...
The executable 'ansible-playbook' Vagrant is trying to run was not
found in the PATH variable. This is an error. Please verify
this software is installed and on the path.
I'm using vagrant-cachier plugin for composer vendor caching and ansible is installed. What could be the problem?
As #ydaetskcoR said, you're missing Ansible on the host machine. Alternatively, you can run the playbooks locally, but the provisioner that ships with Vagrant doesn't support that, so you'll have to do it with a shell provisioner:
config.vm.synced_folder "ansible", "/opt/ansible"
config.vm.provision "ansible", type: "shell" do |s|
s.inline = <<SCRIPT
hash ansible-playbook &> /dev/null
if [ $? -eq 0 ]; then
echo Ansible already installed.
else
echo $(date +"%T"): Updating APT database.
apt-get update &> /dev/null
echo $(date +"%T"): Installing Python and pip.
apt-get -y install python-pip python-dev &> /dev/null
echo $(date +"%T"): Installing Ansible via pip.
pip install ansible &> /dev/null
fi
mkdir -p /etc/ansible
hostname > /etc/ansible/hosts
echo $(date +"%T"): Executing Ansible playbook.
ansible-playbook /opt/ansible/playbook.yml --connection=local
SCRIPT
end

Install Oh My Zsh on a Vagrant Box as part of the bootstrap process

I'd like to add Oh My Zsh to my Vagrant bootstrap process, but a straight install isn't working.
via curl:
curl -L http://install.ohmyz.sh | sh
via wget:
wget --no-check-certificate http://install.ohmyz.sh -O - | sh
Found the solution:
# Added zsh shell.
sudo apt-get install zsh
wget --no-check-certificate https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | sh
sudo chsh -s /bin/zsh vagrant
zsh
As an nice addition, so that your terminals don't look too similar on the different boxes
# Change the oh my zsh default theme.
sed -i 's/ZSH_THEME="robbyrussell"/ZSH_THEME="3den"/g' ~/.zshrc
Here's a complete Vagrantfile that installs Oh My Zsh on an Ubuntu 14.04.2 LTS box and sets it as the default shell for standard vagrant user.
This works with Vagrant 1.7.2. (Your milage may vary with different versions.) It uses the directions from the Manual Installation section of the Readme instead of trying to use the automatic scripts.
# -*- mode: ruby -*-
# vi: set ft=ruby :
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Pick a box to use:
config.vm.box = "ubuntu/trusty64"
############################################################
# Oh My ZSH Install section
# Install git and zsh prerequisites
config.vm.provision :shell, inline: "apt-get -y install git"
config.vm.provision :shell, inline: "apt-get -y install zsh"
# Clone Oh My Zsh from the git repo
config.vm.provision :shell, privileged: false,
inline: "git clone git://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh"
# Copy in the default .zshrc config file
config.vm.provision :shell, privileged: false,
inline: "cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc"
# Change the vagrant user's shell to use zsh
config.vm.provision :shell, inline: "chsh -s /bin/zsh vagrant"
############################################################
end
As a bonus, you can do a one time copy of your host machine's .zshrc file to the vagrant box with:
config.vm.provision "file", source: "~/.zshrc", destination: ".zshrc"
(Keep in mind, You may have to figure things that don't work initially because of differences between the host machine and the vagrant box's setups.)
I came here because had a same issue. After seeing some answer and trying it, mostly the zsh & oh-my-zsh got installed as root. The root will set his $SHELL with zsh. What I want is they are installed as user vagrant. The bootstrap was done by root when provisioning. So the logic is try to run install zsh & oh-my-zsh as user. Here is what I did after trying many times until I got what I wanted :
## In Vagrantfile try to call bootstrap.sh
config.vm.provision "shell", path: "bootstrap.sh"
## This is the bootstrap.sh
aptInstl() {
DEBIAN_FRONTEND=noninteractive apt-get install -qq -y $1 > /dev/null
}
install_zsh() {
aptInstl "zsh"
su -l vagrant -s "/bin/sh" \
-c "curl -fsSO https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh; chmod 755 install.sh; ./install.sh --unattended"
chsh -s /bin/zsh vagrant
}
install_miscellaneous() {
apt-get update > /dev/null
apt-get upgrade > /dev/null
for i in curl git; do
aptInstl "$i"
done
}
main() {
install_miscellaneous
install_zsh
}
main
And It works perfectly :)
When you are done try to vagrant ssh it will automatically logged you in with zsh shell and oh-my-zsh. Here is the complete file.

Resources