#!/usr/bin/env python
import argparse
import re
import collections
from tabulate import tabulate

"""
Script to generate a TABLE representations from information leaked from an instance 
of Kubernetes Metrics Server via its endpoints "/metrics".

Command to get the data:

    wget -q -O kms-data.txt https://[KMS_HOST]/metrics

Sources:
    https://github.com/kubernetes-sigs/metrics-server

Notes & conventions: 
    K8S === KUBERNETES
    KMS === KUBERNETES METRICS SERVER   

Remark:
    Mermaid and other graphical representations were not used due to
    the number of items that cause the generated representation
    to be messy and unsable.

Dependencies:
    pip install tabulate
"""
K8S_RESOURCE_TYPES = ["pod", "deployment", "service", "configmap", "node", "secret"]
NAMESPACE_REGEX = r'namespace="(.*?)"'


def load_records(kms_data_file):
    # KEY is the namespace
    # VALUE is a DICT for which KEY is the K8S resource type and VALUE is a list of the related K8S resource names
    records = {}
    with open(kms_data_file, mode="r", encoding="utf-8") as f:
        lines = f.read().splitlines()
    for line in lines:
        # Skip comment
        if line.startswith("#"):
            continue
        # Extract the namespace
        results = re.findall(NAMESPACE_REGEX, line, re.IGNORECASE)
        k8s_ns = "default"
        if len(results) > 0 and results[0] != "":
            k8s_ns = results[0]
        if k8s_ns not in records:
            records[k8s_ns] = {}
        # Extract the related resource types
        for resource_type in K8S_RESOURCE_TYPES:
            resource_type_regex = f"{resource_type}=\"(.*?)\""
            results = re.findall(resource_type_regex, line, re.IGNORECASE)
            if len(results) > 0:
                resource_name = results[0]
                if resource_type not in records[k8s_ns]:
                    records[k8s_ns][resource_type] = []
                if resource_name not in records[k8s_ns][resource_type]:
                    records[k8s_ns][resource_type].append(resource_name)
    return collections.OrderedDict(sorted(records.items()))


def generate_representation(records):
    table_rows = []
    count_ns = 0
    count_res = 0
    for namespace, namespace_items in records.items():
        content = []
        count_ns += 1
        for namespace_item in namespace_items:
            content.append(f"{len(namespace_items[namespace_item])} {namespace_item.title()}s")
            count_res += len(namespace_items[namespace_item])
        content.sort()
        table_row = [namespace, " / ".join(content)]
        table_rows.append(table_row)
        table_headers = [f"Namespace ({count_ns})", f"Resource types  ({count_res})"]
    print(tabulate(table_rows, headers=table_headers,  numalign="right", stralign="left", tablefmt="grid"))


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Script to generate a TABLE representations from information leaked from an instance of Kubernetes Metrics Server via its endpoints '/metrics'.")
    parser.add_argument("-f", action="store", dest="kms_data_file", help="Text file with the KMS data.", required=True)
    args = parser.parse_args()
    records = load_records(args.kms_data_file)
    generate_representation(records)
