По выше упомянутой связке много чего написано, однако, я вечно чувствовал некие неудобства при заведении нового репозитория: необходимо было завести новый локейшн в конфигурационном файле, создать репозиторий с помощью svnadmin, перезапустить apache. Когда такую работу приходиться выполнять раз в месяц — это терпимо, однако, когда такую работу приходиться выполнять по несколько раз в неделю, стоит задуматься об автоматизации этого процесса. Собственно об этом речь и идёт под катом.
Забегая вперёд, хочу начать именно с конфигурации самого apache.
Главный конфигурационный файл /etc/httpd/conf/httpd.conf
Собственно тут всё ясно (это дефолтное расположение конфигов при установке apache из стандартных репозиториев CentOS 5.6)
Файл /etc/httpd/conf.d/subversion.conf
В этом конфигурационном файле описывается собственно конфигурация репозитория. Тут стоит отметить что мы выносим все локейшены в конфигурационные файлы в директорию conf.d/subversion.d. Зачем это надо? Во-первых нам проще отслеживать какие репозиотории включены, во-вторых мы избавляемся от парсинга конфига при запуске скрипта (об этом ниже).
Файл /etc/httpd/conf.d/subversion.d/example_repo.conf
Тут мы указываем имя и местоположение репозитория, указываем с помощью какой учётной записи мы будет просматривать каталог AD (да в данном случае используется AD), пароль от этой учётной записи, строку и фильтр для поиска. Далее с помощью директории мы указываем, что просмотр репозитория позволен всем пользователям авторизованным в домене (однако можно указать конкретную группу в домене). Далее следующей директорией мы указываем какой группе пользователей в домене (в данном случае это example_group) разрешается производить все остальные действия с репозиторием.
С конфигурацией apache всё ясно, теперь приступим к реализации скрипта с помощью которого мы будем создавать новые репозитории. Скрипт должен
Я использовал python версии 2.7, установленным из исходных кодов с опциями --prefix=/opt/python2.7 --with-threads --enable-unicode=ucs4 --includedir=/usr/include --disable-ipv6. Так же будет необходимо установить модуль python-ldap (я использовал setuptools). Ниже приведён собственно сам скрипт.
Как видно из скрипта, каждое действие я распихал по отдельным функциям. Хочу обратить внимание, что файл конфигурации для репозитория создаётся из темплейта skeleton.tpl, который необходимо положить внутрь директории /etc/httpd/conf.d/subversion.d. Содержимое темплейта
Собственно всё. Однако, пользователям надо предоставить список репозиториев, через который они могут попасть в любой репозиторий и скачать оттуда нужный файл. Делаеться это в файле /etc/httpd/conf.d/subversion.conf добавлением директивы SVNListParentPath On. Однако, необходимо чтобы страничка с меню выглядела в корпоративном стиле. И снова на помощь я вызвал python. В скрипт инициализации apache /etc/init.d/httpd, в функцию start(), добавил строчку
Файл /opt/svn/repo/svn_gen
Тут я специально убрал ссылки на css, чтобы не выдавать организацию в которой работаю (цвета уж больно узнаваемы), но как вы поняли, вы можете реализовать страничку по своему вкусу. В данном случаем можно так же использовать темплейт, однако скрипт svn_gen был написан ещё до того, как мне надоело добавлять репозитории ручками.
Что хотелось бы реализовать в будущем
P.S. Ссылка на архив со скриптами и теплейтом addsvnrepo.tar
P.S.S. Код неидеален, так что с радостью приму любые замечания.
Забегая вперёд, хочу начать именно с конфигурации самого apache.
Главный конфигурационный файл /etc/httpd/conf/httpd.conf
...... # Load config files from the config directory "/etc/httpd/conf.d". # Include conf.d/*.conf ......
Собственно тут всё ясно (это дефолтное расположение конфигов при установке apache из стандартных репозиториев CentOS 5.6)
Файл /etc/httpd/conf.d/subversion.conf
LoadModule dav_svn_module modules/mod_dav_svn.so LoadModule authz_svn_module modules/mod_authz_svn.so LoadModule authnz_ldap_module modules/mod_authnz_ldap.so <VirtualHost *:5553> ServerName svn.company.ru ServerAdmin svn_admin@company.ru DocumentRoot /opt/svn/repo LimitRequestBody 2147483647 CustomLog /var/log/httpd/subversion.log combined ErrorLog /var/log/httpd/subversion-error.log <IfModule rewrite_module> RewriteLogLevel 0 RewriteEngine On RewriteCond "%{REQUEST_METHOD}" !"^(GET|POST|HEAD)$" RewriteCond "%{REQUEST_FILENAME}" "^/([^/\.]+)$" RewriteCond "/opt/svn/repo/%1" -d RewriteRule "^/([^/\.]+)$" "/$1/" [passthrough] </IfModule> Include conf.d/subversion.d/*.conf </VirtualHost>
В этом конфигурационном файле описывается собственно конфигурация репозитория. Тут стоит отметить что мы выносим все локейшены в конфигурационные файлы в директорию conf.d/subversion.d. Зачем это надо? Во-первых нам проще отслеживать какие репозиотории включены, во-вторых мы избавляемся от парсинга конфига при запуске скрипта (об этом ниже).
Файл /etc/httpd/conf.d/subversion.d/example_repo.conf
<Location "/example_repo/"> DAV svn SVNPath /opt/svn/repo/example_repo SVNListParentPath on AuthType Basic AuthName "SVN Server" AuthBasicProvider ldap AuthzLDAPAuthoritative Off AuthLDAPBindDN "cn=ldpcat,cn=users,dc=company,dc=ru" AuthLDAPBindPassword "12345678" AuthLDAPURL ldap://ldap.company.ru:389/ou=user,dc=company,dc=ru?sAMAccountName?sub?(objectClass=*) AuthBasicAuthoritative off <Limit GET PROPFIND> Require valid-user </Limit> <Limit GET PROFIND PROPPATCH DELETE MERGE PUT POST MKCOL MKACTIVITY COPY MOVE LOCK UNLOCK> Require ldap-group cn=example_group,ou=user,dc=company,dc=ru </Limit> </Location>
Тут мы указываем имя и местоположение репозитория, указываем с помощью какой учётной записи мы будет просматривать каталог AD (да в данном случае используется AD), пароль от этой учётной записи, строку и фильтр для поиска. Далее с помощью директории мы указываем, что просмотр репозитория позволен всем пользователям авторизованным в домене (однако можно указать конкретную группу в домене). Далее следующей директорией мы указываем какой группе пользователей в домене (в данном случае это example_group) разрешается производить все остальные действия с репозиторием.
С конфигурацией apache всё ясно, теперь приступим к реализации скрипта с помощью которого мы будем создавать новые репозитории. Скрипт должен
- Создать пустой репозиторий
- Создать конфигурационный файл для репозитоия
- Разослать членам группы, которой предоставлено право вносить изменения в репозиторий, информационное письмо
Приступим.
Я использовал python версии 2.7, установленным из исходных кодов с опциями --prefix=/opt/python2.7 --with-threads --enable-unicode=ucs4 --includedir=/usr/include --disable-ipv6. Так же будет необходимо установить модуль python-ldap (я использовал setuptools). Ниже приведён собственно сам скрипт.
#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- import os import ldap import ldap.sasl import sys import smtplib from email.mime.text import MIMEText server_init_file = '/etc/init.d/httpd' apache_config_dir = '/etc/httpd/conf.d/subversion.d/' repo_path = '/opt/svn/repo/' user_owner_repo = 'apache' group_owner_repo = 'apache' mail_server = 'mail.company.ru' mail_smtp_port = 25 mail_from = 'redmine@company.ru' list_mail = [ ] root_svn_url = 'http://svn.company.ru/' if len(sys.argv)<=2: print u"Нет параметров командной строки" print u"в качестве параметра укажи имя репозитория и группу с правом на запись" print u"Пример: addsvnrepo example_repo example_group" sys.exit() server = 'ldap://ldap' user_id = 'ldpcat' pw = '12345678' dn_search = 'OU=User,DC=company,DC=ru' repo_name = sys.argv[1] group_commit = sys.argv[2] if repo_name != None: print "Создаю репозиторий "+repo_name else: sys.exit() def main(): try: con = ldap.initialize(server) con.set_option(ldap.OPT_REFERRALS, 0) con.simple_bind_s(user_id, pw) print 'Подключение выполнено' except ldap.INVALID_CREDENTIALS: print "Ваш логин или пароль неверны" sys.exit() except ldap.LDAPError, e: if type(e.message) == dict and e.message.has_key('desc'): print 'Error - ' + e.message['desc'] else: print 'Error - ' + str(e) sys.exit() finally: print 'Подлючено' search(con, group_commit) repo_create() config_write() server_reload() mailer() def search(con, group_commit): try: base_dn = 'dc=company,dc=ru' filter = "(memberOf=CN="+group_commit+","+dn_search+")" attrs = ['mail'] timeout = 3 results = con.search_s(base_dn, ldap.SCOPE_SUBTREE, filter, attrs) for dn,entry in results: if dn != None: list_mail.extend(entry['mail']) con.unbind() print list_mail print u"Подключение закрвыто" except ldap.LDAPError, e: print 'Error - ' + str(e) sys.exit() def mailer(): text = u'Репозитоий ' text2 = repo_name text3 = u' создан.\nРепозиторий доступен по адрессу ' text4 = root_svn_url+repo_name text5 = u'/\nС наилучшими пожеланиями!\nРобот' text_s = text+text2+text3+text4+text5 subj = u'Создан репозиторий '+repo_name msg = MIMEText(text_s, "", "cp1251") msg['Subject'] = subj msg['From'] = mail_from msg['To'] = ', '.join( list_mail ) print u"Мы им отправим" print msg['To'] s = smtplib.SMTP(mail_server, mail_smtp_port) s.sendmail(msg['From'], list_mail, msg.as_string()) s.quit() print u"Отправили...." def repo_create(): svnadmin_create_msg = result = os.popen("svnadmin create "+repo_path+repo_name).read() print svnadmin_create_msg chmod_msg = result = os.popen("chown -R "+user_owner_repo+":"+group_owner_repo+" "+repo_path+repo_name).read() print chmod_msg def config_write(): if os.path.exists(apache_config_dir+repo_name+".conf") : print u"Файл конфигурации уже существует" sys.exit() else: print "Создаём файл конфигурации......" f1 = open(apache_config_dir+repo_name+".conf", 'w') f = open(apache_config_dir+"skeleton.tpl", 'r') body_config = f.read() f.close() f1.write(body_config.format(repo_name, repo_path, group_commit, server, dn_search)) f1.close() def server_reload(): print u'Перезагружаем apache.......' reload_msg = result = os.popen(server_init_file+" restart").read() print reload_msg if __name__=="__main__": main()
Как видно из скрипта, каждое действие я распихал по отдельным функциям. Хочу обратить внимание, что файл конфигурации для репозитория создаётся из темплейта skeleton.tpl, который необходимо положить внутрь директории /etc/httpd/conf.d/subversion.d. Содержимое темплейта
<Location "/{0}/"> DAV svn SVNPath {1}{0} SVNListParentPath on AuthType Basic AuthName "SVN Server" AuthBasicProvider ldap AuthzLDAPAuthoritative Off AuthLDAPBindDN "cn=ldpcat,cn=users,dc=company,dc=ru" AuthLDAPBindPassword "12345678" AuthLDAPURL {3}/{4}?sAMAccountName?sub?(objectClass=*) AuthBasicAuthoritative off <Limit GET PROPFIND> Require valid-user </Limit> <Limit PROPPATCH DELETE MERGE PUT POST MKCOL MKACTIVITY COPY MOVE LOCK UNLOCK> Require ldap-group cn={2},{4} </Limit> </Location>
Собственно всё. Однако, пользователям надо предоставить список репозиториев, через который они могут попасть в любой репозиторий и скачать оттуда нужный файл. Делаеться это в файле /etc/httpd/conf.d/subversion.conf добавлением директивы SVNListParentPath On. Однако, необходимо чтобы страничка с меню выглядела в корпоративном стиле. И снова на помощь я вызвал python. В скрипт инициализации apache /etc/init.d/httpd, в функцию start(), добавил строчку
/opt/svn/repo/svn_gen > /opt/svn/repo/index.htmlФайл /opt/svn/repo/svn_gen
#!/usr/bin/env python2.7 import os sdir='/opt/svn/repo/' r, d, f = os.walk(sdir).next() lb=len(d) y=0 addrrepo='http://svn.company.ru/' print "<ul>" while y<lb: print "<li>" print "<a href='" print addrrepo+d[y] print "/" print "'" print ">" print d[y] print "</a>" print "<br \>" y=y+1 else: print "</ul>" print "<hr /" print '<h2>PopoWeb Server running on BolgenOS Server 1.6(fundamentally new system of Denis Popov)</ h2>'
Тут я специально убрал ссылки на css, чтобы не выдавать организацию в которой работаю (цвета уж больно узнаваемы), но как вы поняли, вы можете реализовать страничку по своему вкусу. В данном случаем можно так же использовать темплейт, однако скрипт svn_gen был написан ещё до того, как мне надоело добавлять репозитории ручками.
Что хотелось бы реализовать в будущем
- Добавление конфигов уже для существующих репозиториев
- Отключение и подключение репозиториев
- Вывод списка репозиториев с подробностями (отключен/подключен, какая группа может коммитить
- Импорт из других репозиториев
- В идеале создание группы и добавление пользователей в неё. Однако добавление объектов в AD не в моей
компетенциизоне ответственности
P.S. Ссылка на архив со скриптами и теплейтом addsvnrepo.tar
P.S.S. Код неидеален, так что с радостью приму любые замечания.
