Назад | Перейти на главную страницу

git, nagios и хуки, поврежденный репозиторий git

Задний план

Мы используем nagios для мониторинга нашей инфраструктуры. На данный момент у нас нет конфигураций nagios под контролем версий, и есть двое из нас, которые управляют конфигурацией nagios. Таким образом, я работаю над тем, чтобы поместить нашу конфигурацию nagios в центральный репозиторий git, используя некоторые хуки для проверки синтаксиса, а затем, если конфигурации выглядят хорошо, сделайте их «активными». я использую этого парня пост в качестве отправной точки.

Общий рабочий процесс, который я пытаюсь реализовать:

  1. Отредактируйте локальный репозиторий git конфигурации nagios. Добавить отредактированные файлы, зафиксировать локально.
  2. git push origin master в удаленное репо.
  3. Push перехватывается ловушкой предварительного приема, которая берет файлы, перемещает их во временный каталог на сервере и запускает их через средство проверки синтаксиса nagios.
  4. Если проверка синтаксиса прошла успешно, примите push, затем используйте обработчик post-commit, чтобы git pull новый код в каталог конфигурации live nagios, а затем перезапустите nagios.
  5. Если средство проверки синтаксиса не работает, отклоните push, показывая пользователю синтаксическую ошибку nagios.

Однако я сталкиваюсь со странным поведением, когда отклоняю git push из-за синтаксических ошибок в конфигурации nagios. Что я ожидаю, так это то, что если я отклоню ловушку, предпринятый push должен оставить репозиторий таким, каким он был, нетронутым. Однако, похоже, это не так. Ниже приведены подробности того, что я вижу:

Проблема

Я редактирую конфигурацию nagios локально, намеренно включая синтаксическую ошибку, добавляю, а затем фиксирую локально:

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

Теперь я помещаю эти изменения в главное репо. Это будет отклонено из-за синтаксической ошибки:

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'

это не должен коснулись удаленного репо, но это произошло. Если я перейду в другой локальный временный каталог и попытаюсь клонировать репо, я получу:

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

Теперь я возвращаюсь в исходный рабочий каталог, исправляю синтаксическую ошибку, добавляю, фиксирую и нажимаю:

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

На данный момент с репозиторием все в порядке, и я могу перейти во временный каталог и снова клонировать репо:

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.

Здесь предварительно получить крючок использую.

Я использую git v1.7.5.4 на клиенте и v1.7.2.3 на сервере.

Итак, к вопрос: почему репозиторий остается в несогласованном состоянии, когда я отклоняю push? Что-то не так с моим хуком git или, возможно, я не понимаю git?

Ты поживаешь:

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

в твоем крючке. Хотя это не касается вашей обычной рабочей копии. является обновление ссылок в git-dir (в частности, HEAD ссылка), как показано в вашей ошибке:

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

Ваш крючок делает exit 1 отклонить обновление, но не (повторно) сбросить HEAD ссылка после сбоя.

Я думаю, вам нужно обновить ветку отказа в вашем хуке следующим образом:

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

В git checkout команда в вашем хуке создает / обновляет HEAD ref в вашем репозитории.

Если ваш репозиторий является пустым репозиторием, он может жить без ссылки HEAD (новые клоны по умолчанию будут проверять его мастер ветка, если она есть); просто удалите HEAD ref перед выходом (возможно, в trap так что вам не нужно организовывать это перед каждым exit индивидуально). В любом месте «в начале» вашего сценария:

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

Если ваш репозиторий не пустой или вы хотите поддерживать HEAD ref (так, чтобы клоны по умолчанию проверяли какую-то другую ветку), вам нужно будет сохранить HEAD ref и восстановить его перед выходом.

Во-первых, в репозитории сервера сбросьте HEAD ref так, чтобы он указывал на ветку, которую вы хотите извлекать по умолчанию в новых клонах:

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

Затем в вашем скрипте перехвата (в любом месте до оформления заказа):

# 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

Кстати, pre-receive хуки должны убедиться, что они полностью читают stdin и обрабатывают все строки, на которые им подаются. Выход до использования всего ввода может иногда запускать SIGPIPE в git-receive-pack обработать; это, вероятно, не возникает в вашем случае, если вы нажимаете только одну ссылку за раз (поскольку вы читаете хотя бы одну строку), но об этом нужно помнить. Наверное, этот хук проще сделать как update хук, где вам нужно заботиться только об одном реф. за раз, и вы можете отклонять толчок каждого реф. по отдельности (возможно, вы заботитесь только о том, чтобы сохранить кончик мастер «Чистый»; пока вы проверяете и сообщаете о советах других ветвей, но никогда не отклоняете их, чтобы их можно было использовать для совместной работы над незавершенной работой).