github.com/pmoroney/dnscontrol@v0.2.4-0.20171024134423-fad98f73f44a/providers/namedotcom/nameservers.go (about) 1 package namedotcom 2 3 import ( 4 "fmt" 5 "regexp" 6 "sort" 7 "strings" 8 9 "github.com/StackExchange/dnscontrol/models" 10 ) 11 12 var nsRegex = regexp.MustCompile(`ns([1-4])[a-z]{3}\.name\.com`) 13 14 func (n *nameDotCom) GetNameservers(domain string) ([]*models.Nameserver, error) { 15 //This is an interesting edge case. Name.com expects you to SET the nameservers to ns[1-4].name.com, 16 //but it will internally set it to ns1xyz.name.com, where xyz is a uniqueish 3 letters. 17 //In order to avoid endless loops, we will use the unique nameservers if present, or else the generic ones if not. 18 nss, err := n.getNameserversRaw(domain) 19 if err != nil { 20 return nil, err 21 } 22 toUse := []string{"ns1.name.com", "ns2.name.com", "ns3.name.com", "ns4.name.com"} 23 for _, ns := range nss { 24 if matches := nsRegex.FindStringSubmatch(ns); len(matches) == 2 && len(matches[1]) == 1 { 25 idx := matches[1][0] - '1' //regex ensures proper range 26 toUse[idx] = matches[0] 27 } 28 } 29 return models.StringsToNameservers(toUse), nil 30 } 31 32 func (n *nameDotCom) getNameserversRaw(domain string) ([]string, error) { 33 result := &getDomainResult{} 34 if err := n.get(n.apiGetDomain(domain), result); err != nil { 35 return nil, err 36 } 37 if err := result.getErr(); err != nil { 38 return nil, err 39 } 40 sort.Strings(result.Nameservers) 41 return result.Nameservers, nil 42 } 43 44 func (n *nameDotCom) GetRegistrarCorrections(dc *models.DomainConfig) ([]*models.Correction, error) { 45 nss, err := n.getNameserversRaw(dc.Name) 46 if err != nil { 47 return nil, err 48 } 49 foundNameservers := strings.Join(nss, ",") 50 expected := []string{} 51 for _, ns := range dc.Nameservers { 52 name := strings.TrimRight(ns.Name, ".") 53 expected = append(expected, name) 54 } 55 sort.Strings(expected) 56 expectedNameservers := strings.Join(expected, ",") 57 58 if foundNameservers != expectedNameservers { 59 return []*models.Correction{ 60 { 61 Msg: fmt.Sprintf("Update nameservers %s -> %s", foundNameservers, expectedNameservers), 62 F: n.updateNameservers(expected, dc.Name), 63 }, 64 }, nil 65 } 66 return nil, nil 67 } 68 69 //even if you provide them "ns1.name.com", they will set it to "ns1qrt.name.com". This will match that pattern to see if defaults are in use. 70 var defaultNsRegexp = regexp.MustCompile(`ns1[a-z]{0,3}\.name\.com,ns2[a-z]{0,3}\.name\.com,ns3[a-z]{0,3}\.name\.com,ns4[a-z]{0,3}\.name\.com`) 71 72 func (n *nameDotCom) apiGetDomain(domain string) string { 73 return fmt.Sprintf("%s/domain/get/%s", n.APIUrl, domain) 74 } 75 func (n *nameDotCom) apiUpdateNS(domain string) string { 76 return fmt.Sprintf("%s/domain/update_nameservers/%s", n.APIUrl, domain) 77 } 78 79 type getDomainResult struct { 80 *apiResult 81 DomainName string `json:"domain_name"` 82 Nameservers []string `json:"nameservers"` 83 } 84 85 func (n *nameDotCom) updateNameservers(ns []string, domain string) func() error { 86 return func() error { 87 dat := struct { 88 Nameservers []string `json:"nameservers"` 89 }{ns} 90 resp, err := n.post(n.apiUpdateNS(domain), dat) 91 if err != nil { 92 return err 93 } 94 if err = resp.getErr(); err != nil { 95 return err 96 } 97 return nil 98 } 99 }