Inspect a dynamic Ansible AWS inventory
Tags: ansible, devops, aws
Published: 2023-08-18 13:00:00

We will discover the power of `ansible-inventory` to inspect the structure of the inventory built by ansible when the inventory is generated from the metadata of a machine park. No more wasted time figuring out which groups and hosts Ansible referenced when loading a dynamic inventory.

<!--more-->

Ansible is able to generate dynamic inventory from an AWS account. The `aws_ec2` plugin builds the inventory from the metadata it finds on the account.

To use it, you must configure the `aws_ec2` plugin in an inventory file.

```
ansible -i aws_ec2.yml --list-hosts all
```

```
  hosts (2):
    ec2-52-XX-XX-25.eu-west-1.compute.amazonaws.com
    ec2-52-XX-XX-48.eu-west-1.compute.amazonaws.com
```

## [WARNING]: Could not match supplied host pattern

It all starts with the error `WARNING]: Could not match supplied host pattern`. This error message is generated when ansible cannot find a match between groups and hosts referenced in the inventory.

```bash
ansible-playbook -i aws_ec2.yml deploy.yml
```

```text
[WARNING]: Could not match supplied host pattern, ignoring: farcellier.com

PLAY [farcellier.com] *******************************************************************************************
skipping: no hosts matched
```

I wasted an hour trying to figure out why ansible couldn't find the `farcellier.com` group in the inventory when it should have been there. I would have saved time if I knew how to inspect the inventory.

## Inspect inventory

The `ansible-inventory` command allows you to inspect the inventory as `ansible` sees it. It's a release to be able to see what `ansible` is interpreting instead of trying to guess.

```bash
ansible-inventory -i aws_ec2.yml --graph
```

```text
@all:
  |--@aws_ec2:
  |  |--ec2-52-XX-XX-25.eu-west-1.compute.amazonaws.com
  |  |--ec2-52-XX-XX-48.eu-west-1.compute.amazonaws.com
  |--@other_website:
  |  |--ec2-52-XX-XX-25.eu-west-1.compute.amazonaws.com
  |--@farcellier_com:
  |  |--ec2-52-XX-XX-48.eu-west-1.compute.amazonaws.com
  |--@ungrouped:
```

The solution is before our eyes. Ansible renames the `farcellier.com` tag to `farcellier_com`.

## Inspect inventory deeply

The `ansible-inventory` command allows you to see even more. It is able to trace all the variables captured at the host level. This is handy for improving the AWS inventory definition file.

```bash
ansible-inventory -i aws_ec2.yml --list
```

I've posted a snippet of all the variables that are fetched.

```json
{
  "_meta": {
    "hostvars": {
      "ec2-52-XX-XX-25.eu-west-1.compute.amazonaws.com": {
        "ami_launch_index": 0,
        "ansible_host": "ec2-52-XX-XX-25.eu-west-1.compute.amazonaws.com",
        "architecture": "x86_64"
      },
      "ec2-52-XX-XX-48.eu-west-1.compute.amazonaws.com": {
        "ami_launch_index": 0,
        "ansible_host": "ec2-52-XX-XX-48.eu-west-1.compute.amazonaws.com",
        "architecture": "x86_64"
      }
    }
  },
  "all": {
    "children": [
      "aws_ec2",
      "other_website",
      "farcellier_com",
      "ungrouped"
    ]
  },
  "aws_ec2": {
    "hosts": [
      "ec2-52-XX-XX-25.eu-west-1.compute.amazonaws.com",
      "ec2-52-XX-XX-48.eu-west-1.compute.amazonaws.com"
    ]
  },
  "other_website": {
    "hosts": [
      "ec2-52-XX-XX-48.eu-west-1.compute.amazonaws.com"
    ]
  },
  "farcellier_com": {
    "hosts": [
      "ec2-52-XX-XX-25.eu-west-1.compute.amazonaws.com"
    ]
  }
}
```

## References

* [ansible-inventory](https://docs.ansible.com/ansible/latest/cli/ansible-inventory.html)

* [Amazon AWS - Dynamic Inventory Plugin](https://docs.ansible.com/ansible/latest/collections/amazon/aws/docsite/aws_ec2_guide.html)

### Ansible AWS inventory used in this blog post

For reference, I share the inventory I used. It selects machines in the `eu-west-1` region, groups them from the `Name` tag.

*aws_ec2.yml*
```yaml
---
plugin: aws_ec2

regions:
  - eu-west-1

filters:
  # All instances with their state as `running`
  instance-state-name: running

keyed_groups:
 - key: tags.Name
   separator: ''
   prefix: ''

compose:
    ansible_host: public_dns_name
```