#!/usr/bin/env python
# Copyright 2015 gRPC authors.
#
# 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.
"""Run interop (cross-language) tests in parallel."""

from __future__ import print_function

import argparse
import atexit
import itertools
import json
import multiprocessing
import os
import re
import subprocess
import sys
import tempfile
import time
import uuid
import six
import traceback

import python_utils.dockerjob as dockerjob
import python_utils.jobset as jobset
import python_utils.report_utils as report_utils

# Docker doesn't clean up after itself, so we do it on exit.
atexit.register(lambda: subprocess.call(['stty', 'echo']))

ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
os.chdir(ROOT)

_FALLBACK_SERVER_PORT = 443
_BALANCER_SERVER_PORT = 12000
_BACKEND_SERVER_PORT = 8080

_TEST_TIMEOUT = 30

_FAKE_SERVERS_SAFENAME = 'fake_servers'

# Use a name that's verified by the test certs
_SERVICE_NAME = 'server.test.google.fr'


class CXXLanguage:

    def __init__(self):
        self.client_cwd = '/var/local/git/grpc'
        self.safename = 'cxx'

    def client_cmd(self, args):
        return ['bins/opt/interop_client'] + args

    def global_env(self):
        # 1) Set c-ares as the resolver, to
        #    enable grpclb.
        # 2) Turn on verbose logging.
        # 3) Set the ROOTS_PATH env variable
        #    to the test CA in order for
        #    GoogleDefaultCredentials to be
        #    able to use the test CA.
        return {
            'GRPC_DNS_RESOLVER':
            'ares',
            'GRPC_VERBOSITY':
            'DEBUG',
            'GRPC_TRACE':
            'client_channel,glb',
            'GRPC_DEFAULT_SSL_ROOTS_FILE_PATH':
            '/var/local/git/grpc/src/core/tsi/test_creds/ca.pem',
        }

    def __str__(self):
        return 'c++'


class JavaLanguage:

    def __init__(self):
        self.client_cwd = '/var/local/git/grpc-java'
        self.safename = str(self)

    def client_cmd(self, args):
        # Take necessary steps to import our test CA into
        # the set of test CA's that the Java runtime of the
        # docker container will pick up, so that
        # Java GoogleDefaultCreds can use it.
        pem_to_der_cmd = ('openssl x509 -outform der '
                          '-in /external_mount/src/core/tsi/test_creds/ca.pem '
                          '-out /tmp/test_ca.der')
        keystore_import_cmd = (
            'keytool -import '
            '-keystore /usr/lib/jvm/java-8-oracle/jre/lib/security/cacerts '
            '-file /tmp/test_ca.der '
            '-deststorepass changeit '
            '-noprompt')
        return [
            'bash', '-c', ('{pem_to_der_cmd} && '
                           '{keystore_import_cmd} && '
                           './run-test-client.sh {java_client_args}').format(
                               pem_to_der_cmd=pem_to_der_cmd,
                               keystore_import_cmd=keystore_import_cmd,
                               java_client_args=' '.join(args))
        ]

    def global_env(self):
        # 1) Enable grpclb
        # 2) Enable verbose logging
        return {
            'JAVA_OPTS':
            ('-Dio.grpc.internal.DnsNameResolverProvider.enable_grpclb=true '
             '-Djava.util.logging.config.file=/var/local/grpc_java_logging/logconf.txt'
            )
        }

    def __str__(self):
        return 'java'


class GoLanguage:

    def __init__(self):
        self.client_cwd = '/go/src/google.golang.org/grpc/interop/client'
        self.safename = str(self)

    def client_cmd(self, args):
        # Copy the test CA file into the path that
        # the Go runtime in the docker container will use, so
        # that Go's GoogleDefaultCredentials can use it.
        # See https://golang.org/src/crypto/x509/root_linux.go.
        return [
            'bash', '-c', ('cp /external_mount/src/core/tsi/test_creds/ca.pem '
                           '/etc/ssl/certs/ca-certificates.crt && '
                           '/go/bin/client {go_client_args}'
                          ).format(go_client_args=' '.join(args))
        ]

    def global_env(self):
        return {
            'GRPC_GO_LOG_VERBOSITY_LEVEL': '3',
            'GRPC_GO_LOG_SEVERITY_LEVEL': 'INFO'
        }

    def __str__(self):
        return 'go'


