diff --git a/main.py b/main.py index 5bd2f0c..e3e78ee 100644 --- a/main.py +++ b/main.py @@ -6,6 +6,14 @@ import sched from pathlib import Path +def make_headers(key: str): + headers = { + "Authorization": f"Bearer {key}", + "Content-Type": "application/json" + } + return headers + + class Env: def __init__(self, username, api_key): self.username = username @@ -13,17 +21,71 @@ class Env: class Zone: - def __init__(self, zone_name, env, records): - self.zone_name = zone_name + def __init__(self, env, records): self.env = env self.records = records self.zone_id = None + self.zone_name = None + + def fetch_zone_id(self): + if self.zone_name is None: + print("Zone name is none! Must set at least zone name or zone id!") + exit(1) + + r = requests.get(f"https://api.cloudflare.com/client/v4/zones", headers=make_headers(self.env.api_key)) + if r.status_code == 200: + data = json.loads(r.text) + results = data["result"] + for result in results: + if result["name"] == self.zone_name: + self.zone_id = result["id"] + return + print("Failed to find zone id, does this zone exist?") + return + print(f"Error has occurred, status code: {r.status_code}") + print(r.text) + + def update_record(self, address, record): + print(f"record {record['name']} has address {record['content']} but requires updating!") + r = requests.patch(f"https://api.cloudflare.com/client/v4/zones/{self.zone_id}/dns_records/{record['id']}", + headers=make_headers(self.env.api_key), data=json.dumps({ + "content": address, + "name": record['name'], + "type": record['type'], + "comment": record['comment'], + "ttl": record['ttl'], + "tags": record['tags'], + "proxied": record['proxied'] + })) + if r.status_code: + print(f"record {record['name']} has been updated to {address}") + else: + print(f"Failed to update record {record['name']}") + print(r.text) + + def update_records(self, address): + r = requests.get(f"https://api.cloudflare.com/client/v4/zones/{self.zone_id}/dns_records?type=A", + headers=make_headers(self.env.api_key)) + if r.status_code != 200: + return None + record_data = json.loads(r.text)["result"] + for record in record_data: + if record["name"] not in self.records: + continue + if record["content"] == address: + continue + self.update_record(address, record) class Zones: - def __init__(self, ip_provider, r_zones): + def __init__(self, ip_provider, zones): self.ip_provider = ip_provider - self.zones = r_zones + self.zones = zones + + def fetch_ip(self): + r = requests.get(self.ip_provider) + print(f"Fetching IP Address with '{self.ip_provider}' returned '{r.text}'") + return r.text def parse_arguments(): @@ -52,9 +114,14 @@ def get_conf(conf_path, envs): zones = [] for zone in json_env["zones"]: sites = [] - for site in zone["sites"]: + for site in zone["records"]: sites.append(site) - zones.append(Zone(zone["zone"], envs[zone["username"]], sites)) + zn = Zone(envs[zone["username"]], sites) + if "zone" in zone: + zn.zone_name = zone["zone"] + if "id" in zone: + zn.zone_id = zone["id"] + zones.append(zn) return Zones(json_env["ip_provider"], zones) @@ -96,51 +163,29 @@ def run_install(): print(f"Warning {sites_path} already exists, skipping!") -def fetch_ip(provider): - print(f"Fetching IP Address with '{provider}'") - r = requests.get(provider) - return r.text +def run(scheduler, args, zones): + scheduler.enter(args.time, 1, run, (scheduler, args, zones)) + address = zones.fetch_ip() - -def fetch_zone_id(zone_name, key): - headers = { - "Authorization": f"Bearer {key}", - "Content-Type": "application/json" - } - r = requests.get(f"https://api.cloudflare.com/client/v4/zones", headers=headers) - if r.status_code == 200: - data = json.loads(r.text) - results = data["result"] - for result in results: - if result["name"] == zone_name: - return result["id"] - print("Failed to find zone id, does this zone exist?") - return None - print(f"Error has occurred, status code: {r.status_code}") - print(r.text) - return None - - -def run(scheduler, r_args, r_envs, r_zones): - scheduler.enter(r_args.time, 1, run, (scheduler, r_args, r_envs, r_zones)) - address = fetch_ip(r_zones.ip_provider) - - for zone in r_zones.zones: - user = zone.env + for zone in zones.zones: if zone.zone_id is None: - zone.zone_id = fetch_zone_id(zone.zone_name, user.api_key) + zone.fetch_zone_id() + print(f"Fetched zone {zone.zone_name} with id {zone.zone_id}") + zone.update_records(address) -if __name__ == '__main__': +def main(): args = parse_arguments() if args.install: run_install() else: - m_user_envs = get_env(args.env) - m_zones = get_conf(args.config, m_user_envs) - for v_zone in m_zones.zones: - print(fetch_zone_id(v_zone.zone_name, v_zone.env.api_key)) - #runner = sched.scheduler(time.time, time.sleep) - #runner.enter(args.time, 1, run, (runner, args, user_envs, zones)) - #runner.run() + user_envs = get_env(args.env) + zones = get_conf(args.config, user_envs) + runner = sched.scheduler(time.time, time.sleep) + run(runner, args, zones) + runner.run() + + +if __name__ == '__main__': + main()