Archived
Validate domain resource and extend DNS record typed fields
This commit is contained in:
1 parent
6badcf35f4
commit
e59ad5a65b
9 files changed
+599
-20
No files matched your search
@@ -106,6 +106,12 @@ type DNSRecord struct {
|
||||
UpdatedOn string `json:"updatedOn"`
|
||||
Group string `json:"group"`
|
||||
Host string `json:"host"`
|
||||
Priority int64 `json:"priority"`
|
||||
Weight int64 `json:"weight"`
|
||||
Port int64 `json:"port"`
|
||||
Flags int64 `json:"flags"`
|
||||
Tag string `json:"tag"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type CreateDNSRecordRequest struct {
|
||||
@@ -116,6 +122,12 @@ type CreateDNSRecordRequest struct {
|
||||
State *bool `json:"state,omitempty"`
|
||||
Group string `json:"group,omitempty"`
|
||||
Host string `json:"host,omitempty"`
|
||||
Priority int64 `json:"priority,omitempty"`
|
||||
Weight int64 `json:"weight,omitempty"`
|
||||
Port int64 `json:"port,omitempty"`
|
||||
Flags int64 `json:"flags,omitempty"`
|
||||
Tag string `json:"tag,omitempty"`
|
||||
Value string `json:"value,omitempty"`
|
||||
}
|
||||
|
||||
type UpdateDNSRecordRequest struct {
|
||||
@@ -126,8 +138,24 @@ type UpdateDNSRecordRequest struct {
|
||||
State *bool `json:"state,omitempty"`
|
||||
Group string `json:"group,omitempty"`
|
||||
Host string `json:"host,omitempty"`
|
||||
Priority int64 `json:"priority,omitempty"`
|
||||
Weight int64 `json:"weight,omitempty"`
|
||||
Port int64 `json:"port,omitempty"`
|
||||
Flags int64 `json:"flags,omitempty"`
|
||||
Tag string `json:"tag,omitempty"`
|
||||
Value string `json:"value,omitempty"`
|
||||
}
|
||||
|
||||
type CreateDomainRequest struct {
|
||||
Name string `json:"name"`
|
||||
IPv4Address string `json:"ipv4Address,omitempty"`
|
||||
IPv6Address string `json:"ipv6Address,omitempty"`
|
||||
TTL int64 `json:"ttl,omitempty"`
|
||||
Group string `json:"group,omitempty"`
|
||||
}
|
||||
|
||||
type UpdateDomainRequest = CreateDomainRequest
|
||||
|
||||
type listDomainsResponse struct {
|
||||
apiResponse
|
||||
Domains []Domain `json:"domains"`
|
||||
@@ -172,6 +200,26 @@ func (c *Client) GetDomainByID(ctx context.Context, domainID int64) (*Domain, er
|
||||
return &resp.Domain, nil
|
||||
}
|
||||
|
||||
func (c *Client) CreateDomain(ctx context.Context, req CreateDomainRequest) (*Domain, error) {
|
||||
var resp getDomainResponse
|
||||
if err := c.doRequest(ctx, http.MethodPost, "/dns", req, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp.Domain, nil
|
||||
}
|
||||
|
||||
func (c *Client) UpdateDomain(ctx context.Context, domainID int64, req UpdateDomainRequest) (*Domain, error) {
|
||||
var resp getDomainResponse
|
||||
if err := c.doRequest(ctx, http.MethodPost, fmt.Sprintf("/dns/%d", domainID), req, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp.Domain, nil
|
||||
}
|
||||
|
||||
func (c *Client) DeleteDomain(ctx context.Context, domainID int64) error {
|
||||
return c.doRequest(ctx, http.MethodDelete, fmt.Sprintf("/dns/%d", domainID), nil, nil)
|
||||
}
|
||||
|
||||
func (c *Client) GetRootDomain(ctx context.Context, hostname string) (int64, string, error) {
|
||||
var resp getRootResponse
|
||||
if err := c.doRequest(ctx, http.MethodGet, fmt.Sprintf("/dns/getroot/%s", url.PathEscape(hostname)), nil, &resp); err != nil {
|
||||
@@ -207,7 +255,7 @@ func (c *Client) GetDNSRecord(ctx context.Context, domainID int64, recordID int6
|
||||
|
||||
func (c *Client) CreateDNSRecord(ctx context.Context, domainID int64, req CreateDNSRecordRequest) (*DNSRecord, error) {
|
||||
var resp getDNSRecordResponse
|
||||
if err := c.doRequest(ctx, http.MethodPost, fmt.Sprintf("/dns/%d/record", domainID), buildDNSRecordUpsertPayload(req.RecordType, req.NodeName, req.Content, req.TTL, req.State, req.Group, req.Host), &resp); err != nil {
|
||||
if err := c.doRequest(ctx, http.MethodPost, fmt.Sprintf("/dns/%d/record", domainID), buildDNSRecordUpsertPayload(req), &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
normalizeDNSRecord(&resp.DNSRecord)
|
||||
@@ -216,7 +264,7 @@ func (c *Client) CreateDNSRecord(ctx context.Context, domainID int64, req Create
|
||||
|
||||
func (c *Client) UpdateDNSRecord(ctx context.Context, domainID int64, recordID int64, req UpdateDNSRecordRequest) (*DNSRecord, error) {
|
||||
var resp getDNSRecordResponse
|
||||
if err := c.doRequest(ctx, http.MethodPost, fmt.Sprintf("/dns/%d/record/%d", domainID, recordID), buildDNSRecordUpsertPayload(req.RecordType, req.NodeName, req.Content, req.TTL, req.State, req.Group, req.Host), &resp); err != nil {
|
||||
if err := c.doRequest(ctx, http.MethodPost, fmt.Sprintf("/dns/%d/record/%d", domainID, recordID), buildDNSRecordUpsertPayload(CreateDNSRecordRequest(req)), &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
normalizeDNSRecord(&resp.DNSRecord)
|
||||
@@ -319,18 +367,30 @@ type dnsRecordUpsertPayload struct {
|
||||
State *bool `json:"state,omitempty"`
|
||||
Group string `json:"group,omitempty"`
|
||||
Host string `json:"host,omitempty"`
|
||||
Priority int64 `json:"priority,omitempty"`
|
||||
Weight int64 `json:"weight,omitempty"`
|
||||
Port int64 `json:"port,omitempty"`
|
||||
Flags int64 `json:"flags,omitempty"`
|
||||
Tag string `json:"tag,omitempty"`
|
||||
Value string `json:"value,omitempty"`
|
||||
}
|
||||
|
||||
func buildDNSRecordUpsertPayload(recordType string, nodeName string, content *string, ttl int64, state *bool, group string, host string) dnsRecordUpsertPayload {
|
||||
normalizedType := strings.ToUpper(strings.TrimSpace(recordType))
|
||||
normalizedContent := normalizeOptionalContent(content)
|
||||
func buildDNSRecordUpsertPayload(req CreateDNSRecordRequest) dnsRecordUpsertPayload {
|
||||
normalizedType := strings.ToUpper(strings.TrimSpace(req.RecordType))
|
||||
normalizedContent := normalizeOptionalContent(req.Content)
|
||||
payload := dnsRecordUpsertPayload{
|
||||
NodeName: nodeName,
|
||||
NodeName: req.NodeName,
|
||||
RecordType: normalizedType,
|
||||
TTL: ttl,
|
||||
State: state,
|
||||
Group: group,
|
||||
Host: host,
|
||||
TTL: req.TTL,
|
||||
State: req.State,
|
||||
Group: req.Group,
|
||||
Host: req.Host,
|
||||
Priority: req.Priority,
|
||||
Weight: req.Weight,
|
||||
Port: req.Port,
|
||||
Flags: req.Flags,
|
||||
Tag: req.Tag,
|
||||
Value: req.Value,
|
||||
}
|
||||
|
||||
switch normalizedType {
|
||||
@@ -346,6 +406,14 @@ func buildDNSRecordUpsertPayload(recordType string, nodeName string, content *st
|
||||
if normalizedContent != nil {
|
||||
payload.Host = *normalizedContent
|
||||
}
|
||||
case "MX", "SRV", "NS", "PTR":
|
||||
if normalizedContent != nil {
|
||||
payload.Host = *normalizedContent
|
||||
}
|
||||
case "CAA":
|
||||
if normalizedContent != nil && payload.Value == "" {
|
||||
payload.Value = *normalizedContent
|
||||
}
|
||||
default:
|
||||
payload.Content = normalizedContent
|
||||
}
|
||||
|
||||
@@ -457,3 +457,91 @@ func TestClientCreateDNSRecordOmitsContentWhenUnset(t *testing.T) {
|
||||
func stringPointer(value string) *string {
|
||||
return &value
|
||||
}
|
||||
|
||||
func TestClientDomainCRUD(t *testing.T) {
|
||||
fake := fakedynu.NewServer()
|
||||
defer fake.Close()
|
||||
client := dynuclient.New("test-key", dynuclient.WithBaseURL(fake.BaseURL()), dynuclient.WithHTTPClient(fake.Client()))
|
||||
|
||||
created, err := client.CreateDomain(context.Background(), dynuclient.CreateDomainRequest{Name: "new.example.com", TTL: 300, IPv4Address: "203.0.113.10"})
|
||||
if err != nil {
|
||||
t.Fatalf("CreateDomain() error = %v", err)
|
||||
}
|
||||
if created.ID == 0 || created.Name != "new.example.com" {
|
||||
t.Fatalf("unexpected created domain: %#v", created)
|
||||
}
|
||||
|
||||
updated, err := client.UpdateDomain(context.Background(), created.ID, dynuclient.UpdateDomainRequest{Name: "new.example.com", TTL: 600})
|
||||
if err != nil {
|
||||
t.Fatalf("UpdateDomain() error = %v", err)
|
||||
}
|
||||
if updated.TTL != 600 {
|
||||
t.Fatalf("expected ttl 600, got %d", updated.TTL)
|
||||
}
|
||||
|
||||
if err := client.DeleteDomain(context.Background(), created.ID); err != nil {
|
||||
t.Fatalf("DeleteDomain() error = %v", err)
|
||||
}
|
||||
_, err = client.GetDomainByID(context.Background(), created.ID)
|
||||
if err == nil {
|
||||
t.Fatalf("expected error reading deleted domain")
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientCreateDNSRecordSendsMXFields(t *testing.T) {
|
||||
fake := fakedynu.NewServer()
|
||||
defer fake.Close()
|
||||
client := dynuclient.New("test-key", dynuclient.WithBaseURL(fake.BaseURL()), dynuclient.WithHTTPClient(fake.Client()))
|
||||
host := "mail.example.com"
|
||||
_, err := client.CreateDNSRecord(context.Background(), 1001, dynuclient.CreateDNSRecordRequest{NodeName: "@", RecordType: "MX", Content: &host, Priority: 10})
|
||||
if err != nil {
|
||||
t.Fatalf("CreateDNSRecord() error = %v", err)
|
||||
}
|
||||
rec, _ := client.GetDNSRecord(context.Background(), 1001, 21)
|
||||
if rec.Priority != 10 || rec.Host != host {
|
||||
t.Fatalf("unexpected MX fields: %#v", rec)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientCreateDNSRecordSendsSRVFields(t *testing.T) {
|
||||
fake := fakedynu.NewServer()
|
||||
defer fake.Close()
|
||||
client := dynuclient.New("test-key", dynuclient.WithBaseURL(fake.BaseURL()), dynuclient.WithHTTPClient(fake.Client()))
|
||||
target := "sip.example.com"
|
||||
_, err := client.CreateDNSRecord(context.Background(), 1001, dynuclient.CreateDNSRecordRequest{NodeName: "_sip._tcp", RecordType: "SRV", Content: &target, Priority: 10, Weight: 5, Port: 5060})
|
||||
if err != nil {
|
||||
t.Fatalf("CreateDNSRecord() error = %v", err)
|
||||
}
|
||||
rec, _ := client.GetDNSRecord(context.Background(), 1001, 21)
|
||||
if rec.Port != 5060 || rec.Weight != 5 || rec.Host != target {
|
||||
t.Fatalf("unexpected SRV fields: %#v", rec)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientCreateDNSRecordPreservesTXTContent(t *testing.T) {
|
||||
fake := fakedynu.NewServer()
|
||||
defer fake.Close()
|
||||
client := dynuclient.New("test-key", dynuclient.WithBaseURL(fake.BaseURL()), dynuclient.WithHTTPClient(fake.Client()))
|
||||
txt := "v=spf1 include:_spf.example.com ~all"
|
||||
rec, err := client.CreateDNSRecord(context.Background(), 1001, dynuclient.CreateDNSRecordRequest{NodeName: "@", RecordType: "TXT", Content: &txt})
|
||||
if err != nil {
|
||||
t.Fatalf("CreateDNSRecord() error = %v", err)
|
||||
}
|
||||
if rec.Content != txt {
|
||||
t.Fatalf("expected TXT content preserved, got %q", rec.Content)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientCreateDNSRecordSendsCAAFields(t *testing.T) {
|
||||
fake := fakedynu.NewServer()
|
||||
defer fake.Close()
|
||||
client := dynuclient.New("test-key", dynuclient.WithBaseURL(fake.BaseURL()), dynuclient.WithHTTPClient(fake.Client()))
|
||||
value := "letsencrypt.org"
|
||||
rec, err := client.CreateDNSRecord(context.Background(), 1001, dynuclient.CreateDNSRecordRequest{NodeName: "@", RecordType: "CAA", Content: &value, Flags: 0, Tag: "issue"})
|
||||
if err != nil {
|
||||
t.Fatalf("CreateDNSRecord() error = %v", err)
|
||||
}
|
||||
if rec.Tag != "issue" || rec.Value != value {
|
||||
t.Fatalf("unexpected CAA fields: %#v", rec)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user