2
votes

I need get list of all tasks from ansible playbook and show them.

My problem is conditions like ansible_os_family == "Debian" not executing. I see all tasks (like ansible-playbook rplaybooks/main.yml --list-task). But I want only those that will be executed.

I see two ways:

  1. I will check when to current ansible_os_family. I don't know how to get it?
  2. I will find way inside python-ansible execute this conditions

I created class, that allow to get playbook tasks

playbook.py:

import sys
import os
import stat
import json

import ansible.playbook
import ansible.constants as C
import ansible.utils.template
from ansible import errors
from ansible import callbacks
from ansible import utils
from ansible.color import ANSIBLE_COLOR, stringc
from ansible.callbacks import display



if __name__ !='__main__':
            logging.basicConfig(format = u'%(levelname)-8s [%(asctime)s] %(message)s', level = logging.DEBUG, filename = u'/var/log/rderole.log')
class PyPlaybook(object):
    __filtered_tags=['all']
    def _add_inventory(self,hosts=["127.0.0.1"],params={}):
        """ create inventory obj and add it to params """
        playbook=params["playbook"]
        inventory=ansible.inventory.Inventory(hosts)
        inventory.set_playbook_basedir(os.path.dirname(playbook))

        stats = callbacks.AggregateStats()
        playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY)
        runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY)

        params["inventory"]=inventory
        params["stats"]=stats
        params["callbacks"]=playbook_cb
        params["runner_callbacks"]=runner_cb
        return params


    def _playbook_for_hosts(self,hosts=["127.0.0.1"],params={}):
        """ return playbook object with inventory """
        # interface to Playbook class
        """pb=ansible.playbook.PlayBook(
            playbook         = playbook,
            host_list        = host_list,
            module_path      = module_path,
            forks            = forks ,
            timeout          = timeout,
            remote_user      = remote_user,
            remote_pass      = remote_pass,
            sudo_pass        = sudo_pass,
            remote_port      = remote_port,
            transport        = transport,
            private_key_file = private_key_file,
            callbacks        = callbacks,
            runner_callbacks = runner_callbacks,
            stats            = stats,
            sudo             = sudo,
            sudo_user        = sudo_user,
            extra_vars       = extra_vars,
            only_tags        = only_tags,
            skip_tags        = skip_tags,
            subset           = subset,
            inventory        = inventory,
            check            = check,
            diff             = diff,
            any_errors_fatal = any_errors_fatal,
            su               = su,
            su_user          = su_user,
            su_pass          = su_pass ,
            vault_password   = vault_password,
            force_handlers   = force_handlers,
            )"""

        playbook_params=self._add_inventory(hosts,params)
        pb=ansible.playbook.PlayBook(**playbook_params)
        return pb
    def get_tags(self,hosts=["127.0.0.1"],params={}):
        pb=self._playbook_for_hosts(hosts,params)
        playnum = 0
        tags_array={}
        for (play_ds, play_basedir) in zip(pb.playbook, pb.play_basedirs):
            playnum += 1
            play = ansible.playbook.Play(pb, play_ds, play_basedir)
            label = play.name
            matched_tags, unmatched_tags = play.compare_tags(pb.only_tags)
            # Remove skipped tasks
            matched_tags = matched_tags - set(pb.skip_tags)

            unmatched_tags.discard('all')
            unknown_tags = ((set(pb.only_tags) | set(pb.skip_tags)) -
                            (matched_tags | unmatched_tags))

            if unknown_tags:
                continue
            print '  play #%d (%s):' % (playnum, label)

            for task in play.tasks():
                if (set(task.tags).intersection(pb.only_tags) and not
                    set(task.tags).intersection(pb.skip_tags)):
                    if getattr(task, 'name', None) is not None:
                        # meta tasks have no names
                        print ' %s   %s %s' % (task.tags,task.name,task.when)

                        for task_tag in task.tags:
                            #print '>> %s   %s' % (task_tag,task.name)
                            try:
                                tags_array[task_tag].append(task.name)
                            except:
                                tags_array[task_tag]=[]
                                tags_array[task_tag].append(task.name)
            try:
                for tag in self.__filtered_tags:
                    try:
                        del tags_array[tag]
                    except:
                        pass
            except:
                pass
            print json.dumps(tags_array, sort_keys=True, indent=4, separators=(',', ': '))

            return tags_array



if __name__ =='__main__':
    p=PyPlaybook()
    options={'playbook':'/playbooks/rde/main.yml','subset': None,  'private_key_file': None,  'skip_tags': None, 'diff': False, 'check': False, 'remote_user': 'root', 'forks': 5,   'transport': 'local', 'timeout': 10, 'module_path': None}
    #'only_tags':['base'], 'skip_tags':['base']
    #p.run_playbook(["127.0.0.1"],options)
    p.get_tags(["127.0.0.1"],options)

/playbooks/rde/main.yml:

- include: debian.yml 
  when: "ansible_os_family == 'Debian'"
- include: redhat.yml 
  when: "ansible_os_family == 'RedHat'"

redhat.yml

---
- name: Install x2go application RedHat
  yum: name=x2goserver state=present

  when: ansible_os_family == "RedHat"
  tags:
    - remote-access-x2go

debian.yml

---
- name: Add x2go repository
  apt_repository: repo='deb http://ppa.launchpad.net/x2go/stable/ubuntu precise main' state=present
  apt_repository: repo='deb-src http://ppa.launchpad.net/x2go/stable/ubuntu precise main' state=present
  when: ansible_os_family == "Debian"
  tags:
    - remote-access-x2go
- name: Install x2go application
  apt: name=x2goserver update_cache=yes
  apt: name=x2goserver-xsession update_cache=no
  when: ansible_os_family == "Debian"
  tags:
    - remote-access-x2go

python playbook.py

  play #1 (RDE Role):
 ['all', 'remote-access-x2go']   Add x2go repository jinja2_compare ansible_os_family == "Debian"
 ['all', 'remote-access-x2go']   Install x2go application jinja2_compare ansible_os_family == "Debian"
 ['all', 'remote-access-x2go']   Install x2go application RedHat jinja2_compare ansible_os_family == "RedHat"
{   
    "remote-access-x2go": [
        "Add x2go repository",
        "Install x2go application",
        "Install x2go application RedHat"
    ]
}
2
What do you mean by get all tasks and show them? Do you mean you just want to print names of all tasks? or you want to print the filtered list of tasks? - Kashyap
@thekashyap I want all tasks that will be executed. It's less then ansible-playbook main.yml --list-task. In another words I want ansible-playbook --list-task that support condition execution. - Valeriy Solovyov

2 Answers

1
votes

I don't think that's possible. Evaluation of when clauses is considered part of task-execution itself. Only way would be to hack the code.

Perhaps post the question in ansible group where I expect you'll get a more confident yes/no answer.

0
votes

Instead using when, you should include the file directly, e.g.

- include: "{{ ansible_os_family }}.yml"

And make sure you've the relevant files in place for supported systems.

Check also: Define Ansible variable in a role with OS specific default which can be easily overridden