#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013-2018:
# This file is part of Shinken Enterprise, all rights reserved.
import pymongo
import optparse
import os
import sys
from bson import BSON

OVERLOAD_FILE = "/etc/shinken-user/configuration/daemons/synchronizers/synchronizer_cfg_overload.cfg"
SYNCHRONIZER_FILE = "/etc/shinken/synchronizer.cfg"
SYNCHRONIZER_INFO = 'synchronizer-info'

CLEAN_COMMAND = {
    "_id"         : "ee4d4311970d11e88f18f8bc126497d6",
    "command_line": "/bin/printf 'clean command'",
    "command_name": "clean_command",
    "_SYNC_KEYS"  : ["clean_command"]
}
# List of properties and their new value. If value is None, property will be delete
PROPERTIES_TO_CLEAN = [
    ('address', 'clean address'),
    ('check_command', 'clean_command'),
    ('password', 'clean'),
    ('poller_tag', None),
    ('reactionner_tag', None),
    ('realm', None),
    ('@metadata', None)
]


def read_cfg_file(cfg_file):
    try:
        with open(cfg_file, 'r') as f:
            buff = f.readlines()
    except Exception as e:
        print "Cannot read the file %s to know which fields to clean : %s" % (cfg_file, e.__str__())
        sys.exit(2)
    return buff


def get_protected_data_list():
    # First try to read from overload
    synchronizer_cfg = read_cfg_file(OVERLOAD_FILE)
    for line in synchronizer_cfg:
        if 'protect_fields__substrings_matching_fields' in line:
            return line.replace('\n', '').split('=')[1].split(',')
    
    # If there is no overload, read from the synchronizer itself
    synchronizer_cfg = read_cfg_file(SYNCHRONIZER_FILE)
    for line in synchronizer_cfg:
        if 'protect_fields__substrings_matching_fields' in line:
            return line.replace('\n', '').split('=')[1].split(',')
        
    return []


def clean_properties(item, protected_data):
    last_modification_change = item.get('last_modification', {}).get('change', None)
    if last_modification_change:
        for change in last_modification_change:
            if change['prop'] in [i[0] for i in PROPERTIES_TO_CLEAN]:
                change['new'] = 'clean'
                change['old'] = 'old clean'
            elif change['prop'].startswith('_'):
                for protected_field in protected_data:
                    if protected_field.upper() in change['prop'].upper():
                        change['new'] = 'clean'
                        change['old'] = 'old clean'
    
    work_area_info_diff_item = item.get('work_area_info', {}).get('diff_item', None)
    if work_area_info_diff_item:
        for diff_item in work_area_info_diff_item:
            if diff_item['prop'] in [i[0] for i in PROPERTIES_TO_CLEAN]:
                diff_item['new'] = 'clean'
                diff_item['stagging'] = 'old clean'
            elif diff_item['prop'].startswith('_'):
                for protected_field in protected_data:
                    if protected_field.upper() in diff_item['prop'].upper():
                        diff_item['new'] = 'clean'
                        diff_item['stagging'] = 'old clean'
    
    link_service_overrides = item.get('service_overrides', {}).get('links', None)
    if link_service_overrides:
        for link in link_service_overrides:
            if link['key'].startswith('_'):
                for protected_field in protected_data:
                    if protected_field.upper() in link['key'].upper():
                        link['value'] = 'clean'
    
    for (property, new_value) in PROPERTIES_TO_CLEAN:
        if item.get(property):
            if new_value:
                item[property] = new_value
            else:
                del item[property]
    
    if protected_data:
        for prop_name in item.iterkeys():
            if prop_name.startswith('_'):
                for protected_field in protected_data:
                    if protected_field.upper() in prop_name.upper():
                        item[prop_name] = 'clean'


def main():
    parser = optparse.OptionParser("%prog ", description="Used to anonymize configuration database")
    parser.add_option('-u', '--url', dest='url', default='localhost', help='URL of the mongo db [default : localhost]')
    parser.add_option('', '--db', dest='database', default='synchronizer', help='database')
    parser.add_option('', '--directory', dest='directory', default='dump-configuration', help='Directory backup')
    
    opts, args = parser.parse_args()
    
    protected_data = get_protected_data_list()
    if not protected_data:
        print "No protected fields were found in file %s. Continue without protected_fields" % OVERLOAD_FILE
    
    # STEP : check if directory exists
    if not os.path.exists(opts.directory):
        os.mkdir(opts.directory)
    final_directory = os.path.join(opts.directory, opts.database)
    if not os.path.exists(final_directory):
        os.mkdir(final_directory)
    
    mongodb_con = pymongo.MongoClient("mongodb://%s" % opts.url, fsync=False)
    mongodb_db = getattr(mongodb_con, opts.database)
    
    synchronizer_info = getattr(mongodb_db, SYNCHRONIZER_INFO)
    file_name = os.path.join(final_directory, '%s.bson' % SYNCHRONIZER_INFO)
    with open(file_name, 'wb+') as f:
        for doc in synchronizer_info.find():
            if doc['_id'] == 'protected_fields_info':
                doc['protect_fields__activate_database_encryption'] = False
            f.write(BSON.encode(doc))
    
    for collection_name in mongodb_db.collection_names(include_system_collections=False):
        if not collection_name.startswith('configuration'):
            continue
        
        file_name = os.path.join(final_directory, '%s.bson' % collection_name)
        with open(file_name, 'ab+') as f:
            
            if collection_name in ('configuration-production-command', 'configuration-stagging-command'):
                f.write(BSON.encode(CLEAN_COMMAND))
            
            collection = getattr(mongodb_db, collection_name)
            items = collection.find()
            for item in items:
                clean_properties(item, protected_data)
                f.write(BSON.encode(item))


if __name__ == '__main__':
    main()
