mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-05-11 05:55:12 +00:00
* Stable comparison of metadata (#239) Iterating over a map in Go never produces twice the same ordering. Thus when comparing two metadata map with more than one key, the `differ` is always finding differences. To properly compare records metadata, we need to iterate the maps in a deterministic way. Signed-off-by: Brice Figureau <brice@daysofwonder.com> * Support for Route53 ALIAS record type (#239) Route53 ALIAS doesn't behave like a regular ALIAS, and is much more limited as its target can only be some specific AWS resources or another record in the same zone. According to #239, this change adds a new directive R53_ALIAS which implements this specific alias. This record type can only be used with the Route53 provider. This directive usage looks like this: ```js D("example.com", REGISTRAR, DnsProvider("ROUTE53"), R53_ALIAS("foo1", "A", "bar") // record in same zone R53_ALIAS("foo2", "A", "blahblah.elasticloadbalancing.us-west-1.amazonaws.com", R53_ZONE('Z368ELLRRE2KJ0')) // ELB in us-west-1 ``` Unfortunately, Route53 requires indicating the hosted zone id where the target is defined (those are listed in AWS documentation, see the R53_ALIAS documentation for links).
This commit is contained in:
committed by
Tom Limoncelli
parent
2fc55dfdc4
commit
7b8d608019
@@ -56,7 +56,7 @@ func newRoute53(m map[string]string, metadata json.RawMessage) (*route53Provider
|
||||
}
|
||||
|
||||
var features = providers.DocumentationNotes{
|
||||
providers.CanUseAlias: providers.Cannot("R53 does not provide a generic ALIAS functionality. They do have 'ALIAS' CNAME types to point at various AWS infrastructure, but dnscontrol has not implemented those."),
|
||||
providers.CanUseAlias: providers.Cannot("R53 does not provide a generic ALIAS functionality. Use R53_ALIAS instead."),
|
||||
providers.DocCreateDomains: providers.Can(),
|
||||
providers.DocDualHost: providers.Can(),
|
||||
providers.DocOfficiallySupported: providers.Can(),
|
||||
@@ -64,6 +64,7 @@ var features = providers.DocumentationNotes{
|
||||
providers.CanUseSRV: providers.Can(),
|
||||
providers.CanUseTXTMulti: providers.Can(),
|
||||
providers.CanUseCAA: providers.Can(),
|
||||
providers.CanUseRoute53Alias: providers.Can(),
|
||||
}
|
||||
|
||||
func init() {
|
||||
@@ -155,29 +156,48 @@ func (r *route53Provider) GetDomainCorrections(dc *models.DomainConfig) ([]*mode
|
||||
|
||||
var existingRecords = []*models.RecordConfig{}
|
||||
for _, set := range records {
|
||||
for _, rec := range set.ResourceRecords {
|
||||
if *set.Type == "SOA" {
|
||||
continue
|
||||
if set.AliasTarget == nil {
|
||||
for _, rec := range set.ResourceRecords {
|
||||
if *set.Type == "SOA" {
|
||||
continue
|
||||
}
|
||||
r := &models.RecordConfig{
|
||||
NameFQDN: unescape(set.Name),
|
||||
Type: *set.Type,
|
||||
Target: *rec.Value,
|
||||
TTL: uint32(*set.TTL),
|
||||
CombinedTarget: true,
|
||||
}
|
||||
existingRecords = append(existingRecords, r)
|
||||
}
|
||||
} else {
|
||||
r := &models.RecordConfig{
|
||||
NameFQDN: unescape(set.Name),
|
||||
Type: *set.Type,
|
||||
Target: *rec.Value,
|
||||
TTL: uint32(*set.TTL),
|
||||
Type: "R53_ALIAS",
|
||||
Target: aws.StringValue(set.AliasTarget.DNSName),
|
||||
CombinedTarget: true,
|
||||
TTL: 300,
|
||||
R53Alias: map[string]string{
|
||||
"type": *set.Type,
|
||||
"zone_id": *set.AliasTarget.HostedZoneId,
|
||||
},
|
||||
}
|
||||
existingRecords = append(existingRecords, r)
|
||||
}
|
||||
}
|
||||
for _, want := range dc.Records {
|
||||
want.MergeToTarget()
|
||||
// update zone_id to current zone.id if not specified by the user
|
||||
if want.Type == "R53_ALIAS" && want.R53Alias["zone_id"] == "" {
|
||||
want.R53Alias["zone_id"] = getZoneID(zone, want)
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize
|
||||
models.PostProcessRecords(existingRecords)
|
||||
|
||||
// diff
|
||||
differ := diff.New(dc)
|
||||
differ := diff.New(dc, getAliasMap)
|
||||
_, create, delete, modify := differ.IncrementalDiff(existingRecords)
|
||||
|
||||
namesToUpdate := map[key][]string{}
|
||||
@@ -219,7 +239,7 @@ func (r *route53Provider) GetDomainCorrections(dc *models.DomainConfig) ([]*mode
|
||||
delDesc += strings.Join(namesToUpdate[k], "\n") + "\n"
|
||||
// on delete just submit the original resource set we got from r53.
|
||||
for _, r := range records {
|
||||
if *r.Name == k.Name+"." && *r.Type == k.Type {
|
||||
if *r.Name == k.Name+"." && (*r.Type == k.Type || k.Type == "R53_ALIAS") {
|
||||
rrset = r
|
||||
break
|
||||
}
|
||||
@@ -230,18 +250,21 @@ func (r *route53Provider) GetDomainCorrections(dc *models.DomainConfig) ([]*mode
|
||||
// on change or create, just build a new record set from our desired state
|
||||
chg.Action = sPtr("UPSERT")
|
||||
rrset = &r53.ResourceRecordSet{
|
||||
Name: sPtr(k.Name),
|
||||
Type: sPtr(k.Type),
|
||||
ResourceRecords: []*r53.ResourceRecord{},
|
||||
Name: sPtr(k.Name),
|
||||
Type: sPtr(k.Type),
|
||||
}
|
||||
for _, r := range recs {
|
||||
val := r.Target
|
||||
rr := &r53.ResourceRecord{
|
||||
Value: &val,
|
||||
if r.Type != "R53_ALIAS" {
|
||||
rr := &r53.ResourceRecord{
|
||||
Value: &val,
|
||||
}
|
||||
rrset.ResourceRecords = append(rrset.ResourceRecords, rr)
|
||||
i := int64(r.TTL)
|
||||
rrset.TTL = &i // TODO: make sure that ttls are consistent within a set
|
||||
} else {
|
||||
rrset = aliasToRRSet(zone, r)
|
||||
}
|
||||
rrset.ResourceRecords = append(rrset.ResourceRecords, rr)
|
||||
i := int64(r.TTL)
|
||||
rrset.TTL = &i // TODO: make sure that ttls are consistent within a set
|
||||
}
|
||||
}
|
||||
chg.ResourceRecordSet = rrset
|
||||
@@ -279,6 +302,39 @@ func (r *route53Provider) GetDomainCorrections(dc *models.DomainConfig) ([]*mode
|
||||
|
||||
}
|
||||
|
||||
func getAliasMap(r *models.RecordConfig) map[string]string {
|
||||
if r.Type != "R53_ALIAS" {
|
||||
return nil
|
||||
}
|
||||
return r.R53Alias
|
||||
}
|
||||
|
||||
func aliasToRRSet(zone *r53.HostedZone, r *models.RecordConfig) *r53.ResourceRecordSet {
|
||||
rrset := &r53.ResourceRecordSet{
|
||||
Name: sPtr(r.NameFQDN),
|
||||
Type: sPtr(r.R53Alias["type"]),
|
||||
}
|
||||
zoneID := getZoneID(zone, r)
|
||||
targetHealth := false
|
||||
rrset.AliasTarget = &r53.AliasTarget{
|
||||
DNSName: &r.Target,
|
||||
HostedZoneId: aws.String(zoneID),
|
||||
EvaluateTargetHealth: &targetHealth,
|
||||
}
|
||||
return rrset
|
||||
}
|
||||
|
||||
func getZoneID(zone *r53.HostedZone, r *models.RecordConfig) string {
|
||||
zoneID := r.R53Alias["zone_id"]
|
||||
if zoneID == "" {
|
||||
zoneID = aws.StringValue(zone.Id)
|
||||
}
|
||||
if strings.HasPrefix(zoneID, "/hostedzone/") {
|
||||
zoneID = strings.TrimPrefix(zoneID, "/hostedzone/")
|
||||
}
|
||||
return zoneID
|
||||
}
|
||||
|
||||
func (r *route53Provider) GetRegistrarCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
|
||||
corrections := []*models.Correction{}
|
||||
actualSet, err := r.getRegistrarNameservers(&dc.Name)
|
||||
|
Reference in New Issue
Block a user