transip-client/ip_listener/main.py
2020-12-27 13:43:07 +01:00

97 lines
2.7 KiB
Python

import logging
import subprocess
from concurrent.futures import ThreadPoolExecutor, as_completed
import requests
logger = logging.getLogger(__name__)
def _get_ip():
try:
# TODO make resolvers customizable
output = subprocess.check_output(
["dig", "+short", "myip.opendns.com", "@resolver1.opendns.com"],
stderr=subprocess.STDOUT,
)
except subprocess.CalledProcessError as e:
raise OSError("Unable to retrieve current IP") from e
# TODO set URL global
def _get_domain(domain, token):
headers = {"Authorization": f"Bearer {token}"}
return requests.get(url, headers=headers)
def _get_domain_data(domains, token):
with ThreadPoolExecutor(max_workers=10) as executor:
futures = {
executor.submit(_get_domain, domain, token): 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()}
# TODO set URL global
def _update_domain(domain, payload, token):
headers = {"Authorization": f"Bearer {token}"}
return requests.put(url, data=json.dumps(payload), headers=headers)
def _update_domains(updated_domains, token):
with ThreadPoolExecutor(max_workers=10) as executor:
futures = {
executor.submit(_update_domain, domain, entries, 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, token):
ip = _get_ip()
domain_data = _get_domain_data(domains, token)
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, token)