Bookmark this page

Writing YAML Inventory Files

Objectives

  • Write static inventory files in YAML format.

Inventory Plug-ins

Ansible uses plug-ins to support different formats of inventory files. Plug-ins are pieces of code that enhance the functionality of Ansible. By writing inventory plug-ins, Ansible developers can quickly support new formats and methods of generating inventory data. For example, Ansible manages static inventory files in INI format and dynamic inventory scripts with plug-ins.

Most inventory plug-ins are enabled by default. You can enable additional plug-ins by setting the enable_plugins directive under the inventory section in your ansible.cfg configuration file.

[inventory]
enable_plugins = host_list, script, auto, yaml, ini, toml

The preceding example shows the default list. When Ansible parses inventory sources, it tries the plug-ins in the order they appear in the enable_plugins directive.

The script plug-in provides support for dynamic inventory scripts. The ini plug-in provides support for INI format. The other plug-ins get inventory information from files in other formats or other sources. Details are available at https://docs.ansible.com/ansible/6/plugins/inventory.html.

Some Ansible Content Collections come with additional inventory plug-ins. For example, the amazon.aws content collection provides the aws_ec2 inventory plug-in to retrieve inventory hosts from Amazon Web Services EC2.

Writing YAML Static Inventory Files

You can use the yaml inventory plug-in to write static inventory files in YAML format. This plug-in is enabled by default.

The following example shows a static inventory file in INI format:

[lb_servers]
proxy.example.com

[web_servers]
web1.example.com
web2.example.com

[backend_server_pool]
appsrv-[a:e].example.com

This static inventory has three groups:

  • The lb_servers group includes the proxy.example.com host.

  • The web_servers group includes the web1.example.com and web2.example.com hosts.

  • The backend_server_pool group uses an alphabetical range to include five hosts, appsrv-a, appsrv-b, appsrv-c, appsrv-d, and appsrv-e. The following example defines the same inventory in YAML format:

lb_servers:
  hosts:
    proxy.example.com:
web_servers:
  hosts:
    web1.example.com:
    web2.example.com:
backend_server_pool:
  hosts:
    appsrv-[a:e].example.com:

YAML inventories use blocks to organize related configuration items. Each block begins with the name of a group followed by a colon. Everything indented below the group name belongs to that group.

If indented below a group name, then the hosts keyword starts a block of hostnames. All server names indented below the hosts keyword belong to this group. These servers themselves form their own groups, and must therefore end in a colon.

To define nested groups, use the children keyword in a group block. This keyword starts a list of subgroups that are members of this group. Those member subgroups can have their own hosts and children blocks.

One advantage that the YAML format has over the INI format is that it organizes both the lists of servers and the list of nested groups in the same place in the static inventory file.

Important

The all group implicitly exists at the top level and includes the rest of the inventory as its children. You can explicitly list it in your YAML inventory file, but it is not required.

all:
  children:
    lb_servers:
      hosts:
        proxy.example.com:
    web_servers:
      hosts:
        web1.example.com:
        web2.example.com:
    backend_server_pool:
      hosts:
        appsrv-[a:e].example.com:

Static inventories in INI format often include hosts that are not members of any group.

notinagroup.example.com

[mailservers]
mail1.example.com

Ansible automatically puts those hosts in the special ungrouped group. In YAML, explicitly assign them to the ungrouped group.

all:
  children:
    ungrouped:
      notinagroup.example.com:
    mailservers:
      mail1.example.com:

Setting Inventory Variables

You can set inventory variables directly in an inventory file in YAML format, just like you can in an inventory file in INI format.

Note

It is often a best practice to avoid storing variables in static inventory files.

Experienced Ansible developers prefer to use static inventory files only to list the hosts that Ansible manages, and to organize them in groups. The variables and their values are stored in the host_vars or group_vars files for the inventory.

However, you might want to define variables such as ansible_port or ansible_connection in the same file as the inventory itself, to keep this information in one place. If you set variables in too many places, then it is harder to remember where a particular variable is defined.

In a group block, use the vars keyword to set group variables directly in a YAML inventory file.

The following static inventory file in INI format sets the smtp_relay variable for all the hosts in monitoring group.

[monitoring]
watcher.example.com

[monitoring:vars]
smtp_relay=smtp.example.com

The equivalent static inventory file in YAML format is as follows:

monitoring:
  hosts:
    watcher.example.com:
  vars:
    smtp_relay: smtp.example.com

In YAML, to set a variable for a specific host instead of a group, indent the variable under that host. The following static inventory file in INI format sets the ansible_connection variable for the localhost host.

[databases]
maria1.example.com
localhost ansible_connection=local
maria2.example.com

