lego/providers/dns/hostingde/client.go

144 lines
4.5 KiB
Go
Raw Normal View History

2018-09-15 21:25:14 +00:00
package hostingde
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
)
const defaultBaseURL = "https://secure.hosting.de/api/dns/v1/json"
2018-09-15 21:25:14 +00:00
// RecordsAddRequest represents a DNS record to add
type RecordsAddRequest struct {
Name string `json:"name"`
Type string `json:"type"`
Content string `json:"content"`
TTL int `json:"ttl"`
}
// RecordsDeleteRequest represents a DNS record to remove
type RecordsDeleteRequest struct {
Name string `json:"name"`
Type string `json:"type"`
Content string `json:"content"`
ID string `json:"id"`
}
// ZoneConfigObject represents the ZoneConfig-section of a hosting.de API response.
type ZoneConfigObject struct {
AccountID string `json:"accountId"`
EmailAddress string `json:"emailAddress"`
ID string `json:"id"`
LastChangeDate string `json:"lastChangeDate"`
MasterIP string `json:"masterIp"`
Name string `json:"name"`
NameUnicode string `json:"nameUnicode"`
SOAValues struct {
Expire int `json:"expire"`
NegativeTTL int `json:"negativeTtl"`
Refresh int `json:"refresh"`
Retry int `json:"retry"`
Serial string `json:"serial"`
TTL int `json:"ttl"`
} `json:"soaValues"`
Status string `json:"status"`
TemplateValues string `json:"templateValues"`
Type string `json:"type"`
ZoneTransferWhitelist []string `json:"zoneTransferWhitelist"`
}
// ZoneUpdateError represents an error in a ZoneUpdateResponse
type ZoneUpdateError struct {
Code int `json:"code"`
ContextObject string `json:"contextObject"`
ContextPath string `json:"contextPath"`
Details []string `json:"details"`
Text string `json:"text"`
Value string `json:"value"`
}
// ZoneUpdateMetadata represents the metadata in a ZoneUpdateResponse
type ZoneUpdateMetadata struct {
ClientTransactionID string `json:"clientTransactionId"`
ServerTransactionID string `json:"serverTransactionId"`
}
// ZoneUpdateResponse represents a response from hosting.de API
type ZoneUpdateResponse struct {
Errors []ZoneUpdateError `json:"errors"`
Metadata ZoneUpdateMetadata `json:"metadata"`
Warnings []string `json:"warnings"`
Status string `json:"status"`
Response struct {
Records []struct {
Content string `json:"content"`
Type string `json:"type"`
ID string `json:"id"`
Name string `json:"name"`
LastChangeDate string `json:"lastChangeDate"`
Priority int `json:"priority"`
RecordTemplateID string `json:"recordTemplateId"`
ZoneConfigID string `json:"zoneConfigId"`
TTL int `json:"ttl"`
} `json:"records"`
ZoneConfig ZoneConfigObject `json:"zoneConfig"`
} `json:"response"`
}
// ZoneConfigSelector represents a "minimal" ZoneConfig object used in hosting.de API requests
type ZoneConfigSelector struct {
Name string `json:"name"`
}
// ZoneUpdateRequest represents a hosting.de API ZoneUpdate request
type ZoneUpdateRequest struct {
AuthToken string `json:"authToken"`
ZoneConfigSelector `json:"zoneConfig"`
RecordsToAdd []RecordsAddRequest `json:"recordsToAdd"`
RecordsToDelete []RecordsDeleteRequest `json:"recordsToDelete"`
}
func (d *DNSProvider) updateZone(updateRequest ZoneUpdateRequest) (*ZoneUpdateResponse, error) {
body, err := json.Marshal(updateRequest)
if err != nil {
return nil, err
}
req, err := http.NewRequest(http.MethodPost, defaultBaseURL+"/zoneUpdate", bytes.NewReader(body))
if err != nil {
return nil, err
}
resp, err := d.config.HTTPClient.Do(req)
if err != nil {
return nil, fmt.Errorf("error querying API: %v", err)
}
defer resp.Body.Close()
content, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, errors.New(toUnreadableBodyMessage(req, content))
}
// Everything looks good; but we'll need the ID later to delete the record
updateResponse := &ZoneUpdateResponse{}
err = json.Unmarshal(content, updateResponse)
if err != nil {
return nil, fmt.Errorf("%v: %s", err, toUnreadableBodyMessage(req, content))
}
if updateResponse.Status != "success" && updateResponse.Status != "pending" {
return updateResponse, errors.New(toUnreadableBodyMessage(req, content))
}
return updateResponse, nil
}
func toUnreadableBodyMessage(req *http.Request, rawBody []byte) string {
return fmt.Sprintf("the request %s sent a response with a body which is an invalid format: %q", req.URL, string(rawBody))
}