# 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