Use upstream gerritbot.

Stop using the gerritbot script within the puppet tree. Use the
upstream gerritbot implementation from pypi instead.

Remove old gerritbot script, use pip to install upstream gerritbot,
and update init script to find new location, of the gerritbot script.

Change-Id: I62afe404b1c4d130901e54ca4e7857bb71b4cdd8
Reviewed-on: https://review.openstack.org/10676
Reviewed-by: James E. Blair <corvus@inaugust.com>
Approved: Clark Boylan <clark.boylan@gmail.com>
Reviewed-by: Clark Boylan <clark.boylan@gmail.com>
Tested-by: Jenkins
This commit is contained in:
Clark Boylan 2012-08-01 11:33:14 -07:00 committed by Jenkins
parent 6860917686
commit 97933d1cd2
4 changed files with 58 additions and 349 deletions

View File

@ -1,273 +0,0 @@
#! /usr/bin/env python
# The configuration file should look like:
"""
[ircbot]
nick=NICKNAME
pass=PASSWORD
server=irc.freenode.net
port=6667
channel_config=/path/to/yaml/config
[gerrit]
user=gerrit2
key=/path/to/id_rsa
host=review.example.com
port=29418
"""
# The yaml channel config should look like:
"""
openstack-dev:
events:
- patchset-created
- change-merged
projects:
- openstack/nova
- openstack/swift
branches:
- master
"""
import ircbot
import time
import subprocess
import threading
import select
import json
import sys
import os
import ConfigParser
import daemon, daemon.pidlockfile
import traceback
import yaml
class GerritBot(ircbot.SingleServerIRCBot):
def __init__(self, channels, nickname, password, server, port=6667):
ircbot.SingleServerIRCBot.__init__(self,
[(server, port)],
nickname, nickname)
self.channel_list = channels
self.nickname = nickname
self.password = password
def on_nicknameinuse(self, c, e):
c.nick(c.get_nickname() + "_")
c.privmsg("nickserv", "identify %s " % self.password)
c.privmsg("nickserv", "ghost %s %s" % (self.nickname, self.password))
c.privmsg("nickserv", "release %s %s" % (self.nickname, self.password))
time.sleep(1)
c.nick(self.nickname)
def on_welcome(self, c, e):
c.privmsg("nickserv", "identify %s "% self.password)
for channel in self.channel_list:
c.join(channel)
def send(self, channel, msg):
self.connection.privmsg(channel, msg)
time.sleep(0.5)
class Gerrit(threading.Thread):
def __init__(self, ircbot, channel_config,
username, keyfile, server, port=29418):
threading.Thread.__init__(self)
self.ircbot = ircbot
self.channel_config = channel_config
self.username = username
self.keyfile = keyfile
self.server = server
self.port = port
self.proc = None
self.poll = select.poll()
def _open(self):
self.proc = subprocess.Popen(['/usr/bin/ssh', '-p', str(self.port),
'-i', self.keyfile,
'-l', self.username, self.server,
'gerrit', 'stream-events'],
bufsize=1,
stdin=None,
stdout=subprocess.PIPE,
stderr=None,
)
self.poll.register(self.proc.stdout)
def _close(self):
try:
self.poll.unregister(self.proc.stdout)
except:
pass
try:
self.proc.kill()
except:
pass
self.proc = None
def patchset_created(self, channel, data):
msg = '%s proposed a change to %s: %s %s' % (
data['patchSet']['uploader']['name'],
data['change']['project'],
data['change']['subject'],
data['change']['url'])
self.ircbot.send(channel, msg)
def comment_added(self, channel, data):
msg = 'A comment has been added to a proposed change to %s: %s %s' % (
data['change']['project'],
data['change']['subject'],
data['change']['url'])
self.ircbot.send(channel, msg)
for approval in data.get('approvals', []):
if (approval['type'] == 'VRIF' and approval['value'] == '-2' and
channel in self.channel_config.events.get(
'x-vrif-minus-2', set())):
msg = 'Verification of a change to %s failed: %s %s' % (
data['change']['project'],
data['change']['subject'],
data['change']['url'])
self.ircbot.send(channel, msg)
if (approval['type'] == 'VRIF' and approval['value'] == '2' and
channel in self.channel_config.events.get(
'x-vrif-plus-2', set())):
msg = 'Verification of a change to %s succeeded: %s %s' % (
data['change']['project'],
data['change']['subject'],
data['change']['url'])
self.ircbot.send(channel, msg)
if (approval['type'] == 'CRVW' and approval['value'] == '-2' and
channel in self.channel_config.events.get(
'x-crvw-minus-2', set())):
msg = 'A change to %s has been rejected: %s %s' % (
data['change']['project'],
data['change']['subject'],
data['change']['url'])
self.ircbot.send(channel, msg)
if (approval['type'] == 'CRVW' and approval['value'] == '2' and
channel in self.channel_config.events.get(
'x-crvw-plus-2', set())):
msg = 'A change to %s has been approved: %s %s' % (
data['change']['project'],
data['change']['subject'],
data['change']['url'])
self.ircbot.send(channel, msg)
def change_merged(self, channel, data):
msg = 'A change was merged to %s: %s %s' % (
data['change']['project'],
data['change']['subject'],
data['change']['url'])
self.ircbot.send(channel, msg)
def _read(self):
l = self.proc.stdout.readline()
data = json.loads(l)
channel_set = (self.channel_config.projects.get(
data['change']['project'], set()) &
self.channel_config.events.get(
data['type'], set()) &
self.channel_config.branches.get(
data['change']['branch'], set()))
for channel in channel_set:
if data['type'] == 'comment-added':
self.comment_added(channel, data)
elif data['type'] == 'patchset-created':
self.patchset_created(channel, data)
elif data['type'] == 'change-merged':
self.change_merged(channel, data)
def _listen(self):
while True:
ret = self.poll.poll()
for (fd, event) in ret:
if fd == self.proc.stdout.fileno():
if event == select.POLLIN:
self._read()
else:
raise Exception("event on ssh connection")
def _run(self):
try:
if not self.proc:
self._open()
self._listen()
except:
traceback.print_exc()
self._close()
time.sleep(5)
def run(self):
time.sleep(5)
while True:
self._run()
class ChannelConfig(object):
def __init__(self, data):
self.data = data
keys = data.keys()
for key in keys:
if key[0] != '#':
data['#'+key] = data.pop(key)
self.channels = data.keys()
self.projects = {}
self.events = {}
self.branches = {}
for channel, val in self.data.iteritems():
for event in val['events']:
event_set = self.events.get(event, set())
event_set.add(channel)
self.events[event] = event_set
for project in val['projects']:
project_set = self.projects.get(project, set())
project_set.add(channel)
self.projects[project] = project_set
for branch in val['branches']:
branch_set = self.branches.get(branch, set())
branch_set.add(channel)
self.branches[branch] = branch_set
def _main():
config=ConfigParser.ConfigParser()
config.read(sys.argv[1])
fp = config.get('ircbot', 'channel_config')
if fp:
fp = os.path.expanduser(fp)
if not os.path.exists(fp):
raise Exception("Unable to read layout config file at %s" % fp)
else:
raise Exception("Channel Config must be specified in config file.")
channel_config = ChannelConfig(yaml.load(open(fp)))
bot = GerritBot(channel_config.channels,
config.get('ircbot', 'nick'),
config.get('ircbot', 'pass'),
config.get('ircbot', 'server'),
config.getint('ircbot', 'port'))
g = Gerrit(bot,
channel_config,
config.get('gerrit', 'user'),
config.get('gerrit', 'key'),
config.get('gerrit', 'host'),
config.getint('gerrit', 'port'))
g.start()
bot.start()
def main():
if len(sys.argv) != 2:
print "Usage: %s CONFIGFILE" % sys.argv[0]
sys.exit(1)
pid = daemon.pidlockfile.TimeoutPIDLockFile(
"/var/run/gerritbot/gerritbot.pid", 10)
with daemon.DaemonContext(pidfile=pid):
_main()
if __name__ == "__main__":
main()

