#!/usr/bin/python2
# -*- 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/>.

import parent
from testlib import *

import os
import unittest
import time
import sys

from kubelib import *

# NOTE: Both TestOpenshift and TestRegistry are in this single file to
# prevent them from being run concurrently.  Both use a 'openshift'
# machine, and we can only run a single one of those at the same time.

def wait_project(machine, project):
    i = 0
    found = True
    while True:
        try:
            output = machine.execute("oc get projects")
            if project not in output:
                if not found:
                    sys.stderr.write(output)
                found = True
                raise Exception(output)
            break
        except:
            if i > 60:
                raise
            i = i + 1
            time.sleep(2)

@skipImage("Kubernetes not packaged", "debian-stable", "debian-testing", "ubuntu-1604", "ubuntu-stable", "fedora-i386")
@skipImage("No cockpit-kubernetes packaged", "continuous-atomic", "fedora-atomic", "rhel-atomic")
class TestOpenshift(MachineCase, OpenshiftCommonTests):
    provision = {
        "machine1": { "address": "10.111.113.1/20" },
        "openshift": { "image": "openshift", "forward": { 30000: 30000, 8443: 8443 } }
    }

    def setUp(self):
        super(TestOpenshift, self).setUp()

        self.openshift = self.machines['openshift']
        self.openshift.upload(["verify/files/mock-app-openshift.json"], "/tmp")
        self.kubeconfig = os.path.join(self.tmpdir, "config")
        self.openshift.download("/root/.kube/config", self.kubeconfig)

        m = self.machine
        m.execute("mkdir -p /home/admin/.kube")
        m.upload([self.kubeconfig], "/home/admin/.kube/config")
        m.execute("chown -R admin:admin /home/admin/.kube")

        wait_project(self.openshift, "marmalade")

        # Expect the default container user limitations during testing
        self.openshift.execute("oc patch scc restricted -p '{ \"runAsUser\": { \"type\": \"MustRunAsRange\" } }'")

        self.browser.wait_timeout(120)

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

        # Make sure we can write to kubeconfig
        m.execute("chown -R admin:admin /home/admin/.kube")
        self.login_and_go("/kubernetes")

        # kubevirt not available, so should not show up in the menu
        b.wait_not_present("#vms-menu-link")

        b.wait_present("#service-list")
        b.wait_in_text("#service-list", "docker-registry")
        b.wait_present("a[href='#/volumes']")
        b.click("a[href='#/volumes']")
        b.wait_present(".pv-listing")
        b.wait_in_text(".pv-listing", "No volumes are present")
        b.click("a[href='#/']")

        b.wait_present("#kubernetes-change-connection")
        b.click("#kubernetes-change-connection")
        b.wait_present("modal-dialog")
        b.wait_present("#kubernetes-cluster")
        b.wait_present("#kubernetes-user")
        b.wait_not_present("#kubernetes-username")
        b.wait_not_present("#kubernetes-password")
        b.wait_not_present("#kubernetes-token")

        b.wait_in_text("#kubernetes-cluster button", "10-111-112-101:8443")
        b.wait_in_text("#kubernetes-user button", "system:admin/10-111-112-101:8443")
        b.wait_in_text("modal-dialog", "Client Certificate")

        b.click("#kubernetes-user button")
        b.click("#kubernetes-user ul li:last-child a")
        b.wait_in_text("#kubernetes-user button", "Add New User")
        b.wait_not_present("#kubernetes-token")
        b.wait_val("#kubernetes-username", "")
        b.wait_val("#kubernetes-password", "")
        b.set_val("#kubernetes-username", "new-user")
        b.set_val("#kubernetes-password", "new-user")

        b.click("modal-dialog div.modal-footer button.btn-primary")
        b.wait_not_present("modal-dialog")

        # scruffy isn't a admin
        b.wait_present("#service-list")
        b.wait_not_in_text("#service-list", "docker-registry")
        b.wait_present("a[href='#/volumes']")
        b.click("a[href='#/volumes']")
        b.wait_present(".pv-listing")
        b.wait_in_text(".pv-listing", "cannot watch all")
        b.click("a[href='#/']")

        b.wait_present("#kubernetes-change-connection")
        b.click("#kubernetes-change-connection")
        b.wait_present("modal-dialog")
        b.wait_present("#kubernetes-cluster")
        b.wait_present("#kubernetes-user")
        b.wait_not_present("#kubernetes-username")
        b.wait_not_present("#kubernetes-password")
        b.wait_present("#kubernetes-token")

        b.wait_in_text("#kubernetes-cluster button", "10-111-112-101:8443")
        b.wait_in_text("#kubernetes-user button", "new-user/10-111-112-101:8443")
        b.wait_not_in_text("modal-dialog", "Client Certificate")
        self.assertFalse(b.val("#kubernetes-token") == "")

        b.logout()

        # Test the saved kube config file
        m.execute("rm /home/admin/.kube/config")
        m.upload([self.kubeconfig], "/home/admin/.kube/config")
        m.execute("chown -R admin:admin /home/admin/.kube")

        self.login_and_go("/kubernetes")

        b.wait_present("#service-list")
        b.wait_in_text("#service-list", "docker-registry")

    @unittest.skipIf(True, "Nulecule deploys temporarily removed.")
    def testDeployDialog(self):
        b = self.browser
        m = self.machine
        b.wait_timeout(240)
        m.execute("systemctl start docker")
        # m.execute("docker pull submod/helloapache")
        tmpfile = os.path.join(self.tmpdir, "oc")
        self.openshift.download("/usr/bin/oc", tmpfile)
        m.upload([tmpfile], "/usr/local/bin")

        self.login_and_go("/kubernetes")
        b.wait_present("#service-list")
        b.wait_in_text("#service-list", "registry")

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

        # 2)check provider is supported
        m.execute("mkdir /var/tmp/invalid-app1")
        m.execute("""echo -e '
FROM busybox
MAINTAINER cockpit
LABEL io.projectatomic.nulecule.atomicappversion="0.1.11" \
      RUN="docker run -it --rm \${OPT1} --privileged -v `pwd`:/atomicapp -v /run:/run -v /:/host --net=host --name \${NAME} -e NAME=\${NAME} -e IMAGE=\${IMAGE} \${IMAGE} -v \${OPT2} run \${OPT3} /atomicapp" \
      STOP="docker run -it --rm \${OPT1} --privileged -v `pwd`:/atomicapp -v /run:/run -v /:/host --net=host --name \${NAME} -e NAME=\${NAME} -e IMAGE=\${IMAGE} \${IMAGE} -v \${OPT2} stop \${OPT3} /atomicapp" \
      INSTALL="docker run -it --rm \${OPT1} --privileged -v `pwd`:/atomicapp -v /run:/run  --name \${NAME} -e NAME=\${NAME} -e IMAGE=\${IMAGE} \${IMAGE} -v \${OPT2} install \${OPT3} --destination /atomicapp /application-entity" \
      io.projectatomic.nulecule.providers="kubernetes" \
      io.projectatomic.nulecule.specversion=0.0.2 \
      io.projectatomic.nulecule.atomicappversion="0.1.11"
' > /var/tmp/invalid-app1/Dockerfile""")
        m.execute("docker build -t test/invalid-app1 /var/tmp/invalid-app1")
        m.execute("rm -rf /var/tmp/invalid-app1")

        b.click("#deploy-app")
        b.wait_popup("deploy-app-dialog")
        b.set_val("#deploy-app-type", "nulecule")
        b.set_val("#deploy-app-nulecule-image", "test/invalid-app1")
        b.set_val("#deploy-app-namespace", "mynamespace")
        b.click("#deploy-app-start")
        b.wait_not_attr("#deploy-app-start", "disabled", "disabled")
        b.is_visible(".modal-footer .alert")
        self.assertEqual(b.text(".modal-footer .alert") ,"No supported providers found.")
        b.dialog_cancel("#deploy-app-dialog")

        # 3)check atomicappversion is supported
        m.execute("mkdir /var/tmp/invalid-app2")
        m.execute("""echo -e '
FROM busybox
MAINTAINER cockpit
LABEL io.projectatomic.nulecule.atomicappversion="0.1.11" \
      RUN="docker run -it --rm \${OPT1} --privileged -v `pwd`:/atomicapp -v /run:/run -v /:/host --net=host --name \${NAME} -e NAME=\${NAME} -e IMAGE=\${IMAGE} \${IMAGE} -v \${OPT2} run \${OPT3} /atomicapp" \
      STOP="docker run -it --rm \${OPT1} --privileged -v `pwd`:/atomicapp -v /run:/run -v /:/host --net=host --name \${NAME} -e NAME=\${NAME} -e IMAGE=\${IMAGE} \${IMAGE} -v \${OPT2} stop \${OPT3} /atomicapp" \
      INSTALL="docker run -it --rm \${OPT1} --privileged -v `pwd`:/atomicapp -v /run:/run  --name \${NAME} -e NAME=\${NAME} -e IMAGE=\${IMAGE} \${IMAGE} -v \${OPT2} install \${OPT3} --destination /atomicapp /application-entity" \
      io.projectatomic.nulecule.providers="kubernetes,openshift" \
      io.projectatomic.nulecule.specversion=0.0.2 \
      io.projectatomic.nulecule.atomicappversion="0.0.11"
' > /var/tmp/invalid-app2/Dockerfile""")
        m.execute("docker build -t test/invalid-app2 /var/tmp/invalid-app2")
        m.execute("rm -rf /var/tmp/invalid-app2")

        b.click("#deploy-app")
        b.wait_popup("deploy-app-dialog")
        b.set_val("#deploy-app-type", "nulecule")
        b.set_val("#deploy-app-nulecule-image", "test/invalid-app2")
        b.set_val("#deploy-app-namespace", "mynamespace")
        b.click("#deploy-app-start")
        b.wait_not_attr("#deploy-app-start", "disabled", "disabled")
        b.is_visible(".modal-footer .alert")
        self.assertEqual(b.text(".modal-footer .alert") ,"atomicapp version 0.0.11 is not supported.")
        b.dialog_cancel("#deploy-app-dialog")


        # 5)check for all metadata
        m.execute("mkdir /var/tmp/invalid-app4")
        m.execute("""echo -e '
FROM busybox
MAINTAINER cockpit
LABEL io.projectatomic.nulecule.providers="kubernetes,openshift"
' > /var/tmp/invalid-app4/Dockerfile""")
        m.execute("docker build -t test/invalid-app4 /var/tmp/invalid-app4")
        m.execute("rm -rf /var/tmp/invalid-app4")

        b.click("#deploy-app")
        b.wait_popup("deploy-app-dialog")
        b.set_val("#deploy-app-type", "nulecule")
        b.set_val("#deploy-app-nulecule-image", "test/invalid-app4")
        b.set_val("#deploy-app-namespace", "mynamespace")
        b.click("#deploy-app-start")
        b.wait_not_attr("#deploy-app-start", "disabled", "disabled")
        b.is_visible(".modal-footer .alert")
        self.assertEqual(b.text(".modal-footer .alert") ,"This image is not a supported Nulecule image")
        b.dialog_cancel("#deploy-app-dialog")


        # 6)check when atomicapp is not available
        m.execute("mkdir /var/tmp/invalid-app5")
        m.execute("""echo -e '
FROM busybox
MAINTAINER cockpit
LABEL io.projectatomic.nulecule.atomicappversion="0.1.11" \
      RUN="docker run -it --rm \${OPT1} --privileged -v `pwd`:/atomicapp -v /run:/run -v /:/host --net=host --name \${NAME} -e NAME=\${NAME} -e IMAGE=\${IMAGE} \${IMAGE} -v \${OPT2} run \${OPT3} /atomicapp" \
      STOP="docker run -it --rm \${OPT1} --privileged -v `pwd`:/atomicapp -v /run:/run -v /:/host --net=host --name \${NAME} -e NAME=\${NAME} -e IMAGE=\${IMAGE} \${IMAGE} -v \${OPT2} stop \${OPT3} /atomicapp" \
      INSTALL="docker run -it --rm \${OPT1} --privileged -v `pwd`:/atomicapp -v /run:/run  --name \${NAME} -e NAME=\${NAME} -e IMAGE=\${IMAGE} \${IMAGE} -v \${OPT2} install \${OPT3} --destination /atomicapp /application-entity" \
      io.projectatomic.nulecule.providers="kubernetes,openshift" \
      io.projectatomic.nulecule.specversion=0.0.2 \
      io.projectatomic.nulecule.atomicappversion="0.1.11"
' > /var/tmp/invalid-app5/Dockerfile""")
        m.execute("docker build -t test/invalid-app5 /var/tmp/invalid-app5")
        m.execute("rm -rf /var/tmp/invalid-app5")

        b.click("#deploy-app")
        b.wait_popup("deploy-app-dialog")
        b.set_val("#deploy-app-type", "nulecule")
        b.set_val("#deploy-app-nulecule-image", "test/invalid-app5")
        b.set_val("#deploy-app-namespace", "mynamespace")
        b.click("#deploy-app-start")
        b.wait_not_attr("#deploy-app-start", "disabled", "disabled")
        b.is_visible(".modal-footer .alert")
        self.assertEqual(b.text(".modal-footer .alert") ,"Image failed to install.")
        b.dialog_cancel("#deploy-app-dialog")

        # 7) fail when Unable to pull Nulecule app
        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.click("#deploy-app-start")
        b.wait_not_attr("#deploy-app-start", "disabled", "disabled")
        b.is_visible(".modal-footer .alert")
        self.assertEqual(b.text(".modal-footer .alert") ,"Unable to pull Nulecule app image.")
        b.dialog_cancel("#deploy-app-dialog")

        # 8) check if app can be deployed
        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.click("#deploy-app-start")
        b.wait_popdown("deploy-app-dialog")
        b.click("a[href='#/list']")
        b.wait_present("#content .details-listing")
        b.wait_present(".details-listing tbody[data-id='pods/default/helloapache'] th")
        self.assertEqual(b.text(".details-listing tbody[data-id='pods/default/helloapache'] th"), "helloapache")

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

        # Try to connect with an old and non-matching client cert
        old_cert = ('LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUREVENDQWZXZ0F3SUJBZ0lCQnpBTkJna3Foa2'
                    'lHOXcwQkFRc0ZBREFtTVNRd0lnWURWUVFEREJ0dmNHVnUKYzJocFpuUXRjMmxuYm1WeVFERTBPVEEy'
                    'T0RFMk16RXdIaGNOTVRjd016STRNRFl4TXpVeVdoY05NVGt3TXpJNApNRFl4TXpVeldqQTNNUjR3SE'
                    'FZRFZRUUtFeFZ6ZVhOMFpXMDZZMngxYzNSbGNpMWhaRzFwYm5NeEZUQVRCZ05WCkJBTVRESE41YzNS'
                    'bGJUcGhaRzFwYmpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUIKQU5Rel'
                    'J5SzUzQUhmdlZnME5GTHRSSENhMTEyK3l5a0xXdG14bjAxb2JTMy85VmovQU1UdmZwNVRkUlhKNjF'
                    'WcAo3L0N1L1pkQ3RDc1pyNnJpYVMxbUJGcmtTSkZJdmFjN2NNa3k2M0tVVXNaQmU5ZGFLdG1OMmhY'
                    'TUt0VitESStvCjJFQVJNWlV5YTZIMzJXZUpzRGM0L1lscUR5TFAxYVR3NWNwRTJPY3dWQTdoQ1dCS'
                    'ysyajIvZTl6RDhrYzM2R24KNG0wZWd3YWxlZ2UwTXFaUk1BbTFkenRpS3I1UWZ4MG9ZVUY3Z0JIYm'
                    'RjM253cGZ6a3M2K1F4Tkl6V0hlRmN2WApxcXpsMGxnT2ZGeWc0VWptYzhFcTBiKy9ER3lYSGlHNXN'
                    'vVmw1RGlVa1RKRjNrcURCZVVjZWNZaEx1VDd4emxzClk0bldYVFprc3lJMXVoZFJmS2NnbVZjQ0F3'
                    'RUFBYU0xTURNd0RnWURWUjBQQVFIL0JBUURBZ1dnTUJNR0ExVWQKSlFRTU1Bb0dDQ3NHQVFVRkJ3T'
                    'UNNQXdHQTFVZEV3RUIvd1FDTUFBd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQgpBRy9rTElnQ2YwK2'
                    '1MZ1VXcWZjS2NLN0Nmdm9PbS9qL0FUSW1MR0YvSUtvQTRCWGhqMG5EcEszeVd3ZGt4d0hZCmxxUDh'
                    'xZ1NyQ1FaNkVoSlpMSWtjQWovTUlTUEUvSlJPa3R5TWFTMis4OGhqeGpxdUhucnZ5ODA5ZlJ5QzhF'
                    'R2kKeVIyRzhtNGJ5MEJrOWhENkVxbDYxb21VU0MzL2ozR3lPUGNZWDJEQjZsU2h4ZlFJVEpqUWNKQ'
                    '0oyMnNDdlBBOApVeU9EaUgrNllZSVdtVFN5a2kzazk0Q3NOZXlRbERjNzh3a1BseUdrN0p1anFIK2p'
                    'KaURXSDQ2TXE3TTNaVVArCmowQWxhd3dtdllsRjBVZEIwdGRCenZWR21RbTRudEwwSkhVMGFqRnUy'
                    'QTYvTjJmT3VrZWI0TDR6elBzSkJFNHIKaUUyNWRJUlAvWHRoM0tjRFYyYkxtMUk9Ci0tLS0tRU5EI'
                    'ENFUlRJRklDQVRFLS0tLS0K')
        old_key = ('LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBMUROSElybmNBZC'
                   's5V0RRMFV1MUVjSnJYWGI3TEtRdGEyYkdmVFdodExmLzFXUDhBCnhPOStubE4xRmNuclZXbnY4Szc5'
                   'bDBLMEt4bXZxdUpwTFdZRVd1UklrVWk5cHp0d3lUTHJjcFJTeGtGNzExb3EKMlkzYUZjd3ExWDRNa'
                   'jZqWVFCRXhsVEpyb2ZmWlo0bXdOemo5aVdvUElzL1ZwUERseWtUWTV6QlVEdUVKWUVyNwphUGI5Nz'
                   'NNUHlSemZvYWZpYlI2REJxVjZCN1F5cGxFd0NiVjNPMklxdmxCL0hTaGhRWHVBRWR0MXplZkNsL09'
                   'TCnpyNURFMGpOWWQ0Vnk5ZXFyT1hTV0E1OFhLRGhTT1p6d1NyUnY3OE1iSmNlSWJteWhXWGtPSlNS'
                   'TWtYZVNvTUYKNVJ4NXhpRXU1UHZIT1d4amlkWmRObVN6SWpXNkYxRjhweUNaVndJREFRQUJBb0lCQ'
                   'UNxbjNDYlk0YWJteVBNUQpHMnlJRVhmcFNGMnAyc0QzYlYzUlhNcDhzV1hMekJBRndxdlQwTW9XME'
                   'xSK2tIWHRBN1NJR0tYdFhMWkZSWkMrClRwSTNyYXh2c3o2eE5wNkZUbGpEaVp6UXdBcm1ZdlNaUlg'
                   'vU0NnTFR0ZENRdEFtMDBUT2Z3UzNTb3R3K0xFK3AKMStoaDVtVlhFby9XNDRWeWYxNjNsRHAwOXBD'
                   'K3dpS0ZEa2JHVExBdnA1bnFaMnhtZDRyNzhyMi9TZmZ2YUplZQpJSlpwbENMYzMyQkVZaE4yeDRIa'
                   'HpqQkhOdTJwYkFXS2twUDVjWkZNS3QwSUkrRTN0UUNWMlkrYVZvNTY0TzRGCjZxMmFUUzVxMnRuaW'
                   'VBTS9uay8zN3hkNUVoNjRpMU8vQTU2YzdoZmxkMDVQMC9PdU9OY2dsaVVYRG44cnFvOUoKdXpFQ1F'
                   'ORUNnWUVBN0xOeWRQQlhkdEZRZ3NrWG56UlVYM3hhYWFCYU8xYnJYZzVmUnlMVm5DY2thWlRORXlE'
                   'dAp3eURxSGRUOGtRNXNIcXZ3WDNxNXR1elZBZ3NJUlhvcTZIUGtxRWdLeFZIclhTNzY1OFhLUnR1S'
                   'GswbE11ZkQxCnVPVVBaTTJYNVR4NXRmTmh1Zlh3dXZqTkdyN0E3ZEw4VUFiY3ZtS2VuSnF2bDNJZX'
                   'I0cVpkdDBDZ1lFQTVZQncKZ2pNTGJRZStEUzd1QmdsOFVmdGl5YnZCbDdTSEQ4T2RWamVOdzNEZjJ'
                   'uckltQVdLTVhNTk5GWldwbmhhc0g3Swp1bWtMQWdMNWFEWXJhaFJHN2ZwMGd0YnN0RVE5Uit2dFVp'
                   'azMxaFNHUS83dFBENU1LaU1jcFpnazhYUXI5UnlFCkVEN285bWFvUEZibnJKbFl5VXNQY0FCN3Y1W'
                   'FNxaVdqeFZMODI4TUNnWUVBNUhoSk1DcVVvZkZqL3ZsUFBiSnIKQmtlbmxYRGI1NDc4WEtzT3VFRW'
                   'RZajQ5M1ZOdHB0c1A1RnF1MytDbmNQUTAxRjR1QkZzWFMwUEtUdENMU1ZTawplZjd6WktNMUVrVUN'
                   'JODJuRFhSU3pKWTFoS3NwemdpUmhjaERWWTlFNEZYQlBTa1EyVWhVOW9RVXBZNGQ5dkRCCjdoVFJt'
                   'VXJqd2xGa3o0K3RvczdyVmxrQ2dZRUF4RW8vY0V5aVNDV29HblI2Sm5XMGZCWUxuMGxVUWlHb3B3W'
                   'UQKS3Z1bTUzTkNNd1p6VFByb0FIVkw1T2kzZ2ZoTWNNcHhNRkNwbHBYZXBaQTNQNnFLSS83ajZnaF'
                   'RPYmRueG56MgpaU0JWM21kOWt1aVdGY0dldVNlQTErMHlJOFhkMXU0RjBqTk1ZM3JZQjR1NDZQbmJ'
                   'ZNGNzYy9vbDNXNFNXVzZLCkRUcDJoS3NDZ1lCSlpMQys3Uy9zRGVqdkl0MTZ2Q3JzbDJlWlFsb1p0'
                   'clNoVCtTb0hmR1NPRXZkMXp1NStBL3UKaVVDYyt1SHdUa1c0RVpMTEdBYkUzTG1xSllJcXNkNVpUW'
                   'UkxWTZ1TGoyV1NGWFZYUXVLanVlTDZJdGttc1dvZgpyMHFtQU93RHdFVDFvRXlNVUJoOTJVMmhxSHR'
                   'aamlMdkxQdDc5aUhacDNtTnlLVjc5QXY3dVE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=')

        m.execute("sed -i '/client-certificate-data:/ s/:.*$/: %s/; /client-key-data:/ s/:.*$/: %s/' /home/admin/.kube/config" % (
            old_cert, old_key))
        m.execute("chown -R admin:admin /home/admin/.kube")
        self.login_and_go("/kubernetes")

        b.wait_present(".curtains-ct")
        b.wait_visible(".curtains-ct")
        b.wait_in_text(".curtains-ct", "Couldn't connect to server")
        b.wait_in_text(".curtains-ct", "Unauthorized")
        b.wait_present(".curtains-ct #kubernetes-reconnect")

        # now provide a good certificate, and reconnect
        m.upload([self.kubeconfig], "/home/admin/.kube/config")
        m.execute("chown -R admin:admin /home/admin/.kube")

        b.click("#kubernetes-reconnect")
        b.wait_present("#service-list")

    def bootstrapKubevirt(self):
        o = self.openshift

        o.execute("/root/nested-kvm") # not enabled by default; for troubleshooting use "virt-host-validate qemu"
        o.execute("(cat /sys/module/kvm_intel/parameters/nested || cat /sys/module/kvm_amd/parameters/nested) | grep -q Y")

        o.execute("oc project kube-system")
        o.execute("oc create serviceaccount -n kube-system kubevirt")
        o.execute("oc adm policy add-scc-to-user privileged -n kube-system -z kubevirt")
        o.execute("oc adm policy add-scc-to-user privileged -n kube-system -z kubevirt-admin")
        o.execute("oc adm policy add-scc-to-user privileged -n kube-system -z default")

        o.execute("oc apply -f /kubevirt/kubevirt.yaml") # finalize installation of kubevirt

        wait(lambda: "Running" in o.execute("oc get pods | grep virt-controller"), delay=2) # is it deployed and up?
        wait(lambda: "No resources found" in o.execute("oc get vm 2>&1"), delay=2) # No VM created yet

    def testKubevirtMachinesList(self):
        self.bootstrapKubevirt()

        o = self.openshift
        # *.yaml files comes from kubevirt distribution, see tarball extraction in bots/images/script/lib/kubevirt.setup
        o.execute("oc create -f /kubevirt/iscsi-demo-target.yaml")  # disk for test VM
        o.execute("oc create -f /kubevirt/vm.yaml")  # let's create a VM
        wait(lambda: "testvm" in o.execute("oc get vm"), msg='Deployment of virtual machine "testvm" failed.')
        wait(lambda: "virt-launcher-testvm" in o.execute("oc get pods"))
        wait(lambda: "Running" in o.execute("oc get pods | grep virt-launcher-testvm"))

        b = self.browser
        self.login_and_go("/kubernetes")
        # kubevirt is available, so link should be present
        b.wait_present("#vms-menu-link")
        b.click("#vms-menu-link")
        b.wait_present("tr[data-row-id='vm-testvm']")
        self.assertEqual(b.text("tr[data-row-id='vm-testvm'] th"), "testvm")

        # expand row and check the Overview subtab
        b.click("tr[data-row-id='vm-testvm']")
        b.wait_present("tr[data-row-id='vm-testvm'] + tr.listing-ct-panel")
        b.wait_in_text("tr[data-row-id='vm-testvm'] + tr.listing-ct-panel", "Node")
        b.wait_present("#vm-testvm-memory")
        b.wait_in_text("#vm-testvm-memory", "64M")
        b.wait_in_text("#vm-testvm-labels", "kubevirt.io/nodeName=f1.cockpit.lan")
        b.wait_present("#vm-testvm-pod")

        # switch to the Disks subtab
        b.wait_present("#vm-testvm-disks-tab")
        b.click("#vm-testvm-disks-tab")
        b.wait_present("#vm-testvm-disks-total-value") # wait for the "Count" value
        b.wait_in_text("#vm-testvm-disks-total-value", "1")
        b.wait_present("#vm-testvm-disks-vda-device") # check disk properties
        b.wait_in_text("#vm-testvm-disks-vda-device", "mydisk")
        b.wait_in_text("#vm-testvm-disks-vda-target", "vda")
        b.wait_in_text("#vm-testvm-disks-vda-capacity", "1Gi")
        b.wait_in_text("#vm-testvm-disks-vda-bus", "iSCSI")
        b.wait_in_text("#vm-testvm-disks-volume", "iscsi-disk-alpine")
        b.click("tr.listing-ct-item.listing-ct-noexpand") # test navigation to the "Volumes" page
        b.wait_js_cond('window.location.hash === "#/volumes/iscsi-disk-alpine"')

        # return back to the virtual-machines
        b.wait_present("#vms-menu-link") # left-side menu
        b.click("#vms-menu-link")
        b.wait_present("tr[data-row-id='vm-testvm']") # the row is already expanded if saving of UI state works

        # delete VM
        b.wait_present("#vm-testvm-delete")
        b.click("#vm-testvm-delete")
        b.wait_present("#kubernetes-virtual-machines-root tr > td:contains(No virtual machines)")

        # start the VM again - TODO: replace this step by OfflineVirtualMachines once implemented
        o.execute("oc create -f /kubevirt/vm.yaml")  # let's create a VM
        wait(lambda: "testvm" in o.execute("oc get vm"), msg='Deployment of virtual machine "testvm" failed.')
        wait(lambda: "virt-launcher-testvm" in o.execute("oc get pods"))
        wait(lambda: "Running" in o.execute("oc get pods | grep virt-launcher-testvm"))

        # link to node
        b.wait_present("tr[data-row-id='vm-testvm']") # the just-started VM is listed
        b.click("tr[data-row-id='vm-testvm']")  # expand row
        b.wait_present("tr[data-row-id='vm-testvm'] + tr.listing-ct-panel")
        b.wait_present("#vm-testvm-node")
        wait(lambda: b.text("#vm-testvm-node > a").strip() != "-") # `-` ==  unassigned ; so wait for a change
        node_name = b.text("#vm-testvm-node > a").strip()
        b.click("#vm-testvm-node > a") # jump to "node" detail
        b.wait_js_cond('window.location.hash === "#/nodes/%s"' % (node_name,))

        # link to pod
        b.click("#vms-menu-link")
        b.wait_present("tr[data-row-id='vm-testvm']") # the row is already expanded if saving of UI state works
        b.wait_present("#vm-testvm-pod")
        wait(lambda: b.text("#vm-testvm-pod > a").strip() != "")
        b.wait_in_text("#vm-testvm-pod", "virt-launcher-testvm---") # Example: virt-launcher-testvm-----rx59t
        pod_name = b.text("#vm-testvm-pod > a").strip()
        b.click("#vm-testvm-pod > a")
        b.wait_js_cond('window.location.hash === "#/l/pods/kube-system/%s"' % (pod_name))


class TestOpenshiftPrerelease(TestOpenshift):
    provision = {
        "machine1": { "address": "10.111.113.1/20" },
        "openshift": { "image": "openshift-prerelease", "forward": { 30000: 30000, 8443: 8443 } }
    }


@skipImage("Kubernetes not packaged", "debian-stable", "debian-testing", "ubuntu-1604", "ubuntu-stable", "fedora-i386")
@skipImage("No cockpit-kubernetes packaged", "continuous-atomic", "fedora-atomic", "rhel-atomic")
class TestRegistry(MachineCase, RegistryTests):
    provision = {
        "machine1": { "address": "10.111.113.1/20" },
        "openshift": { "image": "openshift" }
    }
    registry_root = "/kubernetes/registry"

    def setup_user(self, user, password):
        tmpfile = os.path.join(self.tmpdir, "kubeconfig")
        self.openshift.execute('printf "{0}\r\n{1}\r\n" | oc login'.format(user, password))
        self.openshift.download("/root/.kube/config", tmpfile)
        with open(tmpfile, "r") as f:
            self.machine.execute("mkdir -p /home/admin/.kube && cat > /home/admin/.kube/config", input=f.read())

    def setUp(self):
        super(TestRegistry, self).setUp()

        self.openshift = self.machines['openshift']

        # Sync over the kube config file
        tmpfile = os.path.join(self.tmpdir, "config")
        self.openshift.download("/root/.kube/config", tmpfile)
        with open(tmpfile, "r") as f:
            self.machine.execute("mkdir -p /home/admin/.kube && cat > /home/admin/.kube/config", input=f.read())
        wait_project(self.openshift, "marmalade")

        self.browser.wait_timeout(120)


class TestRegistryPrerelease(TestRegistry):
    provision = {
        "machine1": { "address": "10.111.113.1/20" },
        "openshift": { "image": "openshift-prerelease", "forward": { 30000: 30000, 8443: 8443 } }
    }


if __name__ == '__main__':
    test_main()