The equivalent static inventory file in YAML format is as follows:

databases:
  hosts:
    maria1.example.com:
    localhost:
      ansible_connection: local
    maria2.example.com:

Converting a Static Inventory File in INI Format to YAML

You can use the ansible-navigator inventory command to help you convert an inventory file in INI format into YAML format. However, this is not the intended purpose of this command. The command is designed to display the entire configured inventory as Ansible sees it, and results can differ from those reported by the original inventory file. The ansible-navigator inventory command parses and tests the format of the inventory files, but it does not attempt to validate whether a hostname in the inventory exists.

Note

Remember that a name in an inventory file is not necessarily a valid hostname, but is used by the playbook to refer to a specific managed host. The name of that managed host could have an ansible_host host variable set that points to the real name or IP address of the host. The name in the inventory file can be a simplified alias for the purposes of the playbook.

The following example shows a static inventory file in INI format, called origin_inventory, which you want to convert to YAML. Notice that the web1.example.com host belongs to two groups: web_servers and dc1.

[lb_servers]
proxy.example.com

[web_servers]
web1.example.com
web2.example.com

[web_servers:vars]
http_port=8080

[backend_server_pool]
appsrv-[a:e].example.com

[dc1]
web1.example.com
appsrv-e.example.com

Use the following ansible-navigator inventory command to convert the origin_inventory file to YAML.

[user@host ~]$ ansible-navigator inventory --mode stdout -i origin_inventory \
> --list --yaml
all:
  children:
    backend_server_pool:
      hosts:
        appsrv-a.example.com: {}
        appsrv-b.example.com: {}
        appsrv-c.example.com: {}
        appsrv-d.example.com: {}
        appsrv-e.example.com: {}
    dc1:
      hosts:
        appsrv-e.example.com: {}
        web1.example.com:
          http_port: 8080
    lb_servers:
      hosts:
        proxy.example.com: {}
    ungrouped: {}
    web_servers:
      hosts:
        web1.example.com: {}
        web2.example.com:
          http_port: 8080

Notice that the command converts the http_port group variable to a host variable for the two members of the web_servers group.

Also, for the web1.example.com host, the variable is only set for the first occurrence of that host in the inventory; that is, when the host is declared in the dc1 group. This is incorrect because this is not how the original inventory works. If you create a playbook that targets the web_servers group, then Ansible does not set the http_port variable for the web1.example.com host as it would with the original inventory.

It is therefore important to carefully review and fix the resulting YAML file. In this example, you would define the http_port variable in the web_servers group. You could also define the hosts in the backend_server_pool by a range.

all:
  children:
    backend_server_pool:
      hosts:
        appsrv-[a:e].example.com: {}
    dc1:
      hosts:
        appsrv-e.example.com: {}
        web1.example.com: {}
    lb_servers:
      hosts:
        proxy.example.com: {}
    ungrouped: {}
    web_servers:
      hosts:
        web1.example.com: {}
        web2.example.com: {}
      vars:
        http_port: 8080

Note

Some group or host lines in the YAML output end with braces, {}. Those braces indicate that the group does not have any members or group variables, or that the host has no host variables. They do not need to be included.

Using the ansible-navigator inventory command to convert large inventory files can save time, but you must use it with caution. It works better when your original static inventory file does not directly declare inventory variables, but gets them from external files in host_vars and group_vars.

Troubleshooting YAML Files

If you have trouble with static inventory files in YAML format, then consider these points about YAML syntax.

Protecting a Colon Followed by a Space

Remember that in an unquoted string, a colon followed by a space causes an error. YAML interprets this as starting a new element in a dictionary.

The following example causes an error because the second colon is not protected:

title: Ansible: Best Practices

The following strings are correct because they are protected by quotes or they do not have a space after the colons:

title: 'Ansible: Best Practices'
double: "Ansible: Best Practices"
fine: Not:a:problem

Protecting a Variable That Starts a Value

Ansible performs variable replacement with the {{ variable }} syntax, but anything beginning with an opening brace, {, in YAML is interpreted as the start of a dictionary. Thus, you must enclose the variable placeholder with double quotes: name: "{{ variable }} rest of the value".

In general, when using any of the reserved characters, [] {} > , | * & ! % # ` @ , you should use double quotes around the value.

Knowing the Difference Between a String and a Boolean or Float

Booleans and floating point numbers used as values for a variable must not be quoted. Quoted values are treated as strings. The following example sets the active parameter to the true Boolean value, and sets the default_answer parameter to the true string.

active: true
default_answer: "true"

The following example sets the temperature parameter to a floating point value, and sets the version parameter to a string.

temperature: 36.5
version: "2.0"

Revision: do374-2.2-82dc0d7