Wie kann man Ansible ausführen, ohne das Inventar, aber den Host direkt anzugeben?

78

Ich möchte Ansible in Python ausführen, ohne die Inventardatei durch (ANSIBLE_HOST) anzugeben, aber nur durch:

ansible.run.Runner(
  module_name='ping',
  host='www.google.com'
)

Ich kann das eigentlich leicht in Stoff machen, aber ich frage mich nur, wie ich das in Python machen soll. Andererseits ist die Dokumentation der Ansible-API für Python nicht wirklich vollständig.

Ngoc Tran
quelle

Antworten:

173

Überraschenderweise besteht der Trick darin, a anzuhängen ,

# Host and IP address
ansible all -i example.com,
ansible all -i 93.184.216.119,

oder

# Requires 'hosts: all' in your playbook
ansible-playbook -i example.com, playbook.yml

Der Host-Parameter vor dem ,kann entweder ein Hostname oder eine IPv4 / v6-Adresse sein.

trkoch
quelle
1
Wenn Sie in Ansible 1.9.1 ansible-playbook aufrufen, entfernen Sie "all" von der Befehlszeile, lassen Sie es jedoch in der playbook.yml. Dies ist die richtige Antwort "ansible-playbook -i example.com,
playbook.yml
1
Was sollte ich dann im Playbook als "Host" festlegen, damit es mit jedem Server funktioniert?
Azmeuk
2
@azmeuk im Playbook, "Hosts: All" sollte gut funktionieren. Normalerweise mache ich das und benutze dann -i oder --limit in der Befehlszeile, um die Hosts anzugeben.
Dave
Was ist, wenn ein Playbook zwei verschiedene Phasen mit Verbindungen zu verschiedenen Hosts / IPs hat? Hinweis Ich möchte nicht einen Abschnitt gegen mehrere IPs ausführen, sondern 2 verschiedene Abschnitte gegen verschiedene IPs ausführen.
openCivilisation
53

Ich weiß, dass diese Frage wirklich alt ist, aber ich denke, dass dieser kleine Trick für zukünftige Benutzer hilfreich sein könnte, die Hilfe dafür benötigen:

ansible-playbook -i 10.254.3.133, site.yml

Wenn Sie für einen lokalen Host ausgeführt werden:

ansible-playbook -i localhost, --connection=local site.yml

Der Trick ist, dass Sie nach der IP-Adresse / dem DNS-Namen das Komma in die Anführungszeichen setzen und ' hosts: all' in Ihrem Playbook benötigen .

Hoffe das wird helfen.

Arbab Nazar
quelle
6
Für das, was es wert ist, sind die Zitate hier ein No-Op. Wenn Sie 'localhost,'oder verwenden localhost,, erhalten Sie in beiden Fällen ansible-playbookdas gleiche Argument von der Shell. Und 'localhost',würde genauso auswerten (der Schlüssel hier ist, dass Anführungszeichen von der Shell interpretiert werden, bevor sie die Argumente an Ihren Befehl weitergibt).
Larsks
7
Das funktioniert, aber warum im Namen von Merlins Bart ist dieses akzeptable Verhalten von Ansible?! Wie genau sollen die Leute das wissen? Ich riss mir die Haare aus und suchte nach dem besagten Fix.
Jungvogel
1
Ich weiß, dass ich zu spät komme, aber ich bin gerade auf Ihren Kommentar gestoßen und wollte hier einen Einblick geben. Der Grund dafür ist, dass Sie für das Flag -i ein gültiges Inventarziel übergeben müssen. Dies kann eine INI-Datei, eine ausführbare Ansible-gültige Inventardatei oder eine beliebige Zeichenfolge sein, die von einem Ansible-Inventar-Plugin verarbeitet werden kann. Es gibt ein Ansible-Plugin namens "host_list", das eine durch Kommas getrennte Liste von Hosts verwendet und diese Informationen verwendet, um ein sofortiges Inventar zu erstellen, mit dem Ad-hoc-Befehle auf unbekannten Hosts ausgeführt werden können. Dieses Plugin ist standardmäßig in Ansible enthalten.
Héctor Luaces Novo
Ich finde es ein bisschen riskant, ein Playbook zu haben, hosts: allwenn ich beabsichtige, es jeweils nur auf einem Host auszuführen. Ein Mitarbeiter kann das Playbook ohne ausführen -i. Dies ist eine schöne Lösung, aber ich suche weiterhin nach etwas Sichererem. Immer noch auf der Suche ...
Donn Lee
7

