#!/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

import ca


local_root = os.getenv('hscloud_root')
if local_root is None:
    raise Exception("Please source env.sh")


cluster = 'k0.hswaw.net'
remote_root = '/opt/hscloud'
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):
    raw = subprocess.check_output([
        'nix', 'eval', '--raw',
        '( (import ' + local_root + '/nix/toplevel.nix ).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', 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', cluster,
        '--cluster=' + cluster,
        '--user=' + username,
    ])
    subprocess.check_call([
        'kubectl', 'config',
        'use-context', cluster,
    ])


def admincreds(args):
    if len(args) != 1:
        sys.stderr.write("Usage: admincreds q3k\n")
        return 1
    username = args[0]

    ## 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):
    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))

    cfg = dict((k, pki_config(k)) 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.upload(r, cfg['etcdPeer']['ca'])
    c = ca_etcd_peer.make_cert('etcdpeer-{}'.format(fqdn), hosts=[fqdn], ou='node etcd peer certificate')
    c.upload_pki(r, cfg['etcdPeer'])

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

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

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

    # Make root etcd client (do not upload).
    ca_etcd.make_cert('etcd-root', hosts=['root'], ou='root etcd client certificate')

    # Make calico etcd client (do not upload, used by jsonnet).
    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 kubelet certificate (per node).
    c = ca_kube.make_cert('kube-kubelet-'+fqdn, o='system:nodes', ou='Kubelet', hosts=['system:node:'+fqdn, fqdn])
    c.upload_pki(r, pki_config('kube.kubelet'))

    # Make apiserver certificate.
    c = ca_kube.make_cert('kube-apiserver', ou='Kubernetes API', hosts=[cluster, '10.10.12.1'])
    c.upload_pki(r, pki_config('kube.apiserver'), concat_ca=True)

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

    # Make kube component certificates.
    kube_components = ['controllermanager', 'scheduler', 'proxy']
    cfg = dict((k, pki_config('kube.' + k)) for k in kube_components)
    for k in kube_components:
        ca_kube.upload(r, cfg[k]['ca'])
        # 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,])
        c.upload_pki(r, cfg[k])

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

    # Upload NixOS config
    for f in ['toplevel', 'cluster-configuration']:
        r.put(local=os.path.join(local_root, 'nix/{}.nix'.format(f)),
              remote='/etc/nixos/{}.nix'.format(f))

    r.run('nixos-rebuild switch')


def usage():
    sys.stderr.write("Usage: {} <nodestrap|admincreds|config>\n".format(sys.argv[0]))


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

    mode = sys.argv[1]
    if mode == "nodestrap":
        return nodestrap(sys.argv[2:])
    elif mode == "admincreds":
        return admincreds(sys.argv[2:])
    elif mode == "config":
        print('etcd peer:')
        print(json.dumps(pki_config('etcdPeer'), indent=2))
        print('etcd client:')
        print(json.dumps(pki_config('etcdClient'), indent=2))
    else:
        usage()
        return 1

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