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()
예제 #2
0
 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
예제 #3
0
    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
예제 #4
0
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}')