To present a realistic example, we have created a simple inventory script for Amazon Web Service in Python. The code is available on GitHub (https://github.com/ansible-cookbook/ec2_tags_inventory):
#!/usr/bin/env python
import boto3
import json
import ConfigParser
import os
def get_address(instance):
if "PublicIpAddress" in instance:
address = instance["PublicIpAddress"]
else:
address = instance["PrivateIpAddress"]
return address
if os.path.isfile('ec2.ini'):
config_path = 'ec2.ini'
elif os.path.isfile(os.path.expanduser('~/ec2.ini')):
config_path = os.path.expanduser('~/ec2.ini')
config = ConfigParser.ConfigParser()
config.read(config_path)
id = config.get("credentials", "aws_access_key_id", raw=True)
key = config.get("credentials", "aws_secret_access_key", raw=True)
client = boto3.client('ec2', aws_access_key_id = id, aws_secret_access_key = key, region_name="us-east-1")
inventory = {}
reservations = client.describe_instances()['Reservations']
for reservation in reservations:
for instance in reservation['Instances']:
address = get_address(instance)
for tag in instance['Tags']:
if tag['Key'] == "ansible_role":
roles = tag['Value'].split(",")
for role in roles:
if role in inventory:
inventory[role].append(address)
else:
inventory[role] = [address]
print json.dumps(inventory)
This script reads a file called ec2.ini for AWS access and secret key. For the sake of simplicity, we have hardcoded the region to us-east-1 but this can be changed easily. The script goes through AWS EC2 in the us-east-1 region and looks for any instance that has a tag with the name ansible_role and any valid value like webserver or database. It will add the IP addresses of those instances to the Python dictionary variable called inventory. In the end, this variable is dumped as JSON as output.
We can test this by executing:
$ python ec2_tags_inventory.py --list
{"application": ["10.0.0.11", "10.0.0.12"], "database": ["10.0.1.11"]}
Note that output may vary depending on the instances that are tagged in EC2. To use this in an Ansible command, we need to make it executable and just pass the script instead of inventory file to -i flag like this:
$ chmod +x ec2_tags_inventory.py
$ ansible -i ec2_tags_inventory.py database -m ping
database | SUCCESS => {
"changed": false,
"failed": false,
"ping": "pong"
}
Needless to say, this is a very simple example and the actual dynamic inventory script provided by Ansible is much more comprehensive and it looks beyond EC2 to other services, such as RDS.