_LANGUAGES = {
    'c++': CXXLanguage(),
    'go': GoLanguage(),
    'java': JavaLanguage(),
}


def docker_run_cmdline(cmdline, image, docker_args, cwd, environ=None):
    """Wraps given cmdline array to create 'docker run' cmdline from it."""
    # turn environ into -e docker args
    docker_cmdline = 'docker run -i --rm=true'.split()
    if environ:
        for k, v in environ.items():
            docker_cmdline += ['-e', '%s=%s' % (k, v)]
    return docker_cmdline + ['-w', cwd] + docker_args + [image] + cmdline


def _job_kill_handler(job):
    assert job._spec.container_name
    dockerjob.docker_kill(job._spec.container_name)


def transport_security_to_args(transport_security):
    args = []
    if transport_security == 'tls':
        args += ['--use_tls=true']
    elif transport_security == 'alts':
        args += ['--use_tls=false', '--use_alts=true']
    elif transport_security == 'insecure':
        args += ['--use_tls=false']
    elif transport_security == 'google_default_credentials':
        args += ['--custom_credentials_type=google_default_credentials']
    else:
        print('Invalid transport security option.')
        sys.exit(1)
    return args


def lb_client_interop_jobspec(language,
                              dns_server_ip,
                              docker_image,
                              transport_security='tls'):
    """Runs a gRPC client under test in a docker container"""
    interop_only_options = [
        '--server_host=%s' % _SERVICE_NAME,
        '--server_port=%d' % _FALLBACK_SERVER_PORT
    ] + transport_security_to_args(transport_security)
    # Don't set the server host override in any client;
    # Go and Java default to no override.
    # We're using a DNS server so there's no need.
    if language.safename == 'c++':
        interop_only_options += ['--server_host_override=""']
    # Don't set --use_test_ca; we're configuring
    # clients to use test CA's via alternate means.
    interop_only_options += ['--use_test_ca=false']
    client_args = language.client_cmd(interop_only_options)
    container_name = dockerjob.random_name(
        'lb_interop_client_%s' % language.safename)
    docker_cmdline = docker_run_cmdline(
        client_args,
        environ=language.global_env(),
        image=docker_image,
        cwd=language.client_cwd,
        docker_args=[
            '--dns=%s' % dns_server_ip,
            '--net=host',
            '--name=%s' % container_name,
            '-v',
            '{grpc_grpc_root_dir}:/external_mount:ro'.format(
                grpc_grpc_root_dir=ROOT),
        ])
    jobset.message(
        'IDLE',
        'docker_cmdline:\b|%s|' % ' '.join(docker_cmdline),
        do_newline=True)
    test_job = jobset.JobSpec(
        cmdline=docker_cmdline,
        shortname=('lb_interop_client:%s' % language),
        timeout_seconds=_TEST_TIMEOUT,
        kill_handler=_job_kill_handler)
    test_job.container_name = container_name
    return test_job


def fallback_server_jobspec(transport_security, shortname):
    """Create jobspec for running a fallback server"""
    cmdline = [
        'bin/server',
        '--port=%d' % _FALLBACK_SERVER_PORT,
    ] + transport_security_to_args(transport_security)
    return grpc_server_in_docker_jobspec(
        server_cmdline=cmdline, shortname=shortname)


def backend_server_jobspec(transport_security, shortname):
    """Create jobspec for running a backend server"""
    cmdline = [
        'bin/server',
        '--port=%d' % _BACKEND_SERVER_PORT,
    ] + transport_security_to_args(transport_security)
    return grpc_server_in_docker_jobspec(
        server_cmdline=cmdline, shortname=shortname)


def grpclb_jobspec(transport_security, short_stream, backend_addrs, shortname):
    """Create jobspec for running a balancer server"""
    cmdline = [
        'bin/fake_grpclb',
        '--backend_addrs=%s' % ','.join(backend_addrs),
        '--port=%d' % _BALANCER_SERVER_PORT,
        '--short_stream=%s' % short_stream,
        '--service_name=%s' % _SERVICE_NAME,
    ] + transport_security_to_args(transport_security)
    return grpc_server_in_docker_jobspec(
        server_cmdline=cmdline, shortname=shortname)


