diff options
author | Indrajit Raychaudhuri <irc@indrajit.com> | 2023-12-11 18:02:02 -0400 |
---|---|---|
committer | Indrajit Raychaudhuri <irc@indrajit.com> | 2023-12-15 12:19:23 -0600 |
commit | 2b96bc8532b61be96cea92cc1c5468bd5fc3d968 (patch) | |
tree | 9861d47df367875edb09a04318f6c64b1a10764f /src/migration-scripts | |
parent | b0beb1cb732cdf950917f1eb419f66cc4f007f29 (diff) | |
download | vyos-1x-2b96bc8532b61be96cea92cc1c5468bd5fc3d968.tar.gz vyos-1x-2b96bc8532b61be96cea92cc1c5468bd5fc3d968.zip |
ddclient: T5791: Fix migration to normalize config name and avoid config
Since `service dns dynamic address <address> service <service> ...`
changed to `service dns dynamic name <service> address <address> ...`,
the resulting service and address config flip can result in conflicting
`service` name.
Additionally, since dynamic DNS service name now have name constraint,
we need to normalize the service name to conform with the constraint.
We now migrate the service name to (service|rfc2136)-<service>-<address>
to avoid the conflict and optionally append an index if there is still a
name conflict after normalization.
Diffstat (limited to 'src/migration-scripts')
-rwxr-xr-x | src/migration-scripts/dns-dynamic/2-to-3 | 45 |
1 files changed, 38 insertions, 7 deletions
diff --git a/src/migration-scripts/dns-dynamic/2-to-3 b/src/migration-scripts/dns-dynamic/2-to-3 index 187c2a895..e5910f7b4 100755 --- a/src/migration-scripts/dns-dynamic/2-to-3 +++ b/src/migration-scripts/dns-dynamic/2-to-3 @@ -21,10 +21,27 @@ # to "service dns dynamic name <service> address <interface> protocol 'nsupdate'" # - migrate "service dns dynamic address <interface> service <service> ..." # to "service dns dynamic name <service> address <interface> ..." +# - normalize the all service names to conform with name constraints import sys +import re +from unicodedata import normalize from vyos.configtree import ConfigTree +def normalize_name(name): + """Normalize service names to conform with name constraints. + + This is necessary as part of migration because there were no constraints in + the old name format. + """ + # Normalize unicode characters to ASCII (NFKD) + # Replace all separators with hypens, strip leading and trailing hyphens + name = normalize('NFKD', name).encode('ascii', 'ignore').decode() + name = re.sub(r'(\s|\W)+', '-', name).strip('-') + + return name + + if len(sys.argv) < 2: print("Must specify file name!") sys.exit(1) @@ -64,22 +81,36 @@ for address in config.list_nodes(address_path): for svc_type in ['service', 'rfc2136']: if config.exists(address_path_tag + [svc_type]): - # Move RFC2136 as service configuration, rename to avoid name conflict and set protocol to 'nsupdate' + # Set protocol to 'nsupdate' for RFC2136 configuration if svc_type == 'rfc2136': - for rfc_cfg_old in config.list_nodes(address_path_tag + ['rfc2136']): - rfc_cfg_new = f'{rfc_cfg_old}-rfc2136' - config.rename(address_path_tag + ['rfc2136', rfc_cfg_old], rfc_cfg_new) - config.set(address_path_tag + ['rfc2136', rfc_cfg_new, 'protocol'], 'nsupdate') + for rfc_cfg in config.list_nodes(address_path_tag + ['rfc2136']): + config.set(address_path_tag + ['rfc2136', rfc_cfg, 'protocol'], 'nsupdate') # Add address as config value in each service before moving the service path - # And then copy the services from 'address <interface> service <service>' to 'name <service>' + # And then copy the services from 'address <interface> service <service>' + # to 'name (service|rfc2136)-<service>-<address>' + # Note: The new service is named (service|rfc2136)-<service>-<address> + # to avoid name conflict with old entries for svc_cfg in config.list_nodes(address_path_tag + [svc_type]): config.set(address_path_tag + [svc_type, svc_cfg, 'address'], address) - config.copy(address_path_tag + [svc_type, svc_cfg], name_path + [svc_cfg]) + config.copy(address_path_tag + [svc_type, svc_cfg], + name_path + ['-'.join([svc_type, svc_cfg, address])]) # Finally cleanup the old address path config.delete(address_path) +# Normalize the all service names to conform with name constraints +index = 1 +for name in config.list_nodes(name_path): + new_name = normalize_name(name) + if new_name != name: + # Append index if there is still a name conflicts after normalization + # For example, "foo-?(" and "foo-!)" both normalize to "foo-" + if config.exists(name_path + [new_name]): + new_name = f'{new_name}-{index}' + index += 1 + config.rename(name_path + [name], new_name) + try: with open(file_name, 'w') as f: f.write(config.to_string()) |