4

I have a playbook which calls some roles which are skipped. For illustration, I have created a dummy playbook with dummy roles. Everyone of these roles is skipped.

---
- hosts: localhost
  connection: local
  gather_facts: false

  roles:
     - { role: dummy, when: foo | default(false) }
     - { role: dummy, when: foo | default(false) }
     - { role: dummy, when: foo | default(false) }
     - { role: dummy, when: foo | default(false) }
     - { role: dummy, when: foo | default(false) }

and a role dummy

---
- name: "pause 5"
  pause:
    seconds: "5"
- name: "pause 5"
  pause:
    seconds: "5"
- name: "pause 5"
  pause:
    seconds: "5"
- name: "pause 5"
  pause:
    seconds: "5"
- name: "pause 5"
  pause:
    seconds: "5"

with role dependencies:

---
allow_duplicates: yes
dependencies:
    - { role: dummy2, when: false }
    - { role: dummy2, when: false }
    - { role: dummy2, when: false }

Also, dummy2 just does a pause:

---
- name: "pause 5"
  pause:
    seconds: "5"
---
- name: "pause 5"
  pause:
    seconds: "5"

Using this config, there are 5 calls to role dummy, which has 5 tasks and 3 role dependencies with 2 tasks. So alltogether, 55 tasks are skipped 5*(5*3*2), which takes about 2,5 seconds in my VM. If there are more skipped roles, it takes linearly more time.

Maybe it is not a great design to have many skipped roles, but is there any way to speed up these skipped tasks without re-writing everything?

user140547
  • 7,750
  • 3
  • 28
  • 80

2 Answers2

2

Unfortunately due to how ansible handles skipping tasks there are no easy ways to do it. Some options you might try out:

  • Add stdout_callback = skippy to your ansible config (available since 2.0). This will make the logging not log the skipped tasks, which makes the output nicer, and might make the run faster as well. Note that this is a global setting, so if you do want to log some of the skipped task this is not the best idea to use.
  • Move your roles into separate playbooks, and have a main ansible playbook simply calling ansible-playbook command again on these separate playbooks. In this case a skipped call will entirely skip everything, but you will need to handle errors inside these calls separately, as well as figure out a way to propagate your command line parameters into these separate calls
SztupY
  • 10,291
  • 8
  • 64
  • 87
1

If you're on Ansible 2.0 or later, you could use a - block: that will fail when foo is true, and a rescue: that will run your tasks when the block fails.

---
- hosts: localhost
  connection: local
  gather_facts: false
  tasks:

    - block:
        - name: "Fail when foo is true"
          fail:
          when:
            - foo is defined
            - foo
      rescue:
        - name: "Run dummy  role if fail task failed"
          include_role:
            name: dummy

    - block:
        - name: "Fail when foo is true"
          fail:
          when:
            - foo is defined
            - foo
      rescue:
        - name: "Run dummy role if fail task failed"
          include_role:
            name: dummy

You'll end up with some scary "failures" when the role is triggered, but it should eliminate lots of "skipped" tasks.

user187557
  • 843
  • 7
  • 6
  • Your solution does work very well thank you!! I've combined it with the `full_skip` stdout callback module. No more scary "failures"! – tehmoon Nov 20 '17 at 20:28
  • Actually the only drawback is that `include_role`'s option `allow_duplicate won't work. – tehmoon Nov 20 '17 at 22:25