2016-06-03 10 views
9

Gibt es eine Möglichkeit, die Ansible Python-API zu verwenden, um eine Liste von Hosts aus einer bestimmten Kombination aus Inventardatei und -gruppe abzurufen?Wie kann ich eine Liste von Hosts aus einer Ansible-Inventardatei abrufen?

Zum Beispiel unsere Inventardateien werden vom Diensttyp aufgeteilt:

[dev:children] 
dev_a 
dev_b 

[dev_a] 
my.host.int.abc.com 

[dev_b] 
my.host.int.xyz.com 


[prod:children] 
prod_a 
prod_b 

[prod_a] 
my.host.abc.com 

[prod_b] 
my.host.xyz.com 

Kann ich ansible.inventory in irgendeiner Weise verwenden, in einer bestimmten Inventardatei zu übergeben, und die Gruppe möchte ich auf handeln und haben Gibt es eine Liste der Hosts zurück, die übereinstimmen?

Antwort

6

ich damit auch für eine Weile zu kämpfen hatte, aber eine Lösung durch Versuch gefunden & Fehler.

Einer der Hauptvorteile der API besteht darin, dass Sie Variablen und Metadaten abrufen können, nicht nur Hostnamen.

ab Python API - Ansible Documentation:

#!/usr/bin/env python 
# Ansible: initialize needed objects 
variable_manager = VariableManager() 
loader = DataLoader() 

# Ansible: Load inventory 
inventory = Inventory(
    loader = loader, 
    variable_manager = variable_manager, 
    host_list = 'hosts', # Substitute your filename here 
) 

Dies gibt Ihnen eine Bestands Instanz, die Methoden und Eigenschaften bieten Gruppen und Hosts hat.

Um weiter zu expandieren (und Beispiele für Gruppen- und Host-Klassen bereitzustellen), hier ist ein Snippet, das das Inventar als eine Liste von Gruppen serialisiert, wobei jede Gruppe ein "hosts" -Attribut hat, das eine Liste der Attribute jedes Hosts ist .

#/usr/bin/env python 
def serialize(inventory): 
    if not isinstance(inventory, Inventory): 
     return dict() 

    data = list() 
    for group in inventory.get_groups(): 
     if group != 'all': 
      group_data = inventory.get_group(group).serialize() 

      # Seed host data for group 
      host_data = list() 
      for host in inventory.get_group(group).hosts: 
       host_data.append(host.serialize()) 

      group_data['hosts'] = host_data 
      data.append(group_data) 

    return data 

# Continuing from above 
serialized_inventory = serialize(inventory) 

Ich lief dies gegen mein Labor von vier F5 BIG-IP-Adressen, und das ist das Ergebnis (getrimmt):

<!-- language: lang-json --> 
[{'depth': 1, 
    'hosts': [{'address': u'bigip-ve-03', 
      'name': u'bigip-ve-03', 
      'uuid': UUID('b5e2180b-964f-41d9-9f5a-08a0d7dd133c'), 
      'vars': {u'hostname': u'bigip-ve-03.local', 
         u'ip': u'10.128.1.130'}}], 
    'name': 'ungrouped', 
    'vars': {}}, 
{'depth': 1, 
    'hosts': [{'address': u'bigip-ve-01', 
      'name': u'bigip-ve-01', 
      'uuid': UUID('3d7daa57-9d98-4fa6-afe1-5f1e03db4107'), 
      'vars': {u'hostname': u'bigip-ve-01.local', 
         u'ip': u'10.128.1.128'}}, 
      {'address': u'bigip-ve-02', 
      'name': u'bigip-ve-02', 
      'uuid': UUID('72f35cd8-6f9b-4c11-b4e0-5dc5ece30007'), 
      'vars': {u'hostname': u'bigip-ve-02.local', 
         u'ip': u'10.128.1.129'}}, 
      {'address': u'bigip-ve-04', 
      'name': u'bigip-ve-04', 
      'uuid': UUID('255526d0-087e-44ae-85b1-4ce9192e03c1'), 
      'vars': {}}], 
    'name': u'bigip', 
    'vars': {u'password': u'admin', u'username': u'admin'}}] 
+0

Auch, wenn Sie nur die Host-Namen brauchen, ist die Antwort von @MattDavis besser und einfacher wäre, in einem nicht-Python-Skript zu nennen. – Theo

+1

