#!/usr/bin/python
# -*- coding: utf-8 -*-

# This file is part of Cockpit.
#
# Copyright (C) 2015 Red Hat, Inc.
#
# Cockpit is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# Cockpit is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Cockpit; If not, see <http://www.gnu.org/licenses/>.

from testlib import *
import json
import os
import sys
import unittest

from kubelib import *

@unittest.skipIf("rhel-7" == os.environ.get("TEST_OS", ""), "Skipping check-kubernetes on rhel-7.")
@unittest.skipIf("debian" in os.environ.get("TEST_OS", ""), "No kubernetes on Debian (yet).")
class TestKubernetes(KubernetesCase, KubernetesCommonTests):

    def setUp(self):
        MachineCase.setUp(self)
        m = self.machine

        self.fix_apiserver_config()
        self.start_kubernetes()

        m.upload(["files/mock-k8s-tiny-app.json"], "/tmp")
        self.wait_api_server()

@unittest.skipIf("rhel-7" == os.environ.get("TEST_OS", ""), "Skipping check-kubernetes on rhel-7.")
@unittest.skipIf("debian" in os.environ.get("TEST_OS", ""), "No kubernetes on Debian (yet).")
class TestConnection(KubernetesCase):
    def testConnect(self):
        m = self.machine
        b = self.browser

        # Connect without starting a kube server
        self.login_and_go("/kubernetes")
        b.wait_present(".curtains")
        b.wait_in_text(".curtains", "Couldn't connect to Kubernetes server")
        b.wait_in_text(".curtains", "Couldn't find running kube-apiserver")
        self.assertIn("Reconnect", b.text(".blank-slate-pf-main-action button"))

        # Start a kube-apiserver with a 'wrong' http port, forcing use of https
        m.execute("echo 'KUBE_API_PORT=\"--port=1111\"' >> /etc/kubernetes/apiserver")
        m.execute("sed -i s/8080/1111/g /etc/kubernetes/*")
        self.fix_apiserver_config()
        self.start_kubernetes()
        self.wait_api_server(port=6443, scheme='https')

        # Click the Reconnect button
        b.click(".blank-slate-pf-main-action button")
        b.wait_present("#node-list")
        b.wait_in_text("#node-list", "127.0.0.1")

        # Check that this failed as a double check
        output = m.execute("curl -sS http://localhost:8080/api 2>&1 || true")
        self.assertIn("Connection refused", output)

        self.allow_journal_messages(".*: couldn't connect: Connection refused")

    def testAuthConfig(self):
        m = self.machine
        b = self.browser

        # Start a kube-apiserver with a 'wrong' http port, forcing use of https
        m.execute("echo 'KUBE_API_PORT=\"--port=1111\"' >> /etc/kubernetes/apiserver")
        m.execute("sed -i s/8080/1111/g /etc/kubernetes/*")

        # Require authentication from kube
        m.execute("echo 'KUBE_API_ARGS=\"--basic_auth_file=/etc/kubernetes/passwd --authorization_mode=ABAC --authorization_policy_file=/etc/kubernetes/authorization\"' >> /etc/kubernetes/apiserver")
        m.execute("echo '{\"user\":\"admin\"}' > /etc/kubernetes/authorization")
        m.execute("echo 'fubar,admin,10101' > /etc/kubernetes/passwd")

        # Setup the kube stuff in the right place
        m.upload(["files/mock-kube-config-basic.json"], "/tmp")
        m.execute("mkdir -p /home/admin/.kube/ && mv /tmp/mock-kube-config-basic.json /home/admin/.kube/config")

        self.fix_apiserver_config()
        m.execute("systemctl start etcd kube-apiserver")
        self.wait_api_server(port=6443, scheme='https')

        self.login_and_go("/kubernetes")
        b.wait_present("#service-list")
        b.wait_in_text("#service-list", "You can deploy an application to your cluster.")

        # Check that this failed as a double check
        output = m.execute("curl -k -sS https://localhost:6443/api 2>&1 || true")
        self.assertIn("Unauthorized", output)


@unittest.skipIf("rhel-7" == os.environ.get("TEST_OS", ""), "Skipping check-nulecule on rhel-7.")
@unittest.skipIf("debian" in os.environ.get("TEST_OS", ""), "No kubernetes on Debian (yet).")
class TestNulecule(KubernetesCase):
    def setUp(self):
        MachineCase.setUp(self)
        m = self.machine

        self.fix_apiserver_config()
        self.start_kubernetes()
        self.wait_api_server()

    def testDeployDialog(self):
        b = self.browser
        m = self.machine
        b.wait_timeout(120)

        self.login_and_go("/kubernetes")
        b.wait_present("#node-list")
        b.wait_in_text("#node-list", "127.0.0.1")

        # 1)check atomic version
        output = m.execute("atomic -v 2>&1")
        self.assertTrue(float(output) >= 1.1)

        # 2) fail  invalid image
        b.click("#deploy-app")
        b.wait_popup("deploy-app-dialog")
        b.set_val("#deploy-app-type", "nulecule")
        b.set_val("#deploy-app-nulecule-image", "submod/helloapache1")
        b.set_val("#deploy-app-namespace", "mynamespace")
        b.dialog_complete("#deploy-app-dialog", result="fail")
        b.dialog_cancel("#deploy-app-dialog")

        # 3) pass when valid image
        b.click("#deploy-app")
        b.wait_popup("deploy-app-dialog")
        b.set_val("#deploy-app-type", "nulecule")
        b.set_val("#deploy-app-nulecule-image", "submod/helloapache:0.1.11")
        b.set_val("#deploy-app-namespace", "mynamespace")
        b.click("#deploy-app-start")
        self.allow_journal_messages('Could not find any image matching "submod/helloapache:0.1.11".')
        b.wait_not_attr("#deploy-app-start", "disabled", "disabled")
        b.dialog_cancel("#deploy-app-dialog")

        # 4) fail when atomic is not installed
        m.needs_writable_usr()
        m.execute("rm /usr/bin/atomic")
        b.click("#deploy-app")
        b.wait_popup("deploy-app-dialog")
        b.set_val("#deploy-app-type", "nulecule")
        b.set_val("#deploy-app-nulecule-image", "submod/helloapache")
        b.set_val("#deploy-app-namespace", "mynamespace")
        b.dialog_complete("#deploy-app-dialog", result="fail")
        b.dialog_cancel("#deploy-app-dialog")

if __name__ == '__main__':
    test_main()
