I have ansible role which have task delegated to localhost:
- name: Test role
hosts: my_hosts
gather_facts: no
tasks:
- name: Register remote hosts
include_role: name=register_remote_hosts
delegate_to: localhost
The Role register_remote_systems must work for every host in my_hosts, but must be ran from the box where Ansible is invoked, that is why there is delegate_to.
The role register_remote_hosts checks for a specific application on localhost and if one is not installed it creates virtual environment and then installs it:
- name: Check if my_app is installed system-wide
shell: |
my_app --version >/dev/null 2>&1
register: my_app_cmd
failed_when: my_app_cmd.rc not in [0, 127]
- name: Install My App
block:
- name: Create temporary directory for my_app
tempfile:
state: directory
suffix: my_app
register: my_app_temp
- name: Create virtual environment
command: virtualenv "{{ my_app_temp.path }}"
- name: Install my_app
pip:
name: my_app
state: latest
virtualenv: "{{ my_app_temp.path }}"
virtualenv_site_packages: yes
- name: Set Virtual Environment variable
set_fact:
venv_activate: "source {{ my_app_temp.path }}/bin/activate"
when: my_app_cmd.rc != 0
- name: Use my_app
shell: |
{{ venv_activate | default('echo "Using my_app from system path"') }}
my_app --version
Everything works great, but if there are many hosts in my_hosts then a lot of venvs are being created.
What would be the best approach to create role which is reusing same venv with my_app installed. Note that role is included in many different playbooks and I do not want to write additional role included in every playbook where "Register remote hosts" included role is used. There is of course concurrency problem of creating venv prior to using that in other playbooks.
Above solution works and I can live with it, but maybe there are nicer design patterns for such problems in Ansible.