Documentation
¶
Overview ¶
Package dnsrecords builds a provider-agnostic DNS record manager from whichever ACME DNS-01 provider a control plane already has credentials for (Cloudflare or Route53), reusing libdns's own interfaces instead of inventing a second one: github.com/libdns/cloudflare and github.com/libdns/route53, both already a dependency via internal/ingress's Caddy DNS-01 wiring, implement them already.
Index ¶
- Constants
- Variables
- func Candidates(domain string) []string
- func MatchZone(domain string, zones []string) (string, bool)
- func RelativeName(domain, zone string) string
- func TargetFor(ips []string) (recType, value string, err error)
- func ValidateTarget(d Desired, provider string) error
- type CloudflareAPI
- type Desired
- type Manager
- type ManagerZoneFinder
- type Plan
- type ZoneFinder
Constants ¶
const ( OutcomeCreated = "created" OutcomeUpdated = "updated" OutcomeUnchanged = "unchanged" OutcomeConflict = "conflict" )
Outcome values a record plan or apply reports per domain.
Variables ¶
var ErrNoTarget = errors.New("dnsrecords: no public address or CNAME target is known for this server")
ErrNoTarget means neither a public address nor a CNAME target is known.
var ErrZoneNotFound = errors.New("dnsrecords: no managed zone contains the domain")
ErrZoneNotFound means no zone the provider manages contains the domain.
Functions ¶
func Candidates ¶
Candidates returns every zone name domain could belong to, longest first, down to two labels (a bare TLD is never a zone).
func MatchZone ¶
MatchZone returns the longest zone in zones that contains domain, with a trailing dot, or false when none does.
func RelativeName ¶
RelativeName is domain's record name inside zone: "@" for the apex.
func TargetFor ¶
TargetFor picks the record type and value pointing at a server reachable at ips: an A record for the first IPv4 address, else AAAA for the first IPv6 one. ips that are not IP literals are ignored.
func ValidateTarget ¶
ValidateTarget rejects a CNAME at a zone apex for providers that cannot flatten it.
Types ¶
type CloudflareAPI ¶
CloudflareAPI is the few direct Cloudflare calls libdns cannot make: an exact zone lookup and the proxied flag. The token is only ever sent as a bearer header and never appears in an error.
func (*CloudflareAPI) FindZone ¶
FindZone asks Cloudflare for each candidate zone name, longest first.
func (*CloudflareAPI) SetProxied ¶
func (c *CloudflareAPI) SetProxied(ctx context.Context, zone, fqdn, recType, content string, proxied bool) (int, error)
SetProxied sets the proxied flag on the records of recType at fqdn in zone whose content equals content, and returns how many it changed.
type Manager ¶
type Manager interface {
GetRecords(ctx context.Context, zone string) ([]libdns.Record, error)
AppendRecords(ctx context.Context, zone string, recs []libdns.Record) ([]libdns.Record, error)
SetRecords(ctx context.Context, zone string, recs []libdns.Record) ([]libdns.Record, error)
DeleteRecords(ctx context.Context, zone string, recs []libdns.Record) ([]libdns.Record, error)
}
Manager is the subset of libdns's interfaces a DNS records view needs: list, non-destructive add, replace-by-exact-match, and delete. Any provider implementing it already satisfies libdns.RecordGetter, libdns.RecordAppender, libdns.RecordSetter, and libdns.RecordDeleter.
func NewCloudflareManager ¶
NewCloudflareManager wraps github.com/libdns/cloudflare with the same scoped API token (Zone:DNS:Edit) already stored for Cloudflare ACME DNS-01, so records management needs no separate credential.
func NewRoute53Manager ¶
NewRoute53Manager wraps github.com/libdns/route53 with the same IAM access key pair already stored for Route53 ACME DNS-01. Region and hostedZoneID may be empty: the provider resolves them itself the same way it does for DNS-01 (see internal/reconcile/ingress's own use).
type ManagerZoneFinder ¶
type ManagerZoneFinder struct{ Mgr Manager }
ManagerZoneFinder probes candidate zones through a Manager: a zone exists when it lists and its apex SOA is at "@". It is the only option for Route53, which libdns cannot enumerate zones for.
type Plan ¶
type Plan struct {
Outcome string
// Replace holds the existing records an update removes first; for a
// conflict it lists the records that block the create.
Replace []libdns.RR
}
Plan is what applying Desired would do against a zone's existing records.
func PlanRecord ¶
PlanRecord decides how to bring d into existing. An identical record is unchanged even next to siblings; a different A/AAAA/CNAME at the same name is a conflict unless replace is set, and a foreign TXT or MX is never touched.