# pylint: disable=W0613

# Copyright (C) 2019 The Android Open Source Project
#
# 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 hashlib
import json
import time

import pytest
import requests

from kubernetes import client

import utils

PLUGINS = ["uploadvalidator", "serviceuser"]
GERRIT_VERSION = "3.1"


@pytest.fixture(scope="module")
def plugin_list():
    plugin_list = list()
    for plugin in PLUGINS:
        url = (
            "https://gerrit-ci.gerritforge.com/view/Plugins-stable-{gerrit_version}/"
            "job/plugin-{plugin}-bazel-stable-{gerrit_version}/lastSuccessfulBuild/"
            "artifact/bazel-bin/plugins/{plugin}/{plugin}.jar"
        ).format(plugin=plugin, gerrit_version=GERRIT_VERSION)
        jar = requests.get(url, verify=False).content
        plugin_list.append(
            {"name": plugin, "url": url, "sha1": hashlib.sha1(jar).hexdigest()}
        )
    return plugin_list


@pytest.fixture(scope="class")
def gerrit_deployment_with_plugins_factory(request, gerrit_deployment_factory):
    def install_chart(chart_opts):
        chart = gerrit_deployment_factory(chart_opts)
        pod_labels = "app=gerrit,release=%s" % chart["name"]
        finished_in_time = utils.wait_for_pod_readiness(pod_labels, timeout=300)
        if not finished_in_time:
            raise utils.TimeOutException("Gerrit pod was not ready in time.")

        return chart

    return install_chart


@pytest.fixture(
    scope="class",
    params=[["replication"], ["replication", "download-commands"]],
    ids=["single-packaged-plugin", "multiple-packaged-plugins"],
)
def gerrit_deployment_with_packaged_plugins(
    request, docker_tag, test_cluster, gerrit_deployment_with_plugins_factory
):

    plugins_opts_string = "{%s}" % (",".join(request.param))
    chart_opts = {
        "images.registry.name": request.config.getoption("--registry"),
        "images.version": docker_tag,
        "images.ImagePullPolicy": "IfNotPresent",
        "gerrit.ingress.host": "primary.%s" % request.config.getoption("--ingress-url"),
        "gerrit.plugins.packaged": plugins_opts_string,
    }
    chart = gerrit_deployment_with_plugins_factory(chart_opts)
    chart["installed_plugins"] = request.param

    yield chart

    test_cluster.helm.delete(chart["name"], namespace=chart["namespace"])
    test_cluster.delete_namespace(chart["namespace"])


@pytest.fixture(
    scope="class", params=[1, 2], ids=["single-other-plugin", "multiple-other-plugins"]
)
def gerrit_deployment_with_other_plugins(
    request,
    docker_tag,
    test_cluster,
    plugin_list,
    gerrit_deployment_with_plugins_factory,
):
    chart_opts = {
        "images.registry.name": request.config.getoption("--registry"),
        "images.version": docker_tag,
        "images.ImagePullPolicy": "IfNotPresent",
        "gerrit.ingress.host": "primary.%s" % request.config.getoption("--ingress-url"),
    }
    selected_plugins = plugin_list[: request.param]
    for counter, plugin in enumerate(selected_plugins):
        chart_opts["gerrit.plugins.downloaded[%d].name" % counter] = plugin["name"]
        chart_opts["gerrit.plugins.downloaded[%d].url" % counter] = plugin["url"]
        chart_opts["gerrit.plugins.downloaded[%d].sha1" % counter] = plugin["sha1"]
    chart = gerrit_deployment_with_plugins_factory(chart_opts)
    chart["installed_plugins"] = selected_plugins

    yield chart

    test_cluster.helm.delete(chart["name"], namespace=chart["namespace"])


@pytest.fixture()
def gerrit_deployment_with_other_plugin_wrong_sha(
    request, docker_tag, test_cluster, plugin_list, gerrit_deployment_factory
):
    chart_opts = {
        "images.registry.name": request.config.getoption("--registry"),
        "images.version": docker_tag,
        "images.ImagePullPolicy": "IfNotPresent",
        "gerrit.ingress.host": "primary.%s" % request.config.getoption("--ingress-url"),
    }
    plugin = plugin_list[0]
    chart_opts["gerrit.plugins.downloaded[0].name"] = plugin["name"]
    chart_opts["gerrit.plugins.downloaded[0].url"] = plugin["url"]
    chart_opts["gerrit.plugins.downloaded[0].sha1"] = "notAValidSha"
    chart = gerrit_deployment_factory(chart_opts, wait=False)
    chart["installed_plugins"] = plugin

    yield chart

    test_cluster.helm.delete(chart["name"], namespace=chart["namespace"])


def update_chart(helm, chart, opts):
    helm.upgrade(
        chart=chart["chart"],
        name=chart["name"],
        namespace=chart["namespace"],
        set_values=opts,
        reuse_values=True,
        fail_on_err=True,
    )


def get_gerrit_plugin_list(gerrit_url, user="admin", password="secret"):
    list_plugins_url = "%s/a/plugins/?all" % gerrit_url
    response = requests.get(list_plugins_url, auth=(user, password))
    if not response.status_code == 200:
        return None
    body = response.text
    return json.loads(body[body.index("\n") + 1 :])


