Bookmark this page

Managing Facts

Objectives

  • Reference data about managed nodes using Ansible facts.

Ansible Facts

Ansible facts are variables that are automatically discovered by Ansible on a managed node.

Facts contain host specific information that can be used just like regular variables in plays, or any other statement that depends on a value collected from a managed node.

Some facts gathered for a managed node might include:

  • Hostname

  • Serial number

  • Network operating system version

  • Network interface names

  • Network interface IP addresses

  • Number of CPUs

  • Available or free memory

  • Size and free space of storage devices

Facts are a convenient way to retrieve the state of a managed node and to determine what action to take based on that state.

For example, your play might perform one of the following actions:

  • Restart a managed node based on the value of a fact that was gathered, such as the state of a particular interface.

  • Detect and resolve a configuration issue based on the value of a fact.

  • Customize a configuration based on the network OS version that is reported by a fact.

Default Fact Gathering

In previous versions, Ansible was unable to gather facts for managed network nodes using the default fact gathering method of setting the gather_facts keyword to true.

In Ansible version 2.9 and later, if you set the gather_facts keyword to true, then Ansible tries to detect the network platform and use the appropriate *_facts module to gather facts.

The default setting is to gather a minimal subset of facts. This is equivalent to setting the gather_subset parameter to min.

To view a minimal subset of facts for a specific network platform, create a short playbook with a play that gathers facts by setting the gather_facts keyword to true. Then use the ansible.builtin.debug module to display the value of the ansible_facts variable.

---
- name: Gather and display default facts for IOS managed nodes
  hosts: ios
  gather_facts: true
  tasks:
    - name: Display facts
      ansible.builtin.debug:
        var: ansible_facts

The following play gathers and displays the equivalent set of facts as the previous play:

---
- name: Gather and display default facts for IOS managed nodes
  hosts: ios
  gather_facts: false
  tasks:
    - name: Gather IOS facts
      cisco.ios.ios_facts:
        gather_subset:
          - min

    - name: Display facts
      ansible.builtin.debug:
        var: ansible_facts

Configurable Fact Gathering

Use *_facts resource modules to gather facts for your managed nodes. For example, for Cisco IOS or IOS XE managed nodes, use the cisco.ios.ios_facts resource module. For Juniper Junos managed nodes, use the junipernetworks.junos.junos_facts resource module.

View the collections documentation for each network platform at https://docs.ansible.com/ansible/latest/collections/ to determine which modules to use.

To view all available facts for a specific network platform, create a short playbook that gathers all facts by setting the gather_subset parameter to all. Then use the ansible.builtin.debug module to display the value of the ansible_facts variable.

---
- name: Gather and display all facts for IOS managed nodes
  hosts: ios
  gather_facts: false
  tasks:
    - name: Gather IOS facts
      cisco.ios.ios_facts:
         gather_subset:
            - all

    - name: Display facts
      ansible.builtin.debug:
        var: ansible_facts

When you run the playbook, the facts are displayed in the output:

[user@host ~]$ ansible-navigator run iosfacts.yml -m stdout

PLAY [Gather and display facts for IOS managed nodes] *************************

TASK [Gather IOS facts] **********************************************************
ok: [iosxe2.lab.example.com]
ok: [iosxe1.lab.example.com]

