ClouDNS for libdns
This package implements the libdns interfaces for the ClouDNS HTTP API, allowing you to manage DNS records in ClouDNS-hosted zones:
libdns.RecordGetter— list recordslibdns.RecordAppender— create recordslibdns.RecordSetter— create or update records in placelibdns.RecordDeleter— delete recordslibdns.ZoneLister— list zones
go get github.com/libdns/cloudnsThe provider authenticates with the ClouDNS API using one of the three credential types ClouDNS offers (managed in the ClouDNS control panel under API & Resellers), plus the API password:
| Field | ClouDNS parameter | Description |
|---|---|---|
AuthId |
auth-id |
API user ID |
SubAuthId |
sub-auth-id |
API sub-user ID |
SubAuthUser |
sub-auth-user |
API sub-user name |
AuthPassword |
auth-password |
API password (always required) |
Set exactly one of AuthId, SubAuthId, or SubAuthUser. If more than one is set,
they take precedence in that order.
Upgrading from v1.x — breaking change: the precedence flipped. v1.x releases preferred
SubAuthIdoverAuthIdwhen both were set; this version prefersAuthId. If your configuration sets more than one credential field, remove the ones you do not intend to authenticate with.
Note: ClouDNS restricts API access per API user (allowed IPs, allowed zones). Make sure the API user you use is permitted to manage the zone from the machine running your program.
package main
import (
"context"
"fmt"
"time"
"github.com/libdns/cloudns"
"github.com/libdns/libdns"
)
func main() {
provider := &cloudns.Provider{
AuthId: "your_auth_id",
AuthPassword: "your_auth_password",
}
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
zone := "example.com." // zones are fully qualified, with a trailing dot
// List records.
records, err := provider.GetRecords(ctx, zone)
if err != nil {
panic(err)
}
fmt.Printf("records: %+v\n", records)
// Create a record. Names are relative to the zone; "@" is the apex.
created, err := provider.AppendRecords(ctx, zone, []libdns.Record{
libdns.TXT{
Name: "_acme-challenge",
TTL: 60 * time.Second,
Text: "validation-token",
},
})
if err != nil {
panic(err)
}
fmt.Printf("created: %+v\n", created)
// Update the record in place (SetRecords replaces the whole RRset).
_, err = provider.SetRecords(ctx, zone, []libdns.Record{
libdns.TXT{
Name: "_acme-challenge",
TTL: 60 * time.Second,
Text: "new-validation-token",
},
})
if err != nil {
panic(err)
}
// Clean up. Leaving TTL/data zero-valued deletes regardless of their value.
_, err = provider.DeleteRecords(ctx, zone, []libdns.Record{
libdns.RR{Name: "_acme-challenge", Type: "TXT"},
})
if err != nil {
panic(err)
}
}All fields other than the credentials are optional:
| Field | Default | Description |
|---|---|---|
OperationRetries |
5 |
Max attempts per API call (transient failures only) |
InitialBackoff |
1s |
Delay before the first retry; doubles after each attempt |
MaxBackoff |
30s |
Upper bound for the retry delay |
BaseURL |
https://api.cloudns.net/dns/ |
API endpoint override (mostly for testing) |
HTTPClient |
30s-timeout client | Custom *http.Client for API requests |
Only transient failures are retried: network errors, HTTP 429 (the ClouDNS API is rate-limited to 20 requests/second per IP), and HTTP 5xx. Logical API failures (bad credentials, invalid parameters) fail immediately.
- Record types. A, AAAA, CNAME, MX, NS, SRV, TXT, CAA, HTTPS, and SVCB records
are fully modeled with the corresponding
libdnstypes. Other types supported by ClouDNS (e.g. ALIAS, PTR, SSHFP, NAPTR) are passed through as genericlibdns.RRvalues whoseDatacarries the primary record value. - TTLs. ClouDNS only accepts a fixed set of TTL values (60 to 2592000 seconds). TTLs are rounded up to the nearest accepted value; a zero TTL becomes 60 seconds.
- Apex records. Use
"@"as the record name for the zone apex, per the libdns convention. The provider translates it to the empty host ClouDNS uses on the wire. - Long TXT records. The ClouDNS API returns TXT values longer than 255 bytes as multiple quoted chunks; the provider reassembles them into a single string.
- Atomicity. ClouDNS has no batch or transactional API.
SetRecordsand the other mutating methods apply changes one record at a time and are not atomic; on error, the zone may be left partially modified.SetRecordsattempts every planned operation and returns all errors joined together. - Concurrency. A
Provideris safe for concurrent use:SetRecordsandDeleteRecordsserialize their read-modify-write cycles perProviderinstance, so simultaneous calls see each other's changes. Configuration fields must not be modified after the first method call.
The unit and integration tests run against an in-memory mock of the ClouDNS API and require no credentials:
go test ./...To additionally exercise the live ClouDNS API, provide credentials and a dedicated
test zone via the environment; the live test manages only records named
libdns-test* within that zone:
export CLOUDNS_AUTH_ID="your_auth_id" # or CLOUDNS_SUB_AUTH_ID / CLOUDNS_SUB_AUTH_USER
export CLOUDNS_AUTH_PASSWORD="your_auth_password"
export CLOUDNS_TEST_ZONE="example.com"
go test -run TestLiveAPI ./...This project is licensed under the MIT License. See the LICENSE file for details.