Ansible tips’n’tricks: gather facts in an ad-hoc fashion

There are times when I really need to get some ansible_facts from a host to work out details about, say the network card, storage, or Linux Distribution to continue coding. And I don’t want to/have the patience to run add a debug step in my Ansible playbook either :) Thankfully Ansible has just the right tool for the case, called ad-hoc command execution.

Since I can never remember how to gather ansible_facts I decided to write it down, hopefully this saves me (and you!) 5 minutes next time.

Setup

I am using the latest Ansible version 2.15 at the time of writing (250121), taken from PyPi. This example has been re-run on MacOS 15.1/aarch64 using Python 3.9 as the interpreter, but should work everywhere.

There are 2 typical use cases, at least for me:

  1. Gathering facts when using Vagrant
  2. Gathering facts for a newly provisioned (cloud) compute VM

Let’s look at these in turn.

Gathering facts using Vagrant’s dynamic Ansible inventory

If you are using the Ansible provisioner with your Vagrant box, Vagrant will create a suitable inventory for you. Assuming there is only a single VM defined in your Vagrantfile and you didn’t give it a name, the following command will print the VM’s ansible facts:

cd /path/to/vagrant/vm
ansible -i .vagrant/provisioners/ansible/inventory/ default -m setup | head
default | SUCCESS > {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "10.0.2.15"
        ],
        "ansible_all_ipv6_addresses": [
            "fe80::a00:27ff:fec0:f04e"
        ],
        "ansible_apparmor": {
            "status": "enabled"

...

The default VM name is … default. If you are unsure, you can always call vagrant status to tell you the name and status of your Vagrant systems.

If you have multiple VMs defined in your Vagrantfile you need to either specify the patter all or the VM name.

Gathering facts without an inventory

Sometimes you just need to run an ad-hoc command against a machine that’s not yet been added to the inventory. In that case you simply specify the IP address or DNS name of the VM as the Ansible inventory followed by a , as in this example:

ansible all --inventory 1.2.3.4, --user opc --private-key /path/to/private.key --module-name ansible.builtin.setup | head
1.2.3.4 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "10.0.2.15",
            "192.168.56.43"
        ],
        "ansible_all_ipv6_addresses": [
            "fe80::a00:27ff:fe8d:7f5f",
            "fe80::a00:27ff:fe37:33f6"
        ],

...

Since there’s no inventory file, and you target a single host, you should be able to safely specify all as the target pattern.

Summary

Gathering facts in an ad-hoc fashion can really save a lot of time when you develop your Ansible scripts. Depending on how you target your hosts – by means of an inventory or directly – you have to provide different options to the ansible command.

And that really is all there is to say about gathering Ansible facts on the fly. Happy Automating!