Can an Ansible inventory include another?
Asked Answered
A

2

7

We have a set of servers shared between different instances of an application and would like the list of them to be a separate file, with other -- instance-specific inventories -- including it.

(I know, this can be done with dynamic inventories, but those are code and we'd like our server-listings to remain data, so to speak.)

With INI-inventories this is impossible, but with YAML-ones it is tantalizingly close. For example, this answer shows, how this can be done by adding a handler for !include to Python's YAML-parser. One could then write:

all:
  group1:
    host1:
    host2:
  sharedservers: !include shared-servers.yaml

How can one add this functionality to one's own Ansible repository -- preferably, without implementing a whole new inventory-plugin (although inhering from Ansible's existing one would be Ok)?

Alga answered 31/10, 2019 at 22:29 Comment(0)
B
10

To start with, your example inventory in your question does not respect the schema for yaml ansible inventory and will be declined parsing.

Now to answer your question, you can simply use several inventories at once. Here is a simple example:

I created 3 yaml inventory files:

  • inventories/hosts.yml
    ---
    group1:
      hosts:
        host1:
        host2:
    
  • inventories/otherhosts.yml
    ---
    group2:
      hosts:
        hostA:
        hostB:
    
  • and finally inventories/shared.yml
    ---
    sharedservers:
      hosts:
        host3:
        host4:
    

From there, it is fairly easy to address all needed hosts. The example below use ansible-inventory for a better output, but the -i option and target selection is the same whith ansible and ansible-playbook

  • Address all hosts in all inventory files inside inventory directory:
    $ ansible-inventory -i inventories/ all --graph
    @all:
      |--@group1:
      |  |--host1
      |  |--host2
      |--@group2:
      |  |--hostA
      |  |--hostB
      |--@sharedservers:
      |  |--host3
      |  |--host4
      |--@ungrouped:
    
    This is equivalent to calling each yaml files in a seperate -i option in this case
    ansible-inventory -i inventories/hosts.yml \
      -i inventories/otherhosts.yml -i inventories/shared.yml \
      all --graph
    
  • Address only specific inventories
    $ ansible-inventory -i inventories/hosts.yml \
      -i inventories/shared.yml all --graph
    @all:
      |--@group1:
      |  |--host1
      |  |--host2
      |--@sharedservers:
      |  |--host3
      |  |--host4
      |--@ungrouped:
    
    $ ansible-inventory -i inventories/otherhosts.yml \
      -i inventories/shared.yml all --graph
    @all:
      |--@group2:
      |  |--hostA
      |  |--hostB
      |--@sharedservers:
      |  |--host3
      |  |--host4
      |--@ungrouped:
    
Bixby answered 1/11, 2019 at 10:31 Comment(3)
This sounds like a good approach. Is it possible to have a group in an inventory file which uses children to combine other groups which are located in other inventory files?Debut
@Debut This can be tested in less time it takes to askBixby
Yes you are right, but now everybody knows that it is possible, thanks to your gist.Debut
R
6

You could take advantage of what is already there in Ansible:

  1. Using inventory directories, you can specify a folder where all your inventory files are located and they will be included one by one in alphabetical ordering.

  2. You can use multiple inventory sources using either:

    • multiple -i options in the command line
    • the ANSIBLE_INVENTORY environment variable and supply a comma separated list of inventory paths (either directories or files)
    • the inventory option in ansible.cfg to do the same as above.

See the docs.

I doubt that with the above you will not be able to cover your needs. It is better to modify your wrapper scripts and your project's file structure a bit than hack your way into pyyaml and ansible. /intro_inventory.html?highlight=inventory directory#using-multiple-inventory-sources) for more information.

Robynroc answered 2/11, 2019 at 12:40 Comment(5)
Option 1 is interesting, but then the same file still cannot be shared with another inventory (directory), save for a symlink. For the rest -- we have many inventories -- one for each application instance -- and everyone is accustomed, to the one instance -> one file paradigm. The work-arounds you're proposeing will take a while to get used to, unfortunately. Why wouldn't Ansible just implement the feature multiple people want?.. Sigh...Alga
You can "share" an inventory by specifying both the main inventory and the shared inventory in ANSIBLE_INVENTORY.Robynroc
Messes up the command-line :( The concept of include is so simple and known for decades (#include <...>)...Alga
You can create your own inventory script/plugin that will do exactly what you need. docs.ansible.com/ansible/latest/plugins/inventory.html, docs.ansible.com/ansible/latest/dev_guide/…Bixby
As best I can tell, ansible does not support any kind of real inclusion/inheritance with inventory files. It's unfortunate b/c it's pretty necessary for basic organization. E.g. two child inventory files (feature and production), with a parent inventory file with common stuff. My team is looking into symlinks as well, but it's not as clean as if true inclusion was just supported.Colpitis

© 2022 - 2024 — McMap. All rights reserved.