Documentation
¶
Overview ¶
Package eurodns is a client for the EuroDNS User REST API (https://docapi.eurodns.com), focused on DNS zone management.
The same client talks either to EuroDNS directly (X-APP-ID / X-API-KEY) or to an eurodns-gate instance (bearer token), through the Authenticator option. All requests go through a shared Transport that enforces the EuroDNS rate limit (10 requests per 10 seconds per source IP).
Index ¶
- Constants
- Variables
- func IsForbidden(err error) bool
- func IsNotFound(err error) bool
- func IsPreconditionFailed(err error) bool
- func IsRateLimited(err error) bool
- type APIError
- type APIKeyAuth
- type AdoptRRset
- type AdoptRequest
- type Authenticator
- type BearerAuth
- type Client
- func (c *Client) AddRecords(ctx context.Context, domain string, recs []Record, opts ...WriteOption) (*Zone, error)
- func (c *Client) Adopt(ctx context.Context, domain string, req AdoptRequest) error
- func (c *Client) CheckZone(ctx context.Context, domain string, z *Zone) (*Zone, error)
- func (c *Client) DeleteRecord(ctx context.Context, domain string, id int64, opts ...WriteOption) (*Zone, error)
- func (c *Client) GateInfo(ctx context.Context) (*GateInfo, error)
- func (c *Client) GetZone(ctx context.Context, domain string) (*Zone, error)
- func (c *Client) ListSnapshots(ctx context.Context, domain string) ([]Snapshot, error)
- func (c *Client) SaveZone(ctx context.Context, domain string, z *Zone, opts ...WriteOption) error
- func (c *Client) Transport() *Transport
- type ErrorItem
- type GateInfo
- type Option
- func WithAuth(a Authenticator) Option
- func WithBaseURL(u string) Option
- func WithHTTPClient(c *http.Client) Option
- func WithMaxRetries(n int) Option
- func WithRateLimit(every time.Duration, burst int) Option
- func WithRetryBackoff(base, max time.Duration) Option
- func WithTransport(t *Transport) Option
- func WithUserAgent(ua string) Option
- type Problem
- type Record
- type RecordError
- type Severity
- type Snapshot
- type StaticToken
- type TokenSource
- type Transport
- type ValidationReport
- type WriteOption
- type Zone
- type ZoneError
Constants ¶
const ( FeatureIfMatch = "if-match" FeatureOwnership = "ownership" FeatureAdopt = "adopt" )
Gate feature names.
const DefaultBaseURL = "https://rest-api.eurodns.com"
DefaultBaseURL is the EuroDNS REST API endpoint.
const GateInfoPath = "/.well-known/eurodns-gate"
GateInfoPath is the extension endpoint served by eurodns-gate only.
Variables ¶
var AllowedTTLs = []int{600, 900, 1800, 3600, 7200, 14400, 21600, 43200, 86400, 172800, 432000, 604800}
AllowedTTLs is the fixed list of TTL values accepted by EuroDNS.
var ErrNotGate = errors.New("eurodns: endpoint is not an eurodns-gate")
ErrNotGate is returned by GateInfo when the endpoint is plain EuroDNS.
Functions ¶
func IsForbidden ¶
func IsNotFound ¶
func IsPreconditionFailed ¶
func IsRateLimited ¶
Types ¶
type APIError ¶
type APIError struct {
StatusCode int
Method string
Path string
Body []byte
Report *ValidationReport // parsed when the body is a zone with a report
Reason string // eurodns-gate error code, e.g. "foreign_rrset", "not_owner", "tainted"
Message string // human-readable message (gate "message" or EuroDNS "title")
Code string // EuroDNS error code, e.g. "FORBIDDEN_ACTION", "INVALID_API_KEY"
Errors []ErrorItem // EuroDNS error list, as returned
}
APIError is returned for non-2xx responses.
type APIKeyAuth ¶
APIKeyAuth authenticates directly against EuroDNS.
type AdoptRRset ¶
AdoptRRset identifies one RRset to adopt.
type AdoptRequest ¶
type AdoptRequest struct {
RRsets []AdoptRRset `json:"rrsets"`
Owner string `json:"owner,omitempty"` // owner team; defaults to the caller's team
}
AdoptRequest is the body of POST /.well-known/eurodns-gate/zones/{domain}/adopt.
type Authenticator ¶
Authenticator sets credentials on an outgoing request.
type BearerAuth ¶
type BearerAuth struct {
Source TokenSource
}
BearerAuth authenticates against eurodns-gate with a bearer token.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a EuroDNS (or eurodns-gate) API client. Safe for concurrent use.
func (*Client) AddRecords ¶
func (c *Client) AddRecords(ctx context.Context, domain string, recs []Record, opts ...WriteOption) (*Zone, error)
AddRecords adds records (POST /dns-zones/{domain}/dns-records).
func (*Client) CheckZone ¶
CheckZone validates a zone without saving it (POST /dns-zones/{domain}/check).
func (*Client) DeleteRecord ¶
func (c *Client) DeleteRecord(ctx context.Context, domain string, id int64, opts ...WriteOption) (*Zone, error)
DeleteRecord deletes one record by id (DELETE /dns-zones/{domain}/dns-records/{id}).
func (*Client) GateInfo ¶
GateInfo queries GateInfoPath. Returns ErrNotGate on 404 (plain EuroDNS). 401, 403 and 405 are also treated as "not a gate": the gate serves this endpoint without authentication.
func (*Client) GetZone ¶
GetZone returns the zone with its records and forwards. ETag is filled when the server returns one.
func (*Client) ListSnapshots ¶
ListSnapshots lists zone snapshots.
type ErrorItem ¶
type ErrorItem struct {
Status string `json:"status"`
Code string `json:"code"`
Title string `json:"title"`
Meta json.RawMessage `json:"meta,omitempty"`
}
ErrorItem is one entry of the EuroDNS error body {"errors":[{"status":"403","code":"FORBIDDEN_ACTION","title":"...","meta":null}]}.
type GateInfo ¶
type GateInfo struct {
Version string `json:"version"`
Features []string `json:"features"` // e.g. "if-match", "ownership", "adopt"
}
GateInfo is returned by an eurodns-gate on GET /.well-known/eurodns-gate.
func (*GateInfo) HasFeature ¶
HasFeature reports whether the gate advertises a feature.
type Option ¶
type Option func(*options)
Option configures a Client.
func WithAuth ¶
func WithAuth(a Authenticator) Option
func WithBaseURL ¶
func WithHTTPClient ¶
func WithMaxRetries ¶
func WithRateLimit ¶
WithRateLimit sets the client-side limiter: one request every `every`, with the given burst. Default: one request per 1.1s, burst 5.
func WithRetryBackoff ¶
WithRetryBackoff sets the retry backoff (exponential with jitter, capped). Defaults to 10s / 2m: EuroDNS extends its ban on every violation during a ban, so retries must wait at least one rate window.
func WithTransport ¶
WithTransport shares an existing Transport (and therefore its rate limiter) between several clients or with a reverse proxy.
func WithUserAgent ¶
type Record ¶
type Record struct {
ID *int64 `json:"id,omitempty"`
Type string `json:"type"`
Host string `json:"host"`
TTL int `json:"ttl"`
RData string `json:"rdata"`
Updated *bool `json:"updated,omitempty"`
Locked *bool `json:"locked,omitempty"`
IsDynDNS *bool `json:"isDynDns,omitempty"`
Proxy string `json:"proxy,omitempty"`
Extra map[string]json.RawMessage `json:"-"`
}
Record mirrors the DnsRecord schema. Unknown fields are kept in Extra and written back unchanged (custom JSON marshalling).
func (Record) MarshalJSON ¶
MarshalJSON writes known fields, then unknown fields kept in Extra.
func (*Record) UnmarshalJSON ¶
UnmarshalJSON reads known fields and keeps unknown ones in Extra.
type RecordError ¶
type RecordError struct {
Messages []string `json:"messages"`
Record *Record `json:"record,omitempty"`
Severity Severity `json:"severity"`
}
RecordError is one entry of ValidationReport.RecordErrors.
type Snapshot ¶
type Snapshot struct {
ID int64 `json:"id"`
CreatedAt string `json:"createdAt"`
ZoneName string `json:"zoneName"`
}
Snapshot mirrors DnsZoneSnapshotItem.
type TokenSource ¶
TokenSource returns a bearer token (OIDC JWT) for eurodns-gate.
type Transport ¶
type Transport struct {
Base http.RoundTripper
// contains filtered or unexported fields
}
Transport is an http.RoundTripper that applies authentication, the shared rate limit (waits, never drops) and retries with backoff on 429/5xx and network errors for idempotent methods. A reverse proxy can use it directly.
func NewTransport ¶
NewTransport builds a Transport from options (WithAuth, WithRateLimit, WithMaxRetries, WithRetryBackoff, WithUserAgent, WithHTTPClient's transport as base).
type ValidationReport ¶
type ValidationReport struct {
IsValid *bool `json:"isValid,omitempty"`
RecordErrors []json.RawMessage `json:"recordErrors,omitempty"`
URLForwardErrors []json.RawMessage `json:"urlForwardErrors,omitempty"`
MailForwardErrors []json.RawMessage `json:"mailForwardErrors,omitempty"`
ZoneErrors []json.RawMessage `json:"zoneErrors,omitempty"`
}
ValidationReport mirrors ZoneValidationReport; error details are kept raw.
func (*ValidationReport) Errors ¶
func (r *ValidationReport) Errors() []Problem
Errors returns only ERROR-severity problems (warnings do not block a save).
func (*ValidationReport) Problems ¶
func (r *ValidationReport) Problems() []Problem
Problems flattens record, zone and forward errors. A zone error naming several records yields one problem per record. Unparseable entries are reported with their raw JSON as message.
func (*ValidationReport) Valid ¶
func (r *ValidationReport) Valid() bool
Valid reports whether the zone can be saved: isValid is not false and no ERROR-severity problem is present.
type WriteOption ¶
type WriteOption func(*writeOptions)
WriteOption configures a write call.
func WithIfMatch ¶
func WithIfMatch(etag string) WriteOption
WithIfMatch sends If-Match. EuroDNS ignores it; eurodns-gate returns 412 when the zone changed since the given ETag.
type Zone ¶
type Zone struct {
Name string `json:"name,omitempty"`
DomainConnect *bool `json:"domainConnect,omitempty"`
Records []Record `json:"records"`
URLForwards []json.RawMessage `json:"urlForwards"`
MailForwards []json.RawMessage `json:"mailForwards"`
Report *ValidationReport `json:"report,omitempty"`
Extra map[string]json.RawMessage `json:"-"`
// ETag is set by GetZone when the server returns one (eurodns-gate does,
// EuroDNS does not). It is never serialized.
ETag string `json:"-"`
}
Zone mirrors the DnsZonePage schema. URL and mail forwards are kept as raw JSON so that a zone read then written back is preserved byte for byte.
func (Zone) MarshalJSON ¶
MarshalJSON writes known fields, then unknown fields kept in Extra. Nil records and forwards are written as empty arrays.
func (*Zone) UnmarshalJSON ¶
UnmarshalJSON reads known fields and keeps unknown ones in Extra.
type ZoneError ¶
type ZoneError struct {
Message string `json:"message"`
Records []Record `json:"records,omitempty"`
URLForwards []json.RawMessage `json:"urlForwards,omitempty"`
MailForwards []json.RawMessage `json:"mailForwards,omitempty"`
Severity Severity `json:"severity"`
}
ZoneError is one entry of ValidationReport.ZoneErrors (conflict between records, e.g. a missing ending dot).
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package eurodnstest provides an in-memory fake of the EuroDNS DNS zone API for tests (records, ids, forwards, check, snapshots, rate limiting).
|
Package eurodnstest provides an in-memory fake of the EuroDNS DNS zone API for tests (records, ids, forwards, check, snapshots, rate limiting). |
|
Package rrset groups EuroDNS records into RRsets (host + type), the unit of ownership in eurodns-gate and of management in the Terraform provider.
|
Package rrset groups EuroDNS records into RRsets (host + type), the unit of ownership in eurodns-gate and of management in the Terraform provider. |
|
Package zonediff computes the RRset-level delta between two zone states.
|
Package zonediff computes the RRset-level delta between two zone states. |