github.com/teknogeek/dnscontrol/v2@v2.10.1-0.20200227202244-ae299b55ba42/providers/hexonet/nameservers.go (about)

     1  package hexonet
     2  
     3  import (
     4  	"fmt"
     5  	"regexp"
     6  	"sort"
     7  	"strings"
     8  
     9  	"github.com/StackExchange/dnscontrol/v2/models"
    10  )
    11  
    12  var defaultNameservers = []*models.Nameserver{
    13  	{Name: "ns1.ispapi.net"},
    14  	{Name: "ns2.ispapi.net"},
    15  	{Name: "ns3.ispapi.net"},
    16  }
    17  
    18  var nsRegex = regexp.MustCompile(`ns([1-3]{1})[0-9]+\.ispapi\.net`)
    19  
    20  // GetNameservers gets the nameservers set on a domain.
    21  func (n *HXClient) GetNameservers(domain string) ([]*models.Nameserver, error) {
    22  	// This is an interesting edge case. hexonet expects you to SET the nameservers to ns[1-3].ispapi.net,
    23  	// but it will internally set it to (ns1xyz|ns2uvw|ns3asd).ispapi.net, where xyz/uvw/asd is a uniqueish number.
    24  	// In order to avoid endless loops, we will use the unique nameservers if present, or else the generic ones if not.
    25  	nss, err := n.getNameserversRaw(domain)
    26  	if err != nil {
    27  		return nil, err
    28  	}
    29  	toUse := []string{
    30  		defaultNameservers[0].Name,
    31  		defaultNameservers[1].Name,
    32  		defaultNameservers[2].Name,
    33  	}
    34  	for _, ns := range nss {
    35  		if matches := nsRegex.FindStringSubmatch(ns); len(matches) == 2 && len(matches[1]) == 1 {
    36  			idx := matches[1][0] - '1' // regex ensures proper range
    37  			toUse[idx] = matches[0]
    38  		}
    39  	}
    40  	return models.StringsToNameservers(toUse), nil
    41  }
    42  
    43  func (n *HXClient) getNameserversRaw(domain string) ([]string, error) {
    44  	r := n.client.Request(map[string]string{
    45  		"COMMAND": "StatusDomain",
    46  		"DOMAIN":  domain,
    47  	})
    48  	code := r.GetCode()
    49  	if code != 200 {
    50  		return nil, n.GetHXApiError("Could not get status for domain", domain, r)
    51  	}
    52  	nsColumn := r.GetColumn("NAMESERVER")
    53  	if nsColumn == nil {
    54  		return nil, fmt.Errorf("Error getting NAMESERVER column for domain: %s", domain)
    55  	}
    56  	ns := nsColumn.GetData()
    57  	sort.Strings(ns)
    58  	return ns, nil
    59  }
    60  
    61  // GetRegistrarCorrections gathers corrections that would being n to match dc.
    62  func (n *HXClient) GetRegistrarCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
    63  	nss, err := n.getNameserversRaw(dc.Name)
    64  	if err != nil {
    65  		return nil, err
    66  	}
    67  	foundNameservers := strings.Join(nss, ",")
    68  
    69  	expected := []string{}
    70  	for _, ns := range dc.Nameservers {
    71  		name := strings.TrimRight(ns.Name, ".")
    72  		expected = append(expected, name)
    73  	}
    74  	sort.Strings(expected)
    75  	expectedNameservers := strings.Join(expected, ",")
    76  
    77  	if foundNameservers != expectedNameservers {
    78  		return []*models.Correction{
    79  			{
    80  				Msg: fmt.Sprintf("Update nameservers %s -> %s", foundNameservers, expectedNameservers),
    81  				F:   n.updateNameservers(expected, dc.Name),
    82  			},
    83  		}, nil
    84  	}
    85  	return nil, nil
    86  }
    87  
    88  func (n *HXClient) updateNameservers(ns []string, domain string) func() error {
    89  	return func() error {
    90  		cmd := map[string]string{
    91  			"COMMAND": "ModifyDomain",
    92  			"DOMAIN":  domain,
    93  		}
    94  		for idx, ns := range ns {
    95  			cmd[fmt.Sprintf("NAMESERVER%d", idx)] = ns
    96  		}
    97  		response := n.client.Request(cmd)
    98  		code := response.GetCode()
    99  		if code != 200 {
   100  			return fmt.Errorf("%d %s", code, response.GetDescription())
   101  		}
   102  		return nil
   103  	}
   104  }