github.com/StackExchange/DNSControl@v0.2.8/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/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.Code() 49 if code != 200 { 50 return nil, n.GetHXApiError("Could not get status for domain", domain, r) 51 } 52 ns := r.GetColumn("NAMESERVER") 53 sort.Strings(ns) 54 return ns, nil 55 } 56 57 // GetRegistrarCorrections gathers corrections that would being n to match dc. 58 func (n *HXClient) GetRegistrarCorrections(dc *models.DomainConfig) ([]*models.Correction, error) { 59 nss, err := n.getNameserversRaw(dc.Name) 60 if err != nil { 61 return nil, err 62 } 63 foundNameservers := strings.Join(nss, ",") 64 65 expected := []string{} 66 for _, ns := range dc.Nameservers { 67 name := strings.TrimRight(ns.Name, ".") 68 expected = append(expected, name) 69 } 70 sort.Strings(expected) 71 expectedNameservers := strings.Join(expected, ",") 72 73 if foundNameservers != expectedNameservers { 74 return []*models.Correction{ 75 { 76 Msg: fmt.Sprintf("Update nameservers %s -> %s", foundNameservers, expectedNameservers), 77 F: n.updateNameservers(expected, dc.Name), 78 }, 79 }, nil 80 } 81 return nil, nil 82 } 83 84 func (n *HXClient) updateNameservers(ns []string, domain string) func() error { 85 return func() error { 86 cmd := map[string]string{ 87 "COMMAND": "ModifyDomain", 88 "DOMAIN": domain, 89 } 90 for idx, ns := range ns { 91 cmd[fmt.Sprintf("NAMESERVER%d", idx)] = ns 92 } 93 response := n.client.Request(cmd) 94 code := response.Code() 95 if code != 200 { 96 return fmt.Errorf(fmt.Sprintf("%d %s", code, response.Description())) 97 } 98 return nil 99 } 100 }