Ansible - pip not found - ansible

I am getting this error:
TASK [pip] *********************************************************************
failed: [default] (item=urllib3) =>
{"changed": false, "item": "urllib3",
"msg": "Unable to find any of pip2, pip to use. pip needs to be installed."}
Upon a suggestion I run following command:
ansible default -a "which pip"
I get an error:
default | FAILED | rc=1 >>
non-zero return code
So I guess that means no pip installed. I tried installing pip using:
ansible default -a "easy_install pip"
I get the following error:
default | FAILED | rc=2 >>
[Errno 2] No such file or directory
Any ideas?
UPDATE
In play_local.yaml, I have the following task:
- name: Prepare system
hosts: default
become: yes
gather_facts: false
pre_tasks:
- raw: sudo apt-get -y install python python-setuptools python-pip build-essential libssl-dev libffi-dev python-dev easyinstall pip
- file: path=/etc/sudoers.d/ssh-auth-sock state=touch mode=0440
#- lineinfile: line='Defaults env_keep += "SSH_AUTH_SOCK"' path=/etc/sudoers.d/ssh-auth-sock
- replace:
path: /etc/apt/sources.list
regexp: 'br.'
replace: ''
Shouldn't this task install pip?

Seems like pip is not installed, you can use the following task to install it:
- name: Install pip
apt:
name: python-pip
update_cache: yes
state: present

May be pip is hashed. Meaning pip is installed at path x (may be /usr/local/bin/pip), however, cached at path y (may be /usr/bin/pip). You can confirm that from - ansible default -m shell -a ‘type pip’. To resolve this you’ll need to run - ansible default -m shell -a ‘hash -r’.
BTW, you can also use command module instead of shell.

I've just met the same problem on a brand new CentOS 7. Solved through installing setuptools with yum first and then pip with easy_install as below :
ansible default -b -m yum -a "name=python-setuptools state=present"
ansible default -b -m easy_install -a "name=pip state=present"

For Debian Based systems (RUN THIS ON CLIENT SYSTEMS):
first install package python-is-python3 then add alias for pip echo alias pip=pip3 >> ~/.bashrc
I know my solution would be dumb but It works.
# pip-fix.yml
- name: pip fix
hosts: all
become: true
tasks:
- name: install python-is-python3
apt: name=python-is-python3 update_cache=yes state=present
- name: creating alias
shell: echo alias pip=pip3 >> ~/.bashrc
- name: test and upgrade pip
pip: name=pip state=latest
tags:
- packages
run using ansible-playbook pip-fix.yml

