1

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.

4

1 回答 1

1

解决方案是把 run_once (感谢@ssbarnea):

when: my_app_cmd.rc != 0
run_once: yes
于 2018-01-26T10:44:14.907 回答