|
|
|
@ -116,12 +116,12 @@ class _AzureRecord(object): |
|
|
|
return |
|
|
|
|
|
|
|
# Refer to function docstring for key_name and class_name. |
|
|
|
key_name = '{}_records'.format(self.record_type).lower() |
|
|
|
key_name = f'{self.record_type}_records'.lower() |
|
|
|
if record._type == 'CNAME': |
|
|
|
key_name = key_name[:-1] |
|
|
|
azure_class = self.TYPE_MAP[self.record_type] |
|
|
|
|
|
|
|
params_for = getattr(self, '_params_for_{}'.format(record._type)) |
|
|
|
params_for = getattr(self, f'_params_for_{record._type}') |
|
|
|
self.params = params_for(record.data, key_name, azure_class) |
|
|
|
self.params['ttl'] = record.ttl |
|
|
|
|
|
|
|
@ -228,7 +228,7 @@ class _AzureRecord(object): |
|
|
|
''' |
|
|
|
|
|
|
|
def key_dict(d): |
|
|
|
return sum([hash('{}:{}'.format(k, v)) for k, v in d.items()]) |
|
|
|
return sum([hash(f'{k}:{v}') for k, v in d.items()]) |
|
|
|
|
|
|
|
def parse_dict(params): |
|
|
|
vals = [] |
|
|
|
@ -272,18 +272,18 @@ def _root_traffic_manager_name(record): |
|
|
|
# hoping that real life FQDNs won't have double hyphens |
|
|
|
name = record.fqdn[:-1].replace('.', '--') |
|
|
|
if record._type != 'CNAME': |
|
|
|
name += '-{}'.format(record._type) |
|
|
|
name += f'-{record._type}' |
|
|
|
return name |
|
|
|
|
|
|
|
|
|
|
|
def _rule_traffic_manager_name(pool, record): |
|
|
|
prefix = _root_traffic_manager_name(record) |
|
|
|
return '{}-rule-{}'.format(prefix, pool) |
|
|
|
return f'{prefix}-rule-{pool}' |
|
|
|
|
|
|
|
|
|
|
|
def _pool_traffic_manager_name(pool, record): |
|
|
|
prefix = _root_traffic_manager_name(record) |
|
|
|
return '{}-pool-{}'.format(prefix, pool) |
|
|
|
return f'{prefix}-pool-{pool}' |
|
|
|
|
|
|
|
|
|
|
|
def _get_monitor(record): |
|
|
|
@ -314,14 +314,14 @@ def _check_valid_dynamic(record): |
|
|
|
if defaults != vals: |
|
|
|
# we don't yet support multi-value defaults, specifying all |
|
|
|
# pool values allows for Traffic Manager profile optimization |
|
|
|
msg = ('{} {}: Values of A/AAAA dynamic records must either ' |
|
|
|
'have a single value or contain all values from all ' |
|
|
|
'pools') |
|
|
|
raise AzureException(msg.format(record.fqdn, record._type)) |
|
|
|
raise AzureException(f'{record.fqdn} {record._type}: Values ' |
|
|
|
'of A/AAAA dynamic records must either ' |
|
|
|
'have a single value or contain all ' |
|
|
|
'values from all pools') |
|
|
|
elif typ != 'CNAME': |
|
|
|
# dynamic records of unsupported type |
|
|
|
msg = '{}: Dynamic records in Azure must be of type A/AAAA/CNAME' |
|
|
|
raise AzureException(msg.format(record.fqdn)) |
|
|
|
raise AzureException(f'{record.fqdn}: Dynamic records in Azure must ' |
|
|
|
'be of type A/AAAA/CNAME') |
|
|
|
|
|
|
|
|
|
|
|
def _profile_is_match(have, desired): |
|
|
|
@ -331,7 +331,7 @@ def _profile_is_match(have, desired): |
|
|
|
log = logging.getLogger('azuredns._profile_is_match').debug |
|
|
|
|
|
|
|
def false(have, desired, name=None): |
|
|
|
prefix = 'profile={}'.format(name) if name else '' |
|
|
|
prefix = f'profile={name}' if name else '' |
|
|
|
attr = have.__class__.__name__ |
|
|
|
log('%s have.%s = %s', prefix, attr, have) |
|
|
|
log('%s desired.%s = %s', prefix, attr, desired) |
|
|
|
@ -463,7 +463,7 @@ class AzureProvider(BaseProvider): |
|
|
|
|
|
|
|
def __init__(self, id, client_id, key, directory_id, sub_id, |
|
|
|
resource_group, *args, **kwargs): |
|
|
|
self.log = logging.getLogger('AzureProvider[{}]'.format(id)) |
|
|
|
self.log = logging.getLogger(f'AzureProvider[{id}]') |
|
|
|
self.log.debug('__init__: id=%s, client_id=%s, ' |
|
|
|
'key=***, directory_id:%s', id, client_id, directory_id) |
|
|
|
super(AzureProvider, self).__init__(id, *args, **kwargs) |
|
|
|
@ -635,7 +635,7 @@ class AzureProvider(BaseProvider): |
|
|
|
record_name = azrecord.name if azrecord.name != '@' else '' |
|
|
|
typ = _parse_azure_type(azrecord.type) |
|
|
|
|
|
|
|
data_for = getattr(self, '_data_for_{}'.format(typ)) |
|
|
|
data_for = getattr(self, f'_data_for_{typ}') |
|
|
|
data = data_for(azrecord) |
|
|
|
data['type'] = typ |
|
|
|
data['ttl'] = azrecord.ttl |
|
|
|
@ -755,13 +755,13 @@ class AzureProvider(BaseProvider): |
|
|
|
# Throw exception otherwise, it should not happen if the |
|
|
|
# profile was generated by octoDNS |
|
|
|
if 'GEO-AS' not in geo_map: |
|
|
|
msg = 'Profile={} for record {}: '.format( |
|
|
|
root_profile.name, azrecord.fqdn) |
|
|
|
msg += 'Middle East (GEO-ME) is not supported by ' + \ |
|
|
|
'octoDNS. It needs to be either paired ' + \ |
|
|
|
'with Asia (GEO-AS) or expanded into ' + \ |
|
|
|
'individual list of countries.' |
|
|
|
raise AzureException(msg) |
|
|
|
raise AzureException(f'Profile={root_profile.name} ' |
|
|
|
f'for record {azrecord.fqdn}: ' |
|
|
|
'Middle East (GEO-ME) is not ' |
|
|
|
'supported by octoDNS. It needs ' |
|
|
|
'to be either paired with Asia ' |
|
|
|
'(GEO-AS) or expanded into ' |
|
|
|
'individual list of countries.') |
|
|
|
geo_map.remove('GEO-ME') |
|
|
|
geos = rule.setdefault('geos', []) |
|
|
|
for code in geo_map: |
|
|
|
@ -779,7 +779,7 @@ class AzureProvider(BaseProvider): |
|
|
|
# state |
|
|
|
country, province = code.split('-', 1) |
|
|
|
country = GeoCodes.country_to_code(country) |
|
|
|
geos.append('{}-{}'.format(country, province)) |
|
|
|
geos.append(f'{country}-{province}') |
|
|
|
elif code == 'WORLD': |
|
|
|
geos.append(code) |
|
|
|
else: |
|
|
|
@ -904,17 +904,17 @@ class AzureProvider(BaseProvider): |
|
|
|
if not ep.target: |
|
|
|
continue |
|
|
|
if ep.target in endpoints: |
|
|
|
msg = '{} contains duplicate endpoint {}' |
|
|
|
raise AzureException(msg.format(name, ep.target)) |
|
|
|
raise AzureException(f'{name} contains duplicate ' |
|
|
|
f'endpoint {ep.target}') |
|
|
|
endpoints.add(ep.target) |
|
|
|
|
|
|
|
if name in seen_profiles: |
|
|
|
# exit if a possible collision is detected, even though |
|
|
|
# we've tried to ensure unique mapping |
|
|
|
msg = 'Collision in Traffic Manager names detected' |
|
|
|
msg = '{}: {} and {} both want to use {}'.format( |
|
|
|
msg, seen_profiles[name], record.fqdn, name) |
|
|
|
raise AzureException(msg) |
|
|
|
raise AzureException('Collision in Traffic Manager names ' |
|
|
|
f'detected: {seen_profiles[name]} ' |
|
|
|
f'and {record.fqdn} both want to ' |
|
|
|
f'use {name}') |
|
|
|
else: |
|
|
|
seen_profiles[name] = record.fqdn |
|
|
|
|
|
|
|
@ -952,10 +952,9 @@ class AzureProvider(BaseProvider): |
|
|
|
elif ep.target: |
|
|
|
ep.type = endpoint_type_prefix + 'externalEndpoints' |
|
|
|
else: |
|
|
|
msg = ('Invalid endpoint {} in profile {}, needs to have ' + |
|
|
|
'either target or target_resource_id').format( |
|
|
|
ep.name, name) |
|
|
|
raise AzureException(msg) |
|
|
|
raise AzureException(f'Invalid endpoint {ep.name} in profile ' |
|
|
|
f'{name}, needs to have either target ' |
|
|
|
'or target_resource_id') |
|
|
|
|
|
|
|
# build and return |
|
|
|
return Profile( |
|
|
|
@ -1028,7 +1027,7 @@ class AzureProvider(BaseProvider): |
|
|
|
# Oceania |
|
|
|
geo = 'AP' |
|
|
|
|
|
|
|
geos.append('GEO-{}'.format(geo)) |
|
|
|
geos.append(f'GEO-{geo}') |
|
|
|
if not geos or pool_name == world_pool: |
|
|
|
geos.append('WORLD') |
|
|
|
world_seen = True |
|
|
|
@ -1050,7 +1049,7 @@ class AzureProvider(BaseProvider): |
|
|
|
# strip trailing dot from CNAME value |
|
|
|
if typ == 'CNAME': |
|
|
|
target = target[:-1] |
|
|
|
ep_name = '{}--{}'.format(pool_name, target) |
|
|
|
ep_name = f'{pool_name}--{target}' |
|
|
|
# Endpoint names cannot have colons, drop them |
|
|
|
# from IPv6 addresses |
|
|
|
ep_name = ep_name.replace(':', '-') |
|
|
|
@ -1180,8 +1179,8 @@ class AzureProvider(BaseProvider): |
|
|
|
# match existing profiles with record's prefix |
|
|
|
name = profile_id.split('/')[-1] |
|
|
|
if name == tm_prefix or \ |
|
|
|
name.startswith('{}-pool-'.format(tm_prefix)) or \ |
|
|
|
name.startswith('{}-rule-'.format(tm_prefix)): |
|
|
|
name.startswith(f'{tm_prefix}-pool-') or \ |
|
|
|
name.startswith(f'{tm_prefix}-rule-'): |
|
|
|
profiles.add(name) |
|
|
|
|
|
|
|
return profiles |
|
|
|
@ -1236,7 +1235,7 @@ class AzureProvider(BaseProvider): |
|
|
|
root_profile.endpoints = endpoints |
|
|
|
self._sync_traffic_managers([root_profile]) |
|
|
|
|
|
|
|
self.log.debug('* Success Create: {}'.format(record)) |
|
|
|
self.log.debug('* Success Create: %s', record) |
|
|
|
|
|
|
|
def _apply_Update(self, change): |
|
|
|
'''A record from change must be created. |
|
|
|
@ -1300,7 +1299,7 @@ class AzureProvider(BaseProvider): |
|
|
|
# changed to a simple record |
|
|
|
self._traffic_managers_gc(existing, set()) |
|
|
|
|
|
|
|
self.log.debug('* Success Update: {}'.format(new)) |
|
|
|
self.log.debug('* Success Update: %s', new) |
|
|
|
|
|
|
|
def _apply_Delete(self, change): |
|
|
|
'''A record from change must be deleted. |
|
|
|
@ -1320,7 +1319,7 @@ class AzureProvider(BaseProvider): |
|
|
|
if getattr(record, 'dynamic', False): |
|
|
|
self._traffic_managers_gc(record, set()) |
|
|
|
|
|
|
|
self.log.debug('* Success Delete: {}'.format(record)) |
|
|
|
self.log.debug('* Success Delete: %s', record) |
|
|
|
|
|
|
|
def _apply(self, plan): |
|
|
|
'''Required function of manager.py to actually apply a record change. |
|
|
|
@ -1353,4 +1352,4 @@ class AzureProvider(BaseProvider): |
|
|
|
for change in changes: |
|
|
|
class_name = change.__class__.__name__ |
|
|
|
if class_name != 'Delete': |
|
|
|
getattr(self, '_apply_{}'.format(class_name))(change) |
|
|
|
getattr(self, f'_apply_{class_name}')(change) |