Ansible Not finding / Installing Pip
While not using the author's original details, i think this might help them or others.
I was getting the following error for installing pip:
via Ansible:
FAILED! => {"changed": false, "cmd": "/bin/easy_install --upgrade pip", "failed": true, "msg": "Couldn't find index page for 'pip' (maybe misspelled?)
directly on the host:
Searching for pip
Reading https://pypi.python.org/simple/pip/
Couldn't find index page for 'pip' (maybe misspelled?)
Scanning index of all packages (this may take a while)
Reading https://pypi.python.org/simple/
No local packages or download links found for pip
error: Could not find suitable distribution for
Requirement.parse('pip')
I attempted to use the above hash -r answer:
(NOTE: help hash... hash -r == forget all remembered locations)
- name: forget easy_install path
shell: hash -r
become: true
however this was not a solve for me.
I found via another post: 'pip install' fails for every package ("Could not find a version that satisfies the requirement") that this was the final fix:
curl https://bootstrap.pypa.io/get-pip.py | python
or
- name: manually install pip
shell: curl https://bootstrap.pypa.io/pip/2.7/get-pip.py | python
become: true
NOTE: i changed the pip version. Also, there is a better way to do a curl in ansible, this is simply an example
I then followed with the easy_install pip latest. to ensure it was up to date.

below fix worked for me
#ln -s /usr/local/bin/pip /usr/bin/pip

Related

How to use ansible pip executable `/usr/local/bin/python3 -m pip`?

My playbook
- name: "Install python package 'requests'"
pip:
name: requests
executable: /usr/local/bin/python3 -m pip
become: yes
Which errors with:
TASK [Install python package 'requests'] **************************
fatal: [integration]: FAILED! => changed=false
cmd: '''/usr/local/bin/python3 -m pip'' install requests'
msg: '[Errno 2] No such file or directory'
rc: 2
stderr: ''
stderr_lines: <omitted>
stdout: ''
stdout_lines: <omitted>
I didn't install pip or pip3 in the managed node, that is why executable: pip3 would not work.
As per documentation, the recommended way to achieve this is to use the easy_install module in order to make pip available on the managed node, and then, use the builtin module pip, normally.
Please note that the easy_install module can only install Python libraries. Thus this module is not able to remove libraries. It is generally recommended to use the ansible.builtin.pip module which you can first install using community.general.easy_install.
So, in a two tasks:
- name: Install or update pip
community.general.easy_install:
name: pip
state: latest
become: yes
- name: Install python package 'requests'
ansible.builtin.pip:
name: requests
become: yes

How to activate python virtual environment on remote machine with ansible?

I'm learning Vagrant and Ansible, I'm trying to setup a local development environment for a basic flask app in ubuntu20.04 with Nginx.
my vagrantfile looks like this:
Vagrant.configure("2") do |config|
config.vm.define :ubuntuserver do | ubuntuserver |
ubuntuserver.vm.box = "bento/ubuntu-20.04"
ubuntuserver.vm.hostname = "ubuntuserver"
ubuntuserver.vm.provision :ansible do | ansible |
ansible.playbook = "development.yml"
end
ubuntuserver.vm.network "private_network", ip:"10.11.1.105"
ubuntuserver.vm.network "forwarded_port", guest: 80, host: 8080
ubuntuserver.vm.network "public_network", bridge: "en1: Wi-Fi (AirPort)"
ubuntuserver.vm.provider :virtualbox do |vb|
vb.memory = "1024"
end
ubuntuserver.vm.synced_folder "./shared", "/var/www"
end
end
my ansible-playbook like so:
-
name: local env
hosts: ubuntuserver
tasks:
- name: update and upgrade apt packages
become: yes
apt:
upgrade: yes
update_cache: yes
- name: install software properties common
apt:
name: software-properties-common
state: present
- name: install nginx
become: yes
apt:
name: nginx
state: present
update_cache: yes
- name: ufw allow http
become: yes
community.general.ufw:
rule: allow
name: "Nginx HTTP"
- name: installing packages for python env
become: yes
apt:
name:
- python3-pip
- python3-dev
- build-essential
- libssl-dev
- libffi-dev
- python3-setuptools
- python3-venv
update_cache: yes
- name: Create app directory if it does not exist
ansible.builtin.file:
path: /var/www/app
state: directory
mode: '0774'
- name: Install virtualenv via pip
become: yes
pip:
name: virtualenv
executable: pip3
- name: Set python virual env
command:
cmd: virtualenv /var/www/app/ -p python3
creates: "/var/www/app/"
- name: Install requirements
pip:
requirements: /var/www/requirements.txt
virtualenv: /var/www/app/appenv
virtualenv_python: python3
My playbook fails at the next task with error:
- name: Activate /var/www/app/appenv
become: yes
command: source /var/www/app/appenv/bin/activate
fatal: [ubuntuserver]: FAILED! => {"changed": false, "cmd": "source /var/www/app/appenv/bin/activate", "msg": "[Errno 2] No such file or directory: b'source'", "rc": 2}
Rest of the playbook
- name: ufw allow 5000
become: yes
community.general.ufw:
rule: allow
to_port: 5000
- name: Run app
command: python3 /var/www/app/appenv/app.py
From what I understand from this thread, The "source" command must be used from inside the vagrant machine. (I tried solutions from the thread but couldn't get it to work)
If I ssh into the vagrant machine and execute the three last commands of my playbook manually:
source /var/www/app/appenv/bin/activate
sudo ufw allow 5000
python3 /var/www/app/appenv/app.py
my basic flask app is running on port 5000 at the IP set in the vagrantfile 10.11.1.105
My questions are:
How can I get the playbook to work and not have to ssh into the machine to accomplish the same?
Is my approach even correct, knowing that my end goal is to replicate in the vagrant machine a similar environment to what would be the production environment and develop the flask app from my local machine in the synced folder?
to give a maximum of information, if one wants to reproduce this.
I also have a shared/app/appenv/app.py file containing the basic flask app
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "<h1 style='color:blue'>Hello There!</h1>"
if __name__ == "__main__":
app.run(host='0.0.0.0')
and shared/requirements.txt file
wheel
uwsgi
flask
This question was coming from a misconception about python venv.
I thought that in order to install packages inside the virtual env it had to be activated.
for example:
source env/bin/activate
pip install package_name
I understood later that I can install packages in the venv without activating it by doing:
env/bin/pip install package_name
So the solution with ansible is not to activate the venv to install packages but instead
- name: "Install python packages with the local instance of pip"
shell: "{{virtualenv_path}}/bin/pip3 install package_name"
become: no
or better even with the pip module and the packages in a requirements.txt file:
- name: Install project requirements in venv
pip:
requirements: '{{project_path}}/requirements.txt'
virtualenv: '{{virtualenv_path}}'
virtualenv_python: python3
I wrote this article for a Linux computer with Python 3.x. In this scenario, this is your Ansible development machine. First, verify the installed Python version and path:
# check Python version
$ python3 -V
Python 3.6.8
$ which python3
/usr/bin/python3
I recommend setting up a directory for the virtual environment:
$ mkdir python-venv
$ cd !$
Create a new virtual environment
$ python3 -m venv ansible2.9
$ ls
ansible2.9
activate python venv
$ source ansible2.9/bin/activate
(ansible2.9)$ python3 -V
Python 3.6.8
upgrade pip
(ansible2.9)$ python3 -m pip install --upgrade pip
Install Ansible in a virtual environment
(ansible2.9)$ python3 -m pip install ansible==2.9
(ansible2.9)$ which ansible
~/python-venv/ansible2.9/bin/ansible
Verify your new installation:
(ansible2.9)$ ansible --version
ansible 2.9.0
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/devops/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/devops/python-venv/ansible2.9/lib64/python3.6/site-packages/ansible
executable location = /home/devops/python-venv/ansible2.9/bin/ansible
python version = 3.6.8 (default, Jan 09 2021, 10:57:11) [GCC 8.3.1 20191121 (Red Hat 8.3.1-5)]
Install Ansible roles or collections
(ansible2.9)$ ansible-galaxy collection install \
kubernetes.core:==1.2.1 -p collections
Deactivate a Python virtual environment
(ansible2.9)$ deactivate
Create another Python virtual environment for Ansible 3.0
$ python3 -m venv ansible3.0
$ ls -1
ansible2.9
ansible3.0
$ source ansible3.0/bin/activate
(ansible3.0)$ which python
~/python-venv/ansible3.0/bin/python
(ansible3.0)$ python3 -m pip install --upgrade pip
(ansible3.0)$ python3 -m pip install ansible==3.0

ansible throwing error when using pip command

When I am trying to run pip command through ansible I land up in error.
{"changed": false, "msg": "Unable to find any of pip to use. pip needs to be installed."}
When I debugged on my machine I found pip was installed in latest version. I realized my file uses sudo to run the pip.
So if I do which pip
I get the path of pip but if I do sudo which pip I get nothing.
I don't know how to change my file so instead of sudo it take
- name: "Allow newuser for new super user without SUDO password for using rsync:"
lineinfile:
path: /etc/sudoers
state: present
insertafter: '^%sudo'
line: "{{ user }} ALL=(ALL:ALL) NOPASSWD: /usr/bin/rsync"
- pip:
name: opencv-python
state: forcereinstall
executable: pip
I have no idea how to fix this issue
At the remote host find out which pip is used by the remote user. Use the executable and become the remote user. For example,
- name: Install opencv-python
become_user: admin
become: true
pip:
name: opencv-python
state: forcereinstall
executable: /home/admin/.local/bin/pip
See Becoming an Unprivileged User. Pipelining should solve the problems of becoming an unprivileged user.
shell> grep pipe ansible.cfg
pipelining = true
Notes
Whatever you install by pip this way will be available to this particular remote user only.
Preferably distro packages should be used. For example
shell> apt-cache search python-opencv
python-opencv - Python bindings for the computer vision library
python-opencv-apps - opencv_apps Robot OS package - Python 2 bindings
See The pip module isn't always idempotent #28952 and the Conclusions in particular.

How to run apt update and upgrade via Ansible shell

I'm trying to use Ansible to run the following two commands:
sudo apt-get update && sudo apt-get upgrade -y
I know with ansible you can use:
ansible all -m shell -u user -K -a "uptime"
Would running the following command do it? Or do I have to use some sort of raw command
ansible all -m shell -u user -K -a "sudo apt-get update && sudo apt-get upgrade -y"
I wouldn't recommend using shell for this, as Ansible has the apt module designed for just this purpose. I've detailed using apt below.
In a playbook, you can update and upgrade like so:
- name: Update and upgrade apt packages
become: true
apt:
upgrade: yes
update_cache: yes
cache_valid_time: 86400 #One day
The cache_valid_time value can be omitted. Its purpose from the docs:
Update the apt cache if its older than the cache_valid_time. This
option is set in seconds.
So it's good to include if you don't want to update the cache when it has only recently been updated.
To do this as an ad-hoc command you can run:
$ ansible all -m apt -a "upgrade=yes update_cache=yes cache_valid_time=86400" --become
ad-hoc commands are described in detail here
Note that I am using --become and become: true. This is an example of typical privilege escalation through Ansible. You use -u user and -K (ask for privilege escalation password). Use whichever works for you, this is just to show you the most common form.
Just to add a flavour on the answer. This one is an executable playbook in all the hosts specified in your inventory file.
- hosts: all
become: true
tasks:
- name: Update and upgrade apt packages
apt:
upgrade: yes
update_cache: yes
cache_valid_time: 86400
Using Ubuntu 16.04, I did a little adjustement:
- name: Update and upgrade apt packages
become: true
apt:
update_cache: yes
upgrade: 'yes'
I juste put the upgrade yes between apostrophe to avoid un annoying warning:
[WARNING]: The value True (type bool) in a string field was converted to u'True' (type string). If this does
not look like what you expect, quote the entire value to ensure it does not change.
At 2020, I would like just to comment into the original answer, but no enough reputation at that time...
Ref:
The value True (type bool) in a string field was converted to u'True' (type string)
We use the following command to update and upgrade all packages :
ansible all -m apt -a "name='*' state=latest update_cache=yes upgrade=yes" -b --become-user root

Convert Ansible command to pip task

I'd like to convert the following to a Ansible pip task:
- name: install packages and setup profile 3
shell: pip install --user vex
I do not see anything in the Ansible documentation for installing for user.
You can use the pip module with extra_args parameter:
- name: install packages and setup profile 3
pip:
name: vex
state: present
extra_args: --user
Ansible passes the value given in the parameter directly to the pip command.

Resources