diff --git a/go.mod b/go.mod index cbd4d7a0..f08b49f6 100644 --- a/go.mod +++ b/go.mod @@ -30,6 +30,7 @@ require ( github.com/miekg/dns v1.1.27 github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 github.com/nrdcg/auroradns v1.0.1 + github.com/nrdcg/desec v0.5.0 github.com/nrdcg/dnspod-go v0.4.0 github.com/nrdcg/goinwx v0.7.0 github.com/nrdcg/namesilo v0.2.1 @@ -38,7 +39,7 @@ require ( github.com/pquerna/otp v1.2.0 github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2 github.com/sacloud/libsacloud v1.26.1 - github.com/stretchr/testify v1.5.1 + github.com/stretchr/testify v1.6.1 github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7 github.com/transip/gotransip/v6 v6.0.2 github.com/urfave/cli v1.22.1 diff --git a/go.sum b/go.sum index e9730b8b..21a2d754 100644 --- a/go.sum +++ b/go.sum @@ -260,6 +260,8 @@ github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= github.com/nrdcg/auroradns v1.0.1 h1:m/kBq83Xvy3cU261MOknd8BdnOk12q4lAWM+kOdsC2Y= github.com/nrdcg/auroradns v1.0.1/go.mod h1:y4pc0i9QXYlFCWrhWrUSIETnZgrf4KuwjDIWmmXo3JI= +github.com/nrdcg/desec v0.5.0 h1:foL7hqivYOMlv0qDhHXJtuuEXkqf0wW9EQMqyrt228g= +github.com/nrdcg/desec v0.5.0/go.mod h1:2ejvMazkav1VdDbv2HeQO7w+Ta1CGHqzQr27ZBYTuEQ= github.com/nrdcg/dnspod-go v0.4.0 h1:c/jn1mLZNKF3/osJ6mz3QPxTudvPArXTjpkmYj0uK6U= github.com/nrdcg/dnspod-go v0.4.0/go.mod h1:vZSoFSFeQVm2gWLMkyX61LZ8HI3BaqtHZWgPTGKr6KQ= github.com/nrdcg/goinwx v0.7.0 h1:j6JlOp0nNwtvaP09TvKqc9pktjH81nOad0+Gx9S1t9U= @@ -333,6 +335,8 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7 h1:CpHxIaZzVy26GqJn8ptRyto8fuoYOd1v0fXm9bG3wQ8= github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLplxEC/etjIhdr3dNzV3JeT27LbVu5pYWm0JCBY= github.com/transip/gotransip/v6 v6.0.2 h1:rOCMY607PYF+YvMHHtJt7eZRd0mx/uhyz6dsXWPmn+4= @@ -490,6 +494,8 @@ golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0 h1:xQwXv67TxFo9nC1GJFyab5eq golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= +golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -614,6 +620,8 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/providers/dns/desec/desec.go b/providers/dns/desec/desec.go index def3b9fe..fde44df9 100644 --- a/providers/dns/desec/desec.go +++ b/providers/dns/desec/desec.go @@ -9,7 +9,7 @@ import ( "github.com/go-acme/lego/v3/challenge/dns01" "github.com/go-acme/lego/v3/platform/config/env" - "github.com/go-acme/lego/v3/providers/dns/desec/internal" + "github.com/nrdcg/desec" ) // Environment variables names. @@ -48,7 +48,7 @@ func NewDefaultConfig() *Config { // DNSProvider implements the challenge.Provider interface. type DNSProvider struct { config *Config - client *internal.Client + client *desec.Client } // NewDNSProvider returns a DNSProvider instance configured for deSEC. @@ -75,12 +75,13 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) { return nil, errors.New("desec: incomplete credentials, missing token") } - client := internal.NewClient(config.Token) - + opts := desec.NewDefaultClientOptions() if config.HTTPClient != nil { - client.HTTPClient = config.HTTPClient + opts.HTTPClient = config.HTTPClient } + client := desec.New(config.Token, opts) + return &DNSProvider{config: config, client: client}, nil } @@ -104,15 +105,15 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { domainName := dns01.UnFqdn(authZone) - rrSet, err := d.client.GetTxtRRSet(domainName, recordName) + rrSet, err := d.client.Records.Get(domainName, recordName, "TXT") if err != nil { - var nf *internal.NotFound + var nf *desec.NotFound if !errors.As(err, &nf) { return fmt.Errorf("desec: failed to get records: domainName=%s, recordName=%s: %w", domainName, recordName, err) } // Not found case -> create - _, err = d.client.AddTxtRRSet(internal.RRSet{ + _, err = d.client.Records.Create(desec.RRSet{ Domain: domainName, SubName: recordName, Type: "TXT", @@ -129,7 +130,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { // update records := append(rrSet.Records, quotedValue) - _, err = d.client.UpdateTxtRRSet(domainName, recordName, records) + _, err = d.client.Records.Update(domainName, recordName, "TXT", desec.RRSet{Records: records}) if err != nil { return fmt.Errorf("desec: failed to update records: domainName=%s, recordName=%s: %w", domainName, recordName, err) } @@ -150,7 +151,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { domainName := dns01.UnFqdn(authZone) - rrSet, err := d.client.GetTxtRRSet(domainName, recordName) + rrSet, err := d.client.Records.Get(domainName, recordName, "TXT") if err != nil { return fmt.Errorf("desec: failed to get records: domainName=%s, recordName=%s: %w", domainName, recordName, err) } @@ -162,7 +163,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { } } - _, err = d.client.UpdateTxtRRSet(domainName, recordName, records) + _, err = d.client.Records.Update(domainName, recordName, "TXT", desec.RRSet{Records: records}) if err != nil { return fmt.Errorf("desec: failed to update records: domainName=%s, recordName=%s: %w", domainName, recordName, err) } diff --git a/providers/dns/desec/internal/client.go b/providers/dns/desec/internal/client.go deleted file mode 100644 index f43ea69e..00000000 --- a/providers/dns/desec/internal/client.go +++ /dev/null @@ -1,229 +0,0 @@ -package internal - -import ( - "bytes" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "net/url" - "path" -) - -const baseURL = "https://desec.io/api/v1/" - -// Client deSec API client. -type Client struct { - HTTPClient *http.Client - BaseURL string - - token string -} - -// NewClient creates a new Client. -func NewClient(token string) *Client { - return &Client{ - HTTPClient: http.DefaultClient, - BaseURL: baseURL, - token: token, - } -} - -// GetTxtRRSet gets a RRSet. -// https://desec.readthedocs.io/en/latest/dns/rrsets.html#retrieving-a-specific-rrset -func (c *Client) GetTxtRRSet(domainName, subName string) (*RRSet, error) { - if subName == "" { - subName = "@" - } - - endpoint, err := c.createEndpoint("domains", domainName, "rrsets", subName, "TXT") - if err != nil { - return nil, fmt.Errorf("failed to create endpoint: %w", err) - } - - req, err := http.NewRequest(http.MethodGet, endpoint, nil) - if err != nil { - return nil, fmt.Errorf("failed to create request: %w", err) - } - - req.Header.Set("Content-Type", "application/json") - req.Header.Set("Authorization", fmt.Sprintf("Token %s", c.token)) - - resp, err := c.HTTPClient.Do(req) - if err != nil { - return nil, fmt.Errorf("failed to call API: %w", err) - } - - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("failed to read response body: %w", err) - } - - if resp.StatusCode == http.StatusNotFound { - var notFound NotFound - err = json.Unmarshal(body, ¬Found) - if err != nil { - return nil, fmt.Errorf("error: %d: %s", resp.StatusCode, string(body)) - } - - return nil, ¬Found - } - - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("error: %d: %s", resp.StatusCode, string(body)) - } - - var rrSet RRSet - err = json.Unmarshal(body, &rrSet) - if err != nil { - return nil, fmt.Errorf("failed to umarshal response body: %w", err) - } - - return &rrSet, nil -} - -// AddTxtRRSet creates a new RRSet. -// https://desec.readthedocs.io/en/latest/dns/rrsets.html#creating-a-tlsa-rrset -func (c *Client) AddTxtRRSet(rrSet RRSet) (*RRSet, error) { - endpoint, err := c.createEndpoint("domains", rrSet.Domain, "rrsets") - if err != nil { - return nil, fmt.Errorf("failed to create endpoint: %w", err) - } - - raw, err := json.Marshal(rrSet) - if err != nil { - return nil, fmt.Errorf("failed to marshal request body: %w", err) - } - - req, err := http.NewRequest(http.MethodPost, endpoint, bytes.NewReader(raw)) - if err != nil { - return nil, fmt.Errorf("failed to create request: %w", err) - } - - req.Header.Set("Content-Type", "application/json") - req.Header.Set("Authorization", fmt.Sprintf("Token %s", c.token)) - - resp, err := c.HTTPClient.Do(req) - if err != nil { - return nil, fmt.Errorf("failed to call API: %w", err) - } - - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("failed to read response body: %w", err) - } - - if resp.StatusCode != http.StatusCreated { - return nil, fmt.Errorf("error: %d: %s", resp.StatusCode, string(body)) - } - - var newRRSet RRSet - err = json.Unmarshal(body, &newRRSet) - if err != nil { - return nil, fmt.Errorf("failed to umarshal response body: %w", err) - } - - return &newRRSet, nil -} - -// UpdateTxtRRSet updates RRSet records. -// https://desec.readthedocs.io/en/latest/dns/rrsets.html#modifying-an-rrset -func (c *Client) UpdateTxtRRSet(domainName, subName string, records []string) (*RRSet, error) { - if subName == "" { - subName = "@" - } - - endpoint, err := c.createEndpoint("domains", domainName, "rrsets", subName, "TXT") - if err != nil { - return nil, fmt.Errorf("failed to create endpoint: %w", err) - } - - raw, err := json.Marshal(RRSet{Records: records}) - if err != nil { - return nil, fmt.Errorf("failed to marshal request body: %w", err) - } - - req, err := http.NewRequest(http.MethodPatch, endpoint, bytes.NewReader(raw)) - if err != nil { - return nil, fmt.Errorf("failed to create request: %w", err) - } - - req.Header.Set("Content-Type", "application/json") - req.Header.Set("Authorization", fmt.Sprintf("Token %s", c.token)) - - resp, err := c.HTTPClient.Do(req) - if err != nil { - return nil, fmt.Errorf("failed to call API: %w", err) - } - - // when a RRSet is deleted (empty records) - if resp.StatusCode == http.StatusNoContent { - return nil, nil - } - - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("failed to read response body: %w", err) - } - - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("error: %d: %s", resp.StatusCode, string(body)) - } - - var updatedRRSet RRSet - err = json.Unmarshal(body, &updatedRRSet) - if err != nil { - return nil, fmt.Errorf("failed to umarshal response body: %w", err) - } - - return &updatedRRSet, nil -} - -// DeleteTxtRRSet deletes a RRset. -// https://desec.readthedocs.io/en/latest/dns/rrsets.html#deleting-an-rrset -func (c *Client) DeleteTxtRRSet(domainName, subName string) error { - if subName == "" { - subName = "@" - } - - endpoint, err := c.createEndpoint("domains", domainName, "rrsets", subName, "TXT") - if err != nil { - return fmt.Errorf("failed to create endpoint: %w", err) - } - - req, err := http.NewRequest(http.MethodDelete, endpoint, nil) - if err != nil { - return fmt.Errorf("failed to create request: %w", err) - } - - req.Header.Set("Content-Type", "application/json") - req.Header.Set("Authorization", fmt.Sprintf("Token %s", c.token)) - - resp, err := c.HTTPClient.Do(req) - if err != nil { - return fmt.Errorf("failed to call API: %w", err) - } - - if resp.StatusCode != http.StatusNoContent { - body, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("error: %d: %s", resp.StatusCode, string(body)) - } - - return nil -} - -func (c *Client) createEndpoint(parts ...string) (string, error) { - base, err := url.Parse(c.BaseURL) - if err != nil { - return "", err - } - - endpoint, err := base.Parse(path.Join(base.Path, path.Join(parts...))) - if err != nil { - return "", err - } - - endpoint.Path += "/" - - return endpoint.String(), nil -} diff --git a/providers/dns/desec/internal/client_test.go b/providers/dns/desec/internal/client_test.go deleted file mode 100644 index ff2f8a7c..00000000 --- a/providers/dns/desec/internal/client_test.go +++ /dev/null @@ -1,169 +0,0 @@ -package internal - -import ( - "io" - "net/http" - "net/http/httptest" - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestGetTxtRRSet(t *testing.T) { - mux := http.NewServeMux() - server := httptest.NewServer(mux) - t.Cleanup(server.Close) - - client := NewClient("token") - client.BaseURL = server.URL - - mux.HandleFunc("/domains/example.dedyn.io/rrsets/_acme-challenge/TXT/", func(rw http.ResponseWriter, req *http.Request) { - if req.Method != http.MethodGet { - http.Error(rw, "invalid method", http.StatusMethodNotAllowed) - return - } - - file, err := os.Open("./fixtures/get_record.json") - if err != nil { - http.Error(rw, err.Error(), http.StatusInternalServerError) - return - } - defer func() { _ = file.Close() }() - - _, err = io.Copy(rw, file) - if err != nil { - http.Error(rw, err.Error(), http.StatusInternalServerError) - return - } - }) - - record, err := client.GetTxtRRSet("example.dedyn.io", "_acme-challenge") - require.NoError(t, err) - - expected := &RRSet{ - Name: "_acme-challenge.example.dedyn.io.", - Domain: "example.dedyn.io", - SubName: "_acme-challenge", - Type: "TXT", - Records: []string{`"txt"`}, - TTL: 300, - } - assert.Equal(t, expected, record) -} - -func TestAddTxtRRSet(t *testing.T) { - mux := http.NewServeMux() - server := httptest.NewServer(mux) - t.Cleanup(server.Close) - - client := NewClient("token") - client.BaseURL = server.URL - - mux.HandleFunc("/domains/example.dedyn.io/rrsets/", func(rw http.ResponseWriter, req *http.Request) { - if req.Method != http.MethodPost { - http.Error(rw, "invalid method", http.StatusMethodNotAllowed) - return - } - - rw.WriteHeader(http.StatusCreated) - file, err := os.Open("./fixtures/add_record.json") - if err != nil { - http.Error(rw, err.Error(), http.StatusInternalServerError) - return - } - defer func() { _ = file.Close() }() - - _, err = io.Copy(rw, file) - if err != nil { - http.Error(rw, err.Error(), http.StatusInternalServerError) - return - } - }) - - record := RRSet{ - Name: "", - Domain: "example.dedyn.io", - SubName: "_acme-challenge", - Type: "TXT", - Records: []string{`"txt"`}, - TTL: 300, - } - - newRecord, err := client.AddTxtRRSet(record) - require.NoError(t, err) - - expected := &RRSet{ - Name: "_acme-challenge.example.dedyn.io.", - Domain: "example.dedyn.io", - SubName: "_acme-challenge", - Type: "TXT", - Records: []string{`"txt"`}, - TTL: 300, - } - assert.Equal(t, expected, newRecord) -} - -func TestUpdateTxtRRSet(t *testing.T) { - mux := http.NewServeMux() - server := httptest.NewServer(mux) - t.Cleanup(server.Close) - - client := NewClient("token") - client.BaseURL = server.URL - - mux.HandleFunc("/domains/example.dedyn.io/rrsets/_acme-challenge/TXT/", func(rw http.ResponseWriter, req *http.Request) { - if req.Method != http.MethodPatch { - http.Error(rw, "invalid method", http.StatusMethodNotAllowed) - return - } - - file, err := os.Open("./fixtures/update_record.json") - if err != nil { - http.Error(rw, err.Error(), http.StatusInternalServerError) - return - } - defer func() { _ = file.Close() }() - - _, err = io.Copy(rw, file) - if err != nil { - http.Error(rw, err.Error(), http.StatusInternalServerError) - return - } - }) - - updatedRecord, err := client.UpdateTxtRRSet("example.dedyn.io", "_acme-challenge", []string{`"updated"`}) - require.NoError(t, err) - - expected := &RRSet{ - Name: "_acme-challenge.example.dedyn.io.", - Domain: "example.dedyn.io", - SubName: "_acme-challenge", - Type: "TXT", - Records: []string{`"updated"`}, - TTL: 300, - } - assert.Equal(t, expected, updatedRecord) -} - -func TestDeleteTxtRRSet(t *testing.T) { - mux := http.NewServeMux() - server := httptest.NewServer(mux) - t.Cleanup(server.Close) - - client := NewClient("token") - client.BaseURL = server.URL - - mux.HandleFunc("/domains/example.dedyn.io/rrsets/_acme-challenge/TXT/", func(rw http.ResponseWriter, req *http.Request) { - if req.Method != http.MethodDelete { - http.Error(rw, "invalid method", http.StatusMethodNotAllowed) - return - } - - rw.WriteHeader(http.StatusNoContent) - }) - - err := client.DeleteTxtRRSet("example.dedyn.io", "_acme-challenge") - require.NoError(t, err) -} diff --git a/providers/dns/desec/internal/fixtures/add_record.json b/providers/dns/desec/internal/fixtures/add_record.json deleted file mode 100644 index 96ce5590..00000000 --- a/providers/dns/desec/internal/fixtures/add_record.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "created": "2020-05-06T11:46:07.641885Z", - "domain": "example.dedyn.io", - "subname": "_acme-challenge", - "name": "_acme-challenge.example.dedyn.io.", - "records": [ - "\"txt\"" - ], - "ttl": 300, - "type": "TXT" -} diff --git a/providers/dns/desec/internal/fixtures/get_record.json b/providers/dns/desec/internal/fixtures/get_record.json deleted file mode 100644 index 96ce5590..00000000 --- a/providers/dns/desec/internal/fixtures/get_record.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "created": "2020-05-06T11:46:07.641885Z", - "domain": "example.dedyn.io", - "subname": "_acme-challenge", - "name": "_acme-challenge.example.dedyn.io.", - "records": [ - "\"txt\"" - ], - "ttl": 300, - "type": "TXT" -} diff --git a/providers/dns/desec/internal/fixtures/update_record.json b/providers/dns/desec/internal/fixtures/update_record.json deleted file mode 100644 index a2e6b3ee..00000000 --- a/providers/dns/desec/internal/fixtures/update_record.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "created": "2020-05-06T11:46:07.641885Z", - "domain": "example.dedyn.io", - "subname": "_acme-challenge", - "name": "_acme-challenge.example.dedyn.io.", - "records": [ - "\"updated\"" - ], - "ttl": 300, - "type": "TXT" -} diff --git a/providers/dns/desec/internal/model.go b/providers/dns/desec/internal/model.go deleted file mode 100644 index 6e598f4d..00000000 --- a/providers/dns/desec/internal/model.go +++ /dev/null @@ -1,20 +0,0 @@ -package internal - -// RRSet DNS Record Set. -type RRSet struct { - Name string `json:"name,omitempty"` - Domain string `json:"domain,omitempty"` - SubName string `json:"subname,omitempty"` - Type string `json:"type,omitempty"` - Records []string `json:"records"` - TTL int `json:"ttl,omitempty"` -} - -// NotFound Not found error. -type NotFound struct { - Detail string `json:"detail"` -} - -func (n NotFound) Error() string { - return n.Detail -}