BASH: скрипт отката (roll-back) OpenLDAP баз

Автор: | 03/07/2014
 

У Oracle для его баз данных имеется замечательный инструмент Flashback. Его задача — восстанавливать базу до определённого состояния.

Подобное потребовалось сделать и для LDAP-баз при выполнении автотестов.

Решение очень простое, в основном потому, что:

а) имена DIT совпадают с определёнными переменными, которые присвоены каждому из BuildAgent-ов TeamCIty;
б) пароли для доступа к базам — такие же, как и имена баз, так что не о какой безопасности речи нет (всё работает в ограниченной сети).

Список DIT-ов выглядит так:

namingContexts: dc=autobuild1
namingContexts: dc=autobuild2
namingContexts: dc=autobuild3

И в каждом каталоге – две ветки:

dn: ou=Users,dc=autobuild1
dn: ou=Groups,dc=autobuild1

В которых соответственно находятся записи «нижнего» уровня:

dn: uid=0,ou=Users,dc=autobuild1
dn: uid=1,ou=Users,dc=autobuild1

Собственно — сам скрипт:

#!/bin/bash
curdate=`date +%Y-%M-%d-%H:%M:%S`
log="/var/log/ldap_rollback.log"
{

# обработка результатов команд в функциях
resOk () {
echo -e "$1"
}

resEr () {
echo -e "$1"
exit 1
}

# проверяем наличие 1-го аргумента скрипту при вызове
[[ $1 ]] || resEr "nERROR! Must be call with ENV variables as argument.n"
# список допустимых аргументов, что бы не затереть "левую" базу
names="AUTOBUILD1, AUTOBUILD2, AUTOBUILD3"

checknames () {
echo "$names" | grep "$1"
}

# если переданный скрипту аргумент не найден - пишем об ошибке и выходим
checknames $1 2>&1 > /dev/null || resEr "nERROR! I don't know what environment is "$1". Exit.n"

# переменная ENV на билд-агентах задаётся ЗАГЛАВНЫМИ, поэтому - переводим её в строчные
dn="dc=${1,,}"

# формируем пароль, вырезая dc= и оставляя только имя переменной строчными буквами
pw=`echo $dn | cut -d"=" -f 2`

# userfile и groupfile - файлы-шаблоны для баз
userfile="/home/auto/ldifs/Users.ldif"
groupfile="/home/auto/ldifs/Groups.ldif"

# а это временные файлы, которые создаются функцией chNames
t_userfile="/tmp/Users_$dn.ldif"
t_groupfile="/tmp/Groups_$dn.ldif"

# проверяем наличие файлов-шаблонов
if [ ! -e $userfile ] && [ ! -e $groupfile ]; then
echo -e "nERROR: there is no file $userfile or $groupfile!n"
exit 1
fi

echo -e "nStarting rollback at $curdate with DN $dnn"

# в файлах-шаблонах dc=CHANGEME, меняем его на переменную $dn полученную из аргумента самому скрипту
chNames () {
echo -e "nPreparing temporary files...n"
sed 's/dc=CHANGEME/'${1}'/g' $userfile > $t_userfile && resOk "File $t_userfile ready..." || resEr "nCan't create file $t_userfile!n"
sed 's/dc=CHANGEME/'${1}'/g' $groupfile > $t_groupfile && resOk "File $t_groupfile ready..." || resEr "nCan't create file $t_groupfile!n"
}

chNames $dn

# удаляем старые записи из базы
delEntries () {
echo -e "nDeleting old entries in $dn...n"
ldapdelete -v -D "cn=root,$1" -w$pw -r "ou=Users,$1" && resOk "nou=Users,$1 deleted;" || resEr "nCan't delete ou=Users,$1!n"
ldapdelete -v -D "cn=root,$1" -w$pw -r "ou=Groups,$1" && resOk "nou=Groups,$1 deleted;" || resEr "nCan't delete ou=Groups,$1!n"
}

delEntries $dn

# заполняем базу из временных файлов
addEntries () {
echo -e "nAdding new entries...n"
ldapadd -x -D "cn=root,$1" -w$pw -f $t_userfile && resOk "nUsers added.n" || resEr "nCan't add ou=Users,$1!n"
ldapadd -x -D "cn=root,$1" -w$pw -f $t_groupfile && resOk "Groups added.n" || resEr "nCan't add ou=Groups,$1!n"
}

addEntries $dn

# удаляем временные файлы
echo -e "Deleting temporary files..."
rm $t_userfile && echo -e "n$t_userfile deleted;" || echo -e "nCan't delete $t_userfile!n"
rm $t_groupfile && echo -e "n$t_groupfile deleted.n" || echo -e "nCan't delete $t_groupfile!n"

echo -e "Roll-back finihsed at $curdate.n"

# и пишем всё в лог-файл для истории
} | 2>&1 tee -a $log

Далее, в проекте билда на TeamCity добавляется задача на запуск batch-скритпа с BuildAgent-а (или можно его выполнять задачей из Maven) с одной строкой:

plink -batch -agent -l auto ldapserver.com ". /home/auto/ldap/ldap_rollback.sh %ENV%"

При этом plink подключается с помощью ключа авторизации, загруженного в Pageant (см. Putty: настройка авторизации SSH по ключу).