Sorin Sbarnea 3d1411f3a1 Enable configuration via environment variables
Refactors configuration loading in order to simplify it and to
allow overriding defaults using environment variables.

This behavior is similar to other tools like pip or ansible, which
can load any configurable option from env.

This step ease migration towards containerized use, where we do not
want to keep any secrets inside containers and we may want to
avoid volume mounting, especially when testing.

Change-Id: I0d3a9f19b0ba8d1604d0ca63db01296a3219fb47
2020-09-17 10:59:38 +01:00

144 lines
5.4 KiB
Python

# 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 os
import re
import configparser
# Can be overriden by defining environment variables with same name
DEFAULTS = {
'ES_URL': 'http://logstash.openstack.org:80/elasticsearch',
'LS_URL': 'http://logstash.openstack.org',
'DB_URI': 'mysql+pymysql://query:query@logstash.openstack.org/subunit2sql',
'server_password': '',
'CI_USERNAME': 'jenkins',
'JOBS_RE': 'dsvm',
'PID_FN': '/var/run/elastic-recheck/elastic-recheck.pid',
'INDEX_FORMAT': r'logstash-%Y.%m.%d',
'GERRIT_QUERY_FILE': 'queries',
'GERRIT_HOST': 'review.opendev.org',
'IRC_LOG_CONFIG': None
}
# Not all teams actively used elastic recheck for categorizing their
# work, so to keep the uncategorized page more meaningful, we exclude
# jobs from teams that don't use this toolchain.
EXCLUDED_JOBS = (
# Docs team
"api-site",
"operations-guide",
"openstack-manuals",
# Ansible
"ansible",
# Puppet
"puppet",
)
EXCLUDED_JOBS_REGEX = re.compile('(' + '|'.join(EXCLUDED_JOBS) + ')')
INCLUDED_PROJECTS_REGEX = "(^openstack/|devstack|grenade)"
# TODO(dmsimard): Revisit this query once Zuul v2 is no longer supported
# Let's value legibility over pep8 line width here...
ALL_FAILS_QUERY = (
'('
'(filename:"job-output.txt" AND message:"POST-RUN END" AND message:"playbooks/base/post.yaml")' # noqa E501
' OR '
'(filename:"console.html" AND (message:"[Zuul] Job complete" OR message:"[SCP] Copying console log" OR message:"Grabbing consoleLog"))' # noqa E501
')'
' AND build_status:"FAILURE"'
' AND build_queue:"gate"'
' AND voting:"1"'
)
UNCAT_MAX_SEARCH_SIZE = 30000
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,
all_fails_query=None,
excluded_jobs_regex=None,
included_projects_regex=None,
uncat_search_size=None,
gerrit_query_file=None):
# override defaults with environment variables
for key, val in os.environ.items():
if key in DEFAULTS:
DEFAULTS[key] = val
self.es_url = es_url or DEFAULTS['ES_URL']
self.ls_url = ls_url or DEFAULTS['LS_URL']
self.db_uri = db_uri or DEFAULTS['DB_URI']
self.jobs_re = jobs_re or DEFAULTS['JOBS_RE']
self.ci_username = ci_username or DEFAULTS['CI_USERNAME']
self.es_index_format = es_index_format or DEFAULTS['INDEX_FORMAT']
self.pid_fn = pid_fn or DEFAULTS['PID_FN']
self.ircbot_channel_config = None
self.irc_log_config = DEFAULTS['IRC_LOG_CONFIG']
self.all_fails_query = all_fails_query or ALL_FAILS_QUERY
self.excluded_jobs_regex = excluded_jobs_regex or EXCLUDED_JOBS_REGEX
self.included_projects_regex = \
included_projects_regex or INCLUDED_PROJECTS_REGEX
self.uncat_search_size = uncat_search_size or UNCAT_MAX_SEARCH_SIZE
self.gerrit_query_file = (gerrit_query_file or
DEFAULTS['GERRIT_QUERY_FILE'])
self.gerrit_user = None
self.gerrit_host = None
self.gerrit_host_key = None
if config_file or config_obj:
if config_obj:
config = config_obj
else:
config = configparser.ConfigParser()
config.read(config_file)
cfg_map = {
'db_uri': ('data_source', 'db_uri'),
'es_url': ('data_source', 'es_url'),
'gerrit_host': ('gerrit', 'host'),
'gerrit_host_key': ('gerrit', 'key'),
'gerrit_query_file': ('gerrit', 'query_file'),
'gerrit_user': ('gerrit', 'user'),
'index_format': ('data_source', 'index_format'),
'irc_log_config': ('ircbot', 'log_config'),
'ircbot_channel_config': ('ircbot', 'channel_config'),
'ircbot_server': ('ircbot', 'server_password'),
'ircbot_sever_password': ('ircbot', 'port'),
'jobs_re': ('recheckwatch', 'jobs_re'),
'ls_url': ('data_source', 'ls_url'),
'nick': ('ircbot', 'nick'),
'pass': ('ircbot', 'pass'),
'pid_fn': ('ircbot', 'pidfile'),
'recheckwatch': ('recheckwatch', 'ci_username'),
}
for k, v in cfg_map.items():
try:
if hasattr(self, k) and getattr(self, k) is None:
setattr(self, k, config.get(v[0], v[1]))
except (
configparser.NoOptionError,
configparser.NoSectionError):
pass