Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
CLI to add DNS Records in Route53
#!/bin/bash -eo pipefail
## Allows for creation of "Basic" DNS records in a Route53 hosted zone
function main() {
record_name=$1
record_value=$2
[[ -z $record_name ]] && echo "record_name is: $record_name" && exit 1
[[ -z $record_value ]] && echo "record_value is: $record_value" && exit 1
## set some defaults if variables haven't been overridden on script execute
zone_name=${zone_name:-$ROUTE53_DEFAULT_HOSTED_ZONE_NAME}
action=${action:-CREATE}
record_type=${record_type:-A}
ttl=${ttl:-300}
wait_for_sync=${wait_for_sync:-false}
change_id=$(submit_resource_record_change_set) || exit 1
echo "Record change submitted! Change Id: $change_id"
if $wait_for_sync; then
echo -n "Waiting for all Route53 DNS to be in sync..."
until [[ $(get_change_status $change_id) == "INSYNC" ]]; do
echo -n "."
sleep 5
done
echo "!"
echo "Your record change has now propogated."
fi
echo 'Thank you for using "The Cloud".'
}
function change_batch() {
jq -c -n "{\"Changes\": [{\"Action\": \"$action\", \"ResourceRecordSet\": {\"Name\": \"$record_name\", \"Type\": \"$record_type\", \"TTL\": $ttl, \"ResourceRecords\": [{\"Value\": \"$record_value\"} ] } } ] }"
}
function get_change_status() {
aws route53 get-change --id $1 | jq -r '.ChangeInfo.Status'
}
function hosted_zone_id() {
aws route53 list-hosted-zones | jq -r ".HostedZones[] | select(.Name == \"${zone_name}\") | .Id" | cut -d'/' -f3
}
function submit_resource_record_change_set() {
aws route53 change-resource-record-sets --hosted-zone-id $(hosted_zone_id) --change-batch $(change_batch) | jq -r '.ChangeInfo.Id' | cut -d'/' -f3
}
function usage() {
echo "usage: $0 <record_name> <record_value>"
echo ""
echo "possible env config settings and their defaults:"
echo " - action=CREATE"
echo " - ttl=300"
echo " - record_type=A"
echo " - wait_for_sync=false"
echo ""
}
main $1 $2
@AAber

This comment has been minimized.

Copy link

AAber commented Jun 14, 2017

The following line failed for me:
aws route53 list-hosted-zones | jq -r ".HostedZones[] | select(.Name == \"${zone_name}\") | .Id" | cut -d'/' -f3
I changed it to:
aws route53 list-hosted-zones|grep Id|cut -d'/' -f3|awk -F\" '{print $1}'
And it worked.

@eedugon

This comment has been minimized.

Copy link

eedugon commented Jul 3, 2017

Nice script!
Just a comment: If someone has default aws cli output as text (and not json), then the comment by AAber should be applicable and some commands should be changed, like:

#   aws route53 list-hosted-zones | jq -r ".HostedZones[] | select(.Name == \"${zone_name}\") | .Id" | cut -d'/' -f3
   aws route53 list-hosted-zones|grep "${zone_name}" |cut -d'/' -f3|awk '{print $1}'

,

#aws route53 change-resource-record-sets --hosted-zone-id "$(hosted_zone_id)" --change-batch "$(change_batch)" | jq -r '.ChangeInfo.Id' | cut -d'/' -f3
aws route53 change-resource-record-sets --hosted-zone-id "$(hosted_zone_id)" --change-batch "$(change_batch)" | awk -F"/" ' { print $3 }'

and probably others ;-)

@greg-plume

This comment has been minimized.

Copy link

greg-plume commented Oct 6, 2017

Hosted zone id, selected via a --query expression, from one of my scripts:

printf -v query_expr "HostedZones[?Name == '%s.'].[Id]" ${zone_name}   # "." after "%s" is intentional
full_zone_id=$( aws route53 list-hosted-zones --query "${query_expr}" --output=text )
hosted_zone_id=${full_zone_id##*/}   # strip leading "/hostedzone/"
@achilles42

This comment has been minimized.

Copy link

achilles42 commented Oct 31, 2017

thanks it's awesome.

@AstroTom

This comment has been minimized.

Copy link

AstroTom commented Nov 22, 2017

Nice!

For your test of the variables I think you meant:

   [[ ! -z $record_name  ]] && echo "record_name is: $record_name" || exit 1
   [[ ! -z $record_value ]] && echo "record_value is: $record_value" || exit 1

Also to ensure the output is in JSON, just add to the top of the script:

 export AWS_DEFAULT_OUTPUT="json"
@inscrutabledude

This comment has been minimized.

Copy link

inscrutabledude commented Jan 19, 2018

I'm new to the aws thing, just need to be able to add a lot of cnames really quickly, so i found this script. Where does the "$ROUTE53_DEFAULT_HOSTED_ZONE_NAME" come from? Is that something that the aws cli provides automatically once it's configured properly?

@tengg

This comment has been minimized.

Copy link

tengg commented Feb 26, 2018

@inscrutabledude
I believe you need to export it before running the script.

@shaheelk

This comment has been minimized.

Copy link

shaheelk commented Feb 26, 2018

Hi,

I have to update more than 1000 PTR records. What changes needs o above code ??

@yyarmoshyk

This comment has been minimized.

Copy link

yyarmoshyk commented Feb 27, 2018

Awesome work!

I'd recommend to use UPSERT action. In this case non-existing records will be created. Existing records will get updated.
action=${action:-UPSERT}

@harshal-shah

This comment has been minimized.

Copy link

harshal-shah commented Nov 14, 2019

The script is pretty useful! Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.