diff --git a/models/dns.go b/models/dns.go index 2577a4c2d..54df26010 100644 --- a/models/dns.go +++ b/models/dns.go @@ -327,6 +327,46 @@ func SplitCombinedMxValue(s string) (preference uint16, target string, err error return uint16(n64), parts[1], nil } +// CombineSRVs will merge the priority, weight, and port into the target field for all srv records. +// Useful for providers that desire them as one field. +func (dc *DomainConfig) CombineSRVs() { + for _, rec := range dc.Records { + if rec.Type == "SRV" { + if rec.CombinedTarget { + pm := strings.Join([]string{"CombineSRVs: Already collapsed: ", rec.Name, rec.Target}, " ") + panic(pm) + } + rec.Target = fmt.Sprintf("%d %d %d %s", rec.SrvPriority, rec.SrvWeight, rec.SrvPort, rec.Target) + rec.CombinedTarget = true + } + } +} + +//SplitCombinedSrvValue splits a combined SRV priority, weight, port and target into +//separate entities, some DNS providers want "5" "10" 15" and "foo.com.", +//while other providers want "5 10 15 foo.com.". +func SplitCombinedSrvValue(s string) (priority, weight, port uint16, target string, err error) { + parts := strings.Fields(s) + + if len(parts) != 4 { + return 0, 0, 0, "", fmt.Errorf("SRV value %#v contains too many fields", s) + } + + priorityconv, err := strconv.ParseInt(parts[0], 10, 16) + if err != nil { + return 0, 0, 0, "", fmt.Errorf("Priority %#v does not fit into a uint16", parts[0]) + } + weightconv, err := strconv.ParseInt(parts[1], 10, 16) + if err != nil { + return 0, 0, 0, "", fmt.Errorf("Weight %#v does not fit into a uint16", parts[0]) + } + portconv, err := strconv.ParseInt(parts[2], 10, 16) + if err != nil { + return 0, 0, 0, "", fmt.Errorf("Port %#v does not fit into a uint16", parts[0]) + } + return uint16(priorityconv), uint16(weightconv), uint16(portconv), parts[3], nil +} + func copyObj(input interface{}, output interface{}) error { buf := &bytes.Buffer{} enc := gob.NewEncoder(buf) diff --git a/providers/gandi/gandiProvider.go b/providers/gandi/gandiProvider.go index 7270e5cd0..24a6106e8 100644 --- a/providers/gandi/gandiProvider.go +++ b/providers/gandi/gandiProvider.go @@ -61,6 +61,7 @@ func (c *GandiApi) GetNameservers(domain string) ([]*models.Nameserver, error) { func (c *GandiApi) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correction, error) { dc.Punycode() + dc.CombineSRVs() dc.CombineMXs() domaininfo, err := c.getDomainInfo(dc.Name) if err != nil { @@ -146,5 +147,5 @@ func newGandi(m map[string]string, metadata json.RawMessage) (providers.DNSServi } func init() { - providers.RegisterDomainServiceProviderType("GANDI", newGandi, providers.CanUsePTR) + providers.RegisterDomainServiceProviderType("GANDI", newGandi, providers.CanUsePTR, providers.CanUseSRV) } diff --git a/providers/gandi/protocol.go b/providers/gandi/protocol.go index 07d37c724..f7a886271 100644 --- a/providers/gandi/protocol.go +++ b/providers/gandi/protocol.go @@ -184,6 +184,12 @@ func convert(r *gandirecord.RecordInfo, origin string) *models.RecordConfig { } switch r.Type { case "A", "AAAA", "NS", "CNAME", "PTR", "TXT": + case "SRV": + var err error + rc.SrvPriority, rc.SrvWeight, rc.SrvPort, rc.Target, err = models.SplitCombinedSrvValue(r.Value) + if err != nil { + panic(fmt.Sprintf("gandi.convert bad srv value format: %#v (%s)", r.Value, err)) + } // no-op case "MX": var err error