Skip to content

Commit

Permalink
Add RegisterDNS to adminx.Org Setup (#45)
Browse files Browse the repository at this point in the history
* Add RegisterDNS to Org.Setup
* Add DNS for NewOrg setup
  • Loading branch information
stephen-soltesz authored Sep 10, 2024
1 parent f9b2412 commit d9fdb22
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 5 deletions.
15 changes: 12 additions & 3 deletions cmd/orgadm/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ import (
"github.com/m-lab/autojoin/internal/adminx"
"github.com/m-lab/autojoin/internal/adminx/crmiface"
"github.com/m-lab/autojoin/internal/adminx/iamiface"
"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/go/rtx"
"google.golang.org/api/cloudresourcemanager/v1"
"google.golang.org/api/dns/v1"
iam "google.golang.org/api/iam/v1"
)

Expand Down Expand Up @@ -38,13 +42,18 @@ func main() {
defer sc.Close()
ic, err := iam.NewService(ctx)
rtx.Must(err, "failed to create iam service client")
log.Println("Creating SAM & KEYS")
nn := adminx.NewNamer(project)
crm, err := cloudresourcemanager.NewService(ctx)
rtx.Must(err, "failed to allocate new cloud resource manager client")
sa := adminx.NewServiceAccountsManager(iamiface.NewIAM(ic), nn)
rtx.Must(err, "failed to create sam")
sm := adminx.NewSecretManager(sc, nn, sa)
o := adminx.NewOrg(project, crmiface.NewCRM(project, crm), sa, sm)
o.Setup(ctx, org)
ds, err := dns.NewService(ctx)
rtx.Must(err, "failed to create new dns service")
d := dnsx.NewManager(dnsiface.NewCloudDNSService(ds), project, dnsname.ProjectZone(project))

o := adminx.NewOrg(project, crmiface.NewCRM(project, crm), sa, sm, d)
err = o.Setup(ctx, org)
rtx.Must(err, "failed to set up new organization: "+org)
log.Println("okay")
}
35 changes: 34 additions & 1 deletion internal/adminx/org.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import (
"fmt"
"log"

"github.com/m-lab/autojoin/internal/dnsname"
"golang.org/x/exp/slices"

"google.golang.org/api/cloudresourcemanager/v1"
"google.golang.org/api/dns/v1"
"google.golang.org/api/iam/v1"
)

Expand All @@ -20,6 +22,12 @@ var (
` resource.name.startsWith("projects/_/buckets/staging-%s")`)
)

// DNS is a simplified interface to the Google Cloud DNS API.
type DNS interface {
RegisterZone(ctx context.Context, zone *dns.ManagedZone) (*dns.ManagedZone, error)
RegisterZoneSplit(ctx context.Context, zone *dns.ManagedZone) (*dns.ResourceRecordSet, error)
}

