103 lines
2.8 KiB
Python
103 lines
2.8 KiB
Python
import json
|
|
import logging
|
|
import subprocess
|
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
|
|
import requests
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def _get_ip(resolvers):
|
|
try:
|
|
output = subprocess.check_output(
|
|
["dig", "+short", *resolvers],
|
|
stderr=subprocess.STDOUT,
|
|
)
|
|
except subprocess.CalledProcessError as e:
|
|
raise OSError("Unable to retrieve current IP") from e
|
|
|
|
return output.decode("utf-8").strip()
|
|
|
|
|
|
def _get_domain(domain, token, api_url):
|
|
headers = {"Authorization": f"Bearer {token}"}
|
|
|
|
return requests.get(f"{api_url}/domains/{domain}/dns", headers=headers)
|
|
|
|
|
|
def _get_domain_data(domains, token, api_url):
|
|
with ThreadPoolExecutor(max_workers=10) as executor:
|
|
futures = {
|
|
executor.submit(_get_domain, domain, token, api_url): domain
|
|
for domain in domains
|
|
}
|
|
|
|
for future in as_completed(futures):
|
|
response = future.result()
|
|
domain = futures[future]
|
|
|
|
try:
|
|
response.raise_for_status()
|
|
except requests.HTTPError as e:
|
|
logger.exception(f"Failed retrieving information for {domain}")
|
|
continue
|
|
|
|
yield {"domain": domain, **response.json()}
|
|
|
|
|
|
def _update_domain(domain, payload, api_url, token):
|
|
headers = {"Authorization": f"Bearer {token}"}
|
|
|
|
return requests.put(
|
|
f"{api_url}/domains/{domain}/dns", data=json.dumps(payload), headers=headers
|
|
)
|
|
|
|
|
|
def _update_domains(updated_domains, api_url, token, read_only):
|
|
if read_only:
|
|
return
|
|
|
|
with ThreadPoolExecutor(max_workers=10) as executor:
|
|
futures = {
|
|
executor.submit(_update_domain, domain, entries, api_url, token): domain
|
|
for domain, entries in updated_domains.items()
|
|
}
|
|
|
|
for future in as_completed(futures):
|
|
response = future.result()
|
|
domain = futures[future]
|
|
|
|
try:
|
|
response.raise_for_status()
|
|
except request.HTTPError as e:
|
|
logger.exception(f"Unable to update domain {domain}")
|
|
continue
|
|
|
|
logger.info(f"Updated domain {domain}")
|
|
|
|
|
|
def detect(domains, resolvers, api_url, token, read_only):
|
|
ip = _get_ip(resolvers)
|
|
domain_data = _get_domain_data(domains, token, api_url)
|
|
updated_domains = {}
|
|
|
|
for data in domain_data:
|
|
dns_entries = data["dnsEntries"]
|
|
domain = data["domain"]
|
|
updated_entries = []
|
|
|
|
for dns_entry in dns_entries:
|
|
updated_entries.append(
|
|
{
|
|
**dns_entry,
|
|
"content": ip,
|
|
}
|
|
)
|
|
|
|
if dns_entries == updated_entries:
|
|
continue
|
|
|
|
updated_domains[domain] = {"dnsEntries": updated_entries}
|
|
|
|
_update_domains(updated_domains, api_url, token, read_only)
|