2014-02-27 2 views
9

Als Schutz gegen die Verwendung eines veralteten Playbooks möchte ich sicherstellen, dass ich eine aktualisierte Kopie des Git-Checkouts habe, bevor Ansible etwas auf den Servern ändern darf.Wie erhält man einen Ansible-Check, der nur einmal in einem Playbook ausgeführt wird?

So habe ich es versucht. Diese Aktion wird in einer Datei mit allen Spielen Büchern enthalten zu finden:

- name: Ensure local git repository is up-to-date 
    local_action: git pull 
    register: command_result 
    failed_when: "'Updating' in command_result.stdout" 

Das Problem ist, dass dieser Befehl einmal für jeden Knoten ansible verbindet ausgeführt wird, statt nur einmal für jedes Textbuch laufen. Wie kann ich das vermeiden?

Antwort

12

Aktualisiert

Als ich schrieb Faust meine Antwort (2014.02.27), hatte ansible keine eingebaute Unterstützung für eine Aufgabe ausgeführt wird nur einmal pro Textbuch, nicht einmal pro betroffenen Host, dass die Playbook wurde weiter ausgeführt. Als tlo writes wurde jedoch die Unterstützung dafür mit run_once: true in Ansible Version 1.7.0 (veröffentlicht am 06.08.2014) eingeführt. Mit dieser Funktion sollte die Beispielaufgabendefinition aus der Frage geändert werden, um das zu erreichen, was erforderlich ist.

Original-Antwort

[Die folgende Antwort meine vorgeschlagene Lösung für das jeweilige Problem wurde, sicherzustellen, dass der lokale git Zweig aktualisiert wird, bevor ansible die Aufgaben eines Textbuch läuft.]

Ich schrieb das folgende Ansible-Callback-Plug-in, das die Ausführung von Playbooks verhindert, wenn der aktuelle Git-Zweig nicht mehr synchron ist (entweder hinter oder entfernt ist) mit dem Remote-Zweig. Um sie zu verwenden, setzen Sie den folgenden Code in einer Datei wie callback_plugins/require_updated_git_branch.py in Ihrer Top-Level ansible Textbuch-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): 
    """Makes Ansible require that the current git branch is up to date. 
    """ 
    env_var_name = 'IGNORE_OUTDATED_GIT_BRANCH' 

    msg = 'OUTDATED GIT BRANCH: Your git branch is out of sync with the ' \ 
      'remote branch. Please update your branch (git pull) before ' \ 
      'continuing, or skip this test by setting the environment ' \ 
      'variable {0}=yes.'.format(env_var_name) 

    out_of_sync_re = re.compile(r'Your branch (is behind|and .* have diverged)', 
           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) 

Wenn zum Beispiel die lokale Niederlassung befindet sich hinter dem Remote-Zweig, der Befehl ansible-playbook site.yml stoppt früh mit dem folgenden Ausgang:

__________________________________________________________ 
/OUTDATED GIT BRANCH: Your git branch is out of sync with \ 
| the remote branch. Please update your branch (git pull) | 
| before continuing, or skip this test by setting the  | 
\ environment variable IGNORE_OUTDATED_GIT_BRANCH=yes. /
---------------------------------------------------------- 
     \ ^__^ 
     \ (oo)\_______ 
      (__)\  )\/\ 
       ||----w | 
       ||  || 

Und, wie die Kuh schon sagt, deaktivieren dies überprüfen Sie den Befehl wie ausführen können:

$ IGNORE_OUTDATED_GIT_BRANCH=yes ansible-playbook site.yml 

Th Diese Lösung löst nicht das generelle Problem, mehrere Ansible-Tasks mehr als einmal auszuführen, unabhängig von der Anzahl der beteiligten Hosts, stellt jedoch sicher, dass veraltete Playbooks nicht ausgeführt werden, und behandelt die von Ihnen erwähnten Bedenken bezüglich meiner alias-based suggestion.

Verwandte Themen