Skip to content

Instantly share code, notes, and snippets.

@justinclayton
Created July 15, 2015 22:04
Show Gist options
  • Star 37 You must be signed in to star a gist
  • Fork 17 You must be signed in to fork a gist
  • Save justinclayton/0a4df1c85e4aaf6dde52 to your computer and use it in GitHub Desktop.
Save justinclayton/0a4df1c85e4aaf6dde52 to your computer and use it in GitHub Desktop.
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
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
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
Copy link

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
Copy link

thanks it's awesome.

@AstroTom
Copy link

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
Copy link

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
Copy link

tengg commented Feb 26, 2018

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

@shaheelk
Copy link

Hi,

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

@yyarmoshyk
Copy link

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
Copy link

The script is pretty useful! Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment