// Package api speaks the AutoDNS XML gateway that Schlundtech exposes at // gateway.schlundtech.de. It is the only place in this program that performs // HTTP. // // The gateway answers HTTP 200 even when a task fails, so every response is // parsed and judged on result/status/type and result/msg — never on the HTTP // status code. A non-2xx status from this host is an nginx 404 for a wrong // path, not an application error. package api import "encoding/xml" // Request is the AutoDNS request envelope: one auth block plus one or more // task blocks. type Request struct { XMLName xml.Name `xml:"request"` Auth Auth `xml:"auth"` Language string `xml:"language,omitempty"` Task []Task `xml:"task"` } // Auth carries the gateway credentials. Context is the project the records // belong to; for Schlundtech it is 10. type Auth struct { User string `xml:"user"` Password string `xml:"password"` Context string `xml:"context"` // Token is the optional second-factor token, when the account has 2FA on. Token string `xml:"token,omitempty"` } // Task is a single task block. The API is task-specific below the code // element, so only the sub-structures a task can carry are modelled and the // caller populates the one it needs. type Task struct { Code string `xml:"code"` // Zone identifies the zone for a zone info or zone update task. Its Name // is empty for a zone list. Zone *ZoneRef `xml:"zone,omitempty"` // View, Where and Key belong to a list query. View *View `xml:"view,omitempty"` Where *Where `xml:"where,omitempty"` Key []string `xml:"key,omitempty"` // Default is the payload of a zone update. Default *Update `xml:"default,omitempty"` } // ZoneRef names a zone and the name server that serves it. SystemNS is // mandatory on updates — the gateway refuses the task without it. type ZoneRef struct { Name string `xml:"name"` SystemNS string `xml:"system_ns"` VirtualNS string `xml:"virtual_name_server,omitempty"` } // View bounds a list query. type View struct { Offset int `xml:"offset"` Limit int `xml:"limit"` Children int `xml:"children,omitempty"` } // Where filters a list query. type Where struct { Key string `xml:"key"` Operator string `xml:"operator"` Value string `xml:"value"` } // Update is the payload of a zone update. rr_add and rr_rem are repeated // elements: one sibling per record, not one element with children. type Update struct { RRAdd []Record `xml:"rr_add"` RRRem []Record `xml:"rr_rem"` } // Record is one resource record. Name is relative to the zone; the zone apex // is the empty string. type Record struct { Name string `xml:"name"` Type string `xml:"type"` Value string `xml:"value"` TTL int `xml:"ttl,omitempty"` Pref int `xml:"pref,omitempty"` } // Response is the AutoDNS response envelope. Result is repeated because a // multi-zone task answers once per zone. type Response struct { XMLName xml.Name `xml:"response"` Result []Result `xml:"result"` Stid string `xml:"stid"` } // Result is the per-task outcome. type Result struct { Data *Data `xml:"data,omitempty"` Status Status `xml:"status"` Msg []Msg `xml:"msg,omitempty"` } // Status is the overall task status. Type is "success", "error" or // "notification". type Status struct { Code string `xml:"code"` Type string `xml:"type"` Text string `xml:"text"` } // Msg is a system message. On failure this is where the actionable code and // text live; status stays generic (E00000). type Msg struct { Code string `xml:"code"` Type string `xml:"type"` Text string `xml:"text"` Object *Object `xml:"object,omitempty"` } // Object names what a Msg refers to. type Object struct { Type string `xml:"type"` Value string `xml:"value"` } // Data is the payload of an info or list task. type Data struct { Summary int `xml:"summary"` Zone []Zone `xml:"zone"` } // Zone is a DNS zone. The list task returns the summary fields; an info task // additionally returns every record in RRs. type Zone struct { Name string `xml:"name"` Origin string `xml:"origin,omitempty"` SystemNS string `xml:"system_ns"` SOA *SOA `xml:"soa,omitempty"` RRs []Record `xml:"rr"` } // SOA is a zone's start-of-authority record. type SOA struct { TTL int `xml:"ttl,omitempty"` Refresh int `xml:"refresh,omitempty"` Retry int `xml:"retry,omitempty"` Expire int `xml:"expire,omitempty"` Email string `xml:"email,omitempty"` }