Noch etwas zu beachten - wir dokumentieren keine externen Anrufer und unterstützen sie nicht bei der Ansible Python API. Es unterstützt unsere Kommandozeilen-Tools. Offensichtlich ist es Open Source und Sie können frei tun, was Sie wollen, aber seien Sie gewarnt: Wir unternehmen keine Anstrengungen, um Änderungen zu vermeiden, selbst zwischen kleineren/Patch-Releases. – nitzmahone

11

den gleichen Trick aus der Zeit vor, aber statt all, den Gruppennamen Sie auflisten möchten passieren:

ansible (group name here) -i (inventory file here) --list-hosts

0

Ich hatte ein ähnliches Problem und ich denke, nitzmahone Ansatz von nicht ungestützt mit ruft die Python-API auf. Hier ist eine Arbeitslösung, die sich auf die schön JSON-formatierte Ausgabe von ansible-inventory CLI:

pip install ansible==2.4.0.0 sh==1.12.14 

Ein Beispiel Inventardatei, inventory/qa.ini:

[lxlviewer-server] 
id-qa.kb.se 

[xl_auth-server] 
login.libris.kb.se 

[export-server] 
export-qa.libris.kb.se 

[import-server] 
import-vcopy-qa.libris.kb.se 

[rest-api-server] 
api-qa.libris.kb.se 

[postgres-server] 
pgsql01-qa.libris.kb.se 

[elasticsearch-servers] 
es01-qa.libris.kb.se 
es02-qa.libris.kb.se 
es03-qa.libris.kb.se 

[tomcat-servers:children] 
export-server 
import-server 
rest-api-server 

[flask-servers:children] 
lxlviewer-server 
xl_auth-server 

[apache-servers:children] 
lxlviewer-server 

[nginx-servers:children] 
xl_auth-server 

Eine Python 2.7 Funktion zu extrahieren info (leicht erweiterbar auf hostvars et cetera):

import json 
from sh import Command 

def _get_hosts_from(inventory_path, group_name): 
    """Return list of hosts from `group_name` in Ansible `inventory_path`.""" 
    ansible_inventory = Command('ansible-inventory') 
    json_inventory = json.loads(
     ansible_inventory('-i', inventory_path, '--list').stdout) 

    if group_name not in json_inventory: 
     raise AssertionError('Group %r not found.' % group_name) 

    hosts = [] 
    if 'hosts' in json_inventory[group_name]: 
     return json_inventory[group_name]['hosts'] 
    else: 
     children = json_inventory[group_name]['children'] 
     for child in children: 
      if 'hosts' in json_inventory[child]: 
       for host in json_inventory[child]['hosts']: 
        if host not in hosts: 
         hosts.append(host) 
      else: 
       grandchildren = json_inventory[child]['children'] 
       for grandchild in grandchildren: 
        if 'hosts' not in json_inventory[grandchild]: 
         raise AssertionError('Group nesting cap exceeded.') 
        for host in json_inventory[grandchild]['hosts']: 
         if host not in hosts: 
          hosts.append(host) 
     return hosts 

Beweis, dass es funktioniert (auch mit Kind und Enkelkind-Gruppen):

In [1]: from fabfile.conf import _get_hosts_from 

In [2]: _get_hosts_from('inventory/qa.ini', 'elasticsearch-servers') 
Out[2]: [u'es01-qa.libris.kb.se', u'es02-qa.libris.kb.se', u'es03-qa.libris.kb.se'] 

In [3]: _get_hosts_from('inventory/qa.ini', 'flask-servers') 
Out[3]: [u'id-qa.kb.se', u'login.libris.kb.se'] 

In [4]: 
1

Für mich ist folgende

from ansible.parsing.dataloader import DataLoader 
from ansible.inventory.manager import InventoryManager 

if __name__ == '__main__': 
    inventory_file_name = 'my.inventory' 
    data_loader = DataLoader() 
    inventory = InventoryManager(loader = data_loader, 
          sources=[inventory_file_name]) 

    print(inventory.get_groups_dict()['spark-workers']) 

inventory.get_groups_dict() gibt einen Wörterbuch, das Sie Hosts zu erhalten, indem mit der group_name als Schlüssel verwenden können, wie im Code dargestellt. Sie müssen ansible Paket installieren Sie von pip tun können wie folgt

pip install ansible 
Verwandte Themen