TASK [Display facts] *******************************************************
ok: [iosxe1.lab.example.com] => {
    "ansible_facts": {
        "net_all_ipv4_addresses": [
            "172.25.250.20"
        ],
        "net_all_ipv6_addresses": [],
        "net_api": "cliconf",
        "net_config": "Building configuration...\n\nCurrent configuration : 6062 bytes\n!\n! Last configuration change at 15:55:19 UTC Thu Jul 6 2023\n!\nversion 17.6\nservice timestamps debug datetime msec\nse
...output omitted...

The playbook displays facts in JSON format as a dictionary of variables. You can browse the output to see what facts are gathered, and to find facts that you might want to use in your plays.

The following table shows some facts that might be gathered from a managed node and which might be useful in a playbook:

Table 4.1. Examples of Ansible Facts

FactVariable
Hostname ansible_facts['net_hostname']
Serial Number ansible_facts['net_serialnum']
Network OS ansible_facts['net_system']
Network OS Version ansible_facts['net_version']
IPv4 addresses ansible_facts['net_all_ipv4_addresses']
Current Active Configuration ansible_facts['net_config']

Note

One of two syntaxes can be used to retrieve the value of a fact, as in the following examples:

  • ansible_facts['net_hostname'] can also be written as ansible_facts.net_hostname

  • ansible_facts['net_config'] can also be written as ansible_facts.net_config

Registering Facts to a Variable

You can also register the output of the *_facts resource modules to a variable. Because facts are stored in the registered variable, you need to reference the facts using the registered variable's namespace, as in the following example:

---
- name: Gather and display facts for IOS managed nodes
  hosts: ios
  gather_facts: true
  tasks:
   - name: Gather IOS facts
     cisco.ios.ios_facts:
       gather_subset:
         - all
     register: iosfacts

   - name: Display a fact
     ansible.builtin.debug:
       var: iosfacts['ansible_facts']['ansible_net_hostname']

Note

Facts stored in a registered variable are referenced using that variable's namespace, and the individual facts are prefaced with the string ansible_.

For example, the fact ansible_facts['net_hostname'] registered under the variable iosfacts is named iosfacts['ansible_facts']['ansible_net_hostname'].

Because gathered facts are automatically added to the ansible_facts variable, it is simpler and more scalable to reference them using the ansible_facts namespace.

When a fact is used in a playbook, Ansible dynamically substitutes the variable name for the fact with the corresponding value:

---
- name: Display specific facts for managed nodes
  hosts: ios
  gather_facts: false
  tasks:
    - name: Gather IOS facts
      cisco.ios.ios_facts:
        gather_subset:
          - all

    - name: Display hostname and IPv4 addresses
      ansible.builtin.debug:
        msg: >-
          The IPv4 addresses of interfaces on
          {{ ansible_facts['net_hostname'] }} are
          {{ ansible_facts['net_all_ipv4_addresses'] }}

The following output shows how Ansible was able to query the managed node and dynamically use the information to update the variable:

[user@host ~]$ ansible-navigator run factssubset.yml -m stdout

PLAY [Display specific facts for managed nodes] *******************************

TASK [Gather IOS facts] *******************************************************
ok: [iosxe2.lab.example.com]
ok: [iosxe1.lab.example.com]

TASK [Display hostname and IPv4 addresses] ************************************
ok: [iosxe2.lab.example.com] => {
    "msg": "The IPv4 addresses of interfaces on  iosxe2.lab.example.com are  ['172.25.250.21']"
}
ok: [iosxe1.lab.example.com] => {
    "msg": "The IPv4 addresses of interfaces on  iosxe1.lab.example.com are  ['172.25.250.20']"
}

PLAY RECAP ********************************************************************
iosxe1.lab.example.com     : ok=2    changed=0    unreachable=0    failed=0 ...
iosxe2.lab.example.com     : ok=2    changed=0    unreachable=0    failed=0 ...

Gather facts from different network platforms by using the appropriate facts module for each platform.

For example, the following playbook uses a different module in each task to gather facts based on the value of the network_os fact:

---
- name: Gather facts from different network platforms
  hosts: all
  gather_facts: false
  tasks:
    - name: Gather IOS facts
      cisco.ios.ios_facts:
        gather_subset:
          - all
      when: ansible_network_os == 'cisco.ios.ios'

    - name: Gather Junos facts
      junipernetworks.junos.junos_facts:
        gather_subset:
          - all
      when: ansible_network_os == 'junipernetworks.junos.junos'

Turning off Fact Gathering

You might not want to gather facts for your play for the following reasons:

  • You might not be using any facts and want to speed up the play, or reduce load caused by the play on the managed nodes.

  • The managed nodes cannot run the ansible.builtin.setup module for some reason, or cannot gather all facts using that module. This is often the case for managed network nodes.

To disable fact gathering for a play, set the gather_facts keyword to false. You should do this for managed network nodes, unless they support the ansible.builtin.setup module for all fact gathering.

Gathering a Subset of Facts

Configure fact modules to gather all facts for a managed node by setting the gather_subset parameter to all.

Configure fact modules to only gather a subset of facts by setting the gather_facts parameter to the subset you want to gather. For example, to only gather facts about the configuration, set the gather_subset parameter to config:

- name: Collect only configuration facts
  cisco.ios.ios_facts:
    gather_subset:
      - config

If you want to gather all facts except a certain subset, add an exclamation point (!) in front of the subset name. Add quotes around the string because in YAML the exclamation point cannot be used at the start of an unquoted string.

- name: Collect all facts except for the configuration subset
  cisco.ios.ios_facts:
    gather_subset:
      - "!config"

Refer to the documentation for each fact module to view possible values for the gather_subset parameter. For example, visit https://docs.ansible.com/ansible/latest/collections/cisco/ios/ios_facts_module.html#ansible-collections-cisco-ios-ios-facts-module to view possible values for the gather_subset parameter for the cisco.ios.ios_facts module.

Gathering Facts as Structured Resource Data

Use the gather_network_resources parameter to gather facts as structured network resource data.

You can gather all resource facts or a subset of resource facts, similar to the gather_subset parameter. For example, when using the cisco.ios.ios_facts module, you can set the gather_network_resources parameter to values such as the following:

  • l3_interfaces

  • acls

  • interfaces

  • "!lldp_interfaces,!ospf_interfaces"

  • static_routes

  • "!vlans"

Note

Refer to the module documentation for the full list of valid values for the gather_network_resources parameter.

Display network resource facts by referencing the ansible_network_resources variable, as in the following example:

---
- name: Gather facts as resource data
  hosts: ios
  gather_facts: false
  tasks:
    - name: Gather IOS facts
      cisco.ios.ios_facts:
        gather_network_resources:
          - all

    - name: Display facts
      ansible.builtin.debug:
        var: ansible_network_resources

Using Magic Variables

Ansible sets some special variables automatically. These magic variables can also be useful to get information specific to a particular managed node. Magic variable names are reserved, so you should not define variables with these names.

The following list describes four of the most useful magic variables:

hostvars

The hostvars variable contains the variables for managed nodes, and can be used to get the values for another managed node's variables. It does not include the managed node's facts if they have not yet been gathered for that host.

group_names

The group_names variable lists all groups that the current managed node is in.

groups

The groups variable lists all groups and managed nodes in the inventory.

inventory_hostname

The inventory_hostname variable contains the hostname for the current managed node as configured in the inventory. This might be different from the hostname reported by facts for various reasons.

The following task causes every host that runs the play to display the serial number of the junos1.lab.example.com managed node. It uses the hostvars magic variable to access the ansible_facts['net_serialnum'] fact for that host.

This task works as long as facts were gathered for junos1.lab.example.com earlier in the play or by a preceding play in the playbook:

    - name: Print the serial number of junos1
      ansible.builtin.debug:
        var: hostvars['junos1.lab.example.com']['ansible_facts']['net_serialnum']

Several other magic variables are also available. For more information, see https://docs.ansible.com/ansible/latest/reference_appendices/special_variables.html.

Revision: do457-2.3-7cfa22a