diff --git a/internal/dnsclients/cloudflare/response_base.go b/internal/dnsclients/cloudflare/response_base.go new file mode 100644 index 00000000..732c4570 --- /dev/null +++ b/internal/dnsclients/cloudflare/response_base.go @@ -0,0 +1,22 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package cloudflare + +type BaseResponse struct { + Success bool `json:"success"` + Errors []struct { + Code int `json:"code"` + Message string `json:"message"` + } `json:"errors"` +} + +func (this *BaseResponse) IsOk() bool { + return this.Success +} + +func (this *BaseResponse) LastError() (code int, message string) { + if len(this.Errors) == 0 { + return 0, "" + } + return this.Errors[0].Code, this.Errors[0].Message +} diff --git a/internal/dnsclients/cloudflare/response_create_dns_record.go b/internal/dnsclients/cloudflare/response_create_dns_record.go new file mode 100644 index 00000000..9b3dd3a5 --- /dev/null +++ b/internal/dnsclients/cloudflare/response_create_dns_record.go @@ -0,0 +1,7 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package cloudflare + +type CreateDNSRecordResponse struct { + BaseResponse +} diff --git a/internal/dnsclients/cloudflare/response_delete_dns_record.go b/internal/dnsclients/cloudflare/response_delete_dns_record.go new file mode 100644 index 00000000..522391c6 --- /dev/null +++ b/internal/dnsclients/cloudflare/response_delete_dns_record.go @@ -0,0 +1,7 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package cloudflare + +type DeleteDNSRecordResponse struct { + BaseResponse +} diff --git a/internal/dnsclients/cloudflare/response_get_dns_records.go b/internal/dnsclients/cloudflare/response_get_dns_records.go new file mode 100644 index 00000000..8c8e219d --- /dev/null +++ b/internal/dnsclients/cloudflare/response_get_dns_records.go @@ -0,0 +1,17 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package cloudflare + +type GetDNSRecordsResponse struct { + BaseResponse + + Result []struct { + Id string `json:"id"` + Type string `json:"type"` + Name string `json:"name"` + Content string `json:"content"` + Ttl int `json:"ttl"` + ZoneId string `json:"zoneId"` + ZoneName string `json:"zoneName"` + } `json:"result"` +} diff --git a/internal/dnsclients/cloudflare/response_interface.go b/internal/dnsclients/cloudflare/response_interface.go new file mode 100644 index 00000000..5cdad10a --- /dev/null +++ b/internal/dnsclients/cloudflare/response_interface.go @@ -0,0 +1,8 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package cloudflare + +type ResponseInterface interface { + IsOk() bool + LastError() (code int, message string) +} diff --git a/internal/dnsclients/cloudflare/response_update_dns_record.go b/internal/dnsclients/cloudflare/response_update_dns_record.go new file mode 100644 index 00000000..039a3fdf --- /dev/null +++ b/internal/dnsclients/cloudflare/response_update_dns_record.go @@ -0,0 +1,7 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package cloudflare + +type UpdateDNSRecordResponse struct { + BaseResponse +} diff --git a/internal/dnsclients/cloudflare/response_zones.go b/internal/dnsclients/cloudflare/response_zones.go new file mode 100644 index 00000000..f8c4b1b4 --- /dev/null +++ b/internal/dnsclients/cloudflare/response_zones.go @@ -0,0 +1,12 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package cloudflare + +type ZonesResponse struct { + BaseResponse + + Result []struct { + Id string `json:"id"` + Name string `json:"name"` + } `json:"result"` +} diff --git a/internal/dnsclients/provider_alidns.go b/internal/dnsclients/provider_alidns.go index ca21d459..5b8a5c12 100644 --- a/internal/dnsclients/provider_alidns.go +++ b/internal/dnsclients/provider_alidns.go @@ -9,7 +9,7 @@ import ( "strings" ) -// 阿里云服务商 +// AliDNSProvider 阿里云服务商 type AliDNSProvider struct { BaseProvider @@ -17,7 +17,7 @@ type AliDNSProvider struct { accessKeySecret string } -// 认证 +// Auth 认证 func (this *AliDNSProvider) Auth(params maps.Map) error { this.accessKeyId = params.GetString("accessKeyId") this.accessKeySecret = params.GetString("accessKeySecret") @@ -30,7 +30,7 @@ func (this *AliDNSProvider) Auth(params maps.Map) error { return nil } -// 获取域名列表 +// GetRecords 获取域名列表 func (this *AliDNSProvider) GetRecords(domain string) (records []*Record, err error) { pageNumber := 1 size := 100 @@ -70,7 +70,7 @@ func (this *AliDNSProvider) GetRecords(domain string) (records []*Record, err er return } -// 读取域名支持的线路数据 +// GetRoutes 读取域名支持的线路数据 func (this *AliDNSProvider) GetRoutes(domain string) (routes []*Route, err error) { req := alidns.CreateDescribeSupportLinesRequest() req.DomainName = domain @@ -89,7 +89,7 @@ func (this *AliDNSProvider) GetRoutes(domain string) (routes []*Route, err error return } -// 查询单个记录 +// QueryRecord 查询单个记录 func (this *AliDNSProvider) QueryRecord(domain string, name string, recordType RecordType) (*Record, error) { records, err := this.GetRecords(domain) if err != nil { @@ -103,7 +103,7 @@ func (this *AliDNSProvider) QueryRecord(domain string, name string, recordType R return nil, err } -// 设置记录 +// AddRecord 设置记录 func (this *AliDNSProvider) AddRecord(domain string, newRecord *Record) error { req := alidns.CreateAddDomainRecordRequest() req.RR = newRecord.Name @@ -124,7 +124,7 @@ func (this *AliDNSProvider) AddRecord(domain string, newRecord *Record) error { return errors.New(resp.GetHttpContentString()) } -// 修改记录 +// UpdateRecord 修改记录 func (this *AliDNSProvider) UpdateRecord(domain string, record *Record, newRecord *Record) error { req := alidns.CreateUpdateDomainRecordRequest() req.RecordId = record.Id @@ -138,7 +138,7 @@ func (this *AliDNSProvider) UpdateRecord(domain string, record *Record, newRecor return err } -// 删除记录 +// DeleteRecord 删除记录 func (this *AliDNSProvider) DeleteRecord(domain string, record *Record) error { req := alidns.CreateDeleteDomainRecordRequest() req.RecordId = record.Id @@ -148,7 +148,7 @@ func (this *AliDNSProvider) DeleteRecord(domain string, record *Record) error { return err } -// 默认线路 +// DefaultRoute 默认线路 func (this *AliDNSProvider) DefaultRoute() string { return "default" } diff --git a/internal/dnsclients/provider_cloud_flare.go b/internal/dnsclients/provider_cloud_flare.go new file mode 100644 index 00000000..06e65584 --- /dev/null +++ b/internal/dnsclients/provider_cloud_flare.go @@ -0,0 +1,288 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package dnsclients + +import ( + "bytes" + "crypto/tls" + "encoding/json" + "github.com/TeaOSLab/EdgeAPI/internal/dnsclients/cloudflare" + "github.com/TeaOSLab/EdgeAPI/internal/errors" + "github.com/iwind/TeaGo/maps" + "io" + "io/ioutil" + "net/http" + "net/url" + "strconv" + "strings" + "sync" + "time" +) + +const CloudFlareAPIEndpoint = "https://api.cloudflare.com/client/v4/" +const CloudFlareDefaultRoute = "default" + +var cloudFlareHTTPClient = &http.Client{ + Timeout: 10 * time.Second, + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + }, + }, +} + +type CloudFlareProvider struct { + BaseProvider + + apiKey string // API密钥 + email string // 账号邮箱 + + zoneMap map[string]string // domain => zoneId + zoneLocker sync.Mutex +} + +// Auth 认证 +func (this *CloudFlareProvider) Auth(params maps.Map) error { + this.apiKey = params.GetString("apiKey") + if len(this.apiKey) == 0 { + return errors.New("'apiKey' should not be empty") + } + + this.email = params.GetString("email") + if len(this.email) == 0 { + return errors.New("'email' should not be empty") + } + + this.zoneMap = map[string]string{} + + return nil +} + +// GetRecords 获取域名解析记录列表 +func (this *CloudFlareProvider) GetRecords(domain string) (records []*Record, err error) { + zoneId, err := this.findZoneIdWithDomain(domain) + if err != nil { + return nil, err + } + + // 这个页数限制预示着每次最多只能获取 500 * 100 即5万个数据 + for page := 1; page <= 500; page++ { + resp := new(cloudflare.GetDNSRecordsResponse) + err = this.doAPI(http.MethodGet, "zones/"+zoneId+"/dns_records", map[string]string{ + "per_page": "100", + "page": strconv.Itoa(page), + }, nil, resp) + if err != nil { + return nil, err + } + if len(resp.Result) == 0 { + break + } + + for _, record := range resp.Result { + // 修正Record + if record.Type == RecordTypeCName && !strings.HasSuffix(record.Content, ".") { + record.Content += "." + } + + record.Name = strings.TrimSuffix(record.Name, "."+domain) + + records = append(records, &Record{ + Id: record.Id, + Name: record.Name, + Type: record.Type, + Value: record.Content, + Route: CloudFlareDefaultRoute, + }) + } + } + + return +} + +// GetRoutes 读取域名支持的线路数据 +func (this *CloudFlareProvider) GetRoutes(domain string) (routes []*Route, err error) { + routes = []*Route{ + {Name: "默认", Code: CloudFlareDefaultRoute}, + } + return +} + +// QueryRecord 查询单个记录 +func (this *CloudFlareProvider) QueryRecord(domain string, name string, recordType RecordType) (*Record, error) { + zoneId, err := this.findZoneIdWithDomain(domain) + if err != nil { + return nil, err + } + + resp := new(cloudflare.GetDNSRecordsResponse) + err = this.doAPI(http.MethodGet, "zones/"+zoneId+"/dns_records", map[string]string{ + "per_page": "100", + "name": name + "." + domain, + "type": recordType, + }, nil, resp) + if err != nil { + return nil, err + } + if len(resp.Result) == 0 { + return nil, nil + } + + record := resp.Result[0] + + // 修正Record + if record.Type == RecordTypeCName && !strings.HasSuffix(record.Content, ".") { + record.Content += "." + } + + record.Name = strings.TrimSuffix(record.Name, "."+domain) + + return &Record{ + Id: record.Id, + Name: record.Name, + Type: record.Type, + Value: record.Content, + Route: CloudFlareDefaultRoute, + }, nil +} + +// AddRecord 设置记录 +func (this *CloudFlareProvider) AddRecord(domain string, newRecord *Record) error { + zoneId, err := this.findZoneIdWithDomain(domain) + if err != nil { + return err + } + + resp := new(cloudflare.CreateDNSRecordResponse) + err = this.doAPI(http.MethodPost, "zones/"+zoneId+"/dns_records", nil, maps.Map{ + "type": newRecord.Type, + "name": newRecord.Name + "." + domain, + "content": newRecord.Value, + "ttl": 1, + }, resp) + if err != nil { + return err + } + return nil +} + +// UpdateRecord 修改记录 +func (this *CloudFlareProvider) UpdateRecord(domain string, record *Record, newRecord *Record) error { + zoneId, err := this.findZoneIdWithDomain(domain) + if err != nil { + return err + } + + resp := new(cloudflare.UpdateDNSRecordResponse) + return this.doAPI(http.MethodPut, "zones/"+zoneId+"/dns_records/"+record.Id, nil, maps.Map{ + "type": newRecord.Type, + "name": newRecord.Name + "." + domain, + "content": newRecord.Value, + "ttl": 1, + }, resp) +} + +// DeleteRecord 删除记录 +func (this *CloudFlareProvider) DeleteRecord(domain string, record *Record) error { + zoneId, err := this.findZoneIdWithDomain(domain) + if err != nil { + return err + } + + resp := new(cloudflare.DeleteDNSRecordResponse) + err = this.doAPI(http.MethodDelete, "zones/"+zoneId+"/dns_records/"+record.Id, map[string]string{}, nil, resp) + if err != nil { + return err + } + return nil +} + +// DefaultRoute 默认线路 +func (this *CloudFlareProvider) DefaultRoute() string { + return CloudFlareDefaultRoute +} + +// 执行API +func (this *CloudFlareProvider) doAPI(method string, apiPath string, args map[string]string, bodyMap maps.Map, respPtr cloudflare.ResponseInterface) error { + apiURL := CloudFlareAPIEndpoint + strings.TrimLeft(apiPath, "/") + if len(args) > 0 { + apiURL += "?" + argStrings := []string{} + for k, v := range args { + argStrings = append(argStrings, k+"="+url.QueryEscape(v)) + } + apiURL += strings.Join(argStrings, "&") + } + method = strings.ToUpper(method) + + var bodyReader io.Reader = nil + if bodyMap != nil { + bodyData, err := json.Marshal(bodyMap) + if err != nil { + return err + } + bodyReader = bytes.NewReader(bodyData) + } + + req, err := http.NewRequest(method, apiURL, bodyReader) + if err != nil { + return err + } + req.Header.Set("Content-Type", "application/json") + req.Header.Set("X-Auth-Key", this.apiKey) + req.Header.Set("x-Auth-Email", this.email) + resp, err := cloudFlareHTTPClient.Do(req) + if err != nil { + return err + } + defer func() { + _ = resp.Body.Close() + }() + + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return err + } + + if resp.StatusCode == 0 { + return errors.New("invalid response status '" + strconv.Itoa(resp.StatusCode) + "', response '" + string(data) + "'") + } + + err = json.Unmarshal(data, respPtr) + if err != nil { + return err + } + + if resp.StatusCode != http.StatusOK { + return errors.New("response error: " + string(data)) + } + + return nil +} + +// 列出一个域名对应的区域 +func (this *CloudFlareProvider) findZoneIdWithDomain(domain string) (zoneId string, err error) { + this.zoneLocker.Lock() + cacheZonedId, ok := this.zoneMap[domain] + if ok { + this.zoneLocker.Unlock() + return cacheZonedId, nil + } + this.zoneLocker.Unlock() + + resp := new(cloudflare.ZonesResponse) + err = this.doAPI(http.MethodGet, "zones", map[string]string{ + "name": domain, + }, nil, resp) + if err != nil { + return "", err + } + if len(resp.Result) == 0 { + return "", errors.New("can not found zone for domain '" + domain + "'") + } + zoneId = resp.Result[0].Id + this.zoneLocker.Lock() + this.zoneMap[domain] = zoneId + this.zoneLocker.Unlock() + return zoneId, nil +} diff --git a/internal/dnsclients/provider_cloud_flare_test.go b/internal/dnsclients/provider_cloud_flare_test.go new file mode 100644 index 00000000..2669f297 --- /dev/null +++ b/internal/dnsclients/provider_cloud_flare_test.go @@ -0,0 +1,167 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package dnsclients + +import ( + "encoding/json" + "github.com/TeaOSLab/EdgeAPI/internal/errors" + "github.com/iwind/TeaGo/dbs" + "github.com/iwind/TeaGo/logs" + "github.com/iwind/TeaGo/maps" + "testing" +) + +func TestCloudFlareProvider_GetRecords(t *testing.T) { + provider, err := testCloudFlareProvider() + if err != nil { + t.Fatal(err) + } + t.Log("===meloy.cn===") + { + records, err := provider.GetRecords("meloy.cn") + if err != nil { + t.Fatal(err) + } + if len(records) > 0 { + t.Log(len(records), "records") + } + logs.PrintAsJSON(records, t) + } + + t.Log("===teaos.cn===") + { + records, err := provider.GetRecords("teaos.cn") + if err != nil { + t.Fatal(err) + } + logs.PrintAsJSON(records, t) + } +} + +func TestCloudFlareProvider_QueryRecord(t *testing.T) { + provider, err := testCloudFlareProvider() + if err != nil { + t.Fatal(err) + } + { + t.Log("== www.meloy.cn/A ==") + record, err := provider.QueryRecord("meloy.cn", "www", RecordTypeA) + if err != nil { + t.Fatal(err) + } + logs.PrintAsJSON(record, t) + } + { + t.Log("== www.meloy.cn/CNAME ==") + record, err := provider.QueryRecord("meloy.cn", "www", RecordTypeCName) + if err != nil { + t.Fatal(err) + } + logs.PrintAsJSON(record, t) + } + { + t.Log("== hello.meloy.cn ==") + record, err := provider.QueryRecord("meloy.cn", "hello", RecordTypeA) + if err != nil { + t.Fatal(err) + } + logs.PrintAsJSON(record, t) + } + { + t.Log("== test.meloy.cn ==") + record, err := provider.QueryRecord("meloy.cn", "test", RecordTypeCName) + if err != nil { + t.Fatal(err) + } + logs.PrintAsJSON(record, t) + } +} + +func TestCloudFlareProvider_AddRecord(t *testing.T) { + provider, err := testCloudFlareProvider() + if err != nil { + t.Fatal(err) + } + { + err = provider.AddRecord("meloy.cn", &Record{ + Id: "", + Name: "test", + Type: RecordTypeA, + Value: "182.92.212.46", + Route: "", + }) + if err != nil { + t.Fatal(err) + } + } + { + err = provider.AddRecord("meloy.cn", &Record{ + Id: "", + Name: "test1", + Type: RecordTypeCName, + Value: "cdn.meloy.cn.", + Route: "", + }) + if err != nil { + t.Fatal(err) + } + } + t.Log("ok") +} + +func TestCloudFlareProvider_UpdateRecord(t *testing.T) { + provider, err := testCloudFlareProvider() + if err != nil { + t.Fatal(err) + } + err = provider.UpdateRecord("meloy.cn", &Record{Id: "b4da7ad9f90173ec37c80ba6bb70641a"}, &Record{ + Id: "", + Name: "test1", + Type: RecordTypeCName, + Value: "cdn123.meloy.cn.", + Route: "", + }) + if err != nil { + t.Fatal(err) + } + t.Log("ok") +} + +func TestCloudFlareProvider_DeleteRecord(t *testing.T) { + provider, err := testCloudFlareProvider() + if err != nil { + t.Fatal(err) + } + err = provider.DeleteRecord("meloy.cn", &Record{ + Id: "86282d89bbd1f66a69ca409da84f34b1", + }) + if err != nil { + t.Fatal(err) + } + t.Log("ok") +} + +func testCloudFlareProvider() (ProviderInterface, error) { + db, err := dbs.Default() + if err != nil { + return nil, err + } + one, err := db.FindOne("SELECT * FROM edgeDNSProviders WHERE type='cloudFlare' ORDER BY id DESC") + if err != nil { + return nil, err + } + if one == nil { + return nil, errors.New("can not find providers with type 'cloudFlare'") + } + apiParams := maps.Map{} + err = json.Unmarshal([]byte(one.GetString("apiParams")), &apiParams) + if err != nil { + return nil, err + } + provider := &CloudFlareProvider{} + err = provider.Auth(apiParams) + if err != nil { + return nil, err + } + return provider, nil +} diff --git a/internal/dnsclients/provider_custom_http.go b/internal/dnsclients/provider_custom_http.go index ef40e28d..2731f30e 100644 --- a/internal/dnsclients/provider_custom_http.go +++ b/internal/dnsclients/provider_custom_http.go @@ -24,13 +24,13 @@ var customHTTPClient = &http.Client{ }, } -// HTTP自定义DNS +// CustomHTTPProvider HTTP自定义DNS type CustomHTTPProvider struct { url string secret string } -// 认证 +// Auth 认证 // 参数: // - url // - secret @@ -48,7 +48,7 @@ func (this *CustomHTTPProvider) Auth(params maps.Map) error { return nil } -// 获取域名解析记录列表 +// GetRecords 获取域名解析记录列表 func (this *CustomHTTPProvider) GetRecords(domain string) (records []*Record, err error) { resp, err := this.post(maps.Map{ "action": "GetRecords", @@ -61,7 +61,7 @@ func (this *CustomHTTPProvider) GetRecords(domain string) (records []*Record, er return } -// 读取域名支持的线路数据 +// GetRoutes 读取域名支持的线路数据 func (this *CustomHTTPProvider) GetRoutes(domain string) (routes []*Route, err error) { resp, err := this.post(maps.Map{ "action": "GetRoutes", @@ -74,7 +74,7 @@ func (this *CustomHTTPProvider) GetRoutes(domain string) (routes []*Route, err e return } -// 查询单个记录 +// QueryRecord 查询单个记录 func (this *CustomHTTPProvider) QueryRecord(domain string, name string, recordType RecordType) (*Record, error) { resp, err := this.post(maps.Map{ "action": "QueryRecord", @@ -99,7 +99,7 @@ func (this *CustomHTTPProvider) QueryRecord(domain string, name string, recordTy return record, nil } -// 设置记录 +// AddRecord 设置记录 func (this *CustomHTTPProvider) AddRecord(domain string, newRecord *Record) error { _, err := this.post(maps.Map{ "action": "AddRecord", @@ -109,7 +109,7 @@ func (this *CustomHTTPProvider) AddRecord(domain string, newRecord *Record) erro return err } -// 修改记录 +// UpdateRecord 修改记录 func (this *CustomHTTPProvider) UpdateRecord(domain string, record *Record, newRecord *Record) error { _, err := this.post(maps.Map{ "action": "UpdateRecord", @@ -120,7 +120,7 @@ func (this *CustomHTTPProvider) UpdateRecord(domain string, record *Record, newR return err } -// 删除记录 +// DeleteRecord 删除记录 func (this *CustomHTTPProvider) DeleteRecord(domain string, record *Record) error { _, err := this.post(maps.Map{ "action": "DeleteRecord", @@ -130,7 +130,7 @@ func (this *CustomHTTPProvider) DeleteRecord(domain string, record *Record) erro return err } -// 默认线路 +// DefaultRoute 默认线路 func (this *CustomHTTPProvider) DefaultRoute() string { resp, err := this.post(maps.Map{ "action": "DefaultRoute", diff --git a/internal/dnsclients/provider_dnspod.go b/internal/dnsclients/provider_dnspod.go index 23e0e54f..32a32c65 100644 --- a/internal/dnsclients/provider_dnspod.go +++ b/internal/dnsclients/provider_dnspod.go @@ -12,7 +12,7 @@ import ( "strings" ) -// DNSPod服务商 +// DNSPodProvider DNSPod服务商 type DNSPodProvider struct { BaseProvider @@ -20,7 +20,7 @@ type DNSPodProvider struct { apiToken string } -// 认证 +// Auth 认证 func (this *DNSPodProvider) Auth(params maps.Map) error { this.apiId = params.GetString("id") this.apiToken = params.GetString("token") @@ -34,7 +34,7 @@ func (this *DNSPodProvider) Auth(params maps.Map) error { return nil } -// 获取域名列表 +// GetRecords 获取域名列表 func (this *DNSPodProvider) GetRecords(domain string) (records []*Record, err error) { offset := 0 size := 100 @@ -72,7 +72,7 @@ func (this *DNSPodProvider) GetRecords(domain string) (records []*Record, err er return } -// 读取线路数据 +// GetRoutes 读取线路数据 func (this *DNSPodProvider) GetRoutes(domain string) (routes []*Route, err error) { infoResp, err := this.post("/Domain.info", map[string]string{ "domain": domain, @@ -106,7 +106,7 @@ func (this *DNSPodProvider) GetRoutes(domain string) (routes []*Route, err error return routes, nil } -// 查询单个记录 +// QueryRecord 查询单个记录 func (this *DNSPodProvider) QueryRecord(domain string, name string, recordType RecordType) (*Record, error) { records, err := this.GetRecords(domain) if err != nil { @@ -120,7 +120,7 @@ func (this *DNSPodProvider) QueryRecord(domain string, name string, recordType R return nil, err } -// 设置记录 +// AddRecord 设置记录 func (this *DNSPodProvider) AddRecord(domain string, newRecord *Record) error { if newRecord == nil { return errors.New("invalid new record") @@ -140,7 +140,7 @@ func (this *DNSPodProvider) AddRecord(domain string, newRecord *Record) error { return err } -// 修改记录 +// UpdateRecord 修改记录 func (this *DNSPodProvider) UpdateRecord(domain string, record *Record, newRecord *Record) error { if record == nil { return errors.New("invalid record") @@ -164,7 +164,7 @@ func (this *DNSPodProvider) UpdateRecord(domain string, record *Record, newRecor return err } -// 删除记录 +// DeleteRecord 删除记录 func (this *DNSPodProvider) DeleteRecord(domain string, record *Record) error { if record == nil { return errors.New("invalid record to delete") @@ -223,7 +223,7 @@ func (this *DNSPodProvider) post(path string, params map[string]string) (maps.Ma return m, nil } -// 默认线路 +// DefaultRoute 默认线路 func (this *DNSPodProvider) DefaultRoute() string { return "默认" } diff --git a/internal/dnsclients/provider_interface.go b/internal/dnsclients/provider_interface.go index 6afe0622..b96ec673 100644 --- a/internal/dnsclients/provider_interface.go +++ b/internal/dnsclients/provider_interface.go @@ -2,29 +2,29 @@ package dnsclients import "github.com/iwind/TeaGo/maps" -// DNS操作接口 +// ProviderInterface DNS操作接口 type ProviderInterface interface { - // 认证 + // Auth 认证 Auth(params maps.Map) error - // 获取域名解析记录列表 + // GetRecords 获取域名解析记录列表 GetRecords(domain string) (records []*Record, err error) - // 读取域名支持的线路数据 + // GetRoutes 读取域名支持的线路数据 GetRoutes(domain string) (routes []*Route, err error) - // 查询单个记录 + // QueryRecord 查询单个记录 QueryRecord(domain string, name string, recordType RecordType) (*Record, error) - // 设置记录 + // AddRecord 设置记录 AddRecord(domain string, newRecord *Record) error - // 修改记录 + // UpdateRecord 修改记录 UpdateRecord(domain string, record *Record, newRecord *Record) error - // 删除记录 + // DeleteRecord 删除记录 DeleteRecord(domain string, record *Record) error - // 默认线路 + // DefaultRoute 默认线路 DefaultRoute() string } diff --git a/internal/dnsclients/route.go b/internal/dnsclients/route.go index 0520acb3..d494ef6a 100644 --- a/internal/dnsclients/route.go +++ b/internal/dnsclients/route.go @@ -1,6 +1,6 @@ package dnsclients -// 线路描述 +// Route 线路描述 type Route struct { Name string `json:"name"` Code string `json:"code"` diff --git a/internal/dnsclients/types.go b/internal/dnsclients/types.go index da445a3f..970d6535 100644 --- a/internal/dnsclients/types.go +++ b/internal/dnsclients/types.go @@ -9,10 +9,11 @@ const ( ProviderTypeDNSPod ProviderType = "dnspod" ProviderTypeAliDNS ProviderType = "alidns" ProviderTypeDNSCom ProviderType = "dnscom" + ProviderTypeCloudFlare ProviderType = "cloudFlare" ProviderTypeCustomHTTP ProviderType = "customHTTP" ) -// 所有的服务商类型 +// AllProviderTypes 所有的服务商类型 var AllProviderTypes = []maps.Map{ { "name": "阿里云DNS", @@ -26,26 +27,32 @@ var AllProviderTypes = []maps.Map{ "name": "帝恩思DNS.COM", "code": ProviderTypeDNSCom, },**/ + { + "name": "CloudFlare DNS", + "code": ProviderTypeCloudFlare, + }, { "name": "自定义HTTP DNS", "code": ProviderTypeCustomHTTP, }, } -// 查找服务商实例 +// FindProvider 查找服务商实例 func FindProvider(providerType ProviderType) ProviderInterface { switch providerType { case ProviderTypeDNSPod: return &DNSPodProvider{} case ProviderTypeAliDNS: return &AliDNSProvider{} + case ProviderTypeCloudFlare: + return &CloudFlareProvider{} case ProviderTypeCustomHTTP: return &CustomHTTPProvider{} } return nil } -// 查找服务商名称 +// FindProviderTypeName 查找服务商名称 func FindProviderTypeName(providerType ProviderType) string { for _, t := range AllProviderTypes { if t.GetString("code") == providerType {