Running ansible-playbook using Python API

前端 未结 6 1621
余生分开走
余生分开走 2020-12-04 14:47

How can I run a playbook in python script? What is the equivalent of the following using ansible module in python:

ansible -i hosts dbservers -m setup
ansibl         


        
相关标签:
6条回答
  • 2020-12-04 15:00

    Ansible provides the ansible-runner Python package (PyPI, GitHub), which can be used for this.

    Usage example from the documentation:

    import ansible_runner
    r = ansible_runner.run(private_data_dir='/tmp/demo', playbook='test.yml')
    print("{}: {}".format(r.status, r.rc))
    # successful: 0
    for each_host_event in r.events:
        print(each_host_event['event'])
    print("Final status:")
    print(r.stats)
    
    0 讨论(0)
  • 2020-12-04 15:04

    I have answered the question here Posting this here cause posting links is discouraged in the community. Hope it helps.

    The documentation is surprisingly lacking and you'll have to get started here

    That being said, here is a quick script I hacked together that manages to run a playbook.

    #!/usr/bin/env python
    
    import os
    import sys
    from collections import namedtuple
    
    from ansible.parsing.dataloader import DataLoader
    from ansible.vars.manager import VariableManager
    from ansible.inventory.manager import Inventory
    from ansible.executor.playbook_executor import PlaybookExecutor
    
    loader = DataLoader()
    
    inventory = Inventory(loader=loader, sources='/home/slotlocker/hosts2')
    variable_manager = VariableManager(loader=loader, inventory=inventory)
    playbook_path = '/home/slotlocker/ls.yml'
    
    if not os.path.exists(playbook_path):
        print '[INFO] The playbook does not exist'
        sys.exit()
    
    Options = namedtuple('Options', ['listtags', 'listtasks', 'listhosts', 'syntax', 'connection','module_path', 'forks', 'remote_user', 'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', 'verbosity', 'check','diff'])
    options = Options(listtags=False, listtasks=False, listhosts=False, syntax=False, connection='ssh', module_path=None, forks=100, remote_user='slotlocker', private_key_file=None, ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=True, become_method='sudo', become_user='root', verbosity=None, check=False, diff=False)
    
    variable_manager.extra_vars = {'hosts': 'mywebserver'} # This can accomodate various other command line arguments.`
    
    passwords = {}
    
    pbex = PlaybookExecutor(playbooks=[playbook_path], inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords)
    
    results = pbex.run()
    
    0 讨论(0)
  • 2020-12-04 15:11

    Just a quick code update that works on 2.8.3,

    from ansible import context
    from ansible.cli import CLI
    from ansible.module_utils.common.collections import ImmutableDict
    from ansible.executor.playbook_executor import PlaybookExecutor
    from ansible.parsing.dataloader import DataLoader
    from ansible.inventory.manager import InventoryManager
    from ansible.vars.manager import VariableManager
    
    loader = DataLoader()
    
    context.CLIARGS = ImmutableDict(tags={}, listtags=False, listtasks=False, listhosts=False, syntax=False, connection='ssh',
                        module_path=None, forks=100, remote_user='xxx', private_key_file=None,
                        ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=True,
                        become_method='sudo', become_user='root', verbosity=True, check=False, start_at_task=None)
    
    inventory = InventoryManager(loader=loader, sources=('/xxx/inventory_file',))
    
    variable_manager = VariableManager(loader=loader, inventory=inventory, version_info=CLI.version_info(gitinfo=False))
    
    pbex = PlaybookExecutor(playbooks=['/xxx/playbook.yml'], inventory=inventory, variable_manager=variable_manager, loader=loader, passwords={})
    
    results = pbex.run()
    
    0 讨论(0)
  • 2020-12-04 15:17

    Based on vigilander's answer, I took the liberty to upload a pkg to pypi and now you can use this simple ansible runner:

    Just pip install ansible-playbook-runner and run:

    from ansible_playbook_runner import Runner
    
    Runner(['inventory_path'], 'playbook_path').run()
    
    0 讨论(0)
  • 2020-12-04 15:18

    Deprecation Notice: This post doesn't work as of ansible 2. The API was changed.

    This covered in the Ansible documentation under "Python API."

    For example, ansible -i hosts dbservers -m setup is implemented via:

    import ansible.runner
    
    runner = ansible.runner.Runner(
       module_name='setup',
       module_args='',
       pattern='dbservers',
    )
    dbservers_get_facts = runner.run()
    

    There are a bunch of non-documented parameters in the __init__ method of Runner (from ansible.runner). There's too many to list inline, but I've included some of the parameters in this post as a guess to what you're specifically looking for.

    class Runner(object):
        ''' core API interface to ansible '''
    
        # see bin/ansible for how this is used...
    
        def __init__(self,
            host_list=C.DEFAULT_HOST_LIST,      # ex: /etc/ansible/hosts, legacy usage
            module_path=None,                   # ex: /usr/share/ansible
            module_name=C.DEFAULT_MODULE_NAME,  # ex: copy
            module_args=C.DEFAULT_MODULE_ARGS,  # ex: "src=/tmp/a dest=/tmp/b"
            ...
            pattern=C.DEFAULT_PATTERN,          # which hosts?  ex: 'all', 'acme.example.org'
            remote_user=C.DEFAULT_REMOTE_USER,  # ex: 'username'
            remote_pass=C.DEFAULT_REMOTE_PASS,  # ex: 'password123' or None if using key
            remote_port=None,                   # if SSH on different ports
            private_key_file=C.DEFAULT_PRIVATE_KEY_FILE, # if not using keys/passwords
            sudo_pass=C.DEFAULT_SUDO_PASS,      # ex: 'password123' or None
            ...
            sudo=False,                         # whether to run sudo or not
            sudo_user=C.DEFAULT_SUDO_USER,      # ex: 'root'
            module_vars=None,                   # a playbooks internals thing
            play_vars=None,                     #
            play_file_vars=None,                #
            role_vars=None,                     #
            role_params=None,                   #
            default_vars=None,                  #
            extra_vars=None,                    # extra vars specified with he playbook(s)
            is_playbook=False,                  # running from playbook or not?
            inventory=None,                     # reference to Inventory object
            ...
            su=False,                           # Are we running our command via su?
            su_user=None,                       # User to su to when running command, ex: 'root'
            su_pass=C.DEFAULT_SU_PASS,
            vault_pass=None,
            ...
            ):
    

    For instance, the above command that specifies a sudo user and pass would be:

    runner = ansible.runner.Runner(
       module_name='setup',
       module_args='',
       pattern='dbservers',
       remote_user='some_user'
       remote_pass='some_pass_or_python_expression_that_returns_a_string'
    )
    

    For playbooks, look into playbook.PlayBook, which takes a similar set of initializers:

    class PlayBook(object):
        '''
        runs an ansible playbook, given as a datastructure or YAML filename.
        ...
        '''
    
        # *****************************************************
    
        def __init__(self,
            playbook         = None,
            host_list        = C.DEFAULT_HOST_LIST,
            module_path      = None,
            .... 
    

    and can be executed with the .run() method. e.g.:

    from ansible.playbook import PlayBook
    pb = PlayBook(playbook='/path/to/book.yml, --other initializers--)
    pb.run()
    

    more robust usage can be found in the ansible-playbook file.

    As far as I know, translating playbooks to Python modules is a bit more involved, but the documentation listed above should get you covered and you can reuse the YAML parser built into Ansible to convert playbooks to variables.

    0 讨论(0)
  • 2020-12-04 15:25

    You're looking at something that isn't officially supported or recommended therefore little documentation to be had.

    That said, if you really want to pursue that course I would start with cracking open the ansible-playbook script in bin and reverse engineering what you want to do.

    0 讨论(0)
提交回复
热议问题