Git, Nagios und Hooks, beschädigtes Git Repo

14

Hintergrund

Wir verwenden Nagios, um unsere Infrastruktur zu überwachen. Wir haben die Nagios-Konfiguration derzeit nicht unter Versionskontrolle und es gibt zwei von uns, die die Nagios-Konfiguration verwalten. Als solches arbeite ich daran, unsere Nagios-Konfiguration in ein zentrales Git-Repo zu bringen, indem ich einige Hooks verwende, um die Syntax zu überprüfen, und wenn die Konfigurationen gut aussehen, mache ich sie "aktiv". Ich benutze den Beitrag dieses Typen als Ausgangspunkt.

Der allgemeine Workflow, den ich implementieren möchte, lautet:

  1. Bearbeiten Sie das lokale Git-Repo der Nagios-Konfiguration. Fügen Sie bearbeitete Dateien hinzu und übertragen Sie sie lokal.
  2. git push origin master zum Remote-Repo.
  3. Push wird vom Pre-Receive-Hook abgefangen, der die Dateien aufnimmt, in ein temporäres Verzeichnis auf dem Server verschiebt und sie über die Nagios-Syntaxprüfung ausführt.
  4. Wenn die Syntaxprüfung erfolgreich ist, akzeptieren Sie den Push, verwenden Sie den Post-Commit-Hook für git pullden neuen Code im Live-Nagios-Konfigurationsverzeichnis und starten Sie Nagios neu.
  5. Wenn die Syntaxprüfung fehlschlägt, lehnen Sie den Push ab und zeigen Sie dem Benutzer den Nagios-Syntaxfehler an.

Ich habe jedoch ein merkwürdiges Verhalten, wenn ich einen Git-Push aufgrund von Syntaxfehlern in der Nagios-Konfiguration ablehne. Was ich erwarte, ist, dass, wenn ich den Hook ablehne, der versuchte Push das Repository so lassen sollte, wie es war, unberührt. Dies scheint jedoch nicht der Fall zu sein. Nachfolgend finden Sie die Details zu dem, was ich sehe:

Problem

Ich bearbeite die Nagios-Konfiguration lokal, absichtlich einschließlich eines Syntaxfehlers, füge hinzu und bestätige dann lokal:

host:nagios erik$ vi nagios.cfg
host:nagios erik$ git add nagios.cfg
host:nagios erik$ git commit -m "syntax error"
[master da71aed] syntax error
 1 files changed, 1 insertions(+), 0 deletions(-)

Jetzt drücke ich diese Änderungen auf das Master-Repo. Dies wird aufgrund des Syntaxfehlers abgelehnt:

host:nagios erik$ git push origin master
Counting objects: 5, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 12.74 KiB, done.
Total 3 (delta 1), reused 2 (delta 1)
remote: Previous HEAD position was 3ddc880... removed syntax error
remote: HEAD is now at da71aed... syntax error
remote: Nagios Config Check Exit Status: 254
remote: Your configs did not parse correctly, there was an error. Output follows.
remote:
remote: Nagios Core 3.2.3
remote: Copyright (c) 2009-2010 Nagios Core Development Team and Community Contributors
remote: Copyright (c) 1999-2009 Ethan Galstad
remote: Last Modified: 10-03-2010
remote: License: GPL
remote:
remote: Website: http://www.nagios.org
remote: Reading configuration data...
remote: Error in configuration file '/tmp/nagiosworkdir/nagios.cfg' - Line 23 (NULL value)
remote:    Error processing main config file!
remote:
remote:
remote:
remote: ***> One or more problems was encountered while processing the config files...
remote:
remote:      Check your configuration file(s) to ensure that they contain valid
remote:      directives and data defintions.  If you are upgrading from a previous
remote:      version of Nagios, you should be aware that some variables/definitions
remote:      may have been removed or modified in this version.  Make sure to read
remote:      the HTML documentation regarding the config files, as well as the
remote:      'Whats New' section to find out what has changed.
remote:
To [email protected]:nagios
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to '[email protected]:nagios'

Dies hätte das Remote-Repo nicht berühren sollen , aber es tat es. Wenn ich in ein anderes lokales temporäres Verzeichnis wechsle und versuche, das Repo zu klonen, erhalte ich:

host:temp erik$ git clone [email protected]:nagios
Cloning into nagios...
remote: Counting objects: 30, done.
remote: Compressing objects: 100% (29/29), done.
remote: Total 30 (delta 12), reused 0 (delta 0)
Receiving objects: 100% (30/30), 29.81 KiB, done.
Resolving deltas: 100% (12/12), done.
error: Trying to write ref HEAD with nonexistant object da71aedfde2e0469288acd9e45bb8b57a6e5a7b3
fatal: Cannot update the ref 'HEAD'.

Jetzt gehe ich zurück zum ursprünglichen Arbeitsverzeichnis, behebe den Syntaxfehler, füge hinzu, übergebe und drücke:

host:nagios erik$ vi nagios.cfg
host:nagios erik$ git add nagios.cfg
host:nagios erik$ git commit -m "removing syntax error, push should succeed this time"
[master f147ded] removing syntax error, push should succeed this time
 1 files changed, 0 insertions(+), 2 deletions(-)
