dnsrecords

package
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 12, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

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

View Source
const (
	OutcomeCreated   = "created"
	OutcomeUpdated   = "updated"
	OutcomeUnchanged = "unchanged"
	OutcomeConflict  = "conflict"
)

Outcome values a record plan or apply reports per domain.

Variables

View Source
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.

View Source
var ErrZoneNotFound = errors.New("dnsrecords: no managed zone contains the domain")

ErrZoneNotFound means no zone the provider manages contains the domain.

Functions

func Candidates

func Candidates(domain string) []string

Candidates returns every zone name domain could belong to, longest first, down to two labels (a bare TLD is never a zone).

func MatchZone

func MatchZone(domain string, zones []string) (string, bool)

MatchZone returns the longest zone in zones that contains domain, with a trailing dot, or false when none does.

func RelativeName

func RelativeName(domain, zone string) string

RelativeName is domain's record name inside zone: "@" for the apex.

func TargetFor

func TargetFor(ips []string) (recType, value string, err error)

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

func ValidateTarget(d Desired, provider string) error

ValidateTarget rejects a CNAME at a zone apex for providers that cannot flatten it.

Types

type CloudflareAPI

type CloudflareAPI struct {
	Token   string
	BaseURL string
	HTTP    *http.Client
}

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

func (c *CloudflareAPI) FindZone(ctx context.Context, domain string) (string, error)

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 Desired

type Desired struct {
	Name  string
	Type  string
	Value string
	TTL   time.Duration
}

Desired is the one record a domain should have.

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

func NewCloudflareManager(apiToken string) Manager

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

func NewRoute53Manager(accessKeyID, secretAccessKey, region, hostedZoneID string) Manager

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.

func (ManagerZoneFinder) FindZone

func (f ManagerZoneFinder) FindZone(ctx context.Context, domain string) (string, error)

FindZone tries each candidate from longest to shortest.

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

func PlanRecord(d Desired, existing []libdns.Record, replace bool) Plan

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.

type ZoneFinder

type ZoneFinder interface {
	// FindZone returns the zone with a trailing dot, or ErrZoneNotFound.
	FindZone(ctx context.Context, domain string) (string, error)
}

ZoneFinder resolves the zone a domain's records live in.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL