git, nagios e hook, corrotto repository git


14

sfondo

Stiamo utilizzando nagios per monitorare la nostra infrastruttura. Al momento non disponiamo delle configurazioni nagios sotto il controllo della versione e siamo in due a gestire la configurazione di nagios. Come tale, sto lavorando per portare i nostri nagios config in un repository git centrale, usando alcuni hook per fare il controllo della sintassi e poi se i config sembrano buoni, li rendono "attivi". Sto usando il post di questo ragazzo come punto di partenza.

Il flusso di lavoro generale che sto cercando di implementare è:

  1. Modifica il repository git locale di nagios config. Aggiungi file modificati, esegui il commit a livello locale.
  2. git push origin master al repository remoto.
  3. Il push viene intercettato dal hook di pre-ricezione, che prende i file, li sposta in una directory temporanea sul server e li esegue attraverso il controllo della sintassi nagios.
  4. Se il controllo sintassi passa, accetta il push, quindi usa l'hook post-commit git pullsul nuovo codice nella directory di configurazione di nagios live e quindi riavvia nagios.
  5. Se il controllo sintassi non riesce, rifiuta il push, mostrando all'utente l'errore di sintassi nagios.

Sto riscontrando un comportamento strano, tuttavia, quando rifiuto una spinta git a causa di errori di sintassi nella configurazione di nagios. Quello che mi aspetto che accada è che se rifiuto l'hook, la tentata spinta dovrebbe lasciare intatto il repository così com'era. Questo non sembra essere il caso, comunque. Di seguito sono riportati i dettagli di ciò che vedo:

Problema

Modifico localmente la configurazione di nagios, includendo intenzionalmente un errore di sintassi, aggiungo, quindi eseguo il commit a livello locale:

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(-)

Ora invio quelle modifiche al repository principale. Questo sarà rifiutato a causa dell'errore di sintassi:

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 git@remote-server.example.com:nagios
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'git@remote-server.example.com:nagios'

Ciò non avrebbe dovuto toccare il repository remoto, ma è stato così. Se passo a un'altra directory temporanea locale e provo a clonare il repository, ottengo:

host:temp erik$ git clone git@remote-server.example.com: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'.

Ora torno alla directory di lavoro originale, correggo l'errore di sintassi, aggiungo, eseguo il commit e invio:

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 git@remote-server.example.com:nagios
   3ddc880..f147ded  master -> master

A questo punto, il repository va bene e sono in grado di passare a una directory temporanea e clonare nuovamente il repository:

host:temp erik$ git clone git@remote-server.example.com: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.

Ecco l' hook di pre-ricezione che sto usando.

Sto usando git v1.7.5.4 sul client e v1.7.2.3 sul server.

Quindi, alla domanda : perché il repository viene lasciato in uno stato incoerente quando rifiuto la spinta? C'è qualcosa di storto nel mio gancio Git o forse manca la mia comprensione di Git?


Quale versione di Git stai usando?
Robbyt,

@robbyt: 1.7.5.4sul client, 1.7.2.3sul server.
EEAA,

Risposte:


7

Stai facendo:

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

nel tuo gancio. Sebbene non stia toccando la solita copia di lavoro, sta aggiornando i riferimenti in git-dir (in particolare il HEADriferimento), come mostrato nell'errore:

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

Il tuo hook sta facendo exit 1per rifiutare l'aggiornamento, ma non sta reimpostando il HEADriferimento dopo un errore.

Penso che sia necessario aggiornare il ramo di errore nel gancio in questo modo:

...
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
   ...

Sembra fantastico, nickgrim. Ci proverò un po 'più tardi oggi. Grazie!
SEE

0

Il git checkoutcomando nel tuo hook sta creando / aggiornando il riferimento HEAD nel tuo repository.

Se il tuo repository è un repository nudo, può vivere senza un riferimento HEAD (i nuovi cloni eseguiranno il checkout del ramo principale , se ne ha uno); basta eliminare il riferimento HEAD prima di uscire (forse in trapmodo da non dover provvedere a farlo prima di ognuno exitsingolarmente). Ovunque "in anticipo" nella tua sceneggiatura:

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

Se il tuo repository non è nudo o desideri mantenere un riferimento HEAD (in modo che i cloni, per impostazione predefinita, controllino qualche altro ramo), dovrai salvare il riferimento HEAD e ripristinarlo prima di uscire.

Innanzitutto, nel repository del server, reimpostare il riferimento HEAD in modo che punti al ramo che si desidera estrarre per impostazione predefinita nei nuovi cloni:

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

Quindi, nello script hook (ovunque prima del checkout):

# 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

A proposito, i pre-receiveganci dovrebbero assicurarsi di leggere completamente lo stdin ed elaborare tutte le linee che vengono alimentate. Uscire prima di consumare tutto l'input a volte può innescare un SIGPIPE nel git-receive-packprocesso; questo probabilmente non si presenta nel tuo caso se si preme solo un riferimento alla volta (poiché si legge almeno una riga), ma è qualcosa da tenere a mente. Probabilmente è più facile fare questo hook come updatehook dove devi preoccuparti solo di un ref alla volta e puoi rifiutare la spinta di ogni ref singolarmente (forse ti interessa solo mantenere la punta del master "pulita"; mentre controlli e riferire sui suggerimenti di altri rami, ma non rifiutarli mai in modo che possano essere utilizzati per la collaborazione su lavori incompleti).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.