#!/usr/bin/env python

from builtins import object

import datetime
from io import BytesIO
import json
import logging
import os
import tempfile
import subprocess
import sys

from cryptography import x509
from cryptography.hazmat.backends import default_backend
import fabric

from tools import secretstore
from tools.hscloud import lib as hscloud

import ca


local_root = hscloud.workspace_location()


cluster = 'k0.hswaw.net'
ss = secretstore.SecretStore(
    plain_root=os.path.join(local_root, 'cluster/secrets/plain'),
    cipher_root=os.path.join(local_root, 'cluster/secrets/cipher'))


logger = logging.getLogger()
logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(levelname)s - %(message)s')
sh = logging.StreamHandler()
sh.setFormatter(formatter)
logger.addHandler(sh)



def pki_config(key, fqdn):
    machine_name = fqdn.split('.')[0]
    raw = subprocess.check_output([
        'nix', 'eval', '--raw',
        '( ((import ' + local_root + '/cluster/nix/defs-cluster-k0.nix ) "' + machine_name + '").pki.' + key + '.json )',
    ])
    return json.loads(raw)


def _file_exists(c, filename):
    res = c.run('stat "{}"'.format(filename), warn=True, hide=True)
    return res.exited == 0


def configure_k8s(username, ca, cert, key):
    subprocess.check_call([
        'kubectl', 'config',
        'set-cluster', 'admin.' + cluster,
        '--certificate-authority=' + ca,
        '--embed-certs=true',
        '--server=https://' + cluster + ':4001',
    ])
    subprocess.check_call([
        'kubectl', 'config',
        'set-credentials', username,
        '--client-certificate=' + cert,
        '--client-key=' + key,
        '--embed-certs=true',
    ])
    subprocess.check_call([
        'kubectl', 'config',
        'set-context', 'admin.' + cluster,
        '--cluster=' + 'admin.' + cluster,
        '--user=' + username,
    ])
    subprocess.check_call([
        'kubectl', 'config',
        'use-context', 'admin.' + cluster,
    ])


def admincreds(args):
    if len(args) != 1:
        sys.stderr.write("Usage: admincreds q3k\n")
        return 1
    username = args[0]
    print("")
    print("WARNING WARNING WARNING WARNING WARNING WARNING")
    print("===============================================")
    print("")
    print("You are requesting ADMIN credentials.")
    print("")
    print("You likely shouldn't be doing this, and")
    print("instead should be using `prodaccess`.")
    print("")
    print("===============================================")
    print("WARNING WARNING WARNING WARNING WARNING WARNING")
    print("")

    ## Make kube certificates.
    certs_root = os.path.join(local_root, 'cluster/certs')
    ca_kube = ca.CA(ss, certs_root, 'kube', 'kubernetes main CA')

    local_key = os.path.join(local_root, '.kubectl/admin.key')
    local_crt = os.path.join(local_root, '.kubectl/admin.crt')

    kubectl = os.path.join(local_root, '.kubectl')
    if not os.path.exists(kubectl):
        os.mkdir(kubectl)

    generate_cert = False
    if not os.path.exists(local_key):
        generate_cert = True

    if os.path.exists(local_crt):
        with open(local_crt, 'rb') as f:
            b = f.read()
            cert = x509.load_pem_x509_certificate(b, default_backend())
            delta = cert.not_valid_after - datetime.datetime.now()
            logger.info("admin: existing cert expiry: {}".format(delta))
            if delta.total_seconds() < 3600 * 24:
                logger.info("admin: expires soon, regenerating")
                generate_cert = True
    else:
        generate_cert = True

    if not generate_cert:
        return configure_k8s(username, ca_kube._cert, local_crt, local_key)

    key, csr = ca_kube.gen_key(hosts=['admin', username], o='system:masters', ou='Kube Admin Account')
    crt = ca_kube.sign(csr)

    with open(local_key, 'w') as f:
        f.write(key)

    with open(local_crt, 'w') as f:
        f.write(crt)

    configure_k8s(username, ca_kube._cert, local_crt, local_key)


