Reputation: 3086
I need to install Python pip
via Ansible on a remote server. I do it like this and it work:
- name: Download pip installer
get_url:
url: https://bootstrap.pypa.io/pip/2.7/get-pip.py
dest: /tmp/get-pip.py
- name: Install pip
shell: /usr/bin/python /tmp/get-pip.py
One problem - it have status "changed" every time when I run a playbook. I don't need to install it every time I run playbook.
How can I check and install the pip
module only if it didn't installed before?
Upvotes: 2
Views: 2567
Reputation: 838
This nice guy William Yeh has written a nice playbook exactly for that purpose:
---
# file: tasks/install-pip.yml
# Mini installer for pip; only to enable the Ansible `pip` module.
#
# For full installer, use something like:
#
# - Stouts.python
# - bobbyrenwick.pip
#
# @see https://github.com/gmacon/ansible-pip/blob/variable_executables/tasks/main.yml
#
- name: check to see if pip is already installed
command: "pip --version"
ignore_errors: true
register: pip_is_installed
changed_when: false
- block:
- name: download get-pip.py
get_url: url=https://bootstrap.pypa.io/get-pip.py dest=/tmp
- name: install pip
command: "python /tmp/get-pip.py"
- name: delete get-pip.py
file: state=absent path=/tmp/get-pip.py
when: pip_is_installed.rc != 0
Upvotes: 2
Reputation: 44615
You can easily bypass both tasks by using the creates
parameter which exists for shell
and uri
. It expects a filename which will be checked for existence. If the file exists the task will not be run.
Note: In my below not entirely tested example, I infered that your script installs the binary in /usr/local/bin/pip
. Adapt to the exact installation location if different.
---
- name: Install pip
hosts: all
gather_facts: false
vars:
pip_location: /usr/local/bin/pip
tasks:
- name: Download pip installer
get_url:
url: https://bootstrap.pypa.io/pip/2.7/get-pip.py
dest: /tmp/get-pip.py
creates: "{{ pip_location }}"
- name: Install pip
shell:
cmd: /usr/bin/python /tmp/get-pip.py
creates: "{{ pip_location }}"
References:
Upvotes: 3
Reputation: 12063
Since a system where pip
hasn't been installed reports with
pip --version; echo $?
-bash: pip: command not found
127
you could implement installation and version tests before running the download and installation task.
---
- hosts: test
become: false
gather_facts: false
tasks:
- name: Gather installed pip version, if there is any
shell:
cmd: pip --version | cut -d ' ' -f 2
register: result
failed_when: result.rc != 0 and result.rc != 127
# Since this is a reporting task, it should never change
# as well run and register a result in any case
changed_when: false
check_mode: false
- name: Set default version, if there is no
set_fact:
result:
stdout_lines: "00.0.0"
when: "'command not found' in result.stdout"
- name: Report result
debug:
msg: "{{ result.stdout }}"
check_mode: false
when: result.stdout != "20.3.4"
Resulting into an output of
TASK [Gather installed pip version, if there is any] ***
ok: [test.example.com]
TASK [Report result] ***********************************
ok: [test.example.com] =>
msg: 20.3.4
Further Q&A
Documentation
... just an example add-on with shell operators
- name: Install 'pip' only if it not exist
shell:
cmd: pip --version || /usr/bin/python /tmp/get-pip.py
Upvotes: 3