Make Elastic Recheck Watch more reusable

Refactor to use a config class to hold all the
params needed so that they can be more easily
overridden and reused across all the
elastic-recheck tools.

In addition, use the new class to make the
jobs_regex and ci_username configurable.

Change-Id: Ic6f115a6882494bf4c087ded4d7cafa557765c28
This commit is contained in:
Ramy Asselin 2015-11-30 10:34:18 -08:00
parent 35e31cf56b
commit 49999256f4
10 changed files with 187 additions and 139 deletions

View File

@ -6,6 +6,12 @@ server=irc.freenode.net
port=6667 port=6667
channel_config=/home/mtreinish/elasticRecheck/recheckwatchbot.yaml channel_config=/home/mtreinish/elasticRecheck/recheckwatchbot.yaml
[recheckwatch]
#Any project that has a job that matches this regex will have all their
#jobs included in the recheck algorithm
jobs_regex=(tempest-dsvm-full|gate-tempest-dsvm-virtual-ironic)
ci_username=jenkins
[gerrit] [gerrit]
user=treinish user=treinish
host=review.openstack.org host=review.openstack.org

View File

@ -42,7 +42,6 @@ openstack-qa:
""" """
import argparse import argparse
import ConfigParser
import daemon import daemon
import os import os
import textwrap import textwrap
@ -53,6 +52,7 @@ import yaml
import irc.bot import irc.bot
from launchpadlib import launchpad from launchpadlib import launchpad
import elastic_recheck.config as er_conf
from elastic_recheck import log as logging from elastic_recheck import log as logging
LPCACHEDIR = os.path.expanduser('~/.launchpadlib/cache') LPCACHEDIR = os.path.expanduser('~/.launchpadlib/cache')
@ -73,13 +73,16 @@ class ElasticRecheckException(Exception):
class RecheckWatchBot(irc.bot.SingleServerIRCBot): class RecheckWatchBot(irc.bot.SingleServerIRCBot):
def __init__(self, channels, nickname, password, server, port=6667, def __init__(self, channels, config):
server_password=None):
super(RecheckWatchBot, self).__init__( super(RecheckWatchBot, self).__init__(
[(server, port, server_password)], nickname, nickname) [(config.ircbot_server,
config.ircbot_port,
config.ircbot_server_password)],
config.ircbot_nick,
config.ircbot_nick)
self.channel_list = channels self.channel_list = channels
self.nickname = nickname self.nickname = config.ircbot_nick
self.password = password self.password = config.ircbot_pass
self.log = logging.getLogger('recheckwatchbot') self.log = logging.getLogger('recheckwatchbot')
def on_nicknameinuse(self, c, e): def on_nicknameinuse(self, c, e):
@ -111,26 +114,24 @@ class RecheckWatchBot(irc.bot.SingleServerIRCBot):
class RecheckWatch(threading.Thread): class RecheckWatch(threading.Thread):
def __init__(self, ircbot, channel_config, msgs, username, def __init__(self, ircbot, channel_config, msgs, config=None,
queries, host, key, commenting=True, es_url=None, commenting=True):
db_uri=None):
super(RecheckWatch, self).__init__() super(RecheckWatch, self).__init__()
self.config = config or er_conf.Config()
self.ircbot = ircbot self.ircbot = ircbot
self.channel_config = channel_config self.channel_config = channel_config
self.msgs = msgs self.msgs = msgs
self.log = logging.getLogger('recheckwatchbot') self.log = logging.getLogger('recheckwatchbot')
self.username = username self.username = config.gerrit_user
self.queries = queries self.queries = config.gerrit_query_file
self.host = host self.host = config.gerrit_host
self.connected = False self.connected = False
self.commenting = commenting self.commenting = commenting
self.key = key self.key = config.gerrit_host_key
self.lp = launchpad.Launchpad.login_anonymously('grabbing bugs', self.lp = launchpad.Launchpad.login_anonymously('grabbing bugs',
'production', 'production',
LPCACHEDIR, LPCACHEDIR,
timeout=60) timeout=60)
self.es_url = es_url
self.db_uri = db_uri
def display(self, channel, event): def display(self, channel, event):
display = False display = False
@ -200,10 +201,9 @@ class RecheckWatch(threading.Thread):
def run(self): def run(self):
# Import here because it needs to happen after daemonization # Import here because it needs to happen after daemonization
import elastic_recheck.elasticRecheck as er import elastic_recheck.elasticRecheck as er
classifier = er.Classifier(self.queries, es_url=self.es_url, classifier = er.Classifier(self.queries, config=self.config)
db_uri=self.db_uri)
stream = er.Stream(self.username, self.host, self.key, stream = er.Stream(self.username, self.host, self.key,
es_url=self.es_url) config=self.config)
while True: while True:
try: try:
event = stream.get_failed_tempest() event = stream.get_failed_tempest()
@ -285,7 +285,7 @@ def get_options():
def _main(args, config): def _main(args, config):
logging.setup_logging(config) logging.setup_logging(config)
fp = config.get('ircbot', 'channel_config') fp = config.ircbot_channel_config
if fp: if fp:
fp = os.path.expanduser(fp) fp = os.path.expanduser(fp)
if not os.path.exists(fp): if not os.path.exists(fp):
@ -301,11 +301,7 @@ def _main(args, config):
if not args.noirc: if not args.noirc:
bot = RecheckWatchBot( bot = RecheckWatchBot(
channel_config.channels, channel_config.channels,
config.get('ircbot', 'nick'), config=config)
config.get('ircbot', 'pass'),
config.get('ircbot', 'server'),
config.getint('ircbot', 'port'),
config.get('ircbot', 'server_password'))
else: else:
bot = None bot = None
@ -313,16 +309,8 @@ def _main(args, config):
bot, bot,
channel_config, channel_config,
msgs, msgs,
config.get('gerrit', 'user'), config=config,
config.get('gerrit', 'query_file'), commenting=not args.nocomment,
config.get('gerrit', 'host', 'review.openstack.org'),
config.get('gerrit', 'key'),
not args.nocomment,
config.get('data_source', 'es_url',
'http://logstash.openstack.org:80/elasticsearch'),
config.get('data_source', 'db_uri',
'mysql+pymysql://query:query@logstash.openstack.org/'
'subunit2sql'),
) )
recheck.start() recheck.start()
@ -333,18 +321,12 @@ def _main(args, config):
def main(): def main():
args = get_options() args = get_options()
config = ConfigParser.ConfigParser({'server_password': None}) config = er_conf.Config(config_file=args.conffile)
config.read(args.conffile)
if config.has_option('ircbot', 'pidfile'):
pid_fn = os.path.expanduser(config.get('ircbot', 'pidfile'))
else:
pid_fn = '/var/run/elastic-recheck/elastic-recheck.pid'
if args.foreground: if args.foreground:
_main(args, config) _main(args, config)
else: else:
pid = pid_file_module.TimeoutPIDLockFile(pid_fn, 10) pid = pid_file_module.TimeoutPIDLockFile(config.pid_fn, 10)
with daemon.DaemonContext(pidfile=pid): with daemon.DaemonContext(pidfile=pid):
_main(args, config) _main(args, config)

View File

@ -15,7 +15,6 @@
# under the License. # under the License.
import argparse import argparse
import ConfigParser
from datetime import datetime from datetime import datetime
import json import json
import os import os
@ -38,6 +37,8 @@ except ImportError:
from urllib3.exceptions import InsecurePlatformWarning from urllib3.exceptions import InsecurePlatformWarning
urllib3.disable_warnings(InsecurePlatformWarning) urllib3.disable_warnings(InsecurePlatformWarning)
import elastic_recheck.config as er_conf
import elastic_recheck.elasticRecheck as er import elastic_recheck.elasticRecheck as er
from elastic_recheck import log as logging from elastic_recheck import log as logging
import elastic_recheck.query_builder as qb import elastic_recheck.query_builder as qb
@ -111,22 +112,9 @@ def main():
help='print out details as we go') help='print out details as we go')
args = parser.parse_args() args = parser.parse_args()
# Start with defaults config = er_conf.Config(config_file=args.conf)
es_url = er.ES_URL
ls_url = er.LS_URL
db_uri = er.DB_URI
if args.conf: classifier = er.Classifier(args.queries, config=config)
config = ConfigParser.ConfigParser({'es_url': er.ES_URL,
'ls_url': er.LS_URL,
'db_uri': er.DB_URI})
config.read(args.conf)
if config.has_section('data_source'):
es_url = config.get('data_source', 'es_url')
ls_url = config.get('data_source', 'ls_url')
db_uri = config.get('data_source', 'db_uri')
classifier = er.Classifier(args.queries, es_url=es_url, db_uri=db_uri)
buglist = [] buglist = []
@ -160,7 +148,7 @@ def main():
} }
# Get the cluster health for the header # Get the cluster health for the header
es = pyelasticsearch.ElasticSearch(es_url) es = pyelasticsearch.ElasticSearch(config.es_url)
jsondata['status'] = es.health()['status'] jsondata['status'] = es.health()['status']
for query in classifier.queries: for query in classifier.queries:
@ -174,7 +162,7 @@ def main():
logstash_query = qb.encode_logstash_query(query['query'], logstash_query = qb.encode_logstash_query(query['query'],
timeframe=timeframe) timeframe=timeframe)
logstash_url = ("%s/#/dashboard/file/logstash.json?%s" logstash_url = ("%s/#/dashboard/file/logstash.json?%s"
% (ls_url, logstash_query)) % (config.ls_url, logstash_query))
bug_data = get_launchpad_bug(query['bug']) bug_data = get_launchpad_bug(query['bug'])
bug = dict(number=query['bug'], bug = dict(number=query['bug'],
query=query['query'], query=query['query'],

View File

@ -15,18 +15,16 @@
# under the License. # under the License.
import argparse import argparse
import ConfigParser
import itertools import itertools
import json import json
import yaml import yaml
import elastic_recheck.elasticRecheck as er import elastic_recheck.config as er_conf
import elastic_recheck.log as logging import elastic_recheck.log as logging
import elastic_recheck.results as er_results import elastic_recheck.results as er_results
LOG = logging.getLogger('erquery') LOG = logging.getLogger('erquery')
DEFAULT_INDEX_FORMAT = 'logstash-%Y.%m.%d'
DEFAULT_NUMBER_OF_DAYS = 10 DEFAULT_NUMBER_OF_DAYS = 10
DEFAULT_MAX_QUANTITY = 5 DEFAULT_MAX_QUANTITY = 5
IGNORED_ATTRIBUTES = [ IGNORED_ATTRIBUTES = [
@ -64,11 +62,11 @@ def analyze_attributes(attributes):
return analysis return analysis
def query(query_file_name, days=DEFAULT_NUMBER_OF_DAYS, es_url=er.ES_URL, def query(query_file_name, config=None, days=DEFAULT_NUMBER_OF_DAYS,
quantity=DEFAULT_MAX_QUANTITY, verbose=False, quantity=DEFAULT_MAX_QUANTITY, verbose=False,):
indexfmt=DEFAULT_INDEX_FORMAT): _config = config or er_conf.Config()
es = er_results.SearchEngine(url=_config.es_url,
es = er_results.SearchEngine(url=es_url, indexfmt=indexfmt) indexfmt=_config.es_index_format)
with open(query_file_name) as f: with open(query_file_name) as f:
query_file = yaml.load(f.read()) query_file = yaml.load(f.read())
@ -119,21 +117,10 @@ def main():
"elastic search url, logstash url, and database uri.") "elastic search url, logstash url, and database uri.")
args = parser.parse_args() args = parser.parse_args()
# Start with defaults config = er_conf.Config(config_file=args.conf)
es_url = er.ES_URL
es_index_format = DEFAULT_INDEX_FORMAT
if args.conf: query(args.query_file.name, config=config, days=args.days,
config = ConfigParser.ConfigParser({ quantity=args.quantity, verbose=args.verbose)
'es_url': er.ES_URL,
'index_format': DEFAULT_INDEX_FORMAT})
config.read(args.conf)
if config.has_section('data_source'):
es_url = config.get('data_source', 'es_url')
es_index_format = config.get('data_source', 'index_format')
query(args.query_file.name, days=args.days, quantity=args.quantity,
verbose=args.verbose, es_url=es_url, indexfmt=es_index_format)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -16,7 +16,6 @@
import argparse import argparse
import collections import collections
import ConfigParser
import datetime import datetime
import logging import logging
import operator import operator
@ -27,6 +26,7 @@ import requests
import dateutil.parser as dp import dateutil.parser as dp
import jinja2 import jinja2
import elastic_recheck.config as er_config
import elastic_recheck.elasticRecheck as er import elastic_recheck.elasticRecheck as er
import elastic_recheck.query_builder as qb import elastic_recheck.query_builder as qb
import elastic_recheck.results as er_results import elastic_recheck.results as er_results
@ -315,22 +315,10 @@ def collect_metrics(classifier, fails):
def main(): def main():
opts = get_options() opts = get_options()
# Start with defaults
es_url = er.ES_URL
ls_url = er.LS_URL
db_uri = er.DB_URI
if opts.conf: config = er_config.Config(config_file=opts.conf)
config = ConfigParser.ConfigParser({'es_url': er.ES_URL,
'ls_url': er.LS_URL,
'db_uri': er.DB_URI})
config.read(opts.conf)
if config.has_section('data_source'):
es_url = config.get('data_source', 'es_url')
ls_url = config.get('data_source', 'ls_url')
db_uri = config.get('data_source', 'db_uri')
classifier = er.Classifier(opts.dir, es_url=es_url, db_uri=db_uri) classifier = er.Classifier(opts.dir, config=config)
all_gate_fails = all_fails(classifier) all_gate_fails = all_fails(classifier)
for group in all_gate_fails: for group in all_gate_fails:
fails = all_gate_fails[group] fails = all_gate_fails[group]
@ -338,7 +326,7 @@ def main():
continue continue
data = collect_metrics(classifier, fails) data = collect_metrics(classifier, fails)
engine = setup_template_engine(opts.templatedir, group=group) engine = setup_template_engine(opts.templatedir, group=group)
html = classifying_rate(fails, data, engine, classifier, ls_url) html = classifying_rate(fails, data, engine, classifier, config.ls_url)
if opts.output: if opts.output:
out_dir = opts.output out_dir = opts.output
else: else:

100
elastic_recheck/config.py Normal file
View File

@ -0,0 +1,100 @@
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import ConfigParser
import os
DEFAULT_INDEX_FORMAT = 'logstash-%Y.%m.%d'
ES_URL = 'http://logstash.openstack.org:80/elasticsearch'
LS_URL = 'http://logstash.openstack.org'
DB_URI = 'mysql+pymysql://query:query@logstash.openstack.org/subunit2sql'
JOBS_RE = '(tempest-dsvm-full|gate-tempest-dsvm-virtual-ironic)'
CI_USERNAME = 'jenkins'
PID_FN = '/var/run/elastic-recheck/elastic-recheck.pid'
class Config(object):
def __init__(self,
config_file=None,
config_obj=None,
es_url=None,
ls_url=None,
db_uri=None,
jobs_re=None,
ci_username=None,
pid_fn=None,
es_index_format=None):
self.es_url = es_url or ES_URL
self.ls_url = ls_url or LS_URL
self.db_uri = db_uri or DB_URI
self.jobs_re = jobs_re or JOBS_RE
self.ci_username = ci_username or CI_USERNAME
self.es_index_format = es_index_format or DEFAULT_INDEX_FORMAT
self.pid_fn = pid_fn or PID_FN
self.ircbot_channel_config = None
self.irc_log_config = None
if config_file or config_obj:
if config_obj:
config = config_obj
else:
config = ConfigParser.ConfigParser(
{'es_url': ES_URL,
'ls_url': LS_URL,
'db_uri': DB_URI,
'server_password': None,
'ci_username': CI_USERNAME,
'jobs_regex': JOBS_RE,
'pidfile': PID_FN,
'index_format': DEFAULT_INDEX_FORMAT,
}
)
config.read(config_file)
if config.has_section('data_source'):
self.es_url = config.get('data_source', 'es_url')
self.ls_url = config.get('data_source', 'ls_url')
self.db_uri = config.get('data_source', 'db_uri')
self.es_index_format = config.get('data_source',
'index_format')
if config.has_section('recheckwatch'):
self.ci_username = config.get('recheckwatch', 'ci_username')
self.jobs_regex = config.get('recheckwatch', 'jobs_regex')
if config.has_section('gerrit'):
self.gerrit_user = config.get('gerrit', 'user')
self.gerrit_query_file = config.get('gerrit', 'query_file')
self.gerrit_host = config.get('gerrit', 'host',
'review.openstack.org')
self.gerrit_host_key = config.get('gerrit', 'key')
if config.has_section('ircbot'):
self.pid_fn = os.path.expanduser(config.get('ircbot',
'pidfile'))
self.ircbot_nick = config.get('ircbot', 'nick')
self.ircbot_pass = config.get('ircbot', 'pass')
self.ircbot_server = config.get('ircbot', 'server')
self.ircbot_port = config.getint('ircbot', 'port')
self.ircbot_server_password = config.get('ircbot',
'server_password')
self.ircbot_channel_config = config.get('ircbot',
'channel_config')
if config.has_option('ircbot', 'log_config'):
self.irc_log_config = config.get('ircbot', 'log_config')

View File

@ -24,14 +24,11 @@ import logging
import re import re
import time import time
import elastic_recheck.config as er_conf
import elastic_recheck.loader as loader import elastic_recheck.loader as loader
import elastic_recheck.query_builder as qb import elastic_recheck.query_builder as qb
from elastic_recheck import results from elastic_recheck import results
ES_URL = 'http://logstash.openstack.org:80/elasticsearch'
LS_URL = 'http://logstash.openstack.org'
DB_URI = 'mysql+pymysql://query:query@logstash.openstack.org/subunit2sql'
def required_files(job): def required_files(job):
files = ['console.html'] files = ['console.html']
@ -112,7 +109,7 @@ class FailEvent(object):
comment = None comment = None
failed_jobs = [] failed_jobs = []
def __init__(self, event, failed_jobs): def __init__(self, event, failed_jobs, config=None):
self.change = int(event['change']['number']) self.change = int(event['change']['number'])
self.rev = int(event['patchSet']['number']) self.rev = int(event['patchSet']['number'])
self.project = event['change']['project'] self.project = event['change']['project']
@ -120,10 +117,10 @@ class FailEvent(object):
self.comment = event["comment"] self.comment = event["comment"]
# TODO(jogo): make FailEvent generate the jobs # TODO(jogo): make FailEvent generate the jobs
self.failed_jobs = failed_jobs self.failed_jobs = failed_jobs
self.config = config or er_conf.Config()
def is_openstack_project(self): def is_included_job(self):
return ("tempest-dsvm-full" in self.comment or return re.search(self.config.jobs_re, self.comment)
"gate-tempest-dsvm-virtual-ironic" in self.comment)
def name(self): def name(self):
return "%d,%d" % (self.change, self.rev) return "%d,%d" % (self.change, self.rev)
@ -201,22 +198,22 @@ class Stream(object):
log = logging.getLogger("recheckwatchbot") log = logging.getLogger("recheckwatchbot")
def __init__(self, user, host, key, thread=True, es_url=None): def __init__(self, user, host, key, config=None, thread=True):
self.es_url = es_url or ES_URL self.config = config or er_conf.Config()
port = 29418 port = 29418
self.gerrit = gerritlib.gerrit.Gerrit(host, user, port, key) self.gerrit = gerritlib.gerrit.Gerrit(host, user, port, key)
self.es = results.SearchEngine(self.es_url) self.es = results.SearchEngine(self.config.es_url)
if thread: if thread:
self.gerrit.startWatching() self.gerrit.startWatching()
@staticmethod @staticmethod
def parse_jenkins_failure(event): def parse_jenkins_failure(event, ci_username=er_conf.CI_USERNAME):
"""Is this comment a jenkins failure comment.""" """Is this comment a jenkins failure comment."""
if event.get('type', '') != 'comment-added': if event.get('type', '') != 'comment-added':
return False return False
username = event['author'].get('username', '') username = event['author'].get('username', '')
if (username not in ['jenkins', 'zuul']): if (username not in [ci_username, 'zuul']):
return False return False
if not ("Build failed" in if not ("Build failed" in
@ -324,15 +321,17 @@ class Stream(object):
while True: while True:
event = self.gerrit.getEvent() event = self.gerrit.getEvent()
failed_jobs = Stream.parse_jenkins_failure(event) failed_jobs = Stream.parse_jenkins_failure(
event, ci_username=self.config.ci_username)
if not failed_jobs: if not failed_jobs:
# nothing to see here, lets try the next event # nothing to see here, lets try the next event
continue continue
fevent = FailEvent(event, failed_jobs) fevent = FailEvent(event, failed_jobs)
# bail if it's not an openstack project # bail if the failure is from a project
if not fevent.is_openstack_project(): # that hasn't run any of the included jobs
if not fevent.is_included_job():
continue continue
self.log.info("Looking for failures in %d,%d on %s" % self.log.info("Looking for failures in %d,%d on %s" %
@ -379,10 +378,9 @@ class Classifier(object):
queries = None queries = None
def __init__(self, queries_dir, es_url=None, db_uri=None): def __init__(self, queries_dir, config=None):
self.es_url = es_url or ES_URL self.config = config or er_conf.Config()
self.db_uri = db_uri or DB_URI self.es = results.SearchEngine(self.config.es_url)
self.es = results.SearchEngine(self.es_url)
self.queries_dir = queries_dir self.queries_dir = queries_dir
self.queries = loader.load(self.queries_dir) self.queries = loader.load(self.queries_dir)
@ -409,7 +407,7 @@ class Classifier(object):
# Reload each time # Reload each time
self.queries = loader.load(self.queries_dir) self.queries = loader.load(self.queries_dir)
bug_matches = [] bug_matches = []
engine = sqlalchemy.create_engine(self.db_uri) engine = sqlalchemy.create_engine(self.config.db_uri)
Session = orm.sessionmaker(bind=engine) Session = orm.sessionmaker(bind=engine)
session = Session() session = Session()
for x in self.queries: for x in self.queries:

View File

@ -38,9 +38,8 @@ def setup_logging(config=None):
"urllib3.connectionpool": logging.WARN "urllib3.connectionpool": logging.WARN
} }
if config is not None and config.has_option('ircbot', 'log_config'): if config and config.irc_log_config:
log_config = config.get('ircbot', 'log_config') fp = os.path.expanduser(config.irc_log_config)
fp = os.path.expanduser(log_config)
if not os.path.exists(fp): if not os.path.exists(fp):
raise Exception("Unable to read logging config file at %s" % fp) raise Exception("Unable to read logging config file at %s" % fp)
logging.config.fileConfig(fp) logging.config.fileConfig(fp)

View File

@ -20,6 +20,7 @@ import fixtures
import mock import mock
from elastic_recheck import bot from elastic_recheck import bot
import elastic_recheck.config as er_conf
from elastic_recheck import elasticRecheck from elastic_recheck import elasticRecheck
from elastic_recheck import tests from elastic_recheck import tests
import elastic_recheck.tests.unit.fake_gerrit as fg import elastic_recheck.tests.unit.fake_gerrit as fg
@ -29,10 +30,11 @@ def _set_fake_config(fake_config):
fake_config.add_section('ircbot') fake_config.add_section('ircbot')
fake_config.add_section('gerrit') fake_config.add_section('gerrit')
# Set fake ircbot config # Set fake ircbot config
fake_config.set('ircbot', 'pidfile', er_conf.PID_FN)
fake_config.set('ircbot', 'nick', 'Fake_User') fake_config.set('ircbot', 'nick', 'Fake_User')
fake_config.set('ircbot', 'pass', '') fake_config.set('ircbot', 'pass', '')
fake_config.set('ircbot', 'server', 'irc.fake.net') fake_config.set('ircbot', 'server', 'irc.fake.net')
fake_config.set('ircbot', 'port', 6667) fake_config.set('ircbot', 'port', '6667')
fake_config.set('ircbot', 'channel_config', fake_config.set('ircbot', 'channel_config',
'fake_recheck_watch_bot.yaml') 'fake_recheck_watch_bot.yaml')
# Set fake gerrit config # Set fake gerrit config
@ -49,22 +51,21 @@ class TestBot(unittest.TestCase):
super(TestBot, self).setUp() super(TestBot, self).setUp()
self.fake_config = ConfigParser.ConfigParser({'server_password': None}) self.fake_config = ConfigParser.ConfigParser({'server_password': None})
_set_fake_config(self.fake_config) _set_fake_config(self.fake_config)
config = er_conf.Config(config_obj=self.fake_config)
self.channel_config = bot.ChannelConfig(yaml.load( self.channel_config = bot.ChannelConfig(yaml.load(
open('recheckwatchbot.yaml'))) open('recheckwatchbot.yaml')))
with mock.patch('launchpadlib.launchpad.Launchpad'): with mock.patch('launchpadlib.launchpad.Launchpad'):
self.recheck_watch = bot.RecheckWatch( self.recheck_watch = bot.RecheckWatch(
None, None,
self.channel_config, self.channel_config,
self.fake_config.get('gerrit', 'user'), None,
self.fake_config.get('gerrit', 'query_file'), config=config,
self.fake_config.get('gerrit', 'host'), commenting=False)
self.fake_config.get('gerrit', 'key'),
False)
def test_read_channel_config_not_specified(self): def test_read_channel_config_not_specified(self):
self.fake_config.set('ircbot', 'channel_config', None) self.fake_config.set('ircbot', 'channel_config', None)
with self.assertRaises(bot.ElasticRecheckException) as exc: with self.assertRaises(bot.ElasticRecheckException) as exc:
bot._main([], self.fake_config) bot._main([], er_conf.Config(config_obj=self.fake_config))
raised_exc = exc.exception raised_exc = exc.exception
self.assertEqual(str(raised_exc), "Channel Config must be specified " self.assertEqual(str(raised_exc), "Channel Config must be specified "
"in config file.") "in config file.")
@ -72,7 +73,7 @@ class TestBot(unittest.TestCase):
def test_read_channel_config_invalid_path(self): def test_read_channel_config_invalid_path(self):
self.fake_config.set('ircbot', 'channel_config', 'fake_path.yaml') self.fake_config.set('ircbot', 'channel_config', 'fake_path.yaml')
with self.assertRaises(bot.ElasticRecheckException) as exc: with self.assertRaises(bot.ElasticRecheckException) as exc:
bot._main([], self.fake_config) bot._main([], er_conf.Config(config_obj=self.fake_config))
raised_exc = exc.exception raised_exc = exc.exception
error_msg = "Unable to read layout config file at fake_path.yaml" error_msg = "Unable to read layout config file at fake_path.yaml"
self.assertEqual(str(raised_exc), error_msg) self.assertEqual(str(raised_exc), error_msg)
@ -94,17 +95,16 @@ class TestBotWithTestTools(tests.TestCase):
fg.Gerrit)) fg.Gerrit))
self.fake_config = ConfigParser.ConfigParser({'server_password': None}) self.fake_config = ConfigParser.ConfigParser({'server_password': None})
_set_fake_config(self.fake_config) _set_fake_config(self.fake_config)
config = er_conf.Config(config_obj=self.fake_config)
self.channel_config = bot.ChannelConfig(yaml.load( self.channel_config = bot.ChannelConfig(yaml.load(
open('recheckwatchbot.yaml'))) open('recheckwatchbot.yaml')))
with mock.patch('launchpadlib.launchpad.Launchpad'): with mock.patch('launchpadlib.launchpad.Launchpad'):
self.recheck_watch = bot.RecheckWatch( self.recheck_watch = bot.RecheckWatch(
None, None,
self.channel_config, self.channel_config,
self.fake_config.get('gerrit', 'user'), None,
self.fake_config.get('gerrit', 'query_file'), config=config,
self.fake_config.get('gerrit', 'host'), commenting=False)
self.fake_config.get('gerrit', 'key'),
False)
def fake_print(self, cls, channel, msg): def fake_print(self, cls, channel, msg):
reference = ("openstack/keystone change: https://review.openstack.org/" reference = ("openstack/keystone change: https://review.openstack.org/"

View File

@ -47,7 +47,7 @@ class TestStream(tests.TestCase):
self.assertEqual(event.url, "https://review.openstack.org/64750") self.assertEqual(event.url, "https://review.openstack.org/64750")
self.assertEqual(sorted(event.build_short_uuids()), self.assertEqual(sorted(event.build_short_uuids()),
["5dd41fe", "d3fd328"]) ["5dd41fe", "d3fd328"])
self.assertTrue(event.is_openstack_project()) self.assertTrue(event.is_included_job())
self.assertEqual(event.queue(), "gate") self.assertEqual(event.queue(), "gate")
self.assertEqual(event.bug_urls(), None) self.assertEqual(event.bug_urls(), None)
self.assertEqual(event.bug_urls_map(), None) self.assertEqual(event.bug_urls_map(), None)
@ -65,7 +65,7 @@ class TestStream(tests.TestCase):
self.assertEqual(event.url, "https://review.openstack.org/64749") self.assertEqual(event.url, "https://review.openstack.org/64749")
self.assertEqual(sorted(event.build_short_uuids()), self.assertEqual(sorted(event.build_short_uuids()),
["5dd41fe", "d3fd328"]) ["5dd41fe", "d3fd328"])
self.assertTrue(event.is_openstack_project()) self.assertTrue(event.is_included_job())
self.assertEqual(event.queue(), "check") self.assertEqual(event.queue(), "check")
self.assertEqual(event.bug_urls(), None) self.assertEqual(event.bug_urls(), None)
self.assertEqual(event.bug_urls_map(), None) self.assertEqual(event.bug_urls_map(), None)
@ -147,7 +147,7 @@ class TestStream(tests.TestCase):
self.assertEqual(event.url, "https://review.openstack.org/64750") self.assertEqual(event.url, "https://review.openstack.org/64750")
self.assertEqual(sorted(event.build_short_uuids()), self.assertEqual(sorted(event.build_short_uuids()),
["5dd41fe", "d3fd328"]) ["5dd41fe", "d3fd328"])
self.assertTrue(event.is_openstack_project()) self.assertTrue(event.is_included_job())
self.assertEqual(event.queue(), "gate") self.assertEqual(event.queue(), "gate")
self.assertEqual(event.bug_urls(), self.assertEqual(event.bug_urls(),
['https://bugs.launchpad.net/bugs/123456']) ['https://bugs.launchpad.net/bugs/123456'])
@ -175,7 +175,7 @@ class TestStream(tests.TestCase):
self.assertEqual(event.url, "https://review.openstack.org/64749") self.assertEqual(event.url, "https://review.openstack.org/64749")
self.assertEqual(sorted(event.build_short_uuids()), self.assertEqual(sorted(event.build_short_uuids()),
["5dd41fe", "d3fd328"]) ["5dd41fe", "d3fd328"])
self.assertTrue(event.is_openstack_project()) self.assertTrue(event.is_included_job())
self.assertEqual(event.queue(), "check") self.assertEqual(event.queue(), "check")
self.assertEqual(event.bug_urls(), self.assertEqual(event.bug_urls(),
['https://bugs.launchpad.net/bugs/123456']) ['https://bugs.launchpad.net/bugs/123456'])