def grpc_server_in_docker_jobspec(server_cmdline, shortname):
    container_name = dockerjob.random_name(shortname)
    environ = {
        'GRPC_GO_LOG_VERBOSITY_LEVEL': '3',
        'GRPC_GO_LOG_SEVERITY_LEVEL': 'INFO ',
    }
    docker_cmdline = docker_run_cmdline(
        server_cmdline,
        cwd='/go',
        image=docker_images.get(_FAKE_SERVERS_SAFENAME),
        environ=environ,
        docker_args=['--name=%s' % container_name])
    jobset.message(
        'IDLE',
        'docker_cmdline:\b|%s|' % ' '.join(docker_cmdline),
        do_newline=True)
    server_job = jobset.JobSpec(
        cmdline=docker_cmdline, shortname=shortname, timeout_seconds=30 * 60)
    server_job.container_name = container_name
    return server_job


def dns_server_in_docker_jobspec(grpclb_ips, fallback_ips, shortname,
                                 cause_no_error_no_data_for_balancer_a_record):
    container_name = dockerjob.random_name(shortname)
    run_dns_server_cmdline = [
        'python',
        'test/cpp/naming/utils/run_dns_server_for_lb_interop_tests.py',
        '--grpclb_ips=%s' % ','.join(grpclb_ips),
        '--fallback_ips=%s' % ','.join(fallback_ips),
    ]
    if cause_no_error_no_data_for_balancer_a_record:
        run_dns_server_cmdline.append(
            '--cause_no_error_no_data_for_balancer_a_record')
    docker_cmdline = docker_run_cmdline(
        run_dns_server_cmdline,
        cwd='/var/local/git/grpc',
        image=docker_images.get(_FAKE_SERVERS_SAFENAME),
        docker_args=['--name=%s' % container_name])
    jobset.message(
        'IDLE',
        'docker_cmdline:\b|%s|' % ' '.join(docker_cmdline),
        do_newline=True)
    server_job = jobset.JobSpec(
        cmdline=docker_cmdline, shortname=shortname, timeout_seconds=30 * 60)
    server_job.container_name = container_name
    return server_job


def build_interop_image_jobspec(lang_safename, basename_prefix='grpc_interop'):
    """Creates jobspec for building interop docker image for a language"""
    tag = '%s_%s:%s' % (basename_prefix, lang_safename, uuid.uuid4())
    env = {
        'INTEROP_IMAGE': tag,
        'BASE_NAME': '%s_%s' % (basename_prefix, lang_safename),
    }
    build_job = jobset.JobSpec(
        cmdline=['tools/run_tests/dockerize/build_interop_image.sh'],
        environ=env,
        shortname='build_docker_%s' % lang_safename,
        timeout_seconds=30 * 60)
    build_job.tag = tag
    return build_job


argp = argparse.ArgumentParser(description='Run interop tests.')
argp.add_argument(
    '-l',
    '--language',
    choices=['all'] + sorted(_LANGUAGES),
    nargs='+',
    default=['all'],
    help='Clients to run.')
argp.add_argument('-j', '--jobs', default=multiprocessing.cpu_count(), type=int)
argp.add_argument(
    '-s',
    '--scenarios_file',
    default=None,
    type=str,
    help='File containing test scenarios as JSON configs.')
argp.add_argument(
    '-n',
    '--scenario_name',
    default=None,
    type=str,
    help=(
        'Useful for manual runs: specify the name of '
        'the scenario to run from scenarios_file. Run all scenarios if unset.'))
argp.add_argument(
    '--cxx_image_tag',
    default=None,
    type=str,
    help=('Setting this skips the clients docker image '
          'build step and runs the client from the named '
          'image. Only supports running a one client language.'))
argp.add_argument(
    '--go_image_tag',
    default=None,
    type=str,
    help=('Setting this skips the clients docker image build '
          'step and runs the client from the named image. Only '
          'supports running a one client language.'))
argp.add_argument(
    '--java_image_tag',
    default=None,
    type=str,
    help=('Setting this skips the clients docker image build '
          'step and runs the client from the named image. Only '
          'supports running a one client language.'))
argp.add_argument(
    '--servers_image_tag',
    default=None,
    type=str,
    help=('Setting this skips the fake servers docker image '
          'build step and runs the servers from the named image.'))
argp.add_argument(
    '--no_skips',
    default=False,
    type=bool,
    nargs='?',
    const=True,
    help=('Useful for manual runs. Setting this overrides test '
          '"skips" configured in test scenarios.'))
