-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow AWS provider to change record types #1867
Allow AWS provider to change record types #1867
Conversation
Currently the AWS provider cannot handle record type changes. It always attempts to UPSERT such updates, which will fail the entire zone batch of changes. As a result, a single resource change can break all the updates for the entire zone. This change modifies the AWS behavior to correctly identify when the record type changes and perform a batched DELETE and CREATE to update the record successfully. Special logic is required to handle ALIAS records which are not directly encoded by the generic external-dns code, and relies on convention (using a CNAME record type internally). I'm not sure this is ideal as it's fairly error prone, and would prefer to see direct support for such ALIAS types, but I've left it alone in this change.
Welcome @jsravn! |
/assign @Raffo |
ping @Raffo , mind having a look? |
// UpdateRecords updates a given set of old records to a new set of records in a given hosted zone. | ||
func (p *AWSProvider) UpdateRecords(ctx context.Context, updates, current []*endpoint.Endpoint) error { | ||
zones, err := p.Zones(ctx) | ||
if err != nil { | ||
return errors.Wrapf(err, "failed to list zones, aborting UpdateRecords") | ||
} | ||
|
||
records, err := p.records(ctx, zones) | ||
if err != nil { | ||
log.Errorf("failed to list records while preparing UpdateRecords: %s", err) | ||
} | ||
|
||
return p.submitChanges(ctx, p.createUpdateChanges(updates, current, records, zones), zones) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this exactly the same as doRecords
? If so, why are we duplicating it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not quite the same, since we need to call createUpdateChanges to handle the special case of ALIAS records. The duplication is just getting the zones and records. I suppose I could remove the duplication by passing a function as an argument to doRecords.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh right, I missed that. I think we can keep it as is then.
if new.RecordType != old.RecordType || | ||
// Handle the case where an AWS ALIAS record is changing to/from a CNAME. | ||
(old.RecordType == endpoint.RecordTypeCNAME && useAlias(old, p.preferCNAME) != useAlias(new, p.preferCNAME)) { | ||
// The record type changed, so UPSERT will fail. Instead perform a DELETE followed by a CREATE. | ||
deletes = append(deletes, old) | ||
creates = append(creates, new) | ||
} else { | ||
// Safe to perform an UPSERT. | ||
updates = append(updates, new) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we put this into UpdateRecords
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It needs to be called by ApplyChanges as well. I'm not quite sure why ApplyChanges is duplicated w/ these individual methods (Create/Update/Delete), but that's they way it is at the moment. All these methods could be refactored to remove the duplication possibly.
All right, changes look good to me. Did you have the chance to build an image and try this out @jsravn ? In case you didn't can I ask you to test the change once we get a master image before we will make a release? |
Hi @Raffo, I've tested it in a real cluster deployed to AWS and it seems to work well. I'll get better coverage when I roll it out for production usage over the next couple weeks. With this change, attempting to set target to a CNAME when it is currently an ALIAS.
Without it:
|
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: jsravn, Raffo The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Description
Currently the AWS provider cannot handle record type changes. It always
attempts to UPSERT such updates, which will fail the entire zone batch
of changes. As a result, a single resource change can break all the
updates for the entire zone.
This change modifies the AWS behavior to correctly identify when the
record type changes and perform a batched DELETE and CREATE to update
the record successfully.
Special logic is required to handle ALIAS records which are not directly
encoded by the generic external-dns code, and relies on
convention (using a CNAME record type internally). I'm not sure this is
ideal as it's fairly error prone, and would prefer to see direct support
for such ALIAS types, but I've left it alone in this change.
Fixes #1852
Checklist