From 97933d1cd21a765959d49b406c7bacd62e98bee7 Mon Sep 17 00:00:00 2001 From: Clark Boylan Date: Wed, 1 Aug 2012 11:33:14 -0700 Subject: [PATCH] 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 Approved: Clark Boylan Reviewed-by: Clark Boylan Tested-by: Jenkins --- modules/gerritbot/files/gerritbot | 273 ------------------ modules/gerritbot/files/gerritbot.init | 30 +- modules/gerritbot/manifests/init.pp | 102 +++---- .../gerritbot/templates/gerritbot.config.erb | 2 +- 4 files changed, 58 insertions(+), 349 deletions(-) delete mode 100755 modules/gerritbot/files/gerritbot diff --git a/modules/gerritbot/files/gerritbot b/modules/gerritbot/files/gerritbot deleted file mode 100755 index ef9cb36c0e..0000000000 --- a/modules/gerritbot/files/gerritbot +++ /dev/null @@ -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() diff --git a/modules/gerritbot/files/gerritbot.init b/modules/gerritbot/files/gerritbot.init index 7b9ce7db52..8258a01c58 100755 --- a/modules/gerritbot/files/gerritbot.init +++ b/modules/gerritbot/files/gerritbot.init @@ -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 diff --git a/modules/gerritbot/manifests/init.pp b/modules/gerritbot/manifests/init.pp index 45864e72f0..2c5532056e 100644 --- a/modules/gerritbot/manifests/init.pp +++ b/modules/gerritbot/manifests/init.pp @@ -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'] + } } diff --git a/modules/gerritbot/templates/gerritbot.config.erb b/modules/gerritbot/templates/gerritbot.config.erb index 0712697c3a..3eb20dfc16 100644 --- a/modules/gerritbot/templates/gerritbot.config.erb +++ b/modules/gerritbot/templates/gerritbot.config.erb @@ -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]