feat: add cloudflare module for dynamic dns updates
This commit is contained in:
parent
ce67360c3c
commit
837bafba09
3 changed files with 95 additions and 0 deletions
73
infra_cli/cloudflare.py
Normal file
73
infra_cli/cloudflare.py
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
import requests
|
||||
import sys
|
||||
|
||||
class CloudflareManager:
|
||||
def __init__(self, config):
|
||||
self.token = config.get('cloudflare.token')
|
||||
self.ddns_domains = config.get('cloudflare.ddns_domains', [])
|
||||
self.api_url = "https://api.cloudflare.com/client/v4"
|
||||
self.headers = {
|
||||
"Authorization": f"Bearer {self.token}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
def get_external_ip(self):
|
||||
try:
|
||||
return requests.get("https://checkip.amazonaws.com").text.strip()
|
||||
except Exception as e:
|
||||
print(f"Error fetching external IP: {e}")
|
||||
return None
|
||||
|
||||
def get_zone_id(self, domain):
|
||||
res = requests.get(f"{self.api_url}/zones?name={domain}", headers=self.headers)
|
||||
data = res.json()
|
||||
if data.get('success') and data['result']:
|
||||
return data['result'][0]['id']
|
||||
return None
|
||||
|
||||
def update_ddns(self, force=False):
|
||||
current_ip = self.get_external_ip()
|
||||
if not current_ip:
|
||||
return "Failed to determine current external IP."
|
||||
|
||||
results = []
|
||||
for domain in self.ddns_domains:
|
||||
zone_id = self.get_zone_id(domain)
|
||||
if not zone_id:
|
||||
results.append(f"[{domain}] Zone not found.")
|
||||
continue
|
||||
|
||||
# Find A record for the root domain
|
||||
res = requests.get(f"{self.api_url}/zones/{zone_id}/dns_records?type=A&name={domain}", headers=self.headers)
|
||||
records = res.json().get('result', [])
|
||||
|
||||
if not records:
|
||||
# Create if missing? For now, just report
|
||||
results.append(f"[{domain}] No A record found to update.")
|
||||
continue
|
||||
|
||||
record = records[0]
|
||||
if record['content'] == current_ip and not force:
|
||||
results.append(f"[{domain}] Already up to date ({current_ip}).")
|
||||
continue
|
||||
|
||||
# Update record
|
||||
update_data = {
|
||||
"type": "A",
|
||||
"name": domain,
|
||||
"content": current_ip,
|
||||
"ttl": 1, # Auto
|
||||
"proxied": record.get('proxied', True)
|
||||
}
|
||||
u_res = requests.put(f"{self.api_url}/zones/{zone_id}/dns_records/{record['id']}",
|
||||
headers=self.headers, json=update_data)
|
||||
|
||||
if u_res.json().get('success'):
|
||||
results.append(f"[{domain}] Updated to {current_ip}.")
|
||||
else:
|
||||
results.append(f"[{domain}] Update failed: {u_res.text}")
|
||||
|
||||
return "\n".join(results)
|
||||
|
||||
def list_domains(self):
|
||||
return self.ddns_domains
|
||||
|
|
@ -5,6 +5,7 @@ from .ingress import IngressManager
|
|||
from .router import RouterManager
|
||||
from .proxmox import ProxmoxManager
|
||||
from .samba import SambaManager
|
||||
from .cloudflare import CloudflareManager
|
||||
import sys
|
||||
|
||||
@click.group()
|
||||
|
|
@ -18,6 +19,26 @@ def cli(ctx, config):
|
|||
click.echo(f"Error: {e}", err=True)
|
||||
sys.exit(1)
|
||||
|
||||
@cli.group()
|
||||
def cloudflare():
|
||||
"""Manage Cloudflare DNS and DDNS"""
|
||||
pass
|
||||
|
||||
@cloudflare.command(name='list-ddns')
|
||||
@click.pass_obj
|
||||
def cf_list_ddns(config):
|
||||
mgr = CloudflareManager(config)
|
||||
for domain in mgr.list_domains():
|
||||
click.echo(domain)
|
||||
|
||||
@cloudflare.command(name='update-ddns')
|
||||
@click.option('--force', is_flag=True, help='Force update even if IP matches')
|
||||
@click.pass_obj
|
||||
def cf_update_ddns(config, force):
|
||||
mgr = CloudflareManager(config)
|
||||
click.echo("Updating Cloudflare DDNS records...")
|
||||
click.echo(mgr.update_ddns(force))
|
||||
|
||||
@cli.group()
|
||||
def proxmox():
|
||||
"""Manage Proxmox VMs and Containers"""
|
||||
|
|
|
|||
1
setup.py
1
setup.py
|
|
@ -7,6 +7,7 @@ setup(
|
|||
install_requires=[
|
||||
"click",
|
||||
"pyyaml",
|
||||
"requests",
|
||||
],
|
||||
entry_points={
|
||||
"console_scripts": [
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue