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]