Merge pull request #3049 from hikhvar/fix-multiple-records

Allow multiple records per A record in OpenStack Designate Provider
This commit is contained in:
Kubernetes Prow Robot 2023-04-04 03:35:54 -07:00 committed by GitHub
commit 951820356e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 26 deletions

View File

@ -322,13 +322,13 @@ func (p designateProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, e
if recordSet.Type != endpoint.RecordTypeA && recordSet.Type != endpoint.RecordTypeTXT && recordSet.Type != endpoint.RecordTypeCNAME { if recordSet.Type != endpoint.RecordTypeA && recordSet.Type != endpoint.RecordTypeTXT && recordSet.Type != endpoint.RecordTypeCNAME {
return nil return nil
} }
for _, record := range recordSet.Records {
ep := endpoint.NewEndpoint(recordSet.Name, recordSet.Type, record) ep := endpoint.NewEndpoint(recordSet.Name, recordSet.Type, recordSet.Records...)
ep.Labels[designateRecordSetID] = recordSet.ID ep.Labels[designateRecordSetID] = recordSet.ID
ep.Labels[designateZoneID] = recordSet.ZoneID ep.Labels[designateZoneID] = recordSet.ZoneID
ep.Labels[designateOriginalRecords] = strings.Join(recordSet.Records, "\000") ep.Labels[designateOriginalRecords] = strings.Join(recordSet.Records, "\000")
result = append(result, ep) result = append(result, ep)
}
return nil return nil
}, },
) )
@ -358,7 +358,7 @@ type recordSet struct {
} }
// adds endpoint into recordset aggregation, loading original values from endpoint labels first // adds endpoint into recordset aggregation, loading original values from endpoint labels first
func addEndpoint(ep *endpoint.Endpoint, recordSets map[string]*recordSet, delete bool) { func addEndpoint(ep *endpoint.Endpoint, recordSets map[string]*recordSet, oldEndpoints []*endpoint.Endpoint, delete bool) {
key := fmt.Sprintf("%s/%s", ep.DNSName, ep.RecordType) key := fmt.Sprintf("%s/%s", ep.DNSName, ep.RecordType)
rs := recordSets[key] rs := recordSets[key]
if rs == nil { if rs == nil {
@ -368,6 +368,9 @@ func addEndpoint(ep *endpoint.Endpoint, recordSets map[string]*recordSet, delete
names: make(map[string]bool), names: make(map[string]bool),
} }
} }
addDesignateIDLabelsFromExistingEndpoints(oldEndpoints, ep)
if rs.zoneID == "" { if rs.zoneID == "" {
rs.zoneID = ep.Labels[designateZoneID] rs.zoneID = ep.Labels[designateZoneID]
} }
@ -389,25 +392,55 @@ func addEndpoint(ep *endpoint.Endpoint, recordSets map[string]*recordSet, delete
recordSets[key] = rs recordSets[key] = rs
} }
// addDesignateIDLabelsFromExistingEndpoints adds the labels identified by the constants designateZoneID and designateRecordSetID
// to an Endpoint. Therefore, it searches all given existing endpoints for an endpoint with the same record type and record
// value. If the given Endpoint already has the labels set, they are left untouched. This fixes an issue with the
// TXTRegistry which generates new TXT entries instead of updating the old ones.
func addDesignateIDLabelsFromExistingEndpoints(existingEndpoints []*endpoint.Endpoint, ep *endpoint.Endpoint) {
_, hasZoneIDLabel := ep.Labels[designateZoneID]
_, hasRecordSetIDLabel := ep.Labels[designateRecordSetID]
if hasZoneIDLabel && hasRecordSetIDLabel {
return
}
for _, oep := range existingEndpoints {
if ep.RecordType == oep.RecordType && ep.DNSName == oep.DNSName {
if !hasZoneIDLabel {
ep.Labels[designateZoneID] = oep.Labels[designateZoneID]
}
if !hasRecordSetIDLabel {
ep.Labels[designateRecordSetID] = oep.Labels[designateRecordSetID]
}
return
}
}
}
// ApplyChanges applies a given set of changes in a given zone. // ApplyChanges applies a given set of changes in a given zone.
func (p designateProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) error { func (p designateProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) error {
managedZones, err := p.getZones() managedZones, err := p.getZones()
if err != nil { if err != nil {
return err return err
} }
endpoints, err := p.Records(ctx)
if err != nil {
return fmt.Errorf("failed to fetch active records: %w", err)
}
recordSets := map[string]*recordSet{} recordSets := map[string]*recordSet{}
for _, ep := range changes.Create { for _, ep := range changes.Create {
addEndpoint(ep, recordSets, false) addEndpoint(ep, recordSets, endpoints, false)
}
for _, ep := range changes.UpdateNew {
addEndpoint(ep, recordSets, false)
} }
for _, ep := range changes.UpdateOld { for _, ep := range changes.UpdateOld {
addEndpoint(ep, recordSets, true) addEndpoint(ep, recordSets, endpoints, true)
}
for _, ep := range changes.UpdateNew {
addEndpoint(ep, recordSets, endpoints, false)
} }
for _, ep := range changes.Delete { for _, ep := range changes.Delete {
addEndpoint(ep, recordSets, true) addEndpoint(ep, recordSets, endpoints, true)
} }
for _, rs := range recordSets { for _, rs := range recordSets {
if err2 := p.upsertRecordSet(rs, managedZones); err == nil { if err2 := p.upsertRecordSet(rs, managedZones); err == nil {
err = err2 err = err2

View File

@ -274,17 +274,7 @@ func TestDesignateRecords(t *testing.T) {
{ {
DNSName: "srv.test.net", DNSName: "srv.test.net",
RecordType: endpoint.RecordTypeA, RecordType: endpoint.RecordTypeA,
Targets: endpoint.Targets{"10.2.1.1"}, Targets: endpoint.Targets{"10.2.1.1", "10.2.1.2"},
Labels: map[string]string{
designateRecordSetID: rs21ID,
designateZoneID: zone2ID,
designateOriginalRecords: "10.2.1.1\00010.2.1.2",
},
},
{
DNSName: "srv.test.net",
RecordType: endpoint.RecordTypeA,
Targets: endpoint.Targets{"10.2.1.2"},
Labels: map[string]string{ Labels: map[string]string{
designateRecordSetID: rs21ID, designateRecordSetID: rs21ID,
designateZoneID: zone2ID, designateZoneID: zone2ID,
@ -336,6 +326,19 @@ func testDesignateCreateRecords(t *testing.T, client *fakeDesignateClient) []*re
Status: "ACTIVE", Status: "ACTIVE",
}) })
} }
_, err := client.CreateRecordSet("zone-1", recordsets.CreateOpts{
Name: "www.example.com.",
Description: "",
Records: []string{"foo"},
TTL: 60,
Type: endpoint.RecordTypeTXT,
})
if err != nil {
t.Fatal("failed to prefil records")
}
endpoints := []*endpoint.Endpoint{ endpoints := []*endpoint.Endpoint{
{ {
DNSName: "www.example.com", DNSName: "www.example.com",
@ -409,7 +412,7 @@ func testDesignateCreateRecords(t *testing.T, client *fakeDesignateClient) []*re
expectedCopy := make([]*recordsets.RecordSet, len(expected)) expectedCopy := make([]*recordsets.RecordSet, len(expected))
copy(expectedCopy, expected) copy(expectedCopy, expected)
err := client.ToProvider().ApplyChanges(context.Background(), &plan.Changes{Create: endpoints}) err = client.ToProvider().ApplyChanges(context.Background(), &plan.Changes{Create: endpoints})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }