git, nagios et hooks, git repo corrompu


14

Contexte

Nous utilisons des nagios pour surveiller notre infrastructure. Nous n'avons pas les configurations nagios sous contrôle de version pour le moment, et nous sommes deux à gérer la configuration des nagios. En tant que tel, je travaille pour obtenir notre config nagios dans un dépôt git central, en utilisant quelques hooks pour faire la vérification de la syntaxe et ensuite si les configs semblent bonnes, les rendre "actives". J'utilise le post de ce type comme point de départ.

Le flux de travail général que j'essaie de mettre en œuvre est:

  1. Modifier le dépôt git local de la configuration nagios. Ajoutez des fichiers modifiés, validez localement.
  2. git push origin master au référentiel distant.
  3. Push est intercepté par le hook de pré-réception, qui prend les fichiers, les déplace vers un répertoire temporaire sur le serveur et les exécute via le vérificateur de syntaxe nagios.
  4. Si le vérificateur de syntaxe réussit, acceptez le push, puis utilisez le hook post-commit au git pullnouveau code dans le répertoire de configuration de nagios en direct, puis redémarrez nagios.
  5. Si le vérificateur de syntaxe échoue, rejetez la transmission, indiquant l'erreur de syntaxe nagios à l'utilisateur.

Je rencontre un comportement étrange, cependant, lorsque je rejette un push git en raison d'erreurs de syntaxe dans la configuration nagios. Ce que j'attends, c'est que si je rejette le hook, la tentative de push devrait laisser le dépôt tel quel, sans le toucher. Cependant, cela ne semble pas être le cas. Voici les détails de ce que je vois:

Problème

Je modifie la configuration de nagios localement, y compris intentionnellement une erreur de syntaxe, j'ajoute, puis je valide localement:

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

Maintenant, je pousse ces modifications dans le référentiel maître. Cela sera rejeté en raison de l'erreur de syntaxe:

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'

Cela n'aurait pas dû toucher le référentiel distant, mais il l'a fait. Si je passe à un autre répertoire temporaire local et essaie de cloner le dépôt, j'obtiens:

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

Maintenant, je reviens au répertoire de travail d'origine, corrige l'erreur de syntaxe, ajoute, valide et pousse:

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

À ce stade, le référentiel est correct, et je peux passer à un répertoire temporaire et cloner à nouveau le dépôt:

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.

Voici le crochet de pré-réception que j'utilise.

J'utilise git v1.7.5.4 sur le client et v1.7.2.3 sur le serveur.

Donc, à la question : pourquoi le référentiel est-il laissé dans un état incohérent lorsque je rejette la poussée? Quelque chose ne va pas avec mon git hook ou peut-être que ma compréhension de git fait défaut?


Quelle version de git utilisez-vous?
robbyt

@robbyt - 1.7.5.4sur le client, 1.7.2.3sur le serveur.
EEAA

Réponses:


7

Tu fais:

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

dans votre crochet. Bien qu'il ne touche pas à votre copie de travail habituelle, il met à jour les références dans le répertoire git (en particulier la HEADréférence), comme indiqué dans votre erreur:

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

Votre hook fait exit 1pour rejeter la mise à jour, mais ce n'est pas (re) réinitialiser la HEADréférence après l'échec.

Je pense que vous devez mettre à jour la branche de défaillance de votre crochet comme suit:

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

Ça a l'air super, nickgrim. Je vais essayer un peu plus tard dans la journée. Je vous remercie!
EEAA

0

La git checkoutcommande dans votre hook crée / met à jour la référence HEAD dans votre référentiel.

Si votre dépôt est un dépôt nu, il peut vivre sans ref HEAD (nouveaux clones seront par défaut de vérifier son maître branche, si elle en a un); supprimez simplement la référence HEAD avant de quitter (peut-être de manière à trapce que vous n'ayez pas à vous arranger pour le faire avant chacun exitindividuellement). N'importe où «tôt» dans votre script:

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

Si votre référentiel n'est pas nu, ou si vous souhaitez conserver une référence HEAD (afin que les clones, par défaut, vérifient une autre branche), vous devrez enregistrer la référence HEAD et la restaurer avant de quitter.

Tout d'abord, dans le référentiel du serveur, réinitialisez la référence HEAD pour pointer vers la branche que vous souhaitez extraire par défaut dans les nouveaux clones:

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

Ensuite, dans votre script de hook (n'importe où avant votre paiement):

# 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

Soit dit en passant, les pre-receivehooks doivent s'assurer qu'ils lisent entièrement stdin et traitent toutes les lignes qu'ils sont alimentés. Quitter avant de consommer toutes les entrées peut parfois déclencher un SIGPIPE dans le git-receive-packprocessus; cela ne se produit probablement pas dans votre cas si vous ne poussez qu'une seule référence à la fois (puisque vous lisez au moins une ligne), mais c'est quelque chose à garder à l'esprit. Il est probablement plus facile de faire ce crochet comme un updatecrochet où vous ne devez vous soucier que d'une seule référence à la fois et pouvez rejeter la poussée de chaque référence individuellement (peut-être ne vous souciez-vous que de garder la pointe du maître «propre»; pendant que vous vérifiez et rendre compte des conseils des autres branches, mais ne jamais les rejeter afin qu'ils puissent être utilisés pour la collaboration sur des travaux incomplets).

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.