121 lines
4.5 KiB
Python
121 lines
4.5 KiB
Python
"""
|
|
Synchronize Kontor data between configured servers.
|
|
"""
|
|
|
|
import json
|
|
from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser
|
|
from logging import Logger
|
|
from typing import Dict, List
|
|
|
|
from api import (
|
|
MAPPING,
|
|
EndPointNotAvailableException,
|
|
Server,
|
|
get_api_config,
|
|
get_logger,
|
|
)
|
|
|
|
parser = ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter)
|
|
parser.add_argument("--verbose", "-v", action="count", default=0)
|
|
parser.add_argument("--config", "-c", default="kontor-api")
|
|
parser.add_argument("--dry-run", "-m", action="store_true")
|
|
parser.add_argument("--to-file", "-f", action="store_true")
|
|
parser.add_argument("--server", "-s")
|
|
parser.add_argument("--cleanup", "-d", action="store_true")
|
|
args = parser.parse_args()
|
|
|
|
|
|
def create_item_id_mapping(data_list: List[dict]) -> Dict[str, dict]:
|
|
"""
|
|
create dictionary with id as key and dictionary as value.
|
|
"""
|
|
item_id_mapping: Dict[str, dict] = {}
|
|
for data_item in data_list:
|
|
item_id_mapping[data_item["id"]] = data_item
|
|
return item_id_mapping
|
|
|
|
|
|
def is_different(log: Logger, first_item, second_item: dict) -> bool:
|
|
"""
|
|
Check dicts for differences and returns true if values are not equals, except for last_modified_date.
|
|
"""
|
|
check_result = False
|
|
for key, value in first_item.items():
|
|
if key in second_item.keys():
|
|
if value != second_item[key]:
|
|
log.info("%s: %s != %s", key, value, second_item[key])
|
|
if key == "last_modified_date":
|
|
continue
|
|
if not check_result:
|
|
check_result = True
|
|
return check_result
|
|
|
|
|
|
if __name__ == "__main__":
|
|
logger = get_logger(args.verbose, "kontor")
|
|
logger.info("kontor.sync started")
|
|
APICONFIG = get_api_config(logger, args.config)
|
|
server_list: List[Server] = []
|
|
if args.server:
|
|
server = APICONFIG.get_server(args.server)
|
|
if server:
|
|
server_list.append(server)
|
|
else:
|
|
server_list.extend(APICONFIG.server)
|
|
export_data = {}
|
|
for server in server_list:
|
|
export_data[server.name] = {}
|
|
for table, path in MAPPING.items():
|
|
try:
|
|
data = server.request(logger, table=table)
|
|
logger.info("%s: %s", table, len(data))
|
|
export_data[server.name][table] = data
|
|
logger.info("%s: %s exported", table, len(data))
|
|
except EndPointNotAvailableException:
|
|
logger.info("Endpoint not implemented")
|
|
if args.to_file:
|
|
try:
|
|
json_dump = json.dumps(export_data[server.name], indent=4)
|
|
file_name = f"{server.name}-data.json"
|
|
with open(file_name, "w", encoding="utf-8") as dump_file:
|
|
dump_file.write(json_dump)
|
|
except TypeError as error:
|
|
logger.info(error)
|
|
for server in server_list:
|
|
logger.info(
|
|
"%s: %s tables exported", server.name, len(export_data[server.name])
|
|
)
|
|
if len(server_list) > 1:
|
|
for table, path in MAPPING.items():
|
|
mapping = create_item_id_mapping(export_data[server_list[1].name][table])
|
|
for item in export_data[server_list[0].name][table]:
|
|
logger.debug("checking %s:%s", table, item["id"])
|
|
check_item_id = item["id"]
|
|
if check_item_id in mapping:
|
|
check_item = mapping[check_item_id]
|
|
if is_different(logger, item, check_item):
|
|
logger.info(
|
|
"checking values for %s != %s", item["id"], check_item["id"]
|
|
)
|
|
logger.debug("diff: %s\n%s", item, check_item)
|
|
result = server_list[1].update(
|
|
logger, table, check_item_id, item
|
|
)
|
|
logger.info("update result: %s", result)
|
|
else:
|
|
logger.debug(
|
|
"no changes for: %s(%s - %s)",
|
|
table,
|
|
item["id"],
|
|
check_item["id"],
|
|
)
|
|
else:
|
|
logger.info(
|
|
"item %s in %s missing", check_item_id, server_list[1].name
|
|
)
|
|
logger.info("synchronization of %s finished", table)
|
|
logger.info("all tables synchronized")
|
|
else:
|
|
logger.info("not enough server configured for sync")
|
|
logger.info("kontor.sync finished")
|