View File

@ -17,8 +17,8 @@
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="GerritBot"
NAME=gerritbot
DAEMON=/usr/local/gerrit/$NAME
DAEMON_ARGS="/home/gerrit2/gerritbot.config"
DAEMON=/usr/local/bin/$NAME
DAEMON_ARGS="/etc/gerritbot/gerritbot.config"
PIDFILE=/var/run/$NAME/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
USER=gerrit2
@ -36,17 +36,6 @@ USER=gerrit2
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions
pidof_gerritbot() {
# if there is actually an gerritbot process whose pid is in PIDFILE,
# print it and return 0.
if [ -e "$PIDFILE" ]; then
if ps -ef | grep gerrit[b]ot | grep python | awk '{print $2}' | grep -w $(cat $PIDFILE); then
return 0
fi
fi
return 1
}
#
# Function that starts the daemon/service
#
@ -117,19 +106,8 @@ case "$1" in
esac
;;
status)
PID=$(pidof_gerritbot) || true
if [ -n "$PID" ]; then
log_daemon_msg "$DESC is running (pid $PID)."
exit 0
else
log_daemon_msg "$DESC is NOT running."
if [ -e "$PIDFILE" ]; then
exit 1
else
exit 3
fi
fi
;;
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
;;
#reload|force-reload)
#
# If do_reload() is not implemented then leave this commented out

View File

@ -1,57 +1,61 @@
class gerritbot(
$nick,
$password,
$server,
$user,
$vhost_name
) {
$nick,
$password,
$server,
$user,
$vhost_name
) {
file { "/usr/local/gerrit/gerritbot":
owner => 'root',
group => 'root',
mode => 555,
ensure => 'present',
source => 'puppet:///modules/gerritbot/gerritbot',
require => File['/usr/local/gerrit'],
}
include pip
file { "/etc/init.d/gerritbot":
owner => 'root',
group => 'root',
mode => 555,
ensure => 'present',
source => 'puppet:///modules/gerritbot/gerritbot.init',
require => File['/usr/local/gerrit/gerritbot'],
}
package { 'gerritbot':
ensure => latest, # we want the latest from pip
provider => pip,
require => Class[pip]
}
file { "/home/gerrit2/gerritbot_channel_config.yaml":
owner => 'root',
group => 'gerrit2',
mode => 440,
ensure => 'present',
source => 'puppet:///modules/gerritbot/gerritbot_channel_config.yaml',
replace => true,
require => User['gerrit2'],
}
file { '/etc/init.d/gerritbot':
owner => 'root',
group => 'root',
mode => 555,
ensure => 'present',
source => 'puppet:///modules/gerritbot/gerritbot.init',
require => Package['gerritbot'],
}
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"]],
}
service { 'gerritbot':
name => 'gerritbot',
ensure => running,
enable => true,
hasrestart => true,
require => File['/etc/init.d/gerritbot'],
subscribe => [Package['gerritbot'],
File['/etc/gerritbot/gerritbot.confg'],
File['/etc/gerritbot/channel_config.yaml']],
}
file { '/home/gerrit2/gerritbot.config':
owner => 'root',
group => 'gerrit2',
mode => 440,
ensure => 'present',
content => template('gerritbot/gerritbot.config.erb'),
replace => 'true',
require => User['gerrit2']
}
file { '/etc/gerritbot':
ensure => directory
}
file { '/etc/gerritbot/channel_config.yaml':
owner => 'root',
group => 'gerrit2',
mode => 440,
ensure => 'present',
source => 'puppet:///modules/gerritbot/gerritbot_channel_config.yaml',
replace => true,
require => User['gerrit2'],
}
file { '/etc/gerritbot/gerritbot.config':
owner => 'root',
group => 'gerrit2',
mode => 440,
ensure => 'present',
content => template('gerritbot/gerritbot.config.erb'),
replace => 'true',
require => User['gerrit2']
}
}

View File

@ -3,7 +3,7 @@ nick=<%= nick %>
pass=<%= password %>
server=<%= server %>
port=6667
channel_config=/home/gerrit2/gerritbot_channel_config.yaml
channel_config=/etc/gerritbot/channel_config.yaml
lockfile=/var/run/gerritbot/gerritbot.pid
[gerrit]