diff options
| author | Indrajit Raychaudhuri <irc@indrajit.com> | 2026-04-13 03:11:35 -0500 |
|---|---|---|
| committer | Indrajit Raychaudhuri <irc@indrajit.com> | 2026-07-24 12:17:23 -0500 |
| commit | ced95444e5233c4fef5e274220dc665bbe836e69 (patch) | |
| tree | 61cad47d689c868e9fe69c43e6a807ee793d6a7a /src | |
| parent | 98f83eb047c994c30cc254ea7a415b1135765d8b (diff) | |
| download | vyos-1x-ced95444e5233c4fef5e274220dc665bbe836e69.tar.gz vyos-1x-ced95444e5233c4fef5e274220dc665bbe836e69.zip | |
ddclient: T6981: Reformat for ruff compliance
Diffstat (limited to 'src')
| -rwxr-xr-x | src/conf_mode/service_dns_dynamic.py | 178 |
1 files changed, 136 insertions, 42 deletions
diff --git a/src/conf_mode/service_dns_dynamic.py b/src/conf_mode/service_dns_dynamic.py index 92b067dcc..b6daba6ff 100755 --- a/src/conf_mode/service_dns_dynamic.py +++ b/src/conf_mode/service_dns_dynamic.py @@ -27,36 +27,89 @@ from vyos.utils.process import call from vyos.utils.network import interface_exists from vyos import ConfigError from vyos import airbag + airbag.enable() config_file = r'/run/ddclient/ddclient.conf' systemd_override = r'/run/systemd/system/ddclient.service.d/override.conf' # Protocols that require zone -zone_necessary = ['cloudflare', 'digitalocean', 'godaddy', 'hetzner', 'gandi', - 'nfsn', 'nsupdate'] +zone_necessary = [ + 'cloudflare', + 'digitalocean', + 'godaddy', + 'hetzner', + 'gandi', + 'nfsn', + 'nsupdate', +] zone_supported = zone_necessary + ['dnsexit2', 'porkbun', 'zoneedit1'] # Protocols that do not require username -username_unnecessary = ['1984', 'cloudflare', 'cloudns', 'ddns.fm', 'digitalocean', - 'dnsexit2', 'duckdns', 'freemyip', 'gandi', 'he.net', - 'hetzner', 'keysystems', 'njalla', 'nsupdate', 'regfishde'] +username_unnecessary = [ + '1984', + 'cloudflare', + 'cloudns', + 'ddns.fm', + 'digitalocean', + 'dnsexit2', + 'duckdns', + 'freemyip', + 'gandi', + 'he.net', + 'hetzner', + 'keysystems', + 'njalla', + 'nsupdate', + 'regfishde', +] # Protocols that support TTL -ttl_supported = ['cloudflare', 'dnsexit2', 'gandi', 'hetzner', 'godaddy', 'nfsn', - 'nsupdate', 'porkbun'] +ttl_supported = [ + 'cloudflare', + 'dnsexit2', + 'gandi', + 'hetzner', + 'godaddy', + 'nfsn', + 'nsupdate', + 'porkbun', +] # Protocols that support both IPv4 and IPv6 -dualstack_supported = ['cloudflare', 'ddns.fm', 'digitalocean', 'dnsexit2', - 'domeneshop', 'duckdns', 'dyndns2', 'easydns', 'freedns', - 'gandi', 'godaddy', 'he.net', 'hetzner', 'infomaniak', - 'inwx', 'mythicdyn', 'njalla', 'noip', 'nsupdate', - 'porkbun', 'regfishde'] +dualstack_supported = [ + 'cloudflare', + 'ddns.fm', + 'digitalocean', + 'dnsexit2', + 'domeneshop', + 'duckdns', + 'dyndns2', + 'easydns', + 'freedns', + 'gandi', + 'godaddy', + 'he.net', + 'hetzner', + 'infomaniak', + 'inwx', + 'mythicdyn', + 'njalla', + 'noip', + 'nsupdate', + 'porkbun', + 'regfishde', +] # dyndns2 protocol in ddclient honors dual stack for selective servers # because of the way it is implemented in ddclient -dyndns_dualstack_servers = ['members.dyndns.org', 'dynv6.com', 'app.luadns.com', - 'update.dedyn.io'] +dyndns_dualstack_servers = [ + 'app.luadns.com', + 'dynv6.com', + 'members.dyndns.org', + 'update.dedyn.io', +] + def get_config(config=None): if config: @@ -68,14 +121,18 @@ def get_config(config=None): if not conf.exists(base): return None - dyndns = conf.get_config_dict(base, key_mangling=('-', '_'), - no_tag_node_value_mangle=True, - get_first_key=True, - with_recursive_defaults=True) + dyndns = conf.get_config_dict( + base, + key_mangling=('-', '_'), + no_tag_node_value_mangle=True, + get_first_key=True, + with_recursive_defaults=True, + ) dyndns['config_file'] = config_file return dyndns + def verify(dyndns): # bail out early - looks like removal from running config if not dyndns or 'name' not in dyndns: @@ -91,11 +148,15 @@ def verify(dyndns): raise ConfigError(f'"{field.replace("_", "-")}" {error_msg_req}') if not any(x in config['address'] for x in ['interface', 'web']): - raise ConfigError(f'Either "interface" or "web" {error_msg_req} ' - f'with protocol "{config["protocol"]}"') + raise ConfigError( + f'Either "interface" or "web" {error_msg_req} ' + f'with protocol "{config["protocol"]}"' + ) if all(x in config['address'] for x in ['interface', 'web']): - raise ConfigError(f'Both "interface" and "web" at the same time {error_msg_uns} ' - f'with protocol "{config["protocol"]}"') + raise ConfigError( + f'Both "interface" and "web" at the same time {error_msg_uns} ' + f'with protocol "{config["protocol"]}"' + ) # If dyndns address is an interface, ensure that the interface exists # and warn if a non-active dynamic interface is used @@ -104,16 +165,22 @@ def verify(dyndns): # exclude check interface for dynamic interfaces if tmp.match(config['address']['interface']): if not interface_exists(config['address']['interface']): - Warning(f'Interface "{config["address"]["interface"]}" does not exist yet and ' - f'cannot be used for Dynamic DNS service "{service}" until it is up!') + Warning( + f'Interface "{config["address"]["interface"]}" does not exist yet and ' + f'cannot be used for Dynamic DNS service "{service}" until it is up!' + ) else: verify_interface_exists(dyndns, config['address']['interface']) if 'web' in config['address']: # If 'skip' is specified, 'url' is required as well - if 'skip' in config['address']['web'] and 'url' not in config['address']['web']: - raise ConfigError(f'"url" along with "skip" {error_msg_req} ' - f'with protocol "{config["protocol"]}"') + if ( + 'skip' in config['address']['web'] + and 'url' not in config['address']['web'] + ): + raise ConfigError( + f'"url" along with "skip" {error_msg_req} with protocol "{config["protocol"]}"' + ) # RFC2136 uses 'key' instead of 'password' if config['protocol'] != 'nsupdate' and 'password' not in config: @@ -122,38 +189,63 @@ def verify(dyndns): # Other RFC2136 specific configuration validation if config['protocol'] == 'nsupdate': if 'password' in config: - raise ConfigError(f'"password" {error_msg_uns} with protocol "{config["protocol"]}"') + raise ConfigError( + f'"password" {error_msg_uns} with protocol "{config["protocol"]}"' + ) for field in ['server', 'key']: if field not in config: - raise ConfigError(f'"{field}" {error_msg_req} with protocol "{config["protocol"]}"') + raise ConfigError( + f'"{field}" {error_msg_req} with protocol "{config["protocol"]}"' + ) if config['protocol'] in zone_necessary and 'zone' not in config: - raise ConfigError(f'"zone" {error_msg_req} with protocol "{config["protocol"]}"') + raise ConfigError( + f'"zone" {error_msg_req} with protocol "{config["protocol"]}"' + ) if config['protocol'] not in zone_supported and 'zone' in config: - raise ConfigError(f'"zone" {error_msg_uns} with protocol "{config["protocol"]}"') + raise ConfigError( + f'"zone" {error_msg_uns} with protocol "{config["protocol"]}"' + ) if config['protocol'] not in username_unnecessary and 'username' not in config: - raise ConfigError(f'"username" {error_msg_req} with protocol "{config["protocol"]}"') + raise ConfigError( + f'"username" {error_msg_req} with protocol "{config["protocol"]}"' + ) if config['protocol'] not in ttl_supported and 'ttl' in config: - raise ConfigError(f'"ttl" {error_msg_uns} with protocol "{config["protocol"]}"') + raise ConfigError( + f'"ttl" {error_msg_uns} with protocol "{config["protocol"]}"' + ) if config['ip_version'] == 'both': if config['protocol'] not in dualstack_supported: - raise ConfigError(f'Both IPv4 and IPv6 at the same time {error_msg_uns} ' - f'with protocol "{config["protocol"]}"') + raise ConfigError( + f'Both IPv4 and IPv6 at the same time {error_msg_uns} ' + f'with protocol "{config["protocol"]}"' + ) # dyndns2 protocol in ddclient honors dual stack only for dyn.com (dyndns.org) - if config['protocol'] == 'dyndns2' and 'server' in config and config['server'] not in dyndns_dualstack_servers: - raise ConfigError(f'Both IPv4 and IPv6 at the same time {error_msg_uns} ' - f'for "{config["server"]}" with protocol "{config["protocol"]}"') - - if {'wait_time', 'expiry_time'} <= config.keys() and int(config['expiry_time']) < int(config['wait_time']): - raise ConfigError(f'"expiry-time" must be greater than "wait-time" for ' - f'Dynamic DNS service "{service}"') + if ( + config['protocol'] == 'dyndns2' + and 'server' in config + and config['server'] not in dyndns_dualstack_servers + ): + raise ConfigError( + f'Both IPv4 and IPv6 at the same time {error_msg_uns} ' + f'for "{config["server"]}" with protocol "{config["protocol"]}"' + ) + + if {'wait_time', 'expiry_time'} <= config.keys() and int( + config['expiry_time'] + ) < int(config['wait_time']): + raise ConfigError( + f'"expiry-time" must be greater than "wait-time" for ' + f'Dynamic DNS service "{service}"' + ) return None + def generate(dyndns): # bail out early - looks like removal from running config if not dyndns or 'name' not in dyndns: @@ -184,6 +276,7 @@ def generate(dyndns): render(systemd_override, 'dns-dynamic/override.conf.j2', dyndns) return None + def apply(dyndns): systemd_service = 'ddclient.service' # Reload systemd manager configuration @@ -199,6 +292,7 @@ def apply(dyndns): return None + if __name__ == '__main__': try: c = get_config() |
