We have a database that is populated with host and group information. I have searched through various documents on the ansible site and looked at the inventory plugins, but I am not sure how to implement what I need.
We currently have a custom lookup script that does what we need, so I am just trying to pass a call to this from ansible.
example:
hostlookup role dbservers
db1
db2
db3
I want to be able to pass the “dbservers” role/group to my custom inventory script.
ansible -i lookup.py dbservers -m ping
I am unclear on what sys.argv/argument ansible passes, on how to get this passed to an internal function for my custom inventory script.
“When the external node script is called with the single argument ‘–list’, the script must return a JSON hash/dictionary of all the groups to be managed.”
I have checked out the document before, but I am under the impression that I am not able to pass a group to my custom inventory script through the ansible command without making modifications to the ansible inventory modules. The database we have already organizes our hosts by role and returns the list of hostnames. I only need to pass the groupname to my inventory script. This doesn’t seem available without making modifications.
I’m unsure why you need to pass a groupname to your custom script, unless I am misunderstanding your use of groupname in this context. You can return structured JSON that groups hosts automatically, which you can then use in the ‘hosts’ specification in a playbook with ansible-playbook or from the command line with the ansible command.
However, with that aside, there are ways to get data from the command line into your inventory script. Many of the current inventory scripts do this using environment variables. An example would look like:
Maybe I am making too much of an assumption here. But generally you would store the host groupings in some way in your custom inventory/cmdb.
Then, using that information (hosts + groupings) you return something from your inventory script that looks similar to http://www.ansibleworks.com/docs/developing_inventory.html#id2 where the top level keys of the json response are the groups, that contain a list of hosts.
Also, you can have hosts in more than a single group.
But from my previous response, if you need to pass info into your inventory, you need to use environment variables.
This is exactly what my inventory/cmdb does already. At the heart of my custom script is basically a call that looks similar to ansibles output, but I also format into a json dictionary:
From custom_inventory.py script, i have a function called get_hosts_by_role and it looks like:
This works if I use the GROUP=“webservers”, then os.gentenv(‘GROUP’) and run the custom script manually with --list. But if I were to use a playbook or even a one-liner, how would I specify the group “webservers” and be able to pass that to the inventory or ansible to look up?
I feel like I am asking the same question over and over.
If your inventory script already provides these groups, you can simply use those groups wherever you are used to mentioning hosts or lists of hosts (in playbooks, on the command-line, ...)
Simply do:
ansible webservers -a 'ls'
ansible-playbook -l webservers playbook.yml
And you can also use them in set-theory compositions like:
BTW There is no need to make your inventory-script conditionally create groups. Just have your inventory-script create all possible groups you need all the time, and let ansible figure out what groups/hosts are needed simply by using them on the command-line or playbooks.
PS If you have lots of custom groups based around properties of hosts, you can make dynamic groups based on facts using the group_by module. This is quite powerful, however make sure the groups exist prior to using them (in all playbooks). You cannot use these dynamic groups on the command-line since they don't exist at that point (!).
In my-playbook.yml you specify “hosts: webservers” or “hosts: all”.
Generally, I just wouldn’t limit the output from the inventory script, and let the inventory script return all hosts and groups, still with the correct data structure with host groups.
GROUP=webservers ansible all -i /path/to/custom_inventory.py -m ping
In the above one-line examples, using web servers or all would give you the same thing, since you are limiting the response from your inventory script to only the webservers group.
If you just returned all hosts and groups, you could skip the GROUP=whatever part and just do something like:
Thanks for all the help everyone. The GROUP os env variable being passed just makes for a confusing simple one-liner call. I was hoping to find something similar to how saltstack can do a in-line list call with -L: salt -L web1,web2,web3 test.ping
I really do believe you are missing what we are saying. Either that or I am just uber confused about what you are doing that we are not providing you with an explanation for.
You do not need to limit the output of the inventory script itself, you do that filtering with the ansible/ansible-playbook commands. Your inventory should return all groups and hosts. The ansible and ansible-playbook commands offer the ability to filter the list of groups/hosts that you want to run the tasks on.
I appreciate your help, and I do understand what you are explaining. My inventory script does not return all my hosts with all respective groups. This is a limitation based on the number of hosts and how the api outputs a query on our end. I understand that ansible expects the inventory to return all hosts, but I was trying to circumnavigate the ansible call, and be able to pass through the group from the command arguments to get only a limited number of hosts.
Sounds like you need to address the limitations of your API in your the inventory script, if it’s returning a page full of data, just walk through the pages, and cache if need be.
Anyway, this is really a topic for ansible-devel, since this is development related.
I should say, if you want your script to respond to environment variables it of course can. for instance, if you were using ACME_FOO_CLOUD you might have it filter by paying attention to a ACME_FOO_CLOUD_REGION variable.
This is all 100% up to you.
Also, the aforementioned tooling should really give proper credit for it’s origins as we invented host selectors for Func and that’s where they came from