# 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", "account"]
GERRIT_VERSION = "3.3"


@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",
        "ingress.enabled": True,
        "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",
        "ingress.enabled": True,
        "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",
        "ingress.enabled": True,
        "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