Sie können dies tun mit:

hosts = ["webserver1","webserver2"]

webInventory = ansible.inventory.Inventory(hosts)

webPing = ansible.runner.Runner(
    pattern='webserver*',
    module_name='ping',
    inventory = webInventory
).run()

Was auch immer in Hosts ist, wird zu Ihrem Inventar und Sie können es mit Muster durchsuchen (oder "alle" tun).

Seumasmac
quelle
Wissen Sie, wie man ein Modul im Kontext local_action ausführt? Beispielsweise sollten ec2-Module gegen localhost (127.0.0.1) und als local_action aufgerufen werden. danke
kamiseq
egal, ich beantworte meine eigene Frage :-) Runner = ansible.Runner (Modulname = "ec2_group", complex_args = {}, Gabeln = Paralel, # private_key_file = "~ / .ssh / office.pem", Inventar = Inventar ([ "127.0.0.1"]), transport = "local") return running.run ()
kamiseq
6

In meinem Fall wollte ich nicht hosts: allin meinem Spielbuch haben, weil es schlecht wäre, wenn jemand das Spielbuch laufen lassen und vergessen würde, es aufzunehmen-i 10.254.3.133,

Dies war meine Lösung (ansible 2.6):

$ ansible-playbook myplaybook.yml -e "{target: 10.1.1.1}" -i 10.1.1.1, ...

Und dann im Spielbuch:

- hosts: "{{ target }}"
  remote_user: donn
  vars_files:
    - myvars
  roles:
    - myrole

Dies ist ein spezieller Anwendungsfall, wenn ich einen Host bereitstellen muss und ihn nicht zum Inventar hinzufügen möchte / muss.

Donn Lee
quelle
1

Ich musste auch die Ansible Python-API steuern und würde lieber Hosts als Argumente übergeben, als ein Inventar zu führen. Ich habe eine temporäre Datei verwendet, um die Anforderungen von Ansible zu umgehen, die für andere hilfreich sein können:

from tempfile import NamedTemporaryFile

from ansible.inventory import Inventory
from ansible.runner import Runner

def load_temporary_inventory(content):
    tmpfile = NamedTemporaryFile()
    try:
        tmpfile.write(content)
        tmpfile.seek(0)
        inventory = Inventory(tmpfile.name)
    finally:
        tmpfile.close()
    return inventory

def ping(hostname):
    inventory = load_temporary_inventory(hostname)
    runner = Runner(
        module_name='ping',
        inventory=inventory,
    )
    return runner.run()
billkw
quelle
Können Sie auch ein Beispiel geben, wie Sie es verwenden
Arbab Nazar
0

Dies ist keine vollständige Antwort, aber es gibt einige Diskussionen zu diesem Thema in diesem Diskussionsthread . Am Ende des ersten Beitrags in diesem Thread wird vorgeschlagen, ein Wrapper-Bash-Skript für Ansible-Playbook zu erstellen, das ein bisschen hackig, aber praktikabel ist.

Andere Dinge, die ich in Betracht gezogen habe, sind die Verwendung von 'Ansible-Pull' und die Erstellung eines Ansible-Inventar-Plugins. Ich bin auch daran interessiert, die Antwort auf diese Frage zu finden, und ich werde diese Antwort weiter aktualisieren, sobald ich weitere Informationen finde.

bnsmith
quelle