NEW PROVIDER: Tencent Cloud DNS (TENCENTDNS/DNSPOD) provider and registrar#4237
NEW PROVIDER: Tencent Cloud DNS (TENCENTDNS/DNSPOD) provider and registrar#4237cylonchau wants to merge 3 commits into
Conversation
|
Greetings! Thank you for your patience while we migrated to the new GitHub org. Now that the migration is complete, please rebase. Thank you. |
Hi, thanks for the reply. Could you please confirm which branch I should rebase onto? Should I rebase against the latest main branch or is there another target branch I should use? |
Excellent question! Please rebase to main. |
|
@cylonchau I noticed that there are many This error should be properly handled, either with a validator rejecting invalid TTL, or silently rewritten the TTL to the valid value before feed them to |
SukkaW
left a comment
There was a problem hiding this comment.
Handle invalid TTL, either with a validator rejectIf to reject invalid TTL, or silently re-write TTL before feeding records to diff2.
|
Optionally: since #4208 landed before this PR, would you be open to implementing |
906689e to
936b39a
Compare
Thanks your suggestion. dnspod free plan requires a minimum TTL of 600 seconds. if user fill a number less than 600, then notice this message |
Hello friend! I'd like to make a suggestion. This is a common question. Many providers require a minimum TTL or only specific TTL values. The best way to fix this is when converting the RecordConfig to the native record type. In this PR, that means updating You can look at other providers as examples. Most have a function called fixTTL(). |
936b39a to
3332de9
Compare
|
Hi all, thanks for the reviews and helpful suggestions. new submit i am fix some issue and suggestion
Tested with (intl) : Add zone and some recordcreate-zone.js var REG_TENCENT = NewRegistrar("tencentdns");
var DSP_TENCENT = NewDnsProvider("tencentdns");
D("oomkill.net", REG_TENCENT, DnsProvider(DSP_TENCENT),
NAMESERVER("ns1.dnspod.net."),
NAMESERVER("ns2.dnspod.net."),
A("@", "1.2.3.4", TTL(300)),
TXT("txt", "hello")
);preview goldstains@goldsaintsMacBook-Pro dnscontrol % ./dnscontrol preview --config create-zone.js --creds creds.json
CONCURRENTLY checking for 0 zone(s)
SERIALLY checking for 1 zone(s)
Serially checking for zone: "oomkill.net"
******************** Domain: oomkill.net
1 correction (tencentdns)
#1: Ensuring zone "oomkill.net" exists in "tencentdns"
CONCURRENTLY gathering records of 0 zone(s)
SERIALLY gathering records of 1 zone(s)
Serially Gathering: "oomkill.net"
******************** Domain: oomkill.net
1 correction (tencentdns)
INFO#1: Domain "oomkill.net" provider tencentdns Error: [TencentCloudSDKError] Code=InvalidParameterValue.DomainNotExists, Message=当前域名有误,请返回重新操作。, RequestId=0bbf6948-219e-4b74-bb8d-85ca4562826b
#1: Update nameservers fns1.42.pl,fns2.42.pl -> ns1.dnspod.net,ns2.dnspod.net
Done. 2 corrections.
completed with errorspush goldstains@goldsaintsMacBook-Pro dnscontrol % ./dnscontrol push --config create-zone.js --creds creds.json
CONCURRENTLY checking for 0 zone(s)
SERIALLY checking for 1 zone(s)
Serially checking for zone: "oomkill.net"
******************** Domain: oomkill.net
1 correction (tencentdns)
#1: Ensuring zone "oomkill.net" exists in "tencentdns"
SUCCESS!
CONCURRENTLY gathering records of 0 zone(s)
SERIALLY gathering records of 1 zone(s)
Serially Gathering: "oomkill.net"
******************** Domain: oomkill.net
8 corrections (tencentdns)
#1: ± MODIFY-TTL oomkill.net NS ttl=(86400->600) a.dnspod.com.
SUCCESS!
#2: ± MODIFY-TTL oomkill.net NS ttl=(86400->600) b.dnspod.com.
SUCCESS!
#3: ± MODIFY-TTL oomkill.net NS ttl=(86400->600) c.dnspod.com.
SUCCESS!
#4: + CREATE oomkill.net NS ns1.dnspod.net. ttl=600
SUCCESS!
#5: + CREATE oomkill.net NS ns2.dnspod.net. ttl=600
SUCCESS!
#6: + CREATE oomkill.net A 1.2.3.4 ttl=600
SUCCESS!
#7: + CREATE www.oomkill.net CNAME dnscontroltest.com. ttl=600
SUCCESS!
#8: Update nameservers fns1.42.pl,fns2.42.pl -> a.dnspod.com,b.dnspod.com,c.dnspod.com,ns1.dnspod.net,ns2.dnspod.net
SUCCESS!
Done. 9 corrections.
goldstains@goldsaintsMacBook-Pro dnscontrol %
Delete recordgoldstains@goldsaintsMacBook-Pro dnscontrol % ./dnscontrol push --config create-zone.js --creds creds.json
CONCURRENTLY checking for 0 zone(s)
SERIALLY checking for 1 zone(s)
Serially checking for zone: "oomkill.net"
CONCURRENTLY gathering records of 0 zone(s)
SERIALLY gathering records of 1 zone(s)
Serially Gathering: "oomkill.net"
******************** Domain: oomkill.net
3 corrections (tencentdns)
#1: + CREATE txt.oomkill.net TXT "hello" ttl=600
SUCCESS!
#2: - DELETE www.oomkill.net CNAME dnscontroltest.com. ttl=600
SUCCESS!
#3: Update nameservers fns1.42.pl,fns2.42.pl -> a.dnspod.com,b.dnspod.com,c.dnspod.com,ns1.dnspod.net,ns2.dnspod.net
SUCCESS!
Done. 3 corrections.
If user filling TTL less than 600 and is free plan, will get default TTL for tencent cloud API and set to default TTL value (600) func (c *tencentCloudClient) getMinTTL(domainName string) (uint32, error) {
request := dnspod.NewDescribeDomainRequest()
request.Domain = common.StringPtr(domainName)
response, err := c.dnspodClient.DescribeDomain(request)
if err != nil {
return 0, err
}
if response.Response == nil || response.Response.DomainInfo == nil || response.Response.DomainInfo.Grade == nil {
return defaultTTL, nil
}
grade := *response.Response.DomainInfo.Grade
packageRequest := dnspod.NewDescribePackageDetailRequest()
packageResponse, err := c.dnspodClient.DescribePackageDetail(packageRequest)
if err != nil {
return 0, err
}
if packageResponse.Response == nil {
return defaultTTL, nil
}
return minTTLForGrade(grade, packageResponse.Response.Info), nil
}default TTL value const defaultTTL = uint32(600)Change NSThe test domain contains sensitive information, so I have hidden part of it. var REG_TENCENT = NewRegistrar("tencentdns");
D("xxxx.net", REG_TENCENT,
NAMESERVER("dns7.hichina.com."),
NAMESERVER("dns8.hichina.com.")
);preview goldstains@goldsaintsMacBook-Pro dnscontrol % ./dnscontrol preview --config change-ns.js --creds creds.json
CONCURRENTLY checking for 0 zone(s)
SERIALLY checking for 1 zone(s)
Serially checking for zone: "xxxx.net"
CONCURRENTLY gathering records of 0 zone(s)
SERIALLY gathering records of 1 zone(s)
Serially Gathering: "xxxx.net"
******************** Domain: xxxx.net
1 correction (tencentdns)
#1: Update nameservers NANCY.NS.CLOUDFLARE.COM,RUDY.NS.CLOUDFLARE.COM -> dns7.hichina.com,dns8.hichina.com
Done. 1 corrections.push goldstains@goldsaintsMacBook-Pro dnscontrol % ./dnscontrol push --config change-ns-recover.js --creds creds.json --debug
CONCURRENTLY checking for 0 zone(s)
SERIALLY checking for 1 zone(s)
Serially checking for zone: "xxx.net"
CONCURRENTLY gathering records of 0 zone(s)
SERIALLY gathering records of 1 zone(s)
Serially Gathering: "xxx.net"
******************** Domain: xxx.net
1 correction (tencentdns)
#1: Update nameservers dns7.hichina.com,dns8.hichina.com -> a.dnspod.com,b.dnspod.com,c.dnspod.com
SUCCESS!
Done. 1 corrections.
Registrar operations require the correct Tencent Cloud site. Use For example, user will enconter. goldstains@goldsaintsMacBook-Pro dnscontrol % ./dnscontrol push --config change-ns.js --creds creds.json --debug
CONCURRENTLY checking for 0 zone(s)
SERIALLY checking for 1 zone(s)
Serially checking for zone: "xxx.net"
CONCURRENTLY gathering records of 0 zone(s)
SERIALLY gathering records of 1 zone(s)
Serially Gathering: "xxx.net"
******************** Domain: xxx.net
1 correction (tencentdns)
#1: Update nameservers a.dnspod.com,b.dnspod.com,c.dnspod.com -> dns7.hichina.com,dns8.hichina.com
FAILURE! tencent domain batch operation 104311325 failed for xxx.net: 该域名不属于当前账号,无法执行操作
Done. 1 corrections.
completed with errors |
…registrar Add support for Tencent Cloud DNS (encentdns/dnspod) as both DNS provider and registrar using the official Tencent Cloud API 3.0. Features: - DNS Provider: Full CRUD for A, AAAA, CNAME, MX, NS, TXT, CAA, SRV records - Registrar: Nameserver delegation management at the registry level - Apex CNAME support: Seamlessly maps ALIAS records to Tencent's apex CNAME - Zone management: Supports automatic zone creation (EnsureZoneExists) - Zone listing: Supports the get-zones command for easy migration - Incremental updates: Full support for NO_PURGE and IGNORE via diff2 engine Technical details: - Based on tencentcloud-sdk-go (API 3.0) - Implements RecordAuditor to comply with DNSControl v4 requirements - Handles free-tier limitations (TTL minimum 600s) automatically Documentation and CI/CD configuration (GitHub Actions profiles) included.
3332de9 to
a60c2c3
Compare
cafferata
left a comment
There was a problem hiding this comment.
Thanks for addressing the feedback and adding the optional RegisterCredsMetadata()! Two small inline comments, otherwise LGTM from my side.
| providers/unifi @zupolgec | ||
| providers/vercel @SukkaW | ||
| providers/vultr @pgaskin | ||
| providers/tencentdns @cylonchau |
There was a problem hiding this comment.
This entry is appended at the bottom (after vultr), breaking the alphabetical sort. Running generate-all.sh should fix this automatically, or you can move it manually between softlayer and transip.
There was a problem hiding this comment.
Done, has been run to refresh some generated files.
- Implement RegisterCredsMetadata for dnscontrol init - Rewrite low TTLs before diff2 using dnspod package limits - Add cn/intl site selection for dns and registrar API - Poll registrar batch operations and surface failures - Add docs and focused unit tests
a60c2c3 to
cb52553
Compare
|
thanks for @cafferata, The new commit have been fixed, and generate-all.sh has been run to refresh some generated files. |
| if rc.Type == "ALIAS" { | ||
| req.RecordType = new("CNAME") | ||
| } |
There was a problem hiding this comment.
Better add a code comment about why converting ALIAS to CNAME here (ALIAS('@') instead of CNAME('@') for CNAME flattening only).
DNSPod itself doesn't support ALIAS record type in any way, you need to document this.
There was a problem hiding this comment.
Done. I updated the code comment.
| const defaultTTL = uint32(600) | ||
|
|
||
| var features = providers.DocumentationNotes{ | ||
| providers.CanUseAlias: providers.Can(), |
There was a problem hiding this comment.
Better document that canUseALIAs is Can only because this is required to work with CNAME Flattening feature (writing ALIAS('@') instead of CNAME('@')). DNSPods itself doesn't support ALIAS record type at all.
There was a problem hiding this comment.
Done. I updated the CanUseAlias note
There was a problem hiding this comment.
Document how to use ALIAS('@') in the provider docs:
- If you want to add
CNAMEat@ - Configure CNAME flattening at the DNSPod dashboard manually
- Write
ALIAS('@')todnsconfig.js - Explain why write
ALIAS('@'). DNSControl requires this because it considersCNAME('@')invalid. - Under the hood, this provider overwrites
ALIAStoCNAME - Explain that DNSPod doesn't support
ALIASat all, all CNAME flattening configurations must be done via the dashboard for now.
There was a problem hiding this comment.
Done. I updated the docs to clarify how to use ALIAS with the tencentdns provider.
- Add code comments explaining that DNSPod does not support a native ALIAS record - Document how to use ALIAS for DNSPod CNAME flattening.



Summary
Hey! This PR adds support for Tencent Cloud DNS (tencentdns also known as dnspod)for DNS hosting and Tencent Domain for registrar/nameserver management.
Tencent Cloud is one of the major cloud providers in China, and DNSPod is widely used by Chinese users and companies. I also rely on DNSControl in my own projects to manage domain records for real business services, so having native Tencent Cloud support would make DNSControl much more useful for users who need to manage domains across Cloudflare, Tencent Cloud, Aliyun, and other providers in one workflow.
This provider supports both DNS and registrar use cases:
EnsureZoneExistsRecordAuditorThe implementation uses Tencent Cloud's official Go SDK with the modern API 3.0 endpoints:
v20210323(Tencent still continue maintain this sdk, date only a lable, this version is latest)v20180808(Tencent still continue maintain this sdk, date only a lable, this version is latest)Fixes #4171
Test record
add record test
delete record test
add zone test