mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-05-11 05:55:12 +00:00
According to the RFC, the way to indicate that a SRV has no target is to set the target to ".". Some providers do not handle this, or the API returns "" instead of ".". This situation is now tested in the integration tests and all providers (that support this) have been fixed. * Cloudflare: Fix decoding empty SRV target (fixes #561) SRV records with empty (".") targets are now returned as false by the API, which breaks Unmarshaling it into a string. * Use custom type for Cloudflare SRV target Rewrote the SRV target decoding to use a custom type for (un)marshaling, as Cloudflare returns false for null targets, but it requires a single period for giving it one. The target code has also been made more flexible to future API changes with additional normalization. This has been tested with record creation, deletion, and update and works as of 2019-11-05. * DigitalOcean: Fix target FQDN for null targets Without this, dnscontrol thinks an update is needed (.. != .) even when the SRV target is correct. * DNSimple: Fix parsing of null SRV target DNSimple only returns two fields when the target is null. * NameDotCom: Add note about not supporting null SRV targets, skip test * DNSimple: Do not append a . unless we have all three parts Signed-off-by: Amelia Aronsohn <squirrel@wearing.black> * Regenerated provider matrix
69 lines
2.4 KiB
Go
69 lines
2.4 KiB
Go
package models
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// SetTargetSRV sets the SRV fields.
|
|
func (rc *RecordConfig) SetTargetSRV(priority, weight, port uint16, target string) error {
|
|
rc.SrvPriority = priority
|
|
rc.SrvWeight = weight
|
|
rc.SrvPort = port
|
|
rc.SetTarget(target)
|
|
if rc.Type == "" {
|
|
rc.Type = "SRV"
|
|
}
|
|
if rc.Type != "SRV" {
|
|
panic("assertion failed: SetTargetSRV called when .Type is not SRV")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// setTargetSRVIntAndStrings is like SetTargetSRV but accepts priority as an int, the other parameters as strings.
|
|
func (rc *RecordConfig) setTargetSRVIntAndStrings(priority uint16, weight, port, target string) (err error) {
|
|
var i64weight, i64port uint64
|
|
if i64weight, err = strconv.ParseUint(weight, 10, 16); err == nil {
|
|
if i64port, err = strconv.ParseUint(port, 10, 16); err == nil {
|
|
return rc.SetTargetSRV(priority, uint16(i64weight), uint16(i64port), target)
|
|
}
|
|
}
|
|
return errors.Wrap(err, "SRV value too big for uint16")
|
|
}
|
|
|
|
// SetTargetSRVStrings is like SetTargetSRV but accepts all parameters as strings.
|
|
func (rc *RecordConfig) SetTargetSRVStrings(priority, weight, port, target string) (err error) {
|
|
var i64priority uint64
|
|
if i64priority, err = strconv.ParseUint(priority, 10, 16); err == nil {
|
|
return rc.setTargetSRVIntAndStrings(uint16(i64priority), weight, port, target)
|
|
}
|
|
return errors.Wrap(err, "SRV value too big for uint16")
|
|
}
|
|
|
|
// SetTargetSRVPriorityString is like SetTargetSRV but accepts priority as an
|
|
// uint16 and the rest of the values joined in a string that needs to be parsed.
|
|
// This is a helper function that comes in handy when a provider re-uses the MX preference
|
|
// field as the SRV priority.
|
|
func (rc *RecordConfig) SetTargetSRVPriorityString(priority uint16, s string) error {
|
|
part := strings.Fields(s)
|
|
switch len(part) {
|
|
case 3:
|
|
return rc.setTargetSRVIntAndStrings(priority, part[0], part[1], part[2])
|
|
case 2:
|
|
return rc.setTargetSRVIntAndStrings(priority, part[0], part[1], ".")
|
|
default:
|
|
return errors.Errorf("SRV value does not contain 3 fields: (%#v)", s)
|
|
}
|
|
}
|
|
|
|
// SetTargetSRVString is like SetTargetSRV but accepts one big string to be parsed.
|
|
func (rc *RecordConfig) SetTargetSRVString(s string) error {
|
|
part := strings.Fields(s)
|
|
if len(part) != 4 {
|
|
return errors.Errorf("SRC value does not contain 4 fields: (%#v)", s)
|
|
}
|
|
return rc.SetTargetSRVStrings(part[0], part[1], part[2], part[3])
|
|
}
|