41 Stimmen

Wie lässt sich eine Ansible-Überprüfung im Playbook nur einmal ausführen?

Zum Schutz vor der Verwendung eines veralteten Playbooks möchte ich sicherstellen, dass ich eine aktualisierte Kopie des Git-Checkouts habe, bevor Ansible etwas auf den Servern ändert.

So habe ich versucht es zu tun. Diese Aktion befindet sich in einer Datei, die von allen Playbooks eingeschlossen ist:

- name: Stelle sicher, dass das lokale Git-Repository aktualisiert ist
  local_action: git pull
  register: command_result
  failed_when: "'Aktualisierung' in command_result.stdout"

Das Problem ist, dass dieser Befehl für jede Verbindung von Ansible zu einem Knoten einmal ausgeführt wird, anstatt nur einmal für jeden Playbook-Durchlauf. Wie kann ich das vermeiden?

44voto

Martin Thorsen Ranang Punkte 2337

Aktualisiert

Als ich meine Antwort zum ersten Mal geschrieben habe (2014-02-27), hatte Ansible keine eingebaute Unterstützung dafür, eine Aufgabe nur einmal pro Playbook auszuführen, nicht einmal pro betroffenem Host, auf dem das Playbook ausgeführt wurde. Der Support dafür wurde jedoch, wie tlo schreibt, mit run_once: true in Ansible-Version 1.7.0 (veröffentlicht am 2014-08-06) eingeführt. Mit dieser Funktion sollte die Beispielaufgabendefinition aus der Frage wie folgt geändert werden:

- name: Stellen Sie sicher, dass das lokale Git-Repository aktuell ist
  local_action: git pull
  run_once: true
  register: command_result
  failed_when: "'Updating' in command_result.stdout"

um das Gewünschte zu erreichen.

Ursprüngliche Antwort

[Die folgende Antwort war meine vorgeschlagene Lösung für das spezielle Problem sicherzustellen, dass der lokale Git-Zweig aktualisiert ist, bevor Ansible die Aufgaben eines Playbooks ausführt.]

Ich habe das folgende Ansible-Callback-Plugin geschrieben, das die Ausführung des Playbooks vermeidet, wenn der aktuelle Git-Zweig nicht mit dem Remote-Zweig synchron ist (entweder zurückliegt oder sich davon entfernt hat). Um es zu verwenden, platzieren Sie den folgenden Code in einer Datei wie callback_plugins/require_updated_git_branch.py in Ihrem übergeordneten Ansible-Playbook-Verzeichnis:

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import os
import re
import subprocess
import sys

from ansible.callbacks import display, banner

class CallbackModule(object):
    """Macht Ansible erforderlich, dass der aktuelle Git-Zweig auf dem neuesten Stand ist.
    """
    env_var_name = 'IGNORE_OUTDATED_GIT_BRANCH'

    msg = 'ÜBERHOLTER GIT-ZWEIG: Ihr Git-Zweig ist nicht mit dem ' \
          'Remote-Zweig synchron. Bitte aktualisieren Sie Ihren Zweig (git pull), bevor ' \
          'Sie fortfahren, oder überspringen Sie diesen Test, indem Sie die Umgebungsvariable ' \
          '{0}=yes setzen.'.format(env_var_name)

    out_of_sync_re = re.compile(r'Ihr Zweig (liegt zurück|und .* haben sich getrennt)',
                                re.MULTILINE)

    def __init__(self, *args, **kwargs):
        if os.getenv(self.env_var_name, 'no') == 'yes':
            self.disabled = True

    def playbook_on_start(self):
        subprocess.call(['git', 'fetch'])

        if self.out_of_sync_re.search(subprocess.check_output([
            'git', 'status', '--untracked-files=no'])):
            display(banner(self.msg), color='bright purple')
            sys.exit(1)

Zum Beispiel hält der Befehl ansible-playbook site.yml früh an, wenn der lokale Zweig hinter dem Remote-Zweig liegt, mit dem folgenden Output:

 __________________________________________________________
/ ÜBERHOLTER GIT-ZWEIG: Ihr Git-Zweig ist nicht mit \
| dem Remote-Zweig synchron. Bitte aktualisieren Sie Ihren \
| Zweig (git pull) bevor Sie fortfahren, oder überspringen \
\ Sie diesen Test, indem Sie die Umgebungsvariable IGNORE_OUTDATED_GIT_BRANCH=yes setzen. /
 ----------------------------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Und, wie die Kuh vorschlägt, um diese Überprüfung auszuschalten, können Sie den Befehl wie folgt ausführen:

$ IGNORE_OUTDATED_GIT_BRANCH=yes ansible-playbook site.yml

Diese Lösung löst nicht das allgemeine Problem, das jede Ansible-Aufgabe nur einmal ausgeführt wird, unabhängig von der Anzahl der beteiligten Hosts, stellt jedoch sicher, dass veraltete Playbooks nicht ausgeführt werden, und behandelt die von Ihnen erwähnte Sorge bezüglich meines aliasbasierten Vorschlags.

19voto

tlo Punkte 1545

Seit Version 1.7 von Ansible können Sie run_once: true verwenden, um eine Aufgabe nur einmal und nur auf einem Host auszuführen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X