Skip to content

Commit

Permalink
Prepare for dnsx.Manager to operate on zones (#43)
Browse files Browse the repository at this point in the history
* Add new package for naming dns objects
* Extend dnsiface.Service interface
* Use dnsnames and complete dnsiface for tests
* Use NewCloudDNSService function in main
  • Loading branch information
stephen-soltesz authored Sep 10, 2024
1 parent 47f4567 commit af21ff6
Show file tree
Hide file tree
Showing 11 changed files with 157 additions and 42 deletions.
5 changes: 3 additions & 2 deletions handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (

v0 "github.com/m-lab/autojoin/api/v0"
"github.com/m-lab/autojoin/iata"
"github.com/m-lab/autojoin/internal/dnsname"
"github.com/m-lab/autojoin/internal/dnsx"
"github.com/m-lab/autojoin/internal/dnsx/dnsiface"
"github.com/m-lab/autojoin/internal/register"
Expand Down Expand Up @@ -239,7 +240,7 @@ func (s *Server) Register(rw http.ResponseWriter, req *http.Request) {
}

// Register the hostname under the organization zone.
m := dnsx.NewManager(s.DNS, s.Project, register.OrgZone(param.Org, s.Project))
m := dnsx.NewManager(s.DNS, s.Project, dnsname.OrgZone(param.Org, s.Project))
_, err = m.Register(req.Context(), r.Registration.Hostname+".", param.IPv4, param.IPv6)
if err != nil {
resp.Error = &v2.Error{
Expand Down Expand Up @@ -293,7 +294,7 @@ func (s *Server) Delete(rw http.ResponseWriter, req *http.Request) {
return
}

m := dnsx.NewManager(s.DNS, s.Project, register.OrgZone(name.Org, s.Project))
m := dnsx.NewManager(s.DNS, s.Project, dnsname.OrgZone(name.Org, s.Project))
_, err = m.Delete(req.Context(), name.StringAll()+".")
if err != nil {
resp.Error = &v2.Error{
Expand Down
6 changes: 6 additions & 0 deletions handler/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ func (f *fakeDNS) ResourceRecordSetsGet(ctx context.Context, project string, zon
func (f *fakeDNS) ChangeCreate(ctx context.Context, project string, zone string, change *dns.Change) (*dns.Change, error) {
return nil, f.chgErr
}
func (f *fakeDNS) CreateManagedZone(ctx context.Context, project string, zone *dns.ManagedZone) (*dns.ManagedZone, error) {
return nil, nil
}
func (f *fakeDNS) GetManagedZone(ctx context.Context, project, zoneName string) (*dns.ManagedZone, error) {
return nil, nil
}

type fakeStatusTracker struct {
updateErr error
Expand Down
20 changes: 20 additions & 0 deletions internal/dnsname/names.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package dnsname

import "strings"

// ProjectZone returns the project zone name, e.g. "autojoin-sandbox-measurement-lab-org".
func ProjectZone(project string) string {
return "autojoin-" + strings.TrimPrefix(project, "mlab-") + "-measurement-lab-org"
}

// OrgZone returns the organization zone name based on the given organization and
// project, e.g. "autojoin-foo-sandbox-measurement-lab-org".
func OrgZone(org, project string) string {
// NOTE: prefix prevents name collision with existing zones when the org is "mlab".
return "autojoin-" + org + "-" + strings.TrimPrefix(project, "mlab-") + "-measurement-lab-org"
}

// OrgDNS returns the DNS name for the given org and project, e.g. "foo.autojoin.measurement-lab.org."
func OrgDNS(org, project string) string {
return org + "." + strings.TrimPrefix(project, "mlab-") + ".measurement-lab.org."
}
87 changes: 87 additions & 0 deletions internal/dnsname/names_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package dnsname

import "testing"

func TestProjectZone(t *testing.T) {
tests := []struct {
name string
project string
want string
}{
{
name: "success",
project: "mlab-sandbox",
want: "autojoin-sandbox-measurement-lab-org",
},
{
name: "success",
project: "mlab-autojoin",
want: "autojoin-autojoin-measurement-lab-org",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := ProjectZone(tt.project); got != tt.want {
t.Errorf("ProjectZone() = %v, want %v", got, tt.want)
}
})
}
}

func TestOrgZone(t *testing.T) {
tests := []struct {
name string
org string
project string
want string
}{
{
name: "success",
org: "mlab",
project: "mlab-sandbox",
want: "autojoin-mlab-sandbox-measurement-lab-org",
},
{
name: "success",
org: "rnp",
project: "mlab-autojoin",
want: "autojoin-rnp-autojoin-measurement-lab-org",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := OrgZone(tt.org, tt.project); got != tt.want {
t.Errorf("OrgZone() = %v, want %v", got, tt.want)
}
})
}
}

func TestOrgDNS(t *testing.T) {
tests := []struct {
name string
org string
project string
want string
}{
{
name: "success",
org: "foo",
project: "mlab-sandbox",
want: "foo.sandbox.measurement-lab.org.",
},
{
name: "success",
org: "mlab",
project: "mlab-autojoin",
want: "mlab.autojoin.measurement-lab.org.",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := OrgDNS(tt.org, tt.project); got != tt.want {
t.Errorf("OrgDNS() = %v, want %v", got, tt.want)
}
})
}
}
17 changes: 17 additions & 0 deletions internal/dnsx/dnsiface/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,20 @@ import (
type Service interface {
ResourceRecordSetsGet(ctx context.Context, project string, zone string, name string, type_ string) (*dns.ResourceRecordSet, error)
ChangeCreate(ctx context.Context, project string, zone string, change *dns.Change) (*dns.Change, error)
GetManagedZone(ctx context.Context, project, zoneName string) (*dns.ManagedZone, error)
CreateManagedZone(ctx context.Context, project string, z *dns.ManagedZone) (*dns.ManagedZone, error)
}

// CloudDNSService implements the DNS Service interface.
type CloudDNSService struct {
Service *dns.Service
}

// NewCloudDNSService creates a new instance of the CloudDNSService.
func NewCloudDNSService(s *dns.Service) *CloudDNSService {
return &CloudDNSService{Service: s}
}

// ResourceRecordSetsGet gets an existing resource record set, if present.
func (c *CloudDNSService) ResourceRecordSetsGet(ctx context.Context, project string, zone string, name string, rtype string) (*dns.ResourceRecordSet, error) {
return c.Service.ResourceRecordSets.Get(project, zone, name, rtype).Context(ctx).Do()
Expand All @@ -26,3 +33,13 @@ func (c *CloudDNSService) ResourceRecordSetsGet(ctx context.Context, project str
func (c *CloudDNSService) ChangeCreate(ctx context.Context, project string, zone string, change *dns.Change) (*dns.Change, error) {
return c.Service.Changes.Create(project, zone, change).Context(ctx).Do()
}

// GetManagedZone gets the named zone.
func (c *CloudDNSService) GetManagedZone(ctx context.Context, project, zoneName string) (*dns.ManagedZone, error) {
return c.Service.ManagedZones.Get(project, zoneName).Context(ctx).Do()
}

// CreateManagedZone creates the given zone.
func (c *CloudDNSService) CreateManagedZone(ctx context.Context, project string, zone *dns.ManagedZone) (*dns.ManagedZone, error) {
return c.Service.ManagedZones.Create(project, zone).Context(ctx).Do()
}
7 changes: 7 additions & 0 deletions internal/dnsx/register_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ func (f *fakeDNS) ChangeCreate(ctx context.Context, project string, zone string,
return change, nil
}

func (f *fakeDNS) CreateManagedZone(ctx context.Context, project string, zone *dns.ManagedZone) (*dns.ManagedZone, error) {
return nil, nil
}
func (f *fakeDNS) GetManagedZone(ctx context.Context, project, zoneName string) (*dns.ManagedZone, error) {
return nil, nil
}

func TestManager_Register(t *testing.T) {
tests := []struct {
name string
Expand Down
22 changes: 8 additions & 14 deletions internal/register/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,17 @@ var (

// Params is used internally to collect multiple parameters.
type Params struct {
Project string
Service string
Org string
IPv4 string
IPv6 string
Geo *geoip2.City
Metro iata.Row
Network *annotator.Network
Project string
Service string
Org string
IPv4 string
IPv6 string
Geo *geoip2.City
Metro iata.Row
Network *annotator.Network
Probability float64
}

// OrgZone generates the organization zone name based the organization and project.
func OrgZone(org, project string) string {
// NOTE: prefix prevents name collision with existing zones when the org is "mlab".
return "autojoin-" + org + "-" + strings.TrimPrefix(project, "mlab-") + "-measurement-lab-org"
}

// CreateRegisterResponse generates a RegisterResponse from the given
// parameters. As an internal package, the caller is required to validate all
// input parameters.
Expand Down
23 changes: 0 additions & 23 deletions internal/register/register_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,26 +117,3 @@ func TestCreateRegisterResponse(t *testing.T) {
})
}
}

func TestOrgZone(t *testing.T) {
tests := []struct {
name string
org string
project string
want string
}{
{
name: "success",
org: "mlab",
project: "mlab-sandbox",
want: "autojoin-mlab-sandbox-measurement-lab-org",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := OrgZone(tt.org, tt.project); got != tt.want {
t.Errorf("OrgZone() = %v, want %v", got, tt.want)
}
})
}
}
4 changes: 2 additions & 2 deletions internal/tracker/gc.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import (
"time"

"github.com/gomodule/redigo/redis"
"github.com/m-lab/autojoin/internal/dnsname"
"github.com/m-lab/autojoin/internal/dnsx"
"github.com/m-lab/autojoin/internal/dnsx/dnsiface"
"github.com/m-lab/autojoin/internal/register"
"github.com/m-lab/go/host"
"github.com/m-lab/locate/memorystore"
)
Expand Down Expand Up @@ -133,7 +133,7 @@ func (gc *GarbageCollector) checkAndRemoveExpired() ([]string, [][]string, error
// TODO(rd): count errors with a Prometheus metric
}

m := dnsx.NewManager(gc.dns, gc.project, register.OrgZone(name.Org, gc.project))
m := dnsx.NewManager(gc.dns, gc.project, dnsname.OrgZone(name.Org, gc.project))
_, err = m.Delete(context.Background(), name.StringAll()+".")
if err != nil {
log.Printf("Failed to delete DNS entry for %s: %v", name, err)
Expand Down
6 changes: 6 additions & 0 deletions internal/tracker/gc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ func (f *fakeDNS) ResourceRecordSetsGet(ctx context.Context, project string, zon
func (f *fakeDNS) ChangeCreate(ctx context.Context, project string, zone string, change *dns.Change) (*dns.Change, error) {
return nil, f.chgErr
}
func (f *fakeDNS) CreateManagedZone(ctx context.Context, project string, zone *dns.ManagedZone) (*dns.ManagedZone, error) {
return nil, nil
}
func (f *fakeDNS) GetManagedZone(ctx context.Context, project, zoneName string) (*dns.ManagedZone, error) {
return nil, nil
}

type fakeMemorystoreClient[V any] struct {
putErr error
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func main() {
// Setup DNS service.
ds, err := dns.NewService(mainCtx)
rtx.Must(err, "failed to create new dns service")
d := &dnsiface.CloudDNSService{Service: ds}
d := dnsiface.NewCloudDNSService(ds)

// Setup IATA, maxmind, and asn sources.
i, err := iata.New(mainCtx, iataSrc.URL)
Expand Down

0 comments on commit af21ff6

Please sign in to comment.