The runtime now serves gibdns/draft-01 and gibdns/draft-02 from one program and answers each request in its own version, so draft-01 hosts such as gibcert v0.2 are unaffected. - rrset.batch applies several RRset mutations to one zone. Operations share one parse/evaluate path with rrset.patch and rrset.replace. atomic is required; a provider commits all-or-nothing through BatchWriter or applies operations one RRset at a time and stops at the first failure. - BatchReader, BatchWriter, RRsetWrite and BatchOpError let backends read and commit several RRsets in one provider request. - draft-02 capabilities report precondition enforcement levels, features.batch and constraints.maximum_batch_ops. - unsupported_version answers in the newest format and lists every version. - RateLimiter waits on upstream limits only when the delay fits the request deadline and a 30 second budget, otherwise it returns rate_limited. gibdns.ProtocolVersion is replaced by ProtocolDraft01, ProtocolDraft02, LatestVersion and SupportedVersions.
gibdns-go
Go runtime for gibdns provider
programs. It implements the exec-json binding, DNS presentation and equality,
patch/replace semantics, preconditions, and TTL policy so individual DNS
providers can stay small.
This is a library, not a DNS provider you install and run. Operators should install a provider from the catalog and follow Using gibdns. Use this module when writing a new provider.
| Protocol | Status |
|---|---|
gibdns/draft-01 |
Supported |
gibdns/draft-02 |
Supported, including rrset.batch |
The runtime serves every supported protocol identifier from one program. A
response uses the version of the request, so hosts that speak only
gibdns/draft-01 keep working unchanged.
Official providers (Cloudflare, deSEC, Gcore, LuaDNS) are built on this runtime.
Use
package main
import (
"gitfield.org/gibdns/gibdns-go"
"gitfield.org/gibdns/gibdns-go/provider"
)
func main() {
provider.Main(provider.Implementation{
Name: "example-dns",
Version: "1.0.0",
RecordTypes: []string{"TXT", "TLSA", "HTTPS"},
ZoneDiscovery: true,
Preconditions: map[string][]string{
gibdns.MethodRRSetPatch: {gibdns.PreconditionIfRevision, gibdns.PreconditionIfAbsent},
gibdns.MethodRRSetReplace: {gibdns.PreconditionIfRevision, gibdns.PreconditionIfAbsent},
},
NewBackend: func(config map[string]any, secrets map[string]string) (provider.Backend, error) {
return newBackend(config, secrets)
},
})
}
A backend only needs GetRRset and PutRRset. Optional interfaces:
ZoneDiscovererwhenZoneDiscoveryis trueMemberPatcherwhenConcurrentSafePatchis trueBatchReaderto read several RRsets in fewer provider requestsBatchWriterto commit several RRsets in one request; setImplementation.AtomicBatchonly when that commit is all-or-nothing
rrset.batch works for every backend. Without BatchWriter the runtime applies
the operations one RRset at a time, so such a provider reports
features.batch.atomic: false and rejects atomic: true. Set
Implementation.MaxBatchOps to advertise and enforce a size limit.
A provider that waits on an upstream rate limit should use provider.RateLimiter
rather than sleeping on Retry-After: it waits only for short delays that fit
the request deadline and otherwise returns rate_limited with
retry_after_seconds.
Advertise TXT for ACME DNS-01 hosts such as gibcert, and TLSA if the DNS
service can publish DANE records. See the
protocol specification
for the request model.
When a provider is ready, add it to the catalog.
Development
make test
make lint