-
Notifications
You must be signed in to change notification settings - Fork 9.3k
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
Make sure route53 records really exist after creation and add support for all ASCII characters #4183
Merged
Merged
Make sure route53 records really exist after creation and add support for all ASCII characters #4183
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
47a6de3
Switch the no records and no hosted zones errors around so the next
Crazybus e682d46
Use findRecord directly instead of resourceAwsRoute53RecordRead when
Crazybus fe5925e
Set MaxItems to 1 when we know there is only a single record to be found
Crazybus b5fa8ed
Support converting all ASCII characters (such as @) back to their ori…
Crazybus File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ import ( | |
"fmt" | ||
"log" | ||
"regexp" | ||
"strconv" | ||
"strings" | ||
"time" | ||
|
||
|
@@ -20,8 +21,8 @@ import ( | |
"github.com/aws/aws-sdk-go/service/route53" | ||
) | ||
|
||
var r53NoRecordsFound = errors.New("No matching Hosted Zone found") | ||
var r53NoHostedZoneFound = errors.New("No matching records found") | ||
var r53NoRecordsFound = errors.New("No matching records found") | ||
var r53NoHostedZoneFound = errors.New("No matching Hosted Zone found") | ||
var r53ValidRecordTypes = regexp.MustCompile("^(A|AAAA|CAA|CNAME|MX|NAPTR|NS|PTR|SOA|SPF|SRV|TXT)$") | ||
|
||
func resourceAwsRoute53Record() *schema.Resource { | ||
|
@@ -374,7 +375,8 @@ func resourceAwsRoute53RecordUpdate(d *schema.ResourceData, meta interface{}) er | |
return err | ||
} | ||
|
||
return resourceAwsRoute53RecordRead(d, meta) | ||
_, err = findRecord(d, meta) | ||
return err | ||
} | ||
|
||
func resourceAwsRoute53RecordCreate(d *schema.ResourceData, meta interface{}) error { | ||
|
@@ -451,7 +453,8 @@ func resourceAwsRoute53RecordCreate(d *schema.ResourceData, meta interface{}) er | |
return err | ||
} | ||
|
||
return resourceAwsRoute53RecordRead(d, meta) | ||
_, err = findRecord(d, meta) | ||
return err | ||
} | ||
|
||
func changeRoute53RecordSet(conn *route53.Route53, input *route53.ChangeResourceRecordSetsInput) (interface{}, error) { | ||
|
@@ -630,27 +633,49 @@ func findRecord(d *schema.ResourceData, meta interface{}) (*route53.ResourceReco | |
log.Printf("[DEBUG] Expanded record name: %s", en) | ||
d.Set("fqdn", en) | ||
|
||
recordName := FQDN(strings.ToLower(en)) | ||
recordType := d.Get("type").(string) | ||
recordSetIdentifier := d.Get("set_identifier") | ||
|
||
// If this isn't a Weighted, Latency, Geo, or Failover resource with | ||
// a SetIdentifier we only need to look at the first record in the response since there can be | ||
// only one | ||
maxItems := "1" | ||
if recordSetIdentifier != "" { | ||
maxItems = "100" | ||
} | ||
|
||
lopts := &route53.ListResourceRecordSetsInput{ | ||
HostedZoneId: aws.String(cleanZoneID(zone)), | ||
StartRecordName: aws.String(en), | ||
StartRecordType: aws.String(d.Get("type").(string)), | ||
StartRecordName: aws.String(recordName), | ||
StartRecordType: aws.String(recordType), | ||
MaxItems: aws.String(maxItems), | ||
} | ||
|
||
log.Printf("[DEBUG] List resource records sets for zone: %s, opts: %s", | ||
zone, lopts) | ||
|
||
var record *route53.ResourceRecordSet | ||
|
||
// We need to loop over all records starting from the record we are looking for because | ||
// Weighted, Latency, Geo, and Failover resource record sets have a special option | ||
// called SetIdentifier which allows multiple entries with the same name and type but | ||
// a different SetIdentifier | ||
// For all other records we are setting the maxItems to 1 so that we don't return extra | ||
// unneeded records | ||
err = conn.ListResourceRecordSetsPages(lopts, func(resp *route53.ListResourceRecordSetsOutput, lastPage bool) bool { | ||
for _, recordSet := range resp.ResourceRecordSets { | ||
name := cleanRecordName(*recordSet.Name) | ||
if FQDN(strings.ToLower(name)) != FQDN(strings.ToLower(*lopts.StartRecordName)) { | ||
|
||
responseName := strings.ToLower(cleanRecordName(*recordSet.Name)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor nitpick: To prevent crashes in the very unlikely scenario that AWS returns nil for either of these, it would be safer to wrap them in |
||
responseType := strings.ToUpper(*recordSet.Type) | ||
|
||
if recordName != responseName { | ||
continue | ||
} | ||
if strings.ToUpper(*recordSet.Type) != strings.ToUpper(*lopts.StartRecordType) { | ||
if recordType != responseType { | ||
continue | ||
} | ||
|
||
if recordSet.SetIdentifier != nil && *recordSet.SetIdentifier != d.Get("set_identifier") { | ||
if recordSet.SetIdentifier != nil && *recordSet.SetIdentifier != recordSetIdentifier { | ||
continue | ||
} | ||
|
||
|
@@ -883,16 +908,17 @@ func FQDN(name string) string { | |
} | ||
} | ||
|
||
// Route 53 stores the "*" wildcard indicator as ASCII 42 and returns the | ||
// octal equivalent, "\\052". Here we look for that, and convert back to "*" | ||
// as needed. | ||
// Route 53 stores certain characters with the octal equivalent in ASCII format. | ||
// This function converts all of these characters back into the original character | ||
// E.g. "*" is stored as "\\052" and "@" as "\\100" | ||
|
||
func cleanRecordName(name string) string { | ||
str := name | ||
if strings.HasPrefix(name, "\\052") { | ||
str = strings.Replace(name, "\\052", "*", 1) | ||
log.Printf("[DEBUG] Replacing octal \\052 for * in: %s", name) | ||
s, err := strconv.Unquote(`"` + str + `"`) | ||
if err != nil { | ||
return str | ||
} | ||
return str | ||
return s | ||
} | ||
|
||
// Check if the current record name contains the zone suffix. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
❤️ thank you!