From 24f1a56ce8291292860b8d252c272efa93fc79e4 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Wed, 20 Jan 2021 18:14:17 +0100 Subject: [PATCH] Add command line document --- cloudflare_ddns/__main__.py | 51 +++++++++++++++++++++++++++++------- cloudflare_ddns/app.py | 4 +-- cloudflare_ddns/constants.py | 4 +++ 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/cloudflare_ddns/__main__.py b/cloudflare_ddns/__main__.py index eda937b..e3e4908 100644 --- a/cloudflare_ddns/__main__.py +++ b/cloudflare_ddns/__main__.py @@ -1,28 +1,61 @@ import logging +from os import environ from typing import Tuple import click from cloudflare_ddns.app import ApplicationJob -from cloudflare_ddns.constants import DEFAULT_DELAY +from cloudflare_ddns.constants import BASE_ENV_VAR, DEFAULT_DELAY, DOMAINS_ENV_VAR log = logging.getLogger("ddns") @click.command() -@click.option('--delay', '-d', default=DEFAULT_DELAY, show_default=True) -@click.option('--token', '-k', prompt="Enter your Cloudflare Token", hide_input=True, show_envvar=True) -@click.option('-v', '--verbose', is_flag=True, default=False) -@click.argument("domain", nargs=-1) -def start(delay: str, token: str, verbose: int, domain: Tuple[str]) -> None: - """Main application entrypoint.""" +@click.option( + '--delay', '-d', + default=DEFAULT_DELAY, + show_default=True, + show_envvar=True, + help="Time to wait between each update." +) +@click.option( + '--token', '-k', + prompt="Enter your Cloudflare Token", + hide_input=True, + show_envvar=True, + help="Your Cloudflare Bearer token." +) +@click.option('-v', '--verbose', is_flag=True, default=False, help="Show debug logging.") +@click.argument("domains", nargs=-1) +def start(delay: str, token: str, verbose: int, domains: Tuple[str]) -> None: + """ + Update Cloudflare DNS RECORDS to your current IP every (default: 5 minutes). + + The domains can be passed either as command line options, or as a space separated CF_DDNS_DOMAINS environment + variable. + Each domain can be preceded by the record type, either A or AAAA followed by a colon. + + \b + The duration supports the following symbols for each unit of time: + - days: `d`, `D`, `day`, `days` + - hours: `H`, `h`, `hour`, `hours` + - minutes: `M`, `m`, `minute`, `minutes`, `min` + - seconds: `S`, `s`, `second`, `seconds`, `sec` + The units need to be provided in descending order of magnitude. + """ + # Configure logging. logging.basicConfig( format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.DEBUG if verbose else logging.INFO ) - ApplicationJob(delay, token, domain).launch() + # Get domains from the environment variable. + if domain_var := environ.get(DOMAINS_ENV_VAR, None): + domains = list(domains) + domains.extend(domain_var.split(" ")) + + ApplicationJob(delay, token, domains).launch() # Main entrypoint if __name__ == "__main__": - start(auto_envvar_prefix="CF_DDNS") + start(auto_envvar_prefix=BASE_ENV_VAR) diff --git a/cloudflare_ddns/app.py b/cloudflare_ddns/app.py index d353006..2187df2 100644 --- a/cloudflare_ddns/app.py +++ b/cloudflare_ddns/app.py @@ -1,7 +1,7 @@ import logging import threading from dataclasses import dataclass -from typing import List, Tuple +from typing import List import requests from cloudflare_ddns.constants import ACCEPTED_RECORDS, LIST_DNS, LIST_ZONES, PATCH_DNS, VERIFY_TOKEN @@ -32,7 +32,7 @@ class Domain: class ApplicationJob(threading.Thread): """Main application class.""" - def __init__(self, raw_delay: str, token: str, raw_domains: Tuple[str]): + def __init__(self, raw_delay: str, token: str, raw_domains: List[str]): super().__init__() self.stop_signal = threading.Event() diff --git a/cloudflare_ddns/constants.py b/cloudflare_ddns/constants.py index 99ca433..87a5bfb 100644 --- a/cloudflare_ddns/constants.py +++ b/cloudflare_ddns/constants.py @@ -1,6 +1,10 @@ # App defaults DEFAULT_DELAY = "5 minutes" +# App constants +BASE_ENV_VAR = "CF_DDNS" +DOMAINS_ENV_VAR = BASE_ENV_VAR + "_DOMAINS" + # Endpoints BASE_ENDPOINT = "https://api.cloudflare.com/client/v4/"