Skip to content

Commit

Permalink
test version
Browse files Browse the repository at this point in the history
  • Loading branch information
Feinburger committed May 4, 2024
1 parent c9e895d commit 79c2d59
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 61 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ COPY helper.py /automatic-dns-failover

RUN pip install requests

CMD ["python3", "-u", "main.py"]
CMD ["python3", "-u", "main.py"]
12 changes: 6 additions & 6 deletions cloudflare_dns.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ def add_record(ip_addr, subdomain, zone_id):
payload = {
"content": f"{ip_addr}",
"name": subdomain,
"type": "A"
"type": "A",
"comment": "Managed by automatic-dns-failover project"
}

headers = {
Expand All @@ -61,11 +62,10 @@ def add_record(ip_addr, subdomain, zone_id):

response = requests.request("POST", url, json=payload, headers=headers).json()
return response["success"]


def find_zones_under_account():
# returns a dictionary of domain name: zone_id

url = "https://api.cloudflare.com/client/v4/zones"

headers = {
Expand All @@ -75,14 +75,14 @@ def find_zones_under_account():

response = requests.request("GET", url, headers=headers).json()
if response["success"]:
domain_dict = {}
domain_zone_id = {}
count = response["result_info"]["count"]
per_page = response["result_info"]["per_page"]
total_pages = int(count/per_page) + (count%per_page>0)
for i in range(1, total_pages+1):
response = requests.request("GET", url+f"?page={i}", headers=headers).json()
result = response["result"]
for j in range(len(result)):
domain_dict[result[j]["name"]] = result[j]["id"]
domain_zone_id[result[j]["name"]] = result[j]["id"]

return domain_dict
return domain_zone_id
42 changes: 21 additions & 21 deletions helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,46 +36,46 @@ def within_range(status_code_range, status_code):
return False

def string_match(string1, string2):
return string1==string2
return string1==string2 or string1 == "random_string"

def monitor(subdomain, FQDN, ip_addr_list, uptime, downtime, recorded, zone_id):
for i in range(len(ip_addr_list)):
def monitor(subdomain, FQDN, record_list, uptime, downtime, recorded, zone_id):
for i in range(len(record_list)):
try:
dns_cache[FQDN] = ip_addr_list[i]["ip_address"]
# TODO: add path in the URL
response = requests.get(f"http://{FQDN}:{ip_addr_list[i]['port']}", timeout=get_timeout)
# TODO: make default range an environment variable
status_code_range = ip_addr_list[i]["status_code_range"] if ip_addr_list[i].get("status_code_range") else [[200, 299]]
if not within_range(status_code_range, int(response.status_code)) or not string_match(ip_addr_list[i]["match_string"], response.text):
dns_cache[FQDN] = record_list[i]["ip_address"]
response = requests.get(f"http://{FQDN}:{record_list[i].get('port', 80)}{record_list[i].get('path', '/')}", timeout=get_timeout)
status_code_range = record_list[i].get("status_code_range", [[200,299]])
if not within_range(status_code_range, int(response.status_code)) or not string_match(record_list[i].get("match_string", "random_string"), response.text):
raise requests.RequestException()
print(f"{FQDN}: {ip_addr_list[i]['ip_address']} with port {ip_addr_list[i]['port']} and path {ip_addr_list[i]['path']} UP")

# node is up
print(f"{record_list[i]['ip_address']}:{record_list[i].get('port', 80)}{record_list[i].get('path', '/')} UP")
uptime[i] += 1
downtime[i] = 0
if not recorded[i] and uptime[i] >= up_threshold:
# add record to cloudflare dns zone
success = add_record(ip_addr_list[i]["ip_address"], subdomain, zone_id)
success = add_record(record_list[i]['ip_address'], subdomain, zone_id)
if success:
print(f"{FQDN}: {ip_addr_list[i]['ip_address']} ADD SUCCESSFUL")
print(f"{record_list[i]['ip_address']}:{record_list[i].get('port', 80)}{record_list[i].get('path', '/')} ADD SUCCESSFUL")
recorded[i] = True
else:
print(f"{FQDN}: {ip_addr_list[i]['ip_address']} ADD FAILED")
print(f"{record_list[i]['ip_address']}:{record_list[i].get('port', 80)}{record_list[i].get('path', '/')} ADD FAILED")
uptime[i] == 0
except:
# failed connection (node is potentially down)
print(f"{FQDN}: {ip_addr_list[i]['ip_address']} NO ANSWER")
# node is not right
print(f"{record_list[i]['ip_address']}:{record_list[i].get('port', 80)}{record_list[i].get('path', '/')} NO ANSWER")
uptime[i] = 0
downtime[i] += 1
if downtime[i] == down_threshold and recorded[i]:
# find dns id of the host
record_id, found = find_record(ip_addr_list[i]["ip_address"], FQDN, zone_id)
# node is down
record_id, found = find_record(record_list[i]['ip_address'], FQDN, zone_id)
if found:
# delete record from cloudflare dns zone
success = delete_record(record_id, zone_id)
if success:
recorded[i] = False
print(f"{FQDN}: {ip_addr_list[i]['ip_address']} DELETE SUCCESSFUL")
print(f"{record_list[i]['ip_address']}:{record_list[i].get('port', 80)}{record_list[i].get('path', '/')} DELETE SUCCESSFUL")
else:
print(f"{FQDN}: ATTENTION! couldn't delete {ip_addr_list[i]['ip_address']} with its record id")
print(f"{record_list[i]['ip_address']}:{record_list[i].get('port', 80)}{record_list[i].get('path', '/')} DELETE FAILED")
else:
print(f"{FQDN}: record id of {ip_addr_list[i]['ip_address']} cannot be found on cloudflare")
downtime[i] = 0
print(f"{record_list[i]['ip_address']}:{record_list[i].get('port', 80)}{record_list[i].get('path', '/')} not found on cloudflare")
downtime[i] = 0
39 changes: 21 additions & 18 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,29 @@
cloudflare_refresh_period_ticks = int(os.environ["CLOUDFLARE_REFRESH_PERIOD_TICKS"])

# dictionary of domain to zone_id
domain_dict = find_zones_under_account()
domain_zone_id = find_zones_under_account()

# check domain_subdomain_ips
# print(json.dumps(domain_subdomain_ips, indent=2))
print(domain_dict)
print(domain_subdomain_ips)
print(domain_zone_id)

# this delay is needed because of the overlapping existence of a terminating container/pod and a new container/pod
time.sleep(30)

# initialization of variables
uptime = {}
downtime = {}
recorded = {}
for domain in domain_subdomain_ips["domains"]:
for j, domain in enumerate(domain_subdomain_ips["domains"]):
domain_name = domain["domain_name"]
subdomains = domain_subdomain_ips["domains"][domain_name]["subdomains"]
subdomains = domain_subdomain_ips["domains"][j]["subdomains"]
for subdomain in subdomains:
subdomain_name = subdomain["subdomain_name"]
FQDN = subdomain_name + '.' + domain_name
ip_addr_list = subdomain["ip_addresses"]
uptime[FQDN] = [0] * len(ip_addr_list)
downtime[FQDN] = [0] * len(ip_addr_list)
recorded[FQDN] = [find_record(ip_addr_list[i], FQDN, domain_dict[domain_name])[1] for i in range(len(ip_addr_list))]
record_list = subdomain["records"]
uptime[FQDN] = [0] * len(record_list)
downtime[FQDN] = [0] * len(record_list)
recorded[FQDN] = [find_record(record_list[i]["ip_address"], FQDN, domain_zone_id[domain_name])[1] for i in range(len(record_list))]
print(f"{FQDN} status: {recorded[FQDN]}")

# infinite loop
count = 0
Expand All @@ -41,22 +44,22 @@
# will add the record back up if someone manually deletes it on cloudflare by accident
count += 1
if count == cloudflare_refresh_period_ticks:
for domain in domain_subdomain_ips["domains"]:
for j, domain in enumerate(domain_subdomain_ips["domains"]):
domain_name = domain["domain_name"]
subdomains = domain_subdomain_ips["domains"][domain_name]["subdomains"]
subdomains = domain_subdomain_ips["domains"][j]["subdomains"]
for subdomain in subdomains:
subdomain_name = subdomain["subdomain_name"]
FQDN = subdomain_name + '.' + domain_name
ip_addr_list = subdomain["ip_addresses"]
recorded[FQDN] = [find_record(ip_addr_list[i], FQDN, domain_dict[domain_name])[1] for i in range(len(ip_addr_list))]
record_list = subdomain["records"]
recorded[FQDN] = [find_record(record_list[i]["ip_address"], FQDN, domain_zone_id[domain_name])[1] for i in range(len(record_list))]
count = 0

# actual work
for domain in domain_subdomain_ips["domains"]:
for j, domain in enumerate(domain_subdomain_ips["domains"]):
domain_name = domain["domain_name"]
subdomains = domain_subdomain_ips["domains"][domain_name]["subdomains"]
subdomains = domain_subdomain_ips["domains"][j]["subdomains"]
for subdomain in subdomains:
subdomain_name = subdomain["subdomain_name"]
FQDN = subdomain_name + '.' + domain_name
ip_addr_list = subdomain["ip_addresses"]
monitor(subdomain_name, FQDN, ip_addr_list, uptime[FQDN], downtime[FQDN], recorded[FQDN], domain_dict[domain_name])
record_list = subdomain["records"]
monitor(subdomain_name, FQDN, record_list, uptime[FQDN], downtime[FQDN], recorded[FQDN], domain_zone_id[domain_name])
9 changes: 0 additions & 9 deletions parsing.py

This file was deleted.

6 changes: 0 additions & 6 deletions test.py

This file was deleted.

0 comments on commit 79c2d59

Please sign in to comment.