Ansible dynamic inventory service concept

620 views Asked by At

I've been reading the ansible documentation on how to create a dynamic inventory. From what I understand I have to provide a json that is capable of outputing host_vars and group_vars.

With that in mind, how would I go about extending the group_vars and host_vars concepts to include the definition of service ?

In essence, my "end goal" would be to have something that allows me to define:

Host A has services A B C that would then turn into the corresponding host and group vars.

What is the best way to approach this? I have been thinking about maybe a database but I'm not quite sure on how to propperly abstract the service concept.

Thanks in advance for any help

1

There are 1 answers

0
gantte On

I cannot give you all your answers, I just started using Ansible four weeks ago. However, I have successfully integrated dynamic inventories. Here's what I can share: (extrapolate for your setup, I'm in a RHEL shop, using 6.9 and 7.4)

  1. By default, ansible looks for your inventory in a file found at /etc/ansible/hosts The default format for that file is (I believe) INI format. [servers] server-1 server-2

[labhosts] labhost-1 labhost-2

[localhost] 127.0.0.1

  1. /etc/ansible/ansible.cfg will allow you relocate your inventory file/directory if needed. For now, my comments will assume no changes from the default

  2. The example above is static inventory. You can move your /etc/ansible/hosts file aside, then do: mkdir /etc/ansible/hosts/

  3. mv your hosts file, into /etc/ansible/hosts/hosts It's OK, to have static inventory files inside your dynamic directory (for now) So the beauty is, you can still use static inventory, it just now lives in /etc/ansible/etc/ <-- directory There is nothing special about the static filename. It can be any name, however some chars are not valid as part of the static file names.

  4. To use dynamic inventory, you now only need to put into the /etc/ansible/hosts/ directory, executable scripts that pull your hostnames from some external database. AND, this is the KEY part, the output (the stdout) of that script MUST output in JSON format.

  5. When ansible looks for your inventory files, it will "see" that /etc/ansible/hosts/ is a dir and then look in there for scripts. When you run a play or playbook, it will execute the script, and use the JSON output as your host targets of your play.
  6. Now, I'm no JSON expert, but here's what works for me. The syntax of the JSON is like this: {"GROUPNAME":["HOST1","HOST2","HOST3",]}
  7. So the entire string is bounded by left and right curly braces. The first field is the quoted groupname, separated by a colon, then the comma delimited list of quoted hosts, bounded by left and right square brackets.

In my environment, we have a perl script, and based on switch parameters, pulls lists of hostnames. We recently modified the perl script, using print statements to generate the JSON output. There is a JSON: perl module, but we didn't find it necessary to use, as formatting the output using print was sufficient. As for the groupname, we also "built" that groupname from the switch settings on the perl script.

So using my INI inventory example above, the JSON output would be something like this: {"servers":["server-1","server-2",]}

Note1: One quirk that I've learned, if you only have ONE host, it must be terminated with a comma. There's a reason, I'm not sure I can explain it. When we are generating our JSON output, we add a comma, regardless of the number of hosts, and it just works.

Note2: I realize this is not real JSON output, but it's working for our needs.

In your playbooks, you would put - hosts: all or - hosts: your_group_name I usually just put - hosts: all, then limit using -i option and/or "--limit=hostname"

"-i", narrows your inventory to just the static or dynamic generated list --limit=hostname where "hostname" is one of the subset of -i output.

Consider this command: ansible all -m ping This will ping all hosts in your entire inventory. Both static and dynamic

ansible all -m ping -i servers This will ping all hosts in your servers group

ansible all -m ping -i server --limit=server-1 This will ping just the one host, "server-1" Using --limit= is great for testing plays or playbooks

When moving on to playbooks, you specify the hostlist, in the playbook. Then you only need to add limits as needed, on the command line.

Good luck!