argp.add_argument(
    '--verbose',
    default=False,
    type=bool,
    nargs='?',
    const=True,
    help='Increase logging.')
args = argp.parse_args()

docker_images = {}

build_jobs = []
if len(args.language) and args.language[0] == 'all':
    languages = _LANGUAGES.keys()
else:
    languages = args.language
for lang_name in languages:
    l = _LANGUAGES[lang_name]
    # First check if a pre-built image was supplied, and avoid
    # rebuilding the particular docker image if so.
    if lang_name == 'c++' and args.cxx_image_tag:
        docker_images[str(l.safename)] = args.cxx_image_tag
    elif lang_name == 'go' and args.go_image_tag:
        docker_images[str(l.safename)] = args.go_image_tag
    elif lang_name == 'java' and args.java_image_tag:
        docker_images[str(l.safename)] = args.java_image_tag
    else:
        # Build the test client in docker and save the fully
        # built image.
        job = build_interop_image_jobspec(l.safename)
        build_jobs.append(job)
        docker_images[str(l.safename)] = job.tag

# First check if a pre-built image was supplied.
if args.servers_image_tag:
    docker_images[_FAKE_SERVERS_SAFENAME] = args.servers_image_tag
else:
    # Build the test servers in docker and save the fully
    # built image.
    job = build_interop_image_jobspec(
        _FAKE_SERVERS_SAFENAME, basename_prefix='lb_interop')
    build_jobs.append(job)
    docker_images[_FAKE_SERVERS_SAFENAME] = job.tag

if build_jobs:
    jobset.message('START', 'Building interop docker images.', do_newline=True)
    print('Jobs to run: \n%s\n' % '\n'.join(str(j) for j in build_jobs))
    num_failures, _ = jobset.run(
        build_jobs, newline_on_success=True, maxjobs=args.jobs)
    if num_failures == 0:
        jobset.message(
            'SUCCESS', 'All docker images built successfully.', do_newline=True)
    else:
        jobset.message(
            'FAILED', 'Failed to build interop docker images.', do_newline=True)
        sys.exit(1)


def wait_until_dns_server_is_up(dns_server_ip):
    """Probes the DNS server until it's running and safe for tests."""
    for i in range(0, 30):
        print('Health check: attempt to connect to DNS server over TCP.')
        tcp_connect_subprocess = subprocess.Popen([
            os.path.join(os.getcwd(), 'test/cpp/naming/utils/tcp_connect.py'),
            '--server_host', dns_server_ip, '--server_port',
            str(53), '--timeout',
            str(1)
        ])
        tcp_connect_subprocess.communicate()
        if tcp_connect_subprocess.returncode == 0:
            print(('Health check: attempt to make an A-record '
                   'query to DNS server.'))
            dns_resolver_subprocess = subprocess.Popen(
                [
                    os.path.join(os.getcwd(),
                                 'test/cpp/naming/utils/dns_resolver.py'),
                    '--qname', ('health-check-local-dns-server-is-alive.'
                                'resolver-tests.grpctestingexp'),
                    '--server_host', dns_server_ip, '--server_port',
                    str(53)
                ],
                stdout=subprocess.PIPE)
            dns_resolver_stdout, _ = dns_resolver_subprocess.communicate()
            if dns_resolver_subprocess.returncode == 0:
                if '123.123.123.123' in dns_resolver_stdout:
                    print(('DNS server is up! '
                           'Successfully reached it over UDP and TCP.'))
                    return
        time.sleep(0.1)
    raise Exception(('Failed to reach DNS server over TCP and/or UDP. '
                     'Exitting without running tests.'))


def shortname(shortname_prefix, shortname, index):
    return '%s_%s_%d' % (shortname_prefix, shortname, index)


