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 }