git, nagios y ganchos, repositorio de git corrupto

14

Antecedentes

Estamos usando nagios para monitorear nuestra infraestructura. No tenemos las configuraciones de nagios bajo control de versiones en este momento, y hay dos de nosotros que administramos la configuración de nagios. Como tal, estoy trabajando para obtener nuestra configuración nagios en un repositorio central de git, usando algunos ganchos para hacer una verificación de sintaxis y luego, si las configuraciones se ven bien, hacerlas "activas". Estoy usando la publicación de este tipo como punto de partida.

El flujo de trabajo general que estoy tratando de implementar es:

  1. Edite el repositorio git local de la configuración de nagios. Agregue archivos editados, confirme localmente.
  2. git push origin master al repositorio remoto.
  3. Push es interceptado por el enlace de pre-recepción, que toma los archivos, los mueve a un directorio temporal en el servidor y los ejecuta a través del verificador de sintaxis de nagios.
  4. Si se aprueba el verificador de sintaxis, acepte la inserción, luego use el git pullenlace posterior a la confirmación del nuevo código en el directorio de configuración de nagios en vivo y luego reinicie nagios.
  5. Si el verificador de sintaxis falla, rechace la inserción, mostrando el error de sintaxis de nagios al usuario.

Sin embargo, me encuentro con un comportamiento extraño cuando rechazo un empuje de git debido a errores de sintaxis en la configuración de nagios. Lo que espero que suceda es que si rechazo el gancho, el intento de empuje debería dejar el repositorio tal como estaba, intacto. Sin embargo, ese no parece ser el caso. A continuación están los detalles de lo que estoy viendo:

Problema

Edito la configuración de nagios localmente, incluyendo intencionalmente un error de sintaxis, agrego y luego confirmo localmente:

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

Ahora empujo esos cambios al repositorio principal. Esto será rechazado debido al error de sintaxis:

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'

Esto no debería haber tocado el repositorio remoto, pero lo hizo. Si cambio a otro directorio temporal local e intento clonar el repositorio, obtengo:

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

Ahora vuelvo al directorio de trabajo original, corrijo el error de sintaxis, agrego, confirmo y presiono:

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

En este punto, el repositorio está bien, y puedo cambiar a un directorio temporal y clonar el repositorio nuevamente:

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.

Aquí está el gancho de pre-recepción que estoy usando.

Estoy usando git v1.7.5.4 en el cliente y v1.7.2.3 en el servidor.

Entonces, a la pregunta : ¿por qué se deja el repositorio en un estado inconsistente cuando rechazo el empuje? ¿Hay algún problema con mi gancho de git o tal vez falta mi comprensión de git?

EEAA
fuente
¿Qué versión de git estás usando?
robbyt
@robbyt: 1.7.5.4en el cliente, 1.7.2.3en el servidor.
EEAA

Respuestas:

7

Estás haciendo:

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

en tu gancho Aunque no está tocando su copia de trabajo habitual, está actualizando las referencias en el git-dir (específicamente la HEADreferencia), como se muestra en su error:

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

Su enlace está haciendo exit 1para rechazar la actualización, pero no está (re) restableciendo la HEADreferencia después de la falla.

Creo que necesita actualizar la rama de falla en su gancho de esta manera:

...
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
fuente
Esto se ve genial, nickgrim. Lo intentaré un poco más tarde hoy. ¡Gracias!
EEAA
0

El git checkoutcomando en su gancho es crear / actualizar la referencia HEAD en su repositorio.

Si su repositorio es un repositorio desnudo, puede vivir sin una referencia HEAD (los nuevos clones predeterminarán la comprobación de su rama maestra , si tiene una); simplemente elimine la referencia HEAD antes de salir (tal vez de trapmanera que no tenga que hacer arreglos para hacerlo antes de cada uno exitindividualmente). En cualquier lugar "temprano" en su secuencia de comandos:

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

Si su repositorio no está vacío, o si desea mantener una referencia HEAD (de modo que los clones verifiquen de forma predeterminada alguna otra rama), entonces deberá guardar la referencia HEAD y restaurarla antes de salir.

Primero, en el repositorio del servidor, restablezca la referencia HEAD para apuntar a la rama que desea que se desproteja de forma predeterminada en nuevos clones:

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

Luego, en su script de gancho (en cualquier lugar antes de su pago):

# 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

Por cierto, los pre-receiveganchos deben asegurarse de que leen completamente stdin y procesan todas las líneas que reciben. Salir antes de consumir toda la entrada a veces puede desencadenar un SIGPIPE en el git-receive-packproceso; esto probablemente no ocurra en su caso si solo empuja una referencia a la vez (ya que lee al menos una línea), pero es algo a tener en cuenta. Probablemente sea más fácil hacer este gancho como un updategancho donde solo necesita preocuparse por un árbitro a la vez y puede rechazar el empuje de cada árbitro individualmente (tal vez solo le importa mantener la punta del maestro "limpia"; mientras revisa y informe sobre los consejos de otras ramas, pero nunca los rechace para que puedan ser utilizados para colaborar en trabajos incompletos).

Chris Johnsen
fuente