Skip to content

Commit

Permalink
feat: Implement support for PTR records (#22)
Browse files Browse the repository at this point in the history
* feat: Implement PTR records

* fix: fix linter errors
  • Loading branch information
fust authored Nov 6, 2024
1 parent 821c450 commit ca1cbaf
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 66 deletions.
74 changes: 14 additions & 60 deletions internal/infoblox/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,31 +101,20 @@ func ToHostResponseMap(res []ibclient.HostRecord) *ResponseMap {
return rm
}

// TODO: ToPTRResponseMap
//if p.createPTR {
// // infoblox doesn't accept reverse zone's fqdn, and instead expects .in-addr.arpa zone
// // so convert our zone fqdn (if it is a correct cidr block) into in-addr.arpa address and pass that into infoblox
// // example: 10.196.38.0/24 becomes 38.196.10.in-addr.arpa
// arpaZone, err := transform.ReverseDomainName(zone.Fqdn)
// if err == nil {
// var resP []ibclient.RecordPTR
// objP := ibclient.NewEmptyRecordPTR()
// objP.Zone = arpaZone
// objP.View = p.view
// err = p.client.GetObject(objP, "", searchParams, &resP)
// if err != nil && !isNotFoundError(err) {
// return nil, fmt.Errorf("could not fetch PTR records from zone '%s': %w", zone.Fqdn, err)
// }
// for _, res := range resP {
// endpoints = append(endpoints, endpoint.NewEndpointWithTTL(res.PtrdName,
// endpoint.RecordTypePTR,
// endpoint.TTL(int(res.Ttl)),
// res.Ipv4Addr,
// ),
// )
// }
// }
//}
func ToPTRResponseMap(res []ibclient.RecordPTR) *ResponseMap {
rm := &ResponseMap{
Map: make(map[string]ResponseDetails),
RecordType: ibclient.PtrRecord,
}
for _, record := range res {
if _, ok := rm.Map[AsString(record.PtrdName)]; !ok {
rm.Map[AsString(record.PtrdName)] = ResponseDetails{{Target: AsString(record.Ipv4Addr), TTL: AsInt64(record.Ttl)}}
continue
}
rm.Map[AsString(record.PtrdName)] = append(rm.Map[AsString(record.PtrdName)], ResponseDetail{Target: AsString(record.Ipv4Addr), TTL: AsInt64(record.Ttl)})
}
return rm
}

func (rd ResponseDetails) ToEndpointDetail() (targets []string, ttl endpoint.TTL) {
for _, v := range rd {
Expand All @@ -136,10 +125,6 @@ func (rd ResponseDetails) ToEndpointDetail() (targets []string, ttl endpoint.TTL
}

func (rm *ResponseMap) ToEndpoints() []*endpoint.Endpoint {
// TODO: PTR provider specific label records
// if p.createPTR {
// newEndpoint.WithProviderSpecific(providerSpecificInfobloxPtrRecord, "true")
// }
var endpoints []*endpoint.Endpoint
for k, v := range rm.Map {
targets, ttl := v.ToEndpointDetail()
Expand All @@ -149,34 +134,3 @@ func (rm *ResponseMap) ToEndpoints() []*endpoint.Endpoint {
}
return endpoints
}

// TODO: update A records that have PTR record created for them already
//if p.createPTR {
// // save all ptr records into map for a quick look up
// ptrRecordsMap := make(map[string]bool)
// for _, ptrRecord := range endpoints {
// if ptrRecord.RecordType != endpoint.RecordTypePTR {
// continue
// }
// ptrRecordsMap[ptrRecord.DNSName] = true
// }
//
// for i := range endpoints {
// if endpoints[i].RecordType != endpoint.RecordTypeA {
// continue
// }
// // if PTR record already exists for A record, then mark it as such
// if ptrRecordsMap[endpoints[i].DNSName] {
// found := false
// for j := range endpoints[i].ProviderSpecific {
// if endpoints[i].ProviderSpecific[j].Name == providerSpecificInfobloxPtrRecord {
// endpoints[i].ProviderSpecific[j].Value = "true"
// found = true
// }
// }
// if !found {
// endpoints[i].WithProviderSpecific(providerSpecificInfobloxPtrRecord, "true")
// }
// }
// }
//}
49 changes: 49 additions & 0 deletions internal/infoblox/infoblox.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
log "github.com/sirupsen/logrus"

"sigs.k8s.io/external-dns/endpoint"
"sigs.k8s.io/external-dns/pkg/rfc2317"
"sigs.k8s.io/external-dns/plan"
"sigs.k8s.io/external-dns/provider"
)
Expand Down Expand Up @@ -240,6 +241,54 @@ func (p *Provider) Records(_ context.Context) (endpoints []*endpoint.Endpoint, e
}
endpointsTXT := ToTXTResponseMap(resT).ToEndpoints()
endpoints = append(endpoints, endpointsTXT...)

if p.config.CreatePTR {
arpaZone, err := rfc2317.CidrToInAddr(zone.Fqdn)
if err == nil {
var resP []ibclient.RecordPTR
objP := ibclient.NewEmptyRecordPTR()
objP.View = p.config.View
objP.Zone = arpaZone
err = PagingGetObject(p.client, objP, "", map[string]string{"zone": arpaZone, "view": p.config.View}, &resP)
if err != nil && !isNotFoundError(err) {
return nil, fmt.Errorf("could not fetch PTR records from zone '%s': %w", zone.Fqdn, err)
}
endpointsPTR := ToPTRResponseMap(resP).ToEndpoints()
endpoints = append(endpoints, endpointsPTR...)
} else {
log.Debugf("Could not fetch PTR records from zone '%s': %s", zone.Fqdn, err)
}
}
}

if p.config.CreatePTR {
// save all ptr records into map for a quick look up
ptrRecordsMap := make(map[string]bool)
for _, ptrRecord := range endpoints {
if ptrRecord.RecordType != endpoint.RecordTypePTR {
continue
}
ptrRecordsMap[ptrRecord.DNSName] = true
}

for i := range endpoints {
if endpoints[i].RecordType != endpoint.RecordTypeA {
continue
}
// if PTR record already exists for A record, then mark it as such
if ptrRecordsMap[endpoints[i].DNSName] {
found := false
for j := range endpoints[i].ProviderSpecific {
if endpoints[i].ProviderSpecific[j].Name == providerSpecificInfobloxPtrRecord {
endpoints[i].ProviderSpecific[j].Value = "true"
found = true
}
}
if !found {
endpoints[i].WithProviderSpecific(providerSpecificInfobloxPtrRecord, "true")
}
}
}
}

log.Debugf("fetched %d records from infoblox", len(endpoints))
Expand Down
9 changes: 3 additions & 6 deletions internal/infoblox/infoblox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,12 +339,11 @@ func (client *mockIBConnector) GetObject(obj ibclient.IBObject, ref string, quer
ref != object.(*ibclient.RecordPTR).Ref {
continue
}
if *obj.(*ibclient.RecordPTR).PtrdName != "" &&
obj.(*ibclient.RecordPTR).PtrdName != object.(*ibclient.RecordPTR).PtrdName {
if AsString(obj.(*ibclient.RecordPTR).PtrdName) != "" &&
AsString(obj.(*ibclient.RecordPTR).PtrdName) != AsString(object.(*ibclient.RecordPTR).PtrdName) {
continue
}
// TODO:
if !strings.Contains(req.queryParams, fmt.Sprintf("ipv4addr:%s name:%s", AsString(object.(*ibclient.RecordPTR).Ipv4Addr), AsString(object.(*ibclient.RecordPTR).Name))) {
if !strings.Contains(req.queryParams, fmt.Sprintf("name:%s", AsString(object.(*ibclient.RecordPTR).Name))) {
if !strings.Contains(req.queryParams, fmt.Sprintf("zone:%s", object.(*ibclient.RecordPTR).Zone)) {
continue
}
Expand Down Expand Up @@ -790,7 +789,6 @@ func TestInfobloxAdjustEndpoints(t *testing.T) {
}

func TestInfobloxRecordsReverse(t *testing.T) {
t.Skip()
client := mockIBConnector{
mockInfobloxZones: &[]ibclient.ZoneAuth{
createMockInfobloxZone("10.0.0.0/24"),
Expand Down Expand Up @@ -845,7 +843,6 @@ func TestInfobloxApplyChanges(t *testing.T) {
}

func TestInfobloxApplyChangesReverse(t *testing.T) {
t.Skip()
client := mockIBConnector{}

testInfobloxApplyChangesInternal(t, false, true, &client)
Expand Down

0 comments on commit ca1cbaf

Please sign in to comment.