#!/usr/bin/env python3

import argparse
import os
import shutil
import subprocess
import sys
import tempfile
import logging
from contextlib import contextmanager


description = """
Get addon templates for the snap.

This will clone the kubernetes repo and place the addons in ./templates
"""

logging.basicConfig(stream=sys.stdout, level=logging.INFO)
log = logging.getLogger(__name__)


def run_with_logging(command):
    """ Run a command with controlled logging """
    log.debug("Running: %s" % command)
    process = subprocess.Popen(command, stderr=subprocess.PIPE)
    stderr = process.communicate()[1].rstrip()
    process.wait()
    if process.returncode != 0:
        log.error(stderr)
        raise Exception("%s: exit code %d" % (command, process.returncode))
    log.debug(stderr)


@contextmanager
def kubernetes_repo():
    """ Yield a kubernetes repo to copy addons from. """
    repo = "https://github.com/kubernetes/kubernetes.git"
    branch = os.environ["KUBE_VERSION"]
    log.info("Cloning %s with branch %s" % (repo, branch))
    path = tempfile.mkdtemp(prefix="kubernetes")
    try:
        cmd = ["git", "clone", repo, path, "-b", branch, "--depth", "1",
               "--single-branch"]
        run_with_logging(cmd)
        yield path
    finally:
        shutil.rmtree(path)

@contextmanager
def kubernetes_dashboard_repo():
    """ Yield a kubernetes dashboard repo to copy yamls from. """
    repo = "https://github.com/kubernetes/dashboard.git"
    tag = os.environ["KUBE_DASHBOARD_VERSION"]
    log.info("Cloning %s and moving to %s" % (repo, tag))
    path = tempfile.mkdtemp(prefix="dashboard")
    try:
        cmd = ["git", "clone", repo, path, "-b", tag, "--depth", "1",
               "--single-branch"]
        run_with_logging(cmd)
        yield path
    finally:
        shutil.rmtree(path)


def add_addon(repo, source, dest, required=True, base='cluster/addons'):
    """ Add an addon template from the given repo and source.

    Any occurrences of 'amd64' are replaced with '{{ arch }}' so the snap can
    fill it in from config. """
    source = os.path.join(repo, base, source)
    if not os.path.exists(source) and not required:
        return
    if os.path.isdir(dest):
        dest = os.path.join(dest, os.path.basename(source))
    log.debug("Copying: %s -> %s" % (source, dest))
    with open(source, "r") as f:
        content = f.read()
    content = content.replace("amd64", "{{ arch }}")
    with open(dest, "w") as f:
        f.write(content)


def get_addon_templates():
    """ Get addon templates. This will clone the kubernetes repo from upstream
    and copy addons to ./templates """
    dest = os.path.abspath("templates")
    os.mkdir(dest)
    with kubernetes_repo() as repo:
        log.info("Copying addons to " + dest)
        add_addon(repo, "dns/kubedns-sa.yaml", dest, required=False)
        add_addon(repo, "dns/kubedns-cm.yaml", dest, required=False)
        try:
            add_addon(repo, "dns/kubedns-controller.yaml.in",
                      dest + "/kubedns-controller.yaml")
            add_addon(repo, "dns/kubedns-svc.yaml.in",
                      dest + "/kubedns-svc.yaml")
        except IOError as e:
            # fall back to the older filenames
            log.debug(e)
            add_addon(repo, "dns/skydns-rc.yaml.in",
                      dest + "/kubedns-controller.yaml")
            add_addon(repo, "dns/skydns-svc.yaml.in",
                      dest + "/kubedns-svc.yaml")

        influxdb = "cluster-monitoring/influxdb"
        add_addon(repo, influxdb + "/grafana-service.yaml", dest)
        add_addon(repo, influxdb + "/heapster-controller.yaml", dest)
        add_addon(repo, influxdb + "/heapster-service.yaml", dest)
        add_addon(repo, influxdb + "/influxdb-grafana-controller.yaml", dest)
        add_addon(repo, influxdb + "/influxdb-service.yaml", dest)

        # Heapster RBAC
        add_addon(repo, "cluster-monitoring/heapster-rbac.yaml", dest)

    with kubernetes_dashboard_repo() as repo:
        log.info("Copying dashboard to " + dest)
        add_addon(repo, "src/deploy/kubernetes-dashboard.yaml",
                  dest, base='.')


def parse_args():
    """ Parse args. This is solely done for the usage output with -h """
    parser = argparse.ArgumentParser(description=description)
    parser.parse_args()


def main():
    """ Parse args and get the addon templates """
    parse_args()
    get_addon_templates()


if __name__ == "__main__":
    main()