def run_one_scenario(scenario_config):
    jobset.message('START', 'Run scenario: %s' % scenario_config['name'])
    server_jobs = {}
    server_addresses = {}
    suppress_server_logs = True
    try:
        backend_addrs = []
        fallback_ips = []
        grpclb_ips = []
        shortname_prefix = scenario_config['name']
        # Start backends
        for i in xrange(len(scenario_config['backend_configs'])):
            backend_config = scenario_config['backend_configs'][i]
            backend_shortname = shortname(shortname_prefix, 'backend_server', i)
            backend_spec = backend_server_jobspec(
                backend_config['transport_sec'], backend_shortname)
            backend_job = dockerjob.DockerJob(backend_spec)
            server_jobs[backend_shortname] = backend_job
            backend_addrs.append('%s:%d' % (backend_job.ip_address(),
                                            _BACKEND_SERVER_PORT))
        # Start fallbacks
        for i in xrange(len(scenario_config['fallback_configs'])):
            fallback_config = scenario_config['fallback_configs'][i]
            fallback_shortname = shortname(shortname_prefix, 'fallback_server',
                                           i)
            fallback_spec = fallback_server_jobspec(
                fallback_config['transport_sec'], fallback_shortname)
            fallback_job = dockerjob.DockerJob(fallback_spec)
            server_jobs[fallback_shortname] = fallback_job
            fallback_ips.append(fallback_job.ip_address())
        # Start balancers
        for i in xrange(len(scenario_config['balancer_configs'])):
            balancer_config = scenario_config['balancer_configs'][i]
            grpclb_shortname = shortname(shortname_prefix, 'grpclb_server', i)
            grpclb_spec = grpclb_jobspec(balancer_config['transport_sec'],
                                         balancer_config['short_stream'],
                                         backend_addrs, grpclb_shortname)
            grpclb_job = dockerjob.DockerJob(grpclb_spec)
            server_jobs[grpclb_shortname] = grpclb_job
            grpclb_ips.append(grpclb_job.ip_address())
        # Start DNS server
        dns_server_shortname = shortname(shortname_prefix, 'dns_server', 0)
        dns_server_spec = dns_server_in_docker_jobspec(
            grpclb_ips, fallback_ips, dns_server_shortname,
            scenario_config['cause_no_error_no_data_for_balancer_a_record'])
        dns_server_job = dockerjob.DockerJob(dns_server_spec)
        server_jobs[dns_server_shortname] = dns_server_job
        # Get the IP address of the docker container running the DNS server.
        # The DNS server is running on port 53 of that IP address. Note we will
        # point the DNS resolvers of grpc clients under test to our controlled
        # DNS server by effectively modifying the /etc/resolve.conf "nameserver"
        # lists of their docker containers.
        dns_server_ip = dns_server_job.ip_address()
        wait_until_dns_server_is_up(dns_server_ip)
        # Run clients
        jobs = []
        for lang_name in languages:
            # Skip languages that are known to not currently
            # work for this test.
            if not args.no_skips and lang_name in scenario_config.get(
                    'skip_langs', []):
                jobset.message('IDLE',
                               'Skipping scenario: %s for language: %s\n' %
                               (scenario_config['name'], lang_name))
                continue
            lang = _LANGUAGES[lang_name]
            test_job = lb_client_interop_jobspec(
                lang,
                dns_server_ip,
                docker_image=docker_images.get(lang.safename),
                transport_security=scenario_config['transport_sec'])
            jobs.append(test_job)
        jobset.message('IDLE', 'Jobs to run: \n%s\n' % '\n'.join(
            str(job) for job in jobs))
        num_failures, resultset = jobset.run(
            jobs, newline_on_success=True, maxjobs=args.jobs)
        report_utils.render_junit_xml_report(resultset, 'sponge_log.xml')
        if num_failures:
            suppress_server_logs = False
            jobset.message(
                'FAILED',
                'Scenario: %s. Some tests failed' % scenario_config['name'],
                do_newline=True)
        else:
            jobset.message(
                'SUCCESS',
                'Scenario: %s. All tests passed' % scenario_config['name'],
                do_newline=True)
        return num_failures
    finally:
        # Check if servers are still running.
        for server, job in server_jobs.items():
            if not job.is_running():
                print('Server "%s" has exited prematurely.' % server)
        suppress_failure = suppress_server_logs and not args.verbose
        dockerjob.finish_jobs(
            [j for j in six.itervalues(server_jobs)],
            suppress_failure=suppress_failure)


num_failures = 0
with open(args.scenarios_file, 'r') as scenarios_input:
    all_scenarios = json.loads(scenarios_input.read())
    for scenario in all_scenarios:
        if args.scenario_name:
            if args.scenario_name != scenario['name']:
                jobset.message('IDLE',
                               'Skipping scenario: %s' % scenario['name'])
                continue
        num_failures += run_one_scenario(scenario)
if num_failures == 0:
    sys.exit(0)
else:
    sys.exit(1)
