func (ep *ExoscaleProvider) ApplyChanges(changes *plan.Changes) error {
	ep.OnApplyChanges(changes)

	if ep.dryRun {
		log.Infof("Will NOT delete these records: %+v", changes.Delete)
		log.Infof("Will NOT create these records: %+v", changes.Create)
		log.Infof("Will NOT update these records: %+v", merge(changes.UpdateOld, changes.UpdateNew))
		return nil
	}

	zones, err := ep.getZones()
	if err != nil {
		return err
	}

	for _, epoint := range changes.Create {
		if ep.domain.Match(epoint.DNSName) {
			if zoneID, name := ep.filter.EndpointZoneID(epoint, zones); zoneID != 0 {
				rec := egoscale.DNSRecord{
					Name:       name,
					RecordType: epoint.RecordType,
					TTL:        int(epoint.RecordTTL),
					Content:    epoint.Targets[0],
				}
				_, err := ep.client.CreateRecord(zones[zoneID], rec)
				if err != nil {
					return err
				}
			}
		}
	}
	for _, epoint := range changes.UpdateNew {
		if ep.domain.Match(epoint.DNSName) {
			if zoneID, name := ep.filter.EndpointZoneID(epoint, zones); zoneID != 0 {
				records, err := ep.client.GetRecords(zones[zoneID])
				if err != nil {
					return err
				}
				for _, r := range records {
					if r.Name == name {
						rec := egoscale.UpdateDNSRecord{
							ID:         r.ID,
							DomainID:   r.DomainID,
							Name:       name,
							RecordType: epoint.RecordType,
							TTL:        int(epoint.RecordTTL),
							Content:    epoint.Targets[0],
							Prio:       r.Prio,
						}
						if _, err := ep.client.UpdateRecord(zones[zoneID], rec); err != nil {
							return err
						}
						break
					}
				}
			}
		}
	}

	for _, epoint := range changes.UpdateOld {
		// Since Exoscale "Patches", we ignore UpdateOld
		// We leave this logging here for information
		log.Debugf("UPDATE-OLD (ignored) for epoint: %+v", epoint)
	}

	for _, epoint := range changes.Delete {
		if ep.domain.Match(epoint.DNSName) {
			if zoneID, name := ep.filter.EndpointZoneID(epoint, zones); zoneID != 0 {
				records, err := ep.client.GetRecords(zones[zoneID])
				if err != nil {
					return err
				}

				for _, r := range records {
					if r.Name == name {
						if err := ep.client.DeleteRecord(zones[zoneID], r.ID); err != nil {
							return err
						}
						break
					}
				}
			}
		}
	}

	return nil
}
func (ep *ExoscaleProvider) ApplyChanges(changes *plan.Changes) error {
	ep.OnApplyChanges(changes)

	if ep.dryRun {
		log.Infof("Will NOT delete these records: %+v", changes.Delete)
		log.Infof("Will NOT create these records: %+v", changes.Create)
		log.Infof("Will NOT update these records: %+v", merge(changes.UpdateOld, changes.UpdateNew))
		return nil
	}

	zones, err := ep.getZones()
	if err != nil {
		return err
	}

	for _, epoint := range changes.Create {
		if ep.domain.Match(epoint.DNSName) {
			if zoneID, name := ep.filter.EndpointZoneID(epoint, zones); zoneID != 0 {
				rec := egoscale.DNSRecord{
					Name:       name,
					RecordType: epoint.RecordType,
					TTL:        int(epoint.RecordTTL),
					Content:    epoint.Targets[0],
				}
				_, err := ep.client.CreateRecord(zones[zoneID], rec)
				if err != nil {
					return err
				}
			}
		}
	}
	for _, epoint := range changes.UpdateNew {
		if ep.domain.Match(epoint.DNSName) {
			if zoneID, name := ep.filter.EndpointZoneID(epoint, zones); zoneID != 0 {
				records, err := ep.client.GetRecords(zones[zoneID])
				if err != nil {
					return err
				}
				for _, r := range records {
					if r.Name == name {
						rec := egoscale.UpdateDNSRecord{
							ID:         r.ID,
							DomainID:   r.DomainID,
							Name:       name,
							RecordType: epoint.RecordType,
							TTL:        int(epoint.RecordTTL),
							Content:    epoint.Targets[0],
							Prio:       r.Prio,
						}
						if _, err := ep.client.UpdateRecord(zones[zoneID], rec); err != nil {
							return err
						}
						break
					}
				}
			}
		}
	}

	for _, epoint := range changes.UpdateOld {
		// Since Exoscale "Patches", we ignore UpdateOld
		// We leave this logging here for information
		log.Debugf("UPDATE-OLD (ignored) for epoint: %+v", epoint)
	}

	for _, epoint := range changes.Delete {
		if ep.domain.Match(epoint.DNSName) {
			if zoneID, name := ep.filter.EndpointZoneID(epoint, zones); zoneID != 0 {
				records, err := ep.client.GetRecords(zones[zoneID])
				if err != nil {
					return err
				}

				for _, r := range records {
					if r.Name == name {
						if err := ep.client.DeleteRecord(zones[zoneID], r.ID); err != nil {
							return err
						}
						break
					}
				}
			}
		}
	}

	return nil
}
// ApplyChanges simply modifies DNS via exoscale API