system-config/modules/gerrit/manifests/init.pp

612 lines
18 KiB
Puppet

# Install and maintain Gerrit Code Review.
# params:
# virtual_hostname:
# used in the Apache virtual host, eg., review.example.com
# canonicalweburl:
# Used in the Gerrit config to generate links, eg., https://review.example.com/
# ssl_cert_file:
# ssl_key_file:
# Used in the Apache virtual host to specify the SSL cert and key files.
# ssl_chain_file:
# Optional, if you have an intermediate cert Apache should serve.
# openidssourl:
# The URL to use for OpenID in SSO mode.
# email:
# The email address Gerrit should use when sending mail.
# database_poollimit:
# container_heaplimit:
# core_packedgitopenfiles:
# core_packedgitlimit:
# core_packedgitwindowsize:
# sshd_threads:
# httpd_acceptorthreads:
# httpd_minthreads:
# httpd_maxthreads:
# httpd_maxwait:
# Gerrit configuration options; see Gerrit docs.
# commentlinks:
# A list of regexes Gerrit should hyperlink.
# logo:
# The name of the image file for the site header.
# war:
# The URL of the Gerrit WAR that should be downloaded and installed.
# Note that only the final component is used for comparing to the most
# recently installed WAR. In other words, if you update the war from:
#
# http://tarballs.openstack.org/ci/gerrit.war
# to:
# http://somewhereelse.example.com/gerrit.war
#
# Gerrit won't be updated unless you delete gerrit.war from
# ~gerrit2/gerrit-wars. But if you change the URL from:
#
# http://tarballs.openstack.org/ci/gerrit-2.2.2.war
# to:
# http://tarballs.openstack.org/ci/gerrit-2.3.0.war
# Gerrit will be upgraded on the next puppet run.
# TODO: move closing github pull requests to another module
# TODO: move gerritbot configuration to another module
# TODO: move apache configuration to another module
# TODO: move mysql configuration to another module
# TODO: make more gerrit options configurable here
# TODO: launchpadlib creds for user sync script
class gerrit($virtual_hostname='',
$canonicalweburl='',
$ssl_cert_file='',
$ssl_key_file='',
$ssl_chain_file='',
$openidssourl="https://login.launchpad.net/+openid",
$email='',
$database_poollimit='',
$container_heaplimit='',
$core_packedgitopenfiles='',
$core_packedgitlimit='',
$core_packedgitwindowsize='',
$sshd_threads='',
$httpd_acceptorthreads='',
$httpd_minthreads='',
$httpd_maxthreads='',
$httpd_maxwait='',
$github_projects = [],
$upstream_projects = [],
$commentlinks = [ { name => 'changeid',
match => '(I[0-9a-f]{8,40})',
link => '#q,$1,n,z' },
{ name => 'launchpad',
match => '([Bb]ug|[Ll][Pp])[\\s#:]*(\\d+)',
link => 'https://code.launchpad.net/bugs/$2' },
{ name => 'blueprint',
match => '([Bb]lue[Pp]rint|[Bb][Pp])[\\s#:]*([A-Za-z0-9\\-]+)',
link => 'https://blueprints.launchpad.net/openstack/?searchtext=$2' },
],
$logo,
$war,
$script_user,
$script_key_file,
$script_site,
$enable_melody = 'false',
$melody_session = 'false',
$gerritbot_nick,
$gerritbot_password,
$gerritbot_server,
$gerritbot_user,
$github_user,
$github_token,
$mysql_password,
$email_private_key
) {
# Set this to true to disable cron jobs and replication, which can
# interfere with testing.
$testmode = false
user { "gerrit2":
ensure => present,
comment => "Gerrit",
home => "/home/gerrit2",
shell => "/bin/bash",
gid => "gerrit2",
managehome => true,
require => Group["gerrit2"]
}
group { "gerrit2":
ensure => present
}
$packages = ["gitweb",
"python-dev",
"openjdk-6-jre-headless",
"mysql-server",
"python-mysqldb", # for launchpad sync script
"python-openid", # for launchpad sync script
"python-launchpadlib", # for launchpad sync script
"apache2"]
package { $packages:
ensure => present,
}
package { "python-pip":
ensure => present,
require => Package[python-dev]
}
package { "PyGithub":
ensure => latest, # okay to use latest for pip
provider => pip,
require => Package[python-pip]
}
# Skip cron jobs if we're in test mode
if ($testmode == false) {
cron { "gerritsyncusers":
user => gerrit2,
minute => "*/15",
command => "sleep $((RANDOM\\%60+60)) && python /usr/local/gerrit/scripts/update_gerrit_users.py ${script_user} ${script_key_file} ${script_site}",
require => File['/usr/local/gerrit/scripts'],
}
cron { "gerritclosepull":
user => gerrit2,
minute => "*/5",
command => 'sleep $((RANDOM\%60+90)) && python /usr/local/gerrit/scripts/close_pull_requests.py',
require => File['/usr/local/gerrit/scripts'],
}
cron { "expireoldreviews":
user => gerrit2,
hour => 6,
minute => 3,
command => "python /usr/local/gerrit/scripts/expire_old_reviews.py ${script_user} ${script_key_file}",
require => File['/usr/local/gerrit/scripts'],
}
cron { "gerrit_repack":
user => gerrit2,
weekday => 0,
hour => 4,
minute => 7,
command => 'find /home/gerrit2/review_site/git/ -type d -name "*.git" -print -exec git --git-dir="{}" repack -afd \;',
environment => "PATH=/usr/bin:/bin:/usr/sbin:/sbin",
}
cron { "removedbdumps":
user => gerrit2,
hour => 5,
minute => 1,
command => 'find /home/gerrit2/dbupdates/ -name "*.sql.gz" -mtime +30 -exec rm -f {} \;',
environment => "PATH=/usr/bin:/bin:/usr/sbin:/sbin",
}
cron { "gerritfetchremotes":
user => gerrit2,
minute => "*/30",
command => 'sleep $((RANDOM\%60+90)) && python /usr/local/gerrit/scripts/fetch_remotes.py',
require => File['/usr/local/gerrit/scripts'],
}
file { "/usr/local/gerrit/gerritbot":
owner => 'root',
group => 'root',
mode => 555,
ensure => 'present',
source => 'puppet:///modules/gerrit/gerritbot',
}
file { "/etc/init.d/gerritbot":
owner => 'root',
group => 'root',
mode => 555,
ensure => 'present',
source => 'puppet:///modules/gerrit/gerritbot.init',
require => File['/usr/local/gerrit/gerritbot'],
}
file { "/home/gerrit2/gerritbot_channel_config.yaml":
owner => 'root',
group => 'gerrit2',
mode => 440,
ensure => 'present',
source => 'puppet:///modules/gerrit/gerritbot_channel_config.yaml',
replace => true,
require => User['gerrit2']
}
service { 'gerritbot':
name => 'gerritbot',
ensure => running,
enable => true,
hasrestart => true,
require => File['/etc/init.d/gerritbot'],
subscribe => [File["/usr/local/gerrit/gerritbot"],
File["/home/gerrit2/gerritbot_channel_config.yaml"]],
}
} # testmode==false
file { "/var/log/gerrit":
ensure => "directory",
owner => 'gerrit2'
}
# Prepare gerrit directories. Even though some of these would be created
# by the init command, we can go ahead and create them now and populate them.
# That way the config files are already in place before init runs.
file { "/home/gerrit2/review_site":
ensure => "directory",
owner => "gerrit2",
require => User["gerrit2"]
}
file { "/home/gerrit2/review_site/etc":
ensure => "directory",
owner => "gerrit2",
require => File["/home/gerrit2/review_site"]
}
file { "/home/gerrit2/review_site/bin":
ensure => "directory",
owner => "gerrit2",
require => File["/home/gerrit2/review_site"]
}
file { "/home/gerrit2/review_site/hooks":
ensure => "directory",
owner => "gerrit2",
require => File["/home/gerrit2/review_site"]
}
file { "/home/gerrit2/review_site/static":
ensure => "directory",
owner => "gerrit2",
require => File["/home/gerrit2/review_site"]
}
file { '/home/gerrit2/github.config':
owner => 'root',
group => 'root',
mode => 444,
ensure => 'present',
content => template('gerrit/github.config.erb'),
replace => 'true',
require => User["gerrit2"]
}
file { '/home/gerrit2/remotes.config':
owner => 'root',
group => 'root',
mode => 444,
ensure => 'present',
content => template('gerrit/remotes.config.erb'),
replace => 'true',
require => User["gerrit2"]
}
file { '/home/gerrit2/review_site/static/title.png':
ensure => 'present',
source => "puppet:///modules/gerrit/${logo}",
}
file { '/home/gerrit2/review_site/static/openstack-page-bkg.jpg':
ensure => 'present',
source => 'puppet:///modules/gerrit/openstack-page-bkg.jpg'
}
file { '/home/gerrit2/review_site/etc/GerritSite.css':
ensure => 'present',
source => 'puppet:///modules/gerrit/GerritSite.css'
}
file { '/home/gerrit2/review_site/etc/GerritSiteHeader.html':
ensure => 'present',
source => 'puppet:///modules/gerrit/GerritSiteHeader.html'
}
# Skip replication if we're in test mode
if ($testmode == false) {
file { '/home/gerrit2/review_site/etc/replication.config':
owner => 'root',
group => 'root',
mode => 444,
ensure => 'present',
source => 'puppet:///modules/gerrit/replication.config',
replace => 'true',
require => File["/home/gerrit2/review_site/etc"]
}
}
# Gerrit sets these permissions in 'init'; don't fight them.
file { '/home/gerrit2/review_site/etc/gerrit.config':
owner => 'gerrit2',
group => 'gerrit2',
mode => 644,
ensure => 'present',
content => template('gerrit/gerrit.config.erb'),
replace => 'true',
require => File["/home/gerrit2/review_site/etc"]
}
file { '/home/gerrit2/review_site/hooks/change-merged':
owner => 'root',
group => 'root',
mode => 555,
ensure => 'present',
source => 'puppet:///modules/gerrit/change-merged',
replace => 'true',
require => File["/home/gerrit2/review_site/hooks"]
}
file { '/home/gerrit2/review_site/hooks/patchset-created':
owner => 'root',
group => 'root',
mode => 555,
ensure => 'present',
source => 'puppet:///modules/gerrit/patchset-created',
replace => 'true',
require => File["/home/gerrit2/review_site/hooks"]
}
file { '/home/gerrit2/review_site/static/echosign-cla.html':
owner => 'root',
group => 'root',
mode => 444,
ensure => 'present',
source => 'puppet:///modules/gerrit/echosign-cla.html',
replace => 'true',
require => File["/home/gerrit2/review_site/static"]
}
# Secret files.
# TODO: move the first two into other modules since they aren't for gerrit.
file { '/home/gerrit2/github.secure.config':
owner => 'root',
group => 'gerrit2',
mode => 440,
ensure => 'present',
content => template('gerrit/github.secure.config.erb'),
replace => 'true',
require => User['gerrit2']
}
file { '/home/gerrit2/gerritbot.config':
owner => 'root',
group => 'gerrit2',
mode => 440,
ensure => 'present',
content => template('gerrit/gerritbot.config.erb'),
replace => 'true',
require => User['gerrit2']
}
# Gerrit sets these permissions in 'init'; don't fight them. If
# these permissions aren't set correctly, gerrit init will write a
# new secure.config file and lose the mysql password.
file { '/home/gerrit2/review_site/etc/secure.config':
owner => 'gerrit2',
group => 'gerrit2',
mode => 600,
ensure => 'present',
content => template('gerrit/secure.config.erb'),
replace => 'true',
require => File["/home/gerrit2/review_site/etc"]
}
# Set up MySQL.
# We should probably have or use a puppet module to manage mysql, and then
# use that to satisfy the requirements that gerrit has.
exec { "gerrit-mysql":
creates => "/var/lib/mysql/reviewdb/",
command => "/usr/bin/mysql --defaults-file=/etc/mysql/debian.cnf -e \"\
CREATE USER 'gerrit2'@'localhost' IDENTIFIED BY '${mysql_password}';\
CREATE DATABASE reviewdb;\
ALTER DATABASE reviewdb charset=latin1;\
GRANT ALL ON reviewdb.* TO 'gerrit2'@'localhost';\
FLUSH PRIVILEGES;\"",
require => Package["mysql-server"],
}
file { "/etc/mysql/my.cnf":
source => 'puppet:///modules/gerrit/my.cnf',
owner => 'root',
group => 'root',
ensure => 'present',
replace => 'true',
mode => 444,
require => Package["mysql-server"],
}
# Set up apache. This should also be a separate, generalized module.
file { "/etc/apache2/sites-available/gerrit":
content => template('gerrit/gerrit.vhost.erb'),
owner => 'root',
group => 'root',
ensure => 'present',
replace => 'true',
mode => 444,
require => Package["apache2"],
}
file { "/etc/apache2/sites-enabled/gerrit":
ensure => link,
target => '/etc/apache2/sites-available/gerrit',
require => [
File['/etc/apache2/sites-available/gerrit'],
File['/etc/apache2/mods-enabled/ssl.conf'],
File['/etc/apache2/mods-enabled/ssl.load'],
File['/etc/apache2/mods-enabled/rewrite.load'],
File['/etc/apache2/mods-enabled/proxy.conf'],
File['/etc/apache2/mods-enabled/proxy.load'],
File['/etc/apache2/mods-enabled/proxy_http.load'],
],
}
file { '/etc/apache2/sites-enabled/000-default':
require => File['/etc/apache2/sites-available/gerrit'],
ensure => absent,
}
file { '/etc/apache2/mods-enabled/ssl.conf':
target => '/etc/apache2/mods-available/ssl.conf',
ensure => link,
require => Package['apache2'],
}
file { '/etc/apache2/mods-enabled/ssl.load':
target => '/etc/apache2/mods-available/ssl.load',
ensure => link,
require => Package['apache2'],
}
file { '/etc/apache2/mods-enabled/rewrite.load':
target => '/etc/apache2/mods-available/rewrite.load',
ensure => link,
require => Package['apache2'],
}
file { '/etc/apache2/mods-enabled/proxy.conf':
target => '/etc/apache2/mods-available/proxy.conf',
ensure => link,
require => Package['apache2'],
}
file { '/etc/apache2/mods-enabled/proxy.load':
target => '/etc/apache2/mods-available/proxy.load',
ensure => link,
require => Package['apache2'],
}
file { '/etc/apache2/mods-enabled/proxy_http.load':
target => '/etc/apache2/mods-available/proxy_http.load',
ensure => link,
require => Package['apache2'],
}
exec { "gracefully restart apache":
subscribe => [ File["/etc/apache2/sites-available/gerrit"]],
refreshonly => true,
path => "/bin:/usr/bin:/usr/sbin",
command => "apache2ctl graceful",
}
# Install Gerrit itself.
# The Gerrit WAR is specified as a url like 'http://tarballs.openstack.org/ci/gerrit-2.2.2-363-gd0a67ce.war'
# Set $basewar so that we can work with filenames like gerrit-2.2.2-363-gd0a67ce.war'.
if $war =~ /.*\/(.*)/ {
$basewar = $1
} else {
$basewar = $war
}
# This directory is used to download and cache gerrit war files.
# That way the download and install steps are kept separate.
file { "/home/gerrit2/gerrit-wars":
ensure => "directory",
require => User["gerrit2"]
}
# If we don't already have the specified WAR, download it.
exec { "download:$war":
command => "/usr/bin/wget $war -O /home/gerrit2/gerrit-wars/$basewar",
creates => "/home/gerrit2/gerrit-wars/$basewar",
require => File["/home/gerrit2/gerrit-wars"],
}
# If gerrit.war isn't the same as $basewar, install it.
file { "/home/gerrit2/review_site/bin/gerrit.war":
source => "file:///home/gerrit2/gerrit-wars/$basewar",
require => Exec["download:$war"],
ensure => present,
replace => 'true',
# user, group, and mode have to be set this way to avoid retriggering gerrit-init on every run
# because gerrit init sets them this way
owner => 'gerrit2',
group => 'gerrit2',
mode => 644,
}
# If gerrit.war was just installed, run the Gerrit "init" command.
# Stop is included here because it may not be running or the init
# script may not exist, and in those cases, we don't care if it fails.
# Running the init script as the gerrit2 user _does_ work.
exec { "gerrit-init":
user => 'gerrit2',
command => "/etc/init.d/gerrit stop; /usr/bin/java -jar /home/gerrit2/review_site/bin/gerrit.war init -d /home/gerrit2/review_site --batch --no-auto-start",
subscribe => File["/home/gerrit2/review_site/bin/gerrit.war"],
refreshonly => true,
require => [Package["openjdk-6-jre-headless"],
User["gerrit2"],
Exec["gerrit-mysql"],
File["/etc/mysql/my.cnf"], # For innodb default tables
File["/home/gerrit2/review_site/etc/gerrit.config"],
File["/home/gerrit2/review_site/etc/secure.config"]],
notify => Exec["gerrit-start"],
}
# Symlink the init script.
file { "/etc/init.d/gerrit":
ensure => link,
target => '/home/gerrit2/review_site/bin/gerrit.sh',
require => Exec['gerrit-init'],
}
# The init script requires the path to gerrit to be set.
file { "/etc/default/gerritcodereview":
source => 'puppet:///modules/gerrit/gerritcodereview.default',
ensure => present,
replace => 'true',
owner => 'root',
group => 'root',
mode => 444,
}
# Make sure the init script starts on boot.
file { ['/etc/rc0.d/K10gerrit',
'/etc/rc1.d/K10gerrit',
'/etc/rc2.d/S90gerrit',
'/etc/rc3.d/S90gerrit',
'/etc/rc4.d/S90gerrit',
'/etc/rc5.d/S90gerrit',
'/etc/rc6.d/K10gerrit']:
ensure => link,
target => '/etc/init.d/gerrit',
require => File['/etc/init.d/gerrit'],
}
exec { "gerrit-start":
command => '/etc/init.d/gerrit start',
require => File['/etc/init.d/gerrit'],
refreshonly => true,
}
file { '/usr/local/gerrit':
owner => 'root',
group => 'root',
mode => 755,
ensure => 'directory',
}
file { '/usr/local/gerrit/scripts':
owner => 'root',
group => 'root',
mode => 755,
ensure => 'directory',
recurse => true,
require => File['/usr/local/gerrit'],
source => [
"puppet:///modules/gerrit/scripts",
],
}
}