@@ -19,6 +19,7 @@ package provider
1919
2020import (
2121 "context"
22+ "errors"
2223 "external-dns-openstack-webhook/internal/designate/client"
2324 "fmt"
2425 "strings"
@@ -52,10 +53,12 @@ type designateProvider struct {
5253 // only consider hosted zones managing domains ending in this suffix
5354 domainFilter endpoint.DomainFilter
5455 dryRun bool
56+
57+ ownerID string
5558}
5659
5760// NewDesignateProvider is a factory function for OpenStack designate providers
58- func NewDesignateProvider (domainFilter endpoint.DomainFilter , dryRun bool ) (provider.Provider , error ) {
61+ func NewDesignateProvider (domainFilter endpoint.DomainFilter , dryRun bool , ownerID string ) (provider.Provider , error ) {
5962 client , err := client .NewDesignateClient ()
6063 if err != nil {
6164 return nil , err
@@ -64,6 +67,7 @@ func NewDesignateProvider(domainFilter endpoint.DomainFilter, dryRun bool) (prov
6467 client : client ,
6568 domainFilter : domainFilter ,
6669 dryRun : dryRun ,
70+ ownerID : ownerID ,
6771 }, nil
6872}
6973
@@ -156,10 +160,25 @@ func (p designateProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, e
156160 }
157161
158162 ep := endpoint .NewEndpointWithTTL (recordSet .Name , recordSet .Type , endpoint .TTL (recordSet .TTL ), recordSet .Records ... )
159- ep .Labels [designateRecordSetID ] = recordSet .ID
160- ep .Labels [designateZoneID ] = recordSet .ZoneID
161- ep .Labels [designateOriginalRecords ] = strings .Join (recordSet .Records , "\000 " )
162- result = append (result , ep )
163+
164+ parsedLabels , err := endpoint .NewLabelsFromStringPlain (recordSet .Description )
165+ if err != nil && ! errors .Is (err , endpoint .ErrInvalidHeritage ) {
166+ return fmt .Errorf ("unable to parse label: %w" , err )
167+ }
168+ for k , v := range parsedLabels {
169+ ep .WithLabel (k , v )
170+ }
171+
172+ ep .
173+ WithLabel (designateRecordSetID , recordSet .ID ).
174+ WithLabel (designateZoneID , recordSet .ZoneID ).
175+ WithLabel (designateOriginalRecords , strings .Join (recordSet .Records , "\000 " ))
176+
177+ if ep .IsOwnedBy (p .ownerID ) {
178+ result = append (result , ep )
179+ } else {
180+ log .Debugf ("SKIP %s/%s due to owner not matching %s" , recordSet .Name , recordSet .Type , p .ownerID )
181+ }
163182
164183 return nil
165184 },
@@ -174,7 +193,7 @@ func (p designateProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, e
174193
175194func (p designateProvider ) supportedRecordType (recordType string ) bool {
176195 switch recordType {
177- case endpoint .RecordTypeA , endpoint .RecordTypeTXT , endpoint .RecordTypeCNAME , endpoint .RecordTypeNS , endpoint .RecordTypeMX :
196+ case endpoint .RecordTypeA , endpoint .RecordTypeTXT , endpoint .RecordTypeCNAME , endpoint .RecordTypeNS , endpoint .RecordTypeMX , "CAA" :
178197 return true
179198 default :
180199 return false
@@ -189,70 +208,63 @@ type recordSet struct {
189208 recordSetID string
190209 ttl int
191210 names map [string ]bool
211+ description string
192212}
193213
194214// adds endpoint into recordset aggregation, loading original values from endpoint labels first
195215func addEndpoint (ep * endpoint.Endpoint , recordSets map [string ]* recordSet , oldEndpoints []* endpoint.Endpoint , delete bool ) {
196216 key := fmt .Sprintf ("%s/%s" , ep .DNSName , ep .RecordType )
217+
197218 rs := recordSets [key ]
198219 if rs == nil {
220+ recordedLabels := endpoint .NewLabels ()
221+
222+ // Filter out our internal labels
223+ for k , v := range ep .Labels {
224+ switch k {
225+ case designateRecordSetID , designateZoneID , designateOriginalRecords :
226+ default :
227+ recordedLabels [k ] = v
228+ }
229+ }
199230 rs = & recordSet {
200- dnsName : canonicalizeDomainName (ep .DNSName ),
201- recordType : ep .RecordType ,
202- names : make (map [string ]bool ),
231+ dnsName : canonicalizeDomainName (ep .DNSName ),
232+ recordType : ep .RecordType ,
233+ names : make (map [string ]bool ),
234+ description : recordedLabels .SerializePlain (false ),
203235 }
204236 }
205237
206- addDesignateIDLabelsFromExistingEndpoints (oldEndpoints , ep )
207-
208- if rs .zoneID == "" {
209- rs .zoneID = ep .Labels [designateZoneID ]
238+ if zoneID , ok := ep .Labels [designateZoneID ]; ok {
239+ rs .zoneID = zoneID
210240 }
211- if rs . recordSetID == "" {
212- rs .recordSetID = ep . Labels [ designateRecordSetID ]
241+ if recordSetID , ok := ep . Labels [ designateRecordSetID ]; ok {
242+ rs .recordSetID = recordSetID
213243 }
214- rs .ttl = int (ep .RecordTTL )
215- for _ , rec := range strings .Split (ep .Labels [designateOriginalRecords ], "\000 " ) {
216- if _ , ok := rs .names [rec ]; ! ok && rec != "" {
217- rs .names [rec ] = true
244+ if origRecords , ok := ep .Labels [designateOriginalRecords ]; ok {
245+ for _ , rec := range strings .Split (origRecords , "\000 " ) {
246+ if _ , ok := rs .names [rec ]; ! ok && rec != "" {
247+ rs .names [rec ] = true
248+ }
218249 }
219250 }
251+ rs .ttl = int (ep .RecordTTL )
252+
220253 targets := ep .Targets
221254 if ep .RecordType == endpoint .RecordTypeCNAME || ep .RecordType == endpoint .RecordTypeNS {
222255 targets = canonicalizeDomainNames (targets )
223256 }
257+
224258 if ep .RecordType == endpoint .RecordTypeMX {
225259 targets = canonicalizeDomainNamesForMX (targets )
226260 }
261+
227262 for _ , t := range targets {
228263 rs .names [t ] = ! delete
229264 }
230265 recordSets [key ] = rs
231266}
232267
233- // addDesignateIDLabelsFromExistingEndpoints adds the labels identified by the constants designateZoneID and designateRecordSetID
234- // to an Endpoint. Therefore, it searches all given existing endpoints for an endpoint with the same record type and record
235- // value. If the given Endpoint already has the labels set, they are left untouched. This fixes an issue with the
236- // TXTRegistry which generates new TXT entries instead of updating the old ones.
237- func addDesignateIDLabelsFromExistingEndpoints (existingEndpoints []* endpoint.Endpoint , ep * endpoint.Endpoint ) {
238- _ , hasZoneIDLabel := ep .Labels [designateZoneID ]
239- _ , hasRecordSetIDLabel := ep .Labels [designateRecordSetID ]
240- if hasZoneIDLabel && hasRecordSetIDLabel {
241- return
242- }
243- for _ , oep := range existingEndpoints {
244- if ep .RecordType == oep .RecordType && ep .DNSName == oep .DNSName {
245- if ! hasZoneIDLabel {
246- ep .Labels [designateZoneID ] = oep .Labels [designateZoneID ]
247- }
248- if ! hasRecordSetIDLabel {
249- ep .Labels [designateRecordSetID ] = oep .Labels [designateRecordSetID ]
250- }
251- return
252- }
253- }
254- }
255-
256268// ApplyChanges applies a given set of changes in a given zone.
257269func (p designateProvider ) ApplyChanges (ctx context.Context , changes * plan.Changes ) error {
258270 managedZones , err := p .getZones (ctx )
@@ -265,17 +277,25 @@ func (p designateProvider) ApplyChanges(ctx context.Context, changes *plan.Chang
265277 return fmt .Errorf ("failed to fetch active records: %w" , err )
266278 }
267279
280+ for _ , ep := range changes .Create {
281+ log .Debugf ("CREATE %v" , ep )
282+ }
283+
268284 recordSets := map [string ]* recordSet {}
285+
286+ logPlan (changes )
287+
269288 for _ , ep := range changes .Create {
289+ ep .Labels [endpoint .OwnerLabelKey ] = p .ownerID
270290 addEndpoint (ep , recordSets , endpoints , false )
271291 }
272- for _ , ep := range changes .UpdateOld {
292+ for _ , ep := range endpoint . FilterEndpointsByOwnerID ( p . ownerID , changes .UpdateOld ) {
273293 addEndpoint (ep , recordSets , endpoints , true )
274294 }
275- for _ , ep := range changes .UpdateNew {
295+ for _ , ep := range endpoint . FilterEndpointsByOwnerID ( p . ownerID , changes .UpdateNew ) {
276296 addEndpoint (ep , recordSets , endpoints , false )
277297 }
278- for _ , ep := range changes .Delete {
298+ for _ , ep := range endpoint . FilterEndpointsByOwnerID ( p . ownerID , changes .Delete ) {
279299 addEndpoint (ep , recordSets , endpoints , true )
280300 }
281301
@@ -287,6 +307,24 @@ func (p designateProvider) ApplyChanges(ctx context.Context, changes *plan.Chang
287307 return err
288308}
289309
310+ func logPlan (plan * plan.Changes ) {
311+ infos := []struct {
312+ name string
313+ list []* endpoint.Endpoint
314+ }{
315+ {"CREATE" , plan .Create },
316+ {"UPDOLD" , plan .UpdateOld },
317+ {"UPDNEW" , plan .UpdateNew },
318+ {"DELETE" , plan .Delete },
319+ }
320+
321+ for _ , i := range infos {
322+ for _ , ep := range i .list {
323+ log .Debugf ("%s %v" , i .name , * ep )
324+ }
325+ }
326+ }
327+
290328// apply recordset changes by inserting/updating/deleting recordsets
291329func (p designateProvider ) upsertRecordSet (ctx context.Context , rs * recordSet , managedZones map [string ]string ) error {
292330 if rs .zoneID == "" {
@@ -307,10 +345,11 @@ func (p designateProvider) upsertRecordSet(ctx context.Context, rs *recordSet, m
307345 }
308346 if rs .recordSetID == "" {
309347 opts := recordsets.CreateOpts {
310- Name : rs .dnsName ,
311- Type : rs .recordType ,
312- Records : records ,
313- TTL : rs .ttl ,
348+ Name : rs .dnsName ,
349+ Type : rs .recordType ,
350+ Records : records ,
351+ TTL : rs .ttl ,
352+ Description : rs .description ,
314353 }
315354 log .Infof ("Creating records: %s/%s: %s" , rs .dnsName , rs .recordType , strings .Join (records , "," ))
316355 if p .dryRun {
@@ -326,8 +365,9 @@ func (p designateProvider) upsertRecordSet(ctx context.Context, rs *recordSet, m
326365 return p .client .DeleteRecordSet (ctx , rs .zoneID , rs .recordSetID )
327366 } else {
328367 opts := recordsets.UpdateOpts {
329- Records : records ,
330- TTL : & rs .ttl ,
368+ Records : records ,
369+ TTL : & rs .ttl ,
370+ Description : & rs .description ,
331371 }
332372 log .Infof ("Updating records: %s/%s: %s" , rs .dnsName , rs .recordType , strings .Join (records , "," ))
333373 if p .dryRun {
0 commit comments