import json
import os
import re

from testinfra.utils.ansible_runner import AnsibleRunner

import util

testinfra_hosts = AnsibleRunner(os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('agent-integrations')


def _get_key_value(tag_list):
    for key, value in (pair.split(':', 1) for pair in tag_list):
        yield key, value


def _component_data(json_data, type_name, external_id_assert_fn, tags_assert_fn):
    for message in json_data["messages"]:
        p = message["message"]["TopologyElement"]["payload"]
        if "TopologyComponent" in p and \
                p["TopologyComponent"]["typeName"] == type_name and \
                external_id_assert_fn(p["TopologyComponent"]["externalId"]):
            data = json.loads(p["TopologyComponent"]["data"])
            if tags_assert_fn(dict(_get_key_value(data["tags"]))):
                return data
    return None


def test_nagios_mysql(host):
    def assert_topology():
        topo_url = "http://localhost:7070/api/topic/sts_topo_process_agents?limit=1500"
        data = host.check_output('curl "{}"'.format(topo_url))
        json_data = json.loads(data)
        with open("./topic-nagios-topo-process-agents.json", 'w') as f:
            json.dump(json_data, f, indent=4)

        external_id_pattern = re.compile(r"urn:container:/agent-integrations:.*")
        components = [
            {
                "assertion": "Should find the nagios container",
                "type": "container",
                "external_id": lambda e_id: external_id_pattern.findall(e_id),
                "tags": lambda t: t["container_name"] == "ubuntu_nagios_1"
            },
            {
                "assertion": "Should find the mysql container",
                "type": "container",
                "external_id": lambda e_id: external_id_pattern.findall(e_id),
                "tags": lambda t: t["container_name"] == "ubuntu_mysql_1"
            }
        ]

        for c in components:
            print("Running assertion for: " + c["assertion"])
            assert _component_data(
                json_data=json_data,
                type_name=c["type"],
                external_id_assert_fn=c["external_id"],
                tags_assert_fn=c["tags"],
            ) is not None

    util.wait_until(assert_topology, 30, 3)


def test_container_metrics(host):
    url = "http://localhost:7070/api/topic/sts_multi_metrics?limit=1000"

    def wait_for_metrics():
        data = host.check_output("curl \"%s\"" % url)
        json_data = json.loads(data)
        with open("./topic-nagios-sts-multi-metrics.json", 'w') as f:
            json.dump(json_data, f, indent=4)

        def get_keys(m_host):
            return set(
                ''.join(message["message"]["MultiMetric"]["values"].keys())
                for message in json_data["messages"]
                if message["message"]["MultiMetric"]["name"] == "convertedMetric" and
                message["message"]["MultiMetric"]["host"] == m_host
            )

        expected = {'nagios.http.size', 'nagios.ping.pl', 'nagios.http.time', 'nagios.current_load.load15',
                    'nagios.swap_usage.swap', 'nagios.host.pl', 'nagios.root_partition', 'nagios.current_users.users',
                    'nagios.current_load.load1', 'nagios.host.rta', 'nagios.ping.rta', 'nagios.current_load.load5',
                    'nagios.total_processes.procs'}
        assert all([expectedMetric for expectedMetric in expected if expectedMetric in get_keys("agent-integrations")])

    util.wait_until(wait_for_metrics, 180, 3)

[((62, 4, 62, 43), 'util.wait_until', 'util.wait_until', ({(62, 20, 62, 35): 'assert_topology', (62, 37, 62, 39): '(30)', (62, 41, 62, 42): '(3)'}, {}), '(assert_topology, 30, 3)', False, 'import util\n'), ((88, 4, 88, 45), 'util.wait_until', 'util.wait_until', ({(88, 20, 88, 36): 'wait_for_metrics', (88, 38, 88, 41): '(180)', (88, 43, 88, 44): '(3)'}, {}), '(wait_for_metrics, 180, 3)', False, 'import util\n'), ((9, 18, 9, 70), 'testinfra.utils.ansible_runner.AnsibleRunner', 'AnsibleRunner', ({(9, 32, 9, 69): "os.environ['MOLECULE_INVENTORY_FILE']"}, {}), "(os.environ['MOLECULE_INVENTORY_FILE'])", False, 'from testinfra.utils.ansible_runner import AnsibleRunner\n'), ((33, 20, 33, 36), 'json.loads', 'json.loads', ({(33, 31, 33, 35): 'data'}, {}), '(data)', False, 'import json\n'), ((37, 30, 37, 81), 're.compile', 're.compile', ({(37, 41, 37, 80): '"""urn:container:/agent-integrations:.*"""'}, {}), "('urn:container:/agent-integrations:.*')", False, 'import re\n'), ((70, 20, 70, 36), 'json.loads', 'json.loads', ({(70, 31, 70, 35): 'data'}, {}), '(data)', False, 'import json\n'), ((23, 19, 23, 61), 'json.loads', 'json.loads', ({(23, 30, 23, 60): "p['TopologyComponent']['data']"}, {}), "(p['TopologyComponent']['data'])", False, 'import json\n'), ((35, 12, 35, 45), 'json.dump', 'json.dump', (), '', False, 'import json\n'), ((72, 12, 72, 45), 'json.dump', 'json.dump', (), '', False, 'import json\n')]