Was ist das Äquivalent von Puppets "es sei denn" in Ansible?

9

Hintergrund: In Puppet kann ein Befehl ausgeführt werden, sofern er nicht bereits ausgeführt wurde:

exec { '/bin/echo root >> /usr/lib/cron/cron.allow':
  path   => '/usr/bin:/usr/sbin:/bin',
  unless => 'grep root /usr/lib/cron/cron.allow 2>/dev/null',
}

Ziel: Ausführen eines Befehls, sofern dieser nicht bereits in Ansible ausgeführt wurde

Methoden

Aufgaben / main.yml

- name: add vhost sensu
  command: rabbitmqctl add_vhost /sensu

Ergebnisse

TASK [ansible-rabbitmq : add vhost sensu] **************************************
fatal: [111.222.333.444]: FAILED! => {"changed": true, "cmd": ["rabbitmqctl",
"add_vhost", "/sensu"], "delta": "0:00:00.210140", "end": 
"2016-07-29 12:55:19.384455", "failed": true, "rc": 2, "start":
"2016-07-29 12:55:19.174315", "stderr": "Error: vhost_already_exists: /sensu", 
"stdout": "Creating vhost \"/sensu\" ...", "stdout_lines": 
["Creating vhost \"/sensu\" ..."], "warnings": []}

Diskussion

Googeln unless ansiblezeigte dieses Dokument überwhen . Basierend auf dieser Dokumentation wurde eine whenErklärung hinzugefügt:

- name: add vhost sensu
  command: rabbitmqctl add_vhost /sensu
  when: rabbitmqctl list_vhosts | grep sensu

Das Ausführen des Codes führte zu:

fatal: [192.168.0.9]: FAILED! => {"failed": true, "msg": "The conditional
 check 'rabbitmqctl list_vhosts | grep sensu' failed. The error was: template
 error while templating string: expected token 'end of statement block', got
 'list_vhosts'. String: {% if rabbitmqctl list_vhosts | grep sensu %} True {%
 else %} False {% endif %}\n\nThe error appears to have been in '/etc/ansible
/roles/ansible-rabbitmq/tasks/main.yml': line 10, column 3, but may\nbe
 elsewhere in the file depending on the exact syntax problem.\n\nThe
 offending line appears to be:\n\n\n- name: add vhost sensu\n  ^ here\n"}
  1. Stellen Sie sich zunächst vor, dass dies whenerfolgreich war, dann wird der Befehl nicht ausgeführt und sieht dann eher wie onlyifin Puppet aus .
  2. Zweitens, wenn das Wann erfolgreich wäre, sollte ein Eskalationszeichen verwendet werden, um ein Es sei denn?
  3. Verwendung vonregister . Was ist, wenn diese Datei verloren geht oder der vhost beispielsweise von einem Menschen entfernt wurde? Puppet unlessführt die Befehle immer aus, so dass klar ist, ob der Befehl ausgeführt werden muss.
030
quelle

Antworten:

9

Ich denke, was Sie suchen, ist Folgendes:

- name: get vhosts
  command: rabbitmqctl list_vhosts
  register: vhosts
  changed_when: false

- name: add vhost sensu
  command: rabbitmqctl add_vhost /sensu
  when: "'/sensu' not in vhosts.stdout"

Betreff: # 3 erstellt registerkeine Datei. Wenn Sie die Ausgabe von rabbitmqctl list_vhostsvia erfassen register, ist der Inhalt genauso gültig wie der aktuelle Status des Systems.

jscott
quelle
3

Das Problem ist die Leitung when: rabbitmqctl list_vhosts | grep sensu. Es ist hier nicht möglich, bash zu verwenden.

Sie müssen das rabbitmqctl list_vhosts | grep sensuin eine separate Aufgabe einfügen und das Ergebnis registrieren, um es in der when-Klausel zu verwenden. Sie können notFilter verwenden, um ein unlessähnliches Verhalten zu erzielen .

So etwas sollte funktionieren:

- name: Get rabbitmq vhosts.
  command: rabbitmqctl list_vhosts | grep sensu
  register: rabbitmq_vhosts

- name: add vhost sensu
  command: rabbitmqctl add_vhost /sensu
  when: not 'sensu' in rabbitmq_vhosts.stdout

Das Get rabbitmq vhosts.in diesem Beispiel wird immer ausgeführt. Das add vhost sensunur, wenn der String sensu nicht im registrierten ist rabbitmq_vhosts.

Weitere Informationen finden Sie in der Dokumentation zu Bedingungen und Jinja-Filtern .

Henrik Pingel
quelle
Das Problem besteht weiterhin:fatal: [IP]: FAILED! => {"changed": true, "cmd": ["rabbitmqctl", "add_vhost", "/sensu"], "delta": "0:00:00.198681", "end": "2016-07-29 13:43:00.870193", "failed": true, "rc": 2, "start": "2016-07-29 13:43:00.671512", "stderr": "Error: vhost_already_exists: /sensu", "stdout": "Creating vhost \"/sensu\" ...", "stdout_lines": ["Creating vhost \"/sensu\" ..."], "warnings": []}
030
hm, wahrscheinlich meine schuld. Ich denke es war eine fehlende .stdoutbearbeitete meine Antwort.
Henrik Pingel
0

Die whenOption ist das einzige, was Ansible in Bezug auf die Bedingungen hat. Sie können dort jedoch keinen Befehl direkt definieren. whenerwartet einen Jinja-Ausdruck und wird außerdem auf dem Ansible-Kontrollhost ausgewertet. Sie müssen also zuerst eine Aufgabe ausführen, um das Ergebnis abzurufen und zu registrieren.

- shell: rabbitmqctl list_vhosts | grep sensu
  register: sensu_vhosts

- name: add vhost sensu
  command: rabbitmqctl add_vhost /sensu
  when: sensu_vhosts.stdout_lines < 1

stdout_linesist ein Array aller Zeilen, die die Shell-Task zurückgegeben hat. Sie können also die Anzahl der Einträge zählen und Ihre Aufgabe nur ausführen, wenn 0 Elemente zurückgegeben wurden

Udondan
quelle
2
Wenn der / sensu vhost nicht existiert, führt dies zu:fatal: [IP]: FAILED! => {"changed": true, "cmd": "rabbitmqctl list_vhosts | grep sensu", "delta": "0:00:00.198769", "end": "2016-07-29 13:45:59.069981", "failed": true, "rc": 1, "start": "2016-07-29 13:45:58.871212", "stderr": "", "stdout": "", "stdout_lines": [], "warnings": []}
030