wrapper.go raw

   1  package vinyldns
   2  
   3  import (
   4  	"context"
   5  	"fmt"
   6  
   7  	"github.com/cenkalti/backoff/v5"
   8  	"github.com/go-acme/lego/v4/challenge/dns01"
   9  	"github.com/go-acme/lego/v4/platform/wait"
  10  	"github.com/vinyldns/go-vinyldns/vinyldns"
  11  )
  12  
  13  func (d *DNSProvider) getRecordSet(fqdn string) (*vinyldns.RecordSet, error) {
  14  	zoneName, hostName, err := splitDomain(fqdn)
  15  	if err != nil {
  16  		return nil, err
  17  	}
  18  
  19  	zone, err := d.client.ZoneByName(zoneName)
  20  	if err != nil {
  21  		return nil, err
  22  	}
  23  
  24  	allRecordSets, err := d.client.RecordSetsListAll(zone.ID, vinyldns.ListFilter{NameFilter: hostName})
  25  	if err != nil {
  26  		return nil, err
  27  	}
  28  
  29  	var recordSets []vinyldns.RecordSet
  30  
  31  	for _, i := range allRecordSets {
  32  		if i.Type == "TXT" {
  33  			recordSets = append(recordSets, i)
  34  		}
  35  	}
  36  
  37  	switch {
  38  	case len(recordSets) > 1:
  39  		return nil, fmt.Errorf("ambiguous recordset definition of %s", fqdn)
  40  	case len(recordSets) == 1:
  41  		return &recordSets[0], nil
  42  	default:
  43  		return nil, nil
  44  	}
  45  }
  46  
  47  func (d *DNSProvider) createRecordSet(ctx context.Context, fqdn string, records []vinyldns.Record) error {
  48  	zoneName, hostName, err := splitDomain(fqdn)
  49  	if err != nil {
  50  		return err
  51  	}
  52  
  53  	zone, err := d.client.ZoneByName(zoneName)
  54  	if err != nil {
  55  		return err
  56  	}
  57  
  58  	recordSet := vinyldns.RecordSet{
  59  		Name:    hostName,
  60  		ZoneID:  zone.ID,
  61  		Type:    "TXT",
  62  		TTL:     d.config.TTL,
  63  		Records: records,
  64  	}
  65  
  66  	resp, err := d.client.RecordSetCreate(&recordSet)
  67  	if err != nil {
  68  		return err
  69  	}
  70  
  71  	return d.waitForChanges(ctx, "CreateRS", resp)
  72  }
  73  
  74  func (d *DNSProvider) updateRecordSet(ctx context.Context, recordSet *vinyldns.RecordSet, newRecords []vinyldns.Record) error {
  75  	operation := "delete"
  76  	if len(recordSet.Records) < len(newRecords) {
  77  		operation = "add"
  78  	}
  79  
  80  	recordSet.Records = newRecords
  81  	recordSet.TTL = d.config.TTL
  82  
  83  	resp, err := d.client.RecordSetUpdate(recordSet)
  84  	if err != nil {
  85  		return err
  86  	}
  87  
  88  	return d.waitForChanges(ctx, "UpdateRS - "+operation, resp)
  89  }
  90  
  91  func (d *DNSProvider) deleteRecordSet(ctx context.Context, existingRecord *vinyldns.RecordSet) error {
  92  	resp, err := d.client.RecordSetDelete(existingRecord.ZoneID, existingRecord.ID)
  93  	if err != nil {
  94  		return err
  95  	}
  96  
  97  	return d.waitForChanges(ctx, "DeleteRS", resp)
  98  }
  99  
 100  func (d *DNSProvider) waitForChanges(ctx context.Context, operation string, resp *vinyldns.RecordSetUpdateResponse) error {
 101  	return wait.Retry(ctx,
 102  		func() error {
 103  			change, err := d.client.RecordSetChange(resp.Zone.ID, resp.RecordSet.ID, resp.ChangeID)
 104  			if err != nil {
 105  				return fmt.Errorf("failed to query change status: %w", err)
 106  			}
 107  
 108  			if change.Status != "Complete" {
 109  				return fmt.Errorf("waiting operation: %s, zoneID: %s, recordsetID: %s, changeID: %s",
 110  					operation, resp.Zone.ID, resp.RecordSet.ID, resp.ChangeID)
 111  			}
 112  
 113  			return nil
 114  		},
 115  		backoff.WithBackOff(backoff.NewConstantBackOff(d.config.PollingInterval)),
 116  		backoff.WithMaxElapsedTime(d.config.PropagationTimeout),
 117  	)
 118  }
 119  
 120  // splitDomain splits the hostname from the authoritative zone, and returns both parts.
 121  func splitDomain(fqdn string) (string, string, error) {
 122  	zone, err := dns01.FindZoneByFqdn(fqdn)
 123  	if err != nil {
 124  		return "", "", fmt.Errorf("could not find zone: %w", err)
 125  	}
 126  
 127  	subDomain, err := dns01.ExtractSubDomain(fqdn, zone)
 128  	if err != nil {
 129  		return "", "", err
 130  	}
 131  
 132  	return zone, subDomain, nil
 133  }
 134