I am asking for help with a problem of deploying multiple versions (different variables) of the app with the same role run from one playbook.

We have an app with multiple product families, which are different code versions. Each version has separate uWSGI vassal config and Nginx virtualhost config(/api/v2, /api/v3, ...).

The desired state would be to run playbook and configure the server with all versions specified.

Sadly, ansible's `import_role/import_tasks` can't be used with `with_items`, so `include_role/include_tasks` must be used (pitty because they do not honor role tags).

The `include_role` method would not be the biggest problem, but we use handlers to notify **uWSGI touch to reload** - on a code change, link change, virtualenv change, app\_config change, ...).  

But when using loop (`with_items`), the variables passed from the loop does not correctly propagate to **handlers**.

I tried this scenarios

### playbook.yml - with\_items loop inside the playbook

PROBLEM: Handler is run only for the first iteration of the loop.

```
#!/usr/bin/env ansible-playbook

# HAndler is run only once, from first notifier
- hosts: localhost
  gather_facts: no
  vars:
    app_root: "/tmp/test_ansible"
    app_versions:
      - app_product_family: 1
        app_release: "v1.0.2"
      - app_product_family: 3
        app_release: "v4.0.7"
  tasks:
   - name: Deploy multiple versions of app
     include_role:
       name: app
     with_items: "{{ app_versions }}"
     loop_control:
       loop_var: app_version
     vars:
       app_product_family: "{{ app_version.app_product_family }}"
       app_release: "{{ app_version.app_release }}"
     tags:
       - app
       - app_debug

```

### playbook\_v2.yml - with\_items loop inside role task

PROBLEM: Handler is run with the default value from "Defaults"

```
#!/usr/bin/env ansible-playbook

- hosts: localhost
  gather_facts: no
  roles:
    - app_v2
  vars:
    app_v2_root: "/tmp/test_ansible_v2"
    app_v2_versions:
      - app_v2_product_family: 1
        app_v2_release: "v1.0.2"
      - app_v2_product_family: 3
        app_v2_release: "v4.0.7"

```

Tasks `roles/app_v2/main.yml`

```
---
# Workaround because import_tasks can't be run with_items
- include_tasks: deploy.yml
  when: app_v2_versions
  with_items: "{{ app_v2_versions }}"
  loop_control:
    loop_var: app_v2
  vars:
    app_v2_product_family: "{{ app_v2.app_v2_product_family }}"
    app_v2_release: "{{ app_v2.app_v2_release }}"
  tags:
    - app_v2
    - app_v2_deploy
...

```

---

One idea was about writing a separate role for each product family, but they share **nginx** and **uWSGI**, so it will be lots of copy-pasting and sharing tasks (so tags would not work properly).  

For now, I solved it with shell script wrapper, but this is not an ideal solution and does not work from Ansible tower.

[Sample repo](https://github.com/mmitucha/ansible_with_items_handlers) with tasks to reproduce problem (tested with ansible 2.4, 2.5, 2.6)

Any ideas & recommendations are very welcome.