#!/usr/bin/env python
# -*- encoding: utf-8 -*-

import sys
import os
import yaml
import tempfile
import shutil
import subprocess
import argparse
import difflib

from kazoo.client import KazooClient
from kazoo.exceptions import NoNodeError
import direct_juggler.juggler as dj

ZK_HOSTS = "ppcback01f.yandex.ru,ppcback01e.yandex.ru,ppcback01i.yandex.ru"
ZK_TIMEOUT = 10
ZK_RETRY = {"max_tries": 1, "delay": 1, "max_jitter": 1, "backoff": 1, "ignore_expire": False}
zkh = KazooClient(hosts=ZK_HOSTS, timeout=ZK_TIMEOUT, connection_retry=ZK_RETRY, command_retry=ZK_RETRY)

ZK_SYNC_LOCATION = "svn+ssh://robot-direct-arc-p@arcadia.yandex.ru/arc/trunk/arcadia/direct/infra/direct-utils/zk-sync"
SERVICE_NAME = "zk-sync-consistency"
METACONF_NAME = "meta_conf.yaml"


def run(tmp_dir, options):
    subprocess.check_output(
        ['svn', 'co', ZK_SYNC_LOCATION, tmp_dir],
        env={'SVN_SSH': 'ssh -i /etc/direct-tokens/ssh-rsa_robot-direct-arc-p'},
        stderr=subprocess.STDOUT
    )

    zkh.start()

    with open(os.path.join(tmp_dir, METACONF_NAME), 'r') as fh:
        metaconf = yaml.load(fh)

    bad_confs = []
    for conf in metaconf:
        with open(os.path.join(tmp_dir, conf), 'r') as fh:
            conf_svn = fh.read()

        conf_zk = zkh.get(metaconf[conf]['zk_node'])[0]
        if conf_svn != conf_zk:
            diff = ''.join(difflib.unified_diff(
                conf_svn.splitlines(True), conf_zk.splitlines(True), 'svn:zk-sync/' + conf, 'zk:' + metaconf[conf]['zk_node']
            ))
            bad_confs.append(('zk-sync/' + conf, metaconf[conf]['zk_node'], diff))

    
    if not bad_confs:
        if options.juggler:
            dj.queue_events([{'service': SERVICE_NAME, 'status': 'OK', 'description': ''}])
        else:
            print u"Между конфигами zk-sync в svn и zk различий не найдено"
    else:
        if options.juggler:
            dj.queue_events([{
                'service': SERVICE_NAME,
                'status': 'CRIT',
                'description': 'run zk-sync-consistency for more info'
            }])
        else:
            print u"Найдены различия в конфигах zk-sync в svn и zk:"
            print u"\n\n".join(
                u"svn-конфиг %s отличается от zk-конфига %s\ndiff:\n%s" % (svn_path, zk_path, diff.decode('utf-8'))
                for svn_path, zk_path, diff in bad_confs
            )
            print u"\nЕсли понятно, откуда взялись расхождения, можно устранить их через zk-sync (https://wiki.yandex-team.ru/jeri/zk-sync/)."
            print u"\n\nЕсли непонятно - лучше найти причину!"

    zkh.stop()
    return


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Проверяет, что в зукипере и в svn конфиги из zk-sync совпадают")
    parser.add_argument("-j", "--juggler", dest="juggler", help="отправить результат в juggler", action='store_true')
    options = parser.parse_args()

    try:
        tmp_dir = tempfile.mkdtemp(prefix='zk-sync-consistency')
        run(tmp_dir, options)
    except Exception as e:
        description = 'unexpected exception %s %s' % (type(e), e)
        if options.juggler:
            dj.queue_events([{
                'service': SERVICE_NAME, 'status': 'CRIT', 'description': description
            }])
        else:
            print "ERROR:", description
    finally:
        shutil.rmtree(tmp_dir)

