mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2025-09-04 20:24:23 +08:00
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:
parent
aa0850fbaf
commit
638ee45e6c
3 changed files with 79 additions and 38 deletions
16
integrationTest/integration_test.go
Normal file → Executable file
16
integrationTest/integration_test.go
Normal file → Executable file
|
@ -325,14 +325,14 @@ var tests = []*TestCase{
|
||||||
|
|
||||||
//SRV
|
//SRV
|
||||||
tc("Empty").IfHasCapability(providers.CanUseSRV),
|
tc("Empty").IfHasCapability(providers.CanUseSRV),
|
||||||
tc("SRV record", srv("@", 5, 6, 7, "foo.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("@", 5, 6, 7, "foo.com."), srv("@", 5, 60, 70, "foo2.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("@", 5, 6, 7, "foo.com."), srv("@", 5, 60, 70, "foo2.com."), srv("@", 15, 65, 75, "foo3.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("@", 5, 6, 7, "foo.com."), srv("@", 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("@", 5, 6, 7, "foo.com."), srv("@", 15, 65, 75, "foo4.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("@", 52, 6, 7, "foo.com."), srv("@", 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("@", 52, 62, 7, "foo.com."), srv("@", 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("@", 52, 62, 72, "foo.com."), srv("@", 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
|
//CAA
|
||||||
tc("Empty").IfHasCapability(providers.CanUseCAA),
|
tc("Empty").IfHasCapability(providers.CanUseCAA),
|
||||||
|
|
|
@ -34,7 +34,7 @@ Domain level metadata available:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
providers.RegisterDomainServiceProviderType("CLOUDFLAREAPI", newCloudflare, providers.CanUseAlias)
|
providers.RegisterDomainServiceProviderType("CLOUDFLAREAPI", newCloudflare, providers.CanUseSRV, providers.CanUseAlias)
|
||||||
providers.RegisterCustomRecordType("CF_REDIRECT", "CLOUDFLAREAPI", "")
|
providers.RegisterCustomRecordType("CF_REDIRECT", "CLOUDFLAREAPI", "")
|
||||||
providers.RegisterCustomRecordType("CF_TEMP_REDIRECT", "CLOUDFLAREAPI", "")
|
providers.RegisterCustomRecordType("CF_TEMP_REDIRECT", "CLOUDFLAREAPI", "")
|
||||||
}
|
}
|
||||||
|
@ -321,29 +321,39 @@ func newCloudflare(m map[string]string, metadata json.RawMessage) (providers.DNS
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used on the "existing" records.
|
// 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 {
|
type cfRecord struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Content string `json:"content"`
|
Content string `json:"content"`
|
||||||
Proxiable bool `json:"proxiable"`
|
Proxiable bool `json:"proxiable"`
|
||||||
Proxied bool `json:"proxied"`
|
Proxied bool `json:"proxied"`
|
||||||
TTL uint32 `json:"ttl"`
|
TTL uint32 `json:"ttl"`
|
||||||
Locked bool `json:"locked"`
|
Locked bool `json:"locked"`
|
||||||
ZoneID string `json:"zone_id"`
|
ZoneID string `json:"zone_id"`
|
||||||
ZoneName string `json:"zone_name"`
|
ZoneName string `json:"zone_name"`
|
||||||
CreatedOn time.Time `json:"created_on"`
|
CreatedOn time.Time `json:"created_on"`
|
||||||
ModifiedOn time.Time `json:"modified_on"`
|
ModifiedOn time.Time `json:"modified_on"`
|
||||||
Data interface{} `json:"data"`
|
Data *cfRecData `json:"data"`
|
||||||
Priority uint16 `json:"priority"`
|
Priority uint16 `json:"priority"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cfRecord) toRecord(domain string) *models.RecordConfig {
|
func (c *cfRecord) toRecord(domain string) *models.RecordConfig {
|
||||||
//normalize cname,mx,ns records with dots to be consistent with our config format.
|
//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)
|
c.Content = dnsutil.AddOrigin(c.Content+".", domain)
|
||||||
}
|
}
|
||||||
return &models.RecordConfig{
|
rc := &models.RecordConfig{
|
||||||
NameFQDN: c.Name,
|
NameFQDN: c.Name,
|
||||||
Type: c.Type,
|
Type: c.Type,
|
||||||
Target: c.Content,
|
Target: c.Content,
|
||||||
|
@ -351,6 +361,14 @@ func (c *cfRecord) toRecord(domain string) *models.RecordConfig {
|
||||||
TTL: c.TTL,
|
TTL: c.TTL,
|
||||||
Original: c,
|
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 {
|
func getProxyMetadata(r *models.RecordConfig) map[string]string {
|
||||||
|
|
|
@ -116,13 +116,27 @@ func (c *CloudflareApi) createZone(domainName string) (string, error) {
|
||||||
return id, err
|
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 {
|
func (c *CloudflareApi) createRec(rec *models.RecordConfig, domainID string) []*models.Correction {
|
||||||
type createRecord struct {
|
type createRecord struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Content string `json:"content"`
|
Content string `json:"content"`
|
||||||
TTL uint32 `json:"ttl"`
|
TTL uint32 `json:"ttl"`
|
||||||
Priority uint16 `json:"priority"`
|
Priority uint16 `json:"priority"`
|
||||||
|
Data *cfRecData `json:"data"`
|
||||||
}
|
}
|
||||||
var id string
|
var id string
|
||||||
content := rec.Target
|
content := rec.Target
|
||||||
|
@ -144,6 +158,10 @@ func (c *CloudflareApi) createRec(rec *models.RecordConfig, domainID string) []*
|
||||||
Content: content,
|
Content: content,
|
||||||
Priority: rec.MxPreference,
|
Priority: rec.MxPreference,
|
||||||
}
|
}
|
||||||
|
if rec.Type == "SRV" {
|
||||||
|
cf.Data = cfSrvData(rec)
|
||||||
|
cf.Name = rec.NameFQDN
|
||||||
|
}
|
||||||
endpoint := fmt.Sprintf(recordsURL, domainID)
|
endpoint := fmt.Sprintf(recordsURL, domainID)
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
encoder := json.NewEncoder(buf)
|
encoder := json.NewEncoder(buf)
|
||||||
|
@ -173,15 +191,20 @@ func (c *CloudflareApi) modifyRecord(domainID, recID string, proxied bool, rec *
|
||||||
return fmt.Errorf("Cannot modify record if domain or record id are empty.")
|
return fmt.Errorf("Cannot modify record if domain or record id are empty.")
|
||||||
}
|
}
|
||||||
type record struct {
|
type record struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Proxied bool `json:"proxied"`
|
Proxied bool `json:"proxied"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Content string `json:"content"`
|
Content string `json:"content"`
|
||||||
Priority uint16 `json:"priority"`
|
Priority uint16 `json:"priority"`
|
||||||
TTL uint32 `json:"ttl"`
|
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)
|
endpoint := fmt.Sprintf(singleRecordURL, domainID, recID)
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
encoder := json.NewEncoder(buf)
|
encoder := json.NewEncoder(buf)
|
||||||
|
|
Loading…
Add table
Reference in a new issue