Inventory & Data

What is inventory?

A pyinfra inventory contains hosts, groups and data. Hosts are where pyinfra will make changes (a server via SSH, a Docker container or the local machine). Groups are collections of one or more host. Data can be assigned to both groups and hosts.

Inventory Files

Inventory files contain groups of hosts. Groups are defined as a list or tuple. For example, this inventory creates two groups, app_servers and db_servers. Note that group names cannot start _:

app_servers = [
    "app-1.net",
    "app-2.net"
]

db_servers = (["db-1.net", "db-2.net", "db-3.net",], {})

If you save this file as inventory.py, you can then use it when executing pyinfra:

pyinfra inventory.py OPERATIONS...

Autogenerated Groups

A special group, all, will contain every host from the inventory file (whatever the file is called).

All the hosts are added to a group with the name of the inventory file (eg any hosts defined in inventories/production.py belong to group production).

Host Data

Data can be assigned to individual hosts in the inventory by using a tuple (hostname, data_dict):

app_servers = [
    ("app-1.net", {"install_postgres": False}),
    ("db-1.net", {"install_postgres": True}),
]

This data can then be used in operations:

from pyinfra import host

if host.data.get("install_postgres"):
    apt.packages(
        packages=["postgresql-server"],
    )

Host Name

The name of the host can be accessed via the pyinfra.host.name attribute:

from pyinfra import host

print(host.name)  # prints "app-1.net" for example

Groups

It is often useful to access the list of groups a host belongs to in operation code, this can be done via the pyinfra.host.groups attribute:

from pyinfra import host

if "app_servers" in host.groups:
    server.shell(...)

Group Data Files

Group data can be stored in separate files under the group_data directory (there’s also a --group-data $DIR flag). Files will be loaded that match group_data/<group_name>.py, and all hosts in any matching group will receive variables defined in the file as data:

app_user = "myuser"
app_dir = "/opt/pyinfra"

These variables can then be used in operations:

from pyinfra import host

git.repo(
    src="git@github.com:Fizzadar/pyinfra.git",
    dest=host.data.app_dir,
    user=host.data.app_user,
)

Note

The group_data directory is relative to the current working directory. This can be changed at runtime via the --chdir flag.

Data Hierarchy

The same keys can be defined for host and group data - this means we can set a default in all.py and override it on a group or host basis. When accessing data, the first match in the following is returned:

  • “Override” data passed in via CLI args
  • Host data as defined in the inventory file
  • Normal group data
  • all group data

Note

pyinfra contains a debug-inventory command which can be used to explore the data output per-host for a given inventory/deploy, ie pyinfra inventory.py debug-inventory.

Connecting with Data

Data can be used to configure connectors. For example, setting SSH connection details can be done like so:

ssh_user = "ubuntu"
ssh_key = "~/.ssh/some_key"
ssh_key_password = "password for key"

The Connectors Index contains full details of which data keys are available in each connector.

Global Arguments with Data

Data can also provide default values for Global Arguments, for example:

_sudo = True
_sudo_user = "pyinfra"

External Sources for Data

Because pyinfra is configured in Python, you can pull in data from pretty much anywhere just using other Python packages.