Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,23 @@ func (p *Provider) DeleteRecords(ctx context.Context, zone string, records []lib
return ret, nil
}

// ListZones lists all the zones on an account.
func (p *Provider) ListZones(ctx context.Context) ([]libdns.Zone, error) {
// https://desec.readthedocs.io/en/latest/dns/domains.html#listing-domains
desecZones, err := p.listZones(ctx)
if err != nil {
return nil, err
}

zones := make([]libdns.Zone, len(desecZones))
for i, zone := range desecZones {
zones[i] = libdns.Zone{
Name: zone.Name,
}
}
return zones, nil
}

// https://desec.readthedocs.io/en/latest/dns/rrsets.html#rrset-field-reference
type rrSet struct {
Subname string `json:"subname"`
Expand Down Expand Up @@ -538,6 +555,25 @@ func (p *Provider) listRRSets(ctx context.Context, zone string) ([]rrSet, error)
return out, nil
}

// https://desec.readthedocs.io/en/latest/dns/domains.html#domain-field-reference
type domain struct {
Name string `json:"name"`
}

func (p *Provider) listZones(ctx context.Context) ([]domain, error) {
// https://desec.readthedocs.io/en/latest/dns/domains.html#listing-domains
buf, err := p.httpDo(ctx, "GET", "https://desec.io/api/v1/domains/", nil)
if err != nil {
return nil, err
}

var out []domain
if err := json.Unmarshal(buf, &out); err != nil {
return nil, fmt.Errorf("decoding json: %v", err)
}
return out, nil
}

func (p *Provider) putRRSets(ctx context.Context, zone string, rrs []rrSet) error {
if len(rrs) == 0 {
return nil
Expand Down Expand Up @@ -567,4 +603,5 @@ var (
_ libdns.RecordAppender = (*Provider)(nil)
_ libdns.RecordSetter = (*Provider)(nil)
_ libdns.RecordDeleter = (*Provider)(nil)
_ libdns.ZoneLister = (*Provider)(nil)
)
53 changes: 53 additions & 0 deletions provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ package desec_test

import (
"bytes"
gocmp "cmp"
"context"
"encoding/json"
"flag"
Expand Down Expand Up @@ -693,3 +694,55 @@ func TestDeleteRecords(t *testing.T) {
t.Fatalf("p.GetRecords() unexpected diff [-want +got]: %s", diff)
}
}

func TestListZones(t *testing.T) {
if *token == "" || *domain == "" {
t.Skip("skipping integration test; both -token and -domain must be set")
}

ctx := context.Background()
if deadline, ok := t.Deadline(); ok {
var cancel context.CancelFunc
ctx, cancel = context.WithDeadline(ctx, deadline)
t.Cleanup(cancel)
}

p := &desec.Provider{
Token: *token,
}

testDomains := map[string]bool{
*domain: true,
"test1-" + *domain: true,
"test2-" + *domain: true,
}

for testDomain := range testDomains {
if domainExists(ctx, t, testDomain) {
t.Fatalf("domain %q exists, but it should not", testDomain)
}
createDomain(ctx, t, testDomain)
domain := testDomain
t.Cleanup(func() { deleteDomain(ctx, t, domain) })
}

got, err := p.ListZones(ctx)
if err != nil {
t.Fatal(err)
}

var want []libdns.Zone
for domain := range testDomains {
want = append(want, libdns.Zone{Name: domain})
}

// We only control a limited number of zones in the test account, there may be preexisting zones
// that are unknown to us. Ignore all unknown zones.
opts := cmp.Options{
cmpopts.IgnoreSliceElements(func(zone libdns.Zone) bool { return !testDomains[zone.Name] }),
cmpopts.SortSlices(func(a, b libdns.Zone) int { return gocmp.Compare(a.Name, b.Name) }),
}
if diff := cmp.Diff(want, got, opts); diff != "" {
t.Errorf("ListZones() unexpected diff [-want +got]: %s", diff)
}
}