-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path_sync_records.py
115 lines (100 loc) · 3.81 KB
/
_sync_records.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# SPDX-FileCopyrightText: 2024 Max Mehl <https://mehl.mx>
#
# SPDX-License-Identifier: GPL-3.0-only
"""DNS record sync operations between local and remote"""
import logging
from INWX.Domrobot import ApiClient # type: ignore
from . import RECORD_KEYS
from ._api import inwx_api
from ._data import Domain, Record
def sync_existing_local_to_remote(
api: ApiClient, domain: Domain, dry: bool, interactive: bool
) -> None:
"""Compare previously matched local records to remote ones. If differences, update remote"""
# Loop over local records which have an ID, so matched to a remote entry
for loc_rec in [loc_rec for loc_rec in domain.local_records if loc_rec.id]:
# For each ID, compare content, ttl, prio etc, collect changes, and make API call
changes = {}
for key in RECORD_KEYS[3:]:
# Get local and corresponding remote attribute
loc_val = getattr(loc_rec, key)
rem_val = next(
getattr(rem_rec, key)
for rem_rec in domain.remote_records
if rem_rec.id == loc_rec.id
)
# Update attribute at remote if values differ
if loc_val != rem_val:
# Log and update record
logging.info(
"[%s] Update '%s' record of '%s': '%s' from '%s' to '%s'",
domain.name,
loc_rec.type,
loc_rec.name,
key,
rem_val,
loc_val,
)
# Update record via API call
changes[key] = loc_val
else:
# No action needed as records are equal or undefined
logging.debug(
"[%s] (%s) %s equal: %s = %s", loc_rec.name, loc_rec.id, key, rem_val, loc_val
)
# Execute collected changes for this ID, if they exist
if changes:
inwx_api(
api,
"nameserver.updateRecord",
interactive=interactive,
dry=dry,
id=loc_rec.id,
**changes,
)
def create_missing_at_remote(
api: ApiClient, domain: Domain, records: list[Record], dry: bool, interactive: bool
):
"""Create records that only exist locally but not remotely"""
for rec in records:
# Only add record parameter to API call that are set locally
newrecord = {}
for key in RECORD_KEYS:
if value := getattr(rec, key):
newrecord[key] = value
logging.info("[%s] Creating new record: %s", domain.name, newrecord)
# Run the creation of the new nameserver record with API
inwx_api(
api,
"nameserver.createRecord",
interactive=interactive,
dry=dry,
domain=domain.name,
**newrecord,
)
def delete_unconfigured_at_remote(
# pylint: disable=too-many-arguments
api: ApiClient,
domain: Domain,
records: list[Record],
dry: bool,
interactive: bool,
ignore_types: list,
):
"""Delete records that only exist remotely but not locally, except some types"""
for rec in records:
if rec.type not in ignore_types:
logging.info(
"[%s] Deleting record at remote as it is not configured locally: %s",
domain.name,
rec,
)
# Run the deletion of the nameserver record with API
inwx_api(api, "nameserver.deleteRecord", interactive=interactive, dry=dry, id=rec.id)
else:
logging.debug(
"[%s] This remote record is not configured locally, but you "
"requested to not delete remote records of this type: %s",
domain.name,
rec,
)