Jun 13, 2016
•
7 mins
read
tutorialpythondockeransibleautomationansible-python-api
Hello!
As the title suggests, in this tutorial, we will write a python script to run Ansible programmatically.
Ansible is an IT automation tool written in Python. You can find out more here.
We will use Ansible Python API 2.0 to write the script.
This API enables us to use Ansible programmatically through Python.
The play will be able to install docker and run a container in a Debian based machine.
So let’s begin! (make sure you have ansible installed).
First setup all the imports
Here we have some important modules to set the ground for the play.
The data loader is for loading data from a YAML or JSON formatted string/file. But in this play we don’t require it, so will initialize empty.
The VariableManager is for setting different variables and specifying the inventory file.
The Inventory is for initializing an inventory.
The Play is used to set up the play.
The TaskQueueManager is for actually running the play.
Now we will initialize the objects that are needed for the play.
Here we have set few options, such as the connection type, path to extra ansible modules (since we didn’t need here so set that empty), the number of forks to create.
We have also set become, become_method and become_user to run the command as root user.
Finally initiated an inventory with a list of hosts to run (here we are playing around with localhost).
Writing the play
Everything here is self explanatory. We create a dictionary for play with it’s name. hosts and tasks. tasks is a list of tasks we want to run.
Inside each list, there is a name for the task, an action to perform, and other things like register (if we want to cache some output in a variable),
with_items (to loop over items). Every action includes another dictionary with a module that will run in the task and it’s arguments.
Configure the play
We have loaded the play with required configuration and the play data we wrote earlier.
Running the play
Here the TaskQueueManager object is created with all the configurations we cooked earlier. Then we run the play using tqm.run(play).
If the TaskQueueManager was initiated successfully then it’s cleaned up in the end.
Note:
Since it is an example script, you should consider setting up a virtual machine and install ansible in it and then run the script there.
So we saw an example of how we can leverage the Python API to program ansible. Automation of an automation tool, sounds cool, No?
There are many other things we could do, we have just seen a small example to get started. You could dig in the cli itself to find out the more cool stuff.
I just had one question. I am using the exact above example but I have connection='ssh' for running to EC2 instances with host='ec2.py' Now, my problem is I don't want to have remote_user set in my source code and want to use the one specified in /etc/ansible/ansible.cfg. But leaving out that in Options gives me connection error. (P.S. the variable private_key_file specified in /etc/ansible/ansible.cfg is correctly used but remote_user specified there is not used. It is not able to connect correctly unless I specify remote_user in Options)
I just had one question. I am using the exact above example but I have connection='ssh' for running to EC2 instances with host='ec2.py' Now, my problem is I don't want to have remote_user set in my source code and want to use the one specified in /etc/ansible/ansible.cfg. But leaving out that in Options gives me connection error. (P.S. the variable private_key_file specified in /etc/ansible/ansible.cfg is correctly used but remote_user specified there is not used. It is not able to connect correctly unless I specify remote_user in Options)
Thank you for great article. I run the same above script(with tiny bit of modification) to run a simple playbook to perform ping command to localhost . I am getting below syntax error when i execute python script
Error Details:
Traceback (most recent call last): File 'ansible.py', line 2, in <module> from ansible.parsing.dataloader import DataLoader File '/home/tcprod/schaitanya/python_ansible/ansible.py', line 2, in <module> from ansible.parsing.dataloader import DataLoader ImportError: No module named parsing.dataloader
Below is the entire script
from collections import namedtuple from ansible.parsing.dataloader import DataLoader from ansible.vars import VariableManager from ansible.inventory import Inventory from ansible.playbook.play import Play from ansible.executor.task_queue_manager import TaskQueueManager
#Initialize the objects that are needed for the play.
Instead of building the ansible playbook manaully in the script, if i have the tasks in a separate ansible playbook yaml file .. Can I construct the play using this ansible file ?
play = Play().load( <external ansible Yaml file >, variable_manager=variable_manager, loader=loader)
Hey Ruby, which version of the API are you using? As in a previous comment I mentioned, it could be due to older version of the API, I have used 2.0 here.
Hi Swati, i want to install java or other softwares. But i want to write python scripts like playbook. It means describe vars, install by yum command, and also capture output. Can you please assist me.
Hi Manish, If I understood correctly, you might want to look at the gist here: [https://gist.github.com/curioswati/c9c2e91f472c702a7058c99f6dfbf2b4](https://gist.github.com/curioswati/c9c2e91f472c702a7058c99f6dfbf2b4). Its purpose is to install jekyll with all required dependencies and that too through a python script. You can simply replace the apt command with yum commands to install Java. Hope this is what you were looking for.
Comments
devops online training
# Aug 24, 2016, 6:35 am
Thanks for sharing this- good stuff! Keep up the great work, we look forward to reading more from you in the future!
Nirav Radia
# Sep 2, 2016, 1:18 pm
I just had one question. I am using the exact above example but I have connection='ssh' for running to EC2 instances with host='ec2.py' Now, my problem is I don't want to have remote_user set in my source code and want to use the one specified in /etc/ansible/ansible.cfg. But leaving out that in Options gives me connection error. (P.S. the variable private_key_file specified in /etc/ansible/ansible.cfg is correctly used but remote_user specified there is not used. It is not able to connect correctly unless I specify remote_user in Options)
Any help would be appreciated. Thanks.
Nirav Radia
# Sep 2, 2016, 1:23 pm
I just had one question. I am using the exact above example but I have connection='ssh' for running to EC2 instances with host='ec2.py' Now, my problem is I don't want to have remote_user set in my source code and want to use the one specified in /etc/ansible/ansible.cfg. But leaving out that in Options gives me connection error. (P.S. the variable private_key_file specified in /etc/ansible/ansible.cfg is correctly used but remote_user specified there is not used. It is not able to connect correctly unless I specify remote_user in Options)
Any help would be appreciated. Thanks.
automate
# Sep 8, 2016, 11:36 am
Hi,
I want to know how can we run this .py script. where is .yml file to rum this .py script.
is this command we need to use?
ansible python-script-name
Swati Jaiswal
# Sep 8, 2016, 5:37 pm
Hey Automate, you don't need to run it using ansible. As it is a python script, you need to run it like:
santhosh chaitanya
# Nov 18, 2016, 10:37 pm
Hi Swati,
Thank you for great article. I run the same above script(with tiny bit of modification) to run a simple playbook to perform ping command to localhost . I am getting below syntax error when i execute python script
Error Details:
Traceback (most recent call last): File 'ansible.py', line 2, in <module> from ansible.parsing.dataloader import DataLoader File '/home/tcprod/schaitanya/python_ansible/ansible.py', line 2, in <module> from ansible.parsing.dataloader import DataLoader ImportError: No module named parsing.dataloader
Below is the entire script
from collections import namedtuple from ansible.parsing.dataloader import DataLoader from ansible.vars import VariableManager from ansible.inventory import Inventory from ansible.playbook.play import Play from ansible.executor.task_queue_manager import TaskQueueManager
#Initialize the objects that are needed for the play.
Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check'] )
#initialize needed objects
variable_manager = VariableManager() loader = DataLoader()
options = Options( connection='local', module_path='';, forks=100, become=True, become_method='sudo', become_user='root', check=False) passwords = dict(vault_pass='secret')
#create inventory and pass to variable manager
inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list='localhost') variable_manager.set_inventory(inventory)
#create play with tasks
play_src = dict( name='ping localhost', hosts='localhost', gather_facts='no', tasks=[
play = Play().load(play_src, variable_manager=variable_manager, loader=loader)
tqm = None try: tqm = TaskQueueManager( inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords, stdout_callback='default', ) result = tqm.run(play) finally: if tqm is not None: tqm.cleanup()
Googled regarding this but got little help. Please let me know how to resolve this dependency issue and make the python program work
Swati Jaiswal
# Nov 19, 2016, 1:20 pm
Hi santhosh, Maybe you are using the wrong version of API. I have used version 2.0. See if this helps.
Hari
# Apr 4, 2017, 4:16 am
Hi,
Instead of building the ansible playbook manaully in the script, if i have the tasks in a separate ansible playbook yaml file .. Can I construct the play using this ansible file ?
play = Play().load( <external ansible Yaml file >, variable_manager=variable_manager, loader=loader)
Ruby
# Jul 5, 2017, 10:46 am
I receive below error:
ImportError: No module named parsing.dataloader
Can you please help on this?
Ruby
# Jul 5, 2017, 10:46 am
I receive below error:
ImportError: No module named parsing.dataloader
Can you please help on this?
Swati Jaiswal
# Jul 12, 2017, 6:5 pm
Hey Ruby, which version of the API are you using? As in a previous comment I mentioned, it could be due to older version of the API, I have used 2.0 here.
Ruby
# Aug 14, 2017, 7:34 pm
Hi Swati,
I was able to solve it by using 2.0 version. Can you please help me in specifying tags while running Ansible API.
Example:
ansible-playbook -i inventoryName playbookName.yml --tags tagName
Ruby
# Aug 14, 2017, 7:35 pm
Thank you . version change to 2.0 fixed it.
Ruby
# Aug 14, 2017, 7:39 pm
Can you please help me to specify tags while running playbook as below:
ansible-playbook -i inventoryName playbookName.yml --tags tagName
Manish
# Sep 4, 2017, 7:4 am
Hi Swati, i want to install java or other softwares. But i want to write python scripts like playbook. It means describe vars, install by yum command, and also capture output. Can you please assist me.
Swati Jaiswal
# Feb 24, 2018, 9:30 am
Hi Manish, If I understood correctly, you might want to look at the gist here: [https://gist.github.com/curioswati/c9c2e91f472c702a7058c99f6dfbf2b4](https://gist.github.com/curioswati/c9c2e91f472c702a7058c99f6dfbf2b4). Its purpose is to install jekyll with all required dependencies and that too through a python script. You can simply replace the apt command with yum commands to install Java. Hope this is what you were looking for.Leave a comment