#!/usr/bin/python3

import json
import pathlib
import re
import sys

in_error = False

def error(msg):
    print("ERROR: " + msg)
    global in_error
    in_error = True

def has_link(name):
    for l in links:
        if l['ifname'] == name:
            return
    error("link {} not found".format(name))

def has_an_ipv4_addr(name):
    for l in addrs:
        if l['ifname'] == name:
            for addr in l['addr_info']:
                if addr['family'] == 'inet' and addr['scope'] == 'global':
                    print("found addr {} for {}".format(addr, name))
                    return
            error("{} appears to have no addresses".format(name))
            return
    error("link {} not found".format(name))

def has_no_ipv4_addr(name):
    for l in addrs:
        if l['ifname'] == name:
            for addr in l['addr_info']:
                if addr['family'] == 'inet' and addr['scope'] == 'global':
                    error("found addr {} for {}".format(addr, name))
                    return
            print("{} appears to have no addresses".format(name))
            return
    error("link {} not found".format(name))

def has_ipv4_addr(name, wanted_addr):
    for l in addrs:
        if l['ifname'] == name:
            for addr in l['addr_info']:
                if addr['family'] == 'inet' and addr['scope'] == 'global':
                    if addr['local'] == wanted_addr:
                        print("found addr {} for {}".format(addr, name))
                        return
            error("{} appears not to have address {}".format(name, wanted_addr))
            return
    error("link {} not found".format(name))


def extract_from_log(log: str, key: str) -> str:
    """Extract the command output from the given log output.

    The output must be framed by a header and a footer line. The header
    line contains the key surrounded by 10 # characters. The footer
    line consist of 40 # characters.
    """
    marker = "#" * 10
    footer = "#" * 40
    match = re.search(
        f"^{marker} {re.escape(key)} {marker}\n(.*?\n){footer}$",
        log,
        flags=re.DOTALL | re.MULTILINE,
    )
    if not match:
        error(f"Block '{marker} {key} {marker}' not found in log output")
        sys.exit(1)
    return match.group(1)


log_file = sys.argv[1]
log = pathlib.Path(log_file).read_text(encoding="ascii")
addrs = json.loads(extract_from_log(log, "ip -json addr"))
links = json.loads(extract_from_log(log, "ip -json link"))
ps_output = extract_from_log(log, "ps aux")

i = 2
while i < len(sys.argv):
    a = sys.argv[i]
    i += 1
    if a == 'has_link':
        has_link(sys.argv[i])
        i += 1
    elif a == 'has_an_ipv4_addr':
        has_an_ipv4_addr(sys.argv[i])
        i += 1
    elif a == 'has_no_ipv4_addr':
        has_no_ipv4_addr(sys.argv[i])
        i += 1
    elif a == 'has_ipv4_addr':
        has_ipv4_addr(sys.argv[i], sys.argv[i+1])
        i += 2
    else:
        error("unknown check {}".format(a))

if in_error:
    sys.exit(1)