def nodestrap(args, nocerts=False):
    if len(args) != 1:
        sys.stderr.write("Usage: nodestrap bc01n01.hswaw.net\n")
        return 1
    fqdn = args[0]

    logger.info("Nodestrapping {}...".format(fqdn))
    r = fabric.Connection('root@{}'.format(fqdn))

    if not nocerts:
        cfg = dict((k, pki_config(k, fqdn)) for k in [
            'etcdPeer', 'etcd.server', 'etcd.kube'
        ])
        certs_root = os.path.join(local_root, 'cluster/certs')

        # Make etcd peer certificate for node.
        ca_etcd_peer = ca.CA(ss, certs_root, 'etcdpeer', 'etcd peer ca')
        ca_etcd_peer.make_cert('etcdpeer-{}'.format(fqdn), hosts=[fqdn], ou='node etcd peer certificate')

        # Make etcd server certificate for node and client certificate for kube.
        ca_etcd = ca.CA(ss, certs_root, 'etcd', 'etcd ca')

        ca_etcd.make_cert('etcd-{}'.format(fqdn), hosts=[fqdn], ou='node etcd server certificate')

        ca_etcd.make_cert('etcd-kube', hosts=['kube'], ou='kube etcd client certificate')

        ca_etcd.make_cert('etcd-root', hosts=['root'], ou='root etcd client certificate')

        ca_etcd.make_cert('etcd-calico', hosts=['calico'], ou='root etcd client certificate')

        ## Make kube certificates.
        ca_kube = ca.CA(ss, certs_root, 'kube', 'kubernetes main CA')

        # Make prodvider intermediate CA.
        ca_kube.make_cert('ca-kube-prodvider', o='Warsaw Hackerspace', ou='kubernetes prodvider intermediate', hosts=['kubernetes prodvider intermediate CA'], profile='intermediate').ensure()

        # Make kubelet certificate (per node).
        ca_kube.make_cert('kube-kubelet-'+fqdn, o='system:nodes', ou='Kubelet', hosts=['system:node:'+fqdn, fqdn])

        # Make apiserver certificate.
        ca_kube.make_cert('kube-apiserver', ou='Kubernetes API', hosts=[cluster, 'kubernetes.default.svc.'+cluster, '10.10.12.1'])

        # Make service accounts decryption key (as cert for consistency).
        ca_kube.make_cert('kube-serviceaccounts', ou='Kubernetes Service Accounts Signer', hosts=['serviceaccounts'])

        # Make kube component certificates.
        kube_components = ['controllermanager', 'scheduler', 'proxy']
        cfg = dict((k, pki_config('kube.' + k, fqdn)) for k in kube_components)
        for k in kube_components:
            # meh 
            if k == 'controllermanager':
                o = 'system:kube-controller-manager'
            else:
                o = 'system:kube-'+k
            ou = 'Kubernetes Component '+k
            c = ca_kube.make_cert('kube-'+k, ou=ou, o=o, hosts=[o,])

        ## Make kubefront certificates.
        ca_kubefront = ca.CA(ss, certs_root, 'kubefront', 'kubernetes frontend CA')
        ca_kubefront.make_cert('kubefront-apiserver', ou='Kubernetes Frontend', hosts=['apiserver'])

        ## Make admitomatic (admission controller) certificates.
        ca_admitomatic = ca.CA(ss, certs_root, 'admitomatic', 'admitomatic webhook CA')
        ca_admitomatic.make_cert('admitomatic-webhook', ou='Admitomatic Webhook', hosts=['admitomatic.admitomatic.svc'])

    toplevel = subprocess.check_output([
        "nix-build",
        local_root,
        "-A", "ops.machines.\"" + fqdn + "\".config.passthru.hscloud.provision",
    ]).decode().strip()
    subprocess.check_call([toplevel])


def usage():
    sys.stderr.write("Usage: clustercfg <nodestrap|admincreds>\n")


def main():
    if len(sys.argv) < 2:
        usage()
        return 1

    mode = sys.argv[1]
    if mode == "nodestrap":
        return nodestrap(sys.argv[2:])
    elif mode == "nodestrap-nocerts":
        return nodestrap(sys.argv[2:], nocerts=True)
    elif mode == "admincreds":
        return admincreds(sys.argv[2:])
    elif mode == "smoketest":
        sys.stdout.write("Smoke test passed.")
        return 0
    else:
        usage()
        return 1

if __name__ == '__main__':
    sys.exit(main() or 0)
