#!/usr/bin/env python3
import re
import json
import os
import dokuwiki
import siteconf

site_conf = siteconf.read()

def dokuwiki_update(text):
    #print(f"dokuwiki url: {site_conf['-']['dokuwiki_url']}")
    try:
        wiki = dokuwiki.DokuWiki(site_conf['-']['dokuwiki_url'], site_conf['-']['dokuwiki_user'], site_conf['-']['dokuwiki_passwd'])
    except (dokuwiki.DokuWikiError, Exception) as err:
        print(f"Cannot connect to wiki: {err}")
        exit(1)
    wiki.pages.set(site_conf['-']['dokuwiki_facts_page'], text)

def read_facts(factsdir):
    facts = {}
    for fn in os.scandir(factsdir):
        if fn.name.startswith('.') or not fn.is_file():
            continue
        with open(fn.path, "r") as f:
            content = f.read()

        try:
            obj = json.loads(content)
        except JSONDecodeError:
            continue

        if "ansible_facts" not in obj:
            #print(f"no 'ansible_facts' in json '{fn.name}'")
            continue
        facts[fn.name] = obj['ansible_facts']
    return facts

def wikitable(facts):
    text = "<sortable 3=numeric 4=numeric 5=numeric 6=nosort>\n" \
           "^name (hostname) ^OS ^vCPU ^mem ^disk ^IP ^\n"
    for host, fact in sorted(facts.items()):
        hostname = host
        if hostname.lower() != fact.get('ansible_hostname', '').lower():
            hostname += f" ({fact.get('ansible_hostname')})"
        opsys = f"{fact.get('ansible_distribution', '-')} {fact.get('ansible_distribution_version', '-')}"
        opsys = re.sub('Microsoft Windows Server', 'Windows Srv', opsys)
        cpus = fact.get('ansible_processor_vcpus', '-')
        mem = f"{int(fact.get('ansible_memtotal_mb', 0))/1024:.1f} GB"
        if not re.search('Windows', fact.get('ansible_distribution', '')):
            disksize = 0
            for dev, attrs in fact.get('ansible_devices', {}).items():
                if not re.match('sd', dev):
                    continue
                disksize += int(attrs.get('sectors', 0)) * int(attrs.get('sectorsize', 0))
            disksize = f"{disksize / 1024**3:.0f} GB"
        else:
            disksize = "-"

        ips = []
        for ip in sorted(fact.get('ansible_all_ipv4_addresses', []) + fact.get('ansible_ip_addresses', [])):
            if not re.match('[0-9.]+$', ip):
                continue
            if re.match('169\.254\.', ip):
                continue
            if re.match('172\.(17|18|21)\.0\.1$', ip): # docker
                continue
            ips.append(ip)
        ips = ' \\\\ '.join(ips)
            

        text += f"|{hostname} |{opsys} |{cpus} |{mem} |{disksize} | {ips} |\n"

    text += "</sortable>\n"
    return text

def main():
    factsdir = "/etc/ansible/gathered_facts"
    facts = read_facts(factsdir)

    text = wikitable(facts)
    #print(text)
    dokuwiki_update(text)

if __name__ == "__main__":
    main()

# vim: set tabstop=4 shiftwidth=4 expandtab smarttab:
