Files
kontor/kontor-scripts/sync.py
T

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")