client.go raw
1 // Package metaname provides a client for the Metaname API.
2 package metaname
3
4 import (
5 "context"
6 "encoding/json"
7
8 "github.com/AdamSLevy/jsonrpc2/v14"
9 )
10
11 type iJsonRpc2Client interface {
12 Request(context context.Context, host string, method string, params interface{}, result interface{}) error
13 }
14
15 // A client for the Metaname API.
16 type MetanameClient struct {
17 RpcClient iJsonRpc2Client
18 Host string
19 AccountReference string
20 APIKey string
21 }
22
23 // A ResourceRecord is a representation of a DNS record.
24 //
25 // Aux should be nil for records other than MX and SRV records, where it represents the priority.
26 // Reference should be nil when supplying a ResourceRecord, but will be populated when retrieving a record.
27 //
28 // https://metaname.net/api/1.1/doc#Resource_record_details
29 type ResourceRecord struct {
30 Name string `json:"name"`
31 Type string `json:"type"`
32 Aux *int `json:"aux"`
33 Ttl int `json:"ttl"`
34 Data string `json:"data"`
35 Reference *string `json:"reference,omitempty"`
36 }
37
38 // Create a new MetanameClient with some default values.
39 func NewMetanameClient(accountReference string, apiKey string) *MetanameClient {
40 return &MetanameClient{
41 RpcClient: &jsonrpc2.Client{},
42 Host: "https://metaname.net/api/1.1",
43 AccountReference: accountReference,
44 APIKey: apiKey,
45 }
46 }
47
48 // Creates a DNS record in the zone for the given domain and returns a reference that can be used for updating and deleting it.
49 //
50 // https://metaname.net/api/1.1/doc#create_dns_record
51 func (c *MetanameClient) CreateDnsRecord(ctx context.Context, domainName string, record ResourceRecord) (string, error) {
52 params := []interface{}{c.AccountReference, c.APIKey, domainName, record}
53 var result string
54 err := c.RpcClient.Request(ctx, c.Host, "create_dns_record", params, &result)
55 return result, err
56 }
57
58 // Updates the details of a DNS record in a zone.
59 //
60 // https://metaname.net/api/1.1/doc#update_dns_record
61 func (c *MetanameClient) UpdateDnsRecord(ctx context.Context, domainName string, reference string, record ResourceRecord) error {
62 params := []interface{}{c.AccountReference, c.APIKey, domainName, reference, record}
63 err := c.RpcClient.Request(ctx, c.Host, "update_dns_record", params, nil)
64 return ignoreNullResultError(err)
65 }
66
67 // Delete a DNS record from a zone.
68 //
69 // https://metaname.net/api/1.1/doc#delete_dns_record
70 func (c *MetanameClient) DeleteDnsRecord(ctx context.Context, domainName string, reference string) error {
71 params := []interface{}{c.AccountReference, c.APIKey, domainName, reference}
72 err := c.RpcClient.Request(ctx, c.Host, "delete_dns_record", params, nil)
73 return ignoreNullResultError(err)
74 }
75
76 // Retrieve all the DNS records in a zone.
77 //
78 // https://metaname.net/api/1.1/doc#dns_zone
79 func (c *MetanameClient) DnsZone(ctx context.Context, domainName string) ([]ResourceRecord, error) {
80 params := []interface{}{c.AccountReference, c.APIKey, domainName}
81 var result []ResourceRecord
82 err := c.RpcClient.Request(ctx, c.Host, "dns_zone", params, &result)
83 return result, err
84 }
85
86 // Create or update a zone.
87 //
88 // https://metaname.net/api/1.1/doc#configure_zone
89 func (c *MetanameClient) ConfigureZone(ctx context.Context, zoneName string, records []ResourceRecord, options interface{}) error {
90 params := []interface{}{c.AccountReference, c.APIKey, zoneName, records, options}
91 err := c.RpcClient.Request(ctx, c.Host, "configure_zone", params, nil)
92 return ignoreNullResultError(err)
93 }
94
95 // Workaround until https://github.com/AdamSLevy/jsonrpc2/issues/11 is fixed.
96 type nullSafeResponse struct {
97 Result interface{} `json:"result"`
98 }
99
100 func ignoreNullResultError(err error) error {
101 if unexerr, ok := err.(jsonrpc2.ErrorUnexpectedHTTPResponse); ok {
102 var res nullSafeResponse
103 unmerr := json.Unmarshal(unexerr.Body, &res)
104 if unmerr != nil {
105 return err
106 } else if res.Result == nil {
107 return nil
108 }
109 }
110 return err
111 }
112