Ansible @ an efficient configuration management tool-Ansibleconfiguremanagement-translation (12)
If you do not have written authorization, do not repeat Chapter 5 custom modules.
External inventoriesIn the first chapter we saw how Ansible needs an inventory file, so that it knowswhere its hosts are and how to access them. Ansible also allows you to specify ascript that allows you to fetch the inventory from another source. Externalinventory scripts can be written in any language that you like as long as theyoutput valid JSON.An external inventory script has to accept two different calls from Ansible. If calledwith –list , it must return a list of all the available groups and the hosts in them.Additionally, it may be called with --host . In this case, the second argument will bea hostname and the script is expected to return a list of variables for that host. All theoutputs are expected in JSON, so you should use a language that supports it naturally.
External inventory Device List
The first chapter describes how Ansible requires a device inventory list file to access host devices. Ansible can also use scripts to select other inventory list files. This script can be written in any language as long as its output format complies with JSON.
The external inventory list script needs to accept two types of Ansible calls. If you use -- list for calling, it returns a list of available groups and hosts. If you use -- host for calling, returns a list of available hosts. All outputs must be in JSON format, so it is best to easily support this format in your language.
Let's write a module that takes a CSV file listing all your machines and presentsthis to Ansible as an inventory. This will be handy if you have a CMDB that allowsyou to export your machine list as CSV, or for someone who keeps records oftheir machines in Excel. Additionally, it doesn't require any dependencies outsidePython, as a CSV processing module is already included with Python. This really justparses the CSV file into the right data structures and prints them out as JSON datastructures. The following is an example CSV file we wish to process; you may wishto customize it for the machines in your environment:Group,Host,Variablestest,example,ansible_ssh_user=roottest,localhost,connection=local
Let's write a module that extracts data from a CSV file containing all your machines and then releases it to the Ansible inventory list. This module is useful if you have a CMDB (database) that can be used to export devices to CSV files, or if the device records are saved in an excel table. In addition, it does not need any dependencies other than python. It only needs to parse the CSV file and then output the data into JSON format. The following is an example of a CSV file that we want to process. You can also customize machines in your environment:
Group, Host, Variables
Test, example, ansible_ssh_user = root
Test, localhost, connection = local
This file needs to be converted into two different JSON outputs. When --list iscalled, we need to output the whole thing in a form that looks like this:{"test": ["example", "localhost"]}And when it is called with the arguments --host example , it should return this:{"ansible_ssh_user": "root"}Here is the script that opens a file named machines.csv and produces the dictionaryof the groups if --list is given. Additionally, when given --host and a hostname,it parses that host's variables and returns them as a dictionary. The script is well-commented, so you can see what it is doing. You can run the script manually withthe --list and --host arguments to confirm that it behaves correctly.
This file needs to be converted into two formats of JSON output. When called with -- list, it is like this:
{"Test": ["example", "localhost"]}
When you call it with -- host, it is as follows:
{"Ansible_ssh_user": "root "}
The following example opens a machines.csv file. When you call -- list, it uses the dictionary to represent the Group. When you call -- host, it uses the dictionary to represent the host and Their variables. The script has been commented out. You can use the -- list and -- host parameters to test:
#! /Usr/bin/env python #-*-coding: UTF-8-*-import sysimport csvimport jsondef getlist (csvfile): # Init local variables # initialize the local variable glist = dict () rowcount = 0 # Iterate over all the rows # review all rows for row in csvfile: # Throw away the header (Row 0) # Remove the first row and the header line if rowcount! = 0: # Get the values out of the row # obtain data (group, host, variables) of non-title rows) = row # If this is the first time we 've ve # read this group create an empty # list for it # If you read this group for the first time, create a new list for him. if group not in glist: glist [group] = list () # Add the host to the list. glist [group]. append (host) # Count the rows we 've processed # Calculate the row rowcount + = 1 return glistdef gethost (csvfile, host) we have processed: # Init loc Al variables # initialize the local variable rowcount = 0 # Iterate over all the rows # review all rows for row in csvfile: # Throw away the header (Row 0) # Remove the header line if rowcount! = 0 and row [1] = host: # Get the values out of the row # Get data from a non-title row variables = dict () for kvpair in row [2]. split (): key, value = kvpair. split ('=', 1) variables [key] = value return variables # Count the rows we 've processed # calculate the number of rows we have processed rowcount + = 1 command = sys. argv [1] # Open the CSV and start parsing it # Open the csv file and start processing with open('machines.csv ', 'R') as infile: result = dict () csvfile = csv. reader (infile) if command = '-- list': result = getlist (csvfile) elif command =' -- host': result = gethost (csvfile, sys. argv [2]) print json. dumps (result)
You can now use this inventory script to provide the inventory when using Ansible.A quick way to test that everything is working correctly is to use the ping module totest the connection to all the machines. This command will not test whether the hostsare in the right groups; if you want to do that, you can use the same ping modulecommand but instead of running it across all, you can simply use the group youwould like to test.$ ansible -i csvinventory -m ping all
Now you can use this script to provide the inventory list when using Anisbile. Use the ping module to connect all the machines in the list and test whether the script runs well. If the host is not in its group, it will fail, but you can ping it separately. The command for using group to test is as follows:
$ Ansible-I csvinventory-m ping all
Similar to when you used the ping module in Chapter 1, Getting Started with Ansible,you should see an output that looks like the following:localhost | success >> {"changed": false,"ping": "pong"}example | success >> {"changed": false,"ping": "pong"}This indicates that you can connect and use Ansible on all the hosts from yourinventory. You can use the same -i argument with ansible-playbook to run yourplaybooks with the same inventory.
Like the first chapter, the output is similar to the following:
Localhost | success >> {
"Changed": false,
"Ping": "pong"
}
Example | success >> {
"Changed": false,
"Ping": "pong"
}
You can connect all the machines in the list or run the playbook using the-I parameter.
SummaryHaving read this chapter you should now be able to build modules using either Bashor any other languages that you know. You should be able to install modules that youhave either obtained from the Internet, or written yourself. We also covered how towrite modules more efficiently using the boilerplate code in Python. Finally, we wrotean inventory script that allows you to pull your inventory from an external source.
Summary of this Chapter
After reading this chapter, you should be able to use bash or other languages you will use to create custom modules, install the modules you download from the Internet, or write them by yourself. We also introduced how to use python sample code to effectively write modules. Finally, we wrote an inventory list script that allows you to reference the inventory list from an external file.