From 1c531a92815a1009ea17a38da5764c3a38e6de22 Mon Sep 17 00:00:00 2001 From: Viranch Mehta Date: Fri, 17 Sep 2021 11:20:42 -0700 Subject: [PATCH] Force enable/disable pool values --- octodns/provider/azuredns.py | 28 ++++++++++++++++++++++++++++ octodns/provider/ns1.py | 32 +++++++++++++++++++++----------- octodns/provider/route53.py | 10 ++++++++++ octodns/record/__init__.py | 1 + 4 files changed, 60 insertions(+), 11 deletions(-) diff --git a/octodns/provider/azuredns.py b/octodns/provider/azuredns.py index 3290ae5..18762d9 100644 --- a/octodns/provider/azuredns.py +++ b/octodns/provider/azuredns.py @@ -807,9 +807,16 @@ class AzureProvider(BaseProvider): defaults.add(val) ep_name = ep_name[:-len('--default--')] + up = None + if pool_ep.endpoint_status == 'Disabled': + up = False + elif ep_name.endswith('--UP'): + up = True + values.append({ 'value': val, 'weight': pool_ep.weight or 1, + 'up': up, }) return values @@ -898,6 +905,22 @@ class AzureProvider(BaseProvider): return data + def _process_desired_zone(self, desired): + # check for support of force up/down values + for record in desired.records: + if not getattr(record, 'dynamic', False): + continue + for name, pool in record.dynamic.pools.items(): + for value in pool.data['values']: + if value['up']: + # Azure only supports up=None & up=False, not up=True + msg = 'up=True is not supported for "{}" pool in {}' \ + .format(name, record.fqdn) + fallback = 'ignoring it' + self.supports_warn_or_except(msg, fallback) + + return super()._process_desired_zone(desired) + def _extra_changes(self, existing, desired, changes): changed = set(c.record for c in changes) @@ -1033,16 +1056,21 @@ class AzureProvider(BaseProvider): if record._type == 'CNAME': target = target[:-1] ep_name = f'{pool_name}--{target}' + if val['up']: + ep_name += '--UP' # Endpoint names cannot have colons, drop them from IPv6 addresses ep_name = ep_name.replace(':', '-') if target in defaults: # mark default ep_name += '--default--' default_seen = True + ep_status = 'Disabled' if val['up'] == False else \ + 'Enabled' endpoints.append(Endpoint( name=ep_name, target=target, weight=val.get('weight', 1), + endpoint_status=ep_status, )) pool_profile = self._generate_tm_profile( diff --git a/octodns/provider/ns1.py b/octodns/provider/ns1.py index e6fab6e..6e47c65 100644 --- a/octodns/provider/ns1.py +++ b/octodns/provider/ns1.py @@ -591,6 +591,9 @@ class Ns1Provider(BaseProvider): 'value': value, 'weight': int(meta.get('weight', 1)), } + if isinstance(meta['up'], bool): + value_dict['up'] = meta['up'] + if value_dict not in pool['values']: # If we haven't seen this value before add it to the pool pool['values'].append(value_dict) @@ -1141,6 +1144,10 @@ class Ns1Provider(BaseProvider): pool = pools[current_pool_name] for answer in pool_answers[current_pool_name]: fallback = pool.data['fallback'] + if answer['feed_id']: + up = {'feed': answer['feed_id']} + else: + up = answer['up'] answer = { 'answer': answer['answer'], 'meta': { @@ -1150,9 +1157,7 @@ class Ns1Provider(BaseProvider): 'pool': current_pool_name, 'fallback': fallback or '', }), - 'up': { - 'feed': answer['feed_id'], - }, + 'up': up, 'weight': answer['weight'], }, 'region': pool_label, # the one we're answering @@ -1273,20 +1278,25 @@ class Ns1Provider(BaseProvider): for pool_name, pool in sorted(pools.items()): for value in pool.data['values']: weight = value['weight'] + up = value['up'] value = value['value'] - feed_id = value_feed.get(value) - # check for identical monitor and skip creating one if found - if not feed_id: - existing = existing_monitors.get(value) - monitor_id, feed_id = self._monitor_sync(record, value, - existing) - value_feed[value] = feed_id - active_monitors.add(monitor_id) + feed_id = None + if up is None: + # state is not forced, let's find a monitor + feed_id = value_feed.get(value) + # check for identical monitor and skip creating one if found + if not feed_id: + existing = existing_monitors.get(value) + monitor_id, feed_id = self._monitor_sync(record, value, + existing) + value_feed[value] = feed_id + active_monitors.add(monitor_id) pool_answers[pool_name].append({ 'answer': [value], 'weight': weight, 'feed_id': feed_id, + 'up': up, }) if record._type == 'CNAME': diff --git a/octodns/provider/route53.py b/octodns/provider/route53.py index 0ecce72..a145190 100644 --- a/octodns/provider/route53.py +++ b/octodns/provider/route53.py @@ -941,6 +941,16 @@ class Route53Provider(BaseProvider): rule.data['geos'] = filtered_geos rules.append(rule) + # check for use of 'up' flag and warn/except if used + for name, pool in dynamic.pools.items(): + for value in pool.data['values']: + if value['up'] is not None: + msg = '"up" flag is not supported for "{}" pool' \ + ' in {}'.format(name, record.fqdn) + fallback = 'ignoring it, octodns-sync command ' \ + 'will keep showing changes' + self.supports_warn_or_except(msg, fallback) + if rules != dynamic.rules: record = record.copy() record.dynamic.rules = rules diff --git a/octodns/record/__init__.py b/octodns/record/__init__.py index d6fc1d4..fc2cff2 100644 --- a/octodns/record/__init__.py +++ b/octodns/record/__init__.py @@ -418,6 +418,7 @@ class _DynamicPool(object): { 'value': d['value'], 'weight': d.get('weight', 1), + 'up': d.get('up'), # TODO: add validation on this field } for d in data['values'] ] values.sort(key=lambda d: d['value'])