#! /usr/bin/env python
# -*- encoding: utf-8; py-indent-offset: 4 -*-

# Author: Sebastian Mark
# CC-BY-SA (https://creativecommons.org/licenses/by-sa/4.0/deed.de)
# for civil use only

import os
from urllib.request import Request, urlopen

import pandas as pd

import yaml


def kubectl(cmd: str) -> str:
    cmd = f"kubectl -n argocd {cmd}"
    return os.popen(cmd).read()


def get_latest_version(repo_url: str, chart: str) -> str:
    req = Request(
        repo_url + "/index.yaml",
        headers={"User-Agent": "Mozilla/5.0"},
    )
    with urlopen(req) as response:
        body = response.read()
    repos = yaml.safe_load(body)

    chart_df = pd.DataFrame(repos["entries"][chart])
    chart_df = chart_df[
        ~chart_df.version.str.contains("alpha") & ~chart_df.version.str.contains("beta")
    ]  # remove alpha versions

    return chart_df.version.iloc[0]


def get_argo_as_app() -> dict:
    cm = kubectl("get configmaps argocd-cm -o yaml")
    cm_formatted = yaml.safe_load(cm)
    version = cm_formatted["metadata"]["labels"]["helm.sh/chart"].lstrip("argo-cd-")

    return dict(
        {
            "metadata": {
                "name": "argocd",
            },
            "spec": {
                "source": {
                    "chart": "argo-cd",
                    "repoURL": "https://argoproj.github.io/argo-helm",
                },
            },
            "status": {
                "sync": {
                    "revision": version,
                }
            },
        }
    )


def get_apps() -> list:
    apps = kubectl("get applications -o yaml")
    app_list = yaml.safe_load(apps)["items"]
    app_list.append(get_argo_as_app())
    return app_list


def main():
    print("{:<20}{:<15}{:<10}".format("name", "installed", "latest"))

    for app in get_apps():
        try:
            app["spec"]["source"]["chart"]  # skip non-helm apps
        except KeyError:
            continue

        name = app["metadata"]["name"]
        chart = app["spec"]["source"]["chart"]
        repo_url = app["spec"]["source"]["repoURL"]
        installed = app["status"]["sync"]["revision"]
        latest = get_latest_version(repo_url, chart)

        print("{:<20}{:<15}{:<10}".format(name, installed, latest))


if __name__ == "__main__":
    main()