mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-05-11 05:55:12 +00:00
Add R53_ZONE as an domain identifier (#1241)
Using R53_ZONE allows you to differentiate between split horizon domains across zones.
This commit is contained in:
@ -4,8 +4,12 @@ parameters:
|
|||||||
- zone_id
|
- zone_id
|
||||||
---
|
---
|
||||||
|
|
||||||
R53_ZONE sets the required Route53 hosted zone id in a R53_ALIAS record.
|
R53_ZONE lets you specify the AWS Zone ID for an entire domain (D()) or a specific R53_ALIAS() record.
|
||||||
|
|
||||||
|
When used with D(), it sets the zone id of the domain. This can be used to differentiate between split horizon domains in public and private zones.
|
||||||
|
|
||||||
|
When used with R53_ALIAS() it sets the required Route53 hosted zone id in a R53_ALIAS record. See [https://stackexchange.github.io/dnscontrol/js#R53_ALIAS](R53_ALIAS's documentation) for details.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
This directive has no impact when used in anything else than a R53_ALIAS.
|
|
||||||
|
|
||||||
Please refer to the R53_ALIAS directive for usage.
|
|
@ -26,6 +26,10 @@ function initialize() {
|
|||||||
defaultArgs = [];
|
defaultArgs = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _isDomain(d) {
|
||||||
|
return _.isArray(d.nameservers) && _.isArray(d.records) && _.isString(d.name);
|
||||||
|
}
|
||||||
|
|
||||||
// Returns an array of domains which were registered so far during runtime
|
// Returns an array of domains which were registered so far during runtime
|
||||||
// Own function for compatibility reasons or if some day special processing would be required.
|
// Own function for compatibility reasons or if some day special processing would be required.
|
||||||
function getConfiguredDomains() {
|
function getConfiguredDomains() {
|
||||||
@ -276,8 +280,10 @@ var R53_ALIAS = recordBuilder('R53_ALIAS', {
|
|||||||
|
|
||||||
// R53_ZONE(zone_id)
|
// R53_ZONE(zone_id)
|
||||||
function R53_ZONE(zone_id) {
|
function R53_ZONE(zone_id) {
|
||||||
return function(r) {
|
return function (r) {
|
||||||
if (_.isObject(r.r53_alias)) {
|
if (_isDomain(r)) {
|
||||||
|
r.meta.zone_id = zone_id;
|
||||||
|
} else if (_.isObject(r.r53_alias)) {
|
||||||
r.r53_alias['zone_id'] = zone_id;
|
r.r53_alias['zone_id'] = zone_id;
|
||||||
} else {
|
} else {
|
||||||
r.r53_alias = { zone_id: zone_id };
|
r.r53_alias = { zone_id: zone_id };
|
||||||
|
7
pkg/js/parse_tests/040-r53-zone.js
Normal file
7
pkg/js/parse_tests/040-r53-zone.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
D('foo.com', 'none', R53_ZONE('Z2FTEDLFRTZ'));
|
||||||
|
D(
|
||||||
|
'foo.com!internal',
|
||||||
|
'none',
|
||||||
|
R53_ZONE('Z2FTEDLFRTF'),
|
||||||
|
R53_ALIAS('atest', 'A', 'foo.com.', R53_ZONE('Z2FTEDLFRTZ'))
|
||||||
|
);
|
34
pkg/js/parse_tests/040-r53-zone.json
Normal file
34
pkg/js/parse_tests/040-r53-zone.json
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"registrars": [],
|
||||||
|
"dns_providers": [],
|
||||||
|
"domains": [
|
||||||
|
{
|
||||||
|
"name": "foo.com",
|
||||||
|
"registrar": "none",
|
||||||
|
"dnsProviders": {},
|
||||||
|
"records": [],
|
||||||
|
"meta": {
|
||||||
|
"zone_id": "Z2FTEDLFRTZ"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "foo.com!internal",
|
||||||
|
"registrar": "none",
|
||||||
|
"dnsProviders": {},
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"type": "R53_ALIAS",
|
||||||
|
"name": "atest",
|
||||||
|
"r53_alias": {
|
||||||
|
"type": "A",
|
||||||
|
"zone_id": "Z2FTEDLFRTZ"
|
||||||
|
},
|
||||||
|
"target": "foo.com."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"zone_id": "Z2FTEDLFRTF"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -25,7 +25,8 @@ type route53Provider struct {
|
|||||||
client *r53.Route53
|
client *r53.Route53
|
||||||
registrar *r53d.Route53Domains
|
registrar *r53d.Route53Domains
|
||||||
delegationSet *string
|
delegationSet *string
|
||||||
zones map[string]*r53.HostedZone
|
zonesById map[string]*r53.HostedZone
|
||||||
|
zonesByDomain map[string]*r53.HostedZone
|
||||||
originalRecords []*r53.ResourceRecordSet
|
originalRecords []*r53.ResourceRecordSet
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +120,7 @@ func withRetry(f func() error) {
|
|||||||
func (r *route53Provider) ListZones() ([]string, error) {
|
func (r *route53Provider) ListZones() ([]string, error) {
|
||||||
var zones []string
|
var zones []string
|
||||||
// Assumes r.zones was filled already by newRoute53().
|
// Assumes r.zones was filled already by newRoute53().
|
||||||
for i := range r.zones {
|
for i := range r.zonesByDomain {
|
||||||
zones = append(zones, i)
|
zones = append(zones, i)
|
||||||
}
|
}
|
||||||
return zones, nil
|
return zones, nil
|
||||||
@ -127,7 +128,8 @@ func (r *route53Provider) ListZones() ([]string, error) {
|
|||||||
|
|
||||||
func (r *route53Provider) getZones() error {
|
func (r *route53Provider) getZones() error {
|
||||||
var nextMarker *string
|
var nextMarker *string
|
||||||
r.zones = make(map[string]*r53.HostedZone)
|
r.zonesByDomain = make(map[string]*r53.HostedZone)
|
||||||
|
r.zonesById = make(map[string]*r53.HostedZone)
|
||||||
for {
|
for {
|
||||||
var out *r53.ListHostedZonesOutput
|
var out *r53.ListHostedZonesOutput
|
||||||
var err error
|
var err error
|
||||||
@ -143,7 +145,8 @@ func (r *route53Provider) getZones() error {
|
|||||||
}
|
}
|
||||||
for _, z := range out.HostedZones {
|
for _, z := range out.HostedZones {
|
||||||
domain := strings.TrimSuffix(*z.Name, ".")
|
domain := strings.TrimSuffix(*z.Name, ".")
|
||||||
r.zones[domain] = z
|
r.zonesByDomain[domain] = z
|
||||||
|
r.zonesById[parseZoneId(*z.Id)] = z
|
||||||
}
|
}
|
||||||
if out.NextMarker != nil {
|
if out.NextMarker != nil {
|
||||||
nextMarker = out.NextMarker
|
nextMarker = out.NextMarker
|
||||||
@ -154,19 +157,27 @@ func (r *route53Provider) getZones() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type errNoExist struct {
|
type errDomainNoExist struct {
|
||||||
domain string
|
domain string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e errNoExist) Error() string {
|
type errZoneNoExist struct {
|
||||||
|
zoneId string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e errDomainNoExist) Error() string {
|
||||||
return fmt.Sprintf("Domain %s not found in your route 53 account", e.domain)
|
return fmt.Sprintf("Domain %s not found in your route 53 account", e.domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e errZoneNoExist) Error() string {
|
||||||
|
return fmt.Sprintf("Zone with id %s not found in your route 53 account", e.zoneId)
|
||||||
|
}
|
||||||
|
|
||||||
func (r *route53Provider) GetNameservers(domain string) ([]*models.Nameserver, error) {
|
func (r *route53Provider) GetNameservers(domain string) ([]*models.Nameserver, error) {
|
||||||
|
|
||||||
zone, ok := r.zones[domain]
|
zone, ok := r.zonesByDomain[domain]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errNoExist{domain}
|
return nil, errDomainNoExist{domain}
|
||||||
}
|
}
|
||||||
var z *r53.GetHostedZoneOutput
|
var z *r53.GetHostedZoneOutput
|
||||||
var err error
|
var err error
|
||||||
@ -187,14 +198,31 @@ func (r *route53Provider) GetNameservers(domain string) ([]*models.Nameserver, e
|
|||||||
return models.ToNameservers(nss)
|
return models.ToNameservers(nss)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetZoneRecords gets the records of a zone and returns them in RecordConfig format.
|
|
||||||
func (r *route53Provider) GetZoneRecords(domain string) (models.Records, error) {
|
func (r *route53Provider) GetZoneRecords(domain string) (models.Records, error) {
|
||||||
|
if zone, ok := r.zonesByDomain[domain]; ok {
|
||||||
zone, ok := r.zones[domain]
|
return r.getZoneRecords(zone)
|
||||||
if !ok {
|
|
||||||
return nil, errNoExist{domain}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil, errDomainNoExist{domain}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *route53Provider) getZone(dc *models.DomainConfig) (*r53.HostedZone, error) {
|
||||||
|
if zoneId, ok := dc.Metadata["zone_id"]; ok {
|
||||||
|
zone, ok := r.zonesById[zoneId]
|
||||||
|
if !ok {
|
||||||
|
return nil, errZoneNoExist{zoneId}
|
||||||
|
}
|
||||||
|
return zone, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if zone, ok := r.zonesByDomain[dc.Name]; ok {
|
||||||
|
return zone, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, errDomainNoExist{dc.Name}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *route53Provider) getZoneRecords(zone *r53.HostedZone) (models.Records, error) {
|
||||||
records, err := r.fetchRecordSets(zone.Id)
|
records, err := r.fetchRecordSets(zone.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -203,7 +231,7 @@ func (r *route53Provider) GetZoneRecords(domain string) (models.Records, error)
|
|||||||
|
|
||||||
var existingRecords = []*models.RecordConfig{}
|
var existingRecords = []*models.RecordConfig{}
|
||||||
for _, set := range records {
|
for _, set := range records {
|
||||||
rts, err := nativeToRecords(set, domain)
|
rts, err := nativeToRecords(set, unescape(zone.Name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -217,14 +245,14 @@ func (r *route53Provider) GetDomainCorrections(dc *models.DomainConfig) ([]*mode
|
|||||||
|
|
||||||
var corrections = []*models.Correction{}
|
var corrections = []*models.Correction{}
|
||||||
|
|
||||||
existingRecords, err := r.GetZoneRecords(dc.Name)
|
zone, err := r.getZone(dc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
zone, ok := r.zones[dc.Name]
|
existingRecords, err := r.getZoneRecords(zone)
|
||||||
if !ok {
|
if err != nil {
|
||||||
return nil, errNoExist{dc.Name}
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, want := range dc.Records {
|
for _, want := range dc.Records {
|
||||||
@ -492,6 +520,11 @@ func getZoneID(zone *r53.HostedZone, r *models.RecordConfig) string {
|
|||||||
if zoneID == "" {
|
if zoneID == "" {
|
||||||
zoneID = aws.StringValue(zone.Id)
|
zoneID = aws.StringValue(zone.Id)
|
||||||
}
|
}
|
||||||
|
return parseZoneId(zoneID)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Removes "/hostedzone/"" prefix from AWS ZoneId */
|
||||||
|
func parseZoneId(zoneID string) string {
|
||||||
if strings.HasPrefix(zoneID, "/hostedzone/") {
|
if strings.HasPrefix(zoneID, "/hostedzone/") {
|
||||||
zoneID = strings.TrimPrefix(zoneID, "/hostedzone/")
|
zoneID = strings.TrimPrefix(zoneID, "/hostedzone/")
|
||||||
}
|
}
|
||||||
@ -613,7 +646,7 @@ func unescape(s *string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *route53Provider) EnsureDomainExists(domain string) error {
|
func (r *route53Provider) EnsureDomainExists(domain string) error {
|
||||||
if _, ok := r.zones[domain]; ok {
|
if _, ok := r.zonesByDomain[domain]; ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if r.delegationSet != nil {
|
if r.delegationSet != nil {
|
||||||
|
Reference in New Issue
Block a user