mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2025-01-11 09:59:59 +08:00
e230ade9c2
Signed-off-by: Jakob Ackermann <das7pad@outlook.com>
100 lines
2.5 KiB
Go
100 lines
2.5 KiB
Go
package hetzner
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/StackExchange/dnscontrol/v3/models"
|
|
)
|
|
|
|
type bulkCreateRecordsRequest struct {
|
|
Records []record `json:"records"`
|
|
}
|
|
|
|
type bulkUpdateRecordsRequest struct {
|
|
Records []record `json:"records"`
|
|
}
|
|
|
|
type createZoneRequest struct {
|
|
Name string `json:"name"`
|
|
}
|
|
|
|
type getAllRecordsResponse struct {
|
|
Records []record `json:"records"`
|
|
Meta struct {
|
|
Pagination struct {
|
|
LastPage int `json:"last_page"`
|
|
TotalEntries int `json:"total_entries"`
|
|
} `json:"pagination"`
|
|
} `json:"meta"`
|
|
}
|
|
|
|
type getAllZonesResponse struct {
|
|
Zones []zone `json:"zones"`
|
|
Meta struct {
|
|
Pagination struct {
|
|
LastPage int `json:"last_page"`
|
|
TotalEntries int `json:"total_entries"`
|
|
} `json:"pagination"`
|
|
} `json:"meta"`
|
|
}
|
|
|
|
type record struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
TTL *uint32 `json:"ttl"`
|
|
Type string `json:"type"`
|
|
Value string `json:"value"`
|
|
ZoneID string `json:"zone_id"`
|
|
}
|
|
|
|
type zone struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
NameServers []string `json:"ns"`
|
|
TTL uint32 `json:"ttl"`
|
|
}
|
|
|
|
func fromRecordConfig(in *models.RecordConfig, zone *zone) record {
|
|
r := record{
|
|
Name: in.GetLabel(),
|
|
Type: in.Type,
|
|
Value: in.GetTargetCombined(),
|
|
TTL: &in.TTL,
|
|
ZoneID: zone.ID,
|
|
}
|
|
|
|
if r.Type == "TXT" && len(in.TxtStrings) == 1 {
|
|
// HACK: HETZNER rejects values that fit into 255 bytes w/o quotes,
|
|
// but do not fit w/ added quotes (via GetTargetCombined()).
|
|
// Sending the raw, non-quoted value works for the comprehensive
|
|
// suite of integrations tests.
|
|
// The HETZNER validation does not provide helpful error messages.
|
|
// {"error":{"message":"422 Unprocessable Entity: missing: ; ","code":422}}
|
|
// Last checked: 2023-04-01
|
|
valueNotQuoted := in.TxtStrings[0]
|
|
if len(valueNotQuoted) == 254 || len(valueNotQuoted) == 255 {
|
|
r.Value = valueNotQuoted
|
|
}
|
|
}
|
|
|
|
return r
|
|
}
|
|
|
|
func toRecordConfig(domain string, r *record) (*models.RecordConfig, error) {
|
|
rc := models.RecordConfig{
|
|
Type: r.Type,
|
|
TTL: *r.TTL,
|
|
Original: r,
|
|
}
|
|
rc.SetLabel(r.Name, domain)
|
|
|
|
value := r.Value
|
|
// HACK: Hetzner is inserting a trailing space after multiple, quoted values.
|
|
// NOTE: The actual DNS answer does not contain the space.
|
|
// Last checked: 2023-04-01
|
|
if r.Type == "TXT" && len(value) > 0 && value[len(value)-1] == ' ' {
|
|
// Per RFC 1035 spaces outside quoted values are irrelevant.
|
|
value = strings.TrimRight(value, " ")
|
|
}
|
|
return &rc, rc.PopulateFromString(r.Type, value, domain)
|
|
}
|