Mark
Mark

Reputation: 12565

Conditional Ansible roles fail when already executed

I have a role that I would like to execute multiple times, each execution with a different var. However, I would also like some of those executions to be conditional.

Here is a main.yml:

- hosts: localhost
  roles:
    - { role: test, test_files_group: 'a'}
    - { role: test, test_files_group: 'b', when: False}

Here is the main.yml from the 'test' role (roles/test/tasks/main.yml):

- name: List files
  command: "find . ! -path . -type f"
  args:
    chdir: "{{ role_path }}/files/{{ test_files_group }}"
  register: files
- debug: var=files.stdout_lines

- name: do something with the files
  shell: "echo {{ item }}"
  with_items: "{{ files.stdout_lines }}"

And here is part of the ansible-playbook command output:

TASK [test : List files] 

*******************************************************
changed: [localhost]

TASK [test : debug] ************************************************************
ok: [localhost] => {
    "files.stdout_lines": [
        "./testfile-a"
    ]
}

TASK [test : do something with the files] **************************************
changed: [localhost] => (item=./testfile-a)

TASK [test : List files] *******************************************************
skipping: [localhost]

TASK [test : debug] ************************************************************
skipping: [localhost]

TASK [test : do something with the files] **************************************
fatal: [localhost]: FAILED! => {"failed": true, "msg": "'dict object' has no attribute 'stdout_lines'"}

Everything works for 'a' as expected, but then the do something with the files task is executed for b, even though I set when: False.

I feel like I'm missing something - what I'm wanting is for everything in roles/test/tasks/main.yml to be executed with the test_files_group var set accordingly, or not at all. What am I doing wrong? :)

Upvotes: 1

Views: 754

Answers (1)

Konstantin Suvorov
Konstantin Suvorov

Reputation: 68319

You may want to read how when works with includes and roles.

In your case, when: false is attached to every task in the second run, so you have:

- name: List files
  command: "find . ! -path . -type f"
  args:
    chdir: "{{ role_path }}/files/{{ test_files_group }}"
  register: files
  when: false

- debug: var=files.stdout_lines
  when: false

- name: do something with the files
  shell: "echo {{ item }}"
  with_items: "{{ files.stdout_lines }}"
  when: false

1st and 2nd tasks are skipped (see your output), and in the the 3rd task when statement is applied to every iteration, but... at first Ansible tries to evaluate with_items: "{{ files.stdout_lines }}" and fails to do so, because List files task is skipped, so there are no files.stdout_lines.

If you want to fix this, use default for loop argument, e.g.:

with_items: "{{ files.stdout_lines | default([]) }}"

But I'd recommend to refactor your code and don't use "conditionals" with roles.

Upvotes: 2

Related Questions