host:nagios erik$ git push origin master
Counting objects: 6, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 487 bytes, done.
Total 4 (delta 2), reused 0 (delta 0)
remote: Previous HEAD position was 4c80d45... syntax error
remote: HEAD is now at f147ded... removing syntax error, push should succeed this time
remote: Nagios Config Check Exit Status: 0
remote: Your configs look good and parsed correctly.
To [email protected]:nagios
   3ddc880..f147ded  master -> master

Zu diesem Zeitpunkt ist das Repository in Ordnung, und ich kann in ein temporäres Verzeichnis wechseln und das Repo erneut klonen:

host:temp erik$ git clone [email protected]:nagios
Cloning into nagios...
remote: Counting objects: 34, done.
remote: Compressing objects: 100% (33/33), done.
remote: Total 34 (delta 14), reused 0 (delta 0)
Receiving objects: 100% (34/34), 30.22 KiB, done.
Resolving deltas: 100% (14/14), done.

Hier ist der Pre-Receive- Hook, den ich verwende.

Ich verwende git v1.7.5.4 auf dem Client und v1.7.2.3 auf dem Server.

Also zur Frage : Warum bleibt das Repository in einem inkonsistenten Zustand, wenn ich den Push ablehne? Ist etwas schief mit meinem Git Haken oder fehlt vielleicht mein Verständnis von Git?

EEAA
quelle
Welche Version von Git benutzt du?
Robbyt
@robbyt - 1.7.5.4auf dem Client, 1.7.2.3auf dem Server.
EEAA

Antworten:

7

Sie gehen:

export GIT_WORK_TREE=/tmp/nagiosworkdir
/usr/bin/git checkout -f $NEW_SHA1

in deinem Haken. Obwohl es nicht die üblichen berührt Arbeiter kopieren wird Referenzen im git-Verzeichnis (speziell die Aktualisierung HEADReferenz), wie in Ihrem Fehler angezeigt:

...
remote: HEAD is now at da71aed... syntax error
...

Ihr Hook exit 1lehnt das Update zwar ab, setzt den HEADVerweis jedoch nach einem Fehler nicht (erneut) zurück.

Ich denke, Sie müssen den Fehlerzweig in Ihrem Hook wie folgt aktualisieren:

...
if [ "$NAGIOS_CHECK_STATUS" -ne 0 ]
   then
   echo "Your configs did not parse correctly, there was an error. Output follows."
   cat $GIT_WORK_TREE/check.out
   /usr/bin/git reset --hard $OLD_SHA1    # <-- Add This
   exit 1
else
   ...
nickgrim
quelle
Das sieht toll aus, Nickgrim. Ich werde es heute etwas später versuchen. Vielen Dank!
EEAA,
0

Der git checkoutBefehl in Ihrem Hook erstellt / aktualisiert die HEAD-Referenz in Ihrem Repository.

Wenn es sich bei Ihrem Repository um ein reines Repository handelt, kann es ohne eine HEAD-Referenz leben (neue Klone checken standardmäßig den Master- Zweig aus, falls vorhanden). Löschen Sie einfach die HEAD-Referenz vor dem Beenden (möglicherweise in einer, trapdamit Sie nicht vor jedem exiteinzelnen festlegen müssen ). Überall "früh" in Ihrem Skript:

trap 'git update-ref -m "removing HEAD after temporary checkout to alternate workdir" -d HEAD "$NEW_SHA1"' 0

Wenn Ihr Repository nicht leer ist oder Sie eine HEAD-Referenz beibehalten möchten (damit Klone standardmäßig einen anderen Zweig auschecken), müssen Sie die HEAD-Referenz speichern und vor dem Beenden wiederherstellen.

Setzen Sie zunächst im Repository des Servers den HEAD-Verweis zurück, um auf den Zweig zu verweisen, den Sie in neuen Klonen standardmäßig auschecken möchten:

git symbolic-ref -m 'setting default branch for new clones' HEAD refs/heads/master

Dann in Ihrem Hook-Skript (irgendwo vor Ihrer Kasse):

# Restore HEAD symref when exiting
saved_HEAD=$(git symbolic-ref HEAD)
trap 'git symbolic-ref -m "restoring HEAD after temporary checkout to alternate workdir" HEAD "$saved_HEAD"' 0

Übrigens pre-receivesollten Hooks sicherstellen, dass sie stdin vollständig lesen und alle Zeilen verarbeiten, die ihnen zugeführt werden. Das Beenden vor dem Verbrauchen aller Eingaben kann manchmal eine SIGPIPE auslösen git-receive-pack. Dies ist in Ihrem Fall wahrscheinlich nicht der Fall, wenn Sie immer nur eine Referenz auf einmal drücken (da Sie mindestens eine Zeile gelesen haben), es ist jedoch zu beachten. Wahrscheinlich ist es einfacher , diese Haken als zu tun , updateHaken , wo man nur brauchen , um zu einem Zeitpunkt mit einem ref betroffen sein und kann jeder ref Push einzeln ablehnen (vielleicht nur Sie kümmern sich um die Spitze zu halten Master „sauber“, während Sie überprüfen und über die Tipps anderer Branchen berichten, diese jedoch niemals ablehnen, damit sie für die Zusammenarbeit bei unvollständigen Arbeiten verwendet werden können).

Chris Johnsen
quelle