def _update_dyn_traffic_director_records( td: TrafficDirector, records: List, ruleset_label: str, rpool_label: str, chain_label: str, rset_label: str, ): """Updates the records of a TrafficDirector service for a given ruleset, responsepool and failover chain NOTE: This calls the Dyn API to apply the change """ new_rset = DSFRecordSet( "CNAME", label=td.label, automation="manual", records=records ) # Need to follow the hierarchy # TD <- Ruleset -> ResponsePool <- FailoverChain <- RecordSet <- Record ruleset = _get_dyn_traffic_director_ruleset(td, ruleset_label) rpool = _get_dyn_traffic_director_response_pool(ruleset, rpool_label) chain = _get_dyn_traffic_director_chain(rpool, chain_label) current_recordset = _get_dyn_traffic_director_recordset(chain, rset_label) new_rset.add_to_failover_chain(chain) current_recordset.delete()
def _find_or_create_pool(self, td, pools, label, _type, values, monitor_id=None): for pool in pools: if pool.label != label: continue records = pool.rs_chains[0].record_sets[0].records record_values = sorted([r.address for r in records]) if record_values == values: # it's a match return pool # we need to create the pool _class = {'A': DSFARecord, 'AAAA': DSFAAAARecord}[_type] records = [_class(v) for v in values] record_set = DSFRecordSet(_type, label, serve_count=len(records), records=records, dsf_monitor_id=monitor_id) chain = DSFFailoverChain(label, record_sets=[record_set]) pool = DSFResponsePool(label, rs_chains=[chain]) pool.create(td) return pool
def _find_or_create_pool(self, td, pools, label, _type, values, monitor_id=None): for pool in pools: if pool.label != label: continue records = pool.rs_chains[0].record_sets[0].records def _filter_records(r): if hasattr(r, 'address'): return r.address elif hasattr(r, 'cname'): return r.cname elif hasattr(r, 'txtdata'): return r.txtdata else: return None record_values = sorted(map(_filter_records, records)) if record_values == values: # it's a match return pool # we need to create the pool _class = { 'A': DSFARecord, 'AAAA': DSFAAAARecord, 'CNAME': DSFCNAMERecord, 'TXT': DSFTXTRecord }[_type] if isinstance(values, list): records = [_class(v) for v in values] else: records = [_class(values)] record_set = DSFRecordSet(_type, label, serve_count=len(records), records=records, dsf_monitor_id=monitor_id) chain = DSFFailoverChain(label, record_sets=[record_set]) pool = DSFResponsePool(label, rs_chains=[chain]) pool.create(td) return pool
def _new_dyn_traffic_director_service(name, ttl=DEFAULT_TD_TTL, records=None, attach_nodes=None) -> TrafficDirector: """Creates an opinionated Dyn Traffic Director service - Creates a CNAME recordset - Expects all records to be DSFCNAMERecord type - Creates a single failover chain pointing to the recordset - Creates a single pool pointing to the failover chain - Creates a single ruleset that always responds and points to the pool NOTE: The dyn module TrafficDirector constructor has side effects and calls the Dyn API multiple times. It is possible that Dyn resources are created even if the constructor failed """ if records is None: records = [] if attach_nodes is None: attach_nodes = [] try: record_set = DSFRecordSet('CNAME', label=name, automation='manual', records=records) failover_chain = DSFFailoverChain(label=name, record_sets=[record_set]) rpool = DSFResponsePool(label=name, rs_chains=[failover_chain]) ruleset = DSFRuleset(label=name, criteria_type='always', response_pools=[rpool]) # Constructor does the actual resource creation and checking for # creation completion. # It returns returns a resource ID which we don't need return TrafficDirector(name, ttl=ttl, rulesets=[ruleset], nodes=attach_nodes) except Exception as e: raise CreateTrafficDirectorError( f'Exception caught during creation of Traffic Director: {name} ' f'The exception was: {e}')