Ansible EC2 dynamic inventory

Ansible EC2 dynamic inventory

One of the steps of creating and testing Ansible roles is verifying that the role does what it was intended to do in real EC2 instances.

To automate this workflow I usually launch 5 instances (centOS 7, centOS 8, Ubuntu 18, and Ubuntu 20) using python and boto3.

LAUNCH EC2

Here is a snippet of my script, you can find the complete script here

The script adds the tags env: ansible and distro: AMI['distro'] to the instances. This comes handy for grouping the Ansible dynamic inventories

    instances = ec2.create_instances(
        ImageId = AMIS[i]["ami"],
        MinCount = 1,
        MaxCount = 1,
        InstanceType = 't3.micro',
        KeyName = KEY,
        SecurityGroupIds=[SG],
        SubnetId=SUBNET,
        TagSpecifications=[
            {
                'ResourceType': 'instance',
                'Tags': [
                    {
                        'Key': 'Name',
                        'Value': AMIS[i]["os"]
                    },
                    {
                        'Key' : 'env',
                        'Value': 'ansible'
                    },
                                        {
                        'Key' : 'distro',
                        'Value': AMIS[i]["distro"]
                    }
                ]
            }
        ]
    )

DYNAMIC INVENTORY

Once the instances are running, instead of updating the inventory file manually, we can use the Ansible plugin: aws_ec2 to make our inventory dynamic.

Here you can see the inventory file that groups our EC2 instances by their tags, in this case, distro.

The name of the file is important and needs to be inventory_aws_ec2.yml

plugin: aws_ec2
boto_profile: default
regions:
  - us-east-1
filters:
  tag:env:
    - ansible
keyed_groups:
  - key: tags.distro
    separator: ''

hostnames:
  - network-interface.association.public-ip

OUTPUT

Notice that the output groups the distribution name with the public IP address assigned to the EC2 instance.

You can use this command to list the dynamic inventory:

ansible-inventory -i inventory_aws_ec2.yml --list

The output is going to look something like this:

{
    "aws_ec2": {
        "hosts": [
            "18.232.x.x",
            "34.228.x.x",
            "34.230.x.x",
            "54.226.x.x",
        ]
    },
    "centos": {
        "hosts": [
            "18.232.x.x",
            "34.228.x.x"
        ]
    },
    "ubuntu": {
        "hosts": [
            "54.226.x.x",
            "54.234.x.x"
        ]
    }
}

RUN THE PLAYBOOK

And finally, you can run your playbook using the dynamic inventory:

ansible-playbook -u ubuntu play.yml

---
- hosts: ubuntu
  become: true
  roles:
    - ansible-role-update

Don't forget to terminate your instances after testing.

Did you find this article valuable?

Support Libert S by becoming a sponsor. Any amount is appreciated!