diff --git a/provider/pihole/pihole.go b/provider/pihole/pihole.go index a777affcc..0aabb7e5b 100644 --- a/provider/pihole/pihole.go +++ b/provider/pihole/pihole.go @@ -74,25 +74,40 @@ func (p *PiholeProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, err // ApplyChanges implements Provider, syncing desired state with the Pi-hole server Local DNS. func (p *PiholeProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) error { - // Handle deletions first - there are no endpoints for updating in place. + // Handle pure deletes first. for _, ep := range changes.Delete { if err := p.api.deleteRecord(ctx, ep); err != nil { return err } } + + // Handle updated state - there are no endpoints for updating in place. + updateNew := make(map[string]*endpoint.Endpoint) + for _, ep := range changes.UpdateNew { + updateNew[ep.DNSName] = ep + } + for _, ep := range changes.UpdateOld { + // Check if this existing entry has an exact match for an updated entry, and skip it if so. + if newRecord := updateNew[ep.DNSName]; newRecord != nil { + // PiHole only has a single target and a record type, no need to compare other fields. + if newRecord.Targets.String() == ep.Targets.String() && newRecord.RecordType == ep.RecordType { + delete(updateNew, ep.DNSName) + continue + } + } if err := p.api.deleteRecord(ctx, ep); err != nil { return err } } - // Handle desired state + // Handle pure creates before applying new updated state. for _, ep := range changes.Create { if err := p.api.createRecord(ctx, ep); err != nil { return err } } - for _, ep := range changes.UpdateNew { + for _, ep := range updateNew { if err := p.api.createRecord(ctx, ep); err != nil { return err }