Background
I have domain managed via Terraform and it outputs server IP address. Then I have a script which outputs YAML inventory (outputs follows later).
- Ansible 2.6.2
- Source of format: https://docs.ansible.com/ansible/2.6/user_guide/intro_inventory.html#hosts-and-groups
Problem
When I run ansible-inventory --inventory inventory.sh --graph
it always end up with
@all:
|--@stage:
|--@ungrouped:
| |--18.66.1.28
Were I would expect the machine to be in group stage.
I found out there is different behaviour for static inventory and for inventory as a script output.
Static file
If You save this as a static file and use it as an inventory, it will work.
all:
hosts:
18.66.1.28
children:
stage:
hosts:
18.66.1.28:
Output:
@all:
|--@stage:
| |--18.66.1.28
|--@ungrouped:
Script
but if You specify shell script like follows, it won't work
#!/bin/bash
echo "all:
hosts:
18.66.1.28
children:
stage:
hosts:
18.66.1.28:"
Output:
[WARNING]: * Failed to parse /tmp/inventory.sh with script plugin: You defined a group 'all' with bad data for the host list: {u'hosts':
u'18.66.1.28', u'children': {u'stage': {u'hosts': {u'18.66.1.28': None}}}}
[WARNING]: * Failed to parse /tmp/inventory.sh with ini plugin: /tmp/inventory.sh:3: Error parsing host definition 'echo "all:': No closing
quotation
[WARNING]: Unable to parse /tmp/inventory.sh as an inventory source
[WARNING]: No inventory was parsed, only implicit localhost is available
YAML outputs
Variant 1
all:
hosts:
- 18.66.1.28
children:
stage:
hosts:
- 18.66.1.28:
Variant 2
all:
hosts:
- 18.66.1.28
children:
stage:
hosts:
18.66.1.28:
Variant 3
all:
hosts:
- 18.66.1.28
children:
stage:
hosts:
- 18.66.1.28
Best Answer
Short answer
Don't look at https://docs.ansible.com/ansible/2.6/user_guide/intro_inventory.html but at https://docs.ansible.com/ansible/2.6/dev_guide/developing_inventory.html.
Long answer
Ansible is using at least three formats for inventories. YAML, INI and JSON. INI format is completely separate format with its own structure. YAML and JSON per-se allows to create pretty much same data structures. When I look at https://docs.ansible.com/ansible/2.6/user_guide/intro_inventory.html full of YAML examples, using JSON I would just change the notation to produce same data structure as with YAML. The thing is, script plugin is using different different data structure, but it allows you to use both YAML and JSON format.
Examples
Static inventoryInput:
Output
This is correct format and behaviour according to https://docs.ansible.com/ansible/2.6/user_guide/intro_inventory.html .
ScriptInput:
Output:
This is not what I would expect. Problem is the script plugin expects different data structure. Let’s try this with data structure from https://docs.ansible.com/ansible/2.6/dev_guide/developing_inventory.html.
Input:
Output
Yes this is the result I expected. The machine is in the right group and the ingesting plugin is not complaining about anything. Of course according to the “Dynamic Inventory Sources”, the script should do a bit more than just
echo
the inventory and it should probably output JSON, this is just demonstration of how to structure the output of a scripted inventory.This took me quite a lot of time to figure out, so I hope by writing this I'll save it to somebody else.