// CRM is a simplified interface to the Google Cloud Resource Manager API.
type CRM interface {
GetIamPolicy(ctx context.Context, req *cloudresourcemanager.GetIamPolicyRequest) (*cloudresourcemanager.Policy, error)
Expand All @@ -32,15 +40,17 @@ type Org struct {
crm CRM
sam *ServiceAccountsManager
sm *SecretManager
dns DNS
}

// NewOrg creates a new Org instance for setting up a new organization.
func NewOrg(project string, crm CRM, sam *ServiceAccountsManager, sm *SecretManager) *Org {
func NewOrg(project string, crm CRM, sam *ServiceAccountsManager, sm *SecretManager, dns DNS) *Org {
return &Org{
Project: project,
crm: crm,
sam: sam,
sm: sm,
dns: dns,
}
}

Expand All @@ -60,6 +70,29 @@ func (o *Org) Setup(ctx context.Context, org string) error {
if err != nil {
return err
}
// Create DNS zone and zone split.
return o.RegisterDNS(ctx, org)
}

// RegisterDNS creates the organization zone and the zone split within the project zone.
func (o *Org) RegisterDNS(ctx context.Context, org string) error {
zone, err := o.dns.RegisterZone(ctx, &dns.ManagedZone{
Description: "Autojoin registered nodes from org: " + org,
Name: dnsname.OrgZone(org, o.Project),
DnsName: dnsname.OrgDNS(org, o.Project),
DnssecConfig: &dns.ManagedZoneDnsSecConfig{
State: "on",
},
})
if err != nil {
log.Println("failed to register zone:", dnsname.OrgZone(org, o.Project), err)
return err
}
_, err = o.dns.RegisterZoneSplit(ctx, zone)
if err != nil {
log.Println("failed to register zone split:", dnsname.OrgZone(org, o.Project), err)
return err
}
return nil
}

Expand Down
86 changes: 85 additions & 1 deletion internal/adminx/org_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import (
"testing"

"cloud.google.com/go/secretmanager/apiv1/secretmanagerpb"
"github.com/m-lab/autojoin/internal/dnsname"
"google.golang.org/api/cloudresourcemanager/v1"
"google.golang.org/api/dns/v1"
"google.golang.org/api/iam/v1"
)

Expand All @@ -33,13 +35,29 @@ func (f *fakeCRM) SetIamPolicy(ctx context.Context, req *cloudresourcemanager.Se
return f.setPolicyErr
}

type fakeDNS struct {
regZone *dns.ManagedZone
regZoneErr error
regSplit *dns.ResourceRecordSet
regSplitErr error
}

func (f *fakeDNS) RegisterZone(ctx context.Context, zone *dns.ManagedZone) (*dns.ManagedZone, error) {
return f.regZone, f.regZoneErr
}

func (f *fakeDNS) RegisterZoneSplit(ctx context.Context, zone *dns.ManagedZone) (*dns.ResourceRecordSet, error) {
return f.regSplit, f.regSplitErr
}

func TestOrg_Setup(t *testing.T) {
tests := []struct {
name string
project string
crm CRM
sam IAMService
smc SecretManagerClient
dns DNS
org string
wantErr bool
}{
Expand All @@ -63,6 +81,66 @@ func TestOrg_Setup(t *testing.T) {
smc: &fakeSMC{
getSec: &secretmanagerpb.Secret{Name: "okay"},
},
dns: &fakeDNS{
regZone: &dns.ManagedZone{
Name: dnsname.OrgZone("foo", "mlab-foo"),
DnsName: dnsname.OrgDNS("foo", "mlab-foo"),
},
},
},
{
name: "error-register-zone",
crm: &fakeCRM{
getPolicy: &cloudresourcemanager.Policy{
Bindings: []*cloudresourcemanager.Binding{
{
Members: []string{"foo"},
Role: "roles/fooWriter",
},
},
},
},
sam: &fakeIAMService{
getAcct: &iam.ServiceAccount{
Name: "foo",
},
},
smc: &fakeSMC{
getSec: &secretmanagerpb.Secret{Name: "okay"},
},
dns: &fakeDNS{
regZoneErr: fmt.Errorf("fake zone registration error"),
},
wantErr: true,
},
{
name: "error-register-split",
crm: &fakeCRM{
getPolicy: &cloudresourcemanager.Policy{
Bindings: []*cloudresourcemanager.Binding{
{
Members: []string{"foo"},
Role: "roles/fooWriter",
},
},
},
},
sam: &fakeIAMService{
getAcct: &iam.ServiceAccount{
Name: "foo",
},
},
smc: &fakeSMC{
getSec: &secretmanagerpb.Secret{Name: "okay"},
},
dns: &fakeDNS{
regZone: &dns.ManagedZone{
Name: dnsname.OrgZone("foo", "mlab-foo"),
DnsName: dnsname.OrgDNS("foo", "mlab-foo"),
},
regSplitErr: fmt.Errorf("fake split register error"),
},
wantErr: true,
},
{
name: "success-equal-bindings",
Expand Down Expand Up @@ -92,6 +170,12 @@ func TestOrg_Setup(t *testing.T) {
smc: &fakeSMC{
getSec: &secretmanagerpb.Secret{Name: "okay"},
},
dns: &fakeDNS{
regZone: &dns.ManagedZone{
Name: dnsname.OrgZone("foo", "mlab-foo"),
DnsName: dnsname.OrgDNS("foo", "mlab-foo"),
},
},
},
{
name: "error-create-service-account",
Expand Down Expand Up @@ -160,7 +244,7 @@ func TestOrg_Setup(t *testing.T) {
n := NewNamer("mlab-foo")
sam := NewServiceAccountsManager(tt.sam, n)
sm := NewSecretManager(tt.smc, n, sam)
o := NewOrg("mlab-foo", tt.crm, sam, sm)
o := NewOrg("mlab-foo", tt.crm, sam, sm, tt.dns)
if err := o.Setup(context.Background(), "foobar"); (err != nil) != tt.wantErr {
t.Errorf("Org.Setup() error = %v, wantErr %v", err, tt.wantErr)
}
Expand Down

0 comments on commit d9fdb22

Please sign in to comment.