Dynamic Inventory Error

110 views
Skip to first unread message

Leon Pinkney

unread,
Dec 29, 2015, 5:24:31 PM12/29/15
to Ansible Project
Hi All,

I have been using Ansible for a few months now and have started to create some custom python scripts to enable me to implement tasks I haven't otherwise been able to do within standard playbooks.

My inventory file is starting to grow and since all of the information in it is currently available from a DB, I started to look at dynamic inventory.

I wanted to start by understanding the JSON required to build an inventory, so came up with the following code in an effort to understand it.  I realise that this is not a complete solution, it is purely for me to understand the required format of the data.

inv = {
   
"company": {
       
"hosts": [
           
"server",
           
"sensor"
       
]
   
},
   
"_meta": {
       
"hostvars": {
           
"server": {
               
"ansible_ssh_host" : "7.7.7.7",
               
"ansible_ssh_port" : "44"
           
},
           
"sensor": {
               
"ansible_ssh_host" : "7.7.7.7",
               
"ansible_ssh_port" : "33"
           
}
       
}
   
}
}
inv
= json.dumps(inv)

inventory
= ansible.inventory.Inventory(inv)

If I print inv, it comes out like so...

{"company": {"hosts": ["server", "sensor"]}, "_meta": {"hostvars": {"sensor": {"ansible_ssh_host": "7.7.7.7", "ansible_ssh_port": "44"}, "server": {"ansible_ssh_host": "7.7.7.7", "ansible_ssh_port": "33"}}}}

When I execute this code however, I get the following error.

Traceback (most recent call last):
  File "test_inventory.py", line 33, in <module>
    inventory = ansible.inventory.Inventory(inv)
  File "/usr/local/lib/python2.7/dist-packages/ansible/inventory/__init__.py", line 93, in __init__
    all.add_host(Host(tokens[0], tokens[1]))
  File "/usr/local/lib/python2.7/dist-packages/ansible/inventory/host.py", line 32, in __init__
    self.set_variable('ansible_ssh_port', int(port))
ValueError: invalid literal for int() with base 10: '"22"}'

I've tried removing the string quotes from the port number, but the problem persists.  If I remove the ansible_ssh_port lines, I get no errors.

Can anyone offer any advice?  I'm current running Ansible version 1.9.4 which I understand is the latest.

Thanks!

Matt Martz

unread,
Dec 29, 2015, 5:45:44 PM12/29/15
to ansible...@googlegroups.com
You cannot provide dynamic inventory JSON output, that would normally come from a script, directly to the Inventory class.  The first argument for Inventory is the `host_list`, which can be 1 of 3 things:

1) Path to ini formatted inventory file
2) Path to executable dynamic inventory script
3) Comma separated hosts list that looks like "foo,bar,baz" or at minimum "foo," with a trailing comma

Because your JSON has a comma in it, it get's split, and then we try to loop through and split things out.  At this point Ansible believes it finds a host called "ansible_ssh_host" with a port of "22" (including the quotes).


I have done what you are trying to do before, which required subclassing `Inventory` and overriding `parse_inventory` and subclassing `InventoryScript` and overriding `__init__` and `get_host_variables` in order to allow my new classes to just accept a JSON string like you are trying to do.

In the end, it is just easier, using a callable script, and passing that to `Inventory`.  So, basically move the `inv` assignment and do `print json.dumps(inv)` in a single script, and provide the path to that script to `ansible.inventory.Inventory`.



--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/01c098b0-f480-450c-b8df-441122c356a6%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Matt Martz
@sivel
sivel.net

Leon Pinkney

unread,
Dec 29, 2015, 5:45:47 PM12/29/15
to Ansible Project
Just to add, if I change the line to:
    "ansible_ssh_port" : 22

I get:

    ValueError: invalid literal for int() with base 10: '22}'

I edited "/usr/local/lib/python2.7/dist-packages/ansible/inventory/host.py" and before line 32 added:
    print '>>' + port + '<<'

Which outputs:
    >> 22}<<

Clearly, the information isn't being parsed correctly.  Is it my code, or a bug?

pixel fairy

unread,
Jan 5, 2016, 11:51:51 AM1/5/16
to Ansible Project
If your just trying to get the syntax of the json right, there are easier ways to test. heres the above as an inventory script.


#!/usr/bin/env python
import json

inv
= {

   
"company": {
       
"hosts": [
           
"server",
           
"sensor"
       
]
   
},
   
"_meta": {
       
"hostvars": {
           
"server": {
               
"ansible_ssh_host" : "7.7.7.7",
               
"ansible_ssh_port" : 44
           
},
           
"sensor": {
               
"ansible_ssh_host" : "7.7.7.7",
               
"ansible_ssh_port" : "33"
           
}
       
}
   
}
}

print(json.dumps(inv))


heres the output of some test commands with (with ansible 2.0rc8, but it should work the same with 1.9x)

$ ansible -i leon.py all --list-hosts
  hosts
(2):
    server
    sensor
$ ansible
-i leon.py sensor -m debug -a var=vars
sensor
| SUCCESS => {
   
"vars": {
       
"ansible_ssh_host": "7.7.7.7",
       
"ansible_ssh_port": "33",
       
"group_names": [
           
"company"
       
],
       
"inventory_hostname": "sensor",
       
"inventory_hostname_short": "sensor"
   
}
}

Reply all
Reply to author
Forward
0 new messages