# 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 os.path

import git
import pytest
import requests

import mock_ssl
import utils


@pytest.fixture(scope="module")
def cert_dir(tmp_path_factory):
    return tmp_path_factory.mktemp("gerrit-cert")


@pytest.fixture(scope="class")
def ssl_certificate(request, cert_dir):
    url = "primary.%s" % request.config.getoption("--ingress-url")
    keypair = mock_ssl.MockSSLKeyPair("primary.k8sgerrit.test", url)
    open(os.path.join(cert_dir, "server.crt"), "wb").write(keypair.get_cert())
    open(os.path.join(cert_dir, "server.key"), "wb").write(keypair.get_key())
    return keypair


@pytest.fixture(scope="class")
def gerrit_deployment_with_ssl(
    request, docker_tag, test_cluster, ssl_certificate, 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"),
        "gerrit.ingress.tls.enabled": "true",
        "gerrit.ingress.tls.cert": ssl_certificate.get_cert().decode(),
        "gerrit.ingress.tls.key": ssl_certificate.get_key().decode(),
    }
    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.")

    yield chart

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


@pytest.mark.incremental
@pytest.mark.integration
@pytest.mark.kubernetes
@pytest.mark.slow
class TestgerritChartSetup:
    # pylint: disable=W0613
    def test_create_project_rest(self, request, cert_dir, gerrit_deployment_with_ssl):
        create_project_url = "https://primary.%s/a/projects/test" % (
            request.config.getoption("--ingress-url")
        )
        response = requests.put(
            create_project_url,
            auth=("admin", "secret"),
            verify=os.path.join(cert_dir, "server.crt"),
        )
        assert response.status_code == 201

    def test_cloning_project(
        self, request, tmp_path_factory, test_cluster, gerrit_deployment_with_ssl
    ):
        clone_dest = tmp_path_factory.mktemp("gerrit_chart_clone_test")
        repo_url = "https://primary.%s/test.git" % (
            request.config.getoption("--ingress-url")
        )
        repo = git.Repo.clone_from(
            repo_url, clone_dest, env={"GIT_SSL_NO_VERIFY": "true"}
        )
        assert repo.git_dir == os.path.join(clone_dest, ".git")
