Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Ansible, run only one item in a loop based on a variable

Tags:

ansible

In my Ansible playbook I set up a number of websites on one server. Each website has some configuration set in an apps variable:

apps:
  - name: 'app1'
    git_repo: 'https://github.com/philgyford/app1.git'
  - name: 'app2'
    git_repo: 'https://github.com/philgyford/app2.git'

Then certain tasks are run in a loop for every app/site:

- name: Set up git repos for apps
  git:
    repo: '{{ item.git_repo }}'
    version: 'master'
    dest: "/webapps/{{ item.name }}"
    accept_hostkey: yes
  with_items: apps

That's all fine. But ideally I'd like to be able to run the playbook and only run these tasks for a specific app.

One way would be to pass in --extra-vars "app=app1" on the command line. In the playbook I'd set a default value for app of false. And then on every app-related task add:

  when: item.name == app or app == false

This should work, but it seems laborious and error-prone to have to add that to every single task. Is there a more elegant way that avoids so much repetition?

like image 564
Phil Gyford Avatar asked Mar 13 '23 01:03

Phil Gyford


1 Answers

You can filter lists with the selectattr filter like so:

apps | selectattr('name', 'match', app)

Beside your apps definition you could have a filtered list, which defaults to the full list:

vars:
  apps:
    - name: 'app1'
      git_repo: 'https://github.com/philgyford/app1.git'
    - name: 'app2'
      git_repo: 'https://github.com/philgyford/app2.git'

  active_apps: "{{ apps if app is not defined else apps | selectattr('name', 'match', app) | list }}"

Then in your loop you would loop over active_apps instead and no further condition is required.

- name: Set up git repos for apps
  git:
    repo: '{{ item.git_repo }}'
    version: 'master'
    dest: "/webapps/{{ item.name }}"
    accept_hostkey: yes
  with_items: active_apps

The match filter used in selectattr actually takes a regular expression. So you could provide very detailed expressions which apps to process.

--extra-vars "app=app1"
--extra-vars "app=app[12]"
--extra-vars "app=app.*"
--extra-vars "app=app1|app2"
...

But be careful with this. --extra-vars "app=app1" would also match app10 etc.

like image 159
udondan Avatar answered Apr 06 '23 12:04

udondan