Implement SRV support for CloudFlare provider (#174)

* Implement SRV support for CloudFlare provider
* go fmt
* Use valid SRV names in SRV tests
This commit is contained in:
PJ Eby 2017-08-10 16:02:06 -04:00 committed by Tom Limoncelli
parent aa0850fbaf
commit 638ee45e6c
3 changed files with 79 additions and 38 deletions

16
integrationTest/integration_test.go Normal file → Executable file
View file

@ -325,14 +325,14 @@ var tests = []*TestCase{
//SRV
tc("Empty").IfHasCapability(providers.CanUseSRV),
tc("SRV record", srv("@", 5, 6, 7, "foo.com.")).IfHasCapability(providers.CanUseSRV),
tc("Second SRV record, same prio", srv("@", 5, 6, 7, "foo.com."), srv("@", 5, 60, 70, "foo2.com.")).IfHasCapability(providers.CanUseSRV),
tc("3 SRV", srv("@", 5, 6, 7, "foo.com."), srv("@", 5, 60, 70, "foo2.com."), srv("@", 15, 65, 75, "foo3.com.")).IfHasCapability(providers.CanUseSRV),
tc("Delete one", srv("@", 5, 6, 7, "foo.com."), srv("@", 15, 65, 75, "foo3.com.")).IfHasCapability(providers.CanUseSRV),
tc("Change Target", srv("@", 5, 6, 7, "foo.com."), srv("@", 15, 65, 75, "foo4.com.")).IfHasCapability(providers.CanUseSRV),
tc("Change Priority", srv("@", 52, 6, 7, "foo.com."), srv("@", 15, 65, 75, "foo4.com.")).IfHasCapability(providers.CanUseSRV),
tc("Change Weight", srv("@", 52, 62, 7, "foo.com."), srv("@", 15, 65, 75, "foo4.com.")).IfHasCapability(providers.CanUseSRV),
tc("Change Port", srv("@", 52, 62, 72, "foo.com."), srv("@", 15, 65, 75, "foo4.com.")).IfHasCapability(providers.CanUseSRV),
tc("SRV record", srv("_service._protocol", 5, 6, 7, "foo.com.")).IfHasCapability(providers.CanUseSRV),
tc("Second SRV record, same prio", srv("_service._protocol", 5, 6, 7, "foo.com."), srv("_service._protocol", 5, 60, 70, "foo2.com.")).IfHasCapability(providers.CanUseSRV),
tc("3 SRV", srv("_service._protocol", 5, 6, 7, "foo.com."), srv("_service._protocol", 5, 60, 70, "foo2.com."), srv("_service._protocol", 15, 65, 75, "foo3.com.")).IfHasCapability(providers.CanUseSRV),
tc("Delete one", srv("_service._protocol", 5, 6, 7, "foo.com."), srv("_service._protocol", 15, 65, 75, "foo3.com.")).IfHasCapability(providers.CanUseSRV),
tc("Change Target", srv("_service._protocol", 5, 6, 7, "foo.com."), srv("_service._protocol", 15, 65, 75, "foo4.com.")).IfHasCapability(providers.CanUseSRV),
tc("Change Priority", srv("_service._protocol", 52, 6, 7, "foo.com."), srv("_service._protocol", 15, 65, 75, "foo4.com.")).IfHasCapability(providers.CanUseSRV),
tc("Change Weight", srv("_service._protocol", 52, 62, 7, "foo.com."), srv("_service._protocol", 15, 65, 75, "foo4.com.")).IfHasCapability(providers.CanUseSRV),
tc("Change Port", srv("_service._protocol", 52, 62, 72, "foo.com."), srv("_service._protocol", 15, 65, 75, "foo4.com.")).IfHasCapability(providers.CanUseSRV),
//CAA
tc("Empty").IfHasCapability(providers.CanUseCAA),

View file

@ -34,7 +34,7 @@ Domain level metadata available:
*/
func init() {
providers.RegisterDomainServiceProviderType("CLOUDFLAREAPI", newCloudflare, providers.CanUseAlias)
providers.RegisterDomainServiceProviderType("CLOUDFLAREAPI", newCloudflare, providers.CanUseSRV, providers.CanUseAlias)
providers.RegisterCustomRecordType("CF_REDIRECT", "CLOUDFLAREAPI", "")
providers.RegisterCustomRecordType("CF_TEMP_REDIRECT", "CLOUDFLAREAPI", "")
}
@ -321,6 +321,16 @@ func newCloudflare(m map[string]string, metadata json.RawMessage) (providers.DNS
}
// Used on the "existing" records.
type cfRecData struct {
Service string `json:"service"`
Proto string `json:"proto"`
Name string `json:"name"`
Priority uint16 `json:"priority"`
Weight uint16 `json:"weight"`
Port uint16 `json:"port"`
Target string `json:"target"`
}
type cfRecord struct {
ID string `json:"id"`
Type string `json:"type"`
@ -334,16 +344,16 @@ type cfRecord struct {
ZoneName string `json:"zone_name"`
CreatedOn time.Time `json:"created_on"`
ModifiedOn time.Time `json:"modified_on"`
Data interface{} `json:"data"`
Data *cfRecData `json:"data"`
Priority uint16 `json:"priority"`
}
func (c *cfRecord) toRecord(domain string) *models.RecordConfig {
//normalize cname,mx,ns records with dots to be consistent with our config format.
if c.Type == "CNAME" || c.Type == "MX" || c.Type == "NS" {
if c.Type == "CNAME" || c.Type == "MX" || c.Type == "NS" || c.Type == "SRV" {
c.Content = dnsutil.AddOrigin(c.Content+".", domain)
}
return &models.RecordConfig{
rc := &models.RecordConfig{
NameFQDN: c.Name,
Type: c.Type,
Target: c.Content,
@ -351,6 +361,14 @@ func (c *cfRecord) toRecord(domain string) *models.RecordConfig {
TTL: c.TTL,
Original: c,
}
if c.Type == "SRV" {
data := *c.Data
rc.SrvPriority = data.Priority
rc.SrvWeight = data.Weight
rc.SrvPort = data.Port
rc.Target = dnsutil.AddOrigin(data.Target+".", domain)
}
return rc
}
func getProxyMetadata(r *models.RecordConfig) map[string]string {

View file

@ -116,6 +116,19 @@ func (c *CloudflareApi) createZone(domainName string) (string, error) {
return id, err
}
func cfSrvData(rec *models.RecordConfig) *cfRecData {
serverParts := strings.Split(rec.NameFQDN, ".")
return &cfRecData{
Service: serverParts[0],
Proto: serverParts[1],
Name: strings.Join(serverParts[2:], "."),
Port: rec.SrvPort,
Priority: rec.SrvPriority,
Weight: rec.SrvWeight,
Target: rec.Target,
}
}
func (c *CloudflareApi) createRec(rec *models.RecordConfig, domainID string) []*models.Correction {
type createRecord struct {
Name string `json:"name"`
@ -123,6 +136,7 @@ func (c *CloudflareApi) createRec(rec *models.RecordConfig, domainID string) []*
Content string `json:"content"`
TTL uint32 `json:"ttl"`
Priority uint16 `json:"priority"`
Data *cfRecData `json:"data"`
}
var id string
content := rec.Target
@ -144,6 +158,10 @@ func (c *CloudflareApi) createRec(rec *models.RecordConfig, domainID string) []*
Content: content,
Priority: rec.MxPreference,
}
if rec.Type == "SRV" {
cf.Data = cfSrvData(rec)
cf.Name = rec.NameFQDN
}
endpoint := fmt.Sprintf(recordsURL, domainID)
buf := &bytes.Buffer{}
encoder := json.NewEncoder(buf)
@ -180,8 +198,13 @@ func (c *CloudflareApi) modifyRecord(domainID, recID string, proxied bool, rec *
Content string `json:"content"`
Priority uint16 `json:"priority"`
TTL uint32 `json:"ttl"`
Data *cfRecData `json:"data"`
}
r := record{recID, proxied, rec.Name, rec.Type, rec.Target, rec.MxPreference, rec.TTL, nil}
if rec.Type == "SRV" {
r.Data = cfSrvData(rec)
r.Name = rec.NameFQDN
}
r := record{recID, proxied, rec.Name, rec.Type, rec.Target, rec.MxPreference, rec.TTL}
endpoint := fmt.Sprintf(singleRecordURL, domainID, recID)
buf := &bytes.Buffer{}
encoder := json.NewEncoder(buf)