oriolrius.cat

Des del 2000 compartiendo sobre…

Using Ansible like library programming in Python

Reading time: 2 – 4 minutes

Ansible is a very powerful tool. Using playbooks, something like a cookbook, is very easy to automate maintenance tasks of systems. I used Puppet and other tools like that but IMHO Ansible is the best one.

In some cases you need to manage dynamic systems and take into advantage of Ansible like a Python library is a very good complement for your scripts. This is my last requirement and because of that I decided to share some simple Python snippets that help you to understand how to use Ansible as a Python library.

Firstly an example about how to call an Ansible module with just one host in the inventory (test_modules.py):

#!/usr/bin/python 
import ansible.runner
import ansible.playbook
import ansible.inventory
from ansible import callbacks
from ansible import utils
import json

# the fastest way to set up the inventory

# hosts list
hosts = ["10.11.12.66"]
# set up the inventory, if no group is defined then 'all' group is used by default
example_inventory = ansible.inventory.Inventory(hosts)

pm = ansible.runner.Runner(
    module_name = 'command',
    module_args = 'uname -a',
    timeout = 5,
    inventory = example_inventory,
    subset = 'all' # name of the hosts group 
    )

out = pm.run()

print json.dumps(out, sort_keys=True, indent=4, separators=(',', ': '))

As a second example, we’re going to use a simple Ansible Playbook with that code (test.yml):

- hosts: sample_group_name
  tasks:
    - name: just an uname
      command: uname -a

The Python code which uses that playbook is (test_playbook.py):

#!/usr/bin/python 
import ansible.runner
import ansible.playbook
import ansible.inventory
from ansible import callbacks
from ansible import utils
import json

### setting up the inventory

## first of all, set up a host (or more)
example_host = ansible.inventory.host.Host(
    name = '10.11.12.66',
    port = 22
    )
# with its variables to modify the playbook
example_host.set_variable( 'var', 'foo')

## secondly set up the group where the host(s) has to be added
example_group = ansible.inventory.group.Group(
    name = 'sample_group_name'
    )
example_group.add_host(example_host)

## the last step is set up the invetory itself
example_inventory = ansible.inventory.Inventory()
example_inventory.add_group(example_group)
example_inventory.subset('sample_group_name')

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

# creating the playbook instance to run, based on "test.yml" file
pb = ansible.playbook.PlayBook(
    playbook = "test.yml",
    stats = stats,
    callbacks = playbook_cb,
    runner_callbacks = runner_cb,
    inventory = example_inventory,
    check=True
    )

# running the playbook
pr = pb.run()  

# print the summary of results for each host
print json.dumps(pr, sort_keys=True, indent=4, separators=(',', ': '))

If you want to download example files you can go to my github account: github.com/oriolrius/programming-ansible-basics

I hope it was useful for you.

7 thoughts on “Using Ansible like library programming in Python

  1. Hi, very nice vriteup. Based on your example – what would be the proper way of for example install list of packages (given as command line arguments) using “apt” module without calling ansible.runner for each individual package but doing the whole thing in a single run? Can it be done?

  2. I am running a playbook that is supposed to create some config files, using your example code. However, the config files are not created, but my code is executed without error messages. What am I missing? FYI the files are created when I run the playbook from the command line.

  3. This example, don’t create configuration files. You don’t need that if you run Ansible as a library.

  4. Thank you for your reply Oriol. I was probably not clear enough. My playbook creates some files on the local computer, as well as performing other tasks. However, the files that are supposed to be created on the local computer running the python script are not created, although the playbook seems to run just fine. These files are successfully created when running the playbook from the command line. I figure it is a Python problem, but I just can’t get it to work.

  5. Hi I am getting the below error when i tried to run the below play book. i have exactly used the above code only changed the IP. My playbook works just fine when i execute from CLI.

    Error MSG:

    /Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /app/ansible_run.py

    PLAY [sample_group_name] ******************************************************

    GATHERING FACTS ***************************************************************

    ok: [10.*.*.*]

    TASK: [debug msg=“Ansible is great”] *******************************************

    FATAL: no hosts matched or all hosts have already failed — aborting

    {

    “10.*.*.*: {

    “changed”: 0,

    “failures”: 0,

    “ok”: 1,

    “skipped”: 0,

    “unreachable”: 0

    }

    }

    Process finished with exit code 0

    Playbook.yml

    – hosts: sample_group_name

    user: username

    sudo: no

    tasks:
    – debug: msg=“Ansible is great”

  6. A simple way is create a variable with a list of packages and then use it as list. This is the most robust solution. But the fastest way is run all packages as a long command line.

Últimas entradas

Resumen 2023

Reading time: 14 – 22 minutes El 2023 comenzó con una sensación de renovación y optimismo. Tras un período marcado por la pandemia, este año se presentó como un lienzo en blanco, lleno de posibilidades y nuevas experiencias. Aunque el

Leer más »
Archivo