Skip to content
Closed
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)
)
48 changes: 48 additions & 0 deletions provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -693,3 +693,51 @@ 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 := []string{
*domain,
"test1-" + *domain,
"test2-" + *domain,
}

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) })
}

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

zoneMap := make(map[string]bool)
for _, zone := range zones {
zoneMap[zone.Name] = true
}

for _, testDomain := range testDomains {
if !zoneMap[testDomain] {
t.Errorf("Failed to find %s in ListZones call", testDomain)
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the intend is to make sure to allow domains that are not part of the test domains to be part of the result, because there can be preexisting domains (good idea, btw). This is not immediately clear from the code (at first I thought this was a bug).

Also I generally prefer using go-cmp for things like this. In this case, I would use something like the (untested) code below:

testDomains := map[string]bool{
  // ...
}

// ...

got, err := p.ListZones()
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 !testDomain[zone.Name] }),
  comports.SortSlices(func(a, b libdns.Zone) int { return cmp.Compare(a.Name, b.Name) }),
}
if diff := cmp.Diff(want, got, opts); diff != "" {
  t.Errorf("ListZones() unexpected diff [-want +got]: %s", diff)
}

}
}