#!/usr/bin/env python

# Copyright 2013 Red Hat, Inc.
# 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 argparse
import gzip
import io
import os
import re
import sys
import urllib.request as urlreq

import yaml

# DEVSTACK_GATE_GRENADE is either unset if grenade is not running
# or a string describing what type of grenade run to perform.
is_grenade = os.environ.get('DEVSTACK_GATE_GRENADE') is not None
dump_all_errors = True

# As logs are made clean, remove from this set
allowed_dirty = set([
    'c-api',
    'ceilometer-acentral',
    'ceilometer-acompute',
    'ceilometer-alarm-evaluator',
    'ceilometer-anotification',
    'ceilometer-api',
    'ceilometer-collector',
    'c-vol',
    'g-api',
    'h-api',
    'h-eng',
    'ir-cond',
    'n-api',
    'n-cpu',
    'n-net',
    'q-agt',
    'q-dhcp',
    'q-lbaas',
    'q-meta',
    'q-metering',
    'q-svc',
    's-proxy'])


def process_files(file_specs, url_specs, allow_lists):
    regexp = re.compile(r"^.* (ERROR|CRITICAL|TRACE) .*\[.*\-.*\]")
    logs_with_errors = []
    for (name, filename) in file_specs:
        allow_list = allow_lists.get(name, [])
        with open(filename) as content:
            if scan_content(content, regexp, allow_list):
                logs_with_errors.append(name)
    for (name, url) in url_specs:
        allow_list = allow_lists.get(name, [])
        req = urlreq.Request(url)
        req.add_header('Accept-Encoding', 'gzip')
        page = urlreq.urlopen(req)
        buf = io.StringIO(page.read())
        f = gzip.GzipFile(fileobj=buf)
        if scan_content(f.read().splitlines(), regexp, allow_list):
            logs_with_errors.append(name)
    return logs_with_errors


def scan_content(content, regexp, allow_list):
    had_errors = False
    for line in content:
        if not line.startswith("Stderr:") and regexp.match(line):
            allowed = False
            for w in allow_list:
                pat = ".*%s.*%s.*" % (w['module'].replace('.', '\\.'),
                                      w['message'])
                if re.match(pat, line):
                    allowed = True
                    break
            if not allowed or dump_all_errors:
                if not allowed:
                    had_errors = True
    return had_errors


def collect_url_logs(url):
    page = urlreq.urlopen(url)
    content = page.read()
    logs = re.findall(r'(screen-[\w-]+\.txt\.gz)</a>', content)
    return logs


def main(opts):
    if opts.directory and opts.url or not (opts.directory or opts.url):
        print("Must provide exactly one of -d or -u")
        return 1
    print("Checking logs...")
    ALLOW_LIST_FILE = os.path.join(
        os.path.abspath(os.path.dirname(os.path.dirname(__file__))),
        "etc", "allow-list.yaml")

    file_matcher = re.compile(r".*screen-([\w-]+)\.log")
    files = []
    if opts.directory:
        d = opts.directory
        for f in os.listdir(d):
            files.append(os.path.join(d, f))
    files_to_process = []
    for f in files:
        m = file_matcher.match(f)
        if m:
            files_to_process.append((m.group(1), f))

    url_matcher = re.compile(r".*screen-([\w-]+)\.txt\.gz")
    urls = []
    if opts.url:
        for logfile in collect_url_logs(opts.url):
            urls.append("%s/%s" % (opts.url, logfile))
    urls_to_process = []
    for u in urls:
        m = url_matcher.match(u)
        if m:
            urls_to_process.append((m.group(1), u))

    allow_lists = {}
    with open(ALLOW_LIST_FILE) as stream:
        loaded = yaml.safe_load(stream)
        if loaded:
            for (name, l) in loaded.items():
                for w in l:
                    assert 'module' in w, 'no module in %s' % name
                    assert 'message' in w, 'no message in %s' % name
            allow_lists = loaded
    logs_with_errors = process_files(files_to_process, urls_to_process,
                                     allow_lists)

    failed = False
    if logs_with_errors:
        log_files = set(logs_with_errors)
        for log in log_files:
            msg = '%s log file has errors' % log
            if log not in allowed_dirty:
                msg += ' and is not allowed to have them'
                failed = True
            print(msg)
        print("\nPlease check the respective log files to see the errors")
    if failed:
        if is_grenade:
            print("Currently not failing grenade runs with errors")
            return 0
        return 1
    print("ok")
    return 0


usage = """
Find non-allow-listed log errors in log files from a devstack-gate run.
Log files will be searched for ERROR or CRITICAL messages. If any
error messages do not match any of the allow-list entries contained in
etc/allow-list.yaml, those messages will be printed to the console and
failure will be returned. A file directory containing logs or a url to the
log files of an OpenStack gate job can be provided.

The allow-list yaml looks like:

log-name:
    - module: "a.b.c"
      message: "regexp"
    - module: "a.b.c"
      message: "regexp"

repeated for each log file with an allow-list.
"""

parser = argparse.ArgumentParser(description=usage)
parser.add_argument('-d', '--directory',
                    help="Directory containing log files")
parser.add_argument('-u', '--url',
                    help="url containing logs from an OpenStack gate job")

if __name__ == "__main__":
    try:
        sys.exit(main(parser.parse_args()))
    except Exception as e:
        print("Failure in script: %s" % e)
        # Don't fail if there is a problem with the script.
        sys.exit(0)