@pytest.mark.slow
@pytest.mark.incremental
@pytest.mark.integration
@pytest.mark.kubernetes
class TestgerritChartPackagedPluginInstall:
    def _assert_installed_plugins(self, expected_plugins, installed_plugins):
        for plugin in expected_plugins:
            assert plugin in installed_plugins
            assert installed_plugins[plugin]["filename"] == "%s.jar" % plugin

    @pytest.mark.timeout(300)
    def test_install_packaged_plugins(
        self, request, test_cluster, gerrit_deployment_with_packaged_plugins
    ):
        response = None
        while not response:
            try:
                response = get_gerrit_plugin_list(
                    "http://primary.%s" % (request.config.getoption("--ingress-url"))
                )
            except requests.exceptions.ConnectionError:
                time.sleep(1)

        self._assert_installed_plugins(
            gerrit_deployment_with_packaged_plugins["installed_plugins"], response
        )

    @pytest.mark.timeout(300)
    def test_install_packaged_plugins_are_removed_with_update(
        self, request, test_cluster, gerrit_deployment_with_packaged_plugins
    ):
        chart = gerrit_deployment_with_packaged_plugins
        chart["removed_plugin"] = chart["installed_plugins"].pop()
        plugins_opts_string = "{%s}" % (",".join(chart["installed_plugins"]))
        plugins_opts_string = plugins_opts_string if plugins_opts_string else "false"
        update_chart(
            test_cluster.helm, chart, {"gerrit.plugins.packaged": plugins_opts_string}
        )

        response = None
        while True:
            try:
                response = get_gerrit_plugin_list(
                    "http://primary.%s" % (request.config.getoption("--ingress-url"))
                )
                if response is not None and chart["removed_plugin"] not in response:
                    break
            except requests.exceptions.ConnectionError:
                time.sleep(1)

        assert chart["removed_plugin"] not in response
        self._assert_installed_plugins(chart["installed_plugins"], response)


@pytest.mark.slow
@pytest.mark.incremental
@pytest.mark.integration
@pytest.mark.kubernetes
class TestgerritChartOtherPluginInstall:
    def _remove_plugin_from_install_list(self, installed_plugins):
        removed_plugin = installed_plugins.pop()
        plugin_install_list = dict()
        if installed_plugins:
            for counter, plugin in enumerate(installed_plugins):
                plugin_install_list[
                    "gerrit.plugins.downloaded[%d].name" % counter
                ] = plugin["name"]
                plugin_install_list[
                    "gerrit.plugins.downloaded[%d].url" % counter
                ] = plugin["url"]
                plugin_install_list[
                    "gerrit.plugins.downloaded[%d].sha1" % counter
                ] = plugin["sha1"]
        else:
            plugin_install_list["gerrit.plugins.downloaded"] = "false"
        return plugin_install_list, removed_plugin, installed_plugins

    def _assert_installed_plugins(self, expected_plugins, installed_plugins):
        for plugin in expected_plugins:
            assert plugin["name"] in installed_plugins
            assert (
                installed_plugins[plugin["name"]]["filename"]
                == "%s.jar" % plugin["name"]
            )

    @pytest.mark.timeout(300)
    def test_install_other_plugins(
        self, request, test_cluster, gerrit_deployment_with_other_plugins
    ):
        response = None
        while not response:
            try:
                response = get_gerrit_plugin_list(
                    "http://primary.%s" % (request.config.getoption("--ingress-url"))
                )
            except requests.exceptions.ConnectionError:
                continue
        self._assert_installed_plugins(
            gerrit_deployment_with_other_plugins["installed_plugins"], response
        )

    @pytest.mark.timeout(300)
    def test_install_other_plugins_are_removed_with_update(
        self, request, test_cluster, gerrit_deployment_with_other_plugins
    ):
        chart = gerrit_deployment_with_other_plugins
        chart_opts, chart["removed_plugin"], chart[
            "installed_plugin"
        ] = self._remove_plugin_from_install_list(chart["installed_plugins"])
        update_chart(test_cluster.helm, chart, chart_opts)

        response = None
        while True:
            try:
                response = get_gerrit_plugin_list(
                    "http://primary.%s" % (request.config.getoption("--ingress-url"))
                )
                if (
                    response is not None
                    and chart["removed_plugin"]["name"] not in response
                ):
                    break
            except requests.exceptions.ConnectionError:
                time.sleep(1)

        assert chart["removed_plugin"]["name"] not in response
        self._assert_installed_plugins(chart["installed_plugins"], response)


@pytest.mark.integration
@pytest.mark.kubernetes
@pytest.mark.timeout(180)
def test_install_other_plugins_fails_wrong_sha(
    request, test_cluster, gerrit_deployment_with_other_plugin_wrong_sha
):
    pod_labels = "app=gerrit,release=%s" % (
        gerrit_deployment_with_other_plugin_wrong_sha["name"]
    )
    core_v1 = client.CoreV1Api()
    pod_name = ""
    while not pod_name:
        pod_list = core_v1.list_namespaced_pod(
            namespace=gerrit_deployment_with_other_plugin_wrong_sha["namespace"],
            watch=False,
            label_selector=pod_labels,
        )
        if len(pod_list.items) > 1:
            raise RuntimeError("Too many gerrit pods with the same release name.")
        pod_name = pod_list.items[0].metadata.name

    current_status = None
    while not current_status:
        pod = core_v1.read_namespaced_pod_status(
            pod_name, gerrit_deployment_with_other_plugin_wrong_sha["namespace"]
        )
        if not pod.status.init_container_statuses:
            time.sleep(1)
            continue
        for init_container_status in pod.status.init_container_statuses:
            if (
                init_container_status.name == "gerrit-init"
                and init_container_status.last_state.terminated
            ):
                current_status = init_container_status
                assert current_status.last_state.terminated.exit_code > 0
                return

    assert current_status.last_state.terminated.exit_code > 0
