Überschreiben Sie die Hostvariable des Ansible-Playbooks über die Befehlszeile

109

Dies ist ein Fragment eines Playbooks, das ich verwende ( server.yml):

- name: Determine Remote User
  hosts: web
  gather_facts: false
  roles:
    - { role: remote-user, tags: [remote-user, always] }

Meine Hosts-Datei enthält verschiedene Servergruppen, z

[web]
x.x.x.x

[droplets]
x.x.x.x

Jetzt mag ich ausführen ansible-playbook -i hosts/<env> server.ymlund außer Kraft setzt hosts: webaus server.ymldiesem Textbuch zu laufen [droplets].

Kann ich nur einmal überschreiben, ohne server.ymldirekt zu bearbeiten ?

Vielen Dank.

luqo33
quelle

Antworten:

127

Ich glaube nicht, dass Ansible diese Funktion bietet, die es sollte. Folgendes können Sie tun:

hosts: "{{ variable_host | default('web') }}"

und Sie können variable_hostentweder über die Befehlszeile oder über eine Vars-Datei übergeben, z.

ansible-playbook server.yml --extra-vars "variable_host=newtarget(s)"
Wallydrag
quelle
3
Eine kleine Korrektur erforderlich. Es sollte seinhosts: "{{ variable_host | default('web')}}"
SPM
16
Hier ist eine Notiz, die meiner Meinung nach die Antwort für ansible Neulinge vervollständigen würde, die nach dieser Lösung suchen: Beispiel:ansible-playbook server.yml --extra-vars "variable_host=newtarget(s)"
Frobbit
1
WANN (dh in welcher Reihenfolge) ansible-Analysevariablen ausgeführt werden Variablen in group_vars/allscheinen nach der hosts:Zeile des Playbooks analysiert zu werden . Variablen in vars:und Variablen in vars_files:werden jedoch vor der hosts:Zeile analysiert . HINWEIS Ich frage nicht nach Vorrang.
Felipe Alvarez
2
Sie können auch -eanstelle von verwenden --extra-vars.
Nomen
Schauen Sie sich andere Antworten für weitere Details an
Anand Varkey Philips
63

Für alle, die nach einer Lösung suchen.
Spielbuch

- hosts: '{{ host }}'
  tasks:
  - debug: msg="Host is {{ ansible_fqdn }}"

Inventar

[web]
x.x.x.x

[droplets]
x.x.x.x

Befehl: ansible-playbook deplyment.yml -i hosts --extra-vars "host=droplets" So können Sie den Gruppennamen in den Extra-Vars angeben

Mrunal Gosar
quelle
2
Beachten Sie, dass Sie bei der Benennung von Variablen vorsichtig sein müssen. Ich habe dies mit getestet play_hostsund nicht die erwarteten Ergebnisse erhalten, weil ich vergessen habe, dass dies play_hostseine interne Ansible-Variable für alle Hosts im aktuellen Spiel ist.
Ryan Fisher
Ich nehme an, die Standardeinstellung sollte wie in der obigen Antwort festgelegt werden.
Kakaz
19

Dies ist etwas spät, aber ich denke, Sie könnten den --limit or -lBefehl verwenden, um das Muster auf spezifischere Hosts zu beschränken. (Version 2.3.2.0)

Du könntest haben - hosts: all (or group) tasks: - some_task

und dann ansible-playbook playbook.yml -l some_more_strict_host_or_pattern und verwenden Sie das --list-hostsFlag, um zu sehen, auf welchen Hosts diese Konfiguration angewendet werden würde.

Jonathan Hamel
quelle
3
Ich bin sehr neu in Ansible, aber ich halte dies für eine sehr effektive Lösung, viel kompakter als die anderen. Warum wurde es abgelehnt?
Alessandro Dentella
16
Das ist gefährlich. Falls man limitdie Liste der betroffenen Hosts vergisst, kann das Playbook großen Schaden anrichten.
Alexander Shcheblikin
3
Ich finde, dass die Verwendung --extra-vars "variable_host=newtarget(s)"genau wie die akzeptierte Lösung ebenso gefährlich und komplizierter ist. Es werden Standardhosts verwendet, webdie anstelle von hier auch angewendet werden können all. Sie können standardmäßig eine strenge Hostgruppe verwenden, um Fehler zu vermeiden, und das --list-hostsFlag verwenden, um ein klares Verständnis dafür zu erhalten, welche Hosts Sie betreffen.
Jonathan Hamel
3
Die Lösung mit zusätzlichen Variablen ermöglicht die Angabe einer leeren Gruppe (oder einer nicht vorhandenen) als Standardwert. Wenn Sie also vergessen, die Variable über die Befehlszeile anzugeben, passiert nichts Schlimmes. Lösung mit der Option "--limit" ist gefährlicher, da das Playbook keine leere Gruppe als Standardwert für die Hosts verwenden konnte. Die Option "--llmit" wird auf den Host-Wert angewendet, daher wird sie auf die leeren Gruppen angewendet und liefert ein leeres Ergebnis. Sie MÜSSEN also "all" oder einen anderen nicht leeren Host als Standardwert verwenden. Und eines Tages werden Sie vergessen, das Argument "--limit" anzugeben, und das Playbook wird auf alle Hosts angewendet.
Gregory Petukhov
4
Dies sollte mit der Antwort von @ TmTron kombiniert werden, um den Fall zu erfassen, in dem der Anrufer nicht geliefert hat --limit(andernfalls sind alle möglichen Hosts betroffen, was möglicherweise nicht das gewünschte Verhalten ist)
ncoghlan
14

Wir verwenden eine einfache Fail- Task, um den Benutzer zu zwingen, die Option Ansible Limit anzugeben , damit wir nicht standardmäßig / versehentlich auf allen Hosts ausgeführt werden.

Der einfachste Weg, den ich gefunden habe, ist folgender:

---
- name: Force limit
  # 'all' is okay here, because the fail task will force the user to specify a limit on the command line, using -l or --limit
  hosts: 'all'

  tasks:
  - name: checking limit arg
    fail:
      msg: "you must use -l or --limit - when you really want to use all hosts, use -l 'all'"
    when: ansible_limit is not defined
    run_once: true

Jetzt müssen wir die Option -l(= --limit) verwenden, wenn wir das Playbook ausführen, z

ansible-playbook playbook.yml -l www.example.com

Begrenzungsoptionsdokumente :

Beschränkung auf einen oder mehrere Hosts Dies ist erforderlich, wenn ein Playbook gegen eine Hostgruppe ausgeführt werden soll, jedoch nur gegen ein oder mehrere Mitglieder dieser Gruppe.

Beschränken Sie sich auf einen Host

ansible-playbook playbooks/PLAYBOOK_NAME.yml --limit "host1"

Beschränken Sie sich auf mehrere Hosts

ansible-playbook playbooks/PLAYBOOK_NAME.yml --limit "host1,host2"

Negiertes Limit.
HINWEIS: Um die Bash-Interpolation zu verhindern, MÜSSEN einfache Anführungszeichen verwendet werden.

ansible-playbook playbooks/PLAYBOOK_NAME.yml --limit 'all:!host1'

Beschränken Sie sich auf die Hostgruppe

ansible-playbook playbooks/PLAYBOOK_NAME.yml --limit 'group1'

TmTron
quelle
7

Ich verwende einen anderen Ansatz, der kein Inventar benötigt und mit diesem einfachen Befehl arbeitet:

ansible-playbook site.yml -e working_host=myhost

Dazu benötigen Sie ein Spielbuch mit zwei Spielen:

  • Das erste Spiel wird auf localhost ausgeführt und ein Host (aus einer bestimmten Variablen) in einer bekannten Gruppe im Speicherinventar hinzugefügt
  • Das zweite Spiel läuft auf dieser bekannten Gruppe

Ein funktionierendes Beispiel (kopieren Sie es und führen Sie es mit dem vorherigen Befehl aus):

- hosts: localhost
  connection: local
  tasks:
  - add_host:
      name: "{{ working_host }}"
      groups: working_group
    changed_when: false

- hosts: working_group
  gather_facts: false
  tasks:
  - debug:
      msg: "I'm on {{ ansible_host }}"

Ich benutze ansible 2.4.3 und 2.3.3

Nelson G.
quelle
7

Ich habe meinen Standardwert auf "Kein Host" geändert und habe einen Scheck, um ihn abzufangen. Auf diese Weise wird der Benutzer oder Cron gezwungen, einen einzelnen Host oder eine Gruppe usw. bereitzustellen. Ich mag die Logik aus dem Kommentar von @wallydrag. Das empty_groupenthält keine Hosts im Inventar.

- Hosts: "{{variable_host | default ('empty_group')}}"

Fügen Sie dann die Check-in-Aufgaben hinzu:

   Aufgaben:
   - name: Fehlgeschlagenes Skript, falls erforderlich Der Parameter variable_host fehlt
     Scheitern:
       msg: "Sie müssen --extra-vars = 'variable_host =' hinzufügen."
     wenn: (variable_host ist nicht definiert) oder (variable_host == "")
Tony-Caffe
quelle
5

Ich bin gerade auf dieses Googeln gestoßen, um eine Lösung zu finden. Tatsächlich gibt es eine in Ansible 2.5. Sie können Ihre Inventardatei --inventorywie folgt angeben :ansible --inventory configs/hosts --list-hosts all

Bebef
quelle
Ich glaube, dies ist die richtigste Antwort im Jahr unseres Herrn 2019. Aus Ansible 2.8.4's -h:-i INVENTORY, --inventory=INVENTORY, --inventory-file=INVENTORY specify inventory host path or comma separated host list. --inventory-file is deprecated
pyansharp
3

Wenn Sie eine Aufgabe ausführen möchten, die einem Host zugeordnet ist, jedoch auf einem anderen Host, sollten Sie delegate_to ausprobieren .

In Ihrem Fall sollten Sie an Ihren localhost (ansible master) delegieren und den ansible-playbookBefehl aufrufen

Nghnam
quelle
2

Ich verwende ansible 2.5 (genau 2.5.3) und es scheint, dass die vars-Datei geladen wird, bevor der Hosts-Parameter ausgeführt wird. Sie können den Host also in einer vars.yml- Datei festlegen und einfach hosts: {{ host_var }}in Ihr Playbook schreiben

Zum Beispiel in meinem playbook.yml:

---
- hosts: "{{ host_name }}"
  become: yes
  vars_files:
    - vars/project.yml
  tasks:
    ... 

Und in vars / project.yml:

---

# general
host_name: your-fancy-host-name
Lichtmann
quelle
0

Hier ist eine coole Lösung, die ich gefunden habe, um Hosts über die --limitOption sicher anzugeben . In diesem Beispiel wird das Spiel beendet, wenn das Spielbuch ohne Hosts ausgeführt wurde, die über die --limitOption angegeben wurden.

Dies wurde auf Ansible Version 2.7.10 getestet

---
- name: Playbook will fail if hosts not specified via --limit option.
  # Hosts must be set via limit. 
  hosts: "{{ play_hosts }}"
  connection: local
  gather_facts: false
  tasks:
  - set_fact:
      inventory_hosts: []
  - set_fact:
      inventory_hosts: "{{inventory_hosts + [item]}}"
    with_items: "{{hostvars.keys()|list}}"

  - meta: end_play
    when: "(play_hosts|length) == (inventory_hosts|length)"

  - debug:
      msg: "About to execute tasks/roles for {{inventory_hostname}}"
Sudo Seele
quelle
0

Eine andere Lösung besteht darin, die spezielle Variable zu verwenden, ansible_limitdie den Inhalt der --limitCLI-Option für die aktuelle Ausführung von Ansible darstellt.

- hosts: "{{ ansible_limit | default(omit) }}"

Wenn die --limitOption weggelassen wird, gibt Ansible eine Warnung aus, unternimmt jedoch nichts, da kein Host übereinstimmt.

[WARNING]: Could not match supplied host pattern, ignoring: None

PLAY ****************************************************************
skipping: no hosts matched
Manolo
quelle