Bookmark this page

Guided Exercise: Managing Dynamic Inventories

  • Install custom scripts that dynamically generate a list of inventory hosts.

Outcomes

  • Install and use existing dynamic inventory scripts.

As the student user on the workstation machine, use the lab command to prepare your system for this exercise.

This command ensures that Ansible is installed on the workstation machine and also prepares the /home/student/inventory-dynamic working directory for this exercise.

[student@workstation ~]$ lab start inventory-dynamic

Procedure 5.1. Instructions

  1. On the workstation machine, change to the /home/student/inventory-dynamic directory.

    View the contents of the ansible.cfg Ansible configuration file. The configuration file sets the inventory location to ~/inventory-dynamic/inventory.

    [student@workstation ~]$ cd ~/inventory-dynamic/
    [student@workstation inventory-dynamic]$ cat ansible.cfg
    [defaults]
    inventory = inventory
  2. Create the /home/student/inventory-dynamic/inventory directory.

    [student@workstation inventory-dynamic]$ mkdir inventory
  3. Use the tree command to list the files in the current directory.

    [student@workstation inventory-dynamic]$ tree
    .
    ├── ansible.cfg
    ├── ansible-navigator.yml
    ├── hosts 1
    ├── inventory
    ├── inventorya.py 2
    └── inventoryw.py 3
    
    1 directory, 5 files

    1

    The hosts static inventory file defines the servers group, which is a parent group of the webservers group.

    2

    The inventorya.py dynamic inventory script defines the webservers group, which includes the servera.lab.example.com host.

    3

    The inventoryw.py dynamic inventory script defines the workstation.lab.example.com host.

  4. Move the Python scripts and the hosts file into the inventory directory.

    [student@workstation inventory-dynamic]$ mv *.py hosts inventory/
  5. Use the following ansible-navigator inventory command to list the hosts in the webservers group. Use the inventorya.py script as the inventory source and add the --graph option to display the result as a graph. The command fails with a permission error on the inventorya.py file.

    [student@workstation inventory-dynamic]$ ansible-navigator inventory \
    > --mode stdout -i inventory/inventorya.py --graph webservers
    [WARNING]:  * Failed to parse /home/student/inventory-
    dynamic/inventory/inventorya.py with script plugin: problem running
    /home/student/inventory-dynamic/inventory/inventorya.py --list ([Errno 13]
    Permission denied: '/home/student/inventory-dynamic/inventory/inventorya.py')
    [WARNING]:  * Failed to parse /home/student/inventory-
    dynamic/inventory/inventorya.py with ini plugin: /home/student/inventory-
    dynamic/inventory/inventorya.py:3: Expected key=value host variable assignment,
    got: subprocess
    [WARNING]: Unable to parse /home/student/inventory-
    dynamic/inventory/inventorya.py as an inventory source
    [WARNING]: No inventory was parsed, only implicit localhost is available
    usage: ansible-inventory [-h] [--version] [-v] [-i INVENTORY]
                             [--vault-id VAULT_IDS]
                             [--ask-vault-password | --vault-password-file VAULT_PASSWORD_FILES]
                             [--playbook-dir BASEDIR] [-e EXTRA_VARS] [--list]
                             [--host HOST] [--graph] [-y] [--toml] [--vars]
                             [--export] [--output OUTPUT_FILE]
                             [host|group]
    ...output omitted...

    Note, too, that Ansible tries first to process the file as an inventory script and then tries to parse it as a static inventory file in INI format, which also fails. Remember that Ansible tries different plug-ins in a specific order to process inventory files.

  6. Inspect the current mode of the inventorya.py script. Change the mode of all Python scripts to be executable.

    [student@workstation inventory-dynamic]$ ls -l inventory/inventorya.py
    -rw-rw-r--. 1 student student 640 Oct 20 05:26 inventory/inventorya.py
    [student@workstation inventory-dynamic]$ chmod 755 inventory/*.py
  7. Run the inventorya.py script with the --list option. The script displays the hosts in the webservers group.

    [student@workstation inventory-dynamic]$ inventory/inventorya.py --list
    {"webservers": {"hosts": ["servera.lab.example.com"], "vars": {}​}​}
  8. Run the inventoryw.py script with the --list option. The script displays the workstation.lab.example.com host.

    [student@workstation inventory-dynamic]$ inventory/inventoryw.py --list
    {"all": {"hosts": ["workstation.lab.example.com"], "vars": {}​}​}
  9. Display the content of the inventory/hosts file. Notice that the file references the webservers group that the dynamic inventory defines.

    [student@workstation inventory-dynamic]$ cat inventory/hosts
    [servers:children]
    webservers
  10. Use the following ansible-navigator inventory command to list the hosts in the webservers group. Add the --graph option to display the result as a graph. The command fails with an error about the webservers group being undefined.

    [student@workstation inventory-dynamic]$ ansible-navigator inventory \
    > --mode stdout --graph webservers
    [WARNING]:  * Failed to parse /home/student/inventory-dynamic/inventory/hosts
    with yaml plugin: We were unable to read either as JSON nor YAML, these are the
    errors we got from each: JSON: Expecting value: line 1 column 2 (char 1)
    Syntax Error while loading YAML.   found unexpected ':'  The error appears to
    be in '/home/student/inventory-dynamic/inventory/hosts': line 1, column 9, but
    may be elsewhere in the file depending on the exact syntax problem.  The
    offending line appears to be:   [servers:children]         ^ here
    [WARNING]:  * Failed to parse /home/student/inventory-dynamic/inventory/hosts
    with ini plugin: /home/student/inventory-dynamic/inventory/hosts:2: Section
    [servers:children] includes undefined group: webservers
    [WARNING]: Unable to parse /home/student/inventory-dynamic/inventory/hosts as
    an inventory source
    @webservers:
      |--servera.lab.example.com

    Important

    If the dynamic inventory script that provides the host group is named so that it sorts before the static inventory references it, then you do not see this error. However, if the host group is ever removed from the dynamic inventory, and you do not have a placeholder, then the static inventory references a missing host group and the error causes the parsing of the inventory to fail.

  11. To avoid this problem, the static inventory must have a placeholder entry that defines an empty webservers host group. It is important for the static inventory to define any host group it references, because it is possible that it could dynamically get removed from the external source, causing this error.

    Edit the inventory/hosts file and add an empty [webservers] section.

    [webservers]
    
    [servers:children]
    webservers
  12. Rerun the ansible-navigator inventory command that lists the hosts in the webservers group. It works without any errors.

    [student@workstation inventory-dynamic]$ ansible-navigator inventory \
    > --mode stdout --graph webservers
    @webservers:
      |--servera.lab.example.com
  13. Rerun the ansible-navigator inventory command that lists all the hosts in the inventory. Use the --graph option but do not provide a group name.

    [student@workstation inventory-dynamic]$ ansible-navigator inventory \
    > --mode stdout --graph
    @all:
      |--@servers:
      |  |--@webservers:
      |  |  |--servera.lab.example.com
      |--@ungrouped:
      |  |--workstation.lab.example.com

Finish

On the workstation machine, change to the student user home directory and use the lab command to complete this exercise. This step is important to ensure that resources from previous exercises do not impact upcoming exercises.

[student@workstation ~]$ lab finish inventory-dynamic

This concludes the section.

Revision: do374-2.2-82dc0d7