mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-05-11 05:55:12 +00:00
* Added registrar support to Route53 provider * ran gofmt on route53Provider * Caveat: If you use r53 is a Registrar but not as a Dns Service Provider, DNSControl may be DNS-related API calls that you do not have IAM permissions to do.
This commit is contained in:
committed by
Tom Limoncelli
parent
8cff3128ea
commit
7f01a8c9ad
@@ -3,6 +3,7 @@ package route53
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -12,20 +13,34 @@ import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/private/waiter"
|
||||
r53 "github.com/aws/aws-sdk-go/service/route53"
|
||||
r53d "github.com/aws/aws-sdk-go/service/route53domains"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type route53Provider struct {
|
||||
client *r53.Route53
|
||||
zones map[string]*r53.HostedZone
|
||||
client *r53.Route53
|
||||
registrar *r53d.Route53Domains
|
||||
zones map[string]*r53.HostedZone
|
||||
}
|
||||
|
||||
func newRoute53(m map[string]string, metadata json.RawMessage) (providers.DNSServiceProvider, error) {
|
||||
func newRoute53Reg(conf map[string]string) (providers.Registrar, error) {
|
||||
return newRoute53(conf, nil)
|
||||
}
|
||||
|
||||
func newRoute53Dsp(conf map[string]string, metadata json.RawMessage) (providers.DNSServiceProvider, error) {
|
||||
return newRoute53(conf, metadata)
|
||||
}
|
||||
|
||||
func newRoute53(m map[string]string, metadata json.RawMessage) (*route53Provider, error) {
|
||||
keyId, secretKey := m["KeyId"], m["SecretKey"]
|
||||
|
||||
// Route53 uses a global endpoint and route53domains
|
||||
// currently only has a single regional endpoint in us-east-1
|
||||
// http://docs.aws.amazon.com/general/latest/gr/rande.html#r53_region
|
||||
config := &aws.Config{
|
||||
Region: aws.String("us-west-2"),
|
||||
Region: aws.String("us-east-1"),
|
||||
}
|
||||
|
||||
if keyId != "" || secretKey != "" {
|
||||
@@ -33,7 +48,7 @@ func newRoute53(m map[string]string, metadata json.RawMessage) (providers.DNSSer
|
||||
}
|
||||
sess := session.New(config)
|
||||
|
||||
api := &route53Provider{client: r53.New(sess)}
|
||||
api := &route53Provider{client: r53.New(sess), registrar: r53d.New(sess)}
|
||||
err := api.getZones()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -42,8 +57,10 @@ func newRoute53(m map[string]string, metadata json.RawMessage) (providers.DNSSer
|
||||
}
|
||||
|
||||
func init() {
|
||||
providers.RegisterDomainServiceProviderType("ROUTE53", newRoute53, providers.CanUsePTR, providers.CanUseSRV)
|
||||
providers.RegisterDomainServiceProviderType("ROUTE53", newRoute53Dsp, providers.CanUsePTR, providers.CanUseSRV)
|
||||
providers.RegisterRegistrarType("ROUTE53", newRoute53Reg)
|
||||
}
|
||||
|
||||
func sPtr(s string) *string {
|
||||
return &s
|
||||
}
|
||||
@@ -249,6 +266,69 @@ func (r *route53Provider) GetDomainCorrections(dc *models.DomainConfig) ([]*mode
|
||||
|
||||
}
|
||||
|
||||
func (r *route53Provider) GetRegistrarCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
|
||||
corrections := []*models.Correction{}
|
||||
actualSet, err := r.getRegistrarNameservers(&dc.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sort.Strings(actualSet)
|
||||
actual := strings.Join(actualSet, ",")
|
||||
|
||||
expectedSet := []string{}
|
||||
for _, ns := range dc.Nameservers {
|
||||
expectedSet = append(expectedSet, ns.Name)
|
||||
}
|
||||
sort.Strings(expectedSet)
|
||||
expected := strings.Join(expectedSet, ",")
|
||||
|
||||
if actual != expected {
|
||||
return []*models.Correction{
|
||||
{
|
||||
Msg: fmt.Sprintf("Update nameservers %s -> %s", actual, expected),
|
||||
F: func() error {
|
||||
operationId, err := r.updateRegistrarNameservers(dc.Name, expectedSet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return r.waitUntilNameserversUpdate(operationId)
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
func (r *route53Provider) getRegistrarNameservers(domainName *string) ([]string, error) {
|
||||
domainDetail, err := r.registrar.GetDomainDetail(&r53d.GetDomainDetailInput{DomainName: domainName})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nameservers := []string{}
|
||||
for _, ns := range domainDetail.Nameservers {
|
||||
nameservers = append(nameservers, *ns.Name)
|
||||
}
|
||||
|
||||
return nameservers, nil
|
||||
}
|
||||
|
||||
func (r *route53Provider) updateRegistrarNameservers(domainName string, nameservers []string) (*string, error) {
|
||||
servers := []*r53d.Nameserver{}
|
||||
for i := range nameservers {
|
||||
servers = append(servers, &r53d.Nameserver{Name: &nameservers[i]})
|
||||
}
|
||||
|
||||
domainUpdate, err := r.registrar.UpdateDomainNameservers(&r53d.UpdateDomainNameserversInput{DomainName: &domainName, Nameservers: servers})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return domainUpdate.OperationId, nil
|
||||
}
|
||||
|
||||
func (r *route53Provider) fetchRecordSets(zoneID *string) ([]*r53.ResourceRecordSet, error) {
|
||||
if zoneID == nil || *zoneID == "" {
|
||||
return nil, nil
|
||||
@@ -301,3 +381,31 @@ func (r *route53Provider) EnsureDomainExists(domain string) error {
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
func (r *route53Provider) waitUntilNameserversUpdate(operationId *string) error {
|
||||
fmt.Print("Waiting for registrar update to complete...")
|
||||
|
||||
waiterCfg := waiter.Config{
|
||||
Operation: "GetOperationDetail",
|
||||
Delay: 30,
|
||||
MaxAttempts: 10,
|
||||
Acceptors: []waiter.WaitAcceptor{
|
||||
{
|
||||
State: "success",
|
||||
Matcher: "path",
|
||||
Argument: "Status",
|
||||
Expected: "SUCCESSFUL",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
w := waiter.Waiter{
|
||||
Client: r.registrar,
|
||||
Input: &r53d.GetOperationDetailInput{
|
||||
OperationId: operationId,
|
||||
},
|
||||
Config: waiterCfg,
|
||||
}
|
||||
|
||||
return w.Wait()
|
||||
}
|
||||
|
Reference in New Issue
Block a user